]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/bind9/lib/dns/zone.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2011  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: zone.c,v 1.582.8.26 2011-08-09 02:34:24 marka Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23 #include <errno.h>
24
25 #include <isc/file.h>
26 #include <isc/mutex.h>
27 #include <isc/print.h>
28 #include <isc/random.h>
29 #include <isc/ratelimiter.h>
30 #include <isc/refcount.h>
31 #include <isc/rwlock.h>
32 #include <isc/serial.h>
33 #include <isc/strerror.h>
34 #include <isc/stats.h>
35 #include <isc/stdtime.h>
36 #include <isc/string.h>
37 #include <isc/taskpool.h>
38 #include <isc/timer.h>
39 #include <isc/util.h>
40
41 #include <dns/acache.h>
42 #include <dns/acl.h>
43 #include <dns/adb.h>
44 #include <dns/callbacks.h>
45 #include <dns/db.h>
46 #include <dns/dbiterator.h>
47 #include <dns/dnssec.h>
48 #include <dns/events.h>
49 #include <dns/journal.h>
50 #include <dns/keydata.h>
51 #include <dns/keytable.h>
52 #include <dns/keyvalues.h>
53 #include <dns/log.h>
54 #include <dns/master.h>
55 #include <dns/masterdump.h>
56 #include <dns/message.h>
57 #include <dns/name.h>
58 #include <dns/nsec.h>
59 #include <dns/nsec3.h>
60 #include <dns/peer.h>
61 #include <dns/private.h>
62 #include <dns/rbt.h>
63 #include <dns/rcode.h>
64 #include <dns/rdataclass.h>
65 #include <dns/rdatalist.h>
66 #include <dns/rdataset.h>
67 #include <dns/rdatasetiter.h>
68 #include <dns/rdatastruct.h>
69 #include <dns/rdatatype.h>
70 #include <dns/request.h>
71 #include <dns/resolver.h>
72 #include <dns/result.h>
73 #include <dns/rriterator.h>
74 #include <dns/soa.h>
75 #include <dns/ssu.h>
76 #include <dns/stats.h>
77 #include <dns/tsig.h>
78 #include <dns/xfrin.h>
79 #include <dns/zone.h>
80
81 #include <dst/dst.h>
82
83 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
84 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
85
86 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
87 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
88
89 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
90 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
91
92 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
93 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
94
95 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
96 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
97
98 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
99 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
100
101 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
102 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
103
104 /*%
105  * Ensure 'a' is at least 'min' but not more than 'max'.
106  */
107 #define RANGE(a, min, max) \
108                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
109
110 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
111
112 /*%
113  * Key flags
114  */
115 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
116 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
117 #define ALG(x) dst_key_alg(x)
118
119 /*
120  * Default values.
121  */
122 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
123 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
124 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
125 #define RESIGN_DELAY 3600               /*%< 1 hour */
126
127 #ifndef DNS_MAX_EXPIRE
128 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
129 #endif
130
131 #ifndef DNS_DUMP_DELAY
132 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
133 #endif
134
135 typedef struct dns_notify dns_notify_t;
136 typedef struct dns_stub dns_stub_t;
137 typedef struct dns_load dns_load_t;
138 typedef struct dns_forward dns_forward_t;
139 typedef struct dns_io dns_io_t;
140 typedef ISC_LIST(dns_io_t) dns_iolist_t;
141 typedef struct dns_signing dns_signing_t;
142 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
143 typedef struct dns_nsec3chain dns_nsec3chain_t;
144 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
145 typedef struct dns_keyfetch dns_keyfetch_t;
146
147 #define DNS_ZONE_CHECKLOCK
148 #ifdef DNS_ZONE_CHECKLOCK
149 #define LOCK_ZONE(z) \
150          do { LOCK(&(z)->lock); \
151               INSIST((z)->locked == ISC_FALSE); \
152              (z)->locked = ISC_TRUE; \
153                 } while (0)
154 #define UNLOCK_ZONE(z) \
155         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
156 #define LOCKED_ZONE(z) ((z)->locked)
157 #else
158 #define LOCK_ZONE(z) LOCK(&(z)->lock)
159 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
160 #define LOCKED_ZONE(z) ISC_TRUE
161 #endif
162
163 #ifdef ISC_RWLOCK_USEATOMIC
164 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
165 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
166 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
167 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
168 #else
169 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
170 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
171 #define ZONEDB_LOCK(l, t)       LOCK(l)
172 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
173 #endif
174
175 struct dns_zone {
176         /* Unlocked */
177         unsigned int            magic;
178         isc_mutex_t             lock;
179 #ifdef DNS_ZONE_CHECKLOCK
180         isc_boolean_t           locked;
181 #endif
182         isc_mem_t               *mctx;
183         isc_refcount_t          erefs;
184
185 #ifdef ISC_RWLOCK_USEATOMIC
186         isc_rwlock_t            dblock;
187 #else
188         isc_mutex_t             dblock;
189 #endif
190         dns_db_t                *db;            /* Locked by dblock */
191
192         /* Locked */
193         dns_zonemgr_t           *zmgr;
194         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
195         isc_timer_t             *timer;
196         unsigned int            irefs;
197         dns_name_t              origin;
198         char                    *masterfile;
199         dns_masterformat_t      masterformat;
200         char                    *journal;
201         isc_int32_t             journalsize;
202         dns_rdataclass_t        rdclass;
203         dns_zonetype_t          type;
204         unsigned int            flags;
205         unsigned int            options;
206         unsigned int            db_argc;
207         char                    **db_argv;
208         isc_time_t              expiretime;
209         isc_time_t              refreshtime;
210         isc_time_t              dumptime;
211         isc_time_t              loadtime;
212         isc_time_t              notifytime;
213         isc_time_t              resigntime;
214         isc_time_t              keywarntime;
215         isc_time_t              signingtime;
216         isc_time_t              nsec3chaintime;
217         isc_time_t              refreshkeytime;
218         isc_uint32_t            refreshkeycount;
219         isc_uint32_t            refresh;
220         isc_uint32_t            retry;
221         isc_uint32_t            expire;
222         isc_uint32_t            minimum;
223         isc_stdtime_t           key_expiry;
224         isc_stdtime_t           log_key_expired_timer;
225         char                    *keydirectory;
226
227         isc_uint32_t            maxrefresh;
228         isc_uint32_t            minrefresh;
229         isc_uint32_t            maxretry;
230         isc_uint32_t            minretry;
231
232         isc_sockaddr_t          *masters;
233         dns_name_t              **masterkeynames;
234         isc_boolean_t           *mastersok;
235         unsigned int            masterscnt;
236         unsigned int            curmaster;
237         isc_sockaddr_t          masteraddr;
238         dns_notifytype_t        notifytype;
239         isc_sockaddr_t          *notify;
240         unsigned int            notifycnt;
241         isc_sockaddr_t          notifyfrom;
242         isc_task_t              *task;
243         isc_sockaddr_t          notifysrc4;
244         isc_sockaddr_t          notifysrc6;
245         isc_sockaddr_t          xfrsource4;
246         isc_sockaddr_t          xfrsource6;
247         isc_sockaddr_t          altxfrsource4;
248         isc_sockaddr_t          altxfrsource6;
249         isc_sockaddr_t          sourceaddr;
250         dns_xfrin_ctx_t         *xfr;           /* task locked */
251         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
252         /* Access Control Lists */
253         dns_acl_t               *update_acl;
254         dns_acl_t               *forward_acl;
255         dns_acl_t               *notify_acl;
256         dns_acl_t               *query_acl;
257         dns_acl_t               *queryon_acl;
258         dns_acl_t               *xfr_acl;
259         isc_boolean_t           update_disabled;
260         isc_boolean_t           zero_no_soa_ttl;
261         dns_severity_t          check_names;
262         ISC_LIST(dns_notify_t)  notifies;
263         dns_request_t           *request;
264         dns_loadctx_t           *lctx;
265         dns_io_t                *readio;
266         dns_dumpctx_t           *dctx;
267         dns_io_t                *writeio;
268         isc_uint32_t            maxxfrin;
269         isc_uint32_t            maxxfrout;
270         isc_uint32_t            idlein;
271         isc_uint32_t            idleout;
272         isc_event_t             ctlevent;
273         dns_ssutable_t          *ssutable;
274         isc_uint32_t            sigvalidityinterval;
275         isc_uint32_t            sigresigninginterval;
276         dns_view_t              *view;
277         dns_acache_t            *acache;
278         dns_checkmxfunc_t       checkmx;
279         dns_checksrvfunc_t      checksrv;
280         dns_checknsfunc_t       checkns;
281         /*%
282          * Zones in certain states such as "waiting for zone transfer"
283          * or "zone transfer in progress" are kept on per-state linked lists
284          * in the zone manager using the 'statelink' field.  The 'statelist'
285          * field points at the list the zone is currently on.  It the zone
286          * is not on any such list, statelist is NULL.
287          */
288         ISC_LINK(dns_zone_t)    statelink;
289         dns_zonelist_t          *statelist;
290         /*%
291          * Statistics counters about zone management.
292          */
293         isc_stats_t             *stats;
294         /*%
295          * Optional per-zone statistics counters.  Counted outside of this
296          * module.
297          */
298         isc_boolean_t           requeststats_on;
299         isc_stats_t             *requeststats;
300         isc_uint32_t            notifydelay;
301         dns_isselffunc_t        isself;
302         void                    *isselfarg;
303
304         char *                  strnamerd;
305         char *                  strname;
306         char *                  strrdclass;
307         char *                  strviewname;
308
309         /*%
310          * Serial number for deferred journal compaction.
311          */
312         isc_uint32_t            compact_serial;
313         /*%
314          * Keys that are signing the zone for the first time.
315          */
316         dns_signinglist_t       signing;
317         dns_nsec3chainlist_t    nsec3chain;
318         /*%
319          * Signing / re-signing quantum stopping parameters.
320          */
321         isc_uint32_t            signatures;
322         isc_uint32_t            nodes;
323         dns_rdatatype_t         privatetype;
324
325         /*%
326          * Autosigning/key-maintenance options
327          */
328         isc_uint32_t            keyopts;
329
330         /*%
331          * True if added by "rndc addzone"
332          */
333         isc_boolean_t           added;
334
335         /*%
336          * whether a rpz radix was needed when last loaded
337          */
338         isc_boolean_t           rpz_zone;
339 };
340
341 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
342 #define DNS_ZONE_SETFLAG(z,f) do { \
343                 INSIST(LOCKED_ZONE(z)); \
344                 (z)->flags |= (f); \
345                 } while (0)
346 #define DNS_ZONE_CLRFLAG(z,f) do { \
347                 INSIST(LOCKED_ZONE(z)); \
348                 (z)->flags &= ~(f); \
349                 } while (0)
350         /* XXX MPA these may need to go back into zone.h */
351 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
352 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
353 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
354 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
355 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
356 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
357 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
358 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
359 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
360 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
361                                                  * uptodate */
362 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
363                                                  * messages */
364 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
365                                                  * reload */
366 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
367                                                  * zone with no masters
368                                                  * occurred */
369 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
370 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
371                                                  * from SOA (if not set, we
372                                                  * are still using
373                                                  * default timer values) */
374 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
375 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
376 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
377 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
378 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
379 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
380 #define DNS_ZONEFLG_FLUSH       0x00200000U
381 #define DNS_ZONEFLG_NOEDNS      0x00400000U
382 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
383 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
384 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
385 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
386 #define DNS_ZONEFLG_THAW        0x08000000U
387 /* #define DNS_ZONEFLG_XXXXX    0x10000000U   XXXMPA unused. */
388 #define DNS_ZONEFLG_NODELAY     0x20000000U
389
390 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
391 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
392
393 /* Flags for zone_load() */
394 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
395 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
396                                                    load. */
397
398 #define UNREACH_CHACHE_SIZE     10U
399 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
400
401 #define CHECK(op) \
402         do { result = (op); \
403                 if (result != ISC_R_SUCCESS) goto failure; \
404         } while (0)
405
406 struct dns_unreachable {
407         isc_sockaddr_t  remote;
408         isc_sockaddr_t  local;
409         isc_uint32_t    expire;
410         isc_uint32_t    last;
411 };
412
413 struct dns_zonemgr {
414         unsigned int            magic;
415         isc_mem_t *             mctx;
416         int                     refs;           /* Locked by rwlock */
417         isc_taskmgr_t *         taskmgr;
418         isc_timermgr_t *        timermgr;
419         isc_socketmgr_t *       socketmgr;
420         isc_taskpool_t *        zonetasks;
421         isc_task_t *            task;
422         isc_ratelimiter_t *     rl;
423         isc_rwlock_t            rwlock;
424         isc_mutex_t             iolock;
425
426         /* Locked by rwlock. */
427         dns_zonelist_t          zones;
428         dns_zonelist_t          waiting_for_xfrin;
429         dns_zonelist_t          xfrin_in_progress;
430
431         /* Configuration data. */
432         isc_uint32_t            transfersin;
433         isc_uint32_t            transfersperns;
434         unsigned int            serialqueryrate;
435
436         /* Locked by iolock */
437         isc_uint32_t            iolimit;
438         isc_uint32_t            ioactive;
439         dns_iolist_t            high;
440         dns_iolist_t            low;
441
442         /* Locked by rwlock. */
443         /* LRU cache */
444         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
445 };
446
447 /*%
448  * Hold notify state.
449  */
450 struct dns_notify {
451         unsigned int            magic;
452         unsigned int            flags;
453         isc_mem_t               *mctx;
454         dns_zone_t              *zone;
455         dns_adbfind_t           *find;
456         dns_request_t           *request;
457         dns_name_t              ns;
458         isc_sockaddr_t          dst;
459         ISC_LINK(dns_notify_t)  link;
460 };
461
462 #define DNS_NOTIFY_NOSOA        0x0001U
463
464 /*%
465  *      dns_stub holds state while performing a 'stub' transfer.
466  *      'db' is the zone's 'db' or a new one if this is the initial
467  *      transfer.
468  */
469
470 struct dns_stub {
471         unsigned int            magic;
472         isc_mem_t               *mctx;
473         dns_zone_t              *zone;
474         dns_db_t                *db;
475         dns_dbversion_t         *version;
476 };
477
478 /*%
479  *      Hold load state.
480  */
481 struct dns_load {
482         unsigned int            magic;
483         isc_mem_t               *mctx;
484         dns_zone_t              *zone;
485         dns_db_t                *db;
486         isc_time_t              loadtime;
487         dns_rdatacallbacks_t    callbacks;
488 };
489
490 /*%
491  *      Hold forward state.
492  */
493 struct dns_forward {
494         unsigned int            magic;
495         isc_mem_t               *mctx;
496         dns_zone_t              *zone;
497         isc_buffer_t            *msgbuf;
498         dns_request_t           *request;
499         isc_uint32_t            which;
500         isc_sockaddr_t          addr;
501         dns_updatecallback_t    callback;
502         void                    *callback_arg;
503 };
504
505 /*%
506  *      Hold IO request state.
507  */
508 struct dns_io {
509         unsigned int    magic;
510         dns_zonemgr_t   *zmgr;
511         isc_boolean_t   high;
512         isc_task_t      *task;
513         ISC_LINK(dns_io_t) link;
514         isc_event_t     *event;
515 };
516
517 /*%
518  *      Hold state for when we are signing a zone with a new
519  *      DNSKEY as result of an update.
520  */
521 struct dns_signing {
522         unsigned int            magic;
523         dns_db_t                *db;
524         dns_dbiterator_t        *dbiterator;
525         dns_secalg_t            algorithm;
526         isc_uint16_t            keyid;
527         isc_boolean_t           delete;
528         isc_boolean_t           done;
529         ISC_LINK(dns_signing_t) link;
530 };
531
532 struct dns_nsec3chain {
533         unsigned int                    magic;
534         dns_db_t                        *db;
535         dns_dbiterator_t                *dbiterator;
536         dns_rdata_nsec3param_t          nsec3param;
537         unsigned char                   salt[255];
538         isc_boolean_t                   done;
539         isc_boolean_t                   seen_nsec;
540         isc_boolean_t                   delete_nsec;
541         isc_boolean_t                   save_delete_nsec;
542         ISC_LINK(dns_nsec3chain_t)      link;
543 };
544 /*%<
545  * 'dbiterator' contains a iterator for the database.  If we are creating
546  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
547  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
548  * iterated.
549  *
550  * 'nsec3param' contains the parameters of the NSEC3 chain being created
551  * or removed.
552  *
553  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
554  *
555  * 'seen_nsec' will be set to true if, while iterating the zone to create a
556  * NSEC3 chain, a NSEC record is seen.
557  *
558  * 'delete_nsec' will be set to true if, at the completion of the creation
559  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
560  * are in the process of deleting the NSEC chain.
561  *
562  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
563  * so it can be recovered in the event of a error.
564  */
565
566 struct dns_keyfetch {
567         dns_fixedname_t name;
568         dns_rdataset_t keydataset;
569         dns_rdataset_t dnskeyset;
570         dns_rdataset_t dnskeysigset;
571         dns_zone_t *zone;
572         dns_db_t *db;
573         dns_fetch_t *fetch;
574 };
575
576 #define HOUR 3600
577 #define DAY (24*HOUR)
578 #define MONTH (30*DAY)
579
580 #define SEND_BUFFER_SIZE 2048
581
582 static void zone_settimer(dns_zone_t *, isc_time_t *);
583 static void cancel_refresh(dns_zone_t *);
584 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
585                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
586 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
587      ISC_FORMAT_PRINTF(3, 4);
588 static void queue_xfrin(dns_zone_t *zone);
589 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
590                                   dns_diff_t *diff, dns_diffop_t op,
591                                   dns_name_t *name, dns_ttl_t ttl,
592                                   dns_rdata_t *rdata);
593 static void zone_unload(dns_zone_t *zone);
594 static void zone_expire(dns_zone_t *zone);
595 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
596 static void zone_idetach(dns_zone_t **zonep);
597 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
598                                    isc_boolean_t dump);
599 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
600 static inline void zone_detachdb(dns_zone_t *zone);
601 static isc_result_t default_journal(dns_zone_t *zone);
602 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
603 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
604                                   isc_time_t loadtime, isc_result_t result);
605 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
606 static void zone_shutdown(isc_task_t *, isc_event_t *);
607 static void zone_loaddone(void *arg, isc_result_t result);
608 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
609                                    isc_time_t loadtime);
610 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
611 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
612 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
613 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
614
615 #if 0
616 /* ondestroy example */
617 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
618 #endif
619
620 static void refresh_callback(isc_task_t *, isc_event_t *);
621 static void stub_callback(isc_task_t *, isc_event_t *);
622 static void queue_soa_query(dns_zone_t *zone);
623 static void soa_query(isc_task_t *, isc_event_t *);
624 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
625                      dns_stub_t *stub);
626 static int message_count(dns_message_t *msg, dns_section_t section,
627                          dns_rdatatype_t type);
628 static void notify_cancel(dns_zone_t *zone);
629 static void notify_find_address(dns_notify_t *notify);
630 static void notify_send(dns_notify_t *notify);
631 static isc_result_t notify_createmessage(dns_zone_t *zone,
632                                          unsigned int flags,
633                                          dns_message_t **messagep);
634 static void notify_done(isc_task_t *task, isc_event_t *event);
635 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
636 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
637 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
638 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
639                                              dns_zone_t *zone);
640 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
641 static void zonemgr_free(dns_zonemgr_t *zmgr);
642 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
643                                   isc_task_t *task, isc_taskaction_t action,
644                                   void *arg, dns_io_t **iop);
645 static void zonemgr_putio(dns_io_t **iop);
646 static void zonemgr_cancelio(dns_io_t *io);
647
648 static isc_result_t
649 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
650                  unsigned int *soacount, isc_uint32_t *serial,
651                  isc_uint32_t *refresh, isc_uint32_t *retry,
652                  isc_uint32_t *expire, isc_uint32_t *minimum,
653                  unsigned int *errors);
654
655 static void zone_freedbargs(dns_zone_t *zone);
656 static void forward_callback(isc_task_t *task, isc_event_t *event);
657 static void zone_saveunique(dns_zone_t *zone, const char *path,
658                             const char *templat);
659 static void zone_maintenance(dns_zone_t *zone);
660 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
661 static void dump_done(void *arg, isc_result_t result);
662 static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
663                                              isc_sockaddr_t *remote,
664                                              isc_sockaddr_t *local,
665                                              isc_time_t *now);
666 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
667                                      isc_uint16_t keyid, isc_boolean_t delete);
668 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
669                                 dns_dbnode_t *node, dns_name_t *name,
670                                 dns_diff_t *diff);
671 static void zone_rekey(dns_zone_t *zone);
672 static isc_boolean_t delsig_ok(dns_rdata_rrsig_t *rrsig_ptr,
673                                dst_key_t **keys, unsigned int nkeys);
674
675 #define ENTER zone_debuglog(zone, me, 1, "enter")
676
677 static const unsigned int dbargc_default = 1;
678 static const char *dbargv_default[] = { "rbt" };
679
680 #define DNS_ZONE_JITTER_ADD(a, b, c) \
681         do { \
682                 isc_interval_t _i; \
683                 isc_uint32_t _j; \
684                 _j = isc_random_jitter((b), (b)/4); \
685                 isc_interval_set(&_i, _j, 0); \
686                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
687                         dns_zone_log(zone, ISC_LOG_WARNING, \
688                                      "epoch approaching: upgrade required: " \
689                                      "now + %s failed", #b); \
690                         isc_interval_set(&_i, _j/2, 0); \
691                         (void)isc_time_add((a), &_i, (c)); \
692                 } \
693         } while (0)
694
695 #define DNS_ZONE_TIME_ADD(a, b, c) \
696         do { \
697                 isc_interval_t _i; \
698                 isc_interval_set(&_i, (b), 0); \
699                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
700                         dns_zone_log(zone, ISC_LOG_WARNING, \
701                                      "epoch approaching: upgrade required: " \
702                                      "now + %s failed", #b); \
703                         isc_interval_set(&_i, (b)/2, 0); \
704                         (void)isc_time_add((a), &_i, (c)); \
705                 } \
706         } while (0)
707
708 /*%
709  * Increment resolver-related statistics counters.  Zone must be locked.
710  */
711 static inline void
712 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
713         if (zone->stats != NULL)
714                 isc_stats_increment(zone->stats, counter);
715 }
716
717 /***
718  ***    Public functions.
719  ***/
720
721 isc_result_t
722 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
723         isc_result_t result;
724         dns_zone_t *zone;
725         isc_time_t now;
726
727         REQUIRE(zonep != NULL && *zonep == NULL);
728         REQUIRE(mctx != NULL);
729
730         TIME_NOW(&now);
731         zone = isc_mem_get(mctx, sizeof(*zone));
732         if (zone == NULL)
733                 return (ISC_R_NOMEMORY);
734
735         zone->mctx = NULL;
736         isc_mem_attach(mctx, &zone->mctx);
737
738         result = isc_mutex_init(&zone->lock);
739         if (result != ISC_R_SUCCESS)
740                 goto free_zone;
741
742         result = ZONEDB_INITLOCK(&zone->dblock);
743         if (result != ISC_R_SUCCESS)
744                 goto free_mutex;
745
746         /* XXX MPA check that all elements are initialised */
747 #ifdef DNS_ZONE_CHECKLOCK
748         zone->locked = ISC_FALSE;
749 #endif
750         zone->db = NULL;
751         zone->zmgr = NULL;
752         ISC_LINK_INIT(zone, link);
753         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
754         if (result != ISC_R_SUCCESS)
755                 goto free_dblock;
756         zone->irefs = 0;
757         dns_name_init(&zone->origin, NULL);
758         zone->strnamerd = NULL;
759         zone->strname = NULL;
760         zone->strrdclass = NULL;
761         zone->strviewname = NULL;
762         zone->masterfile = NULL;
763         zone->masterformat = dns_masterformat_none;
764         zone->keydirectory = NULL;
765         zone->journalsize = -1;
766         zone->journal = NULL;
767         zone->rdclass = dns_rdataclass_none;
768         zone->type = dns_zone_none;
769         zone->flags = 0;
770         zone->options = 0;
771         zone->keyopts = 0;
772         zone->db_argc = 0;
773         zone->db_argv = NULL;
774         isc_time_settoepoch(&zone->expiretime);
775         isc_time_settoepoch(&zone->refreshtime);
776         isc_time_settoepoch(&zone->dumptime);
777         isc_time_settoepoch(&zone->loadtime);
778         zone->notifytime = now;
779         isc_time_settoepoch(&zone->resigntime);
780         isc_time_settoepoch(&zone->keywarntime);
781         isc_time_settoepoch(&zone->signingtime);
782         isc_time_settoepoch(&zone->nsec3chaintime);
783         isc_time_settoepoch(&zone->refreshkeytime);
784         zone->refreshkeycount = 0;
785         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
786         zone->retry = DNS_ZONE_DEFAULTRETRY;
787         zone->expire = 0;
788         zone->minimum = 0;
789         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
790         zone->minrefresh = DNS_ZONE_MINREFRESH;
791         zone->maxretry = DNS_ZONE_MAXRETRY;
792         zone->minretry = DNS_ZONE_MINRETRY;
793         zone->masters = NULL;
794         zone->masterkeynames = NULL;
795         zone->mastersok = NULL;
796         zone->masterscnt = 0;
797         zone->curmaster = 0;
798         zone->notify = NULL;
799         zone->notifytype = dns_notifytype_yes;
800         zone->notifycnt = 0;
801         zone->task = NULL;
802         zone->update_acl = NULL;
803         zone->forward_acl = NULL;
804         zone->notify_acl = NULL;
805         zone->query_acl = NULL;
806         zone->queryon_acl = NULL;
807         zone->xfr_acl = NULL;
808         zone->update_disabled = ISC_FALSE;
809         zone->zero_no_soa_ttl = ISC_TRUE;
810         zone->check_names = dns_severity_ignore;
811         zone->request = NULL;
812         zone->lctx = NULL;
813         zone->readio = NULL;
814         zone->dctx = NULL;
815         zone->writeio = NULL;
816         zone->timer = NULL;
817         zone->idlein = DNS_DEFAULT_IDLEIN;
818         zone->idleout = DNS_DEFAULT_IDLEOUT;
819         zone->log_key_expired_timer = 0;
820         ISC_LIST_INIT(zone->notifies);
821         isc_sockaddr_any(&zone->notifysrc4);
822         isc_sockaddr_any6(&zone->notifysrc6);
823         isc_sockaddr_any(&zone->xfrsource4);
824         isc_sockaddr_any6(&zone->xfrsource6);
825         isc_sockaddr_any(&zone->altxfrsource4);
826         isc_sockaddr_any6(&zone->altxfrsource6);
827         zone->xfr = NULL;
828         zone->tsigkey = NULL;
829         zone->maxxfrin = MAX_XFER_TIME;
830         zone->maxxfrout = MAX_XFER_TIME;
831         zone->ssutable = NULL;
832         zone->sigvalidityinterval = 30 * 24 * 3600;
833         zone->sigresigninginterval = 7 * 24 * 3600;
834         zone->view = NULL;
835         zone->acache = NULL;
836         zone->checkmx = NULL;
837         zone->checksrv = NULL;
838         zone->checkns = NULL;
839         ISC_LINK_INIT(zone, statelink);
840         zone->statelist = NULL;
841         zone->stats = NULL;
842         zone->requeststats_on = ISC_FALSE;
843         zone->requeststats = NULL;
844         zone->notifydelay = 5;
845         zone->isself = NULL;
846         zone->isselfarg = NULL;
847         ISC_LIST_INIT(zone->signing);
848         ISC_LIST_INIT(zone->nsec3chain);
849         zone->signatures = 10;
850         zone->nodes = 100;
851         zone->privatetype = (dns_rdatatype_t)0xffffU;
852         zone->added = ISC_FALSE;
853         zone->rpz_zone = ISC_FALSE;
854
855         zone->magic = ZONE_MAGIC;
856
857         /* Must be after magic is set. */
858         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
859         if (result != ISC_R_SUCCESS)
860                 goto free_erefs;
861
862         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
863                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
864                        NULL, NULL);
865         *zonep = zone;
866         return (ISC_R_SUCCESS);
867
868  free_erefs:
869         isc_refcount_decrement(&zone->erefs, NULL);
870         isc_refcount_destroy(&zone->erefs);
871
872  free_dblock:
873         ZONEDB_DESTROYLOCK(&zone->dblock);
874
875  free_mutex:
876         DESTROYLOCK(&zone->lock);
877
878  free_zone:
879         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
880         return (result);
881 }
882
883 /*
884  * Free a zone.  Because we require that there be no more
885  * outstanding events or references, no locking is necessary.
886  */
887 static void
888 zone_free(dns_zone_t *zone) {
889         isc_mem_t *mctx = NULL;
890         dns_signing_t *signing;
891         dns_nsec3chain_t *nsec3chain;
892
893         REQUIRE(DNS_ZONE_VALID(zone));
894         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
895         REQUIRE(zone->irefs == 0);
896         REQUIRE(!LOCKED_ZONE(zone));
897         REQUIRE(zone->timer == NULL);
898
899         /*
900          * Managed objects.  Order is important.
901          */
902         if (zone->request != NULL)
903                 dns_request_destroy(&zone->request); /* XXXMPA */
904         INSIST(zone->readio == NULL);
905         INSIST(zone->statelist == NULL);
906         INSIST(zone->writeio == NULL);
907
908         if (zone->task != NULL)
909                 isc_task_detach(&zone->task);
910         if (zone->zmgr != NULL)
911                 dns_zonemgr_releasezone(zone->zmgr, zone);
912
913         /* Unmanaged objects */
914         for (signing = ISC_LIST_HEAD(zone->signing);
915              signing != NULL;
916              signing = ISC_LIST_HEAD(zone->signing)) {
917                 ISC_LIST_UNLINK(zone->signing, signing, link);
918                 dns_db_detach(&signing->db);
919                 dns_dbiterator_destroy(&signing->dbiterator);
920                 isc_mem_put(zone->mctx, signing, sizeof *signing);
921         }
922         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
923              nsec3chain != NULL;
924              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
925                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
926                 dns_db_detach(&nsec3chain->db);
927                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
928                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
929         }
930         if (zone->masterfile != NULL)
931                 isc_mem_free(zone->mctx, zone->masterfile);
932         zone->masterfile = NULL;
933         if (zone->keydirectory != NULL)
934                 isc_mem_free(zone->mctx, zone->keydirectory);
935         zone->keydirectory = NULL;
936         zone->journalsize = -1;
937         if (zone->journal != NULL)
938                 isc_mem_free(zone->mctx, zone->journal);
939         zone->journal = NULL;
940         if (zone->stats != NULL)
941                 isc_stats_detach(&zone->stats);
942         if (zone->requeststats != NULL)
943                 isc_stats_detach(&zone->requeststats);
944         if (zone->db != NULL)
945                 zone_detachdb(zone);
946         if (zone->acache != NULL)
947                 dns_acache_detach(&zone->acache);
948         zone_freedbargs(zone);
949         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
950                       == ISC_R_SUCCESS);
951         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
952                       == ISC_R_SUCCESS);
953         zone->check_names = dns_severity_ignore;
954         if (zone->update_acl != NULL)
955                 dns_acl_detach(&zone->update_acl);
956         if (zone->forward_acl != NULL)
957                 dns_acl_detach(&zone->forward_acl);
958         if (zone->notify_acl != NULL)
959                 dns_acl_detach(&zone->notify_acl);
960         if (zone->query_acl != NULL)
961                 dns_acl_detach(&zone->query_acl);
962         if (zone->queryon_acl != NULL)
963                 dns_acl_detach(&zone->queryon_acl);
964         if (zone->xfr_acl != NULL)
965                 dns_acl_detach(&zone->xfr_acl);
966         if (dns_name_dynamic(&zone->origin))
967                 dns_name_free(&zone->origin, zone->mctx);
968         if (zone->strnamerd != NULL)
969                 isc_mem_free(zone->mctx, zone->strnamerd);
970         if (zone->strname != NULL)
971                 isc_mem_free(zone->mctx, zone->strname);
972         if (zone->strrdclass != NULL)
973                 isc_mem_free(zone->mctx, zone->strrdclass);
974         if (zone->strviewname != NULL)
975                 isc_mem_free(zone->mctx, zone->strviewname);
976         if (zone->ssutable != NULL)
977                 dns_ssutable_detach(&zone->ssutable);
978
979         /* last stuff */
980         ZONEDB_DESTROYLOCK(&zone->dblock);
981         DESTROYLOCK(&zone->lock);
982         isc_refcount_destroy(&zone->erefs);
983         zone->magic = 0;
984         mctx = zone->mctx;
985         isc_mem_put(mctx, zone, sizeof(*zone));
986         isc_mem_detach(&mctx);
987 }
988
989 /*
990  *      Single shot.
991  */
992 void
993 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
994         char namebuf[1024];
995
996         REQUIRE(DNS_ZONE_VALID(zone));
997         REQUIRE(rdclass != dns_rdataclass_none);
998
999         /*
1000          * Test and set.
1001          */
1002         LOCK_ZONE(zone);
1003         REQUIRE(zone->rdclass == dns_rdataclass_none ||
1004                 zone->rdclass == rdclass);
1005         zone->rdclass = rdclass;
1006
1007         if (zone->strnamerd != NULL)
1008                 isc_mem_free(zone->mctx, zone->strnamerd);
1009         if (zone->strrdclass != NULL)
1010                 isc_mem_free(zone->mctx, zone->strrdclass);
1011
1012         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1013         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1014         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1015         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1016
1017         UNLOCK_ZONE(zone);
1018 }
1019
1020 dns_rdataclass_t
1021 dns_zone_getclass(dns_zone_t *zone) {
1022         REQUIRE(DNS_ZONE_VALID(zone));
1023
1024         return (zone->rdclass);
1025 }
1026
1027 void
1028 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1029         REQUIRE(DNS_ZONE_VALID(zone));
1030
1031         LOCK_ZONE(zone);
1032         zone->notifytype = notifytype;
1033         UNLOCK_ZONE(zone);
1034 }
1035
1036 isc_result_t
1037 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1038         isc_result_t result;
1039
1040         REQUIRE(DNS_ZONE_VALID(zone));
1041         REQUIRE(serialp != NULL);
1042
1043         LOCK_ZONE(zone);
1044         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1045         if (zone->db != NULL) {
1046                 result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
1047                                           NULL, NULL, NULL, NULL, NULL);
1048         } else
1049                 result = DNS_R_NOTLOADED;
1050         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1051         UNLOCK_ZONE(zone);
1052
1053         return (result);
1054 }
1055
1056 isc_uint32_t
1057 dns_zone_getserial(dns_zone_t *zone) {
1058         isc_result_t result;
1059         isc_uint32_t serial;
1060
1061         result = dns_zone_getserial2(zone, &serial);
1062         if (result != ISC_R_SUCCESS)
1063                 serial = 0; /* XXX: not really correct, but no other choice */
1064
1065         return (serial);
1066 }
1067
1068 /*
1069  *      Single shot.
1070  */
1071 void
1072 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1073
1074         REQUIRE(DNS_ZONE_VALID(zone));
1075         REQUIRE(type != dns_zone_none);
1076
1077         /*
1078          * Test and set.
1079          */
1080         LOCK_ZONE(zone);
1081         REQUIRE(zone->type == dns_zone_none || zone->type == type);
1082         zone->type = type;
1083         UNLOCK_ZONE(zone);
1084 }
1085
1086 static void
1087 zone_freedbargs(dns_zone_t *zone) {
1088         unsigned int i;
1089
1090         /* Free the old database argument list. */
1091         if (zone->db_argv != NULL) {
1092                 for (i = 0; i < zone->db_argc; i++)
1093                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1094                 isc_mem_put(zone->mctx, zone->db_argv,
1095                             zone->db_argc * sizeof(*zone->db_argv));
1096         }
1097         zone->db_argc = 0;
1098         zone->db_argv = NULL;
1099 }
1100
1101 isc_result_t
1102 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1103         size_t size = 0;
1104         unsigned int i;
1105         isc_result_t result = ISC_R_SUCCESS;
1106         void *mem;
1107         char **tmp, *tmp2;
1108
1109         REQUIRE(DNS_ZONE_VALID(zone));
1110         REQUIRE(argv != NULL && *argv == NULL);
1111
1112         LOCK_ZONE(zone);
1113         size = (zone->db_argc + 1) * sizeof(char *);
1114         for (i = 0; i < zone->db_argc; i++)
1115                 size += strlen(zone->db_argv[i]) + 1;
1116         mem = isc_mem_allocate(mctx, size);
1117         if (mem != NULL) {
1118                 tmp = mem;
1119                 tmp2 = mem;
1120                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1121                 for (i = 0; i < zone->db_argc; i++) {
1122                         *tmp++ = tmp2;
1123                         strcpy(tmp2, zone->db_argv[i]);
1124                         tmp2 += strlen(tmp2) + 1;
1125                 }
1126                 *tmp = NULL;
1127         } else
1128                 result = ISC_R_NOMEMORY;
1129         UNLOCK_ZONE(zone);
1130         *argv = mem;
1131         return (result);
1132 }
1133
1134 isc_result_t
1135 dns_zone_setdbtype(dns_zone_t *zone,
1136                    unsigned int dbargc, const char * const *dbargv) {
1137         isc_result_t result = ISC_R_SUCCESS;
1138         char **new = NULL;
1139         unsigned int i;
1140
1141         REQUIRE(DNS_ZONE_VALID(zone));
1142         REQUIRE(dbargc >= 1);
1143         REQUIRE(dbargv != NULL);
1144
1145         LOCK_ZONE(zone);
1146
1147         /* Set up a new database argument list. */
1148         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1149         if (new == NULL)
1150                 goto nomem;
1151         for (i = 0; i < dbargc; i++)
1152                 new[i] = NULL;
1153         for (i = 0; i < dbargc; i++) {
1154                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1155                 if (new[i] == NULL)
1156                         goto nomem;
1157         }
1158
1159         /* Free the old list. */
1160         zone_freedbargs(zone);
1161
1162         zone->db_argc = dbargc;
1163         zone->db_argv = new;
1164         result = ISC_R_SUCCESS;
1165         goto unlock;
1166
1167  nomem:
1168         if (new != NULL) {
1169                 for (i = 0; i < dbargc; i++)
1170                         if (new[i] != NULL)
1171                                 isc_mem_free(zone->mctx, new[i]);
1172                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1173         }
1174         result = ISC_R_NOMEMORY;
1175
1176  unlock:
1177         UNLOCK_ZONE(zone);
1178         return (result);
1179 }
1180
1181 void
1182 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1183         char namebuf[1024];
1184         REQUIRE(DNS_ZONE_VALID(zone));
1185
1186         LOCK_ZONE(zone);
1187         if (zone->view != NULL)
1188                 dns_view_weakdetach(&zone->view);
1189         dns_view_weakattach(view, &zone->view);
1190
1191         if (zone->strviewname != NULL)
1192                 isc_mem_free(zone->mctx, zone->strviewname);
1193         if (zone->strnamerd != NULL)
1194                 isc_mem_free(zone->mctx, zone->strnamerd);
1195
1196         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1197         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1198         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1199         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1200
1201         UNLOCK_ZONE(zone);
1202 }
1203
1204
1205 dns_view_t *
1206 dns_zone_getview(dns_zone_t *zone) {
1207         REQUIRE(DNS_ZONE_VALID(zone));
1208
1209         return (zone->view);
1210 }
1211
1212
1213 isc_result_t
1214 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1215         isc_result_t result;
1216         char namebuf[1024];
1217
1218         REQUIRE(DNS_ZONE_VALID(zone));
1219         REQUIRE(origin != NULL);
1220
1221         LOCK_ZONE(zone);
1222         if (dns_name_dynamic(&zone->origin)) {
1223                 dns_name_free(&zone->origin, zone->mctx);
1224                 dns_name_init(&zone->origin, NULL);
1225         }
1226         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1227
1228         if (zone->strnamerd != NULL)
1229                 isc_mem_free(zone->mctx, zone->strnamerd);
1230         if (zone->strname != NULL)
1231                 isc_mem_free(zone->mctx, zone->strname);
1232
1233         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1234         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1235         zone_name_tostr(zone, namebuf, sizeof namebuf);
1236         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1237
1238         UNLOCK_ZONE(zone);
1239         return (result);
1240 }
1241
1242 void
1243 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1244         REQUIRE(DNS_ZONE_VALID(zone));
1245         REQUIRE(acache != NULL);
1246
1247         LOCK_ZONE(zone);
1248         if (zone->acache != NULL)
1249                 dns_acache_detach(&zone->acache);
1250         dns_acache_attach(acache, &zone->acache);
1251         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1252         if (zone->db != NULL) {
1253                 isc_result_t result;
1254
1255                 /*
1256                  * If the zone reuses an existing DB, the DB needs to be
1257                  * set in the acache explicitly.  We can safely ignore the
1258                  * case where the DB is already set.  If other error happens,
1259                  * the acache will not work effectively.
1260                  */
1261                 result = dns_acache_setdb(acache, zone->db);
1262                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1263                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1264                                          "dns_acache_setdb() failed: %s",
1265                                          isc_result_totext(result));
1266                 }
1267         }
1268         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1269         UNLOCK_ZONE(zone);
1270 }
1271
1272 static isc_result_t
1273 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1274         char *copy;
1275
1276         if (value != NULL) {
1277                 copy = isc_mem_strdup(zone->mctx, value);
1278                 if (copy == NULL)
1279                         return (ISC_R_NOMEMORY);
1280         } else {
1281                 copy = NULL;
1282         }
1283
1284         if (*field != NULL)
1285                 isc_mem_free(zone->mctx, *field);
1286
1287         *field = copy;
1288         return (ISC_R_SUCCESS);
1289 }
1290
1291 isc_result_t
1292 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1293         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1294 }
1295
1296 isc_result_t
1297 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1298                   dns_masterformat_t format) {
1299         isc_result_t result = ISC_R_SUCCESS;
1300
1301         REQUIRE(DNS_ZONE_VALID(zone));
1302
1303         LOCK_ZONE(zone);
1304         result = dns_zone_setstring(zone, &zone->masterfile, file);
1305         if (result == ISC_R_SUCCESS) {
1306                 zone->masterformat = format;
1307                 result = default_journal(zone);
1308         }
1309         UNLOCK_ZONE(zone);
1310
1311         return (result);
1312 }
1313
1314 const char *
1315 dns_zone_getfile(dns_zone_t *zone) {
1316         REQUIRE(DNS_ZONE_VALID(zone));
1317
1318         return (zone->masterfile);
1319 }
1320
1321 static isc_result_t
1322 default_journal(dns_zone_t *zone) {
1323         isc_result_t result;
1324         char *journal;
1325
1326         REQUIRE(DNS_ZONE_VALID(zone));
1327         REQUIRE(LOCKED_ZONE(zone));
1328
1329         if (zone->masterfile != NULL) {
1330                 /* Calculate string length including '\0'. */
1331                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1332                 journal = isc_mem_allocate(zone->mctx, len);
1333                 if (journal == NULL)
1334                         return (ISC_R_NOMEMORY);
1335                 strcpy(journal, zone->masterfile);
1336                 strcat(journal, ".jnl");
1337         } else {
1338                 journal = NULL;
1339         }
1340         result = dns_zone_setstring(zone, &zone->journal, journal);
1341         if (journal != NULL)
1342                 isc_mem_free(zone->mctx, journal);
1343         return (result);
1344 }
1345
1346 isc_result_t
1347 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1348         isc_result_t result = ISC_R_SUCCESS;
1349
1350         REQUIRE(DNS_ZONE_VALID(zone));
1351
1352         LOCK_ZONE(zone);
1353         result = dns_zone_setstring(zone, &zone->journal, journal);
1354         UNLOCK_ZONE(zone);
1355
1356         return (result);
1357 }
1358
1359 char *
1360 dns_zone_getjournal(dns_zone_t *zone) {
1361         REQUIRE(DNS_ZONE_VALID(zone));
1362
1363         return (zone->journal);
1364 }
1365
1366 /*
1367  * Return true iff the zone is "dynamic", in the sense that the zone's
1368  * master file (if any) is written by the server, rather than being
1369  * updated manually and read by the server.
1370  *
1371  * This is true for slave zones, stub zones, key zones, and zones that
1372  * allow dynamic updates either by having an update policy ("ssutable")
1373  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1374  */
1375 static isc_boolean_t
1376 zone_isdynamic(dns_zone_t *zone) {
1377         REQUIRE(DNS_ZONE_VALID(zone));
1378
1379         return (ISC_TF(zone->type == dns_zone_slave ||
1380                        zone->type == dns_zone_stub ||
1381                        zone->type == dns_zone_key ||
1382                        (!zone->update_disabled && zone->ssutable != NULL) ||
1383                        (!zone->update_disabled && zone->update_acl != NULL &&
1384                         !dns_acl_isnone(zone->update_acl))));
1385 }
1386
1387
1388 static isc_result_t
1389 zone_load(dns_zone_t *zone, unsigned int flags) {
1390         isc_result_t result;
1391         isc_time_t now;
1392         isc_time_t loadtime, filetime;
1393         dns_db_t *db = NULL;
1394         isc_boolean_t rbt;
1395
1396         REQUIRE(DNS_ZONE_VALID(zone));
1397
1398         LOCK_ZONE(zone);
1399         TIME_NOW(&now);
1400
1401         INSIST(zone->type != dns_zone_none);
1402
1403         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1404                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1405                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1406                 result = DNS_R_CONTINUE;
1407                 goto cleanup;
1408         }
1409
1410
1411         INSIST(zone->db_argc >= 1);
1412
1413         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1414               strcmp(zone->db_argv[0], "rbt64") == 0;
1415
1416         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1417                 /*
1418                  * The zone has no master file configured.
1419                  */
1420                 result = ISC_R_SUCCESS;
1421                 goto cleanup;
1422         }
1423
1424         if (zone->db != NULL && zone_isdynamic(zone)) {
1425                 /*
1426                  * This is a slave, stub, or dynamically updated
1427                  * zone being reloaded.  Do nothing - the database
1428                  * we already have is guaranteed to be up-to-date.
1429                  */
1430                 if (zone->type == dns_zone_master)
1431                         result = DNS_R_DYNAMIC;
1432                 else
1433                         result = ISC_R_SUCCESS;
1434                 goto cleanup;
1435         }
1436
1437         /*
1438          * Store the current time before the zone is loaded, so that if the
1439          * file changes between the time of the load and the time that
1440          * zone->loadtime is set, then the file will still be reloaded
1441          * the next time dns_zone_load is called.
1442          */
1443         TIME_NOW(&loadtime);
1444
1445         /*
1446          * Don't do the load if the file that stores the zone is older
1447          * than the last time the zone was loaded.  If the zone has not
1448          * been loaded yet, zone->loadtime will be the epoch.
1449          */
1450         if (zone->masterfile != NULL) {
1451                 /*
1452                  * The file is already loaded.  If we are just doing a
1453                  * "rndc reconfig", we are done.
1454                  */
1455                 if (!isc_time_isepoch(&zone->loadtime) &&
1456                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0 &&
1457                     zone->rpz_zone == dns_rpz_needed()) {
1458                         result = ISC_R_SUCCESS;
1459                         goto cleanup;
1460                 }
1461
1462                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1463                 if (result == ISC_R_SUCCESS) {
1464                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1465                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1466                             isc_time_compare(&filetime, &zone->loadtime) <= 0 &&
1467                             zone->rpz_zone == dns_rpz_needed()) {
1468                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1469                                              "skipping load: master file "
1470                                              "older than last load");
1471                                 result = DNS_R_UPTODATE;
1472                                 goto cleanup;
1473                         }
1474                         loadtime = filetime;
1475                         zone->rpz_zone = dns_rpz_needed();
1476                 }
1477         }
1478
1479         /*
1480          * Built in zones (with the exception of empty zones) don't need
1481          * to be reloaded.
1482          */
1483         if (zone->type == dns_zone_master &&
1484             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1485             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1486             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1487                 result = ISC_R_SUCCESS;
1488                 goto cleanup;
1489         }
1490
1491         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1492             rbt) {
1493                 if (zone->masterfile == NULL ||
1494                     !isc_file_exists(zone->masterfile)) {
1495                         if (zone->masterfile != NULL) {
1496                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1497                                              "no master file");
1498                         }
1499                         zone->refreshtime = now;
1500                         if (zone->task != NULL)
1501                                 zone_settimer(zone, &now);
1502                         result = ISC_R_SUCCESS;
1503                         goto cleanup;
1504                 }
1505         }
1506
1507         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1508
1509         result = dns_db_create(zone->mctx, zone->db_argv[0],
1510                                &zone->origin, (zone->type == dns_zone_stub) ?
1511                                dns_dbtype_stub : dns_dbtype_zone,
1512                                zone->rdclass,
1513                                zone->db_argc - 1, zone->db_argv + 1,
1514                                &db);
1515
1516         if (result != ISC_R_SUCCESS) {
1517                 dns_zone_log(zone, ISC_LOG_ERROR,
1518                              "loading zone: creating database: %s",
1519                              isc_result_totext(result));
1520                 goto cleanup;
1521         }
1522         dns_db_settask(db, zone->task);
1523
1524         if (! dns_db_ispersistent(db)) {
1525                 if (zone->masterfile != NULL) {
1526                         result = zone_startload(db, zone, loadtime);
1527                 } else {
1528                         result = DNS_R_NOMASTERFILE;
1529                         if (zone->type == dns_zone_master) {
1530                                 dns_zone_log(zone, ISC_LOG_ERROR,
1531                                              "loading zone: "
1532                                              "no master file configured");
1533                                 goto cleanup;
1534                         }
1535                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1536                                      "no master file configured: continuing");
1537                 }
1538         }
1539
1540         if (result == DNS_R_CONTINUE) {
1541                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1542                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1543                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1544                 goto cleanup;
1545         }
1546
1547         result = zone_postload(zone, db, loadtime, result);
1548
1549  cleanup:
1550         UNLOCK_ZONE(zone);
1551         if (db != NULL)
1552                 dns_db_detach(&db);
1553         return (result);
1554 }
1555
1556 isc_result_t
1557 dns_zone_load(dns_zone_t *zone) {
1558         return (zone_load(zone, 0));
1559 }
1560
1561 isc_result_t
1562 dns_zone_loadnew(dns_zone_t *zone) {
1563         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1564 }
1565
1566 isc_result_t
1567 dns_zone_loadandthaw(dns_zone_t *zone) {
1568         isc_result_t result;
1569
1570         result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1571         switch (result) {
1572         case DNS_R_CONTINUE:
1573                 /* Deferred thaw. */
1574                 break;
1575         case ISC_R_SUCCESS:
1576         case DNS_R_UPTODATE:
1577         case DNS_R_SEENINCLUDE:
1578                 zone->update_disabled = ISC_FALSE;
1579                 break;
1580         case DNS_R_NOMASTERFILE:
1581                 zone->update_disabled = ISC_FALSE;
1582                 break;
1583         default:
1584                 /* Error, remain in disabled state. */
1585                 break;
1586         }
1587         return (result);
1588 }
1589
1590 static unsigned int
1591 get_master_options(dns_zone_t *zone) {
1592         unsigned int options;
1593
1594         options = DNS_MASTER_ZONE;
1595         if (zone->type == dns_zone_slave)
1596                 options |= DNS_MASTER_SLAVE;
1597         if (zone->type == dns_zone_key)
1598                 options |= DNS_MASTER_KEY;
1599         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1600                 options |= DNS_MASTER_CHECKNS;
1601         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1602                 options |= DNS_MASTER_FATALNS;
1603         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1604                 options |= DNS_MASTER_CHECKNAMES;
1605         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1606                 options |= DNS_MASTER_CHECKNAMESFAIL;
1607         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1608                 options |= DNS_MASTER_CHECKMX;
1609         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1610                 options |= DNS_MASTER_CHECKMXFAIL;
1611         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1612                 options |= DNS_MASTER_CHECKWILDCARD;
1613         if (zone->type == dns_zone_master &&
1614             ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1615               zone->ssutable != NULL))
1616                 options |= DNS_MASTER_RESIGN;
1617         return (options);
1618 }
1619
1620 static void
1621 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1622         dns_load_t *load = event->ev_arg;
1623         isc_result_t result = ISC_R_SUCCESS;
1624         unsigned int options;
1625
1626         REQUIRE(DNS_LOAD_VALID(load));
1627
1628         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1629                 result = ISC_R_CANCELED;
1630         isc_event_free(&event);
1631         if (result == ISC_R_CANCELED)
1632                 goto fail;
1633
1634         options = get_master_options(load->zone);
1635
1636         result = dns_master_loadfileinc3(load->zone->masterfile,
1637                                          dns_db_origin(load->db),
1638                                          dns_db_origin(load->db),
1639                                          load->zone->rdclass,
1640                                          options,
1641                                          load->zone->sigresigninginterval,
1642                                          &load->callbacks, task,
1643                                          zone_loaddone, load,
1644                                          &load->zone->lctx, load->zone->mctx,
1645                                          load->zone->masterformat);
1646         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1647             result != DNS_R_SEENINCLUDE)
1648                 goto fail;
1649         return;
1650
1651  fail:
1652         zone_loaddone(load, result);
1653 }
1654
1655 static void
1656 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1657         const char me[] = "zone_gotwritehandle";
1658         dns_zone_t *zone = event->ev_arg;
1659         isc_result_t result = ISC_R_SUCCESS;
1660         dns_dbversion_t *version = NULL;
1661
1662         REQUIRE(DNS_ZONE_VALID(zone));
1663         INSIST(task == zone->task);
1664         ENTER;
1665
1666         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1667                 result = ISC_R_CANCELED;
1668         isc_event_free(&event);
1669         if (result == ISC_R_CANCELED)
1670                 goto fail;
1671
1672         LOCK_ZONE(zone);
1673         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1674         dns_db_currentversion(zone->db, &version);
1675         result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1676                                      &dns_master_style_default,
1677                                      zone->masterfile, zone->task, dump_done,
1678                                      zone, &zone->dctx, zone->masterformat);
1679         dns_db_closeversion(zone->db, &version, ISC_FALSE);
1680         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1681         UNLOCK_ZONE(zone);
1682         if (result != DNS_R_CONTINUE)
1683                 goto fail;
1684         return;
1685
1686  fail:
1687         dump_done(zone, result);
1688 }
1689
1690 static isc_result_t
1691 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1692         dns_load_t *load;
1693         isc_result_t result;
1694         isc_result_t tresult;
1695         unsigned int options;
1696
1697         options = get_master_options(zone);
1698
1699         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1700                 options |= DNS_MASTER_MANYERRORS;
1701
1702         if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1703                 load = isc_mem_get(zone->mctx, sizeof(*load));
1704                 if (load == NULL)
1705                         return (ISC_R_NOMEMORY);
1706
1707                 load->mctx = NULL;
1708                 load->zone = NULL;
1709                 load->db = NULL;
1710                 load->loadtime = loadtime;
1711                 load->magic = LOAD_MAGIC;
1712
1713                 isc_mem_attach(zone->mctx, &load->mctx);
1714                 zone_iattach(zone, &load->zone);
1715                 dns_db_attach(db, &load->db);
1716                 dns_rdatacallbacks_init(&load->callbacks);
1717                 result = dns_db_beginload(db, &load->callbacks.add,
1718                                           &load->callbacks.add_private);
1719                 if (result != ISC_R_SUCCESS)
1720                         goto cleanup;
1721                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1722                                        zone_gotreadhandle, load,
1723                                        &zone->readio);
1724                 if (result != ISC_R_SUCCESS) {
1725                         /*
1726                          * We can't report multiple errors so ignore
1727                          * the result of dns_db_endload().
1728                          */
1729                         (void)dns_db_endload(load->db,
1730                                              &load->callbacks.add_private);
1731                         goto cleanup;
1732                 } else
1733                         result = DNS_R_CONTINUE;
1734         } else {
1735                 dns_rdatacallbacks_t callbacks;
1736
1737                 dns_rdatacallbacks_init(&callbacks);
1738                 result = dns_db_beginload(db, &callbacks.add,
1739                                           &callbacks.add_private);
1740                 if (result != ISC_R_SUCCESS)
1741                         return (result);
1742                 result = dns_master_loadfile3(zone->masterfile, &zone->origin,
1743                                               &zone->origin, zone->rdclass,
1744                                               options, zone->sigresigninginterval,
1745                                               &callbacks, zone->mctx,
1746                                               zone->masterformat);
1747                 tresult = dns_db_endload(db, &callbacks.add_private);
1748                 if (result == ISC_R_SUCCESS)
1749                         result = tresult;
1750         }
1751
1752         return (result);
1753
1754  cleanup:
1755         load->magic = 0;
1756         dns_db_detach(&load->db);
1757         zone_idetach(&load->zone);
1758         isc_mem_detach(&load->mctx);
1759         isc_mem_put(zone->mctx, load, sizeof(*load));
1760         return (result);
1761 }
1762
1763 static isc_boolean_t
1764 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1765               dns_name_t *owner)
1766 {
1767         isc_result_t result;
1768         char ownerbuf[DNS_NAME_FORMATSIZE];
1769         char namebuf[DNS_NAME_FORMATSIZE];
1770         char altbuf[DNS_NAME_FORMATSIZE];
1771         dns_fixedname_t fixed;
1772         dns_name_t *foundname;
1773         int level;
1774
1775         /*
1776          * "." means the services does not exist.
1777          */
1778         if (dns_name_equal(name, dns_rootname))
1779                 return (ISC_TRUE);
1780
1781         /*
1782          * Outside of zone.
1783          */
1784         if (!dns_name_issubdomain(name, &zone->origin)) {
1785                 if (zone->checkmx != NULL)
1786                         return ((zone->checkmx)(zone, name, owner));
1787                 return (ISC_TRUE);
1788         }
1789
1790         if (zone->type == dns_zone_master)
1791                 level = ISC_LOG_ERROR;
1792         else
1793                 level = ISC_LOG_WARNING;
1794
1795         dns_fixedname_init(&fixed);
1796         foundname = dns_fixedname_name(&fixed);
1797
1798         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1799                              0, 0, NULL, foundname, NULL, NULL);
1800         if (result == ISC_R_SUCCESS)
1801                 return (ISC_TRUE);
1802
1803         if (result == DNS_R_NXRRSET) {
1804                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1805                                      0, 0, NULL, foundname, NULL, NULL);
1806                 if (result == ISC_R_SUCCESS)
1807                         return (ISC_TRUE);
1808         }
1809
1810         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1811         dns_name_format(name, namebuf, sizeof namebuf);
1812         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1813             result == DNS_R_EMPTYNAME) {
1814                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1815                         level = ISC_LOG_WARNING;
1816                 dns_zone_log(zone, level,
1817                              "%s/MX '%s' has no address records (A or AAAA)",
1818                              ownerbuf, namebuf);
1819                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1820         }
1821
1822         if (result == DNS_R_CNAME) {
1823                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1824                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1825                         level = ISC_LOG_WARNING;
1826                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1827                         dns_zone_log(zone, level,
1828                                      "%s/MX '%s' is a CNAME (illegal)",
1829                                      ownerbuf, namebuf);
1830                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1831         }
1832
1833         if (result == DNS_R_DNAME) {
1834                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1835                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1836                         level = ISC_LOG_WARNING;
1837                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1838                         dns_name_format(foundname, altbuf, sizeof altbuf);
1839                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1840                                      " '%s' (illegal)", ownerbuf, namebuf,
1841                                      altbuf);
1842                 }
1843                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1844         }
1845
1846         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1847                 return ((zone->checkmx)(zone, name, owner));
1848
1849         return (ISC_TRUE);
1850 }
1851
1852 static isc_boolean_t
1853 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1854                dns_name_t *owner)
1855 {
1856         isc_result_t result;
1857         char ownerbuf[DNS_NAME_FORMATSIZE];
1858         char namebuf[DNS_NAME_FORMATSIZE];
1859         char altbuf[DNS_NAME_FORMATSIZE];
1860         dns_fixedname_t fixed;
1861         dns_name_t *foundname;
1862         int level;
1863
1864         /*
1865          * "." means the services does not exist.
1866          */
1867         if (dns_name_equal(name, dns_rootname))
1868                 return (ISC_TRUE);
1869
1870         /*
1871          * Outside of zone.
1872          */
1873         if (!dns_name_issubdomain(name, &zone->origin)) {
1874                 if (zone->checksrv != NULL)
1875                         return ((zone->checksrv)(zone, name, owner));
1876                 return (ISC_TRUE);
1877         }
1878
1879         if (zone->type == dns_zone_master)
1880                 level = ISC_LOG_ERROR;
1881         else
1882                 level = ISC_LOG_WARNING;
1883
1884         dns_fixedname_init(&fixed);
1885         foundname = dns_fixedname_name(&fixed);
1886
1887         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1888                              0, 0, NULL, foundname, NULL, NULL);
1889         if (result == ISC_R_SUCCESS)
1890                 return (ISC_TRUE);
1891
1892         if (result == DNS_R_NXRRSET) {
1893                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1894                                      0, 0, NULL, foundname, NULL, NULL);
1895                 if (result == ISC_R_SUCCESS)
1896                         return (ISC_TRUE);
1897         }
1898
1899         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1900         dns_name_format(name, namebuf, sizeof namebuf);
1901         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1902             result == DNS_R_EMPTYNAME) {
1903                 dns_zone_log(zone, level,
1904                              "%s/SRV '%s' has no address records (A or AAAA)",
1905                              ownerbuf, namebuf);
1906                 /* XXX950 make fatal for 9.5.0. */
1907                 return (ISC_TRUE);
1908         }
1909
1910         if (result == DNS_R_CNAME) {
1911                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1912                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1913                         level = ISC_LOG_WARNING;
1914                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1915                         dns_zone_log(zone, level,
1916                                      "%s/SRV '%s' is a CNAME (illegal)",
1917                                      ownerbuf, namebuf);
1918                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1919         }
1920
1921         if (result == DNS_R_DNAME) {
1922                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1923                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1924                         level = ISC_LOG_WARNING;
1925                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1926                         dns_name_format(foundname, altbuf, sizeof altbuf);
1927                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1928                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
1929                                      altbuf);
1930                 }
1931                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1932         }
1933
1934         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1935                 return ((zone->checksrv)(zone, name, owner));
1936
1937         return (ISC_TRUE);
1938 }
1939
1940 static isc_boolean_t
1941 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1942                 dns_name_t *owner)
1943 {
1944         isc_boolean_t answer = ISC_TRUE;
1945         isc_result_t result, tresult;
1946         char ownerbuf[DNS_NAME_FORMATSIZE];
1947         char namebuf[DNS_NAME_FORMATSIZE];
1948         char altbuf[DNS_NAME_FORMATSIZE];
1949         dns_fixedname_t fixed;
1950         dns_name_t *foundname;
1951         dns_rdataset_t a;
1952         dns_rdataset_t aaaa;
1953         int level;
1954
1955         /*
1956          * Outside of zone.
1957          */
1958         if (!dns_name_issubdomain(name, &zone->origin)) {
1959                 if (zone->checkns != NULL)
1960                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
1961                 return (ISC_TRUE);
1962         }
1963
1964         if (zone->type == dns_zone_master)
1965                 level = ISC_LOG_ERROR;
1966         else
1967                 level = ISC_LOG_WARNING;
1968
1969         dns_fixedname_init(&fixed);
1970         foundname = dns_fixedname_name(&fixed);
1971         dns_rdataset_init(&a);
1972         dns_rdataset_init(&aaaa);
1973
1974         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1975                              DNS_DBFIND_GLUEOK, 0, NULL,
1976                              foundname, &a, NULL);
1977
1978         if (result == ISC_R_SUCCESS) {
1979                 dns_rdataset_disassociate(&a);
1980                 return (ISC_TRUE);
1981         } else if (result == DNS_R_DELEGATION)
1982                 dns_rdataset_disassociate(&a);
1983
1984         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1985             result == DNS_R_GLUE) {
1986                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1987                                      DNS_DBFIND_GLUEOK, 0, NULL,
1988                                      foundname, &aaaa, NULL);
1989                 if (tresult == ISC_R_SUCCESS) {
1990                         dns_rdataset_disassociate(&aaaa);
1991                         return (ISC_TRUE);
1992                 }
1993                 if (tresult == DNS_R_DELEGATION)
1994                         dns_rdataset_disassociate(&aaaa);
1995                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
1996                         /*
1997                          * Check glue against child zone.
1998                          */
1999                         if (zone->checkns != NULL)
2000                                 answer = (zone->checkns)(zone, name, owner,
2001                                                          &a, &aaaa);
2002                         if (dns_rdataset_isassociated(&a))
2003                                 dns_rdataset_disassociate(&a);
2004                         if (dns_rdataset_isassociated(&aaaa))
2005                                 dns_rdataset_disassociate(&aaaa);
2006                         return (answer);
2007                 }
2008         }
2009
2010         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2011         dns_name_format(name, namebuf, sizeof namebuf);
2012         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2013             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2014                 const char *what;
2015                 isc_boolean_t required = ISC_FALSE;
2016                 if (dns_name_issubdomain(name, owner)) {
2017                         what = "REQUIRED GLUE ";
2018                         required = ISC_TRUE;
2019                  } else if (result == DNS_R_DELEGATION)
2020                         what = "SIBLING GLUE ";
2021                 else
2022                         what = "";
2023
2024                 if (result != DNS_R_DELEGATION || required ||
2025                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2026                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2027                                      "address records (A or AAAA)",
2028                                      ownerbuf, namebuf, what);
2029                         /*
2030                          * Log missing address record.
2031                          */
2032                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2033                                 (void)(zone->checkns)(zone, name, owner,
2034                                                       &a, &aaaa);
2035                         /* XXX950 make fatal for 9.5.0. */
2036                         /* answer = ISC_FALSE; */
2037                 }
2038         } else if (result == DNS_R_CNAME) {
2039                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2040                              ownerbuf, namebuf);
2041                 /* XXX950 make fatal for 9.5.0. */
2042                 /* answer = ISC_FALSE; */
2043         } else if (result == DNS_R_DNAME) {
2044                 dns_name_format(foundname, altbuf, sizeof altbuf);
2045                 dns_zone_log(zone, level,
2046                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
2047                              ownerbuf, namebuf, altbuf);
2048                 /* XXX950 make fatal for 9.5.0. */
2049                 /* answer = ISC_FALSE; */
2050         }
2051
2052         if (dns_rdataset_isassociated(&a))
2053                 dns_rdataset_disassociate(&a);
2054         if (dns_rdataset_isassociated(&aaaa))
2055                 dns_rdataset_disassociate(&aaaa);
2056         return (answer);
2057 }
2058
2059 static isc_boolean_t
2060 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2061                      dns_rdataset_t *rdataset)
2062 {
2063         dns_rdataset_t tmprdataset;
2064         isc_result_t result;
2065         isc_boolean_t answer = ISC_TRUE;
2066         isc_boolean_t format = ISC_TRUE;
2067         int level = ISC_LOG_WARNING;
2068         char ownerbuf[DNS_NAME_FORMATSIZE];
2069         char typebuf[DNS_RDATATYPE_FORMATSIZE];
2070         unsigned int count1 = 0;
2071
2072         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2073                 level = ISC_LOG_ERROR;
2074
2075         dns_rdataset_init(&tmprdataset);
2076         for (result = dns_rdataset_first(rdataset);
2077              result == ISC_R_SUCCESS;
2078              result = dns_rdataset_next(rdataset)) {
2079                 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2080                 unsigned int count2 = 0;
2081
2082                 count1++;
2083                 dns_rdataset_current(rdataset, &rdata1);
2084                 dns_rdataset_clone(rdataset, &tmprdataset);
2085                 for (result = dns_rdataset_first(&tmprdataset);
2086                      result == ISC_R_SUCCESS;
2087                      result = dns_rdataset_next(&tmprdataset)) {
2088                         dns_rdata_t rdata2 = DNS_RDATA_INIT;
2089                         count2++;
2090                         if (count1 >= count2)
2091                                 continue;
2092                         dns_rdataset_current(&tmprdataset, &rdata2);
2093                         if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2094                                 if (format) {
2095                                         dns_name_format(owner, ownerbuf,
2096                                                         sizeof ownerbuf);
2097                                         dns_rdatatype_format(rdata1.type,
2098                                                              typebuf,
2099                                                              sizeof(typebuf));
2100                                         format = ISC_FALSE;
2101                                 }
2102                                 dns_zone_log(zone, level, "%s/%s has "
2103                                              "semantically identical records",
2104                                              ownerbuf, typebuf);
2105                                 if (level == ISC_LOG_ERROR)
2106                                         answer = ISC_FALSE;
2107                                 break;
2108                         }
2109                 }
2110                 dns_rdataset_disassociate(&tmprdataset);
2111                 if (!format)
2112                         break;
2113         }
2114         return (answer);
2115 }
2116
2117 static isc_boolean_t
2118 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2119         dns_dbiterator_t *dbiterator = NULL;
2120         dns_dbnode_t *node = NULL;
2121         dns_fixedname_t fixed;
2122         dns_name_t *name;
2123         dns_rdataset_t rdataset;
2124         dns_rdatasetiter_t *rdsit = NULL;
2125         isc_boolean_t ok = ISC_TRUE;
2126         isc_result_t result;
2127
2128         dns_fixedname_init(&fixed);
2129         name = dns_fixedname_name(&fixed);
2130         dns_rdataset_init(&rdataset);
2131
2132         result = dns_db_createiterator(db, 0, &dbiterator);
2133         if (result != ISC_R_SUCCESS)
2134                 return (ISC_TRUE);
2135
2136         for (result = dns_dbiterator_first(dbiterator);
2137              result == ISC_R_SUCCESS;
2138              result = dns_dbiterator_next(dbiterator)) {
2139                 result = dns_dbiterator_current(dbiterator, &node, name);
2140                 if (result != ISC_R_SUCCESS)
2141                         continue;
2142
2143                 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2144                 if (result != ISC_R_SUCCESS)
2145                         continue;
2146
2147                 for (result = dns_rdatasetiter_first(rdsit);
2148                      result == ISC_R_SUCCESS;
2149                      result = dns_rdatasetiter_next(rdsit)) {
2150                         dns_rdatasetiter_current(rdsit, &rdataset);
2151                         if (!zone_rrset_check_dup(zone, name, &rdataset))
2152                                 ok = ISC_FALSE;
2153                         dns_rdataset_disassociate(&rdataset);
2154                 }
2155                 dns_rdatasetiter_destroy(&rdsit);
2156                 dns_db_detachnode(db, &node);
2157         }
2158
2159         if (node != NULL)
2160                 dns_db_detachnode(db, &node);
2161         dns_dbiterator_destroy(&dbiterator);
2162
2163         return (ok);
2164 }
2165
2166 static isc_boolean_t
2167 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2168         dns_dbiterator_t *dbiterator = NULL;
2169         dns_dbnode_t *node = NULL;
2170         dns_rdataset_t rdataset;
2171         dns_fixedname_t fixed;
2172         dns_fixedname_t fixedbottom;
2173         dns_rdata_mx_t mx;
2174         dns_rdata_ns_t ns;
2175         dns_rdata_in_srv_t srv;
2176         dns_rdata_t rdata;
2177         dns_name_t *name;
2178         dns_name_t *bottom;
2179         isc_result_t result;
2180         isc_boolean_t ok = ISC_TRUE;
2181
2182         dns_fixedname_init(&fixed);
2183         name = dns_fixedname_name(&fixed);
2184         dns_fixedname_init(&fixedbottom);
2185         bottom = dns_fixedname_name(&fixedbottom);
2186         dns_rdataset_init(&rdataset);
2187         dns_rdata_init(&rdata);
2188
2189         result = dns_db_createiterator(db, 0, &dbiterator);
2190         if (result != ISC_R_SUCCESS)
2191                 return (ISC_TRUE);
2192
2193         result = dns_dbiterator_first(dbiterator);
2194         while (result == ISC_R_SUCCESS) {
2195                 result = dns_dbiterator_current(dbiterator, &node, name);
2196                 if (result != ISC_R_SUCCESS)
2197                         goto cleanup;
2198
2199                 /*
2200                  * Is this name visible in the zone?
2201                  */
2202                 if (!dns_name_issubdomain(name, &zone->origin) ||
2203                     (dns_name_countlabels(bottom) > 0 &&
2204                      dns_name_issubdomain(name, bottom)))
2205                         goto next;
2206
2207                 /*
2208                  * Don't check the NS records at the origin.
2209                  */
2210                 if (dns_name_equal(name, &zone->origin))
2211                         goto checkmx;
2212
2213                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2214                                              0, 0, &rdataset, NULL);
2215                 if (result != ISC_R_SUCCESS)
2216                         goto checkmx;
2217                 /*
2218                  * Remember bottom of zone.
2219                  */
2220                 dns_name_copy(name, bottom, NULL);
2221
2222                 result = dns_rdataset_first(&rdataset);
2223                 while (result == ISC_R_SUCCESS) {
2224                         dns_rdataset_current(&rdataset, &rdata);
2225                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2226                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2227                         if (!zone_check_glue(zone, db, &ns.name, name))
2228                                 ok = ISC_FALSE;
2229                         dns_rdata_reset(&rdata);
2230                         result = dns_rdataset_next(&rdataset);
2231                 }
2232                 dns_rdataset_disassociate(&rdataset);
2233                 goto next;
2234
2235  checkmx:
2236                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2237                                              0, 0, &rdataset, NULL);
2238                 if (result != ISC_R_SUCCESS)
2239                         goto checksrv;
2240                 result = dns_rdataset_first(&rdataset);
2241                 while (result == ISC_R_SUCCESS) {
2242                         dns_rdataset_current(&rdataset, &rdata);
2243                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2244                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2245                         if (!zone_check_mx(zone, db, &mx.mx, name))
2246                                 ok = ISC_FALSE;
2247                         dns_rdata_reset(&rdata);
2248                         result = dns_rdataset_next(&rdataset);
2249                 }
2250                 dns_rdataset_disassociate(&rdataset);
2251
2252  checksrv:
2253                 if (zone->rdclass != dns_rdataclass_in)
2254                         goto next;
2255                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2256                                              0, 0, &rdataset, NULL);
2257                 if (result != ISC_R_SUCCESS)
2258                         goto next;
2259                 result = dns_rdataset_first(&rdataset);
2260                 while (result == ISC_R_SUCCESS) {
2261                         dns_rdataset_current(&rdataset, &rdata);
2262                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2263                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2264                         if (!zone_check_srv(zone, db, &srv.target, name))
2265                                 ok = ISC_FALSE;
2266                         dns_rdata_reset(&rdata);
2267                         result = dns_rdataset_next(&rdataset);
2268                 }
2269                 dns_rdataset_disassociate(&rdataset);
2270
2271  next:
2272                 dns_db_detachnode(db, &node);
2273                 result = dns_dbiterator_next(dbiterator);
2274         }
2275
2276  cleanup:
2277         if (node != NULL)
2278                 dns_db_detachnode(db, &node);
2279         dns_dbiterator_destroy(&dbiterator);
2280
2281         return (ok);
2282 }
2283
2284 /*
2285  * OpenSSL verification of RSA keys with exponent 3 is known to be
2286  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2287  * if they are in use.
2288  */
2289 static void
2290 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2291         dns_dbnode_t *node = NULL;
2292         dns_dbversion_t *version = NULL;
2293         dns_rdata_dnskey_t dnskey;
2294         dns_rdata_t rdata = DNS_RDATA_INIT;
2295         dns_rdataset_t rdataset;
2296         isc_result_t result;
2297         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2298         const char *algorithm;
2299
2300         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2301         if (result != ISC_R_SUCCESS)
2302                 goto cleanup;
2303
2304         dns_db_currentversion(db, &version);
2305         dns_rdataset_init(&rdataset);
2306         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2307                                      dns_rdatatype_none, 0, &rdataset, NULL);
2308         if (result != ISC_R_SUCCESS)
2309                 goto cleanup;
2310
2311         for (result = dns_rdataset_first(&rdataset);
2312              result == ISC_R_SUCCESS;
2313              result = dns_rdataset_next(&rdataset))
2314         {
2315                 dns_rdataset_current(&rdataset, &rdata);
2316                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2317                 INSIST(result == ISC_R_SUCCESS);
2318
2319                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2320                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2321                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2322                      dnskey.data[1] == 3)
2323                 {
2324                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2325                                 logit = !foundrsa;
2326                                 foundrsa = ISC_TRUE;
2327                                 algorithm = "RSASHA1";
2328                         } else {
2329                                 logit = !foundmd5;
2330                                 foundmd5 = ISC_TRUE;
2331                                 algorithm = "RSAMD5";
2332                         }
2333                         if (logit)
2334                                 dns_zone_log(zone, ISC_LOG_WARNING,
2335                                              "weak %s (%u) key found "
2336                                              "(exponent=3)", algorithm,
2337                                              dnskey.algorithm);
2338                         if (foundrsa && foundmd5)
2339                                 break;
2340                 }
2341                 dns_rdata_reset(&rdata);
2342         }
2343         dns_rdataset_disassociate(&rdataset);
2344
2345  cleanup:
2346         if (node != NULL)
2347                 dns_db_detachnode(db, &node);
2348         if (version != NULL)
2349                 dns_db_closeversion(db, &version, ISC_FALSE);
2350 }
2351
2352 static void
2353 resume_signingwithkey(dns_zone_t *zone) {
2354         dns_dbnode_t *node = NULL;
2355         dns_dbversion_t *version = NULL;
2356         dns_rdata_t rdata = DNS_RDATA_INIT;
2357         dns_rdataset_t rdataset;
2358         isc_result_t result;
2359
2360         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2361         if (result != ISC_R_SUCCESS)
2362                 goto cleanup;
2363
2364         dns_db_currentversion(zone->db, &version);
2365         dns_rdataset_init(&rdataset);
2366         result = dns_db_findrdataset(zone->db, node, version,
2367                                      zone->privatetype,
2368                                      dns_rdatatype_none, 0,
2369                                      &rdataset, NULL);
2370         if (result != ISC_R_SUCCESS) {
2371                 INSIST(!dns_rdataset_isassociated(&rdataset));
2372                 goto cleanup;
2373         }
2374
2375         for (result = dns_rdataset_first(&rdataset);
2376              result == ISC_R_SUCCESS;
2377              result = dns_rdataset_next(&rdataset))
2378         {
2379                 dns_rdataset_current(&rdataset, &rdata);
2380                 if (rdata.length != 5 ||
2381                     rdata.data[0] == 0 || rdata.data[4] != 0) {
2382                         dns_rdata_reset(&rdata);
2383                         continue;
2384                 }
2385
2386                 result = zone_signwithkey(zone, rdata.data[0],
2387                                           (rdata.data[1] << 8) | rdata.data[2],
2388                                           ISC_TF(rdata.data[3]));
2389                 if (result != ISC_R_SUCCESS) {
2390                         dns_zone_log(zone, ISC_LOG_ERROR,
2391                                      "zone_signwithkey failed: %s",
2392                                      dns_result_totext(result));
2393                 }
2394                 dns_rdata_reset(&rdata);
2395         }
2396         dns_rdataset_disassociate(&rdataset);
2397
2398  cleanup:
2399         if (node != NULL)
2400                 dns_db_detachnode(zone->db, &node);
2401         if (version != NULL)
2402                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2403 }
2404
2405 static isc_result_t
2406 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2407         dns_nsec3chain_t *nsec3chain, *current;
2408         isc_result_t result;
2409         isc_time_t now;
2410         unsigned int options = 0;
2411         char saltbuf[255*2+1];
2412         char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")];
2413         int i;
2414
2415         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2416         if (nsec3chain == NULL)
2417                 return (ISC_R_NOMEMORY);
2418
2419         nsec3chain->magic = 0;
2420         nsec3chain->done = ISC_FALSE;
2421         nsec3chain->db = NULL;
2422         nsec3chain->dbiterator = NULL;
2423         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2424         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2425         nsec3chain->nsec3param.hash = nsec3param->hash;
2426         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2427         nsec3chain->nsec3param.flags = nsec3param->flags;
2428         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2429         memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2430         nsec3chain->nsec3param.salt = nsec3chain->salt;
2431         nsec3chain->seen_nsec = ISC_FALSE;
2432         nsec3chain->delete_nsec = ISC_FALSE;
2433         nsec3chain->save_delete_nsec = ISC_FALSE;
2434
2435         if (nsec3param->flags == 0)
2436                 strlcpy(flags, "NONE", sizeof(flags));
2437         else {
2438                 flags[0] = '\0';
2439                 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2440                         strlcat(flags, "REMOVE", sizeof(flags));
2441                 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2442                         if (flags[0] == '\0')
2443                                 strlcpy(flags, "CREATE", sizeof(flags));
2444                         else
2445                                 strlcat(flags, "|CREATE", sizeof(flags));
2446                 }
2447                 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2448                         if (flags[0] == '\0')
2449                                 strlcpy(flags, "NONSEC", sizeof(flags));
2450                         else
2451                                 strlcat(flags, "|NONSEC", sizeof(flags));
2452                 }
2453                 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2454                         if (flags[0] == '\0')
2455                                 strlcpy(flags, "OPTOUT", sizeof(flags));
2456                         else
2457                                 strlcat(flags, "|OPTOUT", sizeof(flags));
2458                 }
2459         }
2460         if (nsec3param->salt_length == 0)
2461                 strlcpy(saltbuf, "-", sizeof(saltbuf));
2462         else
2463                 for (i = 0; i < nsec3param->salt_length; i++)
2464                         sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2465         dns_zone_log(zone, ISC_LOG_INFO,
2466                      "zone_addnsec3chain(%u,%s,%u,%s)",
2467                       nsec3param->hash, flags, nsec3param->iterations,
2468                       saltbuf);
2469         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2470              current != NULL;
2471              current = ISC_LIST_NEXT(current, link)) {
2472                 if (current->db == zone->db &&
2473                     current->nsec3param.hash == nsec3param->hash &&
2474                     current->nsec3param.iterations == nsec3param->iterations &&
2475                     current->nsec3param.salt_length == nsec3param->salt_length
2476                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2477                                nsec3param->salt_length))
2478                         current->done = ISC_TRUE;
2479         }
2480
2481         if (zone->db != NULL) {
2482                 dns_db_attach(zone->db, &nsec3chain->db);
2483                 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2484                         options = DNS_DB_NONSEC3;
2485                 result = dns_db_createiterator(nsec3chain->db, options,
2486                                                &nsec3chain->dbiterator);
2487                 if (result == ISC_R_SUCCESS)
2488                         dns_dbiterator_first(nsec3chain->dbiterator);
2489                 if (result == ISC_R_SUCCESS) {
2490                         dns_dbiterator_pause(nsec3chain->dbiterator);
2491                         ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2492                                                nsec3chain, link);
2493                         nsec3chain = NULL;
2494                         if (isc_time_isepoch(&zone->nsec3chaintime)) {
2495                                 TIME_NOW(&now);
2496                                 zone->nsec3chaintime = now;
2497                                 if (zone->task != NULL)
2498                                         zone_settimer(zone, &now);
2499                         }
2500                 }
2501         } else
2502                 result = ISC_R_NOTFOUND;
2503
2504         if (nsec3chain != NULL) {
2505                 if (nsec3chain->db != NULL)
2506                         dns_db_detach(&nsec3chain->db);
2507                 if (nsec3chain->dbiterator != NULL)
2508                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
2509                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2510         }
2511         return (result);
2512 }
2513
2514 static void
2515 resume_addnsec3chain(dns_zone_t *zone) {
2516         dns_dbnode_t *node = NULL;
2517         dns_dbversion_t *version = NULL;
2518         dns_rdataset_t rdataset;
2519         isc_result_t result;
2520         dns_rdata_nsec3param_t nsec3param;
2521
2522         if (zone->privatetype == 0)
2523                 return;
2524
2525         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2526         if (result != ISC_R_SUCCESS)
2527                 goto cleanup;
2528
2529         dns_db_currentversion(zone->db, &version);
2530         dns_rdataset_init(&rdataset);
2531         result = dns_db_findrdataset(zone->db, node, version,
2532                                      zone->privatetype, dns_rdatatype_none,
2533                                      0, &rdataset, NULL);
2534         if (result != ISC_R_SUCCESS) {
2535                 INSIST(!dns_rdataset_isassociated(&rdataset));
2536                 goto cleanup;
2537         }
2538
2539         for (result = dns_rdataset_first(&rdataset);
2540              result == ISC_R_SUCCESS;
2541              result = dns_rdataset_next(&rdataset))
2542         {
2543                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
2544                 dns_rdata_t rdata = DNS_RDATA_INIT;
2545                 dns_rdata_t private = DNS_RDATA_INIT;
2546
2547                 dns_rdataset_current(&rdataset, &private);
2548                 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
2549                                                 sizeof(buf)))
2550                         continue;
2551                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2552                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2553                 if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
2554                     (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
2555                         result = zone_addnsec3chain(zone, &nsec3param);
2556                         if (result != ISC_R_SUCCESS) {
2557                                 dns_zone_log(zone, ISC_LOG_ERROR,
2558                                              "zone_addnsec3chain failed: %s",
2559                                              dns_result_totext(result));
2560                         }
2561                 }
2562         }
2563         dns_rdataset_disassociate(&rdataset);
2564  cleanup:
2565         if (node != NULL)
2566                 dns_db_detachnode(zone->db, &node);
2567         if (version != NULL)
2568                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2569 }
2570
2571 static void
2572 set_resigntime(dns_zone_t *zone) {
2573         dns_rdataset_t rdataset;
2574         dns_fixedname_t fixed;
2575         unsigned int resign;
2576         isc_result_t result;
2577         isc_uint32_t nanosecs;
2578
2579         dns_rdataset_init(&rdataset);
2580         dns_fixedname_init(&fixed);
2581         result = dns_db_getsigningtime(zone->db, &rdataset,
2582                                        dns_fixedname_name(&fixed));
2583         if (result != ISC_R_SUCCESS) {
2584                 isc_time_settoepoch(&zone->resigntime);
2585                 return;
2586         }
2587         resign = rdataset.resign;
2588         dns_rdataset_disassociate(&rdataset);
2589         isc_random_get(&nanosecs);
2590         nanosecs %= 1000000000;
2591         isc_time_set(&zone->resigntime, resign, nanosecs);
2592 }
2593
2594 static isc_result_t
2595 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2596         dns_dbnode_t *node = NULL;
2597         dns_rdataset_t rdataset;
2598         dns_dbversion_t *version = NULL;
2599         dns_rdata_nsec3param_t nsec3param;
2600         isc_boolean_t ok = ISC_FALSE;
2601         isc_result_t result;
2602         dns_rdata_t rdata = DNS_RDATA_INIT;
2603         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2604                                 zone_isdynamic(zone) : ISC_FALSE;
2605
2606         dns_rdataset_init(&rdataset);
2607         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2608         if (result != ISC_R_SUCCESS) {
2609                 dns_zone_log(zone, ISC_LOG_ERROR,
2610                              "nsec3param lookup failure: %s",
2611                              dns_result_totext(result));
2612                 return (result);
2613         }
2614         dns_db_currentversion(db, &version);
2615
2616         result = dns_db_findrdataset(db, node, version,
2617                                      dns_rdatatype_nsec3param,
2618                                      dns_rdatatype_none, 0, &rdataset, NULL);
2619         if (result == ISC_R_NOTFOUND) {
2620                 INSIST(!dns_rdataset_isassociated(&rdataset));
2621                 result = ISC_R_SUCCESS;
2622                 goto cleanup;
2623         }
2624         if (result != ISC_R_SUCCESS) {
2625                 INSIST(!dns_rdataset_isassociated(&rdataset));
2626                 dns_zone_log(zone, ISC_LOG_ERROR,
2627                              "nsec3param lookup failure: %s",
2628                              dns_result_totext(result));
2629                 goto cleanup;
2630         }
2631
2632         /*
2633          * For dynamic zones we must support every algorithm so we can
2634          * regenerate all the NSEC3 chains.
2635          * For non-dynamic zones we only need to find a supported algorithm.
2636          */
2637         for (result = dns_rdataset_first(&rdataset);
2638              result == ISC_R_SUCCESS;
2639              result = dns_rdataset_next(&rdataset))
2640         {
2641                 dns_rdataset_current(&rdataset, &rdata);
2642                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2643                 dns_rdata_reset(&rdata);
2644                 INSIST(result == ISC_R_SUCCESS);
2645                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2646                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2647                 {
2648                         dns_zone_log(zone, ISC_LOG_WARNING,
2649                              "nsec3 test \"unknown\" hash algorithm found: %u",
2650                                      nsec3param.hash);
2651                         ok = ISC_TRUE;
2652                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2653                         if (dynamic) {
2654                                 dns_zone_log(zone, ISC_LOG_ERROR,
2655                                              "unsupported nsec3 hash algorithm"
2656                                              " in dynamic zone: %u",
2657                                              nsec3param.hash);
2658                                 result = DNS_R_BADZONE;
2659                                 /* Stop second error message. */
2660                                 ok = ISC_TRUE;
2661                                 break;
2662                         } else
2663                                 dns_zone_log(zone, ISC_LOG_WARNING,
2664                                      "unsupported nsec3 hash algorithm: %u",
2665                                              nsec3param.hash);
2666                 } else
2667                         ok = ISC_TRUE;
2668         }
2669         if (result == ISC_R_NOMORE)
2670                 result = ISC_R_SUCCESS;
2671
2672         if (!ok) {
2673                 result = DNS_R_BADZONE;
2674                 dns_zone_log(zone, ISC_LOG_ERROR,
2675                              "no supported nsec3 hash algorithm");
2676         }
2677
2678  cleanup:
2679         if (dns_rdataset_isassociated(&rdataset))
2680                 dns_rdataset_disassociate(&rdataset);
2681         dns_db_closeversion(db, &version, ISC_FALSE);
2682         dns_db_detachnode(db, &node);
2683         return (result);
2684 }
2685
2686 /*
2687  * Set the timer for refreshing the key zone to the soonest future time
2688  * of the set (current timer, keydata->refresh, keydata->addhd,
2689  * keydata->removehd).
2690  */
2691 static void
2692 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
2693                     isc_stdtime_t now) {
2694         const char me[] = "set_refreshkeytimer";
2695         isc_stdtime_t then;
2696         isc_time_t timenow, timethen;
2697         char timebuf[80];
2698
2699         ENTER;
2700         then = key->refresh;
2701         if (key->addhd > now && key->addhd < then)
2702                 then = key->addhd;
2703         if (key->removehd > now && key->removehd < then)
2704                 then = key->removehd;
2705
2706         TIME_NOW(&timenow);
2707         if (then > now)
2708                 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
2709         else
2710                 timethen = timenow;
2711         if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
2712             isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
2713                 zone->refreshkeytime = timethen;
2714
2715         isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
2716         dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
2717         zone_settimer(zone, &timenow);
2718 }
2719
2720 /*
2721  * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
2722  * If the key zone is changed, set '*changed' to ISC_TRUE.
2723  */
2724 static isc_result_t
2725 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
2726                dns_diff_t *diff, dns_keytable_t *keytable,
2727                dns_keynode_t **keynodep, isc_boolean_t *changed)
2728 {
2729         const char me[] = "create_keydata";
2730         isc_result_t result = ISC_R_SUCCESS;
2731         isc_buffer_t keyb, dstb;
2732         unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
2733         dns_rdata_keydata_t keydata;
2734         dns_rdata_dnskey_t dnskey;
2735         dns_rdata_t rdata = DNS_RDATA_INIT;
2736         dns_keynode_t *keynode;
2737         isc_stdtime_t now;
2738         isc_region_t r;
2739         dst_key_t *key;
2740
2741         REQUIRE(keynodep != NULL);
2742         keynode = *keynodep;
2743
2744         ENTER;
2745         isc_stdtime_get(&now);
2746
2747         /* Loop in case there's more than one key. */
2748         while (result == ISC_R_SUCCESS) {
2749                 dns_keynode_t *nextnode = NULL;
2750
2751                 key = dns_keynode_key(keynode);
2752                 if (key == NULL)
2753                         goto skip;
2754
2755                 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
2756                 CHECK(dst_key_todns(key, &dstb));
2757
2758                 /* Convert DST key to DNSKEY. */
2759                 dns_rdata_reset(&rdata);
2760                 isc_buffer_usedregion(&dstb, &r);
2761                 dns_rdata_fromregion(&rdata, dst_key_class(key),
2762                                      dns_rdatatype_dnskey, &r);
2763
2764                 /* DSTKEY to KEYDATA. */
2765                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
2766                 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
2767                                              NULL));
2768
2769                 /* KEYDATA to rdata. */
2770                 dns_rdata_reset(&rdata);
2771                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
2772                 CHECK(dns_rdata_fromstruct(&rdata,
2773                                            zone->rdclass, dns_rdatatype_keydata,
2774                                            &keydata, &keyb));
2775
2776                 /* Add rdata to zone. */
2777                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
2778                                     dst_key_name(key), 0, &rdata));
2779                 *changed = ISC_TRUE;
2780
2781  skip:
2782                 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
2783                 if (result != ISC_R_NOTFOUND) {
2784                         dns_keytable_detachkeynode(keytable, &keynode);
2785                         keynode = nextnode;
2786                 }
2787         }
2788
2789         /* Refresh new keys from the zone apex as soon as possible. */
2790         if (*changed)
2791                 set_refreshkeytimer(zone, &keydata, now);
2792
2793         if (keynode != NULL)
2794                 dns_keytable_detachkeynode(keytable, &keynode);
2795         *keynodep = NULL;
2796
2797         return (ISC_R_SUCCESS);
2798
2799   failure:
2800         return (result);
2801 }
2802
2803 /*
2804  * Remove from the key zone all the KEYDATA records found in rdataset.
2805  */
2806 static isc_result_t
2807 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
2808                dns_name_t *name, dns_rdataset_t *rdataset)
2809 {
2810         dns_rdata_t rdata = DNS_RDATA_INIT;
2811         isc_result_t result, uresult;
2812
2813         for (result = dns_rdataset_first(rdataset);
2814              result == ISC_R_SUCCESS;
2815              result = dns_rdataset_next(rdataset)) {
2816                 dns_rdata_reset(&rdata);
2817                 dns_rdataset_current(rdataset, &rdata);
2818                 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
2819                                         name, 0, &rdata);
2820                 if (uresult != ISC_R_SUCCESS)
2821                         return (uresult);
2822         }
2823         if (result == ISC_R_NOMORE)
2824                 result = ISC_R_SUCCESS;
2825         return (result);
2826 }
2827
2828 /*
2829  * Compute the DNSSEC key ID for a DNSKEY record.
2830  */
2831 static isc_result_t
2832 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
2833             dns_keytag_t *tag)
2834 {
2835         isc_result_t result;
2836         dns_rdata_t rdata = DNS_RDATA_INIT;
2837         unsigned char data[4096];
2838         isc_buffer_t buffer;
2839         dst_key_t *dstkey = NULL;
2840
2841         isc_buffer_init(&buffer, data, sizeof(data));
2842         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2843                              dns_rdatatype_dnskey, dnskey, &buffer);
2844
2845         result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
2846         if (result == ISC_R_SUCCESS)
2847                 *tag = dst_key_id(dstkey);
2848         dst_key_free(&dstkey);
2849
2850         return (result);
2851 }
2852
2853 /*
2854  * Add key to the security roots.
2855  */
2856 static void
2857 trust_key(dns_zone_t *zone, dns_name_t *keyname,
2858           dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
2859         isc_result_t result;
2860         dns_rdata_t rdata = DNS_RDATA_INIT;
2861         unsigned char data[4096];
2862         isc_buffer_t buffer;
2863         dns_keytable_t *sr = NULL;
2864         dst_key_t *dstkey = NULL;
2865
2866         /* Convert dnskey to DST key. */
2867         isc_buffer_init(&buffer, data, sizeof(data));
2868         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2869                              dns_rdatatype_dnskey, dnskey, &buffer);
2870
2871         result = dns_view_getsecroots(zone->view, &sr);
2872         if (result != ISC_R_SUCCESS)
2873                 goto failure;
2874
2875         CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
2876         CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
2877         dns_keytable_detach(&sr);
2878
2879   failure:
2880         if (dstkey != NULL)
2881                 dst_key_free(&dstkey);
2882         if (sr != NULL)
2883                 dns_keytable_detach(&sr);
2884         return;
2885 }
2886
2887 /*
2888  * Add a null key to the security roots for so that all queries
2889  * to the zone will fail.
2890  */
2891 static void
2892 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
2893         isc_result_t result;
2894         dns_keytable_t *sr = NULL;
2895
2896         result = dns_view_getsecroots(zone->view, &sr);
2897         if (result == ISC_R_SUCCESS) {
2898                 dns_keytable_marksecure(sr, keyname);
2899                 dns_keytable_detach(&sr);
2900         }
2901 }
2902
2903 /*
2904  * Scan a set of KEYDATA records from the key zone.  The ones that are
2905  * valid (i.e., the add holddown timer has expired) become trusted keys.
2906  */
2907 static void
2908 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
2909         isc_result_t result;
2910         dns_rdata_t rdata = DNS_RDATA_INIT;
2911         dns_rdata_keydata_t keydata;
2912         dns_rdata_dnskey_t dnskey;
2913         isc_mem_t *mctx = zone->mctx;
2914         int trusted = 0, revoked = 0, pending = 0;
2915         isc_stdtime_t now;
2916         dns_keytable_t *sr = NULL;
2917
2918         isc_stdtime_get(&now);
2919
2920         result = dns_view_getsecroots(zone->view, &sr);
2921         if (result == ISC_R_SUCCESS) {
2922                 dns_keytable_delete(sr, name);
2923                 dns_keytable_detach(&sr);
2924         }
2925
2926         /* Now insert all the accepted trust anchors from this keydata set. */
2927         for (result = dns_rdataset_first(rdataset);
2928              result == ISC_R_SUCCESS;
2929              result = dns_rdataset_next(rdataset)) {
2930                 dns_rdata_reset(&rdata);
2931                 dns_rdataset_current(rdataset, &rdata);
2932
2933                 /* Convert rdata to keydata. */
2934                 dns_rdata_tostruct(&rdata, &keydata, NULL);
2935
2936                 /* Set the key refresh timer. */
2937                 set_refreshkeytimer(zone, &keydata, now);
2938
2939                 /* If the removal timer is nonzero, this key was revoked. */
2940                 if (keydata.removehd != 0) {
2941                         revoked++;
2942                         continue;
2943                 }
2944
2945                 /*
2946                  * If the add timer is still pending, this key is not
2947                  * trusted yet.
2948                  */
2949                 if (now < keydata.addhd) {
2950                         pending++;
2951                         continue;
2952                 }
2953
2954                 /* Convert keydata to dnskey. */
2955                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
2956
2957                 /* Add to keytables. */
2958                 trusted++;
2959                 trust_key(zone, name, &dnskey, mctx);
2960         }
2961
2962         if (trusted == 0 && pending != 0) {
2963                 char namebuf[DNS_NAME_FORMATSIZE];
2964                 dns_name_format(name, namebuf, sizeof namebuf);
2965                 dns_zone_log(zone, ISC_LOG_ERROR,
2966                              "No valid trust anchors for '%s'!", namebuf);
2967                 dns_zone_log(zone, ISC_LOG_ERROR,
2968                              "%d key(s) revoked, %d still pending",
2969                              revoked, pending);
2970                 dns_zone_log(zone, ISC_LOG_ERROR,
2971                              "All queries to '%s' will fail", namebuf);
2972                 fail_secure(zone, name);
2973         }
2974 }
2975
2976 static isc_result_t
2977 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
2978              dns_diff_t *diff)
2979 {
2980         dns_diff_t temp_diff;
2981         isc_result_t result;
2982
2983         /*
2984          * Create a singleton diff.
2985          */
2986         dns_diff_init(diff->mctx, &temp_diff);
2987         temp_diff.resign = diff->resign;
2988         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
2989
2990         /*
2991          * Apply it to the database.
2992          */
2993         result = dns_diff_apply(&temp_diff, db, ver);
2994         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
2995         if (result != ISC_R_SUCCESS) {
2996                 dns_difftuple_free(tuple);
2997                 return (result);
2998         }
2999
3000         /*
3001          * Merge it into the current pending journal entry.
3002          */
3003         dns_diff_appendminimal(diff, tuple);
3004
3005         /*
3006          * Do not clear temp_diff.
3007          */
3008         return (ISC_R_SUCCESS);
3009 }
3010
3011 static isc_result_t
3012 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3013               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3014               dns_rdata_t *rdata)
3015 {
3016         dns_difftuple_t *tuple = NULL;
3017         isc_result_t result;
3018         result = dns_difftuple_create(diff->mctx, op,
3019                                       name, ttl, rdata, &tuple);
3020         if (result != ISC_R_SUCCESS)
3021                 return (result);
3022         return (do_one_tuple(&tuple, db, ver, diff));
3023 }
3024
3025 static isc_result_t
3026 increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
3027                      dns_diff_t *diff, isc_mem_t *mctx) {
3028         dns_difftuple_t *deltuple = NULL;
3029         dns_difftuple_t *addtuple = NULL;
3030         isc_uint32_t serial;
3031         isc_result_t result;
3032
3033         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3034         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3035         addtuple->op = DNS_DIFFOP_ADD;
3036
3037         serial = dns_soa_getserial(&addtuple->rdata);
3038
3039         /* RFC1982 */
3040         serial = (serial + 1) & 0xFFFFFFFF;
3041         if (serial == 0)
3042                 serial = 1;
3043
3044         dns_soa_setserial(serial, &addtuple->rdata);
3045         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3046         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3047         result = ISC_R_SUCCESS;
3048
3049         failure:
3050         if (addtuple != NULL)
3051                 dns_difftuple_free(&addtuple);
3052         if (deltuple != NULL)
3053                 dns_difftuple_free(&deltuple);
3054         return (result);
3055 }
3056
3057 /*
3058  * Write all transactions in 'diff' to the zone journal file.
3059  */
3060 static isc_result_t
3061 zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) {
3062         const char me[] = "zone_journal";
3063         const char *journalfile;
3064         isc_result_t result = ISC_R_SUCCESS;
3065         dns_journal_t *journal = NULL;
3066
3067         ENTER;
3068         journalfile = dns_zone_getjournal(zone);
3069         if (journalfile != NULL) {
3070                 result = dns_journal_open(zone->mctx, journalfile,
3071                                           ISC_TRUE, &journal);
3072                 if (result != ISC_R_SUCCESS) {
3073                         dns_zone_log(zone, ISC_LOG_ERROR,
3074                                      "%s:dns_journal_open -> %s\n",
3075                                      caller, dns_result_totext(result));
3076                         return (result);
3077                 }
3078
3079                 result = dns_journal_write_transaction(journal, diff);
3080                 dns_journal_destroy(&journal);
3081                 if (result != ISC_R_SUCCESS) {
3082                         dns_zone_log(zone, ISC_LOG_ERROR,
3083                                      "%s:dns_journal_write_transaction -> %s\n",
3084                                      caller, dns_result_totext(result));
3085                         return (result);
3086                 }
3087         }
3088         return (result);
3089 }
3090
3091 /*
3092  * Create an SOA record for a newly-created zone
3093  */
3094 static isc_result_t
3095 add_soa(dns_zone_t *zone, dns_db_t *db) {
3096         isc_result_t result;
3097         dns_rdata_t rdata = DNS_RDATA_INIT;
3098         unsigned char buf[DNS_SOA_BUFFERSIZE];
3099         dns_dbversion_t *ver = NULL;
3100         dns_diff_t diff;
3101
3102         dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3103
3104         dns_diff_init(zone->mctx, &diff);
3105         result = dns_db_newversion(db, &ver);
3106         if (result != ISC_R_SUCCESS) {
3107                 dns_zone_log(zone, ISC_LOG_ERROR,
3108                              "add_soa:dns_db_newversion -> %s\n",
3109                              dns_result_totext(result));
3110                 goto failure;
3111         }
3112
3113         /* Build SOA record */
3114         result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3115                                     0, 0, 0, 0, 0, buf, &rdata);
3116         if (result != ISC_R_SUCCESS) {
3117                 dns_zone_log(zone, ISC_LOG_ERROR,
3118                              "add_soa:dns_soa_buildrdata -> %s\n",
3119                              dns_result_totext(result));
3120                 goto failure;
3121         }
3122
3123         result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3124                                &zone->origin, 0, &rdata);
3125
3126 failure:
3127         dns_diff_clear(&diff);
3128         if (ver != NULL)
3129                 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3130
3131         return (result);
3132 }
3133
3134 /*
3135  * Synchronize the set of initializing keys found in managed-keys {}
3136  * statements with the set of trust anchors found in the managed-keys.bind
3137  * zone.  If a domain is no longer named in managed-keys, delete all keys
3138  * from that domain from the key zone.  If a domain is mentioned in in
3139  * managed-keys but there are no references to it in the key zone, load
3140  * the key zone with the initializing key(s) for that domain.
3141  */
3142 static isc_result_t
3143 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3144         isc_result_t result = ISC_R_SUCCESS;
3145         isc_boolean_t changed = ISC_FALSE;
3146         isc_boolean_t commit = ISC_FALSE;
3147         dns_rbtnodechain_t chain;
3148         dns_fixedname_t fn;
3149         dns_name_t foundname, *origin;
3150         dns_keynode_t *keynode = NULL;
3151         dns_view_t *view = zone->view;
3152         dns_keytable_t *sr = NULL;
3153         dns_dbversion_t *ver = NULL;
3154         dns_diff_t diff;
3155         dns_rriterator_t rrit;
3156
3157         dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3158
3159         dns_name_init(&foundname, NULL);
3160         dns_fixedname_init(&fn);
3161         origin = dns_fixedname_name(&fn);
3162
3163         dns_diff_init(zone->mctx, &diff);
3164
3165         CHECK(dns_view_getsecroots(view, &sr));
3166
3167         result = dns_db_newversion(db, &ver);
3168         if (result != ISC_R_SUCCESS) {
3169                 dns_zone_log(zone, ISC_LOG_ERROR,
3170                              "sync_keyzone:dns_db_newversion -> %s\n",
3171                              dns_result_totext(result));
3172                 goto failure;
3173         }
3174
3175         /*
3176          * Walk the zone DB.  If we find any keys whose names are no longer
3177          * in managed-keys (or *are* in trusted-keys, meaning they are
3178          * permanent and not RFC5011-maintained), delete them from the
3179          * zone.  Otherwise call load_secroots(), which loads keys into
3180          * secroots as appropriate.
3181          */
3182         dns_rriterator_init(&rrit, db, ver, 0);
3183         for (result = dns_rriterator_first(&rrit);
3184              result == ISC_R_SUCCESS;
3185              result = dns_rriterator_nextrrset(&rrit)) {
3186                 dns_rdataset_t *rdataset;
3187                 dns_name_t *rrname = NULL;
3188                 isc_uint32_t ttl;
3189
3190                 dns_rriterator_current(&rrit, &rrname, &ttl,
3191                                        &rdataset, NULL);
3192                 if (!dns_rdataset_isassociated(rdataset)) {
3193                         dns_rriterator_destroy(&rrit);
3194                         goto failure;
3195                 }
3196
3197                 if (rdataset->type != dns_rdatatype_keydata)
3198                         continue;
3199
3200                 result = dns_keytable_find(sr, rrname, &keynode);
3201                 if ((result != ISC_R_SUCCESS &&
3202                      result != DNS_R_PARTIALMATCH) ||
3203                     dns_keynode_managed(keynode) == ISC_FALSE) {
3204                         CHECK(delete_keydata(db, ver, &diff,
3205                                              rrname, rdataset));
3206                         changed = ISC_TRUE;
3207                 } else {
3208                         load_secroots(zone, rrname, rdataset);
3209                 }
3210
3211                 if (keynode != NULL)
3212                         dns_keytable_detachkeynode(sr, &keynode);
3213         }
3214         dns_rriterator_destroy(&rrit);
3215
3216         /*
3217          * Now walk secroots to find any managed keys that aren't
3218          * in the zone.  If we find any, we add them to the zone.
3219          */
3220         RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3221         dns_rbtnodechain_init(&chain, zone->mctx);
3222         result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3223         if (result == ISC_R_NOTFOUND)
3224                 result = ISC_R_NOMORE;
3225         while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3226                 dns_rbtnode_t *rbtnode = NULL;
3227
3228                 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3229                 if (rbtnode->data == NULL)
3230                         goto skip;
3231
3232                 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3233                 if (dns_keynode_managed(keynode)) {
3234                         dns_fixedname_t fname;
3235                         dns_name_t *keyname;
3236                         dst_key_t *key;
3237
3238                         key = dns_keynode_key(keynode);
3239                         dns_fixedname_init(&fname);
3240
3241                         if (key == NULL)   /* fail_secure() was called. */
3242                                 goto skip;
3243
3244                         keyname = dst_key_name(key);
3245                         result = dns_db_find(db, keyname, ver,
3246                                              dns_rdatatype_keydata,
3247                                              DNS_DBFIND_NOWILD, 0, NULL,
3248                                              dns_fixedname_name(&fname),
3249                                              NULL, NULL);
3250                         if (result != ISC_R_SUCCESS)
3251                                 result = create_keydata(zone, db, ver, &diff,
3252                                                         sr, &keynode, &changed);
3253                         if (result != ISC_R_SUCCESS)
3254                                 break;
3255                 }
3256   skip:
3257                 result = dns_rbtnodechain_next(&chain, &foundname, origin);
3258                 if (keynode != NULL)
3259                         dns_keytable_detachkeynode(sr, &keynode);
3260         }
3261         RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3262
3263         if (result == ISC_R_NOMORE)
3264                 result = ISC_R_SUCCESS;
3265
3266         if (changed) {
3267                 /* Write changes to journal file. */
3268                 CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
3269                 CHECK(zone_journal(zone, &diff, "sync_keyzone"));
3270
3271                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3272                 zone_needdump(zone, 30);
3273                 commit = ISC_TRUE;
3274         }
3275
3276  failure:
3277         if (keynode != NULL)
3278                 dns_keytable_detachkeynode(sr, &keynode);
3279         if (sr != NULL)
3280                 dns_keytable_detach(&sr);
3281         if (ver != NULL)
3282                 dns_db_closeversion(db, &ver, commit);
3283         dns_diff_clear(&diff);
3284
3285         return (result);
3286 }
3287
3288 static isc_result_t
3289 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3290               isc_result_t result)
3291 {
3292         unsigned int soacount = 0;
3293         unsigned int nscount = 0;
3294         unsigned int errors = 0;
3295         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3296         isc_time_t now;
3297         isc_boolean_t needdump = ISC_FALSE;
3298         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3299         isc_boolean_t nomaster = ISC_FALSE;
3300         unsigned int options;
3301
3302         TIME_NOW(&now);
3303
3304         /*
3305          * Initiate zone transfer?  We may need a error code that
3306          * indicates that the "permanent" form does not exist.
3307          * XXX better error feedback to log.
3308          */
3309         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3310                 if (zone->type == dns_zone_slave ||
3311                     zone->type == dns_zone_stub) {
3312                         if (result == ISC_R_FILENOTFOUND)
3313                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3314                                              "no master file");
3315                         else if (result != DNS_R_NOMASTERFILE)
3316                                 dns_zone_log(zone, ISC_LOG_ERROR,
3317                                              "loading from master file %s "
3318                                              "failed: %s",
3319                                              zone->masterfile,
3320                                              dns_result_totext(result));
3321                 } else {
3322                         dns_zone_log(zone, ISC_LOG_ERROR,
3323                                      "loading from master file %s failed: %s",
3324                                      zone->masterfile,
3325                                      dns_result_totext(result));
3326                         nomaster = ISC_TRUE;
3327                 }
3328
3329                 if (zone->type != dns_zone_key)
3330                         goto cleanup;
3331         }
3332
3333         dns_zone_log(zone, ISC_LOG_DEBUG(2),
3334                      "number of nodes in database: %u",
3335                      dns_db_nodecount(db));
3336
3337         if (result == DNS_R_SEENINCLUDE)
3338                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3339         else
3340                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3341
3342         /*
3343          * If there's no master file for a key zone, then the zone is new:
3344          * create an SOA record.  (We do this now, instead of later, so that
3345          * if there happens to be a journal file, we can roll forward from
3346          * a sane starting point.)
3347          */
3348         if (nomaster && zone->type == dns_zone_key) {
3349                 result = add_soa(zone, db);
3350                 if (result != ISC_R_SUCCESS)
3351                         goto cleanup;
3352         }
3353
3354         /*
3355          * Apply update log, if any, on initial load.
3356          */
3357         if (zone->journal != NULL &&
3358             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3359             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3360         {
3361                 if (zone->type == dns_zone_master &&
3362                     (zone->update_acl != NULL || zone->ssutable != NULL))
3363                         options = DNS_JOURNALOPT_RESIGN;
3364                 else
3365                         options = 0;
3366                 result = dns_journal_rollforward2(zone->mctx, db, options,
3367                                                   zone->sigresigninginterval,
3368                                                   zone->journal);
3369                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3370                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3371                     result != ISC_R_RANGE) {
3372                         dns_zone_log(zone, ISC_LOG_ERROR,
3373                                      "journal rollforward failed: %s",
3374                                      dns_result_totext(result));
3375                         goto cleanup;
3376                 }
3377                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3378                         dns_zone_log(zone, ISC_LOG_ERROR,
3379                                      "journal rollforward failed: "
3380                                      "journal out of sync with zone");
3381                         goto cleanup;
3382                 }
3383                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3384                              "journal rollforward completed "
3385                              "successfully: %s",
3386                              dns_result_totext(result));
3387                 if (result == ISC_R_SUCCESS)
3388                         needdump = ISC_TRUE;
3389         }
3390
3391         zone->loadtime = loadtime;
3392
3393         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
3394         /*
3395          * Obtain ns, soa and cname counts for top of zone.
3396          */
3397         INSIST(db != NULL);
3398         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3399                                   &refresh, &retry, &expire, &minimum,
3400                                   &errors);
3401         if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3402                 dns_zone_log(zone, ISC_LOG_ERROR,
3403                              "could not find NS and/or SOA records");
3404         }
3405
3406         /*
3407          * Master / Slave / Stub zones require both NS and SOA records at
3408          * the top of the zone.
3409          */
3410
3411         switch (zone->type) {
3412         case dns_zone_dlz:
3413         case dns_zone_master:
3414         case dns_zone_slave:
3415         case dns_zone_stub:
3416                 if (soacount != 1) {
3417                         dns_zone_log(zone, ISC_LOG_ERROR,
3418                                      "has %d SOA records", soacount);
3419                         result = DNS_R_BADZONE;
3420                 }
3421                 if (nscount == 0) {
3422                         dns_zone_log(zone, ISC_LOG_ERROR,
3423                                      "has no NS records");
3424                         result = DNS_R_BADZONE;
3425                 }
3426                 if (result != ISC_R_SUCCESS)
3427                         goto cleanup;
3428                 if (zone->type == dns_zone_master && errors != 0) {
3429                         result = DNS_R_BADZONE;
3430                         goto cleanup;
3431                 }
3432                 if (zone->type != dns_zone_stub) {
3433                         result = check_nsec3param(zone, db);
3434                         if (result != ISC_R_SUCCESS)
3435                                 goto cleanup;
3436                 }
3437                 if (zone->type == dns_zone_master &&
3438                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
3439                     !integrity_checks(zone, db)) {
3440                         result = DNS_R_BADZONE;
3441                         goto cleanup;
3442                 }
3443
3444                 if (zone->type == dns_zone_master &&
3445                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
3446                     !zone_check_dup(zone, db)) {
3447                         result = DNS_R_BADZONE;
3448                         goto cleanup;
3449                 }
3450
3451                 if (zone->db != NULL) {
3452                         /*
3453                          * This is checked in zone_replacedb() for slave zones
3454                          * as they don't reload from disk.
3455                          */
3456                         result = zone_get_from_db(zone, zone->db, NULL, NULL,
3457                                                   &oldserial, NULL, NULL, NULL,
3458                                                   NULL, NULL);
3459                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3460                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
3461                             !isc_serial_gt(serial, oldserial)) {
3462                                 isc_uint32_t serialmin, serialmax;
3463
3464                                 INSIST(zone->type == dns_zone_master);
3465
3466                                 serialmin = (oldserial + 1) & 0xffffffffU;
3467                                 serialmax = (oldserial + 0x7fffffffU) &
3468                                              0xffffffffU;
3469                                 dns_zone_log(zone, ISC_LOG_ERROR,
3470                                              "ixfr-from-differences: "
3471                                              "new serial (%u) out of range "
3472                                              "[%u - %u]", serial, serialmin,
3473                                              serialmax);
3474                                 result = DNS_R_BADZONE;
3475                                 goto cleanup;
3476                         } else if (!isc_serial_ge(serial, oldserial))
3477                                 dns_zone_log(zone, ISC_LOG_ERROR,
3478                                              "zone serial (%u/%u) has gone "
3479                                              "backwards", serial, oldserial);
3480                         else if (serial == oldserial && !hasinclude &&
3481                                  strcmp(zone->db_argv[0], "_builtin") != 0)
3482                                 dns_zone_log(zone, ISC_LOG_ERROR,
3483                                              "zone serial (%u) unchanged. "
3484                                              "zone may fail to transfer "
3485                                              "to slaves.", serial);
3486                 }
3487
3488                 if (zone->type == dns_zone_master &&
3489                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
3490                     zone->sigresigninginterval < (3 * refresh) &&
3491                     dns_db_issecure(db))
3492                 {
3493                         dns_zone_log(zone, ISC_LOG_WARNING,
3494                                      "sig-re-signing-interval less than "
3495                                      "3 * refresh.");
3496                 }
3497
3498                 zone->refresh = RANGE(refresh,
3499                                       zone->minrefresh, zone->maxrefresh);
3500                 zone->retry = RANGE(retry,
3501                                     zone->minretry, zone->maxretry);
3502                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
3503                                      DNS_MAX_EXPIRE);
3504                 zone->minimum = minimum;
3505                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3506
3507                 if (zone->type == dns_zone_slave ||
3508                     zone->type == dns_zone_stub) {
3509                         isc_time_t t;
3510                         isc_uint32_t delay;
3511
3512                         result = isc_file_getmodtime(zone->journal, &t);
3513                         if (result != ISC_R_SUCCESS)
3514                                 result = isc_file_getmodtime(zone->masterfile,
3515                                                              &t);
3516                         if (result == ISC_R_SUCCESS)
3517                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
3518                                                   &zone->expiretime);
3519                         else
3520                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
3521                                                   &zone->expiretime);
3522
3523                         delay = isc_random_jitter(zone->retry,
3524                                                   (zone->retry * 3) / 4);
3525                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
3526                         if (isc_time_compare(&zone->refreshtime,
3527                                              &zone->expiretime) >= 0)
3528                                 zone->refreshtime = now;
3529                 }
3530                 break;
3531
3532         case dns_zone_key:
3533                 result = sync_keyzone(zone, db);
3534                 if (result != ISC_R_SUCCESS)
3535                         goto cleanup;
3536                 break;
3537
3538         default:
3539                 UNEXPECTED_ERROR(__FILE__, __LINE__,
3540                                  "unexpected zone type %d", zone->type);
3541                 result = ISC_R_UNEXPECTED;
3542                 goto cleanup;
3543         }
3544
3545         /*
3546          * Check for weak DNSKEY's.
3547          */
3548         if (zone->type == dns_zone_master)
3549                 zone_check_dnskeys(zone, db);
3550
3551         /*
3552          * Schedule DNSSEC key refresh.
3553          */
3554         if (zone->type == dns_zone_master &&
3555             DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
3556                 zone->refreshkeytime = now;
3557
3558 #if 0
3559         /* destroy notification example. */
3560         {
3561                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
3562                                                     DNS_EVENT_DBDESTROYED,
3563                                                     dns_zonemgr_dbdestroyed,
3564                                                     zone,
3565                                                     sizeof(isc_event_t));
3566                 dns_db_ondestroy(db, zone->task, &e);
3567         }
3568 #endif
3569
3570         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3571         if (zone->db != NULL) {
3572                 result = zone_replacedb(zone, db, ISC_FALSE);
3573                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3574                 if (result != ISC_R_SUCCESS)
3575                         goto cleanup;
3576         } else {
3577                 zone_attachdb(zone, db);
3578                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3579                 DNS_ZONE_SETFLAG(zone,
3580                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
3581         }
3582
3583         result = ISC_R_SUCCESS;
3584
3585         if (needdump) {
3586                 if (zone->type == dns_zone_key)
3587                         zone_needdump(zone, 30);
3588                 else
3589                         zone_needdump(zone, DNS_DUMP_DELAY);
3590         }
3591
3592         if (zone->task != NULL) {
3593                 if (zone->type == dns_zone_master) {
3594                         set_resigntime(zone);
3595                         resume_signingwithkey(zone);
3596                         resume_addnsec3chain(zone);
3597                 }
3598
3599                 if (zone->type == dns_zone_master &&
3600                     zone_isdynamic(zone) &&
3601                     dns_db_issecure(db)) {
3602                         dns_name_t *name;
3603                         dns_fixedname_t fixed;
3604                         dns_rdataset_t next;
3605
3606                         dns_rdataset_init(&next);
3607                         dns_fixedname_init(&fixed);
3608                         name = dns_fixedname_name(&fixed);
3609
3610                         result = dns_db_getsigningtime(db, &next, name);
3611                         if (result == ISC_R_SUCCESS) {
3612                                 isc_stdtime_t timenow;
3613                                 char namebuf[DNS_NAME_FORMATSIZE];
3614                                 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3615
3616                                 isc_stdtime_get(&timenow);
3617                                 dns_name_format(name, namebuf, sizeof(namebuf));
3618                                 dns_rdatatype_format(next.covers,
3619                                                      typebuf, sizeof(typebuf));
3620                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
3621                                              "next resign: %s/%s in %d seconds",
3622                                              namebuf, typebuf,
3623                                              next.resign - timenow);
3624                                 dns_rdataset_disassociate(&next);
3625                         } else
3626                                 dns_zone_log(zone, ISC_LOG_WARNING,
3627                                              "signed dynamic zone has no "
3628                                              "resign event scheduled");
3629                 }
3630
3631                 zone_settimer(zone, &now);
3632         }
3633
3634         if (! dns_db_ispersistent(db))
3635                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
3636                              dns_db_issecure(db) ? " (DNSSEC signed)" : "");
3637
3638         return (result);
3639
3640  cleanup:
3641         if (zone->type == dns_zone_slave ||
3642             zone->type == dns_zone_stub ||
3643             zone->type == dns_zone_key) {
3644                 if (zone->journal != NULL)
3645                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
3646                 if (zone->masterfile != NULL)
3647                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
3648
3649                 /* Mark the zone for immediate refresh. */
3650                 zone->refreshtime = now;
3651                 if (zone->task != NULL)
3652                         zone_settimer(zone, &now);
3653                 result = ISC_R_SUCCESS;
3654         } else if (zone->type == dns_zone_master)
3655                 dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors.");
3656         return (result);
3657 }
3658
3659 static isc_boolean_t
3660 exit_check(dns_zone_t *zone) {
3661
3662         REQUIRE(LOCKED_ZONE(zone));
3663
3664         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
3665             zone->irefs == 0)
3666         {
3667                 /*
3668                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
3669                  */
3670                 INSIST(isc_refcount_current(&zone->erefs) == 0);
3671                 return (ISC_TRUE);
3672         }
3673         return (ISC_FALSE);
3674 }
3675
3676 static isc_boolean_t
3677 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
3678               dns_name_t *name, isc_boolean_t logit)
3679 {
3680         isc_result_t result;
3681         char namebuf[DNS_NAME_FORMATSIZE];
3682         char altbuf[DNS_NAME_FORMATSIZE];
3683         dns_fixedname_t fixed;
3684         dns_name_t *foundname;
3685         int level;
3686
3687         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
3688                 return (ISC_TRUE);
3689
3690         if (zone->type == dns_zone_master)
3691                 level = ISC_LOG_ERROR;
3692         else
3693                 level = ISC_LOG_WARNING;
3694
3695         dns_fixedname_init(&fixed);
3696         foundname = dns_fixedname_name(&fixed);
3697
3698         result = dns_db_find(db, name, version, dns_rdatatype_a,
3699                              0, 0, NULL, foundname, NULL, NULL);
3700         if (result == ISC_R_SUCCESS)
3701                 return (ISC_TRUE);
3702
3703         if (result == DNS_R_NXRRSET) {
3704                 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
3705                                      0, 0, NULL, foundname, NULL, NULL);
3706                 if (result == ISC_R_SUCCESS)
3707                         return (ISC_TRUE);
3708         }
3709
3710         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3711             result == DNS_R_EMPTYNAME) {
3712                 if (logit) {
3713                         dns_name_format(name, namebuf, sizeof namebuf);
3714                         dns_zone_log(zone, level, "NS '%s' has no address "
3715                                      "records (A or AAAA)", namebuf);
3716                 }
3717                 return (ISC_FALSE);
3718         }
3719
3720         if (result == DNS_R_CNAME) {
3721                 if (logit) {
3722                         dns_name_format(name, namebuf, sizeof namebuf);
3723                         dns_zone_log(zone, level, "NS '%s' is a CNAME "
3724                                      "(illegal)", namebuf);
3725                 }
3726                 return (ISC_FALSE);
3727         }
3728
3729         if (result == DNS_R_DNAME) {
3730                 if (logit) {
3731                         dns_name_format(name, namebuf, sizeof namebuf);
3732                         dns_name_format(foundname, altbuf, sizeof altbuf);
3733                         dns_zone_log(zone, level, "NS '%s' is below a DNAME "
3734                                      "'%s' (illegal)", namebuf, altbuf);
3735                 }
3736                 return (ISC_FALSE);
3737         }
3738
3739         return (ISC_TRUE);
3740 }
3741
3742 static isc_result_t
3743 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
3744                  dns_dbversion_t *version, unsigned int *nscount,
3745                  unsigned int *errors, isc_boolean_t logit)
3746 {
3747         isc_result_t result;
3748         unsigned int count = 0;
3749         unsigned int ecount = 0;
3750         dns_rdataset_t rdataset;
3751         dns_rdata_t rdata;
3752         dns_rdata_ns_t ns;
3753
3754         dns_rdataset_init(&rdataset);
3755         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
3756                                      dns_rdatatype_none, 0, &rdataset, NULL);
3757         if (result == ISC_R_NOTFOUND) {
3758                 INSIST(!dns_rdataset_isassociated(&rdataset));
3759                 goto success;
3760         }
3761         if (result != ISC_R_SUCCESS) {
3762                 INSIST(!dns_rdataset_isassociated(&rdataset));
3763                 goto invalidate_rdataset;
3764         }
3765
3766         result = dns_rdataset_first(&rdataset);
3767         while (result == ISC_R_SUCCESS) {
3768                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
3769                     (zone->type == dns_zone_master ||
3770                      zone->type == dns_zone_slave)) {
3771                         dns_rdata_init(&rdata);
3772                         dns_rdataset_current(&rdataset, &rdata);
3773                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
3774                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3775                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
3776                             !zone_check_ns(zone, db, version, &ns.name, logit))
3777                                 ecount++;
3778                 }
3779                 count++;
3780                 result = dns_rdataset_next(&rdataset);
3781         }
3782         dns_rdataset_disassociate(&rdataset);
3783
3784  success:
3785         if (nscount != NULL)
3786                 *nscount = count;
3787         if (errors != NULL)
3788                 *errors = ecount;
3789
3790         result = ISC_R_SUCCESS;
3791
3792  invalidate_rdataset:
3793         dns_rdataset_invalidate(&rdataset);
3794
3795         return (result);
3796 }
3797
3798 static isc_result_t
3799 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
3800                  unsigned int *soacount,
3801                  isc_uint32_t *serial, isc_uint32_t *refresh,
3802                  isc_uint32_t *retry, isc_uint32_t *expire,
3803                  isc_uint32_t *minimum)
3804 {
3805         isc_result_t result;
3806         unsigned int count;
3807         dns_rdataset_t rdataset;
3808         dns_rdata_t rdata = DNS_RDATA_INIT;
3809         dns_rdata_soa_t soa;
3810
3811         dns_rdataset_init(&rdataset);
3812         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
3813                                      dns_rdatatype_none, 0, &rdataset, NULL);
3814         if (result == ISC_R_NOTFOUND) {
3815                 INSIST(!dns_rdataset_isassociated(&rdataset));
3816                 if (soacount != NULL)
3817                         *soacount = 0;
3818                 if (serial != NULL)
3819                         *serial = 0;
3820                 if (refresh != NULL)
3821                         *refresh = 0;
3822                 if (retry != NULL)
3823                         *retry = 0;
3824                 if (expire != NULL)
3825                         *expire = 0;
3826                 if (minimum != NULL)
3827                         *minimum = 0;
3828                 result = ISC_R_SUCCESS;
3829                 goto invalidate_rdataset;
3830         }
3831         if (result != ISC_R_SUCCESS) {
3832                 INSIST(!dns_rdataset_isassociated(&rdataset));
3833                 goto invalidate_rdataset;
3834         }
3835
3836         count = 0;
3837         result = dns_rdataset_first(&rdataset);
3838         while (result == ISC_R_SUCCESS) {
3839                 dns_rdata_init(&rdata);
3840                 dns_rdataset_current(&rdataset, &rdata);
3841                 count++;
3842                 if (count == 1) {
3843                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
3844                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
3845                 }
3846
3847                 result = dns_rdataset_next(&rdataset);
3848                 dns_rdata_reset(&rdata);
3849         }
3850         dns_rdataset_disassociate(&rdataset);
3851
3852         if (soacount != NULL)
3853                 *soacount = count;
3854
3855         if (count > 0) {
3856                 if (serial != NULL)
3857                         *serial = soa.serial;
3858                 if (refresh != NULL)
3859                         *refresh = soa.refresh;
3860                 if (retry != NULL)
3861                         *retry = soa.retry;
3862                 if (expire != NULL)
3863                         *expire = soa.expire;
3864                 if (minimum != NULL)
3865                         *minimum = soa.minimum;
3866         }
3867
3868         result = ISC_R_SUCCESS;
3869
3870  invalidate_rdataset:
3871         dns_rdataset_invalidate(&rdataset);
3872
3873         return (result);
3874 }
3875
3876 /*
3877  * zone must be locked.
3878  */
3879 static isc_result_t
3880 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
3881                  unsigned int *soacount, isc_uint32_t *serial,
3882                  isc_uint32_t *refresh, isc_uint32_t *retry,
3883                  isc_uint32_t *expire, isc_uint32_t *minimum,
3884                  unsigned int *errors)
3885 {
3886         isc_result_t result;
3887         isc_result_t answer = ISC_R_SUCCESS;
3888         dns_dbversion_t *version = NULL;
3889         dns_dbnode_t *node;
3890
3891         REQUIRE(db != NULL);
3892         REQUIRE(zone != NULL);
3893
3894         dns_db_currentversion(db, &version);
3895
3896         node = NULL;
3897         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3898         if (result != ISC_R_SUCCESS) {
3899                 answer = result;
3900                 goto closeversion;
3901         }
3902
3903         if (nscount != NULL || errors != NULL) {
3904                 result = zone_count_ns_rr(zone, db, node, version,
3905                                           nscount, errors, ISC_TRUE);
3906                 if (result != ISC_R_SUCCESS)
3907                         answer = result;
3908         }
3909
3910         if (soacount != NULL || serial != NULL || refresh != NULL
3911             || retry != NULL || expire != NULL || minimum != NULL) {
3912                 result = zone_load_soa_rr(db, node, version, soacount,
3913                                           serial, refresh, retry, expire,
3914                                           minimum);
3915                 if (result != ISC_R_SUCCESS)
3916                         answer = result;
3917         }
3918
3919         dns_db_detachnode(db, &node);
3920  closeversion:
3921         dns_db_closeversion(db, &version, ISC_FALSE);
3922
3923         return (answer);
3924 }
3925
3926 void
3927 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
3928         REQUIRE(DNS_ZONE_VALID(source));
3929         REQUIRE(target != NULL && *target == NULL);
3930         isc_refcount_increment(&source->erefs, NULL);
3931         *target = source;
3932 }
3933
3934 void
3935 dns_zone_detach(dns_zone_t **zonep) {
3936         dns_zone_t *zone;
3937         unsigned int refs;
3938         isc_boolean_t free_now = ISC_FALSE;
3939
3940         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3941
3942         zone = *zonep;
3943
3944         isc_refcount_decrement(&zone->erefs, &refs);
3945
3946         if (refs == 0) {
3947                 LOCK_ZONE(zone);
3948                 /*
3949                  * We just detached the last external reference.
3950                  */
3951                 if (zone->task != NULL) {
3952                         /*
3953                          * This zone is being managed.  Post
3954                          * its control event and let it clean
3955                          * up synchronously in the context of
3956                          * its task.
3957                          */
3958                         isc_event_t *ev = &zone->ctlevent;
3959                         isc_task_send(zone->task, &ev);
3960                 } else {
3961                         /*
3962                          * This zone is not being managed; it has
3963                          * no task and can have no outstanding
3964                          * events.  Free it immediately.
3965                          */
3966                         /*
3967                          * Unmanaged zones should not have non-null views;
3968                          * we have no way of detaching from the view here
3969                          * without causing deadlock because this code is called
3970                          * with the view already locked.
3971                          */
3972                         INSIST(zone->view == NULL);
3973                         free_now = ISC_TRUE;
3974                 }
3975                 UNLOCK_ZONE(zone);
3976         }
3977         *zonep = NULL;
3978         if (free_now)
3979                 zone_free(zone);
3980 }
3981
3982 void
3983 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3984         REQUIRE(DNS_ZONE_VALID(source));
3985         REQUIRE(target != NULL && *target == NULL);
3986         LOCK_ZONE(source);
3987         zone_iattach(source, target);
3988         UNLOCK_ZONE(source);
3989 }
3990
3991 static void
3992 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3993
3994         /*
3995          * 'source' locked by caller.
3996          */
3997         REQUIRE(LOCKED_ZONE(source));
3998         REQUIRE(DNS_ZONE_VALID(source));
3999         REQUIRE(target != NULL && *target == NULL);
4000         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
4001         source->irefs++;
4002         INSIST(source->irefs != 0);
4003         *target = source;
4004 }
4005
4006 static void
4007 zone_idetach(dns_zone_t **zonep) {
4008         dns_zone_t *zone;
4009
4010         /*
4011          * 'zone' locked by caller.
4012          */
4013         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4014         zone = *zonep;
4015         REQUIRE(LOCKED_ZONE(*zonep));
4016         *zonep = NULL;
4017
4018         INSIST(zone->irefs > 0);
4019         zone->irefs--;
4020         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4021 }
4022
4023 void
4024 dns_zone_idetach(dns_zone_t **zonep) {
4025         dns_zone_t *zone;
4026         isc_boolean_t free_needed;
4027
4028         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4029         zone = *zonep;
4030         *zonep = NULL;
4031
4032         LOCK_ZONE(zone);
4033         INSIST(zone->irefs > 0);
4034         zone->irefs--;
4035         free_needed = exit_check(zone);
4036         UNLOCK_ZONE(zone);
4037         if (free_needed)
4038                 zone_free(zone);
4039 }
4040
4041 isc_mem_t *
4042 dns_zone_getmctx(dns_zone_t *zone) {
4043         REQUIRE(DNS_ZONE_VALID(zone));
4044
4045         return (zone->mctx);
4046 }
4047
4048 dns_zonemgr_t *
4049 dns_zone_getmgr(dns_zone_t *zone) {
4050         REQUIRE(DNS_ZONE_VALID(zone));
4051
4052         return (zone->zmgr);
4053 }
4054
4055 void
4056 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4057         REQUIRE(DNS_ZONE_VALID(zone));
4058
4059         LOCK_ZONE(zone);
4060         if (value)
4061                 DNS_ZONE_SETFLAG(zone, flags);
4062         else
4063                 DNS_ZONE_CLRFLAG(zone, flags);
4064         UNLOCK_ZONE(zone);
4065 }
4066
4067 void
4068 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4069 {
4070         REQUIRE(DNS_ZONE_VALID(zone));
4071
4072         LOCK_ZONE(zone);
4073         if (value)
4074                 zone->options |= option;
4075         else
4076                 zone->options &= ~option;
4077         UNLOCK_ZONE(zone);
4078 }
4079
4080 unsigned int
4081 dns_zone_getoptions(dns_zone_t *zone) {
4082
4083         REQUIRE(DNS_ZONE_VALID(zone));
4084
4085         return (zone->options);
4086 }
4087
4088 void
4089 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4090 {
4091         REQUIRE(DNS_ZONE_VALID(zone));
4092
4093         LOCK_ZONE(zone);
4094         if (value)
4095                 zone->keyopts |= keyopt;
4096         else
4097                 zone->keyopts &= ~keyopt;
4098         UNLOCK_ZONE(zone);
4099 }
4100
4101 unsigned int
4102 dns_zone_getkeyopts(dns_zone_t *zone) {
4103
4104         REQUIRE(DNS_ZONE_VALID(zone));
4105
4106         return (zone->keyopts);
4107 }
4108
4109 isc_result_t
4110 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4111         REQUIRE(DNS_ZONE_VALID(zone));
4112
4113         LOCK_ZONE(zone);
4114         zone->xfrsource4 = *xfrsource;
4115         UNLOCK_ZONE(zone);
4116
4117         return (ISC_R_SUCCESS);
4118 }
4119
4120 isc_sockaddr_t *
4121 dns_zone_getxfrsource4(dns_zone_t *zone) {
4122         REQUIRE(DNS_ZONE_VALID(zone));
4123         return (&zone->xfrsource4);
4124 }
4125
4126 isc_result_t
4127 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4128         REQUIRE(DNS_ZONE_VALID(zone));
4129
4130         LOCK_ZONE(zone);
4131         zone->xfrsource6 = *xfrsource;
4132         UNLOCK_ZONE(zone);
4133
4134         return (ISC_R_SUCCESS);
4135 }
4136
4137 isc_sockaddr_t *
4138 dns_zone_getxfrsource6(dns_zone_t *zone) {
4139         REQUIRE(DNS_ZONE_VALID(zone));
4140         return (&zone->xfrsource6);
4141 }
4142
4143 isc_result_t
4144 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4145                           const isc_sockaddr_t *altxfrsource)
4146 {
4147         REQUIRE(DNS_ZONE_VALID(zone));
4148
4149         LOCK_ZONE(zone);
4150         zone->altxfrsource4 = *altxfrsource;
4151         UNLOCK_ZONE(zone);
4152
4153         return (ISC_R_SUCCESS);
4154 }
4155
4156 isc_sockaddr_t *
4157 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4158         REQUIRE(DNS_ZONE_VALID(zone));
4159         return (&zone->altxfrsource4);
4160 }
4161
4162 isc_result_t
4163 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4164                           const isc_sockaddr_t *altxfrsource)
4165 {
4166         REQUIRE(DNS_ZONE_VALID(zone));
4167
4168         LOCK_ZONE(zone);
4169         zone->altxfrsource6 = *altxfrsource;
4170         UNLOCK_ZONE(zone);
4171
4172         return (ISC_R_SUCCESS);
4173 }
4174
4175 isc_sockaddr_t *
4176 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4177         REQUIRE(DNS_ZONE_VALID(zone));
4178         return (&zone->altxfrsource6);
4179 }
4180
4181 isc_result_t
4182 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4183         REQUIRE(DNS_ZONE_VALID(zone));
4184
4185         LOCK_ZONE(zone);
4186         zone->notifysrc4 = *notifysrc;
4187         UNLOCK_ZONE(zone);
4188
4189         return (ISC_R_SUCCESS);
4190 }
4191
4192 isc_sockaddr_t *
4193 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4194         REQUIRE(DNS_ZONE_VALID(zone));
4195         return (&zone->notifysrc4);
4196 }
4197
4198 isc_result_t
4199 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4200         REQUIRE(DNS_ZONE_VALID(zone));
4201
4202         LOCK_ZONE(zone);
4203         zone->notifysrc6 = *notifysrc;
4204         UNLOCK_ZONE(zone);
4205
4206         return (ISC_R_SUCCESS);
4207 }
4208
4209 isc_sockaddr_t *
4210 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4211         REQUIRE(DNS_ZONE_VALID(zone));
4212         return (&zone->notifysrc6);
4213 }
4214
4215 isc_result_t
4216 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
4217                        isc_uint32_t count)
4218 {
4219         isc_sockaddr_t *new;
4220
4221         REQUIRE(DNS_ZONE_VALID(zone));
4222         REQUIRE(count == 0 || notify != NULL);
4223
4224         LOCK_ZONE(zone);
4225         if (zone->notify != NULL) {
4226                 isc_mem_put(zone->mctx, zone->notify,
4227                             zone->notifycnt * sizeof(*new));
4228                 zone->notify = NULL;
4229                 zone->notifycnt = 0;
4230         }
4231         if (count != 0) {
4232                 new = isc_mem_get(zone->mctx, count * sizeof(*new));
4233                 if (new == NULL) {
4234                         UNLOCK_ZONE(zone);
4235                         return (ISC_R_NOMEMORY);
4236                 }
4237                 memcpy(new, notify, count * sizeof(*new));
4238                 zone->notify = new;
4239                 zone->notifycnt = count;
4240         }
4241         UNLOCK_ZONE(zone);
4242         return (ISC_R_SUCCESS);
4243 }
4244
4245 isc_result_t
4246 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
4247                     isc_uint32_t count)
4248 {
4249         isc_result_t result;
4250
4251         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
4252         return (result);
4253 }
4254
4255 static isc_boolean_t
4256 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4257              isc_uint32_t count)
4258 {
4259         unsigned int i;
4260
4261         for (i = 0; i < count; i++)
4262                 if (!isc_sockaddr_equal(&old[i], &new[i]))
4263                         return (ISC_FALSE);
4264         return (ISC_TRUE);
4265 }
4266
4267 static isc_boolean_t
4268 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4269         unsigned int i;
4270
4271         if (old == NULL && new == NULL)
4272                 return (ISC_TRUE);
4273         if (old == NULL || new == NULL)
4274                 return (ISC_FALSE);
4275
4276         for (i = 0; i < count; i++) {
4277                 if (old[i] == NULL && new[i] == NULL)
4278                         continue;
4279                 if (old[i] == NULL || new[i] == NULL ||
4280                      !dns_name_equal(old[i], new[i]))
4281                         return (ISC_FALSE);
4282         }
4283         return (ISC_TRUE);
4284 }
4285
4286 isc_result_t
4287 dns_zone_setmasterswithkeys(dns_zone_t *zone,
4288                             const isc_sockaddr_t *masters,
4289                             dns_name_t **keynames,
4290                             isc_uint32_t count)
4291 {
4292         isc_sockaddr_t *new;
4293         isc_result_t result = ISC_R_SUCCESS;
4294         dns_name_t **newname;
4295         isc_boolean_t *newok;
4296         unsigned int i;
4297
4298         REQUIRE(DNS_ZONE_VALID(zone));
4299         REQUIRE(count == 0 || masters != NULL);
4300         if (keynames != NULL) {
4301                 REQUIRE(count != 0);
4302         }
4303
4304         LOCK_ZONE(zone);
4305         /*
4306          * The refresh code assumes that 'masters' wouldn't change under it.
4307          * If it will change then kill off any current refresh in progress
4308          * and update the masters info.  If it won't change then we can just
4309          * unlock and exit.
4310          */
4311         if (count != zone->masterscnt ||
4312             !same_masters(zone->masters, masters, count) ||
4313             !same_keynames(zone->masterkeynames, keynames, count)) {
4314                 if (zone->request != NULL)
4315                         dns_request_cancel(zone->request);
4316         } else
4317                 goto unlock;
4318         if (zone->masters != NULL) {
4319                 isc_mem_put(zone->mctx, zone->masters,
4320                             zone->masterscnt * sizeof(*new));
4321                 zone->masters = NULL;
4322         }
4323         if (zone->masterkeynames != NULL) {
4324                 for (i = 0; i < zone->masterscnt; i++) {
4325                         if (zone->masterkeynames[i] != NULL) {
4326                                 dns_name_free(zone->masterkeynames[i],
4327                                               zone->mctx);
4328                                 isc_mem_put(zone->mctx,
4329                                             zone->masterkeynames[i],
4330                                             sizeof(dns_name_t));
4331                                 zone->masterkeynames[i] = NULL;
4332                         }
4333                 }
4334                 isc_mem_put(zone->mctx, zone->masterkeynames,
4335                             zone->masterscnt * sizeof(dns_name_t *));
4336                 zone->masterkeynames = NULL;
4337         }
4338         if (zone->mastersok != NULL) {
4339                 isc_mem_put(zone->mctx, zone->mastersok,
4340                             zone->masterscnt * sizeof(isc_boolean_t));
4341                 zone->mastersok = NULL;
4342         }
4343         zone->masterscnt = 0;
4344         /*
4345          * If count == 0, don't allocate any space for masters, mastersok or
4346          * keynames so internally, those pointers are NULL if count == 0
4347          */
4348         if (count == 0)
4349                 goto unlock;
4350
4351         /*
4352          * masters must contain count elements!
4353          */
4354         new = isc_mem_get(zone->mctx, count * sizeof(*new));
4355         if (new == NULL) {
4356                 result = ISC_R_NOMEMORY;
4357                 goto unlock;
4358         }
4359         memcpy(new, masters, count * sizeof(*new));
4360
4361         /*
4362          * Similarly for mastersok.
4363          */
4364         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
4365         if (newok == NULL) {
4366                 result = ISC_R_NOMEMORY;
4367                 isc_mem_put(zone->mctx, new, count * sizeof(*new));
4368                 goto unlock;
4369         };
4370         for (i = 0; i < count; i++)
4371                 newok[i] = ISC_FALSE;
4372
4373         /*
4374          * if keynames is non-NULL, it must contain count elements!
4375          */
4376         newname = NULL;
4377         if (keynames != NULL) {
4378                 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
4379                 if (newname == NULL) {
4380                         result = ISC_R_NOMEMORY;
4381                         isc_mem_put(zone->mctx, new, count * sizeof(*new));
4382                         isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
4383                         goto unlock;
4384                 }
4385                 for (i = 0; i < count; i++)
4386                         newname[i] = NULL;
4387                 for (i = 0; i < count; i++) {
4388                         if (keynames[i] != NULL) {
4389                                 newname[i] = isc_mem_get(zone->mctx,
4390                                                          sizeof(dns_name_t));
4391                                 if (newname[i] == NULL)
4392                                         goto allocfail;
4393                                 dns_name_init(newname[i], NULL);
4394                                 result = dns_name_dup(keynames[i], zone->mctx,
4395                                                       newname[i]);
4396                                 if (result != ISC_R_SUCCESS) {
4397                                 allocfail:
4398                                         for (i = 0; i < count; i++)
4399                                                 if (newname[i] != NULL)
4400                                                         dns_name_free(
4401                                                                newname[i],
4402                                                                zone->mctx);
4403                                         isc_mem_put(zone->mctx, new,
4404                                                     count * sizeof(*new));
4405                                         isc_mem_put(zone->mctx, newok,
4406                                                     count * sizeof(*newok));
4407                                         isc_mem_put(zone->mctx, newname,
4408                                                     count * sizeof(*newname));
4409                                         goto unlock;
4410                                 }
4411                         }
4412                 }
4413         }
4414
4415         /*
4416          * Everything is ok so attach to the zone.
4417          */
4418         zone->masters = new;
4419         zone->mastersok = newok;
4420         zone->masterkeynames = newname;
4421         zone->masterscnt = count;
4422         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
4423
4424  unlock:
4425         UNLOCK_ZONE(zone);
4426         return (result);
4427 }
4428
4429 isc_result_t
4430 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
4431         isc_result_t result = ISC_R_SUCCESS;
4432
4433         REQUIRE(DNS_ZONE_VALID(zone));
4434
4435         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4436         if (zone->db == NULL)
4437                 result = DNS_R_NOTLOADED;
4438         else
4439                 dns_db_attach(zone->db, dpb);
4440         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4441
4442         return (result);
4443 }
4444
4445 void
4446 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
4447         REQUIRE(DNS_ZONE_VALID(zone));
4448         REQUIRE(zone->type == dns_zone_staticstub);
4449
4450         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4451         REQUIRE(zone->db == NULL);
4452         dns_db_attach(db, &zone->db);
4453         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4454 }
4455
4456 /*
4457  * Co-ordinates the starting of routine jobs.
4458  */
4459
4460 void
4461 dns_zone_maintenance(dns_zone_t *zone) {
4462         const char me[] = "dns_zone_maintenance";
4463         isc_time_t now;
4464
4465         REQUIRE(DNS_ZONE_VALID(zone));
4466         ENTER;
4467
4468         LOCK_ZONE(zone);
4469         TIME_NOW(&now);
4470         zone_settimer(zone, &now);
4471         UNLOCK_ZONE(zone);
4472 }
4473
4474 static inline isc_boolean_t
4475 was_dumping(dns_zone_t *zone) {
4476         isc_boolean_t dumping;
4477
4478         REQUIRE(LOCKED_ZONE(zone));
4479
4480         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
4481         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
4482         if (!dumping) {
4483                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
4484                 isc_time_settoepoch(&zone->dumptime);
4485         }
4486         return (dumping);
4487 }
4488
4489 #define MAXZONEKEYS 10
4490
4491 static isc_result_t
4492 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4493                isc_mem_t *mctx, unsigned int maxkeys,
4494                dst_key_t **keys, unsigned int *nkeys)
4495 {
4496         isc_result_t result;
4497         dns_dbnode_t *node = NULL;
4498         const char *directory = dns_zone_getkeydirectory(zone);
4499
4500         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
4501         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
4502                                           directory, mctx, maxkeys, keys,
4503                                           nkeys);
4504         if (result == ISC_R_NOTFOUND)
4505                 result = ISC_R_SUCCESS;
4506  failure:
4507         if (node != NULL)
4508                 dns_db_detachnode(db, &node);
4509         return (result);
4510 }
4511
4512 static isc_result_t
4513 offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
4514         dns_ttl_t ttl, dns_rdata_t *rdata)
4515 {
4516         isc_result_t result;
4517
4518         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
4519                 return (ISC_R_SUCCESS);
4520         result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
4521                                name, ttl, rdata);
4522         if (result != ISC_R_SUCCESS)
4523                 return (result);
4524         rdata->flags |= DNS_RDATA_OFFLINE;
4525         result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4526                                name, ttl, rdata);
4527         return (result);
4528 }
4529
4530 static void
4531 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
4532 {
4533         unsigned int delta;
4534         char timebuf[80];
4535
4536         zone->key_expiry = when;
4537         if (when <= now) {
4538                 dns_zone_log(zone, ISC_LOG_ERROR,
4539                              "DNSKEY RRSIG(s) have expired");
4540                 isc_time_settoepoch(&zone->keywarntime);
4541         } else if (when < now + 7 * 24 * 3600) {
4542                 isc_time_t t;
4543                 isc_time_set(&t, when, 0);
4544                 isc_time_formattimestamp(&t, timebuf, 80);
4545                 dns_zone_log(zone, ISC_LOG_WARNING,
4546                              "DNSKEY RRSIG(s) will expire within 7 days: %s",
4547                              timebuf);
4548                 delta = when - now;
4549                 delta--;                /* loop prevention */
4550                 delta /= 24 * 3600;     /* to whole days */
4551                 delta *= 24 * 3600;     /* to seconds */
4552                 isc_time_set(&zone->keywarntime, when - delta, 0);
4553         }  else {
4554                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
4555                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4556                 dns_zone_log(zone, ISC_LOG_NOTICE,
4557                              "setting keywarntime to %s", timebuf);
4558         }
4559 }
4560
4561 /*
4562  * Helper function to del_sigs(). We don't want to delete RRSIGs that
4563  * have no new key.
4564  */
4565 static isc_boolean_t
4566 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys) {
4567         unsigned int i = 0;
4568
4569         /*
4570          * It's okay to delete a signature if there is an active ZSK
4571          * with the same algorithm
4572          */
4573         for (i = 0; i < nkeys; i++) {
4574                 if (rrsig_ptr->algorithm == dst_key_alg(keys[i]) &&
4575                     (dst_key_isprivate(keys[i])) && !KSK(keys[i]))
4576                         return (ISC_TRUE);
4577         }
4578
4579         /*
4580          * Failing that, it is *not* okay to delete a signature
4581          * if the associated public key is still in the DNSKEY RRset
4582          */
4583         for (i = 0; i < nkeys; i++) {
4584                 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
4585                     (rrsig_ptr->keyid == dst_key_id(keys[i])))
4586                         return (ISC_FALSE);
4587         }
4588
4589         /*
4590          * But if the key is gone, then go ahead.
4591          */
4592         return (ISC_TRUE);
4593 }
4594
4595 /*
4596  * Delete expired RRsigs and any RRsigs we are about to re-sign.
4597  * See also update.c:del_keysigs().
4598  */
4599 static isc_result_t
4600 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4601          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4602          unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
4603 {
4604         isc_result_t result;
4605         dns_dbnode_t *node = NULL;
4606         dns_rdataset_t rdataset;
4607         dns_rdata_t rdata = DNS_RDATA_INIT;
4608         unsigned int i;
4609         dns_rdata_rrsig_t rrsig;
4610         isc_boolean_t found, changed;
4611         isc_stdtime_t warn = 0, maybe = 0;
4612
4613         dns_rdataset_init(&rdataset);
4614
4615         if (type == dns_rdatatype_nsec3)
4616                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4617         else
4618                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
4619         if (result == ISC_R_NOTFOUND)
4620                 return (ISC_R_SUCCESS);
4621         if (result != ISC_R_SUCCESS)
4622                 goto failure;
4623         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
4624                                      (isc_stdtime_t) 0, &rdataset, NULL);
4625         dns_db_detachnode(db, &node);
4626
4627         if (result == ISC_R_NOTFOUND) {
4628                 INSIST(!dns_rdataset_isassociated(&rdataset));
4629                 return (ISC_R_SUCCESS);
4630         }
4631         if (result != ISC_R_SUCCESS) {
4632                 INSIST(!dns_rdataset_isassociated(&rdataset));
4633                 goto failure;
4634         }
4635
4636         changed = ISC_FALSE;
4637         for (result = dns_rdataset_first(&rdataset);
4638              result == ISC_R_SUCCESS;
4639              result = dns_rdataset_next(&rdataset)) {
4640                 dns_rdataset_current(&rdataset, &rdata);
4641                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4642                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4643
4644                 if (type != dns_rdatatype_dnskey) {
4645                         if (delsig_ok(&rrsig, keys, nkeys)) {
4646                                 result = update_one_rr(db, ver, diff,
4647                                                DNS_DIFFOP_DELRESIGN, name,
4648                                                rdataset.ttl, &rdata);
4649                                 if (incremental)
4650                                         changed = ISC_TRUE;
4651                                 dns_rdata_reset(&rdata);
4652                                 if (result != ISC_R_SUCCESS)
4653                                         break;
4654                         } else {
4655                                 /*
4656                                  * At this point, we've got an RRSIG,
4657                                  * which is signed by an inactive key.
4658                                  * An administrator needs to provide a new
4659                                  * key/alg, but until that time, we want to
4660                                  * keep the old RRSIG.  Marking the key as
4661                                  * offline will prevent us spinning waiting
4662                                  * for the private part.
4663                                  */
4664                                 if (incremental) {
4665                                         result = offline(db, ver, diff, name,
4666                                                          rdataset.ttl, &rdata);
4667                                         changed = ISC_TRUE;
4668                                         if (result != ISC_R_SUCCESS)
4669                                                 break;
4670                                 }
4671
4672                                 /*
4673                                  * Log the key id and algorithm of
4674                                  * the inactive key with no replacement
4675                                  */
4676                                 if (zone->log_key_expired_timer <= now) {
4677                                         char origin[DNS_NAME_FORMATSIZE];
4678                                         char algbuf[DNS_NAME_FORMATSIZE];
4679                                         dns_name_format(&zone->origin, origin,
4680                                                         sizeof(origin));
4681                                         dns_secalg_format(rrsig.algorithm,
4682                                                           algbuf,
4683                                                           sizeof(algbuf));
4684                                         dns_zone_log(zone, ISC_LOG_WARNING,
4685                                                      "Key %s/%s/%d "
4686                                                      "missing or inactive "
4687                                                      "and has no replacement: "
4688                                                      "retaining signatures.",
4689                                                      origin, algbuf,
4690                                                      rrsig.keyid);
4691                                         zone->log_key_expired_timer = now +
4692                                                                         3600;
4693                                 }
4694                         }
4695                         continue;
4696                 }
4697
4698                 /*
4699                  * RRSIG(DNSKEY) requires special processing.
4700                  */
4701                 found = ISC_FALSE;
4702                 for (i = 0; i < nkeys; i++) {
4703                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
4704                             rrsig.keyid == dst_key_id(keys[i])) {
4705                                 found = ISC_TRUE;
4706                                 /*
4707                                  * Mark offline RRSIG(DNSKEY).
4708                                  * We want the earliest offline expire time
4709                                  * iff there is a new offline signature.
4710                                  */
4711                                 if (!dst_key_isprivate(keys[i])) {
4712                                         if (warn != 0 &&
4713                                             warn > rrsig.timeexpire)
4714                                                 warn = rrsig.timeexpire;
4715                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
4716                                                 if (maybe == 0 ||
4717                                                     maybe > rrsig.timeexpire)
4718                                                         maybe =
4719                                                              rrsig.timeexpire;
4720                                                 break;
4721                                         }
4722                                         if (warn == 0)
4723                                                 warn = maybe;
4724                                         if (warn == 0 ||
4725                                             warn > rrsig.timeexpire)
4726                                                 warn = rrsig.timeexpire;
4727                                         result = offline(db, ver, diff, name,
4728                                                          rdataset.ttl, &rdata);
4729                                         break;
4730                                 }
4731                                 result = update_one_rr(db, ver, diff,
4732                                                        DNS_DIFFOP_DELRESIGN,
4733                                                        name, rdataset.ttl,
4734                                                        &rdata);
4735                                 break;
4736                         }
4737                 }
4738
4739                 /*
4740                  * If there is not a matching DNSKEY then
4741                  * delete the RRSIG.
4742                  */
4743                 if (!found)
4744                         result = update_one_rr(db, ver, diff,
4745                                                DNS_DIFFOP_DELRESIGN, name,
4746                                                rdataset.ttl, &rdata);
4747                 dns_rdata_reset(&rdata);
4748                 if (result != ISC_R_SUCCESS)
4749                         break;
4750         }
4751
4752         if (changed && (rdataset.attributes & DNS_RDATASETATTR_RESIGN) != 0)
4753                 dns_db_resigned(db, &rdataset, ver);
4754
4755         dns_rdataset_disassociate(&rdataset);
4756         if (result == ISC_R_NOMORE)
4757                 result = ISC_R_SUCCESS;
4758         if (warn != 0)
4759                 set_key_expiry_warning(zone, warn, now);
4760  failure:
4761         if (node != NULL)
4762                 dns_db_detachnode(db, &node);
4763         return (result);
4764 }
4765
4766 static isc_result_t
4767 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4768          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4769          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
4770          isc_stdtime_t expire, isc_boolean_t check_ksk,
4771          isc_boolean_t keyset_kskonly)
4772 {
4773         isc_result_t result;
4774         dns_dbnode_t *node = NULL;
4775         dns_rdataset_t rdataset;
4776         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
4777         unsigned char data[1024]; /* XXX */
4778         isc_buffer_t buffer;
4779         unsigned int i, j;
4780
4781         dns_rdataset_init(&rdataset);
4782         isc_buffer_init(&buffer, data, sizeof(data));
4783
4784         if (type == dns_rdatatype_nsec3)
4785                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4786         else
4787                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
4788         if (result == ISC_R_NOTFOUND)
4789                 return (ISC_R_SUCCESS);
4790         if (result != ISC_R_SUCCESS)
4791                 goto failure;
4792         result = dns_db_findrdataset(db, node, ver, type, 0,
4793                                      (isc_stdtime_t) 0, &rdataset, NULL);
4794         dns_db_detachnode(db, &node);
4795         if (result == ISC_R_NOTFOUND) {
4796                 INSIST(!dns_rdataset_isassociated(&rdataset));
4797                 return (ISC_R_SUCCESS);
4798         }
4799         if (result != ISC_R_SUCCESS) {
4800                 INSIST(!dns_rdataset_isassociated(&rdataset));
4801                 goto failure;
4802         }
4803
4804         for (i = 0; i < nkeys; i++) {
4805                 isc_boolean_t both = ISC_FALSE;
4806
4807                 if (!dst_key_isprivate(keys[i]))
4808                         continue;
4809
4810                 if (check_ksk && !REVOKE(keys[i])) {
4811                         isc_boolean_t have_ksk, have_nonksk;
4812                         if (KSK(keys[i])) {
4813                                 have_ksk = ISC_TRUE;
4814                                 have_nonksk = ISC_FALSE;
4815                         } else {
4816                                 have_ksk = ISC_FALSE;
4817                                 have_nonksk = ISC_TRUE;
4818                         }
4819                         for (j = 0; j < nkeys; j++) {
4820                                 if (j == i || ALG(keys[i]) != ALG(keys[j]))
4821                                         continue;
4822                                 if (REVOKE(keys[j]))
4823                                         continue;
4824                                 if (KSK(keys[j]))
4825                                         have_ksk = ISC_TRUE;
4826                                 else
4827                                         have_nonksk = ISC_TRUE;
4828                                 both = have_ksk && have_nonksk;
4829                                 if (both)
4830                                         break;
4831                         }
4832                 }
4833                 if (both) {
4834                         if (type == dns_rdatatype_dnskey) {
4835                                 if (!KSK(keys[i]) && keyset_kskonly)
4836                                         continue;
4837                         } else if (KSK(keys[i]))
4838                                 continue;
4839                 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
4840                                 continue;
4841
4842                 /* Calculate the signature, creating a RRSIG RDATA. */
4843                 isc_buffer_clear(&buffer);
4844                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
4845                                       &inception, &expire,
4846                                       mctx, &buffer, &sig_rdata));
4847                 /* Update the database and journal with the RRSIG. */
4848                 /* XXX inefficient - will cause dataset merging */
4849                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4850                                     name, rdataset.ttl, &sig_rdata));
4851                 dns_rdata_reset(&sig_rdata);
4852                 isc_buffer_init(&buffer, data, sizeof(data));
4853         }
4854
4855  failure:
4856         if (dns_rdataset_isassociated(&rdataset))
4857                 dns_rdataset_disassociate(&rdataset);
4858         if (node != NULL)
4859                 dns_db_detachnode(db, &node);
4860         return (result);
4861 }
4862
4863 static void
4864 zone_resigninc(dns_zone_t *zone) {
4865         dns_db_t *db = NULL;
4866         dns_dbversion_t *version = NULL;
4867         dns_diff_t sig_diff;
4868         dns_fixedname_t fixed;
4869         dns_name_t *name;
4870         dns_rdataset_t rdataset;
4871         dns_rdatatype_t covers;
4872         dst_key_t *zone_keys[MAXZONEKEYS];
4873         isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
4874         isc_result_t result;
4875         isc_stdtime_t now, inception, soaexpire, expire, stop;
4876         isc_uint32_t jitter;
4877         unsigned int i;
4878         unsigned int nkeys = 0;
4879         unsigned int resign;
4880
4881         dns_rdataset_init(&rdataset);
4882         dns_fixedname_init(&fixed);
4883         dns_diff_init(zone->mctx, &sig_diff);
4884         sig_diff.resign = zone->sigresigninginterval;
4885
4886         /*
4887          * Updates are disabled.  Pause for 5 minutes.
4888          */
4889         if (zone->update_disabled) {
4890                 result = ISC_R_FAILURE;
4891                 goto failure;
4892         }
4893
4894         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4895         dns_db_attach(zone->db, &db);
4896         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4897
4898         result = dns_db_newversion(db, &version);
4899         if (result != ISC_R_SUCCESS) {
4900                 dns_zone_log(zone, ISC_LOG_ERROR,
4901                              "zone_resigninc:dns_db_newversion -> %s\n",
4902                              dns_result_totext(result));
4903                 goto failure;
4904         }
4905
4906         result = find_zone_keys(zone, db, version, zone->mctx, MAXZONEKEYS,
4907                                 zone_keys, &nkeys);
4908         if (result != ISC_R_SUCCESS) {
4909                 dns_zone_log(zone, ISC_LOG_ERROR,
4910                              "zone_resigninc:find_zone_keys -> %s\n",
4911                              dns_result_totext(result));
4912                 goto failure;
4913         }
4914
4915         isc_stdtime_get(&now);
4916         inception = now - 3600; /* Allow for clock skew. */
4917         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
4918         /*
4919          * Spread out signatures over time if they happen to be
4920          * clumped.  We don't do this for each add_sigs() call as
4921          * we still want some clustering to occur.
4922          */
4923         isc_random_get(&jitter);
4924         expire = soaexpire - jitter % 3600;
4925         stop = now + 5;
4926
4927         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
4928         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
4929
4930         name = dns_fixedname_name(&fixed);
4931         result = dns_db_getsigningtime(db, &rdataset, name);
4932         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
4933                 dns_zone_log(zone, ISC_LOG_ERROR,
4934                              "zone_resigninc:dns_db_getsigningtime -> %s\n",
4935                              dns_result_totext(result));
4936         }
4937
4938         i = 0;
4939         while (result == ISC_R_SUCCESS) {
4940                 resign = rdataset.resign;
4941                 covers = rdataset.covers;
4942                 dns_rdataset_disassociate(&rdataset);
4943
4944                 /*
4945                  * Stop if we hit the SOA as that means we have walked the
4946                  * entire zone.  The SOA record should always be the most
4947                  * recent signature.
4948                  */
4949                 /* XXXMPA increase number of RRsets signed pre call */
4950                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
4951                     resign > stop)
4952                         break;
4953
4954                 result = del_sigs(zone, db, version, name, covers, &sig_diff,
4955                                   zone_keys, nkeys, now, ISC_TRUE);
4956                 if (result != ISC_R_SUCCESS) {
4957                         dns_zone_log(zone, ISC_LOG_ERROR,
4958                                      "zone_resigninc:del_sigs -> %s\n",
4959                                      dns_result_totext(result));
4960                         break;
4961                 }
4962
4963                 result = add_sigs(db, version, name, covers, &sig_diff,
4964                                   zone_keys, nkeys, zone->mctx, inception,
4965                                   expire, check_ksk, keyset_kskonly);
4966                 if (result != ISC_R_SUCCESS) {
4967                         dns_zone_log(zone, ISC_LOG_ERROR,
4968                                      "zone_resigninc:add_sigs -> %s\n",
4969                                      dns_result_totext(result));
4970                         break;
4971                 }
4972                 result  = dns_db_getsigningtime(db, &rdataset,
4973                                                 dns_fixedname_name(&fixed));
4974                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
4975                         result = ISC_R_SUCCESS;
4976                         break;
4977                 }
4978                 if (result != ISC_R_SUCCESS)
4979                         dns_zone_log(zone, ISC_LOG_ERROR,
4980                              "zone_resigninc:dns_db_getsigningtime -> %s\n",
4981                                      dns_result_totext(result));
4982         }
4983
4984         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
4985                 goto failure;
4986
4987         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
4988                           &sig_diff, zone_keys, nkeys, now, ISC_TRUE);
4989         if (result != ISC_R_SUCCESS) {
4990                 dns_zone_log(zone, ISC_LOG_ERROR,
4991                              "zone_resigninc:del_sigs -> %s\n",
4992                              dns_result_totext(result));
4993                 goto failure;
4994         }
4995
4996         /*
4997          * Did we change anything in the zone?
4998          */
4999         if (ISC_LIST_EMPTY(sig_diff.tuples))
5000                 goto failure;
5001
5002         /* Increment SOA serial if we have made changes */
5003         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
5004         if (result != ISC_R_SUCCESS) {
5005                 dns_zone_log(zone, ISC_LOG_ERROR,
5006                              "zone_resigninc:increment_soa_serial -> %s\n",
5007                              dns_result_totext(result));
5008                 goto failure;
5009         }
5010
5011         /*
5012          * Generate maximum life time signatures so that the above loop
5013          * termination is sensible.
5014          */
5015         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5016                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5017                           soaexpire, check_ksk, keyset_kskonly);
5018         if (result != ISC_R_SUCCESS) {
5019                 dns_zone_log(zone, ISC_LOG_ERROR,
5020                              "zone_resigninc:add_sigs -> %s\n",
5021                              dns_result_totext(result));
5022                 goto failure;
5023         }
5024
5025         /* Write changes to journal file. */
5026         CHECK(zone_journal(zone, &sig_diff, "zone_resigninc"));
5027
5028         /* Everything has succeeded. Commit the changes. */
5029         dns_db_closeversion(db, &version, ISC_TRUE);
5030
5031  failure:
5032         dns_diff_clear(&sig_diff);
5033         for (i = 0; i < nkeys; i++)
5034                 dst_key_free(&zone_keys[i]);
5035         if (version != NULL) {
5036                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
5037                 dns_db_detach(&db);
5038         } else if (db != NULL)
5039                 dns_db_detach(&db);
5040         if (result == ISC_R_SUCCESS) {
5041                 set_resigntime(zone);
5042                 LOCK_ZONE(zone);
5043                 zone_needdump(zone, DNS_DUMP_DELAY);
5044                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5045                 UNLOCK_ZONE(zone);
5046         } else {
5047                 /*
5048                  * Something failed.  Retry in 5 minutes.
5049                  */
5050                 isc_interval_t ival;
5051                 isc_interval_set(&ival, 300, 0);
5052                 isc_time_nowplusinterval(&zone->resigntime, &ival);
5053         }
5054 }
5055
5056 static isc_result_t
5057 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
5058             dns_name_t *newname, isc_boolean_t bottom)
5059 {
5060         isc_result_t result;
5061         dns_dbiterator_t *dbit = NULL;
5062         dns_rdatasetiter_t *rdsit = NULL;
5063         dns_dbnode_t *node = NULL;
5064
5065         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
5066         CHECK(dns_dbiterator_seek(dbit, oldname));
5067         do {
5068                 result = dns_dbiterator_next(dbit);
5069                 if (result == ISC_R_NOMORE)
5070                         CHECK(dns_dbiterator_first(dbit));
5071                 CHECK(dns_dbiterator_current(dbit, &node, newname));
5072                 if (bottom && dns_name_issubdomain(newname, oldname) &&
5073                     !dns_name_equal(newname, oldname)) {
5074                         dns_db_detachnode(db, &node);
5075                         continue;
5076                 }
5077                 /*
5078                  * Is this node empty?
5079                  */
5080                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
5081                 result = dns_rdatasetiter_first(rdsit);
5082                 dns_db_detachnode(db, &node);
5083                 dns_rdatasetiter_destroy(&rdsit);
5084                 if (result != ISC_R_NOMORE)
5085                         break;
5086         } while (1);
5087  failure:
5088         if (node != NULL)
5089                 dns_db_detachnode(db, &node);
5090         if (dbit != NULL)
5091                 dns_dbiterator_destroy(&dbit);
5092         return (result);
5093 }
5094
5095 static isc_boolean_t
5096 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5097                 dns_rdatatype_t type, dst_key_t *key)
5098 {
5099         isc_result_t result;
5100         dns_rdataset_t rdataset;
5101         dns_rdata_t rdata = DNS_RDATA_INIT;
5102         dns_rdata_rrsig_t rrsig;
5103
5104         dns_rdataset_init(&rdataset);
5105         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
5106                                      type, 0, &rdataset, NULL);
5107         if (result != ISC_R_SUCCESS) {
5108                 INSIST(!dns_rdataset_isassociated(&rdataset));
5109                 return (ISC_FALSE);
5110         }
5111         for (result = dns_rdataset_first(&rdataset);
5112              result == ISC_R_SUCCESS;
5113              result = dns_rdataset_next(&rdataset)) {
5114                 dns_rdataset_current(&rdataset, &rdata);
5115                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5116                 INSIST(result == ISC_R_SUCCESS);
5117                 if (rrsig.algorithm == dst_key_alg(key) &&
5118                     rrsig.keyid == dst_key_id(key)) {
5119                         dns_rdataset_disassociate(&rdataset);
5120                         return (ISC_TRUE);
5121                 }
5122                 dns_rdata_reset(&rdata);
5123         }
5124         dns_rdataset_disassociate(&rdataset);
5125         return (ISC_FALSE);
5126 }
5127
5128 static isc_result_t
5129 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5130          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5131          dns_diff_t *diff)
5132 {
5133         dns_fixedname_t fixed;
5134         dns_name_t *next;
5135         dns_rdata_t rdata = DNS_RDATA_INIT;
5136         isc_result_t result;
5137         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5138
5139         dns_fixedname_init(&fixed);
5140         next = dns_fixedname_name(&fixed);
5141
5142         CHECK(next_active(db, version, name, next, bottom));
5143         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5144                                   &rdata));
5145         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5146                             &rdata));
5147  failure:
5148         return (result);
5149 }
5150
5151 static isc_result_t
5152 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5153             dns_dbversion_t *version, isc_boolean_t build_nsec3,
5154             isc_boolean_t build_nsec, dst_key_t *key,
5155             isc_stdtime_t inception, isc_stdtime_t expire,
5156             unsigned int minimum, isc_boolean_t is_ksk,
5157             isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5158             dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5159 {
5160         isc_result_t result;
5161         dns_rdatasetiter_t *iterator = NULL;
5162         dns_rdataset_t rdataset;
5163         dns_rdata_t rdata = DNS_RDATA_INIT;
5164         isc_buffer_t buffer;
5165         unsigned char data[1024];
5166         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5167                       seen_nsec3, seen_ds;
5168         isc_boolean_t bottom;
5169
5170         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5171         if (result != ISC_R_SUCCESS) {
5172                 if (result == ISC_R_NOTFOUND)
5173                         result = ISC_R_SUCCESS;
5174                 return (result);
5175         }
5176
5177         dns_rdataset_init(&rdataset);
5178         isc_buffer_init(&buffer, data, sizeof(data));
5179         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5180         seen_nsec3 = seen_ds = ISC_FALSE;
5181         for (result = dns_rdatasetiter_first(iterator);
5182              result == ISC_R_SUCCESS;
5183              result = dns_rdatasetiter_next(iterator)) {
5184                 dns_rdatasetiter_current(iterator, &rdataset);
5185                 if (rdataset.type == dns_rdatatype_soa)
5186                         seen_soa = ISC_TRUE;
5187                 else if (rdataset.type == dns_rdatatype_ns)
5188                         seen_ns = ISC_TRUE;
5189                 else if (rdataset.type == dns_rdatatype_ds)
5190                         seen_ds = ISC_TRUE;
5191                 else if (rdataset.type == dns_rdatatype_dname)
5192                         seen_dname = ISC_TRUE;
5193                 else if (rdataset.type == dns_rdatatype_nsec)
5194                         seen_nsec = ISC_TRUE;
5195                 else if (rdataset.type == dns_rdatatype_nsec3)
5196                         seen_nsec3 = ISC_TRUE;
5197                 if (rdataset.type != dns_rdatatype_rrsig)
5198                         seen_rr = ISC_TRUE;
5199                 dns_rdataset_disassociate(&rdataset);
5200         }
5201         if (result != ISC_R_NOMORE)
5202                 goto failure;
5203         if (seen_ns && !seen_soa)
5204                 *delegation = ISC_TRUE;
5205         /*
5206          * Going from insecure to NSEC3.
5207          * Don't generate NSEC3 records for NSEC3 records.
5208          */
5209         if (build_nsec3 && !seen_nsec3 && seen_rr) {
5210                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
5211                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
5212                                           unsecure, diff));
5213                 (*signatures)--;
5214         }
5215         /*
5216          * Going from insecure to NSEC.
5217          * Don't generate NSEC records for NSEC3 records.
5218          */
5219         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
5220                 /* Build and add NSEC. */
5221                 bottom = (seen_ns && !seen_soa) || seen_dname;
5222                 /*
5223                  * Build a NSEC record except at the origin.
5224                  */
5225                 if (!dns_name_equal(name, dns_db_origin(db))) {
5226                         CHECK(add_nsec(db, version, name, node, minimum,
5227                                        bottom, diff));
5228                         /* Count a NSEC generation as a signature generation. */
5229                         (*signatures)--;
5230                 }
5231         }
5232         result = dns_rdatasetiter_first(iterator);
5233         while (result == ISC_R_SUCCESS) {
5234                 dns_rdatasetiter_current(iterator, &rdataset);
5235                 if (rdataset.type == dns_rdatatype_soa ||
5236                     rdataset.type == dns_rdatatype_rrsig)
5237                         goto next_rdataset;
5238                 if (rdataset.type == dns_rdatatype_dnskey) {
5239                         if (!is_ksk && keyset_kskonly)
5240                                 goto next_rdataset;
5241                 } else if (is_ksk)
5242                         goto next_rdataset;
5243                 if (*delegation &&
5244                     rdataset.type != dns_rdatatype_ds &&
5245                     rdataset.type != dns_rdatatype_nsec)
5246                         goto next_rdataset;
5247                 if (signed_with_key(db, node, version, rdataset.type, key))
5248                         goto next_rdataset;
5249                 /* Calculate the signature, creating a RRSIG RDATA. */
5250                 isc_buffer_clear(&buffer);
5251                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
5252                                       &expire, mctx, &buffer, &rdata));
5253                 /* Update the database and journal with the RRSIG. */
5254                 /* XXX inefficient - will cause dataset merging */
5255                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
5256                                     name, rdataset.ttl, &rdata));
5257                 dns_rdata_reset(&rdata);
5258                 (*signatures)--;
5259  next_rdataset:
5260                 dns_rdataset_disassociate(&rdataset);
5261                 result = dns_rdatasetiter_next(iterator);
5262         }
5263         if (result == ISC_R_NOMORE)
5264                 result = ISC_R_SUCCESS;
5265         if (seen_dname)
5266                 *delegation = ISC_TRUE;
5267  failure:
5268         if (dns_rdataset_isassociated(&rdataset))
5269                 dns_rdataset_disassociate(&rdataset);
5270         if (iterator != NULL)
5271                 dns_rdatasetiter_destroy(&iterator);
5272         return (result);
5273 }
5274
5275 /*
5276  * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
5277  */
5278 static isc_result_t
5279 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5280              dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
5281 {
5282         isc_result_t result;
5283         dns_rdataset_t rdataset;
5284         dns_dbnode_t *node = NULL;
5285
5286         CHECK(dns_db_getoriginnode(db, &node));
5287         if (update_only) {
5288                 dns_rdataset_init(&rdataset);
5289                 result = dns_db_findrdataset(db, node, version,
5290                                              dns_rdatatype_nsec,
5291                                              dns_rdatatype_none,
5292                                              0, &rdataset, NULL);
5293                 if (dns_rdataset_isassociated(&rdataset))
5294                         dns_rdataset_disassociate(&rdataset);
5295                 if (result == ISC_R_NOTFOUND)
5296                         goto success;
5297                 if (result != ISC_R_SUCCESS)
5298                         goto failure;
5299         }
5300         CHECK(delete_nsec(db, version, node, name, diff));
5301         CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
5302  success:
5303         result = ISC_R_SUCCESS;
5304  failure:
5305         if (node != NULL)
5306                 dns_db_detachnode(db, &node);
5307         return (result);
5308 }
5309
5310 static isc_result_t
5311 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
5312                   dns_dbversion_t *version, isc_boolean_t build_nsec3,
5313                   dns_ttl_t minimum, dns_diff_t *diff)
5314 {
5315         isc_result_t result;
5316         dns_dbnode_t *node = NULL;
5317         dns_rdataset_t rdataset;
5318         dns_rdata_t rdata = DNS_RDATA_INIT;
5319         unsigned char data[5];
5320         isc_boolean_t seen_done = ISC_FALSE;
5321         isc_boolean_t have_rr = ISC_FALSE;
5322
5323         dns_rdataset_init(&rdataset);
5324         result = dns_db_getoriginnode(signing->db, &node);
5325         if (result != ISC_R_SUCCESS)
5326                 goto failure;
5327
5328         result = dns_db_findrdataset(signing->db, node, version,
5329                                      zone->privatetype, dns_rdatatype_none,
5330                                      0, &rdataset, NULL);
5331         if (result == ISC_R_NOTFOUND) {
5332                 INSIST(!dns_rdataset_isassociated(&rdataset));
5333                 result = ISC_R_SUCCESS;
5334                 goto failure;
5335         }
5336         if (result != ISC_R_SUCCESS) {
5337                 INSIST(!dns_rdataset_isassociated(&rdataset));
5338                 goto failure;
5339         }
5340         for (result = dns_rdataset_first(&rdataset);
5341              result == ISC_R_SUCCESS;
5342              result = dns_rdataset_next(&rdataset)) {
5343                 dns_rdataset_current(&rdataset, &rdata);
5344                 /*
5345                  * If we don't match the algorithm or keyid skip the record.
5346                  */
5347                 if (rdata.length != 5 ||
5348                     rdata.data[0] != signing->algorithm ||
5349                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
5350                     rdata.data[2] != (signing->keyid & 0xff)) {
5351                         have_rr = ISC_TRUE;
5352                         dns_rdata_reset(&rdata);
5353                         continue;
5354                 }
5355                 /*
5356                  * We have a match.  If we were signing (!signing->delete)
5357                  * and we already have a record indicating that we have
5358                  * finished signing (rdata.data[4] != 0) then keep it.
5359                  * Otherwise it needs to be deleted as we have removed all
5360                  * the signatures (signing->delete), so any record indicating
5361                  * completion is now out of date, or we have finished signing
5362                  * with the new record so we no longer need to remember that
5363                  * we need to sign the zone with the matching key across a
5364                  * nameserver re-start.
5365                  */
5366                 if (!signing->delete && rdata.data[4] != 0) {
5367                         seen_done = ISC_TRUE;
5368                         have_rr = ISC_TRUE;
5369                 } else
5370                         CHECK(update_one_rr(signing->db, version, diff,
5371                                             DNS_DIFFOP_DEL, &zone->origin,
5372                                             rdataset.ttl, &rdata));
5373                 dns_rdata_reset(&rdata);
5374         }
5375         if (result == ISC_R_NOMORE)
5376                 result = ISC_R_SUCCESS;
5377         if (!signing->delete && !seen_done) {
5378                 /*
5379                  * If we were signing then we need to indicate that we have
5380                  * finished signing the zone with this key.  If it is already
5381                  * there we don't need to add it a second time.
5382                  */
5383                 data[0] = signing->algorithm;
5384                 data[1] = (signing->keyid >> 8) & 0xff;
5385                 data[2] = signing->keyid & 0xff;
5386                 data[3] = 0;
5387                 data[4] = 1;
5388                 rdata.length = sizeof(data);
5389                 rdata.data = data;
5390                 rdata.type = zone->privatetype;
5391                 rdata.rdclass = dns_db_class(signing->db);
5392                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
5393                                     &zone->origin, rdataset.ttl, &rdata));
5394         } else if (!have_rr) {
5395                 dns_name_t *origin = dns_db_origin(signing->db);
5396                 /*
5397                  * Rebuild the NSEC/NSEC3 record for the origin as we no
5398                  * longer have any private records.
5399                  */
5400                 if (build_nsec3)
5401                         CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
5402                                                   minimum, ISC_FALSE, diff));
5403                 CHECK(updatesecure(signing->db, version, origin, minimum,
5404                                    ISC_TRUE, diff));
5405         }
5406
5407  failure:
5408         if (dns_rdataset_isassociated(&rdataset))
5409                 dns_rdataset_disassociate(&rdataset);
5410         if (node != NULL)
5411                 dns_db_detachnode(signing->db, &node);
5412         return (result);
5413 }
5414
5415 /*
5416  * If 'active' is set then we are not done with the chain yet so only
5417  * delete the nsec3param record which indicates a full chain exists
5418  * (flags == 0).
5419  */
5420 static isc_result_t
5421 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
5422                  isc_boolean_t active, dns_rdatatype_t privatetype,
5423                  dns_diff_t *diff)
5424 {
5425         dns_dbnode_t *node = NULL;
5426         dns_name_t *name = dns_db_origin(db);
5427         dns_rdata_t rdata = DNS_RDATA_INIT;
5428         dns_rdataset_t rdataset;
5429         dns_rdata_nsec3param_t nsec3param;
5430         isc_result_t result;
5431         isc_buffer_t buffer;
5432         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
5433         dns_ttl_t ttl = 0;
5434
5435         dns_rdataset_init(&rdataset);
5436
5437         result = dns_db_getoriginnode(db, &node);
5438         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5439         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5440                                      0, 0, &rdataset, NULL);
5441         if (result == ISC_R_NOTFOUND)
5442                 goto try_private;
5443         if (result != ISC_R_SUCCESS)
5444                 goto failure;
5445
5446         /*
5447          * Preserve the existing ttl.
5448          */
5449         ttl = rdataset.ttl;
5450
5451         /*
5452          * Delete all NSEC3PARAM records which match that in nsec3chain.
5453          */
5454         for (result = dns_rdataset_first(&rdataset);
5455              result == ISC_R_SUCCESS;
5456              result = dns_rdataset_next(&rdataset)) {
5457
5458                 dns_rdataset_current(&rdataset, &rdata);
5459                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5460
5461                 if (nsec3param.hash != chain->nsec3param.hash ||
5462                     (active && nsec3param.flags != 0) ||
5463                     nsec3param.iterations != chain->nsec3param.iterations ||
5464                     nsec3param.salt_length != chain->nsec3param.salt_length ||
5465                     memcmp(nsec3param.salt, chain->nsec3param.salt,
5466                            nsec3param.salt_length)) {
5467                         dns_rdata_reset(&rdata);
5468                         continue;
5469                 }
5470
5471                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5472                                     name, rdataset.ttl, &rdata));
5473                 dns_rdata_reset(&rdata);
5474         }
5475         if (result != ISC_R_NOMORE)
5476                 goto failure;
5477
5478         dns_rdataset_disassociate(&rdataset);
5479
5480  try_private:
5481
5482         if (active)
5483                 goto add;
5484         /*
5485          * Delete all private records which match that in nsec3chain.
5486          */
5487         result = dns_db_findrdataset(db, node, ver, privatetype,
5488                                      0, 0, &rdataset, NULL);
5489         if (result == ISC_R_NOTFOUND)
5490                 goto add;
5491         if (result != ISC_R_SUCCESS)
5492                 goto failure;
5493
5494         for (result = dns_rdataset_first(&rdataset);
5495              result == ISC_R_SUCCESS;
5496              result = dns_rdataset_next(&rdataset)) {
5497                 dns_rdata_t private = DNS_RDATA_INIT;
5498                 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
5499
5500                 dns_rdataset_current(&rdataset, &private);
5501                 if (!dns_nsec3param_fromprivate(&private, &rdata,
5502                                                 buf, sizeof(buf)))
5503                         continue;
5504                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5505
5506                 if (nsec3param.hash != chain->nsec3param.hash ||
5507                     nsec3param.iterations != chain->nsec3param.iterations ||
5508                     nsec3param.salt_length != chain->nsec3param.salt_length ||
5509                     memcmp(nsec3param.salt, chain->nsec3param.salt,
5510                            nsec3param.salt_length)) {
5511                         dns_rdata_reset(&rdata);
5512                         continue;
5513                 }
5514
5515                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5516                                     name, rdataset.ttl, &private));
5517                 dns_rdata_reset(&rdata);
5518         }
5519         if (result != ISC_R_NOMORE)
5520                 goto failure;
5521
5522   add:
5523         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
5524                 result = ISC_R_SUCCESS;
5525                 goto failure;
5526         }
5527
5528         /*
5529          * Add a NSEC3PARAM record which matches that in nsec3chain but
5530          * with all flags bits cleared.
5531          *
5532          * Note: we do not clear chain->nsec3param.flags as this change
5533          * may be reversed.
5534          */
5535         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
5536         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
5537                                    dns_rdatatype_nsec3param,
5538                                    &chain->nsec3param, &buffer));
5539         rdata.data[1] = 0;      /* Clear flag bits. */
5540         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
5541
5542   failure:
5543         dns_db_detachnode(db, &node);
5544         if (dns_rdataset_isassociated(&rdataset))
5545                 dns_rdataset_disassociate(&rdataset);
5546         return (result);
5547 }
5548
5549 static isc_result_t
5550 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5551             dns_name_t *name, dns_diff_t *diff)
5552 {
5553         dns_rdataset_t rdataset;
5554         isc_result_t result;
5555
5556         dns_rdataset_init(&rdataset);
5557
5558         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5559                                      0, 0, &rdataset, NULL);
5560         if (result == ISC_R_NOTFOUND)
5561                 return (ISC_R_SUCCESS);
5562         if (result != ISC_R_SUCCESS)
5563                 return (result);
5564         for (result = dns_rdataset_first(&rdataset);
5565              result == ISC_R_SUCCESS;
5566              result = dns_rdataset_next(&rdataset)) {
5567                 dns_rdata_t rdata = DNS_RDATA_INIT;
5568
5569                 dns_rdataset_current(&rdataset, &rdata);
5570                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5571                                     rdataset.ttl, &rdata));
5572         }
5573         if (result == ISC_R_NOMORE)
5574                 result = ISC_R_SUCCESS;
5575  failure:
5576         dns_rdataset_disassociate(&rdataset);
5577         return (result);
5578 }
5579
5580 static isc_result_t
5581 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5582                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
5583                     dns_diff_t *diff)
5584 {
5585         dns_rdataset_t rdataset;
5586         dns_rdata_nsec3_t nsec3;
5587         isc_result_t result;
5588
5589         dns_rdataset_init(&rdataset);
5590         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
5591                                      0, 0, &rdataset, NULL);
5592         if (result == ISC_R_NOTFOUND)
5593                 return (ISC_R_SUCCESS);
5594         if (result != ISC_R_SUCCESS)
5595                 return (result);
5596
5597         for (result = dns_rdataset_first(&rdataset);
5598              result == ISC_R_SUCCESS;
5599              result = dns_rdataset_next(&rdataset)) {
5600                 dns_rdata_t rdata = DNS_RDATA_INIT;
5601
5602                 dns_rdataset_current(&rdataset, &rdata);
5603                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
5604                 if (nsec3.hash != param->hash ||
5605                     nsec3.iterations != param->iterations ||
5606                     nsec3.salt_length != param->salt_length ||
5607                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
5608                         continue;
5609                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5610                                     rdataset.ttl, &rdata));
5611         }
5612         if (result == ISC_R_NOMORE)
5613                 result = ISC_R_SUCCESS;
5614  failure:
5615         dns_rdataset_disassociate(&rdataset);
5616         return (result);
5617 }
5618
5619 static isc_result_t
5620 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
5621                 const dns_rdata_nsec3param_t *param,
5622                 isc_boolean_t *answer)
5623 {
5624         dns_dbnode_t *node = NULL;
5625         dns_rdata_t rdata = DNS_RDATA_INIT;
5626         dns_rdata_nsec3param_t myparam;
5627         dns_rdataset_t rdataset;
5628         isc_result_t result;
5629
5630         *answer = ISC_FALSE;
5631
5632         result = dns_db_getoriginnode(db, &node);
5633         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5634
5635         dns_rdataset_init(&rdataset);
5636
5637         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5638                                      0, 0, &rdataset, NULL);
5639         if (result == ISC_R_SUCCESS) {
5640                 dns_rdataset_disassociate(&rdataset);
5641                 dns_db_detachnode(db, &node);
5642                 return (result);
5643         }
5644         if (result != ISC_R_NOTFOUND) {
5645                 dns_db_detachnode(db, &node);
5646                 return (result);
5647         }
5648
5649         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5650                                      0, 0, &rdataset, NULL);
5651         if (result == ISC_R_NOTFOUND) {
5652                 *answer = ISC_TRUE;
5653                 dns_db_detachnode(db, &node);
5654                 return (ISC_R_SUCCESS);
5655         }
5656         if (result != ISC_R_SUCCESS) {
5657                 dns_db_detachnode(db, &node);
5658                 return (result);
5659         }
5660
5661         for (result = dns_rdataset_first(&rdataset);
5662              result == ISC_R_SUCCESS;
5663              result = dns_rdataset_next(&rdataset)) {
5664                 dns_rdataset_current(&rdataset, &rdata);
5665                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
5666                 dns_rdata_reset(&rdata);
5667                 /*
5668                  * Ignore any NSEC3PARAM removals.
5669                  */
5670                 if (NSEC3REMOVE(myparam.flags))
5671                         continue;
5672                 /*
5673                  * Ignore the chain that we are in the process of deleting.
5674                  */
5675                 if (myparam.hash == param->hash &&
5676                     myparam.iterations == param->iterations &&
5677                     myparam.salt_length == param->salt_length &&
5678                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
5679                         continue;
5680                 /*
5681                  * Found an active NSEC3 chain.
5682                  */
5683                 break;
5684         }
5685         if (result == ISC_R_NOMORE) {
5686                 *answer = ISC_TRUE;
5687                 result = ISC_R_SUCCESS;
5688         }
5689
5690  failure:
5691         if (dns_rdataset_isassociated(&rdataset))
5692                 dns_rdataset_disassociate(&rdataset);
5693         dns_db_detachnode(db, &node);
5694         return (result);
5695 }
5696
5697 static isc_result_t
5698 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
5699             dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
5700             isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
5701             isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
5702             dns_diff_t *sig_diff)
5703 {
5704         dns_difftuple_t *tuple;
5705         isc_result_t result;
5706
5707         for (tuple = ISC_LIST_HEAD(diff->tuples);
5708              tuple != NULL;
5709              tuple = ISC_LIST_HEAD(diff->tuples)) {
5710                 result = del_sigs(zone, db, version, &tuple->name,
5711                                   tuple->rdata.type, sig_diff,
5712                                   zone_keys, nkeys, now, ISC_FALSE);
5713                 if (result != ISC_R_SUCCESS) {
5714                         dns_zone_log(zone, ISC_LOG_ERROR,
5715                                      "update_sigs:del_sigs -> %s\n",
5716                                      dns_result_totext(result));
5717                         return (result);
5718                 }
5719                 result = add_sigs(db, version, &tuple->name,
5720                                   tuple->rdata.type, sig_diff,
5721                                   zone_keys, nkeys, zone->mctx, inception,
5722                                   expire, check_ksk, keyset_kskonly);
5723                 if (result != ISC_R_SUCCESS) {
5724                         dns_zone_log(zone, ISC_LOG_ERROR,
5725                                      "update_sigs:add_sigs -> %s\n",
5726                                      dns_result_totext(result));
5727                         return (result);
5728                 }
5729
5730                 do {
5731                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
5732                         while (next != NULL &&
5733                                (tuple->rdata.type != next->rdata.type ||
5734                                 !dns_name_equal(&tuple->name, &next->name)))
5735                                 next = ISC_LIST_NEXT(next, link);
5736                         ISC_LIST_UNLINK(diff->tuples, tuple, link);
5737                         dns_diff_appendminimal(sig_diff, &tuple);
5738                         INSIST(tuple == NULL);
5739                         tuple = next;
5740                 } while (tuple != NULL);
5741         }
5742         return (ISC_R_SUCCESS);
5743 }
5744
5745 /*
5746  * Incrementally build and sign a new NSEC3 chain using the parameters
5747  * requested.
5748  */
5749 static void
5750 zone_nsec3chain(dns_zone_t *zone) {
5751         dns_db_t *db = NULL;
5752         dns_dbnode_t *node = NULL;
5753         dns_dbversion_t *version = NULL;
5754         dns_diff_t sig_diff;
5755         dns_diff_t nsec_diff;
5756         dns_diff_t nsec3_diff;
5757         dns_diff_t param_diff;
5758         dns_fixedname_t fixed;
5759         dns_fixedname_t nextfixed;
5760         dns_name_t *name, *nextname;
5761         dns_rdataset_t rdataset;
5762         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
5763         dns_nsec3chainlist_t cleanup;
5764         dst_key_t *zone_keys[MAXZONEKEYS];
5765         isc_int32_t signatures;
5766         isc_boolean_t check_ksk, keyset_kskonly;
5767         isc_boolean_t delegation;
5768         isc_boolean_t first;
5769         isc_result_t result;
5770         isc_stdtime_t now, inception, soaexpire, expire;
5771         isc_uint32_t jitter;
5772         unsigned int i;
5773         unsigned int nkeys = 0;
5774         isc_uint32_t nodes;
5775         isc_boolean_t unsecure = ISC_FALSE;
5776         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
5777         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
5778         dns_rdatasetiter_t *iterator = NULL;
5779         isc_boolean_t buildnsecchain;
5780         isc_boolean_t updatensec = ISC_FALSE;
5781         dns_rdatatype_t privatetype = zone->privatetype;
5782
5783         dns_rdataset_init(&rdataset);
5784         dns_fixedname_init(&fixed);
5785         name = dns_fixedname_name(&fixed);
5786         dns_fixedname_init(&nextfixed);
5787         nextname = dns_fixedname_name(&nextfixed);
5788         dns_diff_init(zone->mctx, &param_diff);
5789         dns_diff_init(zone->mctx, &nsec3_diff);
5790         dns_diff_init(zone->mctx, &nsec_diff);
5791         dns_diff_init(zone->mctx, &sig_diff);
5792         sig_diff.resign = zone->sigresigninginterval;
5793         ISC_LIST_INIT(cleanup);
5794
5795         /*
5796          * Updates are disabled.  Pause for 5 minutes.
5797          */
5798         if (zone->update_disabled) {
5799                 result = ISC_R_FAILURE;
5800                 goto failure;
5801         }
5802
5803         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5804         dns_db_attach(zone->db, &db);
5805         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5806
5807         result = dns_db_newversion(db, &version);
5808         if (result != ISC_R_SUCCESS) {
5809                 dns_zone_log(zone, ISC_LOG_ERROR,
5810                              "zone_nsec3chain:dns_db_newversion -> %s\n",
5811                              dns_result_totext(result));
5812                 goto failure;
5813         }
5814
5815         result = find_zone_keys(zone, db, version, zone->mctx,
5816                                 MAXZONEKEYS, zone_keys, &nkeys);
5817         if (result != ISC_R_SUCCESS) {
5818                 dns_zone_log(zone, ISC_LOG_ERROR,
5819                              "zone_nsec3chain:find_zone_keys -> %s\n",
5820                              dns_result_totext(result));
5821                 goto failure;
5822         }
5823
5824         isc_stdtime_get(&now);
5825         inception = now - 3600; /* Allow for clock skew. */
5826         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5827
5828         /*
5829          * Spread out signatures over time if they happen to be
5830          * clumped.  We don't do this for each add_sigs() call as
5831          * we still want some clustering to occur.
5832          */
5833         isc_random_get(&jitter);
5834         expire = soaexpire - jitter % 3600;
5835
5836         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5837         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5838
5839         /*
5840          * We keep pulling nodes off each iterator in turn until
5841          * we have no more nodes to pull off or we reach the limits
5842          * for this quantum.
5843          */
5844         nodes = zone->nodes;
5845         signatures = zone->signatures;
5846         LOCK_ZONE(zone);
5847         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5848         UNLOCK_ZONE(zone);
5849         first = ISC_TRUE;
5850
5851         if (nsec3chain != NULL)
5852                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
5853         /*
5854          * Generate new NSEC3 chains first.
5855          */
5856         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
5857                 LOCK_ZONE(zone);
5858                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
5859
5860                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5861                 if (nsec3chain->done || nsec3chain->db != zone->db) {
5862                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
5863                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
5864                 }
5865                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5866                 UNLOCK_ZONE(zone);
5867                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
5868                         goto next_addchain;
5869
5870                 /*
5871                  * Possible future db.
5872                  */
5873                 if (nsec3chain->db != db) {
5874                         goto next_addchain;
5875                 }
5876
5877                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
5878                         goto next_addchain;
5879
5880                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
5881
5882                 if (nsec3chain->delete_nsec) {
5883                         delegation = ISC_FALSE;
5884                         dns_dbiterator_pause(nsec3chain->dbiterator);
5885                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
5886                         goto next_addnode;
5887                 }
5888                 /*
5889                  * On the first pass we need to check if the current node
5890                  * has not been obscured.
5891                  */
5892                 delegation = ISC_FALSE;
5893                 unsecure = ISC_FALSE;
5894                 if (first) {
5895                         dns_fixedname_t ffound;
5896                         dns_name_t *found;
5897                         dns_fixedname_init(&ffound);
5898                         found = dns_fixedname_name(&ffound);
5899                         result = dns_db_find(db, name, version,
5900                                              dns_rdatatype_soa,
5901                                              DNS_DBFIND_NOWILD, 0, NULL, found,
5902                                              NULL, NULL);
5903                         if ((result == DNS_R_DELEGATION ||
5904                             result == DNS_R_DNAME) &&
5905                             !dns_name_equal(name, found)) {
5906                                 /*
5907                                  * Remember the obscuring name so that
5908                                  * we skip all obscured names.
5909                                  */
5910                                 dns_name_copy(found, name, NULL);
5911                                 delegation = ISC_TRUE;
5912                                 goto next_addnode;
5913                         }
5914                 }
5915
5916                 /*
5917                  * Check to see if this is a bottom of zone node.
5918                  */
5919                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5920                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
5921                         goto next_addnode;
5922                 if (result != ISC_R_SUCCESS)
5923                         goto failure;
5924
5925                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
5926                         ISC_FALSE;
5927                 for (result = dns_rdatasetiter_first(iterator);
5928                      result == ISC_R_SUCCESS;
5929                      result = dns_rdatasetiter_next(iterator)) {
5930                         dns_rdatasetiter_current(iterator, &rdataset);
5931                         INSIST(rdataset.type != dns_rdatatype_nsec3);
5932                         if (rdataset.type == dns_rdatatype_soa)
5933                                 seen_soa = ISC_TRUE;
5934                         else if (rdataset.type == dns_rdatatype_ns)
5935                                 seen_ns = ISC_TRUE;
5936                         else if (rdataset.type == dns_rdatatype_dname)
5937                                 seen_dname = ISC_TRUE;
5938                         else if (rdataset.type == dns_rdatatype_ds)
5939                                 seen_ds = ISC_TRUE;
5940                         else if (rdataset.type == dns_rdatatype_nsec)
5941                                 seen_nsec = ISC_TRUE;
5942                         dns_rdataset_disassociate(&rdataset);
5943                 }
5944                 dns_rdatasetiter_destroy(&iterator);
5945                 /*
5946                  * Is there a NSEC chain than needs to be cleaned up?
5947                  */
5948                 if (seen_nsec)
5949                         nsec3chain->seen_nsec = ISC_TRUE;
5950                 if (seen_ns && !seen_soa && !seen_ds)
5951                         unsecure = ISC_TRUE;
5952                 if ((seen_ns && !seen_soa) || seen_dname)
5953                         delegation = ISC_TRUE;
5954
5955                 /*
5956                  * Process one node.
5957                  */
5958                 dns_dbiterator_pause(nsec3chain->dbiterator);
5959                 result = dns_nsec3_addnsec3(db, version, name,
5960                                             &nsec3chain->nsec3param,
5961                                             zone->minimum, unsecure,
5962                                             &nsec3_diff);
5963                 if (result != ISC_R_SUCCESS) {
5964                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5965                                      "dns_nsec3_addnsec3 -> %s\n",
5966                                      dns_result_totext(result));
5967                         goto failure;
5968                 }
5969
5970                 /*
5971                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
5972                  * two signatures.  Additionally there will, in general, be
5973                  * two signature generated below.
5974                  *
5975                  * If we are only changing the optout flag the cost is half
5976                  * that of the cost of generating a completely new chain.
5977                  */
5978                 signatures -= 4;
5979
5980                 /*
5981                  * Go onto next node.
5982                  */
5983  next_addnode:
5984                 first = ISC_FALSE;
5985                 dns_db_detachnode(db, &node);
5986                 do {
5987                         result = dns_dbiterator_next(nsec3chain->dbiterator);
5988
5989                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
5990                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
5991                                                        ISC_FALSE, privatetype,
5992                                                        &param_diff));
5993                                 LOCK_ZONE(zone);
5994                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
5995                                                 link);
5996                                 UNLOCK_ZONE(zone);
5997                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
5998                                 goto next_addchain;
5999                         }
6000                         if (result == ISC_R_NOMORE) {
6001                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6002                                 if (nsec3chain->seen_nsec) {
6003                                         CHECK(fixup_nsec3param(db, version,
6004                                                                nsec3chain,
6005                                                                ISC_TRUE,
6006                                                                privatetype,
6007                                                                &param_diff));
6008                                         nsec3chain->delete_nsec = ISC_TRUE;
6009                                         goto same_addchain;
6010                                 }
6011                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
6012                                                        ISC_FALSE, privatetype,
6013                                                        &param_diff));
6014                                 LOCK_ZONE(zone);
6015                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6016                                                 link);
6017                                 UNLOCK_ZONE(zone);
6018                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6019                                 goto next_addchain;
6020                         } else if (result != ISC_R_SUCCESS) {
6021                                 dns_zone_log(zone, ISC_LOG_ERROR,
6022                                              "zone_nsec3chain:"
6023                                              "dns_dbiterator_next -> %s\n",
6024                                              dns_result_totext(result));
6025                                 goto failure;
6026                         } else if (delegation) {
6027                                 dns_dbiterator_current(nsec3chain->dbiterator,
6028                                                        &node, nextname);
6029                                 dns_db_detachnode(db, &node);
6030                                 if (!dns_name_issubdomain(nextname, name))
6031                                         break;
6032                         } else
6033                                 break;
6034                 } while (1);
6035                 continue;
6036
6037  same_addchain:
6038                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6039                 first = ISC_TRUE;
6040                 continue;
6041
6042  next_addchain:
6043                 dns_dbiterator_pause(nsec3chain->dbiterator);
6044                 nsec3chain = nextnsec3chain;
6045                 first = ISC_TRUE;
6046                 if (nsec3chain != NULL)
6047                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
6048         }
6049
6050         /*
6051          * Process removals.
6052          */
6053         LOCK_ZONE(zone);
6054         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6055         UNLOCK_ZONE(zone);
6056         first = ISC_TRUE;
6057         buildnsecchain = ISC_FALSE;
6058         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
6059                 LOCK_ZONE(zone);
6060                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
6061                 UNLOCK_ZONE(zone);
6062
6063                 if (nsec3chain->db != db)
6064                         goto next_removechain;
6065
6066                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
6067                         goto next_removechain;
6068
6069                 /*
6070                  * Work out if we need to build a NSEC chain as a consequence
6071                  * of removing this NSEC3 chain.
6072                  */
6073                 if (first && !updatensec &&
6074                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) {
6075                         result = need_nsec_chain(db, version,
6076                                                  &nsec3chain->nsec3param,
6077                                                  &buildnsecchain);
6078                         if (result != ISC_R_SUCCESS) {
6079                                 dns_zone_log(zone, ISC_LOG_ERROR,
6080                                              "zone_nsec3chain:"
6081                                              "need_nsec_chain -> %s\n",
6082                                              dns_result_totext(result));
6083                                 goto failure;
6084                         }
6085                 }
6086
6087                 if (first)
6088                         dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
6089                                      "buildnsecchain = %u\n", buildnsecchain);
6090
6091                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
6092                 delegation = ISC_FALSE;
6093
6094                 if (!buildnsecchain) {
6095                         /*
6096                          * Delete the NSECPARAM record that matches this chain.
6097                          */
6098                         if (first) {
6099                                 result = fixup_nsec3param(db, version,
6100                                                           nsec3chain,
6101                                                           ISC_TRUE, privatetype,
6102                                                           &param_diff);
6103                                 if (result != ISC_R_SUCCESS) {
6104                                         dns_zone_log(zone, ISC_LOG_ERROR,
6105                                                      "zone_nsec3chain:"
6106                                                      "fixup_nsec3param -> %s\n",
6107                                                      dns_result_totext(result));
6108                                         goto failure;
6109                                 }
6110                         }
6111
6112                         /*
6113                          *  Delete the NSEC3 records.
6114                          */
6115                         result = deletematchingnsec3(db, version, node, name,
6116                                                      &nsec3chain->nsec3param,
6117                                                      &nsec3_diff);
6118                         if (result != ISC_R_SUCCESS) {
6119                                 dns_zone_log(zone, ISC_LOG_ERROR,
6120                                              "zone_nsec3chain:"
6121                                              "deletematchingnsec3 -> %s\n",
6122                                              dns_result_totext(result));
6123                                 goto failure;
6124                         }
6125                         goto next_removenode;
6126                 }
6127
6128                 if (first) {
6129                         dns_fixedname_t ffound;
6130                         dns_name_t *found;
6131                         dns_fixedname_init(&ffound);
6132                         found = dns_fixedname_name(&ffound);
6133                         result = dns_db_find(db, name, version,
6134                                              dns_rdatatype_soa,
6135                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6136                                              NULL, NULL);
6137                         if ((result == DNS_R_DELEGATION ||
6138                              result == DNS_R_DNAME) &&
6139                             !dns_name_equal(name, found)) {
6140                                 /*
6141                                  * Remember the obscuring name so that
6142                                  * we skip all obscured names.
6143                                  */
6144                                 dns_name_copy(found, name, NULL);
6145                                 delegation = ISC_TRUE;
6146                                 goto next_removenode;
6147                         }
6148                 }
6149
6150                 /*
6151                  * Check to see if this is a bottom of zone node.
6152                  */
6153                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6154                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
6155                         goto next_removenode;
6156                 if (result != ISC_R_SUCCESS)
6157                         goto failure;
6158
6159                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6160                         seen_rr = ISC_FALSE;
6161                 for (result = dns_rdatasetiter_first(iterator);
6162                      result == ISC_R_SUCCESS;
6163                      result = dns_rdatasetiter_next(iterator)) {
6164                         dns_rdatasetiter_current(iterator, &rdataset);
6165                         if (rdataset.type == dns_rdatatype_soa)
6166                                 seen_soa = ISC_TRUE;
6167                         else if (rdataset.type == dns_rdatatype_ns)
6168                                 seen_ns = ISC_TRUE;
6169                         else if (rdataset.type == dns_rdatatype_dname)
6170                                 seen_dname = ISC_TRUE;
6171                         else if (rdataset.type == dns_rdatatype_nsec)
6172                                 seen_nsec = ISC_TRUE;
6173                         else if (rdataset.type == dns_rdatatype_nsec3)
6174                                 seen_nsec3 = ISC_TRUE;
6175                         if (rdataset.type != dns_rdatatype_rrsig)
6176                                 seen_rr = ISC_TRUE;
6177                         dns_rdataset_disassociate(&rdataset);
6178                 }
6179                 dns_rdatasetiter_destroy(&iterator);
6180
6181                 if (!seen_rr || seen_nsec3 || seen_nsec)
6182                         goto next_removenode;
6183                 if ((seen_ns && !seen_soa) || seen_dname)
6184                         delegation = ISC_TRUE;
6185
6186                 /*
6187                  * Add a NSEC record except at the origin.
6188                  */
6189                 if (!dns_name_equal(name, dns_db_origin(db))) {
6190                         dns_dbiterator_pause(nsec3chain->dbiterator);
6191                         CHECK(add_nsec(db, version, name, node, zone->minimum,
6192                                        delegation, &nsec_diff));
6193                 }
6194
6195  next_removenode:
6196                 first = ISC_FALSE;
6197                 dns_db_detachnode(db, &node);
6198                 do {
6199                         result = dns_dbiterator_next(nsec3chain->dbiterator);
6200                         if (result == ISC_R_NOMORE && buildnsecchain) {
6201                                 /*
6202                                  * The NSEC chain should now be built.
6203                                  * We can now remove the NSEC3 chain.
6204                                  */
6205                                 updatensec = ISC_TRUE;
6206                                 goto same_removechain;
6207                         }
6208                         if (result == ISC_R_NOMORE) {
6209                                 LOCK_ZONE(zone);
6210                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6211                                                 link);
6212                                 UNLOCK_ZONE(zone);
6213                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6214                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6215                                 result = fixup_nsec3param(db, version,
6216                                                           nsec3chain, ISC_FALSE,
6217                                                           privatetype,
6218                                                           &param_diff);
6219                                 if (result != ISC_R_SUCCESS) {
6220                                         dns_zone_log(zone, ISC_LOG_ERROR,
6221                                                      "zone_nsec3chain:"
6222                                                      "fixup_nsec3param -> %s\n",
6223                                                      dns_result_totext(result));
6224                                         goto failure;
6225                                 }
6226                                 goto next_removechain;
6227                         } else if (result != ISC_R_SUCCESS) {
6228                                 dns_zone_log(zone, ISC_LOG_ERROR,
6229                                              "zone_nsec3chain:"
6230                                              "dns_dbiterator_next -> %s\n",
6231                                              dns_result_totext(result));
6232                                 goto failure;
6233                         } else if (delegation) {
6234                                 dns_dbiterator_current(nsec3chain->dbiterator,
6235                                                        &node, nextname);
6236                                 dns_db_detachnode(db, &node);
6237                                 if (!dns_name_issubdomain(nextname, name))
6238                                         break;
6239                         } else
6240                                 break;
6241                 } while (1);
6242                 continue;
6243
6244  same_removechain:
6245                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6246                 buildnsecchain = ISC_FALSE;
6247                 first = ISC_TRUE;
6248                 continue;
6249
6250  next_removechain:
6251                 dns_dbiterator_pause(nsec3chain->dbiterator);
6252                 nsec3chain = nextnsec3chain;
6253                 first = ISC_TRUE;
6254         }
6255
6256         /*
6257          * We may need to update the NSEC/NSEC3 records for the zone apex.
6258          */
6259         if (!ISC_LIST_EMPTY(param_diff.tuples)) {
6260                 isc_boolean_t rebuild_nsec = ISC_FALSE,
6261                               rebuild_nsec3 = ISC_FALSE;
6262                 result = dns_db_getoriginnode(db, &node);
6263                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6264                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6265                 if (result != ISC_R_SUCCESS) {
6266                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6267                                      "dns_db_allrdatasets -> %s\n",
6268                                      dns_result_totext(result));
6269                         goto failure;
6270                 }
6271                 for (result = dns_rdatasetiter_first(iterator);
6272                      result == ISC_R_SUCCESS;
6273                      result = dns_rdatasetiter_next(iterator)) {
6274                         dns_rdatasetiter_current(iterator, &rdataset);
6275                         if (rdataset.type == dns_rdatatype_nsec)
6276                                 rebuild_nsec = ISC_TRUE;
6277                         if (rdataset.type == dns_rdatatype_nsec3param)
6278                                 rebuild_nsec3 = ISC_TRUE;
6279                         dns_rdataset_disassociate(&rdataset);
6280                 }
6281                 dns_rdatasetiter_destroy(&iterator);
6282                 dns_db_detachnode(db, &node);
6283
6284                 if (rebuild_nsec) {
6285                         if (nsec3chain != NULL)
6286                                 dns_dbiterator_pause(nsec3chain->dbiterator);
6287                         result = updatesecure(db, version, &zone->origin,
6288                                               zone->minimum, ISC_TRUE,
6289                                               &nsec_diff);
6290                         if (result != ISC_R_SUCCESS) {
6291                                 dns_zone_log(zone, ISC_LOG_ERROR,
6292                                              "zone_nsec3chain:"
6293                                              "updatesecure -> %s\n",
6294                                              dns_result_totext(result));
6295                                 goto failure;
6296                         }
6297                 }
6298                 if (rebuild_nsec3) {
6299                         result = dns_nsec3_addnsec3s(db, version,
6300                                                      dns_db_origin(db),
6301                                                      zone->minimum, ISC_FALSE,
6302                                                      &nsec3_diff);
6303                         if (result != ISC_R_SUCCESS) {
6304                                 dns_zone_log(zone, ISC_LOG_ERROR,
6305                                              "zone_nsec3chain:"
6306                                              "dns_nsec3_addnsec3s -> %s\n",
6307                                              dns_result_totext(result));
6308                                 goto failure;
6309                         }
6310                 }
6311         }
6312
6313         /*
6314          * Add / update signatures for the NSEC3 records.
6315          */
6316         result = update_sigs(&nsec3_diff, db, version, zone_keys,
6317                              nkeys, zone, inception, expire, now,
6318                              check_ksk, keyset_kskonly, &sig_diff);
6319         if (result != ISC_R_SUCCESS) {
6320                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6321                              "update_sigs -> %s\n", dns_result_totext(result));
6322                 goto failure;
6323         }
6324
6325         /*
6326          * We have changed the NSEC3PARAM or private RRsets
6327          * above so we need to update the signatures.
6328          */
6329         result = update_sigs(&param_diff, db, version, zone_keys,
6330                              nkeys, zone, inception, expire, now,
6331                              check_ksk, keyset_kskonly, &sig_diff);
6332         if (result != ISC_R_SUCCESS) {
6333                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6334                              "update_sigs -> %s\n", dns_result_totext(result));
6335                 goto failure;
6336         }
6337
6338         if (updatensec) {
6339                 if (nsec3chain != NULL)
6340                         dns_dbiterator_pause(nsec3chain->dbiterator);
6341                 result = updatesecure(db, version, &zone->origin,
6342                                       zone->minimum, ISC_FALSE, &nsec_diff);
6343                 if (result != ISC_R_SUCCESS) {
6344                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6345                                      "updatesecure -> %s\n",
6346                                      dns_result_totext(result));
6347                         goto failure;
6348                 }
6349         }
6350
6351         result = update_sigs(&nsec_diff, db, version, zone_keys,
6352                              nkeys, zone, inception, expire, now,
6353                              check_ksk, keyset_kskonly, &sig_diff);
6354         if (result != ISC_R_SUCCESS) {
6355                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6356                              "update_sigs -> %s\n", dns_result_totext(result));
6357                 goto failure;
6358         }
6359
6360         /*
6361          * If we made no effective changes to the zone then we can just
6362          * cleanup otherwise we need to increment the serial.
6363          */
6364         if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
6365                 goto done;
6366
6367         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6368                           &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
6369         if (result != ISC_R_SUCCESS) {
6370                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6371                              "del_sigs -> %s\n", dns_result_totext(result));
6372                 goto failure;
6373         }
6374
6375         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6376         if (result != ISC_R_SUCCESS) {
6377                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6378                              "increment_soa_serial -> %s\n",
6379                              dns_result_totext(result));
6380                 goto failure;
6381         }
6382
6383         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6384                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6385                           soaexpire, check_ksk, keyset_kskonly);
6386         if (result != ISC_R_SUCCESS) {
6387                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6388                              "add_sigs -> %s\n", dns_result_totext(result));
6389                 goto failure;
6390         }
6391
6392         /* Write changes to journal file. */
6393         CHECK(zone_journal(zone, &sig_diff, "zone_nsec3chain"));
6394
6395         LOCK_ZONE(zone);
6396         zone_needdump(zone, DNS_DUMP_DELAY);
6397         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6398         UNLOCK_ZONE(zone);
6399
6400  done:
6401         /*
6402          * Pause all iterators so that dns_db_closeversion() can succeed.
6403          */
6404         LOCK_ZONE(zone);
6405         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6406              nsec3chain != NULL;
6407              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6408                 dns_dbiterator_pause(nsec3chain->dbiterator);
6409         UNLOCK_ZONE(zone);
6410
6411         /*
6412          * Everything has succeeded. Commit the changes.
6413          */
6414         dns_db_closeversion(db, &version, ISC_TRUE);
6415
6416         /*
6417          * Everything succeeded so we can clean these up now.
6418          */
6419         nsec3chain = ISC_LIST_HEAD(cleanup);
6420         while (nsec3chain != NULL) {
6421                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6422                 dns_db_detach(&nsec3chain->db);
6423                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
6424                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6425                 nsec3chain = ISC_LIST_HEAD(cleanup);
6426         }
6427
6428         set_resigntime(zone);
6429
6430  failure:
6431         if (result != ISC_R_SUCCESS)
6432                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s\n",
6433                              dns_result_totext(result));
6434         /*
6435          * On error roll back the current nsec3chain.
6436          */
6437         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
6438                 if (nsec3chain->done) {
6439                         dns_db_detach(&nsec3chain->db);
6440                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
6441                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6442                 } else {
6443                         result = dns_dbiterator_first(nsec3chain->dbiterator);
6444                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6445                         dns_dbiterator_pause(nsec3chain->dbiterator);
6446                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6447                 }
6448         }
6449
6450         /*
6451          * Rollback the cleanup list.
6452          */
6453         nsec3chain = ISC_LIST_TAIL(cleanup);
6454         while (nsec3chain != NULL) {
6455                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6456                 if (nsec3chain->done) {
6457                         dns_db_detach(&nsec3chain->db);
6458                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
6459                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6460                 } else {
6461                         LOCK_ZONE(zone);
6462                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
6463                         UNLOCK_ZONE(zone);
6464                         result = dns_dbiterator_first(nsec3chain->dbiterator);
6465                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
6466                         dns_dbiterator_pause(nsec3chain->dbiterator);
6467                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6468                 }
6469                 nsec3chain = ISC_LIST_TAIL(cleanup);
6470         }
6471
6472         LOCK_ZONE(zone);
6473         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6474              nsec3chain != NULL;
6475              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6476                 dns_dbiterator_pause(nsec3chain->dbiterator);
6477         UNLOCK_ZONE(zone);
6478
6479         dns_diff_clear(&param_diff);
6480         dns_diff_clear(&nsec3_diff);
6481         dns_diff_clear(&nsec_diff);
6482         dns_diff_clear(&sig_diff);
6483
6484         if (iterator != NULL)
6485                 dns_rdatasetiter_destroy(&iterator);
6486
6487         for (i = 0; i < nkeys; i++)
6488                 dst_key_free(&zone_keys[i]);
6489
6490         if (node != NULL)
6491                 dns_db_detachnode(db, &node);
6492         if (version != NULL) {
6493                 dns_db_closeversion(db, &version, ISC_FALSE);
6494                 dns_db_detach(&db);
6495         } else if (db != NULL)
6496                 dns_db_detach(&db);
6497
6498         LOCK_ZONE(zone);
6499         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
6500                 isc_interval_t i;
6501                 if (zone->update_disabled || result != ISC_R_SUCCESS)
6502                         isc_interval_set(&i, 60, 0);            /* 1 minute */
6503                 else
6504                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
6505                 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
6506         } else
6507                 isc_time_settoepoch(&zone->nsec3chaintime);
6508         UNLOCK_ZONE(zone);
6509 }
6510
6511 static isc_result_t
6512 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6513         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
6514         isc_uint16_t keyid, dns_diff_t *diff)
6515 {
6516         dns_rdata_rrsig_t rrsig;
6517         dns_rdataset_t rdataset;
6518         dns_rdatasetiter_t *iterator = NULL;
6519         isc_result_t result;
6520
6521         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6522         if (result != ISC_R_SUCCESS) {
6523                 if (result == ISC_R_NOTFOUND)
6524                         result = ISC_R_SUCCESS;
6525                 return (result);
6526         }
6527
6528         dns_rdataset_init(&rdataset);
6529         for (result = dns_rdatasetiter_first(iterator);
6530              result == ISC_R_SUCCESS;
6531              result = dns_rdatasetiter_next(iterator)) {
6532                 dns_rdatasetiter_current(iterator, &rdataset);
6533                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
6534                         for (result = dns_rdataset_first(&rdataset);
6535                              result == ISC_R_SUCCESS;
6536                              result = dns_rdataset_next(&rdataset)) {
6537                                 dns_rdata_t rdata = DNS_RDATA_INIT;
6538                                 dns_rdataset_current(&rdataset, &rdata);
6539                                 CHECK(update_one_rr(db, version, diff,
6540                                                     DNS_DIFFOP_DEL, name,
6541                                                     rdataset.ttl, &rdata));
6542                         }
6543                         if (result != ISC_R_NOMORE)
6544                                 goto failure;
6545                         dns_rdataset_disassociate(&rdataset);
6546                         continue;
6547                 }
6548                 if (rdataset.type != dns_rdatatype_rrsig) {
6549                         dns_rdataset_disassociate(&rdataset);
6550                         continue;
6551                 }
6552                 for (result = dns_rdataset_first(&rdataset);
6553                      result == ISC_R_SUCCESS;
6554                      result = dns_rdataset_next(&rdataset)) {
6555                         dns_rdata_t rdata = DNS_RDATA_INIT;
6556                         dns_rdataset_current(&rdataset, &rdata);
6557                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
6558                         if (rrsig.algorithm != algorithm ||
6559                             rrsig.keyid != keyid)
6560                                 continue;
6561                         CHECK(update_one_rr(db, version, diff,
6562                                             DNS_DIFFOP_DELRESIGN, name,
6563                                             rdataset.ttl, &rdata));
6564                 }
6565                 dns_rdataset_disassociate(&rdataset);
6566                 if (result != ISC_R_NOMORE)
6567                         break;
6568         }
6569         if (result == ISC_R_NOMORE)
6570                 result = ISC_R_SUCCESS;
6571  failure:
6572         if (dns_rdataset_isassociated(&rdataset))
6573                 dns_rdataset_disassociate(&rdataset);
6574         dns_rdatasetiter_destroy(&iterator);
6575         return (result);
6576 }
6577
6578 /*
6579  * Incrementally sign the zone using the keys requested.
6580  * Builds the NSEC chain if required.
6581  */
6582 static void
6583 zone_sign(dns_zone_t *zone) {
6584         dns_db_t *db = NULL;
6585         dns_dbnode_t *node = NULL;
6586         dns_dbversion_t *version = NULL;
6587         dns_diff_t sig_diff;
6588         dns_diff_t post_diff;
6589         dns_fixedname_t fixed;
6590         dns_fixedname_t nextfixed;
6591         dns_name_t *name, *nextname;
6592         dns_rdataset_t rdataset;
6593         dns_signing_t *signing, *nextsigning;
6594         dns_signinglist_t cleanup;
6595         dst_key_t *zone_keys[MAXZONEKEYS];
6596         isc_int32_t signatures;
6597         isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
6598         isc_boolean_t commit = ISC_FALSE;
6599         isc_boolean_t delegation;
6600         isc_boolean_t build_nsec = ISC_FALSE;
6601         isc_boolean_t build_nsec3 = ISC_FALSE;
6602         isc_boolean_t first;
6603         isc_result_t result;
6604         isc_stdtime_t now, inception, soaexpire, expire;
6605         isc_uint32_t jitter;
6606         unsigned int i, j;
6607         unsigned int nkeys = 0;
6608         isc_uint32_t nodes;
6609
6610         dns_rdataset_init(&rdataset);
6611         dns_fixedname_init(&fixed);
6612         name = dns_fixedname_name(&fixed);
6613         dns_fixedname_init(&nextfixed);
6614         nextname = dns_fixedname_name(&nextfixed);
6615         dns_diff_init(zone->mctx, &sig_diff);
6616         sig_diff.resign = zone->sigresigninginterval;
6617         dns_diff_init(zone->mctx, &post_diff);
6618         ISC_LIST_INIT(cleanup);
6619
6620         /*
6621          * Updates are disabled.  Pause for 5 minutes.
6622          */
6623         if (zone->update_disabled) {
6624                 result = ISC_R_FAILURE;
6625                 goto failure;
6626         }
6627
6628         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6629         dns_db_attach(zone->db, &db);
6630         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6631
6632         result = dns_db_newversion(db, &version);
6633         if (result != ISC_R_SUCCESS) {
6634                 dns_zone_log(zone, ISC_LOG_ERROR,
6635                              "zone_sign:dns_db_newversion -> %s\n",
6636                              dns_result_totext(result));
6637                 goto failure;
6638         }
6639
6640         result = find_zone_keys(zone, db, version, zone->mctx,
6641                                 MAXZONEKEYS, zone_keys, &nkeys);
6642         if (result != ISC_R_SUCCESS) {
6643                 dns_zone_log(zone, ISC_LOG_ERROR,
6644                              "zone_sign:find_zone_keys -> %s\n",
6645                              dns_result_totext(result));
6646                 goto failure;
6647         }
6648
6649         isc_stdtime_get(&now);
6650         inception = now - 3600; /* Allow for clock skew. */
6651         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6652
6653         /*
6654          * Spread out signatures over time if they happen to be
6655          * clumped.  We don't do this for each add_sigs() call as
6656          * we still want some clustering to occur.
6657          */
6658         isc_random_get(&jitter);
6659         expire = soaexpire - jitter % 3600;
6660
6661         /*
6662          * We keep pulling nodes off each iterator in turn until
6663          * we have no more nodes to pull off or we reach the limits
6664          * for this quantum.
6665          */
6666         nodes = zone->nodes;
6667         signatures = zone->signatures;
6668         signing = ISC_LIST_HEAD(zone->signing);
6669         first = ISC_TRUE;
6670
6671         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6672         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6673
6674         /* Determine which type of chain to build */
6675         CHECK(dns_private_chains(db, version, zone->privatetype,
6676                                  &build_nsec, &build_nsec3));
6677
6678         /* If neither chain is found, default to NSEC */
6679         if (!build_nsec && !build_nsec3)
6680                 build_nsec = ISC_TRUE;
6681
6682         while (signing != NULL && nodes-- > 0 && signatures > 0) {
6683                 nextsigning = ISC_LIST_NEXT(signing, link);
6684
6685                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6686                 if (signing->done || signing->db != zone->db) {
6687                         /*
6688                          * The zone has been reloaded.  We will have
6689                          * created new signings as part of the reload
6690                          * process so we can destroy this one.
6691                          */
6692                         ISC_LIST_UNLINK(zone->signing, signing, link);
6693                         ISC_LIST_APPEND(cleanup, signing, link);
6694                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6695                         goto next_signing;
6696                 }
6697                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6698
6699                 if (signing->db != db)
6700                         goto next_signing;
6701
6702                 delegation = ISC_FALSE;
6703
6704                 if (first && signing->delete) {
6705                         /*
6706                          * Remove the key we are deleting from consideration.
6707                          */
6708                         for (i = 0, j = 0; i < nkeys; i++) {
6709                                 /*
6710                                  * Find the key we want to remove.
6711                                  */
6712                                 if (ALG(zone_keys[i]) == signing->algorithm &&
6713                                     dst_key_id(zone_keys[i]) == signing->keyid)
6714                                 {
6715                                         if (KSK(zone_keys[i]))
6716                                                 dst_key_free(&zone_keys[i]);
6717                                         continue;
6718                                 }
6719                                 zone_keys[j] = zone_keys[i];
6720                                 j++;
6721                         }
6722                         nkeys = j;
6723                 }
6724
6725                 dns_dbiterator_current(signing->dbiterator, &node, name);
6726
6727                 if (signing->delete) {
6728                         dns_dbiterator_pause(signing->dbiterator);
6729                         CHECK(del_sig(db, version, name, node, nkeys,
6730                                       signing->algorithm, signing->keyid,
6731                                       &sig_diff));
6732                 }
6733
6734                 /*
6735                  * On the first pass we need to check if the current node
6736                  * has not been obscured.
6737                  */
6738                 if (first) {
6739                         dns_fixedname_t ffound;
6740                         dns_name_t *found;
6741                         dns_fixedname_init(&ffound);
6742                         found = dns_fixedname_name(&ffound);
6743                         result = dns_db_find(db, name, version,
6744                                              dns_rdatatype_soa,
6745                                              DNS_DBFIND_NOWILD, 0, NULL, found,
6746                                              NULL, NULL);
6747                         if ((result == DNS_R_DELEGATION ||
6748                             result == DNS_R_DNAME) &&
6749                             !dns_name_equal(name, found)) {
6750                                 /*
6751                                  * Remember the obscuring name so that
6752                                  * we skip all obscured names.
6753                                  */
6754                                 dns_name_copy(found, name, NULL);
6755                                 delegation = ISC_TRUE;
6756                                 goto next_node;
6757                         }
6758                 }
6759
6760                 /*
6761                  * Process one node.
6762                  */
6763                 dns_dbiterator_pause(signing->dbiterator);
6764                 for (i = 0; i < nkeys; i++) {
6765                         isc_boolean_t both = ISC_FALSE;
6766
6767                         /*
6768                          * Find the keys we want to sign with.
6769                          */
6770                         if (!dst_key_isprivate(zone_keys[i]))
6771                                 continue;
6772
6773                         /*
6774                          * When adding look for the specific key.
6775                          */
6776                         if (!signing->delete &&
6777                             (dst_key_alg(zone_keys[i]) != signing->algorithm ||
6778                              dst_key_id(zone_keys[i]) != signing->keyid))
6779                                 continue;
6780
6781                         /*
6782                          * When deleting make sure we are properly signed
6783                          * with the algorithm that was being removed.
6784                          */
6785                         if (signing->delete &&
6786                             ALG(zone_keys[i]) != signing->algorithm)
6787                                 continue;
6788
6789                         /*
6790                          * Do we do KSK processing?
6791                          */
6792                         if (check_ksk && !REVOKE(zone_keys[i])) {
6793                                 isc_boolean_t have_ksk, have_nonksk;
6794                                 if (KSK(zone_keys[i])) {
6795                                         have_ksk = ISC_TRUE;
6796                                         have_nonksk = ISC_FALSE;
6797                                 } else {
6798                                         have_ksk = ISC_FALSE;
6799                                         have_nonksk = ISC_TRUE;
6800                                 }
6801                                 for (j = 0; j < nkeys; j++) {
6802                                         if (j == i ||
6803                                             ALG(zone_keys[i]) !=
6804                                             ALG(zone_keys[j]))
6805                                                 continue;
6806                                         if (REVOKE(zone_keys[j]))
6807                                                 continue;
6808                                         if (KSK(zone_keys[j]))
6809                                                 have_ksk = ISC_TRUE;
6810                                         else
6811                                                 have_nonksk = ISC_TRUE;
6812                                         both = have_ksk && have_nonksk;
6813                                         if (both)
6814                                                 break;
6815                                 }
6816                         }
6817                         if (both || REVOKE(zone_keys[i]))
6818                                 is_ksk = KSK(zone_keys[i]);
6819                         else
6820                                 is_ksk = ISC_FALSE;
6821
6822                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
6823                                           build_nsec, zone_keys[i], inception,
6824                                           expire, zone->minimum, is_ksk,
6825                                           ISC_TF(both && keyset_kskonly),
6826                                           &delegation, &sig_diff,
6827                                           &signatures, zone->mctx));
6828                         /*
6829                          * If we are adding we are done.  Look for other keys
6830                          * of the same algorithm if deleting.
6831                          */
6832                         if (!signing->delete)
6833                                 break;
6834                 }
6835
6836                 /*
6837                  * Go onto next node.
6838                  */
6839  next_node:
6840                 first = ISC_FALSE;
6841                 dns_db_detachnode(db, &node);
6842                 do {
6843                         result = dns_dbiterator_next(signing->dbiterator);
6844                         if (result == ISC_R_NOMORE) {
6845                                 ISC_LIST_UNLINK(zone->signing, signing, link);
6846                                 ISC_LIST_APPEND(cleanup, signing, link);
6847                                 dns_dbiterator_pause(signing->dbiterator);
6848                                 if (nkeys != 0 && build_nsec) {
6849                                         /*
6850                                          * We have finished regenerating the
6851                                          * zone with a zone signing key.
6852                                          * The NSEC chain is now complete and
6853                                          * there is a full set of signatures
6854                                          * for the zone.  We can now clear the
6855                                          * OPT bit from the NSEC record.
6856                                          */
6857                                         result = updatesecure(db, version,
6858                                                               &zone->origin,
6859                                                               zone->minimum,
6860                                                               ISC_FALSE,
6861                                                               &post_diff);
6862                                         if (result != ISC_R_SUCCESS) {
6863                                                 dns_zone_log(zone,
6864                                                              ISC_LOG_ERROR,
6865                                                     "updatesecure -> %s\n",
6866                                                     dns_result_totext(result));
6867                                                 goto failure;
6868                                         }
6869                                 }
6870                                 result = updatesignwithkey(zone, signing,
6871                                                            version,
6872                                                            build_nsec3,
6873                                                            zone->minimum,
6874                                                            &post_diff);
6875                                 if (result != ISC_R_SUCCESS) {
6876                                         dns_zone_log(zone, ISC_LOG_ERROR,
6877                                                      "updatesignwithkey "
6878                                                      "-> %s\n",
6879                                                      dns_result_totext(result));
6880                                         goto failure;
6881                                 }
6882                                 build_nsec = ISC_FALSE;
6883                                 goto next_signing;
6884                         } else if (result != ISC_R_SUCCESS) {
6885                                 dns_zone_log(zone, ISC_LOG_ERROR,
6886                                         "zone_sign:dns_dbiterator_next -> %s\n",
6887                                              dns_result_totext(result));
6888                                 goto failure;
6889                         } else if (delegation) {
6890                                 dns_dbiterator_current(signing->dbiterator,
6891                                                        &node, nextname);
6892                                 dns_db_detachnode(db, &node);
6893                                 if (!dns_name_issubdomain(nextname, name))
6894                                         break;
6895                         } else
6896                                 break;
6897                 } while (1);
6898                 continue;
6899
6900  next_signing:
6901                 dns_dbiterator_pause(signing->dbiterator);
6902                 signing = nextsigning;
6903                 first = ISC_TRUE;
6904         }
6905
6906         if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
6907                 result = update_sigs(&post_diff, db, version, zone_keys,
6908                                      nkeys, zone, inception, expire, now,
6909                                      check_ksk, keyset_kskonly, &sig_diff);
6910                 if (result != ISC_R_SUCCESS) {
6911                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
6912                                      "update_sigs -> %s\n",
6913                                      dns_result_totext(result));
6914                         goto failure;
6915                 }
6916         }
6917
6918         /*
6919          * Have we changed anything?
6920          */
6921         if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) {
6922                 result = ISC_R_SUCCESS;
6923                 goto pauseall;
6924         }
6925
6926         commit = ISC_TRUE;
6927
6928         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6929                           &sig_diff, zone_keys, nkeys, now, ISC_FALSE);
6930         if (result != ISC_R_SUCCESS) {
6931                 dns_zone_log(zone, ISC_LOG_ERROR,
6932                              "zone_sign:del_sigs -> %s\n",
6933                              dns_result_totext(result));
6934                 goto failure;
6935         }
6936
6937         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6938         if (result != ISC_R_SUCCESS) {
6939                 dns_zone_log(zone, ISC_LOG_ERROR,
6940                              "zone_sign:increment_soa_serial -> %s\n",
6941                              dns_result_totext(result));
6942                 goto failure;
6943         }
6944
6945         /*
6946          * Generate maximum life time signatures so that the above loop
6947          * termination is sensible.
6948          */
6949         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6950                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6951                           soaexpire, check_ksk, keyset_kskonly);
6952         if (result != ISC_R_SUCCESS) {
6953                 dns_zone_log(zone, ISC_LOG_ERROR,
6954                              "zone_sign:add_sigs -> %s\n",
6955                              dns_result_totext(result));
6956                 goto failure;
6957         }
6958
6959         /*
6960          * Write changes to journal file.
6961          */
6962         CHECK(zone_journal(zone, &sig_diff, "zone_sign"));
6963
6964  pauseall:
6965         /*
6966          * Pause all iterators so that dns_db_closeversion() can succeed.
6967          */
6968         for (signing = ISC_LIST_HEAD(zone->signing);
6969              signing != NULL;
6970              signing = ISC_LIST_NEXT(signing, link))
6971                 dns_dbiterator_pause(signing->dbiterator);
6972
6973         for (signing = ISC_LIST_HEAD(cleanup);
6974              signing != NULL;
6975              signing = ISC_LIST_NEXT(signing, link))
6976                 dns_dbiterator_pause(signing->dbiterator);
6977
6978         /*
6979          * Everything has succeeded. Commit the changes.
6980          */
6981         dns_db_closeversion(db, &version, commit);
6982
6983         /*
6984          * Everything succeeded so we can clean these up now.
6985          */
6986         signing = ISC_LIST_HEAD(cleanup);
6987         while (signing != NULL) {
6988                 ISC_LIST_UNLINK(cleanup, signing, link);
6989                 dns_db_detach(&signing->db);
6990                 dns_dbiterator_destroy(&signing->dbiterator);
6991                 isc_mem_put(zone->mctx, signing, sizeof *signing);
6992                 signing = ISC_LIST_HEAD(cleanup);
6993         }
6994
6995         set_resigntime(zone);
6996
6997         if (commit) {
6998                 LOCK_ZONE(zone);
6999                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7000                 zone_needdump(zone, DNS_DUMP_DELAY);
7001                 UNLOCK_ZONE(zone);
7002         }
7003
7004  failure:
7005         /*
7006          * Rollback the cleanup list.
7007          */
7008         signing = ISC_LIST_HEAD(cleanup);
7009         while (signing != NULL) {
7010                 ISC_LIST_UNLINK(cleanup, signing, link);
7011                 ISC_LIST_PREPEND(zone->signing, signing, link);
7012                 dns_dbiterator_first(signing->dbiterator);
7013                 dns_dbiterator_pause(signing->dbiterator);
7014                 signing = ISC_LIST_HEAD(cleanup);
7015         }
7016
7017         for (signing = ISC_LIST_HEAD(zone->signing);
7018              signing != NULL;
7019              signing = ISC_LIST_NEXT(signing, link))
7020                 dns_dbiterator_pause(signing->dbiterator);
7021
7022         dns_diff_clear(&sig_diff);
7023
7024         for (i = 0; i < nkeys; i++)
7025                 dst_key_free(&zone_keys[i]);
7026
7027         if (node != NULL)
7028                 dns_db_detachnode(db, &node);
7029
7030         if (version != NULL) {
7031                 dns_db_closeversion(db, &version, ISC_FALSE);
7032                 dns_db_detach(&db);
7033         } else if (db != NULL)
7034                 dns_db_detach(&db);
7035
7036         if (ISC_LIST_HEAD(zone->signing) != NULL) {
7037                 isc_interval_t i;
7038                 if (zone->update_disabled || result != ISC_R_SUCCESS)
7039                         isc_interval_set(&i, 60, 0);            /* 1 minute */
7040                 else
7041                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
7042                 isc_time_nowplusinterval(&zone->signingtime, &i);
7043         } else
7044                 isc_time_settoepoch(&zone->signingtime);
7045 }
7046
7047 static void
7048 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
7049               unsigned char *data, int size) {
7050         dns_rdata_dnskey_t dnskey;
7051         dns_rdata_keydata_t keydata;
7052         isc_buffer_t buf;
7053
7054         dns_rdata_reset(target);
7055         isc_buffer_init(&buf, data, size);
7056
7057         switch (rr->type) {
7058             case dns_rdatatype_dnskey:
7059                 dns_rdata_tostruct(rr, &dnskey, NULL);
7060                 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
7061                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7062                                      &dnskey, &buf);
7063                 break;
7064             case dns_rdatatype_keydata:
7065                 dns_rdata_tostruct(rr, &keydata, NULL);
7066                 dns_keydata_todnskey(&keydata, &dnskey, NULL);
7067                 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
7068                                      &dnskey, &buf);
7069                 break;
7070             default:
7071                 INSIST(0);
7072         }
7073 }
7074
7075 /*
7076  * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
7077  * a KEYDATA rdataset from the key zone.
7078  *
7079  * 'rr' contains either a DNSKEY record, or a KEYDATA record
7080  *
7081  * After normalizing keys to the same format (DNSKEY, with revoke bit
7082  * cleared), return ISC_TRUE if a key that matches 'rr' is found in
7083  * 'rdset', or ISC_FALSE if not.
7084  */
7085
7086 static isc_boolean_t
7087 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
7088         unsigned char data1[4096], data2[4096];
7089         dns_rdata_t rdata, rdata1, rdata2;
7090         isc_result_t result;
7091
7092         dns_rdata_init(&rdata);
7093         dns_rdata_init(&rdata1);
7094         dns_rdata_init(&rdata2);
7095
7096         normalize_key(rr, &rdata1, data1, sizeof(data1));
7097
7098         for (result = dns_rdataset_first(rdset);
7099              result == ISC_R_SUCCESS;
7100              result = dns_rdataset_next(rdset)) {
7101                 dns_rdata_reset(&rdata);
7102                 dns_rdataset_current(rdset, &rdata);
7103                 normalize_key(&rdata, &rdata2, data2, sizeof(data2));
7104                 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
7105                         return (ISC_TRUE);
7106         }
7107
7108         return (ISC_FALSE);
7109 }
7110
7111 /*
7112  * Calculate the refresh interval for a keydata zone, per
7113  * RFC5011: MAX(1 hr,
7114  *              MIN(15 days,
7115  *                  1/2 * OrigTTL,
7116  *                  1/2 * RRSigExpirationInterval))
7117  * or for retries: MAX(1 hr,
7118  *                     MIN(1 day,
7119  *                         1/10 * OrigTTL,
7120  *                         1/10 * RRSigExpirationInterval))
7121  */
7122 static inline isc_stdtime_t
7123 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
7124         isc_result_t result;
7125         isc_uint32_t t;
7126         dns_rdataset_t *rdset;
7127         dns_rdata_t sigrr = DNS_RDATA_INIT;
7128         dns_rdata_sig_t sig;
7129         isc_stdtime_t now;
7130
7131         isc_stdtime_get(&now);
7132
7133         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7134                 rdset = &kfetch->dnskeysigset;
7135         else
7136                 return (now + HOUR);
7137
7138         result = dns_rdataset_first(rdset);
7139         if (result != ISC_R_SUCCESS)
7140                 return (now + HOUR);
7141
7142         dns_rdataset_current(rdset, &sigrr);
7143         result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7144         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7145
7146         if (!retry) {
7147                 t = sig.originalttl / 2;
7148
7149                 if (isc_serial_gt(sig.timeexpire, now)) {
7150                         isc_uint32_t exp = (sig.timeexpire - now) / 2;
7151                         if (t > exp)
7152                                 t = exp;
7153                 }
7154
7155                 if (t > (15*DAY))
7156                         t = (15*DAY);
7157
7158                 if (t < HOUR)
7159                         t = HOUR;
7160         } else {
7161                 t = sig.originalttl / 10;
7162
7163                 if (isc_serial_gt(sig.timeexpire, now)) {
7164                         isc_uint32_t exp = (sig.timeexpire - now) / 10;
7165                         if (t > exp)
7166                                 t = exp;
7167                 }
7168
7169                 if (t > DAY)
7170                         t = DAY;
7171
7172                 if (t < HOUR)
7173                         t = HOUR;
7174         }
7175
7176         return (now + t);
7177 }
7178
7179 /*
7180  * This routine is called when no changes are needed in a KEYDATA
7181  * record except to simply update the refresh timer.  Caller should
7182  * hold zone lock.
7183  */
7184 static isc_result_t
7185 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
7186 {
7187         isc_result_t result;
7188         isc_buffer_t keyb;
7189         unsigned char key_buf[4096];
7190         dns_rdata_t rdata = DNS_RDATA_INIT;
7191         dns_rdata_keydata_t keydata;
7192         dns_name_t *name;
7193         dns_zone_t *zone = kfetch->zone;
7194         isc_stdtime_t now;
7195
7196         name = dns_fixedname_name(&kfetch->name);
7197         isc_stdtime_get(&now);
7198
7199         for (result = dns_rdataset_first(&kfetch->keydataset);
7200              result == ISC_R_SUCCESS;
7201              result = dns_rdataset_next(&kfetch->keydataset)) {
7202                 dns_rdata_reset(&rdata);
7203                 dns_rdataset_current(&kfetch->keydataset, &rdata);
7204
7205                 /* Delete old version */
7206                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
7207                                     name, 0, &rdata));
7208
7209                 /* Update refresh timer */
7210                 CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
7211                 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
7212                 set_refreshkeytimer(zone, &keydata, now);
7213
7214                 dns_rdata_reset(&rdata);
7215                 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7216                 CHECK(dns_rdata_fromstruct(&rdata,
7217                                            zone->rdclass, dns_rdatatype_keydata,
7218                                            &keydata, &keyb));
7219
7220                 /* Insert updated version */
7221                 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
7222                                     name, 0, &rdata));
7223         }
7224         result = ISC_R_SUCCESS;
7225   failure:
7226         return (result);
7227 }
7228
7229 /*
7230  * Verify that DNSKEY set is signed by the key specified in 'keydata'.
7231  */
7232 static isc_boolean_t
7233 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
7234         isc_result_t result;
7235         dns_name_t *keyname;
7236         isc_mem_t *mctx;
7237         dns_rdata_t sigrr = DNS_RDATA_INIT;
7238         dns_rdata_t rr = DNS_RDATA_INIT;
7239         dns_rdata_rrsig_t sig;
7240         dns_rdata_dnskey_t dnskey;
7241         dst_key_t *dstkey = NULL;
7242         unsigned char key_buf[4096];
7243         isc_buffer_t keyb;
7244         isc_boolean_t answer = ISC_FALSE;
7245
7246         REQUIRE(kfetch != NULL && keydata != NULL);
7247         REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
7248
7249         keyname = dns_fixedname_name(&kfetch->name);
7250         mctx = kfetch->zone->view->mctx;
7251
7252         /* Generate a key from keydata */
7253         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7254         dns_keydata_todnskey(keydata, &dnskey, NULL);
7255         dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
7256                                      &dnskey, &keyb);
7257         result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
7258         if (result != ISC_R_SUCCESS)
7259                 return (ISC_FALSE);
7260
7261         /* See if that key generated any of the signatures */
7262         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7263              result == ISC_R_SUCCESS;
7264              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7265                 dns_fixedname_t fixed;
7266                 dns_fixedname_init(&fixed);
7267
7268                 dns_rdata_reset(&sigrr);
7269                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7270                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7271                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7272
7273                 if (dst_key_alg(dstkey) == sig.algorithm &&
7274                     (dst_key_id(dstkey) == sig.keyid ||
7275                      (sig.algorithm != 1 && sig.keyid ==
7276                        ((dst_key_id(dstkey) + 128) & 0xffff)))) {
7277                         result = dns_dnssec_verify2(keyname,
7278                                             &kfetch->dnskeyset,
7279                                             dstkey, ISC_FALSE, mctx, &sigrr,
7280                                             dns_fixedname_name(&fixed));
7281
7282                         dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
7283                                      "Confirm revoked DNSKEY is self-signed: "
7284                                      "%s", dns_result_totext(result));
7285
7286                         if (result == ISC_R_SUCCESS) {
7287                                 answer = ISC_TRUE;
7288                                 break;
7289                         }
7290                 }
7291         }
7292
7293         dst_key_free(&dstkey);
7294         return (answer);
7295 }
7296
7297 /*
7298  * A DNSKEY set has been fetched from the zone apex of a zone whose trust
7299  * anchors are being managed; scan the keyset, and update the key zone and the
7300  * local trust anchors according to RFC5011.
7301  */
7302 static void
7303 keyfetch_done(isc_task_t *task, isc_event_t *event) {
7304         isc_result_t result, eresult;
7305         dns_fetchevent_t *devent;
7306         dns_keyfetch_t *kfetch;
7307         dns_zone_t *zone;
7308         isc_mem_t *mctx = NULL;
7309         dns_keytable_t *secroots = NULL;
7310         dns_dbversion_t *ver = NULL;
7311         dns_diff_t diff;
7312         isc_boolean_t alldone = ISC_FALSE;
7313         isc_boolean_t commit = ISC_FALSE;
7314         dns_name_t *keyname;
7315         dns_rdata_t sigrr = DNS_RDATA_INIT;
7316         dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
7317         dns_rdata_t keydatarr = DNS_RDATA_INIT;
7318         dns_rdata_rrsig_t sig;
7319         dns_rdata_dnskey_t dnskey;
7320         dns_rdata_keydata_t keydata;
7321         isc_boolean_t initializing;
7322         char namebuf[DNS_NAME_FORMATSIZE];
7323         unsigned char key_buf[4096];
7324         isc_buffer_t keyb;
7325         dst_key_t *dstkey;
7326         isc_stdtime_t now;
7327         int pending = 0;
7328         isc_boolean_t secure;
7329         isc_boolean_t free_needed;
7330
7331         UNUSED(task);
7332         INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
7333         INSIST(event->ev_arg != NULL);
7334
7335         kfetch = event->ev_arg;
7336         zone = kfetch->zone;
7337         isc_mem_attach(zone->mctx, &mctx);
7338         keyname = dns_fixedname_name(&kfetch->name);
7339
7340         devent = (dns_fetchevent_t *) event;
7341         eresult = devent->result;
7342
7343         /* Free resources which are not of interest */
7344         if (devent->node != NULL)
7345                 dns_db_detachnode(devent->db, &devent->node);
7346         if (devent->db != NULL)
7347                 dns_db_detach(&devent->db);
7348         isc_event_free(&event);
7349         dns_resolver_destroyfetch(&kfetch->fetch);
7350
7351         LOCK_ZONE(zone);
7352         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
7353                 goto cleanup;
7354
7355         isc_stdtime_get(&now);
7356         dns_name_format(keyname, namebuf, sizeof(namebuf));
7357
7358         result = dns_view_getsecroots(zone->view, &secroots);
7359         INSIST(result == ISC_R_SUCCESS);
7360
7361         dns_diff_init(mctx, &diff);
7362         diff.resign = zone->sigresigninginterval;
7363
7364         CHECK(dns_db_newversion(kfetch->db, &ver));
7365
7366         zone->refreshkeycount--;
7367         alldone = ISC_TF(zone->refreshkeycount == 0);
7368
7369         if (alldone)
7370                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7371
7372         /* Fetch failed */
7373         if (eresult != ISC_R_SUCCESS ||
7374             !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
7375                 dns_zone_log(zone, ISC_LOG_WARNING,
7376                              "Unable to fetch DNSKEY set "
7377                              "'%s': %s", namebuf, dns_result_totext(eresult));
7378                 CHECK(minimal_update(kfetch, ver, &diff));
7379                 goto done;
7380         }
7381
7382         /* No RRSIGs found */
7383         if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
7384                 dns_zone_log(zone, ISC_LOG_WARNING,
7385                              "No DNSKEY RRSIGs found for "
7386                              "'%s': %s", namebuf, dns_result_totext(eresult));
7387                 CHECK(minimal_update(kfetch, ver, &diff));
7388                 goto done;
7389         }
7390
7391         /*
7392          * Validate the dnskeyset against the current trusted keys.
7393          */
7394         for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7395              result == ISC_R_SUCCESS;
7396              result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7397                 dns_keynode_t *keynode = NULL;
7398
7399                 dns_rdata_reset(&sigrr);
7400                 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7401                 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7402                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7403
7404                 result = dns_keytable_find(secroots, keyname, &keynode);
7405                 while (result == ISC_R_SUCCESS) {
7406                         dns_keynode_t *nextnode = NULL;
7407                         dns_fixedname_t fixed;
7408                         dns_fixedname_init(&fixed);
7409
7410                         dstkey = dns_keynode_key(keynode);
7411                         if (dstkey == NULL) /* fail_secure() was called */
7412                                 break;
7413
7414                         if (dst_key_alg(dstkey) == sig.algorithm &&
7415                             dst_key_id(dstkey) == sig.keyid) {
7416                                 result = dns_dnssec_verify2(keyname,
7417                                                     &kfetch->dnskeyset,
7418                                                     dstkey, ISC_FALSE,
7419                                                     zone->view->mctx, &sigrr,
7420                                                     dns_fixedname_name(&fixed));
7421
7422                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
7423                                              "Verifying DNSKEY set for zone "
7424                                              "'%s': %s", namebuf,
7425                                              dns_result_totext(result));
7426
7427                                 if (result == ISC_R_SUCCESS) {
7428                                         kfetch->dnskeyset.trust =
7429                                                 dns_trust_secure;
7430                                         kfetch->dnskeysigset.trust =
7431                                                 dns_trust_secure;
7432                                         dns_keytable_detachkeynode(secroots,
7433                                                                    &keynode);
7434                                         break;
7435                                 }
7436                         }
7437
7438                         result = dns_keytable_nextkeynode(secroots,
7439                                                           keynode, &nextnode);
7440                         dns_keytable_detachkeynode(secroots, &keynode);
7441                         keynode = nextnode;
7442                 }
7443
7444                 if (kfetch->dnskeyset.trust == dns_trust_secure)
7445                         break;
7446         }
7447
7448         /*
7449          * If we were not able to verify the answer using the current
7450          * trusted keys then all we can do is look at any revoked keys.
7451          */
7452         secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
7453
7454         /*
7455          * First scan keydataset to find keys that are not in dnskeyset
7456          *   - Missing keys which are not scheduled for removal,
7457          *     log a warning
7458          *   - Missing keys which are scheduled for removal and
7459          *     the remove hold-down timer has completed should
7460          *     be removed from the key zone
7461          *   - Missing keys whose acceptance timers have not yet
7462          *     completed, log a warning and reset the acceptance
7463          *     timer to 30 days in the future
7464          *   - All keys not being removed have their refresh timers
7465          *     updated
7466          */
7467         initializing = ISC_TRUE;
7468         for (result = dns_rdataset_first(&kfetch->keydataset);
7469              result == ISC_R_SUCCESS;
7470              result = dns_rdataset_next(&kfetch->keydataset)) {
7471                 dns_rdata_reset(&keydatarr);
7472                 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7473                 dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7474
7475                 /*
7476                  * If any keydata record has a nonzero add holddown, then
7477                  * there was a pre-existing trust anchor for this domain;
7478                  * that means we are *not* initializing it and shouldn't
7479                  * automatically trust all the keys we find at the zone apex.
7480                  */
7481                 initializing = initializing && ISC_TF(keydata.addhd == 0);
7482
7483                 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
7484                         isc_boolean_t deletekey = ISC_FALSE;
7485
7486                         if (!secure) {
7487                                 if (now > keydata.removehd)
7488                                         deletekey = ISC_TRUE;
7489                         } else if (now < keydata.addhd) {
7490                                 dns_zone_log(zone, ISC_LOG_WARNING,
7491                                              "Pending key unexpectedly missing "
7492                                              "from %s; restarting acceptance "
7493                                              "timer", namebuf);
7494                                 keydata.addhd = now + MONTH;
7495                                 keydata.refresh = refresh_time(kfetch,
7496                                                                ISC_FALSE);
7497                         } else if (keydata.addhd == 0) {
7498                                 keydata.addhd = now;
7499                         } else if (keydata.removehd == 0) {
7500                                 dns_zone_log(zone, ISC_LOG_WARNING,
7501                                              "Active key unexpectedly missing "
7502                                              "from %s", namebuf);
7503                                 keydata.refresh = now + HOUR;
7504                         } else if (now > keydata.removehd) {
7505                                 deletekey = ISC_TRUE;
7506                         } else {
7507                                 keydata.refresh = refresh_time(kfetch,
7508                                                                ISC_FALSE);
7509                         }
7510
7511                         if  (secure || deletekey) {
7512                                 /* Delete old version */
7513                                 CHECK(update_one_rr(kfetch->db, ver, &diff,
7514                                                     DNS_DIFFOP_DEL, keyname, 0,
7515                                                     &keydatarr));
7516                         }
7517
7518                         if (!secure || deletekey)
7519                                 continue;
7520
7521                         dns_rdata_reset(&keydatarr);
7522                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7523                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7524                                              dns_rdatatype_keydata,
7525                                              &keydata, &keyb);
7526
7527                         /* Insert updated version */
7528                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7529                                             DNS_DIFFOP_ADD, keyname, 0,
7530                                             &keydatarr));
7531
7532                         set_refreshkeytimer(zone, &keydata, now);
7533                 }
7534         }
7535
7536         /*
7537          * Next scan dnskeyset:
7538          *   - If new keys are found (i.e., lacking a match in keydataset)
7539          *     add them to the key zone and set the acceptance timer
7540          *     to 30 days in the future (or to immediately if we've
7541          *     determined that we're initializing the zone for the
7542          *     first time)
7543          *   - Previously-known keys that have been revoked
7544          *     must be scheduled for removal from the key zone (or,
7545          *     if they hadn't been accepted as trust anchors yet
7546          *     anyway, removed at once)
7547          *   - Previously-known unrevoked keys whose acceptance timers
7548          *     have completed are promoted to trust anchors
7549          *   - All keys not being removed have their refresh
7550          *     timers updated
7551          */
7552         for (result = dns_rdataset_first(&kfetch->dnskeyset);
7553              result == ISC_R_SUCCESS;
7554              result = dns_rdataset_next(&kfetch->dnskeyset)) {
7555                 isc_boolean_t revoked = ISC_FALSE;
7556                 isc_boolean_t newkey = ISC_FALSE;
7557                 isc_boolean_t updatekey = ISC_FALSE;
7558                 isc_boolean_t deletekey = ISC_FALSE;
7559                 isc_boolean_t trustkey = ISC_FALSE;
7560
7561                 dns_rdata_reset(&dnskeyrr);
7562                 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
7563                 dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7564
7565                 /* Skip ZSK's */
7566                 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
7567                         continue;
7568
7569                 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
7570
7571                 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
7572                         dns_rdata_reset(&keydatarr);
7573                         dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7574                         dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7575
7576                         if (revoked && revocable(kfetch, &keydata)) {
7577                                 if (keydata.addhd > now) {
7578                                         /*
7579                                          * Key wasn't trusted yet, and now
7580                                          * it's been revoked?  Just remove it
7581                                          */
7582                                         deletekey = ISC_TRUE;
7583                                 } else if (keydata.removehd == 0) {
7584                                         /* Remove from secroots */
7585                                         dns_view_untrust(zone->view, keyname,
7586                                                          &dnskey, mctx);
7587
7588                                         /* If initializing, delete now */
7589                                         if (keydata.addhd == 0)
7590                                                 deletekey = ISC_TRUE;
7591                                         else
7592                                                 keydata.removehd = now + MONTH;
7593                                 } else if (keydata.removehd < now) {
7594                                         /* Scheduled for removal */
7595                                         deletekey = ISC_TRUE;
7596                                 }
7597                         } else if (revoked) {
7598                                 if (secure && keydata.removehd == 0) {
7599                                         dns_zone_log(zone, ISC_LOG_WARNING,
7600                                                      "Active key for zone "
7601                                                      "'%s' is revoked but "
7602                                                      "did not self-sign; "
7603                                                          "ignoring.", namebuf);
7604                                                 continue;
7605                                 }
7606                         } else if (secure) {
7607                                 if (keydata.removehd != 0) {
7608                                         /*
7609                                          * Key isn't revoked--but it
7610                                          * seems it used to be.
7611                                          * Remove it now and add it
7612                                          * back as if it were a fresh key.
7613                                          */
7614                                         deletekey = ISC_TRUE;
7615                                         newkey = ISC_TRUE;
7616                                 } else if (keydata.addhd > now)
7617                                         pending++;
7618                                 else if (keydata.addhd == 0)
7619                                         keydata.addhd = now;
7620
7621                                 if (keydata.addhd <= now)
7622                                         trustkey = ISC_TRUE;
7623                         }
7624
7625                         if (!deletekey && !newkey)
7626                                 updatekey = ISC_TRUE;
7627                 } else if (secure) {
7628                         /*
7629                          * Key wasn't in the key zone but it's
7630                          * revoked now anyway, so just skip it
7631                          */
7632                         if (revoked)
7633                                 continue;
7634
7635                         /* Key wasn't in the key zone: add it */
7636                         newkey = ISC_TRUE;
7637
7638                         if (initializing) {
7639                                 dns_keytag_t tag = 0;
7640                                 CHECK(compute_tag(keyname, &dnskey,
7641                                                   mctx, &tag));
7642                                 dns_zone_log(zone, ISC_LOG_WARNING,
7643                                              "Initializing automatic trust "
7644                                              "anchor management for zone '%s'; "
7645                                              "DNSKEY ID %d is now trusted, "
7646                                              "waiving the normal 30-day "
7647                                              "waiting period.",
7648                                              namebuf, tag);
7649                                 trustkey = ISC_TRUE;
7650                         }
7651                 }
7652
7653                 /* Delete old version */
7654                 if (deletekey || !newkey)
7655                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7656                                             DNS_DIFFOP_DEL, keyname, 0,
7657                                             &keydatarr));
7658
7659                 if (updatekey) {
7660                         /* Set refresh timer */
7661                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7662                         dns_rdata_reset(&keydatarr);
7663                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7664                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7665                                              dns_rdatatype_keydata,
7666                                              &keydata, &keyb);
7667
7668                         /* Insert updated version */
7669                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7670                                             DNS_DIFFOP_ADD, keyname, 0,
7671                                             &keydatarr));
7672                 } else if (newkey) {
7673                         /* Convert DNSKEY to KEYDATA */
7674                         dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7675                         dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
7676                                                NULL);
7677                         keydata.addhd = initializing ? now : now + MONTH;
7678                         keydata.refresh = refresh_time(kfetch, ISC_FALSE);
7679                         dns_rdata_reset(&keydatarr);
7680                         isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7681                         dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7682                                              dns_rdatatype_keydata,
7683                                              &keydata, &keyb);
7684
7685                         /* Insert into key zone */
7686                         CHECK(update_one_rr(kfetch->db, ver, &diff,
7687                                             DNS_DIFFOP_ADD, keyname, 0,
7688                                             &keydatarr));
7689                 }
7690
7691                 if (trustkey) {
7692                         /* Trust this key. */
7693                         dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7694                         trust_key(zone, keyname, &dnskey, mctx);
7695                 }
7696
7697                 if (!deletekey)
7698                         set_refreshkeytimer(zone, &keydata, now);
7699         }
7700
7701         /*
7702          * RFC5011 says, "A trust point that has all of its trust anchors
7703          * revoked is considered deleted and is treated as if the trust
7704          * point was never configured."  But if someone revoked their
7705          * active key before the standby was trusted, that would mean the
7706          * zone would suddenly be nonsecured.  We avoid this by checking to
7707          * see if there's pending keydata.  If so, we put a null key in
7708          * the security roots; then all queries to the zone will fail.
7709          */
7710         if (pending != 0)
7711                 fail_secure(zone, keyname);
7712
7713  done:
7714
7715         if (!ISC_LIST_EMPTY(diff.tuples)) {
7716                 /* Write changes to journal file. */
7717                 CHECK(increment_soa_serial(kfetch->db, ver, &diff, mctx));
7718                 CHECK(zone_journal(zone, &diff, "keyfetch_done"));
7719                 commit = ISC_TRUE;
7720
7721                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7722                 zone_needdump(zone, 30);
7723         }
7724
7725   failure:
7726
7727         dns_diff_clear(&diff);
7728         if (ver != NULL)
7729                 dns_db_closeversion(kfetch->db, &ver, commit);
7730
7731  cleanup:
7732         dns_db_detach(&kfetch->db);
7733
7734         INSIST(zone->irefs > 0);
7735         zone->irefs--;
7736         kfetch->zone = NULL;
7737
7738         if (dns_rdataset_isassociated(&kfetch->keydataset))
7739                 dns_rdataset_disassociate(&kfetch->keydataset);
7740         if (dns_rdataset_isassociated(&kfetch->dnskeyset))
7741                 dns_rdataset_disassociate(&kfetch->dnskeyset);
7742         if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7743                 dns_rdataset_disassociate(&kfetch->dnskeysigset);
7744
7745         dns_name_free(keyname, mctx);
7746         isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
7747         isc_mem_detach(&mctx);
7748
7749         if (secroots != NULL)
7750                 dns_keytable_detach(&secroots);
7751
7752         free_needed = exit_check(zone);
7753         UNLOCK_ZONE(zone);
7754         if (free_needed)
7755                 zone_free(zone);
7756 }
7757
7758 /*
7759  * Refresh the data in the key zone.  Initiate a fetch to get new DNSKEY
7760  * records from the zone apex.
7761  */
7762 static void
7763 zone_refreshkeys(dns_zone_t *zone) {
7764         const char me[] = "zone_refreshkeys";
7765         isc_result_t result;
7766         dns_rriterator_t rrit;
7767         dns_db_t *db = NULL;
7768         dns_dbversion_t *ver = NULL;
7769         dns_diff_t diff;
7770         dns_rdata_t rdata = DNS_RDATA_INIT;
7771         dns_rdata_keydata_t kd;
7772         isc_stdtime_t now;
7773         isc_boolean_t commit = ISC_FALSE;
7774
7775         ENTER;
7776         REQUIRE(zone->db != NULL);
7777
7778         isc_stdtime_get(&now);
7779
7780         LOCK_ZONE(zone);
7781         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7782                 isc_time_settoepoch(&zone->refreshkeytime);
7783                 UNLOCK_ZONE(zone);
7784                 return;
7785         }
7786
7787         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7788         dns_db_attach(zone->db, &db);
7789         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7790
7791         dns_diff_init(zone->mctx, &diff);
7792
7793         CHECK(dns_db_newversion(db, &ver));
7794
7795         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
7796
7797         dns_rriterator_init(&rrit, db, ver, 0);
7798         for (result = dns_rriterator_first(&rrit);
7799              result == ISC_R_SUCCESS;
7800              result = dns_rriterator_nextrrset(&rrit)) {
7801                 isc_stdtime_t timer = 0xffffffff;
7802                 dns_keyfetch_t *kfetch;
7803                 dns_rdataset_t *kdset;
7804                 dns_name_t *name = NULL;
7805                 isc_uint32_t ttl;
7806
7807                 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
7808                 if (!dns_rdataset_isassociated(kdset))
7809                         continue;
7810
7811                 if (kdset->type != dns_rdatatype_keydata)
7812                         continue;
7813
7814                 /*
7815                  * Scan the stored keys looking for ones that need
7816                  * removal or refreshing
7817                  */
7818                 for (result = dns_rdataset_first(kdset);
7819                      result == ISC_R_SUCCESS;
7820                      result = dns_rdataset_next(kdset)) {
7821                         dns_rdata_reset(&rdata);
7822                         dns_rdataset_current(kdset, &rdata);
7823                         result = dns_rdata_tostruct(&rdata, &kd, NULL);
7824                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7825
7826                         /* Removal timer expired? */
7827                         if (kd.removehd != 0 && kd.removehd < now) {
7828                                 CHECK(update_one_rr(db, ver, &diff,
7829                                                     DNS_DIFFOP_DEL, name, ttl,
7830                                                     &rdata));
7831                                 continue;
7832                         }
7833
7834                         /* Acceptance timer expired? */
7835                         if (kd.addhd != 0 && kd.addhd < now)
7836                                 timer = kd.addhd;
7837
7838                         /* Or do we just need to refresh the keyset? */
7839                         if (timer > kd.refresh)
7840                                 timer = kd.refresh;
7841                 }
7842
7843                 if (timer > now)
7844                         continue;
7845
7846                 zone->refreshkeycount++;
7847
7848                 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
7849                 kfetch->zone = zone;
7850                 zone->irefs++;
7851                 INSIST(zone->irefs != 0);
7852                 dns_fixedname_init(&kfetch->name);
7853                 dns_name_dup(name, zone->mctx,
7854                              dns_fixedname_name(&kfetch->name));
7855                 dns_rdataset_init(&kfetch->dnskeyset);
7856                 dns_rdataset_init(&kfetch->dnskeysigset);
7857                 dns_rdataset_init(&kfetch->keydataset);
7858                 dns_rdataset_clone(kdset, &kfetch->keydataset);
7859                 kfetch->db = NULL;
7860                 dns_db_attach(db, &kfetch->db);
7861                 kfetch->fetch = NULL;
7862
7863                 dns_resolver_createfetch(zone->view->resolver,
7864                                          dns_fixedname_name(&kfetch->name),
7865                                          dns_rdatatype_dnskey,
7866                                          NULL, NULL, NULL,
7867                                          DNS_FETCHOPT_NOVALIDATE,
7868                                          zone->task, keyfetch_done, kfetch,
7869                                          &kfetch->dnskeyset,
7870                                          &kfetch->dnskeysigset,
7871                                          &kfetch->fetch);
7872         }
7873         if (!ISC_LIST_EMPTY(diff.tuples)) {
7874                 CHECK(increment_soa_serial(db, ver, &diff, zone->mctx));
7875                 CHECK(zone_journal(zone, &diff, "sync_keyzone"));
7876                 commit = ISC_TRUE;
7877                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7878                 zone_needdump(zone, 30);
7879         }
7880
7881   failure:
7882         UNLOCK_ZONE(zone);
7883
7884         dns_diff_clear(&diff);
7885         if (ver != NULL) {
7886                 dns_rriterator_destroy(&rrit);
7887                 dns_db_closeversion(db, &ver, commit);
7888         }
7889         dns_db_detach(&db);
7890 }
7891
7892 static void
7893 zone_maintenance(dns_zone_t *zone) {
7894         const char me[] = "zone_maintenance";
7895         isc_time_t now;
7896         isc_result_t result;
7897         isc_boolean_t dumping;
7898
7899         REQUIRE(DNS_ZONE_VALID(zone));
7900         ENTER;
7901
7902         /*
7903          * Configuring the view of this zone may have
7904          * failed, for example because the config file
7905          * had a syntax error.  In that case, the view
7906          * adb or resolver, and we had better not try
7907          * to do maintenance on it.
7908          */
7909         if (zone->view == NULL || zone->view->adb == NULL)
7910                 return;
7911
7912         TIME_NOW(&now);
7913
7914         /*
7915          * Expire check.
7916          */
7917         switch (zone->type) {
7918         case dns_zone_slave:
7919         case dns_zone_stub:
7920                 LOCK_ZONE(zone);
7921                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
7922                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
7923                         zone_expire(zone);
7924                         zone->refreshtime = now;
7925                 }
7926                 UNLOCK_ZONE(zone);
7927                 break;
7928         default:
7929                 break;
7930         }
7931
7932         /*
7933          * Up to date check.
7934          */
7935         switch (zone->type) {
7936         case dns_zone_slave:
7937         case dns_zone_stub:
7938                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
7939                     isc_time_compare(&now, &zone->refreshtime) >= 0)
7940                         dns_zone_refresh(zone);
7941                 break;
7942         default:
7943                 break;
7944         }
7945
7946         /*
7947          * Do we need to consolidate the backing store?
7948          */
7949         switch (zone->type) {
7950         case dns_zone_master:
7951         case dns_zone_slave:
7952         case dns_zone_key:
7953                 LOCK_ZONE(zone);
7954                 if (zone->masterfile != NULL &&
7955                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
7956                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
7957                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
7958                         dumping = was_dumping(zone);
7959                 } else
7960                         dumping = ISC_TRUE;
7961                 UNLOCK_ZONE(zone);
7962                 if (!dumping) {
7963                         result = zone_dump(zone, ISC_TRUE); /* task locked */
7964                         if (result != ISC_R_SUCCESS)
7965                                 dns_zone_log(zone, ISC_LOG_WARNING,
7966                                              "dump failed: %s",
7967                                              dns_result_totext(result));
7968                 }
7969                 break;
7970         default:
7971                 break;
7972         }
7973
7974         /*
7975          * Do we need to refresh keys?
7976          */
7977         switch (zone->type) {
7978         case dns_zone_key:
7979                 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
7980                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
7981                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
7982                         zone_refreshkeys(zone);
7983                 break;
7984         case dns_zone_master:
7985                 if (!isc_time_isepoch(&zone->refreshkeytime) &&
7986                     isc_time_compare(&now, &zone->refreshkeytime) >= 0)
7987                         zone_rekey(zone);
7988         default:
7989                 break;
7990         }
7991
7992         switch (zone->type) {
7993         case dns_zone_master:
7994         case dns_zone_slave:
7995                 /*
7996                  * Do we need to send out notify messages?
7997                  */
7998                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
7999                     isc_time_compare(&now, &zone->notifytime) >= 0)
8000                         zone_notify(zone, &now);
8001                 /*
8002                  * Do we need to sign/resign some RRsets?
8003                  */
8004                 if (!isc_time_isepoch(&zone->signingtime) &&
8005                     isc_time_compare(&now, &zone->signingtime) >= 0)
8006                         zone_sign(zone);
8007                 else if (!isc_time_isepoch(&zone->resigntime) &&
8008                     isc_time_compare(&now, &zone->resigntime) >= 0)
8009                         zone_resigninc(zone);
8010                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
8011                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
8012                         zone_nsec3chain(zone);
8013                 /*
8014                  * Do we need to issue a key expiry warning.
8015                  */
8016                 if (!isc_time_isepoch(&zone->keywarntime) &&
8017                     isc_time_compare(&now, &zone->keywarntime) >= 0)
8018                         set_key_expiry_warning(zone, zone->key_expiry,
8019                                                isc_time_seconds(&now));
8020                 break;
8021         default:
8022                 break;
8023         }
8024         zone_settimer(zone, &now);
8025 }
8026
8027 void
8028 dns_zone_markdirty(dns_zone_t *zone) {
8029
8030         LOCK_ZONE(zone);
8031         if (zone->type == dns_zone_master)
8032                 set_resigntime(zone);   /* XXXMPA make separate call back */
8033         zone_needdump(zone, DNS_DUMP_DELAY);
8034         UNLOCK_ZONE(zone);
8035 }
8036
8037 void
8038 dns_zone_expire(dns_zone_t *zone) {
8039         REQUIRE(DNS_ZONE_VALID(zone));
8040
8041         LOCK_ZONE(zone);
8042         zone_expire(zone);
8043         UNLOCK_ZONE(zone);
8044 }
8045
8046 static void
8047 zone_expire(dns_zone_t *zone) {
8048         /*
8049          * 'zone' locked by caller.
8050          */
8051
8052         REQUIRE(LOCKED_ZONE(zone));
8053
8054         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
8055
8056         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
8057         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
8058         zone->retry = DNS_ZONE_DEFAULTRETRY;
8059         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
8060         zone_unload(zone);
8061 }
8062
8063 void
8064 dns_zone_refresh(dns_zone_t *zone) {
8065         isc_interval_t i;
8066         isc_uint32_t oldflags;
8067         unsigned int j;
8068         isc_result_t result;
8069
8070         REQUIRE(DNS_ZONE_VALID(zone));
8071
8072         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8073                 return;
8074
8075         /*
8076          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
8077          * in progress at a time.
8078          */
8079
8080         LOCK_ZONE(zone);
8081         oldflags = zone->flags;
8082         if (zone->masterscnt == 0) {
8083                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
8084                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
8085                         dns_zone_log(zone, ISC_LOG_ERROR,
8086                                      "cannot refresh: no masters");
8087                 goto unlock;
8088         }
8089         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
8090         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
8091         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
8092         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
8093                 goto unlock;
8094
8095         /*
8096          * Set the next refresh time as if refresh check has failed.
8097          * Setting this to the retry time will do that.  XXXMLG
8098          * If we are successful it will be reset using zone->refresh.
8099          */
8100         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
8101                          0);
8102         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
8103         if (result != ISC_R_SUCCESS)
8104                 dns_zone_log(zone, ISC_LOG_WARNING,
8105                              "isc_time_nowplusinterval() failed: %s",
8106                              dns_result_totext(result));
8107
8108         /*
8109          * When lacking user-specified timer values from the SOA,
8110          * do exponential backoff of the retry time up to a
8111          * maximum of six hours.
8112          */
8113         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
8114                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
8115
8116         zone->curmaster = 0;
8117         for (j = 0; j < zone->masterscnt; j++)
8118                 zone->mastersok[j] = ISC_FALSE;
8119         /* initiate soa query */
8120         queue_soa_query(zone);
8121  unlock:
8122         UNLOCK_ZONE(zone);
8123 }
8124
8125 isc_result_t
8126 dns_zone_flush(dns_zone_t *zone) {
8127         isc_result_t result = ISC_R_SUCCESS;
8128         isc_boolean_t dumping;
8129
8130         REQUIRE(DNS_ZONE_VALID(zone));
8131
8132         LOCK_ZONE(zone);
8133         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
8134         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8135             zone->masterfile != NULL) {
8136                 result = ISC_R_ALREADYRUNNING;
8137                 dumping = was_dumping(zone);
8138         } else
8139                 dumping = ISC_TRUE;
8140         UNLOCK_ZONE(zone);
8141         if (!dumping)
8142                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8143         return (result);
8144 }
8145
8146 isc_result_t
8147 dns_zone_dump(dns_zone_t *zone) {
8148         isc_result_t result = ISC_R_ALREADYRUNNING;
8149         isc_boolean_t dumping;
8150
8151         REQUIRE(DNS_ZONE_VALID(zone));
8152
8153         LOCK_ZONE(zone);
8154         dumping = was_dumping(zone);
8155         UNLOCK_ZONE(zone);
8156         if (!dumping)
8157                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
8158         return (result);
8159 }
8160
8161 static void
8162 zone_needdump(dns_zone_t *zone, unsigned int delay) {
8163         isc_time_t dumptime;
8164         isc_time_t now;
8165
8166         /*
8167          * 'zone' locked by caller
8168          */
8169
8170         REQUIRE(DNS_ZONE_VALID(zone));
8171         REQUIRE(LOCKED_ZONE(zone));
8172
8173         /*
8174          * Do we have a place to dump to and are we loaded?
8175          */
8176         if (zone->masterfile == NULL ||
8177             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8178                 return;
8179
8180         TIME_NOW(&now);
8181         /* add some noise */
8182         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
8183
8184         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8185         if (isc_time_isepoch(&zone->dumptime) ||
8186             isc_time_compare(&zone->dumptime, &dumptime) > 0)
8187                 zone->dumptime = dumptime;
8188         if (zone->task != NULL)
8189                 zone_settimer(zone, &now);
8190 }
8191
8192 static void
8193 dump_done(void *arg, isc_result_t result) {
8194         const char me[] = "dump_done";
8195         dns_zone_t *zone = arg;
8196         dns_db_t *db;
8197         dns_dbversion_t *version;
8198         isc_boolean_t again = ISC_FALSE;
8199         isc_boolean_t compact = ISC_FALSE;
8200         isc_uint32_t serial;
8201         isc_result_t tresult;
8202
8203         REQUIRE(DNS_ZONE_VALID(zone));
8204
8205         ENTER;
8206
8207         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
8208             zone->journalsize != -1) {
8209
8210                 /*
8211                  * We don't own these, zone->dctx must stay valid.
8212                  */
8213                 db = dns_dumpctx_db(zone->dctx);
8214                 version = dns_dumpctx_version(zone->dctx);
8215
8216                 tresult = dns_db_getsoaserial(db, version, &serial);
8217                 /*
8218                  * Note: we are task locked here so we can test
8219                  * zone->xfr safely.
8220                  */
8221                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
8222                         tresult = dns_journal_compact(zone->mctx,
8223                                                       zone->journal,
8224                                                       serial,
8225                                                       zone->journalsize);
8226                         switch (tresult) {
8227                         case ISC_R_SUCCESS:
8228                         case ISC_R_NOSPACE:
8229                         case ISC_R_NOTFOUND:
8230                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8231                                              "dns_journal_compact: %s",
8232                                              dns_result_totext(tresult));
8233                                 break;
8234                         default:
8235                                 dns_zone_log(zone, ISC_LOG_ERROR,
8236                                              "dns_journal_compact failed: %s",
8237                                              dns_result_totext(tresult));
8238                                 break;
8239                         }
8240                 } else if (tresult == ISC_R_SUCCESS) {
8241                         compact = ISC_TRUE;
8242                         zone->compact_serial = serial;
8243                 }
8244         }
8245
8246         LOCK_ZONE(zone);
8247         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8248         if (compact)
8249                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
8250         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
8251                 /*
8252                  * Try again in a short while.
8253                  */
8254                 zone_needdump(zone, DNS_DUMP_DELAY);
8255         } else if (result == ISC_R_SUCCESS &&
8256                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8257                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8258                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8259                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8260                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8261                 isc_time_settoepoch(&zone->dumptime);
8262                 again = ISC_TRUE;
8263         } else if (result == ISC_R_SUCCESS)
8264                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8265
8266         if (zone->dctx != NULL)
8267                 dns_dumpctx_detach(&zone->dctx);
8268         zonemgr_putio(&zone->writeio);
8269         UNLOCK_ZONE(zone);
8270         if (again)
8271                 (void)zone_dump(zone, ISC_FALSE);
8272         dns_zone_idetach(&zone);
8273 }
8274
8275 static isc_result_t
8276 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
8277         const char me[] = "zone_dump";
8278         isc_result_t result;
8279         dns_dbversion_t *version = NULL;
8280         isc_boolean_t again;
8281         dns_db_t *db = NULL;
8282         char *masterfile = NULL;
8283         dns_masterformat_t masterformat = dns_masterformat_none;
8284
8285 /*
8286  * 'compact' MUST only be set if we are task locked.
8287  */
8288
8289         REQUIRE(DNS_ZONE_VALID(zone));
8290         ENTER;
8291
8292  redo:
8293         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8294         if (zone->db != NULL)
8295                 dns_db_attach(zone->db, &db);
8296         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8297         LOCK_ZONE(zone);
8298         if (zone->masterfile != NULL) {
8299                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
8300                 masterformat = zone->masterformat;
8301         }
8302         UNLOCK_ZONE(zone);
8303         if (db == NULL) {
8304                 result = DNS_R_NOTLOADED;
8305                 goto fail;
8306         }
8307         if (masterfile == NULL) {
8308                 result = DNS_R_NOMASTERFILE;
8309                 goto fail;
8310         }
8311
8312         if (compact) {
8313                 dns_zone_t *dummy = NULL;
8314                 LOCK_ZONE(zone);
8315                 zone_iattach(zone, &dummy);
8316                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
8317                                        zone_gotwritehandle, zone,
8318                                        &zone->writeio);
8319                 if (result != ISC_R_SUCCESS)
8320                         zone_idetach(&dummy);
8321                 else
8322                         result = DNS_R_CONTINUE;
8323                 UNLOCK_ZONE(zone);
8324         } else {
8325                 dns_db_currentversion(db, &version);
8326                 result = dns_master_dump2(zone->mctx, db, version,
8327                                           &dns_master_style_default,
8328                                           masterfile, masterformat);
8329                 dns_db_closeversion(db, &version, ISC_FALSE);
8330         }
8331  fail:
8332         if (db != NULL)
8333                 dns_db_detach(&db);
8334         if (masterfile != NULL)
8335                 isc_mem_free(zone->mctx, masterfile);
8336         masterfile = NULL;
8337
8338         if (result == DNS_R_CONTINUE)
8339                 return (ISC_R_SUCCESS); /* XXXMPA */
8340
8341         again = ISC_FALSE;
8342         LOCK_ZONE(zone);
8343         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8344         if (result != ISC_R_SUCCESS) {
8345                 /*
8346                  * Try again in a short while.
8347                  */
8348                 zone_needdump(zone, DNS_DUMP_DELAY);
8349         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8350                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8351                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8352                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8353                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8354                 isc_time_settoepoch(&zone->dumptime);
8355                 again = ISC_TRUE;
8356         } else
8357                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8358         UNLOCK_ZONE(zone);
8359         if (again)
8360                 goto redo;
8361
8362         return (result);
8363 }
8364
8365 static isc_result_t
8366 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
8367              dns_masterformat_t format)
8368 {
8369         isc_result_t result;
8370         dns_dbversion_t *version = NULL;
8371         dns_db_t *db = NULL;
8372
8373         REQUIRE(DNS_ZONE_VALID(zone));
8374
8375         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8376         if (zone->db != NULL)
8377                 dns_db_attach(zone->db, &db);
8378         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8379         if (db == NULL)
8380                 return (DNS_R_NOTLOADED);
8381
8382         dns_db_currentversion(db, &version);
8383         result = dns_master_dumptostream2(zone->mctx, db, version, style,
8384                                           format, fd);
8385         dns_db_closeversion(db, &version, ISC_FALSE);
8386         dns_db_detach(&db);
8387         return (result);
8388 }
8389
8390 isc_result_t
8391 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
8392                        const dns_master_style_t *style) {
8393         return dumptostream(zone, fd, style, format);
8394 }
8395
8396 isc_result_t
8397 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
8398         return dumptostream(zone, fd, &dns_master_style_default,
8399                             dns_masterformat_text);
8400 }
8401
8402 isc_result_t
8403 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
8404         return dumptostream(zone, fd, &dns_master_style_full,
8405                             dns_masterformat_text);
8406 }
8407
8408 void
8409 dns_zone_unload(dns_zone_t *zone) {
8410         REQUIRE(DNS_ZONE_VALID(zone));
8411
8412         LOCK_ZONE(zone);
8413         zone_unload(zone);
8414         UNLOCK_ZONE(zone);
8415 }
8416
8417 static void
8418 notify_cancel(dns_zone_t *zone) {
8419         dns_notify_t *notify;
8420
8421         /*
8422          * 'zone' locked by caller.
8423          */
8424
8425         REQUIRE(LOCKED_ZONE(zone));
8426
8427         for (notify = ISC_LIST_HEAD(zone->notifies);
8428              notify != NULL;
8429              notify = ISC_LIST_NEXT(notify, link)) {
8430                 if (notify->find != NULL)
8431                         dns_adb_cancelfind(notify->find);
8432                 if (notify->request != NULL)
8433                         dns_request_cancel(notify->request);
8434         }
8435 }
8436
8437 static void
8438 zone_unload(dns_zone_t *zone) {
8439
8440         /*
8441          * 'zone' locked by caller.
8442          */
8443
8444         REQUIRE(LOCKED_ZONE(zone));
8445
8446         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
8447         zone_detachdb(zone);
8448         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
8449         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
8450         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8451 }
8452
8453 void
8454 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8455         REQUIRE(DNS_ZONE_VALID(zone));
8456         REQUIRE(val > 0);
8457
8458         zone->minrefresh = val;
8459 }
8460
8461 void
8462 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8463         REQUIRE(DNS_ZONE_VALID(zone));
8464         REQUIRE(val > 0);
8465
8466         zone->maxrefresh = val;
8467 }
8468
8469 void
8470 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
8471         REQUIRE(DNS_ZONE_VALID(zone));
8472         REQUIRE(val > 0);
8473
8474         zone->minretry = val;
8475 }
8476
8477 void
8478 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
8479         REQUIRE(DNS_ZONE_VALID(zone));
8480         REQUIRE(val > 0);
8481
8482         zone->maxretry = val;
8483 }
8484
8485 static isc_boolean_t
8486 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
8487         dns_notify_t *notify;
8488
8489         for (notify = ISC_LIST_HEAD(zone->notifies);
8490              notify != NULL;
8491              notify = ISC_LIST_NEXT(notify, link)) {
8492                 if (notify->request != NULL)
8493                         continue;
8494                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
8495                     dns_name_equal(name, &notify->ns))
8496                         return (ISC_TRUE);
8497                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
8498                         return (ISC_TRUE);
8499         }
8500         return (ISC_FALSE);
8501 }
8502
8503 static isc_boolean_t
8504 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
8505         dns_tsigkey_t *key = NULL;
8506         isc_sockaddr_t src;
8507         isc_sockaddr_t any;
8508         isc_boolean_t isself;
8509         isc_netaddr_t dstaddr;
8510         isc_result_t result;
8511
8512         if (zone->view == NULL || zone->isself == NULL)
8513                 return (ISC_FALSE);
8514
8515         switch (isc_sockaddr_pf(dst)) {
8516         case PF_INET:
8517                 src = zone->notifysrc4;
8518                 isc_sockaddr_any(&any);
8519                 break;
8520         case PF_INET6:
8521                 src = zone->notifysrc6;
8522                 isc_sockaddr_any6(&any);
8523                 break;
8524         default:
8525                 return (ISC_FALSE);
8526         }
8527
8528         /*
8529          * When sending from any the kernel will assign a source address
8530          * that matches the destination address.
8531          */
8532         if (isc_sockaddr_eqaddr(&any, &src))
8533                 src = *dst;
8534
8535         isc_netaddr_fromsockaddr(&dstaddr, dst);
8536         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
8537         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
8538                 return (ISC_FALSE);
8539         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
8540                                 zone->isselfarg);
8541         if (key != NULL)
8542                 dns_tsigkey_detach(&key);
8543         return (isself);
8544 }
8545
8546 static void
8547 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
8548         isc_mem_t *mctx;
8549
8550         /*
8551          * Caller holds zone lock.
8552          */
8553         REQUIRE(DNS_NOTIFY_VALID(notify));
8554
8555         if (notify->zone != NULL) {
8556                 if (!locked)
8557                         LOCK_ZONE(notify->zone);
8558                 REQUIRE(LOCKED_ZONE(notify->zone));
8559                 if (ISC_LINK_LINKED(notify, link))
8560                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
8561                 if (!locked)
8562                         UNLOCK_ZONE(notify->zone);
8563                 if (locked)
8564                         zone_idetach(&notify->zone);
8565                 else
8566                         dns_zone_idetach(&notify->zone);
8567         }
8568         if (notify->find != NULL)
8569                 dns_adb_destroyfind(&notify->find);
8570         if (notify->request != NULL)
8571                 dns_request_destroy(&notify->request);
8572         if (dns_name_dynamic(&notify->ns))
8573                 dns_name_free(&notify->ns, notify->mctx);
8574         mctx = notify->mctx;
8575         isc_mem_put(notify->mctx, notify, sizeof(*notify));
8576         isc_mem_detach(&mctx);
8577 }
8578
8579 static isc_result_t
8580 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
8581         dns_notify_t *notify;
8582
8583         REQUIRE(notifyp != NULL && *notifyp == NULL);
8584
8585         notify = isc_mem_get(mctx, sizeof(*notify));
8586         if (notify == NULL)
8587                 return (ISC_R_NOMEMORY);
8588
8589         notify->mctx = NULL;
8590         isc_mem_attach(mctx, &notify->mctx);
8591         notify->flags = flags;
8592         notify->zone = NULL;
8593         notify->find = NULL;
8594         notify->request = NULL;
8595         isc_sockaddr_any(&notify->dst);
8596         dns_name_init(&notify->ns, NULL);
8597         ISC_LINK_INIT(notify, link);
8598         notify->magic = NOTIFY_MAGIC;
8599         *notifyp = notify;
8600         return (ISC_R_SUCCESS);
8601 }
8602
8603 /*
8604  * XXXAG should check for DNS_ZONEFLG_EXITING
8605  */
8606 static void
8607 process_adb_event(isc_task_t *task, isc_event_t *ev) {
8608         dns_notify_t *notify;
8609         isc_eventtype_t result;
8610
8611         UNUSED(task);
8612
8613         notify = ev->ev_arg;
8614         REQUIRE(DNS_NOTIFY_VALID(notify));
8615         INSIST(task == notify->zone->task);
8616         result = ev->ev_type;
8617         isc_event_free(&ev);
8618         if (result == DNS_EVENT_ADBMOREADDRESSES) {
8619                 dns_adb_destroyfind(&notify->find);
8620                 notify_find_address(notify);
8621                 return;
8622         }
8623         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
8624                 LOCK_ZONE(notify->zone);
8625                 notify_send(notify);
8626                 UNLOCK_ZONE(notify->zone);
8627         }
8628         notify_destroy(notify, ISC_FALSE);
8629 }
8630
8631 static void
8632 notify_find_address(dns_notify_t *notify) {
8633         isc_result_t result;
8634         unsigned int options;
8635
8636         REQUIRE(DNS_NOTIFY_VALID(notify));
8637         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
8638                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
8639
8640         if (notify->zone->view->adb == NULL)
8641                 goto destroy;
8642
8643         result = dns_adb_createfind(notify->zone->view->adb,
8644                                     notify->zone->task,
8645                                     process_adb_event, notify,
8646                                     &notify->ns, dns_rootname, 0,
8647                                     options, 0, NULL,
8648                                     notify->zone->view->dstport,
8649                                     &notify->find);
8650
8651         /* Something failed? */
8652         if (result != ISC_R_SUCCESS)
8653                 goto destroy;
8654
8655         /* More addresses pending? */
8656         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
8657                 return;
8658
8659         /* We have as many addresses as we can get. */
8660         LOCK_ZONE(notify->zone);
8661         notify_send(notify);
8662         UNLOCK_ZONE(notify->zone);
8663
8664  destroy:
8665         notify_destroy(notify, ISC_FALSE);
8666 }
8667
8668
8669 static isc_result_t
8670 notify_send_queue(dns_notify_t *notify) {
8671         isc_event_t *e;
8672         isc_result_t result;
8673
8674         e = isc_event_allocate(notify->mctx, NULL,
8675                                DNS_EVENT_NOTIFYSENDTOADDR,
8676                                notify_send_toaddr,
8677                                notify, sizeof(isc_event_t));
8678         if (e == NULL)
8679                 return (ISC_R_NOMEMORY);
8680         e->ev_arg = notify;
8681         e->ev_sender = NULL;
8682         result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
8683                                          notify->zone->task, &e);
8684         if (result != ISC_R_SUCCESS)
8685                 isc_event_free(&e);
8686         return (result);
8687 }
8688
8689 static void
8690 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
8691         dns_notify_t *notify;
8692         isc_result_t result;
8693         dns_message_t *message = NULL;
8694         isc_netaddr_t dstip;
8695         dns_tsigkey_t *key = NULL;
8696         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
8697         isc_sockaddr_t src;
8698         int timeout;
8699         isc_boolean_t have_notifysource = ISC_FALSE;
8700
8701         notify = event->ev_arg;
8702         REQUIRE(DNS_NOTIFY_VALID(notify));
8703
8704         UNUSED(task);
8705
8706         LOCK_ZONE(notify->zone);
8707
8708         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
8709                 result = ISC_R_CANCELED;
8710                 goto cleanup;
8711         }
8712
8713         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
8714             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
8715             notify->zone->view->requestmgr == NULL ||
8716             notify->zone->db == NULL) {
8717                 result = ISC_R_CANCELED;
8718                 goto cleanup;
8719         }
8720
8721         /*
8722          * The raw IPv4 address should also exist.  Don't send to the
8723          * mapped form.
8724          */
8725         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
8726             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
8727                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8728                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
8729                            "notify: ignoring IPv6 mapped IPV4 address: %s",
8730                            addrbuf);
8731                 result = ISC_R_CANCELED;
8732                 goto cleanup;
8733         }
8734
8735         result = notify_createmessage(notify->zone, notify->flags, &message);
8736         if (result != ISC_R_SUCCESS)
8737                 goto cleanup;
8738
8739         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
8740         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8741         result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
8742         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
8743                 notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not "
8744                            "sent. Peer TSIG key lookup failure.", addrbuf);
8745                 goto cleanup_message;
8746         }
8747
8748         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
8749                    addrbuf);
8750         if (notify->zone->view->peers != NULL) {
8751                 dns_peer_t *peer = NULL;
8752                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
8753                                                  &dstip, &peer);
8754                 if (result == ISC_R_SUCCESS) {
8755                         result = dns_peer_getnotifysource(peer, &src);
8756                         if (result == ISC_R_SUCCESS)
8757                                 have_notifysource = ISC_TRUE;
8758                 }
8759         }
8760         switch (isc_sockaddr_pf(&notify->dst)) {
8761         case PF_INET:
8762                 if (!have_notifysource)
8763                         src = notify->zone->notifysrc4;
8764                 break;
8765         case PF_INET6:
8766                 if (!have_notifysource)
8767                         src = notify->zone->notifysrc6;
8768                 break;
8769         default:
8770                 result = ISC_R_NOTIMPLEMENTED;
8771                 goto cleanup_key;
8772         }
8773         timeout = 15;
8774         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
8775                 timeout = 30;
8776         result = dns_request_createvia2(notify->zone->view->requestmgr,
8777                                         message, &src, &notify->dst, 0, key,
8778                                         timeout * 3, timeout,
8779                                         notify->zone->task, notify_done,
8780                                         notify, &notify->request);
8781         if (result == ISC_R_SUCCESS) {
8782                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
8783                         inc_stats(notify->zone,
8784                                   dns_zonestatscounter_notifyoutv4);
8785                 } else {
8786                         inc_stats(notify->zone,
8787                                   dns_zonestatscounter_notifyoutv6);
8788                 }
8789         }
8790
8791  cleanup_key:
8792         if (key != NULL)
8793                 dns_tsigkey_detach(&key);
8794  cleanup_message:
8795         dns_message_destroy(&message);
8796  cleanup:
8797         UNLOCK_ZONE(notify->zone);
8798         if (result != ISC_R_SUCCESS)
8799                 notify_destroy(notify, ISC_FALSE);
8800         isc_event_free(&event);
8801 }
8802
8803 static void
8804 notify_send(dns_notify_t *notify) {
8805         dns_adbaddrinfo_t *ai;
8806         isc_sockaddr_t dst;
8807         isc_result_t result;
8808         dns_notify_t *new = NULL;
8809
8810         /*
8811          * Zone lock held by caller.
8812          */
8813         REQUIRE(DNS_NOTIFY_VALID(notify));
8814         REQUIRE(LOCKED_ZONE(notify->zone));
8815
8816         for (ai = ISC_LIST_HEAD(notify->find->list);
8817              ai != NULL;
8818              ai = ISC_LIST_NEXT(ai, publink)) {
8819                 dst = ai->sockaddr;
8820                 if (notify_isqueued(notify->zone, NULL, &dst))
8821                         continue;
8822                 if (notify_isself(notify->zone, &dst))
8823                         continue;
8824                 new = NULL;
8825                 result = notify_create(notify->mctx,
8826                                        (notify->flags & DNS_NOTIFY_NOSOA),
8827                                        &new);
8828                 if (result != ISC_R_SUCCESS)
8829                         goto cleanup;
8830                 zone_iattach(notify->zone, &new->zone);
8831                 ISC_LIST_APPEND(new->zone->notifies, new, link);
8832                 new->dst = dst;
8833                 result = notify_send_queue(new);
8834                 if (result != ISC_R_SUCCESS)
8835                         goto cleanup;
8836                 new = NULL;
8837         }
8838
8839  cleanup:
8840         if (new != NULL)
8841                 notify_destroy(new, ISC_TRUE);
8842 }
8843
8844 void
8845 dns_zone_notify(dns_zone_t *zone) {
8846         isc_time_t now;
8847
8848         REQUIRE(DNS_ZONE_VALID(zone));
8849
8850         LOCK_ZONE(zone);
8851         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8852
8853         TIME_NOW(&now);
8854         zone_settimer(zone, &now);
8855         UNLOCK_ZONE(zone);
8856 }
8857
8858 static void
8859 zone_notify(dns_zone_t *zone, isc_time_t *now) {
8860         dns_dbnode_t *node = NULL;
8861         dns_db_t *zonedb = NULL;
8862         dns_dbversion_t *version = NULL;
8863         dns_name_t *origin = NULL;
8864         dns_name_t master;
8865         dns_rdata_ns_t ns;
8866         dns_rdata_soa_t soa;
8867         isc_uint32_t serial;
8868         dns_rdata_t rdata = DNS_RDATA_INIT;
8869         dns_rdataset_t nsrdset;
8870         dns_rdataset_t soardset;
8871         isc_result_t result;
8872         dns_notify_t *notify = NULL;
8873         unsigned int i;
8874         isc_sockaddr_t dst;
8875         isc_boolean_t isqueued;
8876         dns_notifytype_t notifytype;
8877         unsigned int flags = 0;
8878         isc_boolean_t loggednotify = ISC_FALSE;
8879
8880         REQUIRE(DNS_ZONE_VALID(zone));
8881
8882         LOCK_ZONE(zone);
8883         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8884         notifytype = zone->notifytype;
8885         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
8886         UNLOCK_ZONE(zone);
8887
8888         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
8889                 return;
8890
8891         if (notifytype == dns_notifytype_no)
8892                 return;
8893
8894         if (notifytype == dns_notifytype_masteronly &&
8895             zone->type != dns_zone_master)
8896                 return;
8897
8898         origin = &zone->origin;
8899
8900         /*
8901          * If the zone is dialup we are done as we don't want to send
8902          * the current soa so as to force a refresh query.
8903          */
8904         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
8905                 flags |= DNS_NOTIFY_NOSOA;
8906
8907         /*
8908          * Get SOA RRset.
8909          */
8910         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8911         if (zone->db != NULL)
8912                 dns_db_attach(zone->db, &zonedb);
8913         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8914         if (zonedb == NULL)
8915                 return;
8916         dns_db_currentversion(zonedb, &version);
8917         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
8918         if (result != ISC_R_SUCCESS)
8919                 goto cleanup1;
8920
8921         dns_rdataset_init(&soardset);
8922         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
8923                                      dns_rdatatype_none, 0, &soardset, NULL);
8924         if (result != ISC_R_SUCCESS)
8925                 goto cleanup2;
8926
8927         /*
8928          * Find serial and master server's name.
8929          */
8930         dns_name_init(&master, NULL);
8931         result = dns_rdataset_first(&soardset);
8932         if (result != ISC_R_SUCCESS)
8933                 goto cleanup3;
8934         dns_rdataset_current(&soardset, &rdata);
8935         result = dns_rdata_tostruct(&rdata, &soa, NULL);
8936         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8937         dns_rdata_reset(&rdata);
8938         result = dns_name_dup(&soa.origin, zone->mctx, &master);
8939         serial = soa.serial;
8940         dns_rdataset_disassociate(&soardset);
8941         if (result != ISC_R_SUCCESS)
8942                 goto cleanup3;
8943
8944         /*
8945          * Enqueue notify requests for 'also-notify' servers.
8946          */
8947         LOCK_ZONE(zone);
8948         for (i = 0; i < zone->notifycnt; i++) {
8949                 dst = zone->notify[i];
8950                 if (notify_isqueued(zone, NULL, &dst))
8951                         continue;
8952                 result = notify_create(zone->mctx, flags, &notify);
8953                 if (result != ISC_R_SUCCESS)
8954                         continue;
8955                 zone_iattach(zone, &notify->zone);
8956                 notify->dst = dst;
8957                 ISC_LIST_APPEND(zone->notifies, notify, link);
8958                 result = notify_send_queue(notify);
8959                 if (result != ISC_R_SUCCESS)
8960                         notify_destroy(notify, ISC_TRUE);
8961                 if (!loggednotify) {
8962                         notify_log(zone, ISC_LOG_INFO,
8963                                    "sending notifies (serial %u)",
8964                                    serial);
8965                         loggednotify = ISC_TRUE;
8966                 }
8967                 notify = NULL;
8968         }
8969         UNLOCK_ZONE(zone);
8970
8971         if (notifytype == dns_notifytype_explicit)
8972                 goto cleanup3;
8973
8974         /*
8975          * Process NS RRset to generate notifies.
8976          */
8977
8978         dns_rdataset_init(&nsrdset);
8979         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
8980                                      dns_rdatatype_none, 0, &nsrdset, NULL);
8981         if (result != ISC_R_SUCCESS)
8982                 goto cleanup3;
8983
8984         result = dns_rdataset_first(&nsrdset);
8985         while (result == ISC_R_SUCCESS) {
8986                 dns_rdataset_current(&nsrdset, &rdata);
8987                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
8988                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8989                 dns_rdata_reset(&rdata);
8990                 /*
8991                  * Don't notify the master server unless explicitly
8992                  * configured to do so.
8993                  */
8994                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
8995                     dns_name_compare(&master, &ns.name) == 0) {
8996                         result = dns_rdataset_next(&nsrdset);
8997                         continue;
8998                 }
8999
9000                 if (!loggednotify) {
9001                         notify_log(zone, ISC_LOG_INFO,
9002                                    "sending notifies (serial %u)",
9003                                    serial);
9004                         loggednotify = ISC_TRUE;
9005                 }
9006
9007                 LOCK_ZONE(zone);
9008                 isqueued = notify_isqueued(zone, &ns.name, NULL);
9009                 UNLOCK_ZONE(zone);
9010                 if (isqueued) {
9011                         result = dns_rdataset_next(&nsrdset);
9012                         continue;
9013                 }
9014                 result = notify_create(zone->mctx, flags, &notify);
9015                 if (result != ISC_R_SUCCESS)
9016                         continue;
9017                 dns_zone_iattach(zone, &notify->zone);
9018                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
9019                 if (result != ISC_R_SUCCESS) {
9020                         LOCK_ZONE(zone);
9021                         notify_destroy(notify, ISC_TRUE);
9022                         UNLOCK_ZONE(zone);
9023                         continue;
9024                 }
9025                 LOCK_ZONE(zone);
9026                 ISC_LIST_APPEND(zone->notifies, notify, link);
9027                 UNLOCK_ZONE(zone);
9028                 notify_find_address(notify);
9029                 notify = NULL;
9030                 result = dns_rdataset_next(&nsrdset);
9031         }
9032         dns_rdataset_disassociate(&nsrdset);
9033
9034  cleanup3:
9035         if (dns_name_dynamic(&master))
9036                 dns_name_free(&master, zone->mctx);
9037  cleanup2:
9038         dns_db_detachnode(zonedb, &node);
9039  cleanup1:
9040         dns_db_closeversion(zonedb, &version, ISC_FALSE);
9041         dns_db_detach(&zonedb);
9042 }
9043
9044 /***
9045  *** Private
9046  ***/
9047
9048 static inline isc_result_t
9049 save_nsrrset(dns_message_t *message, dns_name_t *name,
9050              dns_db_t *db, dns_dbversion_t *version)
9051 {
9052         dns_rdataset_t *nsrdataset = NULL;
9053         dns_rdataset_t *rdataset = NULL;
9054         dns_dbnode_t *node = NULL;
9055         dns_rdata_ns_t ns;
9056         isc_result_t result;
9057         dns_rdata_t rdata = DNS_RDATA_INIT;
9058
9059         /*
9060          * Extract NS RRset from message.
9061          */
9062         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
9063                                       dns_rdatatype_ns, dns_rdatatype_none,
9064                                       NULL, &nsrdataset);
9065         if (result != ISC_R_SUCCESS)
9066                 goto fail;
9067
9068         /*
9069          * Add NS rdataset.
9070          */
9071         result = dns_db_findnode(db, name, ISC_TRUE, &node);
9072         if (result != ISC_R_SUCCESS)
9073                 goto fail;
9074         result = dns_db_addrdataset(db, node, version, 0,
9075                                     nsrdataset, 0, NULL);
9076         dns_db_detachnode(db, &node);
9077         if (result != ISC_R_SUCCESS)
9078                 goto fail;
9079         /*
9080          * Add glue rdatasets.
9081          */
9082         for (result = dns_rdataset_first(nsrdataset);
9083              result == ISC_R_SUCCESS;
9084              result = dns_rdataset_next(nsrdataset)) {
9085                 dns_rdataset_current(nsrdataset, &rdata);
9086                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
9087                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9088                 dns_rdata_reset(&rdata);
9089                 if (!dns_name_issubdomain(&ns.name, name))
9090                         continue;
9091                 rdataset = NULL;
9092                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9093                                               &ns.name, dns_rdatatype_aaaa,
9094                                               dns_rdatatype_none, NULL,
9095                                               &rdataset);
9096                 if (result == ISC_R_SUCCESS) {
9097                         result = dns_db_findnode(db, &ns.name,
9098                                                  ISC_TRUE, &node);
9099                         if (result != ISC_R_SUCCESS)
9100                                 goto fail;
9101                         result = dns_db_addrdataset(db, node, version, 0,
9102                                                     rdataset, 0, NULL);
9103                         dns_db_detachnode(db, &node);
9104                         if (result != ISC_R_SUCCESS)
9105                                 goto fail;
9106                 }
9107                 rdataset = NULL;
9108                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
9109                                               &ns.name, dns_rdatatype_a,
9110                                               dns_rdatatype_none, NULL,
9111                                               &rdataset);
9112                 if (result == ISC_R_SUCCESS) {
9113                         result = dns_db_findnode(db, &ns.name,
9114                                                  ISC_TRUE, &node);
9115                         if (result != ISC_R_SUCCESS)
9116                                 goto fail;
9117                         result = dns_db_addrdataset(db, node, version, 0,
9118                                                     rdataset, 0, NULL);
9119                         dns_db_detachnode(db, &node);
9120                         if (result != ISC_R_SUCCESS)
9121                                 goto fail;
9122                 }
9123         }
9124         if (result != ISC_R_NOMORE)
9125                 goto fail;
9126
9127         return (ISC_R_SUCCESS);
9128
9129 fail:
9130         return (result);
9131 }
9132
9133 static void
9134 stub_callback(isc_task_t *task, isc_event_t *event) {
9135         const char me[] = "stub_callback";
9136         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9137         dns_stub_t *stub = NULL;
9138         dns_message_t *msg = NULL;
9139         dns_zone_t *zone = NULL;
9140         char master[ISC_SOCKADDR_FORMATSIZE];
9141         char source[ISC_SOCKADDR_FORMATSIZE];
9142         isc_uint32_t nscnt, cnamecnt;
9143         isc_result_t result;
9144         isc_time_t now;
9145         isc_boolean_t exiting = ISC_FALSE;
9146         isc_interval_t i;
9147         unsigned int j;
9148
9149         stub = revent->ev_arg;
9150         INSIST(DNS_STUB_VALID(stub));
9151
9152         UNUSED(task);
9153
9154         zone = stub->zone;
9155
9156         ENTER;
9157
9158         TIME_NOW(&now);
9159
9160         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9161                 zone_debuglog(zone, me, 1, "exiting");
9162                 exiting = ISC_TRUE;
9163                 goto next_master;
9164         }
9165
9166         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9167         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9168
9169         if (revent->result != ISC_R_SUCCESS) {
9170                 if (revent->result == ISC_R_TIMEDOUT &&
9171                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9172                         LOCK_ZONE(zone);
9173                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9174                         UNLOCK_ZONE(zone);
9175                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9176                                      "refreshing stub: timeout retrying "
9177                                      " without EDNS master %s (source %s)",
9178                                      master, source);
9179                         goto same_master;
9180                 }
9181                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
9182                                            &zone->sourceaddr, &now);
9183                 dns_zone_log(zone, ISC_LOG_INFO,
9184                              "could not refresh stub from master %s"
9185                              " (source %s): %s", master, source,
9186                              dns_result_totext(revent->result));
9187                 goto next_master;
9188         }
9189
9190         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9191         if (result != ISC_R_SUCCESS)
9192                 goto next_master;
9193
9194         result = dns_request_getresponse(revent->request, msg, 0);
9195         if (result != ISC_R_SUCCESS)
9196                 goto next_master;
9197
9198         /*
9199          * Unexpected rcode.
9200          */
9201         if (msg->rcode != dns_rcode_noerror) {
9202                 char rcode[128];
9203                 isc_buffer_t rb;
9204
9205                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9206                 (void)dns_rcode_totext(msg->rcode, &rb);
9207
9208                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9209                     (msg->rcode == dns_rcode_servfail ||
9210                      msg->rcode == dns_rcode_notimp ||
9211                      msg->rcode == dns_rcode_formerr)) {
9212                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9213                                      "refreshing stub: rcode (%.*s) retrying "
9214                                      "without EDNS master %s (source %s)",
9215                                      (int)rb.used, rcode, master, source);
9216                         LOCK_ZONE(zone);
9217                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9218                         UNLOCK_ZONE(zone);
9219                         goto same_master;
9220                 }
9221
9222                 dns_zone_log(zone, ISC_LOG_INFO,
9223                              "refreshing stub: "
9224                              "unexpected rcode (%.*s) from %s (source %s)",
9225                              (int)rb.used, rcode, master, source);
9226                 goto next_master;
9227         }
9228
9229         /*
9230          * We need complete messages.
9231          */
9232         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9233                 if (dns_request_usedtcp(revent->request)) {
9234                         dns_zone_log(zone, ISC_LOG_INFO,
9235                                      "refreshing stub: truncated TCP "
9236                                      "response from master %s (source %s)",
9237                                      master, source);
9238                         goto next_master;
9239                 }
9240                 LOCK_ZONE(zone);
9241                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9242                 UNLOCK_ZONE(zone);
9243                 goto same_master;
9244         }
9245
9246         /*
9247          * If non-auth log and next master.
9248          */
9249         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9250                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
9251                              "non-authoritative answer from "
9252                              "master %s (source %s)", master, source);
9253                 goto next_master;
9254         }
9255
9256         /*
9257          * Sanity checks.
9258          */
9259         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9260         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
9261
9262         if (cnamecnt != 0) {
9263                 dns_zone_log(zone, ISC_LOG_INFO,
9264                              "refreshing stub: unexpected CNAME response "
9265                              "from master %s (source %s)", master, source);
9266                 goto next_master;
9267         }
9268
9269         if (nscnt == 0) {
9270                 dns_zone_log(zone, ISC_LOG_INFO,
9271                              "refreshing stub: no NS records in response "
9272                              "from master %s (source %s)", master, source);
9273                 goto next_master;
9274         }
9275
9276         /*
9277          * Save answer.
9278          */
9279         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
9280         if (result != ISC_R_SUCCESS) {
9281                 dns_zone_log(zone, ISC_LOG_INFO,
9282                              "refreshing stub: unable to save NS records "
9283                              "from master %s (source %s)", master, source);
9284                 goto next_master;
9285         }
9286
9287         /*
9288          * Tidy up.
9289          */
9290         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
9291         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9292         if (zone->db == NULL)
9293                 zone_attachdb(zone, stub->db);
9294         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9295         dns_db_detach(&stub->db);
9296
9297         if (zone->masterfile != NULL) {
9298                 dns_zone_dump(zone);
9299                 TIME_NOW(&zone->loadtime);
9300         }
9301
9302         dns_message_destroy(&msg);
9303         isc_event_free(&event);
9304         LOCK_ZONE(zone);
9305         dns_request_destroy(&zone->request);
9306         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9307         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9308         isc_interval_set(&i, zone->expire, 0);
9309         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9310         zone_settimer(zone, &now);
9311         UNLOCK_ZONE(zone);
9312         goto free_stub;
9313
9314  next_master:
9315         if (stub->version != NULL)
9316                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
9317         if (stub->db != NULL)
9318                 dns_db_detach(&stub->db);
9319         if (msg != NULL)
9320                 dns_message_destroy(&msg);
9321         isc_event_free(&event);
9322         LOCK_ZONE(zone);
9323         dns_request_destroy(&zone->request);
9324         /*
9325          * Skip to next failed / untried master.
9326          */
9327         do {
9328                 zone->curmaster++;
9329         } while (zone->curmaster < zone->masterscnt &&
9330                  zone->mastersok[zone->curmaster]);
9331         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9332         if (exiting || zone->curmaster >= zone->masterscnt) {
9333                 isc_boolean_t done = ISC_TRUE;
9334                 if (!exiting &&
9335                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9336                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9337                         /*
9338                          * Did we get a good answer from all the masters?
9339                          */
9340                         for (j = 0; j < zone->masterscnt; j++)
9341                                 if (zone->mastersok[j] == ISC_FALSE) {
9342                                         done = ISC_FALSE;
9343                                         break;
9344                                 }
9345                 } else
9346                         done = ISC_TRUE;
9347                 if (!done) {
9348                         zone->curmaster = 0;
9349                         /*
9350                          * Find the next failed master.
9351                          */
9352                         while (zone->curmaster < zone->masterscnt &&
9353                                zone->mastersok[zone->curmaster])
9354                                 zone->curmaster++;
9355                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9356                 } else {
9357                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9358
9359                         zone_settimer(zone, &now);
9360                         UNLOCK_ZONE(zone);
9361                         goto free_stub;
9362                 }
9363         }
9364         queue_soa_query(zone);
9365         UNLOCK_ZONE(zone);
9366         goto free_stub;
9367
9368  same_master:
9369         if (msg != NULL)
9370                 dns_message_destroy(&msg);
9371         isc_event_free(&event);
9372         LOCK_ZONE(zone);
9373         dns_request_destroy(&zone->request);
9374         UNLOCK_ZONE(zone);
9375         ns_query(zone, NULL, stub);
9376         goto done;
9377
9378  free_stub:
9379         stub->magic = 0;
9380         dns_zone_idetach(&stub->zone);
9381         INSIST(stub->db == NULL);
9382         INSIST(stub->version == NULL);
9383         isc_mem_put(stub->mctx, stub, sizeof(*stub));
9384
9385  done:
9386         INSIST(event == NULL);
9387         return;
9388 }
9389
9390 /*
9391  * An SOA query has finished (successfully or not).
9392  */
9393 static void
9394 refresh_callback(isc_task_t *task, isc_event_t *event) {
9395         const char me[] = "refresh_callback";
9396         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9397         dns_zone_t *zone;
9398         dns_message_t *msg = NULL;
9399         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
9400         isc_time_t now;
9401         char master[ISC_SOCKADDR_FORMATSIZE];
9402         char source[ISC_SOCKADDR_FORMATSIZE];
9403         dns_rdataset_t *rdataset = NULL;
9404         dns_rdata_t rdata = DNS_RDATA_INIT;
9405         dns_rdata_soa_t soa;
9406         isc_result_t result;
9407         isc_uint32_t serial, oldserial;
9408         unsigned int j;
9409
9410         zone = revent->ev_arg;
9411         INSIST(DNS_ZONE_VALID(zone));
9412
9413         UNUSED(task);
9414
9415         ENTER;
9416
9417         /*
9418          * if timeout log and next master;
9419          */
9420
9421         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9422         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9423
9424         TIME_NOW(&now);
9425
9426         if (revent->result != ISC_R_SUCCESS) {
9427                 if (revent->result == ISC_R_TIMEDOUT &&
9428                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9429                         LOCK_ZONE(zone);
9430                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9431                         UNLOCK_ZONE(zone);
9432                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9433                                      "refresh: timeout retrying without EDNS "
9434                                      "master %s (source %s)", master, source);
9435                         goto same_master;
9436                 }
9437                 if (revent->result == ISC_R_TIMEDOUT &&
9438                     !dns_request_usedtcp(revent->request)) {
9439                         dns_zone_log(zone, ISC_LOG_INFO,
9440                                      "refresh: retry limit for "
9441                                      "master %s exceeded (source %s)",
9442                                      master, source);
9443                         /* Try with slave with TCP. */
9444                         if (zone->type == dns_zone_slave &&
9445                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
9446                                 if (!dns_zonemgr_unreachable(zone->zmgr,
9447                                                              &zone->masteraddr,
9448                                                              &zone->sourceaddr,
9449                                                              &now)) {
9450                                         LOCK_ZONE(zone);
9451                                         DNS_ZONE_SETFLAG(zone,
9452                                                      DNS_ZONEFLG_SOABEFOREAXFR);
9453                                         UNLOCK_ZONE(zone);
9454                                         goto tcp_transfer;
9455                                 }
9456                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9457                                              "refresh: skipped tcp fallback "
9458                                              "as master %s (source %s) is "
9459                                              "unreachable (cached)",
9460                                               master, source);
9461                         }
9462                 } else
9463                         dns_zone_log(zone, ISC_LOG_INFO,
9464                                      "refresh: failure trying master "
9465                                      "%s (source %s): %s", master, source,
9466                                      dns_result_totext(revent->result));
9467                 goto next_master;
9468         }
9469
9470         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9471         if (result != ISC_R_SUCCESS)
9472                 goto next_master;
9473         result = dns_request_getresponse(revent->request, msg, 0);
9474         if (result != ISC_R_SUCCESS) {
9475                 dns_zone_log(zone, ISC_LOG_INFO,
9476                              "refresh: failure trying master "
9477                              "%s (source %s): %s", master, source,
9478                              dns_result_totext(result));
9479                 goto next_master;
9480         }
9481
9482         /*
9483          * Unexpected rcode.
9484          */
9485         if (msg->rcode != dns_rcode_noerror) {
9486                 char rcode[128];
9487                 isc_buffer_t rb;
9488
9489                 isc_buffer_init(&rb, rcode, sizeof(rcode));
9490                 (void)dns_rcode_totext(msg->rcode, &rb);
9491
9492                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9493                     (msg->rcode == dns_rcode_servfail ||
9494                      msg->rcode == dns_rcode_notimp ||
9495                      msg->rcode == dns_rcode_formerr)) {
9496                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9497                                      "refresh: rcode (%.*s) retrying without "
9498                                      "EDNS master %s (source %s)",
9499                                      (int)rb.used, rcode, master, source);
9500                         LOCK_ZONE(zone);
9501                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9502                         UNLOCK_ZONE(zone);
9503                         goto same_master;
9504                 }
9505                 dns_zone_log(zone, ISC_LOG_INFO,
9506                              "refresh: unexpected rcode (%.*s) from "
9507                              "master %s (source %s)", (int)rb.used, rcode,
9508                              master, source);
9509                 /*
9510                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
9511                  */
9512                 if (msg->rcode == dns_rcode_refused &&
9513                     zone->type == dns_zone_slave)
9514                         goto tcp_transfer;
9515                 goto next_master;
9516         }
9517
9518         /*
9519          * If truncated punt to zone transfer which will query again.
9520          */
9521         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9522                 if (zone->type == dns_zone_slave) {
9523                         dns_zone_log(zone, ISC_LOG_INFO,
9524                                      "refresh: truncated UDP answer, "
9525                                      "initiating TCP zone xfer "
9526                                      "for master %s (source %s)",
9527                                      master, source);
9528                         LOCK_ZONE(zone);
9529                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9530                         UNLOCK_ZONE(zone);
9531                         goto tcp_transfer;
9532                 } else {
9533                         INSIST(zone->type == dns_zone_stub);
9534                         if (dns_request_usedtcp(revent->request)) {
9535                                 dns_zone_log(zone, ISC_LOG_INFO,
9536                                              "refresh: truncated TCP response "
9537                                              "from master %s (source %s)",
9538                                              master, source);
9539                                 goto next_master;
9540                         }
9541                         LOCK_ZONE(zone);
9542                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9543                         UNLOCK_ZONE(zone);
9544                         goto same_master;
9545                 }
9546         }
9547
9548         /*
9549          * if non-auth log and next master;
9550          */
9551         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9552                 dns_zone_log(zone, ISC_LOG_INFO,
9553                              "refresh: non-authoritative answer from "
9554                              "master %s (source %s)", master, source);
9555                 goto next_master;
9556         }
9557
9558         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9559         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
9560         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
9561         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
9562                                  dns_rdatatype_soa);
9563
9564         /*
9565          * There should not be a CNAME record at top of zone.
9566          */
9567         if (cnamecnt != 0) {
9568                 dns_zone_log(zone, ISC_LOG_INFO,
9569                              "refresh: CNAME at top of zone "
9570                              "in master %s (source %s)", master, source);
9571                 goto next_master;
9572         }
9573
9574         /*
9575          * if referral log and next master;
9576          */
9577         if (soacnt == 0 && soacount == 0 && nscount != 0) {
9578                 dns_zone_log(zone, ISC_LOG_INFO,
9579                              "refresh: referral response "
9580                              "from master %s (source %s)", master, source);
9581                 goto next_master;
9582         }
9583
9584         /*
9585          * if nodata log and next master;
9586          */
9587         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
9588                 dns_zone_log(zone, ISC_LOG_INFO,
9589                              "refresh: NODATA response "
9590                              "from master %s (source %s)", master, source);
9591                 goto next_master;
9592         }
9593
9594         /*
9595          * Only one soa at top of zone.
9596          */
9597         if (soacnt != 1) {
9598                 dns_zone_log(zone, ISC_LOG_INFO,
9599                              "refresh: answer SOA count (%d) != 1 "
9600                              "from master %s (source %s)",
9601                              soacnt, master, source);
9602                 goto next_master;
9603         }
9604         /*
9605          * Extract serial
9606          */
9607         rdataset = NULL;
9608         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
9609                                       dns_rdatatype_soa, dns_rdatatype_none,
9610                                       NULL, &rdataset);
9611         if (result != ISC_R_SUCCESS) {
9612                 dns_zone_log(zone, ISC_LOG_INFO,
9613                              "refresh: unable to get SOA record "
9614                              "from master %s (source %s)", master, source);
9615                 goto next_master;
9616         }
9617
9618         result = dns_rdataset_first(rdataset);
9619         if (result != ISC_R_SUCCESS) {
9620                 dns_zone_log(zone, ISC_LOG_INFO,
9621                              "refresh: dns_rdataset_first() failed");
9622                 goto next_master;
9623         }
9624
9625         dns_rdataset_current(rdataset, &rdata);
9626         result = dns_rdata_tostruct(&rdata, &soa, NULL);
9627         RUNTIME_CHECK(result == ISC_R_SUCCESS);
9628
9629         serial = soa.serial;
9630         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9631                 result = dns_zone_getserial2(zone, &oldserial);
9632                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9633                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
9634                               serial, oldserial);
9635         } else
9636                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
9637                               serial);
9638
9639         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
9640             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
9641             isc_serial_gt(serial, oldserial)) {
9642                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
9643                                             &zone->sourceaddr, &now)) {
9644                         dns_zone_log(zone, ISC_LOG_INFO,
9645                                      "refresh: skipping %s as master %s "
9646                                      "(source %s) is unreachable (cached)",
9647                                      zone->type == dns_zone_slave ?
9648                                      "zone transfer" : "NS query",
9649                                      master, source);
9650                         goto next_master;
9651                 }
9652  tcp_transfer:
9653                 isc_event_free(&event);
9654                 LOCK_ZONE(zone);
9655                 dns_request_destroy(&zone->request);
9656                 UNLOCK_ZONE(zone);
9657                 if (zone->type == dns_zone_slave) {
9658                         queue_xfrin(zone);
9659                 } else {
9660                         INSIST(zone->type == dns_zone_stub);
9661                         ns_query(zone, rdataset, NULL);
9662                 }
9663                 if (msg != NULL)
9664                         dns_message_destroy(&msg);
9665         } else if (isc_serial_eq(soa.serial, oldserial)) {
9666                 if (zone->masterfile != NULL) {
9667                         result = ISC_R_FAILURE;
9668                         if (zone->journal != NULL)
9669                                 result = isc_file_settime(zone->journal, &now);
9670                         if (result == ISC_R_SUCCESS &&
9671                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9672                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9673                                 result = isc_file_settime(zone->masterfile,
9674                                                           &now);
9675                         } else if (result != ISC_R_SUCCESS)
9676                                 result = isc_file_settime(zone->masterfile,
9677                                                           &now);
9678                         /* Someone removed the file from underneath us! */
9679                         if (result == ISC_R_FILENOTFOUND) {
9680                                 LOCK_ZONE(zone);
9681                                 zone_needdump(zone, DNS_DUMP_DELAY);
9682                                 UNLOCK_ZONE(zone);
9683                         } else if (result != ISC_R_SUCCESS)
9684                                 dns_zone_log(zone, ISC_LOG_ERROR,
9685                                              "refresh: could not set file "
9686                                              "modification time of '%s': %s",
9687                                              zone->masterfile,
9688                                              dns_result_totext(result));
9689                 }
9690                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9691                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9692                 zone->mastersok[zone->curmaster] = ISC_TRUE;
9693                 goto next_master;
9694         } else {
9695                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
9696                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
9697                                      "received from master %s < ours (%u)",
9698                                      soa.serial, master, oldserial);
9699                 else
9700                         zone_debuglog(zone, me, 1, "ahead");
9701                 zone->mastersok[zone->curmaster] = ISC_TRUE;
9702                 goto next_master;
9703         }
9704         if (msg != NULL)
9705                 dns_message_destroy(&msg);
9706         goto detach;
9707
9708  next_master:
9709         if (msg != NULL)
9710                 dns_message_destroy(&msg);
9711         isc_event_free(&event);
9712         LOCK_ZONE(zone);
9713         dns_request_destroy(&zone->request);
9714         /*
9715          * Skip to next failed / untried master.
9716          */
9717         do {
9718                 zone->curmaster++;
9719         } while (zone->curmaster < zone->masterscnt &&
9720                  zone->mastersok[zone->curmaster]);
9721         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9722         if (zone->curmaster >= zone->masterscnt) {
9723                 isc_boolean_t done = ISC_TRUE;
9724                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9725                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9726                         /*
9727                          * Did we get a good answer from all the masters?
9728                          */
9729                         for (j = 0; j < zone->masterscnt; j++)
9730                                 if (zone->mastersok[j] == ISC_FALSE) {
9731                                         done = ISC_FALSE;
9732                                         break;
9733                                 }
9734                 } else
9735                         done = ISC_TRUE;
9736                 if (!done) {
9737                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9738                         zone->curmaster = 0;
9739                         /*
9740                          * Find the next failed master.
9741                          */
9742                         while (zone->curmaster < zone->masterscnt &&
9743                                zone->mastersok[zone->curmaster])
9744                                 zone->curmaster++;
9745                         goto requeue;
9746                 }
9747                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9748                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
9749                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
9750                         zone->refreshtime = now;
9751                 }
9752                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9753                 zone_settimer(zone, &now);
9754                 UNLOCK_ZONE(zone);
9755                 goto detach;
9756         }
9757
9758  requeue:
9759         queue_soa_query(zone);
9760         UNLOCK_ZONE(zone);
9761         goto detach;
9762
9763  same_master:
9764         if (msg != NULL)
9765                 dns_message_destroy(&msg);
9766         isc_event_free(&event);
9767         LOCK_ZONE(zone);
9768         dns_request_destroy(&zone->request);
9769         queue_soa_query(zone);
9770         UNLOCK_ZONE(zone);
9771
9772  detach:
9773         dns_zone_idetach(&zone);
9774         return;
9775 }
9776
9777 static void
9778 queue_soa_query(dns_zone_t *zone) {
9779         const char me[] = "queue_soa_query";
9780         isc_event_t *e;
9781         dns_zone_t *dummy = NULL;
9782         isc_result_t result;
9783
9784         ENTER;
9785         /*
9786          * Locked by caller
9787          */
9788         REQUIRE(LOCKED_ZONE(zone));
9789
9790         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9791                 cancel_refresh(zone);
9792                 return;
9793         }
9794
9795         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
9796                                soa_query, zone, sizeof(isc_event_t));
9797         if (e == NULL) {
9798                 cancel_refresh(zone);
9799                 return;
9800         }
9801
9802         /*
9803          * Attach so that we won't clean up
9804          * until the event is delivered.
9805          */
9806         zone_iattach(zone, &dummy);
9807
9808         e->ev_arg = zone;
9809         e->ev_sender = NULL;
9810         result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
9811         if (result != ISC_R_SUCCESS) {
9812                 zone_idetach(&dummy);
9813                 isc_event_free(&e);
9814                 cancel_refresh(zone);
9815         }
9816 }
9817
9818 static inline isc_result_t
9819 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
9820              dns_message_t **messagep)
9821 {
9822         dns_message_t *message = NULL;
9823         dns_name_t *qname = NULL;
9824         dns_rdataset_t *qrdataset = NULL;
9825         isc_result_t result;
9826
9827         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
9828                                     &message);
9829         if (result != ISC_R_SUCCESS)
9830                 goto cleanup;
9831
9832         message->opcode = dns_opcode_query;
9833         message->rdclass = zone->rdclass;
9834
9835         result = dns_message_gettempname(message, &qname);
9836         if (result != ISC_R_SUCCESS)
9837                 goto cleanup;
9838
9839         result = dns_message_gettemprdataset(message, &qrdataset);
9840         if (result != ISC_R_SUCCESS)
9841                 goto cleanup;
9842
9843         /*
9844          * Make question.
9845          */
9846         dns_name_init(qname, NULL);
9847         dns_name_clone(&zone->origin, qname);
9848         dns_rdataset_init(qrdataset);
9849         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
9850         ISC_LIST_APPEND(qname->list, qrdataset, link);
9851         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
9852
9853         *messagep = message;
9854         return (ISC_R_SUCCESS);
9855
9856  cleanup:
9857         if (qname != NULL)
9858                 dns_message_puttempname(message, &qname);
9859         if (qrdataset != NULL)
9860                 dns_message_puttemprdataset(message, &qrdataset);
9861         if (message != NULL)
9862                 dns_message_destroy(&message);
9863         return (result);
9864 }
9865
9866 static isc_result_t
9867 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
9868         dns_rdataset_t *rdataset = NULL;
9869         dns_rdatalist_t *rdatalist = NULL;
9870         dns_rdata_t *rdata = NULL;
9871         isc_result_t result;
9872
9873         result = dns_message_gettemprdatalist(message, &rdatalist);
9874         if (result != ISC_R_SUCCESS)
9875                 goto cleanup;
9876         result = dns_message_gettemprdata(message, &rdata);
9877         if (result != ISC_R_SUCCESS)
9878                 goto cleanup;
9879         result = dns_message_gettemprdataset(message, &rdataset);
9880         if (result != ISC_R_SUCCESS)
9881                 goto cleanup;
9882         dns_rdataset_init(rdataset);
9883
9884         rdatalist->type = dns_rdatatype_opt;
9885         rdatalist->covers = 0;
9886
9887         /*
9888          * Set Maximum UDP buffer size.
9889          */
9890         rdatalist->rdclass = udpsize;
9891
9892         /*
9893          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
9894          */
9895         rdatalist->ttl = 0;
9896
9897         /* Set EDNS options if applicable */
9898         if (reqnsid) {
9899                 unsigned char data[4];
9900                 isc_buffer_t buf;
9901
9902                 isc_buffer_init(&buf, data, sizeof(data));
9903                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
9904                 isc_buffer_putuint16(&buf, 0);
9905                 rdata->data = data;
9906                 rdata->length = sizeof(data);
9907         } else {
9908                 rdata->data = NULL;
9909                 rdata->length = 0;
9910         }
9911
9912         rdata->rdclass = rdatalist->rdclass;
9913         rdata->type = rdatalist->type;
9914         rdata->flags = 0;
9915
9916         ISC_LIST_INIT(rdatalist->rdata);
9917         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
9918         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
9919                       == ISC_R_SUCCESS);
9920
9921         return (dns_message_setopt(message, rdataset));
9922
9923  cleanup:
9924         if (rdatalist != NULL)
9925                 dns_message_puttemprdatalist(message, &rdatalist);
9926         if (rdataset != NULL)
9927                 dns_message_puttemprdataset(message, &rdataset);
9928         if (rdata != NULL)
9929                 dns_message_puttemprdata(message, &rdata);
9930
9931         return (result);
9932 }
9933
9934 static void
9935 soa_query(isc_task_t *task, isc_event_t *event) {
9936         const char me[] = "soa_query";
9937         isc_result_t result = ISC_R_FAILURE;
9938         dns_message_t *message = NULL;
9939         dns_zone_t *zone = event->ev_arg;
9940         dns_zone_t *dummy = NULL;
9941         isc_netaddr_t masterip;
9942         dns_tsigkey_t *key = NULL;
9943         isc_uint32_t options;
9944         isc_boolean_t cancel = ISC_TRUE;
9945         int timeout;
9946         isc_boolean_t have_xfrsource, reqnsid;
9947         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
9948
9949         REQUIRE(DNS_ZONE_VALID(zone));
9950
9951         UNUSED(task);
9952
9953         ENTER;
9954
9955         LOCK_ZONE(zone);
9956         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
9957             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
9958             zone->view->requestmgr == NULL) {
9959                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9960                         cancel = ISC_FALSE;
9961                 goto cleanup;
9962         }
9963
9964         /*
9965          * XXX Optimisation: Create message when zone is setup and reuse.
9966          */
9967         result = create_query(zone, dns_rdatatype_soa, &message);
9968         if (result != ISC_R_SUCCESS)
9969                 goto cleanup;
9970
9971  again:
9972         INSIST(zone->masterscnt > 0);
9973         INSIST(zone->curmaster < zone->masterscnt);
9974
9975         zone->masteraddr = zone->masters[zone->curmaster];
9976
9977         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
9978         /*
9979          * First, look for a tsig key in the master statement, then
9980          * try for a server key.
9981          */
9982         if ((zone->masterkeynames != NULL) &&
9983             (zone->masterkeynames[zone->curmaster] != NULL)) {
9984                 dns_view_t *view = dns_zone_getview(zone);
9985                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
9986                 result = dns_view_gettsig(view, keyname, &key);
9987                 if (result != ISC_R_SUCCESS) {
9988                         char namebuf[DNS_NAME_FORMATSIZE];
9989                         dns_name_format(keyname, namebuf, sizeof(namebuf));
9990                         dns_zone_log(zone, ISC_LOG_ERROR,
9991                                      "unable to find key: %s", namebuf);
9992                         goto skip_master;
9993                 }
9994         }
9995         if (key == NULL) {
9996                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
9997                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9998                         char addrbuf[ISC_NETADDR_FORMATSIZE];
9999                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
10000                         dns_zone_log(zone, ISC_LOG_ERROR,
10001                                      "unable to find TSIG key for %s", addrbuf);
10002                         goto skip_master;
10003                 }
10004         }
10005
10006         have_xfrsource = ISC_FALSE;
10007         reqnsid = zone->view->requestnsid;
10008         if (zone->view->peers != NULL) {
10009                 dns_peer_t *peer = NULL;
10010                 isc_boolean_t edns;
10011                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10012                                                  &masterip, &peer);
10013                 if (result == ISC_R_SUCCESS) {
10014                         result = dns_peer_getsupportedns(peer, &edns);
10015                         if (result == ISC_R_SUCCESS && !edns)
10016                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10017                         result = dns_peer_gettransfersource(peer,
10018                                                             &zone->sourceaddr);
10019                         if (result == ISC_R_SUCCESS)
10020                                 have_xfrsource = ISC_TRUE;
10021                         if (zone->view->resolver != NULL)
10022                                 udpsize =
10023                                   dns_resolver_getudpsize(zone->view->resolver);
10024                         (void)dns_peer_getudpsize(peer, &udpsize);
10025                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10026                 }
10027         }
10028
10029         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10030         case PF_INET:
10031                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10032                         if (isc_sockaddr_equal(&zone->altxfrsource4,
10033                                                &zone->xfrsource4))
10034                                 goto skip_master;
10035                         zone->sourceaddr = zone->altxfrsource4;
10036                 } else if (!have_xfrsource)
10037                         zone->sourceaddr = zone->xfrsource4;
10038                 break;
10039         case PF_INET6:
10040                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
10041                         if (isc_sockaddr_equal(&zone->altxfrsource6,
10042                                                &zone->xfrsource6))
10043                                 goto skip_master;
10044                         zone->sourceaddr = zone->altxfrsource6;
10045                 } else if (!have_xfrsource)
10046                         zone->sourceaddr = zone->xfrsource6;
10047                 break;
10048         default:
10049                 result = ISC_R_NOTIMPLEMENTED;
10050                 goto cleanup;
10051         }
10052
10053         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
10054                   DNS_REQUESTOPT_TCP : 0;
10055
10056         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10057                 result = add_opt(message, udpsize, reqnsid);
10058                 if (result != ISC_R_SUCCESS)
10059                         zone_debuglog(zone, me, 1,
10060                                       "unable to add opt record: %s",
10061                                       dns_result_totext(result));
10062         }
10063
10064         zone_iattach(zone, &dummy);
10065         timeout = 15;
10066         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10067                 timeout = 30;
10068         result = dns_request_createvia2(zone->view->requestmgr, message,
10069                                         &zone->sourceaddr, &zone->masteraddr,
10070                                         options, key, timeout * 3, timeout,
10071                                         zone->task, refresh_callback, zone,
10072                                         &zone->request);
10073         if (result != ISC_R_SUCCESS) {
10074                 zone_idetach(&dummy);
10075                 zone_debuglog(zone, me, 1,
10076                               "dns_request_createvia2() failed: %s",
10077                               dns_result_totext(result));
10078                 goto cleanup;
10079         } else {
10080                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
10081                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
10082                 else
10083                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
10084         }
10085         cancel = ISC_FALSE;
10086
10087  cleanup:
10088         if (key != NULL)
10089                 dns_tsigkey_detach(&key);
10090         if (result != ISC_R_SUCCESS)
10091                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10092         if (message != NULL)
10093                 dns_message_destroy(&message);
10094         if (cancel)
10095                 cancel_refresh(zone);
10096         isc_event_free(&event);
10097         UNLOCK_ZONE(zone);
10098         dns_zone_idetach(&zone);
10099         return;
10100
10101  skip_master:
10102         if (key != NULL)
10103                 dns_tsigkey_detach(&key);
10104         /*
10105          * Skip to next failed / untried master.
10106          */
10107         do {
10108                 zone->curmaster++;
10109         } while (zone->curmaster < zone->masterscnt &&
10110                  zone->mastersok[zone->curmaster]);
10111         if (zone->curmaster < zone->masterscnt)
10112                 goto again;
10113         zone->curmaster = 0;
10114         goto cleanup;
10115 }
10116
10117 static void
10118 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
10119         const char me[] = "ns_query";
10120         isc_result_t result;
10121         dns_message_t *message = NULL;
10122         isc_netaddr_t masterip;
10123         dns_tsigkey_t *key = NULL;
10124         dns_dbnode_t *node = NULL;
10125         int timeout;
10126         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
10127         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
10128
10129         REQUIRE(DNS_ZONE_VALID(zone));
10130         REQUIRE((soardataset != NULL && stub == NULL) ||
10131                 (soardataset == NULL && stub != NULL));
10132         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
10133
10134         ENTER;
10135
10136         LOCK_ZONE(zone);
10137         if (stub == NULL) {
10138                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
10139                 if (stub == NULL)
10140                         goto cleanup;
10141                 stub->magic = STUB_MAGIC;
10142                 stub->mctx = zone->mctx;
10143                 stub->zone = NULL;
10144                 stub->db = NULL;
10145                 stub->version = NULL;
10146
10147                 /*
10148                  * Attach so that the zone won't disappear from under us.
10149                  */
10150                 zone_iattach(zone, &stub->zone);
10151
10152                 /*
10153                  * If a db exists we will update it, otherwise we create a
10154                  * new one and attach it to the zone once we have the NS
10155                  * RRset and glue.
10156                  */
10157                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10158                 if (zone->db != NULL) {
10159                         dns_db_attach(zone->db, &stub->db);
10160                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10161                 } else {
10162                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10163
10164                         INSIST(zone->db_argc >= 1);
10165                         result = dns_db_create(zone->mctx, zone->db_argv[0],
10166                                                &zone->origin, dns_dbtype_stub,
10167                                                zone->rdclass,
10168                                                zone->db_argc - 1,
10169                                                zone->db_argv + 1,
10170                                                &stub->db);
10171                         if (result != ISC_R_SUCCESS) {
10172                                 dns_zone_log(zone, ISC_LOG_ERROR,
10173                                              "refreshing stub: "
10174                                              "could not create "
10175                                              "database: %s",
10176                                              dns_result_totext(result));
10177                                 goto cleanup;
10178                         }
10179                         dns_db_settask(stub->db, zone->task);
10180                 }
10181
10182                 result = dns_db_newversion(stub->db, &stub->version);
10183                 if (result != ISC_R_SUCCESS) {
10184                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10185                                      "dns_db_newversion() failed: %s",
10186                                      dns_result_totext(result));
10187                         goto cleanup;
10188                 }
10189
10190                 /*
10191                  * Update SOA record.
10192                  */
10193                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
10194                                          &node);
10195                 if (result != ISC_R_SUCCESS) {
10196                         dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10197                                      "dns_db_findnode() failed: %s",
10198                                      dns_result_totext(result));
10199                         goto cleanup;
10200                 }
10201
10202                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
10203                                             soardataset, 0, NULL);
10204                 dns_db_detachnode(stub->db, &node);
10205                 if (result != ISC_R_SUCCESS) {
10206                         dns_zone_log(zone, ISC_LOG_INFO,
10207                                      "refreshing stub: "
10208                                      "dns_db_addrdataset() failed: %s",
10209                                      dns_result_totext(result));
10210                         goto cleanup;
10211                 }
10212         }
10213
10214         /*
10215          * XXX Optimisation: Create message when zone is setup and reuse.
10216          */
10217         result = create_query(zone, dns_rdatatype_ns, &message);
10218         INSIST(result == ISC_R_SUCCESS);
10219
10220         INSIST(zone->masterscnt > 0);
10221         INSIST(zone->curmaster < zone->masterscnt);
10222         zone->masteraddr = zone->masters[zone->curmaster];
10223
10224         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10225         /*
10226          * First, look for a tsig key in the master statement, then
10227          * try for a server key.
10228          */
10229         if ((zone->masterkeynames != NULL) &&
10230             (zone->masterkeynames[zone->curmaster] != NULL)) {
10231                 dns_view_t *view = dns_zone_getview(zone);
10232                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10233                 result = dns_view_gettsig(view, keyname, &key);
10234                 if (result != ISC_R_SUCCESS) {
10235                         char namebuf[DNS_NAME_FORMATSIZE];
10236                         dns_name_format(keyname, namebuf, sizeof(namebuf));
10237                         dns_zone_log(zone, ISC_LOG_ERROR,
10238                                      "unable to find key: %s", namebuf);
10239                 }
10240         }
10241         if (key == NULL)
10242                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
10243
10244         reqnsid = zone->view->requestnsid;
10245         if (zone->view->peers != NULL) {
10246                 dns_peer_t *peer = NULL;
10247                 isc_boolean_t edns;
10248                 result = dns_peerlist_peerbyaddr(zone->view->peers,
10249                                                  &masterip, &peer);
10250                 if (result == ISC_R_SUCCESS) {
10251                         result = dns_peer_getsupportedns(peer, &edns);
10252                         if (result == ISC_R_SUCCESS && !edns)
10253                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10254                         result = dns_peer_gettransfersource(peer,
10255                                                             &zone->sourceaddr);
10256                         if (result == ISC_R_SUCCESS)
10257                                 have_xfrsource = ISC_TRUE;
10258                         if (zone->view->resolver != NULL)
10259                                 udpsize =
10260                                   dns_resolver_getudpsize(zone->view->resolver);
10261                         (void)dns_peer_getudpsize(peer, &udpsize);
10262                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
10263                 }
10264
10265         }
10266         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10267                 result = add_opt(message, udpsize, reqnsid);
10268                 if (result != ISC_R_SUCCESS)
10269                         zone_debuglog(zone, me, 1,
10270                                       "unable to add opt record: %s",
10271                                       dns_result_totext(result));
10272         }
10273
10274         /*
10275          * Always use TCP so that we shouldn't truncate in additional section.
10276          */
10277         switch (isc_sockaddr_pf(&zone->masteraddr)) {
10278         case PF_INET:
10279                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10280                         zone->sourceaddr = zone->altxfrsource4;
10281                 else if (!have_xfrsource)
10282                         zone->sourceaddr = zone->xfrsource4;
10283                 break;
10284         case PF_INET6:
10285                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10286                         zone->sourceaddr = zone->altxfrsource6;
10287                 else if (!have_xfrsource)
10288                         zone->sourceaddr = zone->xfrsource6;
10289                 break;
10290         default:
10291                 result = ISC_R_NOTIMPLEMENTED;
10292                 POST(result);
10293                 goto cleanup;
10294         }
10295         timeout = 15;
10296         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10297                 timeout = 30;
10298         result = dns_request_createvia2(zone->view->requestmgr, message,
10299                                         &zone->sourceaddr, &zone->masteraddr,
10300                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
10301                                         timeout, zone->task, stub_callback,
10302                                         stub, &zone->request);
10303         if (result != ISC_R_SUCCESS) {
10304                 zone_debuglog(zone, me, 1,
10305                               "dns_request_createvia() failed: %s",
10306                               dns_result_totext(result));
10307                 goto cleanup;
10308         }
10309         dns_message_destroy(&message);
10310         goto unlock;
10311
10312  cleanup:
10313         cancel_refresh(zone);
10314         if (stub != NULL) {
10315                 stub->magic = 0;
10316                 if (stub->version != NULL)
10317                         dns_db_closeversion(stub->db, &stub->version,
10318                                             ISC_FALSE);
10319                 if (stub->db != NULL)
10320                         dns_db_detach(&stub->db);
10321                 if (stub->zone != NULL)
10322                         zone_idetach(&stub->zone);
10323                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
10324         }
10325         if (message != NULL)
10326                 dns_message_destroy(&message);
10327   unlock:
10328         if (key != NULL)
10329                 dns_tsigkey_detach(&key);
10330         UNLOCK_ZONE(zone);
10331         return;
10332 }
10333
10334 /*
10335  * Handle the control event.  Note that although this event causes the zone
10336  * to shut down, it is not a shutdown event in the sense of the task library.
10337  */
10338 static void
10339 zone_shutdown(isc_task_t *task, isc_event_t *event) {
10340         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
10341         isc_boolean_t free_needed, linked = ISC_FALSE;
10342
10343         UNUSED(task);
10344         REQUIRE(DNS_ZONE_VALID(zone));
10345         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
10346         INSIST(isc_refcount_current(&zone->erefs) == 0);
10347         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
10348
10349         /*
10350          * Stop things being restarted after we cancel them below.
10351          */
10352         LOCK_ZONE(zone);
10353         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
10354         UNLOCK_ZONE(zone);
10355
10356         /*
10357          * If we were waiting for xfrin quota, step out of
10358          * the queue.
10359          * If there's no zone manager, we can't be waiting for the
10360          * xfrin quota
10361          */
10362         if (zone->zmgr != NULL) {
10363                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10364                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
10365                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
10366                                         statelink);
10367                         linked = ISC_TRUE;
10368                         zone->statelist = NULL;
10369                 }
10370                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10371         }
10372
10373         /*
10374          * In task context, no locking required.  See zone_xfrdone().
10375          */
10376         if (zone->xfr != NULL)
10377                 dns_xfrin_shutdown(zone->xfr);
10378
10379         LOCK_ZONE(zone);
10380         if (linked) {
10381                 INSIST(zone->irefs > 0);
10382                 zone->irefs--;
10383         }
10384         if (zone->request != NULL) {
10385                 dns_request_cancel(zone->request);
10386         }
10387
10388         if (zone->readio != NULL)
10389                 zonemgr_cancelio(zone->readio);
10390
10391         if (zone->lctx != NULL)
10392                 dns_loadctx_cancel(zone->lctx);
10393
10394         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10395             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10396                 if (zone->writeio != NULL)
10397                         zonemgr_cancelio(zone->writeio);
10398
10399                 if (zone->dctx != NULL)
10400                         dns_dumpctx_cancel(zone->dctx);
10401         }
10402
10403         notify_cancel(zone);
10404
10405         if (zone->timer != NULL) {
10406                 isc_timer_detach(&zone->timer);
10407                 INSIST(zone->irefs > 0);
10408                 zone->irefs--;
10409         }
10410
10411         if (zone->view != NULL)
10412                 dns_view_weakdetach(&zone->view);
10413
10414         /*
10415          * We have now canceled everything set the flag to allow exit_check()
10416          * to succeed.  We must not unlock between setting this flag and
10417          * calling exit_check().
10418          */
10419         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
10420         free_needed = exit_check(zone);
10421         UNLOCK_ZONE(zone);
10422         if (free_needed)
10423                 zone_free(zone);
10424 }
10425
10426 static void
10427 zone_timer(isc_task_t *task, isc_event_t *event) {
10428         const char me[] = "zone_timer";
10429         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
10430
10431         UNUSED(task);
10432         REQUIRE(DNS_ZONE_VALID(zone));
10433
10434         ENTER;
10435
10436         zone_maintenance(zone);
10437
10438         isc_event_free(&event);
10439 }
10440
10441 static void
10442 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
10443         const char me[] = "zone_settimer";
10444         isc_time_t next;
10445         isc_result_t result;
10446
10447         ENTER;
10448         REQUIRE(DNS_ZONE_VALID(zone));
10449         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10450                 return;
10451
10452         isc_time_settoepoch(&next);
10453
10454         switch (zone->type) {
10455         case dns_zone_master:
10456                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10457                         next = zone->notifytime;
10458                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10459                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10460                         INSIST(!isc_time_isepoch(&zone->dumptime));
10461                         if (isc_time_isepoch(&next) ||
10462                             isc_time_compare(&zone->dumptime, &next) < 0)
10463                                 next = zone->dumptime;
10464                 }
10465                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
10466                     !isc_time_isepoch(&zone->refreshkeytime)) {
10467                         if (isc_time_isepoch(&next) ||
10468                             isc_time_compare(&zone->refreshkeytime, &next) < 0)
10469                                 next = zone->refreshkeytime;
10470                 }
10471                 if (!isc_time_isepoch(&zone->resigntime)) {
10472                         if (isc_time_isepoch(&next) ||
10473                             isc_time_compare(&zone->resigntime, &next) < 0)
10474                                 next = zone->resigntime;
10475                 }
10476                 if (!isc_time_isepoch(&zone->keywarntime)) {
10477                         if (isc_time_isepoch(&next) ||
10478                             isc_time_compare(&zone->keywarntime, &next) < 0)
10479                                 next = zone->keywarntime;
10480                 }
10481                 if (!isc_time_isepoch(&zone->signingtime)) {
10482                         if (isc_time_isepoch(&next) ||
10483                             isc_time_compare(&zone->signingtime, &next) < 0)
10484                                 next = zone->signingtime;
10485                 }
10486                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
10487                         if (isc_time_isepoch(&next) ||
10488                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
10489                                 next = zone->nsec3chaintime;
10490                 }
10491                 break;
10492
10493         case dns_zone_slave:
10494                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10495                         next = zone->notifytime;
10496                 /*FALLTHROUGH*/
10497
10498         case dns_zone_stub:
10499                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
10500                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
10501                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
10502                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
10503                         INSIST(!isc_time_isepoch(&zone->refreshtime));
10504                         if (isc_time_isepoch(&next) ||
10505                             isc_time_compare(&zone->refreshtime, &next) < 0)
10506                                 next = zone->refreshtime;
10507                 }
10508                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10509                         INSIST(!isc_time_isepoch(&zone->expiretime));
10510                         if (isc_time_isepoch(&next) ||
10511                             isc_time_compare(&zone->expiretime, &next) < 0)
10512                                 next = zone->expiretime;
10513                 }
10514                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10515                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10516                         INSIST(!isc_time_isepoch(&zone->dumptime));
10517                         if (isc_time_isepoch(&next) ||
10518                             isc_time_compare(&zone->dumptime, &next) < 0)
10519                                 next = zone->dumptime;
10520                 }
10521                 break;
10522
10523         case dns_zone_key:
10524                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10525                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10526                         INSIST(!isc_time_isepoch(&zone->dumptime));
10527                         if (isc_time_isepoch(&next) ||
10528                             isc_time_compare(&zone->dumptime, &next) < 0)
10529                                 next = zone->dumptime;
10530                 }
10531                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10532                         if (isc_time_isepoch(&next) ||
10533                             (!isc_time_isepoch(&zone->refreshkeytime) &&
10534                             isc_time_compare(&zone->refreshkeytime, &next) < 0))
10535                                 next = zone->refreshkeytime;
10536                 }
10537                 break;
10538
10539         default:
10540                 break;
10541         }
10542
10543         if (isc_time_isepoch(&next)) {
10544                 zone_debuglog(zone, me, 10, "settimer inactive");
10545                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
10546                                           NULL, NULL, ISC_TRUE);
10547                 if (result != ISC_R_SUCCESS)
10548                         dns_zone_log(zone, ISC_LOG_ERROR,
10549                                      "could not deactivate zone timer: %s",
10550                                      isc_result_totext(result));
10551         } else {
10552                 if (isc_time_compare(&next, now) <= 0)
10553                         next = *now;
10554                 result = isc_timer_reset(zone->timer, isc_timertype_once,
10555                                          &next, NULL, ISC_TRUE);
10556                 if (result != ISC_R_SUCCESS)
10557                         dns_zone_log(zone, ISC_LOG_ERROR,
10558                                      "could not reset zone timer: %s",
10559                                      isc_result_totext(result));
10560         }
10561 }
10562
10563 static void
10564 cancel_refresh(dns_zone_t *zone) {
10565         const char me[] = "cancel_refresh";
10566         isc_time_t now;
10567
10568         /*
10569          * 'zone' locked by caller.
10570          */
10571
10572         REQUIRE(DNS_ZONE_VALID(zone));
10573         REQUIRE(LOCKED_ZONE(zone));
10574
10575         ENTER;
10576
10577         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10578         TIME_NOW(&now);
10579         zone_settimer(zone, &now);
10580 }
10581
10582 static isc_result_t
10583 notify_createmessage(dns_zone_t *zone, unsigned int flags,
10584                      dns_message_t **messagep)
10585 {
10586         dns_db_t *zonedb = NULL;
10587         dns_dbnode_t *node = NULL;
10588         dns_dbversion_t *version = NULL;
10589         dns_message_t *message = NULL;
10590         dns_rdataset_t rdataset;
10591         dns_rdata_t rdata = DNS_RDATA_INIT;
10592
10593         dns_name_t *tempname = NULL;
10594         dns_rdata_t *temprdata = NULL;
10595         dns_rdatalist_t *temprdatalist = NULL;
10596         dns_rdataset_t *temprdataset = NULL;
10597
10598         isc_result_t result;
10599         isc_region_t r;
10600         isc_buffer_t *b = NULL;
10601
10602         REQUIRE(DNS_ZONE_VALID(zone));
10603         REQUIRE(messagep != NULL && *messagep == NULL);
10604
10605         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10606                                     &message);
10607         if (result != ISC_R_SUCCESS)
10608                 return (result);
10609
10610         message->opcode = dns_opcode_notify;
10611         message->flags |= DNS_MESSAGEFLAG_AA;
10612         message->rdclass = zone->rdclass;
10613
10614         result = dns_message_gettempname(message, &tempname);
10615         if (result != ISC_R_SUCCESS)
10616                 goto cleanup;
10617
10618         result = dns_message_gettemprdataset(message, &temprdataset);
10619         if (result != ISC_R_SUCCESS)
10620                 goto cleanup;
10621
10622         /*
10623          * Make question.
10624          */
10625         dns_name_init(tempname, NULL);
10626         dns_name_clone(&zone->origin, tempname);
10627         dns_rdataset_init(temprdataset);
10628         dns_rdataset_makequestion(temprdataset, zone->rdclass,
10629                                   dns_rdatatype_soa);
10630         ISC_LIST_APPEND(tempname->list, temprdataset, link);
10631         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
10632         tempname = NULL;
10633         temprdataset = NULL;
10634
10635         if ((flags & DNS_NOTIFY_NOSOA) != 0)
10636                 goto done;
10637
10638         result = dns_message_gettempname(message, &tempname);
10639         if (result != ISC_R_SUCCESS)
10640                 goto soa_cleanup;
10641         result = dns_message_gettemprdata(message, &temprdata);
10642         if (result != ISC_R_SUCCESS)
10643                 goto soa_cleanup;
10644         result = dns_message_gettemprdataset(message, &temprdataset);
10645         if (result != ISC_R_SUCCESS)
10646                 goto soa_cleanup;
10647         result = dns_message_gettemprdatalist(message, &temprdatalist);
10648         if (result != ISC_R_SUCCESS)
10649                 goto soa_cleanup;
10650
10651         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10652         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
10653         dns_db_attach(zone->db, &zonedb);
10654         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10655
10656         dns_name_init(tempname, NULL);
10657         dns_name_clone(&zone->origin, tempname);
10658         dns_db_currentversion(zonedb, &version);
10659         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
10660         if (result != ISC_R_SUCCESS)
10661                 goto soa_cleanup;
10662
10663         dns_rdataset_init(&rdataset);
10664         result = dns_db_findrdataset(zonedb, node, version,
10665                                      dns_rdatatype_soa,
10666                                      dns_rdatatype_none, 0, &rdataset,
10667                                      NULL);
10668         if (result != ISC_R_SUCCESS)
10669                 goto soa_cleanup;
10670         result = dns_rdataset_first(&rdataset);
10671         if (result != ISC_R_SUCCESS)
10672                 goto soa_cleanup;
10673         dns_rdataset_current(&rdataset, &rdata);
10674         dns_rdata_toregion(&rdata, &r);
10675         result = isc_buffer_allocate(zone->mctx, &b, r.length);
10676         if (result != ISC_R_SUCCESS)
10677                 goto soa_cleanup;
10678         isc_buffer_putmem(b, r.base, r.length);
10679         isc_buffer_usedregion(b, &r);
10680         dns_rdata_init(temprdata);
10681         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
10682         dns_message_takebuffer(message, &b);
10683         result = dns_rdataset_next(&rdataset);
10684         dns_rdataset_disassociate(&rdataset);
10685         if (result != ISC_R_NOMORE)
10686                 goto soa_cleanup;
10687         temprdatalist->rdclass = rdata.rdclass;
10688         temprdatalist->type = rdata.type;
10689         temprdatalist->covers = 0;
10690         temprdatalist->ttl = rdataset.ttl;
10691         ISC_LIST_INIT(temprdatalist->rdata);
10692         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
10693
10694         dns_rdataset_init(temprdataset);
10695         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
10696         if (result != ISC_R_SUCCESS)
10697                 goto soa_cleanup;
10698
10699         ISC_LIST_APPEND(tempname->list, temprdataset, link);
10700         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
10701         temprdatalist = NULL;
10702         temprdataset = NULL;
10703         temprdata = NULL;
10704         tempname = NULL;
10705
10706  soa_cleanup:
10707         if (node != NULL)
10708                 dns_db_detachnode(zonedb, &node);
10709         if (version != NULL)
10710                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
10711         if (zonedb != NULL)
10712                 dns_db_detach(&zonedb);
10713         if (tempname != NULL)
10714                 dns_message_puttempname(message, &tempname);
10715         if (temprdata != NULL)
10716                 dns_message_puttemprdata(message, &temprdata);
10717         if (temprdataset != NULL)
10718                 dns_message_puttemprdataset(message, &temprdataset);
10719         if (temprdatalist != NULL)
10720                 dns_message_puttemprdatalist(message, &temprdatalist);
10721
10722  done:
10723         *messagep = message;
10724         return (ISC_R_SUCCESS);
10725
10726  cleanup:
10727         if (tempname != NULL)
10728                 dns_message_puttempname(message, &tempname);
10729         if (temprdataset != NULL)
10730                 dns_message_puttemprdataset(message, &temprdataset);
10731         dns_message_destroy(&message);
10732         return (result);
10733 }
10734
10735 isc_result_t
10736 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
10737                        dns_message_t *msg)
10738 {
10739         unsigned int i;
10740         dns_rdata_soa_t soa;
10741         dns_rdataset_t *rdataset = NULL;
10742         dns_rdata_t rdata = DNS_RDATA_INIT;
10743         isc_result_t result;
10744         char fromtext[ISC_SOCKADDR_FORMATSIZE];
10745         int match = 0;
10746         isc_netaddr_t netaddr;
10747
10748         REQUIRE(DNS_ZONE_VALID(zone));
10749
10750         /*
10751          * If type != T_SOA return DNS_R_NOTIMP.  We don't yet support
10752          * ROLLOVER.
10753          *
10754          * SOA: RFC1996
10755          * Check that 'from' is a valid notify source, (zone->masters).
10756          *      Return DNS_R_REFUSED if not.
10757          *
10758          * If the notify message contains a serial number check it
10759          * against the zones serial and return if <= current serial
10760          *
10761          * If a refresh check is progress, if so just record the
10762          * fact we received a NOTIFY and from where and return.
10763          * We will perform a new refresh check when the current one
10764          * completes. Return ISC_R_SUCCESS.
10765          *
10766          * Otherwise initiate a refresh check using 'from' as the
10767          * first address to check.  Return ISC_R_SUCCESS.
10768          */
10769
10770         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
10771
10772         /*
10773          *  We only handle NOTIFY (SOA) at the present.
10774          */
10775         LOCK_ZONE(zone);
10776         if (isc_sockaddr_pf(from) == PF_INET)
10777                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
10778         else
10779                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
10780         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
10781             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
10782                                  dns_rdatatype_soa, dns_rdatatype_none,
10783                                  NULL, NULL) != ISC_R_SUCCESS) {
10784                 UNLOCK_ZONE(zone);
10785                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
10786                         dns_zone_log(zone, ISC_LOG_NOTICE,
10787                                      "NOTIFY with no "
10788                                      "question section from: %s", fromtext);
10789                         return (DNS_R_FORMERR);
10790                 }
10791                 dns_zone_log(zone, ISC_LOG_NOTICE,
10792                              "NOTIFY zone does not match");
10793                 return (DNS_R_NOTIMP);
10794         }
10795
10796         /*
10797          * If we are a master zone just succeed.
10798          */
10799         if (zone->type == dns_zone_master) {
10800                 UNLOCK_ZONE(zone);
10801                 return (ISC_R_SUCCESS);
10802         }
10803
10804         isc_netaddr_fromsockaddr(&netaddr, from);
10805         for (i = 0; i < zone->masterscnt; i++) {
10806                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
10807                         break;
10808                 if (zone->view->aclenv.match_mapped &&
10809                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
10810                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
10811                         isc_netaddr_t na1, na2;
10812                         isc_netaddr_fromv4mapped(&na1, &netaddr);
10813                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
10814                         if (isc_netaddr_equal(&na1, &na2))
10815                                 break;
10816                 }
10817         }
10818
10819         /*
10820          * Accept notify requests from non masters if they are on
10821          * 'zone->notify_acl'.
10822          */
10823         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
10824             dns_acl_match(&netaddr, NULL, zone->notify_acl,
10825                           &zone->view->aclenv,
10826                           &match, NULL) == ISC_R_SUCCESS &&
10827             match > 0)
10828         {
10829                 /* Accept notify. */
10830         } else if (i >= zone->masterscnt) {
10831                 UNLOCK_ZONE(zone);
10832                 dns_zone_log(zone, ISC_LOG_INFO,
10833                              "refused notify from non-master: %s", fromtext);
10834                 inc_stats(zone, dns_zonestatscounter_notifyrej);
10835                 return (DNS_R_REFUSED);
10836         }
10837
10838         /*
10839          * If the zone is loaded and there are answers check the serial
10840          * to see if we need to do a refresh.  Do not worry about this
10841          * check if we are a dialup zone as we use the notify request
10842          * to trigger a refresh check.
10843          */
10844         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
10845             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10846             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
10847                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
10848                                               &zone->origin,
10849                                               dns_rdatatype_soa,
10850                                               dns_rdatatype_none, NULL,
10851                                               &rdataset);
10852                 if (result == ISC_R_SUCCESS)
10853                         result = dns_rdataset_first(rdataset);
10854                 if (result == ISC_R_SUCCESS) {
10855                         isc_uint32_t serial = 0, oldserial;
10856
10857                         dns_rdataset_current(rdataset, &rdata);
10858                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
10859                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10860                         serial = soa.serial;
10861                         /*
10862                          * The following should safely be performed without DB
10863                          * lock and succeed in this context.
10864                          */
10865                         result = zone_get_from_db(zone, zone->db, NULL, NULL,
10866                                                   &oldserial, NULL, NULL, NULL,
10867                                                   NULL, NULL);
10868                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10869                         if (isc_serial_le(serial, oldserial)) {
10870                                 dns_zone_log(zone,
10871                                              ISC_LOG_INFO,
10872                                              "notify from %s: "
10873                                              "zone is up to date",
10874                                              fromtext);
10875                                 UNLOCK_ZONE(zone);
10876                                 return (ISC_R_SUCCESS);
10877                         }
10878                 }
10879         }
10880
10881         /*
10882          * If we got this far and there was a refresh in progress just
10883          * let it complete.  Record where we got the notify from so we
10884          * can perform a refresh check when the current one completes
10885          */
10886         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
10887                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10888                 zone->notifyfrom = *from;
10889                 UNLOCK_ZONE(zone);
10890                 dns_zone_log(zone, ISC_LOG_INFO,
10891                              "notify from %s: refresh in progress, "
10892                              "refresh check queued",
10893                              fromtext);
10894                 return (ISC_R_SUCCESS);
10895         }
10896         zone->notifyfrom = *from;
10897         UNLOCK_ZONE(zone);
10898         dns_zone_refresh(zone);
10899         return (ISC_R_SUCCESS);
10900 }
10901
10902 void
10903 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
10904
10905         REQUIRE(DNS_ZONE_VALID(zone));
10906
10907         LOCK_ZONE(zone);
10908         if (zone->notify_acl != NULL)
10909                 dns_acl_detach(&zone->notify_acl);
10910         dns_acl_attach(acl, &zone->notify_acl);
10911         UNLOCK_ZONE(zone);
10912 }
10913
10914 void
10915 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
10916
10917         REQUIRE(DNS_ZONE_VALID(zone));
10918
10919         LOCK_ZONE(zone);
10920         if (zone->query_acl != NULL)
10921                 dns_acl_detach(&zone->query_acl);
10922         dns_acl_attach(acl, &zone->query_acl);
10923         UNLOCK_ZONE(zone);
10924 }
10925
10926 void
10927 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
10928
10929         REQUIRE(DNS_ZONE_VALID(zone));
10930
10931         LOCK_ZONE(zone);
10932         if (zone->queryon_acl != NULL)
10933                 dns_acl_detach(&zone->queryon_acl);
10934         dns_acl_attach(acl, &zone->queryon_acl);
10935         UNLOCK_ZONE(zone);
10936 }
10937
10938 void
10939 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
10940
10941         REQUIRE(DNS_ZONE_VALID(zone));
10942
10943         LOCK_ZONE(zone);
10944         if (zone->update_acl != NULL)
10945                 dns_acl_detach(&zone->update_acl);
10946         dns_acl_attach(acl, &zone->update_acl);
10947         UNLOCK_ZONE(zone);
10948 }
10949
10950 void
10951 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
10952
10953         REQUIRE(DNS_ZONE_VALID(zone));
10954
10955         LOCK_ZONE(zone);
10956         if (zone->forward_acl != NULL)
10957                 dns_acl_detach(&zone->forward_acl);
10958         dns_acl_attach(acl, &zone->forward_acl);
10959         UNLOCK_ZONE(zone);
10960 }
10961
10962 void
10963 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
10964
10965         REQUIRE(DNS_ZONE_VALID(zone));
10966
10967         LOCK_ZONE(zone);
10968         if (zone->xfr_acl != NULL)
10969                 dns_acl_detach(&zone->xfr_acl);
10970         dns_acl_attach(acl, &zone->xfr_acl);
10971         UNLOCK_ZONE(zone);
10972 }
10973
10974 dns_acl_t *
10975 dns_zone_getnotifyacl(dns_zone_t *zone) {
10976
10977         REQUIRE(DNS_ZONE_VALID(zone));
10978
10979         return (zone->notify_acl);
10980 }
10981
10982 dns_acl_t *
10983 dns_zone_getqueryacl(dns_zone_t *zone) {
10984
10985         REQUIRE(DNS_ZONE_VALID(zone));
10986
10987         return (zone->query_acl);
10988 }
10989
10990 dns_acl_t *
10991 dns_zone_getqueryonacl(dns_zone_t *zone) {
10992
10993         REQUIRE(DNS_ZONE_VALID(zone));
10994
10995         return (zone->queryon_acl);
10996 }
10997
10998 dns_acl_t *
10999 dns_zone_getupdateacl(dns_zone_t *zone) {
11000
11001         REQUIRE(DNS_ZONE_VALID(zone));
11002
11003         return (zone->update_acl);
11004 }
11005
11006 dns_acl_t *
11007 dns_zone_getforwardacl(dns_zone_t *zone) {
11008
11009         REQUIRE(DNS_ZONE_VALID(zone));
11010
11011         return (zone->forward_acl);
11012 }
11013
11014 dns_acl_t *
11015 dns_zone_getxfracl(dns_zone_t *zone) {
11016
11017         REQUIRE(DNS_ZONE_VALID(zone));
11018
11019         return (zone->xfr_acl);
11020 }
11021
11022 void
11023 dns_zone_clearupdateacl(dns_zone_t *zone) {
11024
11025         REQUIRE(DNS_ZONE_VALID(zone));
11026
11027         LOCK_ZONE(zone);
11028         if (zone->update_acl != NULL)
11029                 dns_acl_detach(&zone->update_acl);
11030         UNLOCK_ZONE(zone);
11031 }
11032
11033 void
11034 dns_zone_clearforwardacl(dns_zone_t *zone) {
11035
11036         REQUIRE(DNS_ZONE_VALID(zone));
11037
11038         LOCK_ZONE(zone);
11039         if (zone->forward_acl != NULL)
11040                 dns_acl_detach(&zone->forward_acl);
11041         UNLOCK_ZONE(zone);
11042 }
11043
11044 void
11045 dns_zone_clearnotifyacl(dns_zone_t *zone) {
11046
11047         REQUIRE(DNS_ZONE_VALID(zone));
11048
11049         LOCK_ZONE(zone);
11050         if (zone->notify_acl != NULL)
11051                 dns_acl_detach(&zone->notify_acl);
11052         UNLOCK_ZONE(zone);
11053 }
11054
11055 void
11056 dns_zone_clearqueryacl(dns_zone_t *zone) {
11057
11058         REQUIRE(DNS_ZONE_VALID(zone));
11059
11060         LOCK_ZONE(zone);
11061         if (zone->query_acl != NULL)
11062                 dns_acl_detach(&zone->query_acl);
11063         UNLOCK_ZONE(zone);
11064 }
11065
11066 void
11067 dns_zone_clearqueryonacl(dns_zone_t *zone) {
11068
11069         REQUIRE(DNS_ZONE_VALID(zone));
11070
11071         LOCK_ZONE(zone);
11072         if (zone->queryon_acl != NULL)
11073                 dns_acl_detach(&zone->queryon_acl);
11074         UNLOCK_ZONE(zone);
11075 }
11076
11077 void
11078 dns_zone_clearxfracl(dns_zone_t *zone) {
11079
11080         REQUIRE(DNS_ZONE_VALID(zone));
11081
11082         LOCK_ZONE(zone);
11083         if (zone->xfr_acl != NULL)
11084                 dns_acl_detach(&zone->xfr_acl);
11085         UNLOCK_ZONE(zone);
11086 }
11087
11088 isc_boolean_t
11089 dns_zone_getupdatedisabled(dns_zone_t *zone) {
11090         REQUIRE(DNS_ZONE_VALID(zone));
11091         return (zone->update_disabled);
11092
11093 }
11094
11095 void
11096 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
11097         REQUIRE(DNS_ZONE_VALID(zone));
11098         zone->update_disabled = state;
11099 }
11100
11101 isc_boolean_t
11102 dns_zone_getzeronosoattl(dns_zone_t *zone) {
11103         REQUIRE(DNS_ZONE_VALID(zone));
11104         return (zone->zero_no_soa_ttl);
11105
11106 }
11107
11108 void
11109 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
11110         REQUIRE(DNS_ZONE_VALID(zone));
11111         zone->zero_no_soa_ttl = state;
11112 }
11113
11114 void
11115 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
11116
11117         REQUIRE(DNS_ZONE_VALID(zone));
11118
11119         zone->check_names = severity;
11120 }
11121
11122 dns_severity_t
11123 dns_zone_getchecknames(dns_zone_t *zone) {
11124
11125         REQUIRE(DNS_ZONE_VALID(zone));
11126
11127         return (zone->check_names);
11128 }
11129
11130 void
11131 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
11132
11133         REQUIRE(DNS_ZONE_VALID(zone));
11134
11135         zone->journalsize = size;
11136 }
11137
11138 isc_int32_t
11139 dns_zone_getjournalsize(dns_zone_t *zone) {
11140
11141         REQUIRE(DNS_ZONE_VALID(zone));
11142
11143         return (zone->journalsize);
11144 }
11145
11146 static void
11147 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
11148         isc_result_t result = ISC_R_FAILURE;
11149         isc_buffer_t buffer;
11150
11151         REQUIRE(buf != NULL);
11152         REQUIRE(length > 1U);
11153
11154         /*
11155          * Leave space for terminating '\0'.
11156          */
11157         isc_buffer_init(&buffer, buf, length - 1);
11158         if (dns_name_dynamic(&zone->origin))
11159                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11160         if (result != ISC_R_SUCCESS &&
11161             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11162                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11163
11164         if (isc_buffer_availablelength(&buffer) > 0)
11165                 isc_buffer_putstr(&buffer, "/");
11166         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11167
11168         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
11169             strcmp(zone->view->name, "_default") != 0 &&
11170             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
11171                 isc_buffer_putstr(&buffer, "/");
11172                 isc_buffer_putstr(&buffer, zone->view->name);
11173         }
11174
11175         buf[isc_buffer_usedlength(&buffer)] = '\0';
11176 }
11177
11178 static void
11179 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
11180         isc_result_t result = ISC_R_FAILURE;
11181         isc_buffer_t buffer;
11182
11183         REQUIRE(buf != NULL);
11184         REQUIRE(length > 1U);
11185
11186         /*
11187          * Leave space for terminating '\0'.
11188          */
11189         isc_buffer_init(&buffer, buf, length - 1);
11190         if (dns_name_dynamic(&zone->origin))
11191                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11192         if (result != ISC_R_SUCCESS &&
11193             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11194                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11195
11196         buf[isc_buffer_usedlength(&buffer)] = '\0';
11197 }
11198
11199 static void
11200 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
11201         isc_buffer_t buffer;
11202
11203         REQUIRE(buf != NULL);
11204         REQUIRE(length > 1U);
11205
11206         /*
11207          * Leave space for terminating '\0'.
11208          */
11209         isc_buffer_init(&buffer, buf, length - 1);
11210         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11211
11212         buf[isc_buffer_usedlength(&buffer)] = '\0';
11213 }
11214
11215 static void
11216 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
11217         isc_buffer_t buffer;
11218
11219         REQUIRE(buf != NULL);
11220         REQUIRE(length > 1U);
11221
11222
11223         /*
11224          * Leave space for terminating '\0'.
11225          */
11226         isc_buffer_init(&buffer, buf, length - 1);
11227
11228         if (zone->view == NULL) {
11229                 isc_buffer_putstr(&buffer, "_none");
11230         } else if (strlen(zone->view->name)
11231                    < isc_buffer_availablelength(&buffer)) {
11232                 isc_buffer_putstr(&buffer, zone->view->name);
11233         } else {
11234                 isc_buffer_putstr(&buffer, "_toolong");
11235         }
11236
11237         buf[isc_buffer_usedlength(&buffer)] = '\0';
11238 }
11239
11240 void
11241 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
11242         REQUIRE(DNS_ZONE_VALID(zone));
11243         REQUIRE(buf != NULL);
11244         zone_namerd_tostr(zone, buf, length);
11245 }
11246
11247 static void
11248 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11249         va_list ap;
11250         char message[4096];
11251
11252         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11253                 return;
11254
11255         va_start(ap, fmt);
11256         vsnprintf(message, sizeof(message), fmt, ap);
11257         va_end(ap);
11258         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
11259                       level, "zone %s: %s", zone->strnamerd, message);
11260 }
11261
11262 void
11263 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
11264               int level, const char *fmt, ...) {
11265         va_list ap;
11266         char message[4096];
11267
11268         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11269                 return;
11270
11271         va_start(ap, fmt);
11272         vsnprintf(message, sizeof(message), fmt, ap);
11273         va_end(ap);
11274         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
11275                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11276                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11277 }
11278
11279 void
11280 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11281         va_list ap;
11282         char message[4096];
11283
11284         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11285                 return;
11286
11287         va_start(ap, fmt);
11288         vsnprintf(message, sizeof(message), fmt, ap);
11289         va_end(ap);
11290         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11291                       level, "%s %s: %s", (zone->type == dns_zone_key) ?
11292                       "managed-keys-zone" : "zone", zone->strnamerd, message);
11293 }
11294
11295 static void
11296 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
11297               const char *fmt, ...)
11298 {
11299         va_list ap;
11300         char message[4096];
11301         int level = ISC_LOG_DEBUG(debuglevel);
11302
11303         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11304                 return;
11305
11306         va_start(ap, fmt);
11307         vsnprintf(message, sizeof(message), fmt, ap);
11308         va_end(ap);
11309         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11310                       level, "%s: %s %s: %s", me, zone->type != dns_zone_key ?
11311                       "zone" : "managed-keys-zone", zone->strnamerd, message);
11312 }
11313
11314 static int
11315 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
11316 {
11317         isc_result_t result;
11318         dns_name_t *name;
11319         dns_rdataset_t *curr;
11320         int count = 0;
11321
11322         result = dns_message_firstname(msg, section);
11323         while (result == ISC_R_SUCCESS) {
11324                 name = NULL;
11325                 dns_message_currentname(msg, section, &name);
11326
11327                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
11328                      curr = ISC_LIST_PREV(curr, link)) {
11329                         if (curr->type == type)
11330                                 count++;
11331                 }
11332                 result = dns_message_nextname(msg, section);
11333         }
11334
11335         return (count);
11336 }
11337
11338 void
11339 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
11340         REQUIRE(DNS_ZONE_VALID(zone));
11341
11342         zone->maxxfrin = maxxfrin;
11343 }
11344
11345 isc_uint32_t
11346 dns_zone_getmaxxfrin(dns_zone_t *zone) {
11347         REQUIRE(DNS_ZONE_VALID(zone));
11348
11349         return (zone->maxxfrin);
11350 }
11351
11352 void
11353 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
11354         REQUIRE(DNS_ZONE_VALID(zone));
11355         zone->maxxfrout = maxxfrout;
11356 }
11357
11358 isc_uint32_t
11359 dns_zone_getmaxxfrout(dns_zone_t *zone) {
11360         REQUIRE(DNS_ZONE_VALID(zone));
11361
11362         return (zone->maxxfrout);
11363 }
11364
11365 dns_zonetype_t
11366 dns_zone_gettype(dns_zone_t *zone) {
11367         REQUIRE(DNS_ZONE_VALID(zone));
11368
11369         return (zone->type);
11370 }
11371
11372 dns_name_t *
11373 dns_zone_getorigin(dns_zone_t *zone) {
11374         REQUIRE(DNS_ZONE_VALID(zone));
11375
11376         return (&zone->origin);
11377 }
11378
11379 void
11380 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
11381         REQUIRE(DNS_ZONE_VALID(zone));
11382
11383         LOCK_ZONE(zone);
11384         if (zone->task != NULL)
11385                 isc_task_detach(&zone->task);
11386         isc_task_attach(task, &zone->task);
11387         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11388         if (zone->db != NULL)
11389                 dns_db_settask(zone->db, zone->task);
11390         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11391         UNLOCK_ZONE(zone);
11392 }
11393
11394 void
11395 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
11396         REQUIRE(DNS_ZONE_VALID(zone));
11397         isc_task_attach(zone->task, target);
11398 }
11399
11400 void
11401 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
11402         REQUIRE(DNS_ZONE_VALID(zone));
11403
11404         if (idlein == 0)
11405                 idlein = DNS_DEFAULT_IDLEIN;
11406         zone->idlein = idlein;
11407 }
11408
11409 isc_uint32_t
11410 dns_zone_getidlein(dns_zone_t *zone) {
11411         REQUIRE(DNS_ZONE_VALID(zone));
11412
11413         return (zone->idlein);
11414 }
11415
11416 void
11417 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
11418         REQUIRE(DNS_ZONE_VALID(zone));
11419
11420         zone->idleout = idleout;
11421 }
11422
11423 isc_uint32_t
11424 dns_zone_getidleout(dns_zone_t *zone) {
11425         REQUIRE(DNS_ZONE_VALID(zone));
11426
11427         return (zone->idleout);
11428 }
11429
11430 static void
11431 notify_done(isc_task_t *task, isc_event_t *event) {
11432         dns_requestevent_t *revent = (dns_requestevent_t *)event;
11433         dns_notify_t *notify;
11434         isc_result_t result;
11435         dns_message_t *message = NULL;
11436         isc_buffer_t buf;
11437         char rcode[128];
11438         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11439
11440         UNUSED(task);
11441
11442         notify = event->ev_arg;
11443         REQUIRE(DNS_NOTIFY_VALID(notify));
11444         INSIST(task == notify->zone->task);
11445
11446         isc_buffer_init(&buf, rcode, sizeof(rcode));
11447         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11448
11449         result = revent->result;
11450         if (result == ISC_R_SUCCESS)
11451                 result = dns_message_create(notify->zone->mctx,
11452                                             DNS_MESSAGE_INTENTPARSE, &message);
11453         if (result == ISC_R_SUCCESS)
11454                 result = dns_request_getresponse(revent->request, message,
11455                                         DNS_MESSAGEPARSE_PRESERVEORDER);
11456         if (result == ISC_R_SUCCESS)
11457                 result = dns_rcode_totext(message->rcode, &buf);
11458         if (result == ISC_R_SUCCESS)
11459                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11460                            "notify response from %s: %.*s",
11461                            addrbuf, (int)buf.used, rcode);
11462         else
11463                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
11464                            "notify to %s failed: %s", addrbuf,
11465                            dns_result_totext(result));
11466
11467         /*
11468          * Old bind's return formerr if they see a soa record.  Retry w/o
11469          * the soa if we see a formerr and had sent a SOA.
11470          */
11471         isc_event_free(&event);
11472         if (message != NULL && message->rcode == dns_rcode_formerr &&
11473             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
11474                 notify->flags |= DNS_NOTIFY_NOSOA;
11475                 dns_request_destroy(&notify->request);
11476                 result = notify_send_queue(notify);
11477                 if (result != ISC_R_SUCCESS)
11478                         notify_destroy(notify, ISC_FALSE);
11479         } else {
11480                 if (result == ISC_R_TIMEDOUT)
11481                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
11482                                    "notify to %s: retries exceeded", addrbuf);
11483                 notify_destroy(notify, ISC_FALSE);
11484         }
11485         if (message != NULL)
11486                 dns_message_destroy(&message);
11487 }
11488
11489 isc_result_t
11490 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11491         isc_result_t result;
11492
11493         REQUIRE(DNS_ZONE_VALID(zone));
11494         LOCK_ZONE(zone);
11495         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11496         result = zone_replacedb(zone, db, dump);
11497         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11498         UNLOCK_ZONE(zone);
11499         return (result);
11500 }
11501
11502 static isc_result_t
11503 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11504         dns_dbversion_t *ver;
11505         isc_result_t result;
11506         unsigned int soacount = 0;
11507         unsigned int nscount = 0;
11508
11509         /*
11510          * 'zone' and 'zonedb' locked by caller.
11511          */
11512         REQUIRE(DNS_ZONE_VALID(zone));
11513         REQUIRE(LOCKED_ZONE(zone));
11514
11515         result = zone_get_from_db(zone, db, &nscount, &soacount,
11516                                   NULL, NULL, NULL, NULL, NULL, NULL);
11517         if (result == ISC_R_SUCCESS) {
11518                 if (soacount != 1) {
11519                         dns_zone_log(zone, ISC_LOG_ERROR,
11520                                      "has %d SOA records", soacount);
11521                         result = DNS_R_BADZONE;
11522                 }
11523                 if (nscount == 0 && zone->type != dns_zone_key) {
11524                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
11525                         result = DNS_R_BADZONE;
11526                 }
11527                 if (result != ISC_R_SUCCESS)
11528                         return (result);
11529         } else {
11530                 dns_zone_log(zone, ISC_LOG_ERROR,
11531                             "retrieving SOA and NS records failed: %s",
11532                             dns_result_totext(result));
11533                 return (result);
11534         }
11535
11536         result = check_nsec3param(zone, db);
11537         if (result != ISC_R_SUCCESS)
11538                 return (result);
11539
11540         ver = NULL;
11541         dns_db_currentversion(db, &ver);
11542
11543         /*
11544          * The initial version of a slave zone is always dumped;
11545          * subsequent versions may be journaled instead if this
11546          * is enabled in the configuration.
11547          */
11548         if (zone->db != NULL && zone->journal != NULL &&
11549             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
11550             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
11551                 isc_uint32_t serial, oldserial;
11552
11553                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
11554
11555                 result = dns_db_getsoaserial(db, ver, &serial);
11556                 if (result != ISC_R_SUCCESS) {
11557                         dns_zone_log(zone, ISC_LOG_ERROR,
11558                                      "ixfr-from-differences: unable to get "
11559                                      "new serial");
11560                         goto fail;
11561                 }
11562
11563                 /*
11564                  * This is checked in zone_postload() for master zones.
11565                  */
11566                 result = zone_get_from_db(zone, zone->db, NULL, NULL,
11567                                           &oldserial, NULL, NULL, NULL, NULL,
11568                                           NULL);
11569                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11570                 if (zone->type == dns_zone_slave &&
11571                     !isc_serial_gt(serial, oldserial)) {
11572                         isc_uint32_t serialmin, serialmax;
11573                         serialmin = (oldserial + 1) & 0xffffffffU;
11574                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
11575                         dns_zone_log(zone, ISC_LOG_ERROR,
11576                                      "ixfr-from-differences: failed: "
11577                                      "new serial (%u) out of range [%u - %u]",
11578                                      serial, serialmin, serialmax);
11579                         result = ISC_R_RANGE;
11580                         goto fail;
11581                 }
11582
11583                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
11584                                      zone->journal);
11585                 if (result != ISC_R_SUCCESS)
11586                         goto fail;
11587                 if (dump)
11588                         zone_needdump(zone, DNS_DUMP_DELAY);
11589                 else if (zone->journalsize != -1) {
11590                         result = dns_journal_compact(zone->mctx, zone->journal,
11591                                                      serial, zone->journalsize);
11592                         switch (result) {
11593                         case ISC_R_SUCCESS:
11594                         case ISC_R_NOSPACE:
11595                         case ISC_R_NOTFOUND:
11596                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
11597                                              "dns_journal_compact: %s",
11598                                              dns_result_totext(result));
11599                                 break;
11600                         default:
11601                                 dns_zone_log(zone, ISC_LOG_ERROR,
11602                                              "dns_journal_compact failed: %s",
11603                                              dns_result_totext(result));
11604                                 break;
11605                         }
11606                 }
11607         } else {
11608                 if (dump && zone->masterfile != NULL) {
11609                         /*
11610                          * If DNS_ZONEFLG_FORCEXFER was set we don't want
11611                          * to keep the old masterfile.
11612                          */
11613                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
11614                             remove(zone->masterfile) < 0 && errno != ENOENT) {
11615                                 char strbuf[ISC_STRERRORSIZE];
11616                                 isc__strerror(errno, strbuf, sizeof(strbuf));
11617                                 isc_log_write(dns_lctx,
11618                                               DNS_LOGCATEGORY_GENERAL,
11619                                               DNS_LOGMODULE_ZONE,
11620                                               ISC_LOG_WARNING,
11621                                               "unable to remove masterfile "
11622                                               "'%s': '%s'",
11623                                               zone->masterfile, strbuf);
11624                         }
11625                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
11626                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
11627                         else
11628                                 zone_needdump(zone, 0);
11629                 }
11630                 if (dump && zone->journal != NULL) {
11631                         /*
11632                          * The in-memory database just changed, and
11633                          * because 'dump' is set, it didn't change by
11634                          * being loaded from disk.  Also, we have not
11635                          * journaled diffs for this change.
11636                          * Therefore, the on-disk journal is missing
11637                          * the deltas for this change.  Since it can
11638                          * no longer be used to bring the zone
11639                          * up-to-date, it is useless and should be
11640                          * removed.
11641                          */
11642                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11643                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11644                                       "removing journal file");
11645                         if (remove(zone->journal) < 0 && errno != ENOENT) {
11646                                 char strbuf[ISC_STRERRORSIZE];
11647                                 isc__strerror(errno, strbuf, sizeof(strbuf));
11648                                 isc_log_write(dns_lctx,
11649                                               DNS_LOGCATEGORY_GENERAL,
11650                                               DNS_LOGMODULE_ZONE,
11651                                               ISC_LOG_WARNING,
11652                                               "unable to remove journal "
11653                                               "'%s': '%s'",
11654                                               zone->journal, strbuf);
11655                         }
11656                 }
11657         }
11658
11659         dns_db_closeversion(db, &ver, ISC_FALSE);
11660
11661         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11662                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11663                       "replacing zone database");
11664
11665         if (zone->db != NULL)
11666                 zone_detachdb(zone);
11667         zone_attachdb(zone, db);
11668         dns_db_settask(zone->db, zone->task);
11669         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
11670         return (ISC_R_SUCCESS);
11671
11672  fail:
11673         dns_db_closeversion(db, &ver, ISC_FALSE);
11674         return (result);
11675 }
11676
11677 /* The caller must hold the dblock as a writer. */
11678 static inline void
11679 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
11680         REQUIRE(zone->db == NULL && db != NULL);
11681
11682         dns_db_attach(db, &zone->db);
11683         if (zone->acache != NULL) {
11684                 isc_result_t result;
11685                 result = dns_acache_setdb(zone->acache, db);
11686                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
11687                         UNEXPECTED_ERROR(__FILE__, __LINE__,
11688                                          "dns_acache_setdb() failed: %s",
11689                                          isc_result_totext(result));
11690                 }
11691         }
11692 }
11693
11694 /* The caller must hold the dblock as a writer. */
11695 static inline void
11696 zone_detachdb(dns_zone_t *zone) {
11697         REQUIRE(zone->db != NULL);
11698
11699         if (zone->acache != NULL)
11700                 (void)dns_acache_putdb(zone->acache, zone->db);
11701         dns_db_detach(&zone->db);
11702 }
11703
11704 static void
11705 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
11706         isc_time_t now;
11707         isc_boolean_t again = ISC_FALSE;
11708         unsigned int soacount;
11709         unsigned int nscount;
11710         isc_uint32_t serial, refresh, retry, expire, minimum;
11711         isc_result_t xfrresult = result;
11712         isc_boolean_t free_needed;
11713
11714         REQUIRE(DNS_ZONE_VALID(zone));
11715
11716         dns_zone_log(zone, ISC_LOG_DEBUG(1),
11717                      "zone transfer finished: %s", dns_result_totext(result));
11718
11719         LOCK_ZONE(zone);
11720         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
11721         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11722         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
11723
11724         TIME_NOW(&now);
11725         switch (result) {
11726         case ISC_R_SUCCESS:
11727                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11728                 /*FALLTHROUGH*/
11729         case DNS_R_UPTODATE:
11730                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
11731                 /*
11732                  * Has the zone expired underneath us?
11733                  */
11734                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11735                 if (zone->db == NULL) {
11736                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11737                         goto same_master;
11738                 }
11739
11740                 /*
11741                  * Update the zone structure's data from the actual
11742                  * SOA received.
11743                  */
11744                 nscount = 0;
11745                 soacount = 0;
11746                 INSIST(zone->db != NULL);
11747                 result = zone_get_from_db(zone, zone->db, &nscount,
11748                                           &soacount, &serial, &refresh,
11749                                           &retry, &expire, &minimum, NULL);
11750                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11751                 if (result == ISC_R_SUCCESS) {
11752                         if (soacount != 1)
11753                                 dns_zone_log(zone, ISC_LOG_ERROR,
11754                                              "transferred zone "
11755                                              "has %d SOA record%s", soacount,
11756                                              (soacount != 0) ? "s" : "");
11757                         if (nscount == 0) {
11758                                 dns_zone_log(zone, ISC_LOG_ERROR,
11759                                              "transferred zone "
11760                                              "has no NS records");
11761                                 if (DNS_ZONE_FLAG(zone,
11762                                                   DNS_ZONEFLG_HAVETIMERS)) {
11763                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11764                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
11765                                 }
11766                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11767                                 zone_unload(zone);
11768                                 goto next_master;
11769                         }
11770                         zone->refresh = RANGE(refresh, zone->minrefresh,
11771                                               zone->maxrefresh);
11772                         zone->retry = RANGE(retry, zone->minretry,
11773                                             zone->maxretry);
11774                         zone->expire = RANGE(expire,
11775                                              zone->refresh + zone->retry,
11776                                              DNS_MAX_EXPIRE);
11777                         zone->minimum = minimum;
11778                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11779                 }
11780
11781                 /*
11782                  * Set our next update/expire times.
11783                  */
11784                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11785                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11786                         zone->refreshtime = now;
11787                         DNS_ZONE_TIME_ADD(&now, zone->expire,
11788                                           &zone->expiretime);
11789                 } else {
11790                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
11791                                             &zone->refreshtime);
11792                         DNS_ZONE_TIME_ADD(&now, zone->expire,
11793                                           &zone->expiretime);
11794                 }
11795                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
11796                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
11797                         if (zone->tsigkey != NULL) {
11798                                 char namebuf[DNS_NAME_FORMATSIZE];
11799                                 dns_name_format(&zone->tsigkey->name, namebuf,
11800                                                 sizeof(namebuf));
11801                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
11802                                          namebuf);
11803                         } else
11804                                 buf[0] = '\0';
11805                         dns_zone_log(zone, ISC_LOG_INFO,
11806                                      "transferred serial %u%s",
11807                                      serial, buf);
11808                 }
11809
11810                 /*
11811                  * This is not necessary if we just performed a AXFR
11812                  * however it is necessary for an IXFR / UPTODATE and
11813                  * won't hurt with an AXFR.
11814                  */
11815                 if (zone->masterfile != NULL || zone->journal != NULL) {
11816                         result = ISC_R_FAILURE;
11817                         if (zone->journal != NULL)
11818                                 result = isc_file_settime(zone->journal, &now);
11819                         if (result != ISC_R_SUCCESS &&
11820                             zone->masterfile != NULL)
11821                                 result = isc_file_settime(zone->masterfile,
11822                                                           &now);
11823                         /* Someone removed the file from underneath us! */
11824                         if (result == ISC_R_FILENOTFOUND &&
11825                             zone->masterfile != NULL) {
11826                                 unsigned int delay = DNS_DUMP_DELAY;
11827                                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY))
11828                                         delay = 0;
11829                                 zone_needdump(zone, delay);
11830                         } else if (result != ISC_R_SUCCESS)
11831                                 dns_zone_log(zone, ISC_LOG_ERROR,
11832                                              "transfer: could not set file "
11833                                              "modification time of '%s': %s",
11834                                              zone->masterfile,
11835                                              dns_result_totext(result));
11836                 }
11837                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
11838                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
11839                 break;
11840
11841         case DNS_R_BADIXFR:
11842                 /* Force retry with AXFR. */
11843                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
11844                 goto same_master;
11845
11846         default:
11847         next_master:
11848                 /*
11849                  * Skip to next failed / untried master.
11850                  */
11851                 do {
11852                         zone->curmaster++;
11853                 } while (zone->curmaster < zone->masterscnt &&
11854                          zone->mastersok[zone->curmaster]);
11855                 /* FALLTHROUGH */
11856         same_master:
11857                 if (zone->curmaster >= zone->masterscnt) {
11858                         zone->curmaster = 0;
11859                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11860                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11861                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11862                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11863                                 while (zone->curmaster < zone->masterscnt &&
11864                                        zone->mastersok[zone->curmaster])
11865                                         zone->curmaster++;
11866                                 again = ISC_TRUE;
11867                         } else
11868                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11869                 } else {
11870                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11871                         again = ISC_TRUE;
11872                 }
11873                 inc_stats(zone, dns_zonestatscounter_xfrfail);
11874                 break;
11875         }
11876         zone_settimer(zone, &now);
11877
11878         /*
11879          * If creating the transfer object failed, zone->xfr is NULL.
11880          * Otherwise, we are called as the done callback of a zone
11881          * transfer object that just entered its shutting-down
11882          * state.  Since we are no longer responsible for shutting
11883          * it down, we can detach our reference.
11884          */
11885         if (zone->xfr != NULL)
11886                 dns_xfrin_detach(&zone->xfr);
11887
11888         if (zone->tsigkey != NULL)
11889                 dns_tsigkey_detach(&zone->tsigkey);
11890
11891         /*
11892          * Handle any deferred journal compaction.
11893          */
11894         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
11895                 result = dns_journal_compact(zone->mctx, zone->journal,
11896                                              zone->compact_serial,
11897                                              zone->journalsize);
11898                 switch (result) {
11899                 case ISC_R_SUCCESS:
11900                 case ISC_R_NOSPACE:
11901                 case ISC_R_NOTFOUND:
11902                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
11903                                      "dns_journal_compact: %s",
11904                                      dns_result_totext(result));
11905                         break;
11906                 default:
11907                         dns_zone_log(zone, ISC_LOG_ERROR,
11908                                      "dns_journal_compact failed: %s",
11909                                      dns_result_totext(result));
11910                         break;
11911                 }
11912                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11913         }
11914
11915         /*
11916          * This transfer finishing freed up a transfer quota slot.
11917          * Let any other zones waiting for quota have it.
11918          */
11919         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11920         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
11921         zone->statelist = NULL;
11922         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
11923         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11924
11925         /*
11926          * Retry with a different server if necessary.
11927          */
11928         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11929                 queue_soa_query(zone);
11930
11931         INSIST(zone->irefs > 0);
11932         zone->irefs--;
11933         free_needed = exit_check(zone);
11934         UNLOCK_ZONE(zone);
11935         if (free_needed)
11936                 zone_free(zone);
11937 }
11938
11939 static void
11940 zone_loaddone(void *arg, isc_result_t result) {
11941         static char me[] = "zone_loaddone";
11942         dns_load_t *load = arg;
11943         dns_zone_t *zone;
11944         isc_result_t tresult;
11945
11946         REQUIRE(DNS_LOAD_VALID(load));
11947         zone = load->zone;
11948
11949         ENTER;
11950
11951         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
11952         if (tresult != ISC_R_SUCCESS &&
11953             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
11954                 result = tresult;
11955
11956         LOCK_ZONE(load->zone);
11957         (void)zone_postload(load->zone, load->db, load->loadtime, result);
11958         zonemgr_putio(&load->zone->readio);
11959         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
11960         /*
11961          * Leave the zone frozen if the reload fails.
11962          */
11963         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
11964              DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
11965                 zone->update_disabled = ISC_FALSE;
11966         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
11967         UNLOCK_ZONE(load->zone);
11968
11969         load->magic = 0;
11970         dns_db_detach(&load->db);
11971         if (load->zone->lctx != NULL)
11972                 dns_loadctx_detach(&load->zone->lctx);
11973         dns_zone_idetach(&load->zone);
11974         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
11975 }
11976
11977 void
11978 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
11979         REQUIRE(DNS_ZONE_VALID(zone));
11980         REQUIRE(table != NULL);
11981         REQUIRE(*table == NULL);
11982
11983         LOCK_ZONE(zone);
11984         if (zone->ssutable != NULL)
11985                 dns_ssutable_attach(zone->ssutable, table);
11986         UNLOCK_ZONE(zone);
11987 }
11988
11989 void
11990 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
11991         REQUIRE(DNS_ZONE_VALID(zone));
11992
11993         LOCK_ZONE(zone);
11994         if (zone->ssutable != NULL)
11995                 dns_ssutable_detach(&zone->ssutable);
11996         if (table != NULL)
11997                 dns_ssutable_attach(table, &zone->ssutable);
11998         UNLOCK_ZONE(zone);
11999 }
12000
12001 void
12002 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
12003         REQUIRE(DNS_ZONE_VALID(zone));
12004
12005         zone->sigvalidityinterval = interval;
12006 }
12007
12008 isc_uint32_t
12009 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
12010         REQUIRE(DNS_ZONE_VALID(zone));
12011
12012         return (zone->sigvalidityinterval);
12013 }
12014
12015 void
12016 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
12017         REQUIRE(DNS_ZONE_VALID(zone));
12018
12019         zone->sigresigninginterval = interval;
12020 }
12021
12022 isc_uint32_t
12023 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
12024         REQUIRE(DNS_ZONE_VALID(zone));
12025
12026         return (zone->sigresigninginterval);
12027 }
12028
12029 static void
12030 queue_xfrin(dns_zone_t *zone) {
12031         const char me[] = "queue_xfrin";
12032         isc_result_t result;
12033         dns_zonemgr_t *zmgr = zone->zmgr;
12034
12035         ENTER;
12036
12037         INSIST(zone->statelist == NULL);
12038
12039         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12040         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
12041         LOCK_ZONE(zone);
12042         zone->irefs++;
12043         UNLOCK_ZONE(zone);
12044         zone->statelist = &zmgr->waiting_for_xfrin;
12045         result = zmgr_start_xfrin_ifquota(zmgr, zone);
12046         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12047
12048         if (result == ISC_R_QUOTA) {
12049                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
12050                               "zone transfer deferred due to quota");
12051         } else if (result != ISC_R_SUCCESS) {
12052                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
12053                               "starting zone transfer: %s",
12054                               isc_result_totext(result));
12055         }
12056 }
12057
12058 /*
12059  * This event callback is called when a zone has received
12060  * any necessary zone transfer quota.  This is the time
12061  * to go ahead and start the transfer.
12062  */
12063 static void
12064 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
12065         isc_result_t result;
12066         dns_peer_t *peer = NULL;
12067         char master[ISC_SOCKADDR_FORMATSIZE];
12068         char source[ISC_SOCKADDR_FORMATSIZE];
12069         dns_rdatatype_t xfrtype;
12070         dns_zone_t *zone = event->ev_arg;
12071         isc_netaddr_t masterip;
12072         isc_sockaddr_t sourceaddr;
12073         isc_sockaddr_t masteraddr;
12074         isc_time_t now;
12075         const char *soa_before = "";
12076
12077         UNUSED(task);
12078
12079         INSIST(task == zone->task);
12080
12081         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12082                 result = ISC_R_CANCELED;
12083                 goto cleanup;
12084         }
12085
12086         TIME_NOW(&now);
12087
12088         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12089         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12090                                     &zone->sourceaddr, &now)) {
12091                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12092                 dns_zone_log(zone, ISC_LOG_INFO,
12093                              "got_transfer_quota: skipping zone transfer as "
12094                              "master %s (source %s) is unreachable (cached)",
12095                              master, source);
12096                 result = ISC_R_CANCELED;
12097                 goto cleanup;
12098         }
12099
12100         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12101         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
12102
12103         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12104                 soa_before = "SOA before ";
12105         /*
12106          * Decide whether we should request IXFR or AXFR.
12107          */
12108         if (zone->db == NULL) {
12109                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12110                              "no database exists yet, requesting AXFR of "
12111                              "initial version from %s", master);
12112                 xfrtype = dns_rdatatype_axfr;
12113         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
12114                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
12115                              "set, requesting %sAXFR from %s", soa_before,
12116                              master);
12117                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12118                         xfrtype = dns_rdatatype_soa;
12119                 else
12120                         xfrtype = dns_rdatatype_axfr;
12121         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
12122                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12123                              "forced reload, requesting AXFR of "
12124                              "initial version from %s", master);
12125                 xfrtype = dns_rdatatype_axfr;
12126         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
12127                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12128                              "retrying with AXFR from %s due to "
12129                              "previous IXFR failure", master);
12130                 xfrtype = dns_rdatatype_axfr;
12131                 LOCK_ZONE(zone);
12132                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
12133                 UNLOCK_ZONE(zone);
12134         } else {
12135                 isc_boolean_t use_ixfr = ISC_TRUE;
12136                 if (peer != NULL &&
12137                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
12138                     ISC_R_SUCCESS) {
12139                         ; /* Using peer setting */
12140                 } else {
12141                         use_ixfr = zone->view->requestixfr;
12142                 }
12143                 if (use_ixfr == ISC_FALSE) {
12144                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12145                                      "IXFR disabled, requesting %sAXFR from %s",
12146                                      soa_before, master);
12147                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
12148                                 xfrtype = dns_rdatatype_soa;
12149                         else
12150                                 xfrtype = dns_rdatatype_axfr;
12151                 } else {
12152                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12153                                      "requesting IXFR from %s", master);
12154                         xfrtype = dns_rdatatype_ixfr;
12155                 }
12156         }
12157
12158         /*
12159          * Determine if we should attempt to sign the request with TSIG.
12160          */
12161         result = ISC_R_NOTFOUND;
12162         /*
12163          * First, look for a tsig key in the master statement, then
12164          * try for a server key.
12165          */
12166         if ((zone->masterkeynames != NULL) &&
12167             (zone->masterkeynames[zone->curmaster] != NULL)) {
12168                 dns_view_t *view = dns_zone_getview(zone);
12169                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12170                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
12171         }
12172         if (zone->tsigkey == NULL)
12173                 result = dns_view_getpeertsig(zone->view, &masterip,
12174                                               &zone->tsigkey);
12175
12176         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12177                 dns_zone_log(zone, ISC_LOG_ERROR,
12178                              "could not get TSIG key for zone transfer: %s",
12179                              isc_result_totext(result));
12180         }
12181
12182         LOCK_ZONE(zone);
12183         masteraddr = zone->masteraddr;
12184         sourceaddr = zone->sourceaddr;
12185         UNLOCK_ZONE(zone);
12186         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
12187         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
12188                                    zone->tsigkey, zone->mctx,
12189                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
12190                                    zone->task, zone_xfrdone, &zone->xfr);
12191         if (result == ISC_R_SUCCESS) {
12192                 LOCK_ZONE(zone);
12193                 if (xfrtype == dns_rdatatype_axfr) {
12194                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12195                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
12196                         else
12197                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
12198                 } else if (xfrtype == dns_rdatatype_ixfr) {
12199                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12200                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
12201                         else
12202                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
12203                 }
12204                 UNLOCK_ZONE(zone);
12205         }
12206  cleanup:
12207         /*
12208          * Any failure in this function is handled like a failed
12209          * zone transfer.  This ensures that we get removed from
12210          * zmgr->xfrin_in_progress.
12211          */
12212         if (result != ISC_R_SUCCESS)
12213                 zone_xfrdone(zone, result);
12214
12215         isc_event_free(&event);
12216 }
12217
12218 /*
12219  * Update forwarding support.
12220  */
12221
12222 static void
12223 forward_destroy(dns_forward_t *forward) {
12224
12225         forward->magic = 0;
12226         if (forward->request != NULL)
12227                 dns_request_destroy(&forward->request);
12228         if (forward->msgbuf != NULL)
12229                 isc_buffer_free(&forward->msgbuf);
12230         if (forward->zone != NULL)
12231                 dns_zone_idetach(&forward->zone);
12232         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
12233 }
12234
12235 static isc_result_t
12236 sendtomaster(dns_forward_t *forward) {
12237         isc_result_t result;
12238         isc_sockaddr_t src;
12239
12240         LOCK_ZONE(forward->zone);
12241         if (forward->which >= forward->zone->masterscnt) {
12242                 UNLOCK_ZONE(forward->zone);
12243                 return (ISC_R_NOMORE);
12244         }
12245
12246         forward->addr = forward->zone->masters[forward->which];
12247         /*
12248          * Always use TCP regardless of whether the original update
12249          * used TCP.
12250          * XXX The timeout may but a bit small if we are far down a
12251          * transfer graph and the master has to try several masters.
12252          */
12253         switch (isc_sockaddr_pf(&forward->addr)) {
12254         case PF_INET:
12255                 src = forward->zone->xfrsource4;
12256                 break;
12257         case PF_INET6:
12258                 src = forward->zone->xfrsource6;
12259                 break;
12260         default:
12261                 result = ISC_R_NOTIMPLEMENTED;
12262                 goto unlock;
12263         }
12264         result = dns_request_createraw(forward->zone->view->requestmgr,
12265                                        forward->msgbuf,
12266                                        &src, &forward->addr,
12267                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
12268                                        forward->zone->task,
12269                                        forward_callback, forward,
12270                                        &forward->request);
12271  unlock:
12272         UNLOCK_ZONE(forward->zone);
12273         return (result);
12274 }
12275
12276 static void
12277 forward_callback(isc_task_t *task, isc_event_t *event) {
12278         const char me[] = "forward_callback";
12279         dns_requestevent_t *revent = (dns_requestevent_t *)event;
12280         dns_message_t *msg = NULL;
12281         char master[ISC_SOCKADDR_FORMATSIZE];
12282         isc_result_t result;
12283         dns_forward_t *forward;
12284         dns_zone_t *zone;
12285
12286         UNUSED(task);
12287
12288         forward = revent->ev_arg;
12289         INSIST(DNS_FORWARD_VALID(forward));
12290         zone = forward->zone;
12291         INSIST(DNS_ZONE_VALID(zone));
12292
12293         ENTER;
12294
12295         isc_sockaddr_format(&forward->addr, master, sizeof(master));
12296
12297         if (revent->result != ISC_R_SUCCESS) {
12298                 dns_zone_log(zone, ISC_LOG_INFO,
12299                              "could not forward dynamic update to %s: %s",
12300                              master, dns_result_totext(revent->result));
12301                 goto next_master;
12302         }
12303
12304         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12305         if (result != ISC_R_SUCCESS)
12306                 goto next_master;
12307
12308         result = dns_request_getresponse(revent->request, msg,
12309                                          DNS_MESSAGEPARSE_PRESERVEORDER |
12310                                          DNS_MESSAGEPARSE_CLONEBUFFER);
12311         if (result != ISC_R_SUCCESS)
12312                 goto next_master;
12313
12314         switch (msg->rcode) {
12315         /*
12316          * Pass these rcodes back to client.
12317          */
12318         case dns_rcode_noerror:
12319         case dns_rcode_yxdomain:
12320         case dns_rcode_yxrrset:
12321         case dns_rcode_nxrrset:
12322         case dns_rcode_refused:
12323         case dns_rcode_nxdomain:
12324                 break;
12325
12326         /* These should not occur if the masters/zone are valid. */
12327         case dns_rcode_notzone:
12328         case dns_rcode_notauth: {
12329                 char rcode[128];
12330                 isc_buffer_t rb;
12331
12332                 isc_buffer_init(&rb, rcode, sizeof(rcode));
12333                 (void)dns_rcode_totext(msg->rcode, &rb);
12334                 dns_zone_log(zone, ISC_LOG_WARNING,
12335                              "forwarding dynamic update: "
12336                              "unexpected response: master %s returned: %.*s",
12337                              master, (int)rb.used, rcode);
12338                 goto next_master;
12339         }
12340
12341         /* Try another server for these rcodes. */
12342         case dns_rcode_formerr:
12343         case dns_rcode_servfail:
12344         case dns_rcode_notimp:
12345         case dns_rcode_badvers:
12346         default:
12347                 goto next_master;
12348         }
12349
12350         /* call callback */
12351         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
12352         msg = NULL;
12353         dns_request_destroy(&forward->request);
12354         forward_destroy(forward);
12355         isc_event_free(&event);
12356         return;
12357
12358  next_master:
12359         if (msg != NULL)
12360                 dns_message_destroy(&msg);
12361         isc_event_free(&event);
12362         forward->which++;
12363         dns_request_destroy(&forward->request);
12364         result = sendtomaster(forward);
12365         if (result != ISC_R_SUCCESS) {
12366                 /* call callback */
12367                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
12368                              "exhausted dynamic update forwarder list");
12369                 (forward->callback)(forward->callback_arg, result, NULL);
12370                 forward_destroy(forward);
12371         }
12372 }
12373
12374 isc_result_t
12375 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
12376                        dns_updatecallback_t callback, void *callback_arg)
12377 {
12378         dns_forward_t *forward;
12379         isc_result_t result;
12380         isc_region_t *mr;
12381
12382         REQUIRE(DNS_ZONE_VALID(zone));
12383         REQUIRE(msg != NULL);
12384         REQUIRE(callback != NULL);
12385
12386         forward = isc_mem_get(zone->mctx, sizeof(*forward));
12387         if (forward == NULL)
12388                 return (ISC_R_NOMEMORY);
12389
12390         forward->request = NULL;
12391         forward->zone = NULL;
12392         forward->msgbuf = NULL;
12393         forward->which = 0;
12394         forward->mctx = 0;
12395         forward->callback = callback;
12396         forward->callback_arg = callback_arg;
12397         forward->magic = FORWARD_MAGIC;
12398
12399         mr = dns_message_getrawmessage(msg);
12400         if (mr == NULL) {
12401                 result = ISC_R_UNEXPECTEDEND;
12402                 goto cleanup;
12403         }
12404
12405         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
12406         if (result != ISC_R_SUCCESS)
12407                 goto cleanup;
12408         result = isc_buffer_copyregion(forward->msgbuf, mr);
12409         if (result != ISC_R_SUCCESS)
12410                 goto cleanup;
12411
12412         isc_mem_attach(zone->mctx, &forward->mctx);
12413         dns_zone_iattach(zone, &forward->zone);
12414         result = sendtomaster(forward);
12415
12416  cleanup:
12417         if (result != ISC_R_SUCCESS) {
12418                 forward_destroy(forward);
12419         }
12420         return (result);
12421 }
12422
12423 isc_result_t
12424 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
12425         REQUIRE(DNS_ZONE_VALID(zone));
12426         REQUIRE(next != NULL && *next == NULL);
12427
12428         *next = ISC_LIST_NEXT(zone, link);
12429         if (*next == NULL)
12430                 return (ISC_R_NOMORE);
12431         else
12432                 return (ISC_R_SUCCESS);
12433 }
12434
12435 isc_result_t
12436 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
12437         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12438         REQUIRE(first != NULL && *first == NULL);
12439
12440         *first = ISC_LIST_HEAD(zmgr->zones);
12441         if (*first == NULL)
12442                 return (ISC_R_NOMORE);
12443         else
12444                 return (ISC_R_SUCCESS);
12445 }
12446
12447 /***
12448  ***    Zone manager.
12449  ***/
12450
12451 isc_result_t
12452 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
12453                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
12454                    dns_zonemgr_t **zmgrp)
12455 {
12456         dns_zonemgr_t *zmgr;
12457         isc_result_t result;
12458         isc_interval_t interval;
12459
12460         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
12461         if (zmgr == NULL)
12462                 return (ISC_R_NOMEMORY);
12463         zmgr->mctx = NULL;
12464         zmgr->refs = 1;
12465         isc_mem_attach(mctx, &zmgr->mctx);
12466         zmgr->taskmgr = taskmgr;
12467         zmgr->timermgr = timermgr;
12468         zmgr->socketmgr = socketmgr;
12469         zmgr->zonetasks = NULL;
12470         zmgr->task = NULL;
12471         zmgr->rl = NULL;
12472         ISC_LIST_INIT(zmgr->zones);
12473         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
12474         ISC_LIST_INIT(zmgr->xfrin_in_progress);
12475         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
12476         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
12477         if (result != ISC_R_SUCCESS)
12478                 goto free_mem;
12479
12480         zmgr->transfersin = 10;
12481         zmgr->transfersperns = 2;
12482
12483         /* Create a single task for queueing of SOA queries. */
12484         result = isc_task_create(taskmgr, 1, &zmgr->task);
12485         if (result != ISC_R_SUCCESS)
12486                 goto free_rwlock;
12487         isc_task_setname(zmgr->task, "zmgr", zmgr);
12488         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12489                                         &zmgr->rl);
12490         if (result != ISC_R_SUCCESS)
12491                 goto free_task;
12492         /* default to 20 refresh queries / notifies per second. */
12493         isc_interval_set(&interval, 0, 1000000000/2);
12494         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
12495         RUNTIME_CHECK(result == ISC_R_SUCCESS);
12496         isc_ratelimiter_setpertic(zmgr->rl, 10);
12497
12498         zmgr->iolimit = 1;
12499         zmgr->ioactive = 0;
12500         ISC_LIST_INIT(zmgr->high);
12501         ISC_LIST_INIT(zmgr->low);
12502
12503         result = isc_mutex_init(&zmgr->iolock);
12504         if (result != ISC_R_SUCCESS)
12505                 goto free_rl;
12506
12507         zmgr->magic = ZONEMGR_MAGIC;
12508
12509         *zmgrp = zmgr;
12510         return (ISC_R_SUCCESS);
12511
12512 #if 0
12513  free_iolock:
12514         DESTROYLOCK(&zmgr->iolock);
12515 #endif
12516  free_rl:
12517         isc_ratelimiter_detach(&zmgr->rl);
12518  free_task:
12519         isc_task_detach(&zmgr->task);
12520  free_rwlock:
12521         isc_rwlock_destroy(&zmgr->rwlock);
12522  free_mem:
12523         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12524         isc_mem_detach(&mctx);
12525         return (result);
12526 }
12527
12528 isc_result_t
12529 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12530         isc_result_t result;
12531
12532         REQUIRE(DNS_ZONE_VALID(zone));
12533         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12534
12535         if (zmgr->zonetasks == NULL)
12536                 return (ISC_R_FAILURE);
12537
12538         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12539         LOCK_ZONE(zone);
12540         REQUIRE(zone->task == NULL);
12541         REQUIRE(zone->timer == NULL);
12542         REQUIRE(zone->zmgr == NULL);
12543
12544         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
12545
12546         /*
12547          * Set the task name.  The tag will arbitrarily point to one
12548          * of the zones sharing the task (in practice, the one
12549          * to be managed last).
12550          */
12551         isc_task_setname(zone->task, "zone", zone);
12552
12553         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
12554                                   NULL, NULL,
12555                                   zone->task, zone_timer, zone,
12556                                   &zone->timer);
12557
12558         if (result != ISC_R_SUCCESS)
12559                 goto cleanup_task;
12560
12561         /*
12562          * The timer "holds" a iref.
12563          */
12564         zone->irefs++;
12565         INSIST(zone->irefs != 0);
12566
12567         ISC_LIST_APPEND(zmgr->zones, zone, link);
12568         zone->zmgr = zmgr;
12569         zmgr->refs++;
12570
12571         goto unlock;
12572
12573  cleanup_task:
12574         isc_task_detach(&zone->task);
12575
12576  unlock:
12577         UNLOCK_ZONE(zone);
12578         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12579         return (result);
12580 }
12581
12582 void
12583 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12584         isc_boolean_t free_now = ISC_FALSE;
12585
12586         REQUIRE(DNS_ZONE_VALID(zone));
12587         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12588         REQUIRE(zone->zmgr == zmgr);
12589
12590         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12591         LOCK_ZONE(zone);
12592
12593         ISC_LIST_UNLINK(zmgr->zones, zone, link);
12594         zone->zmgr = NULL;
12595         zmgr->refs--;
12596         if (zmgr->refs == 0)
12597                 free_now = ISC_TRUE;
12598
12599         UNLOCK_ZONE(zone);
12600         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12601
12602         if (free_now)
12603                 zonemgr_free(zmgr);
12604         ENSURE(zone->zmgr == NULL);
12605 }
12606
12607 void
12608 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
12609         REQUIRE(DNS_ZONEMGR_VALID(source));
12610         REQUIRE(target != NULL && *target == NULL);
12611
12612         RWLOCK(&source->rwlock, isc_rwlocktype_write);
12613         REQUIRE(source->refs > 0);
12614         source->refs++;
12615         INSIST(source->refs > 0);
12616         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
12617         *target = source;
12618 }
12619
12620 void
12621 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
12622         dns_zonemgr_t *zmgr;
12623         isc_boolean_t free_now = ISC_FALSE;
12624
12625         REQUIRE(zmgrp != NULL);
12626         zmgr = *zmgrp;
12627         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12628
12629         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12630         zmgr->refs--;
12631         if (zmgr->refs == 0)
12632                 free_now = ISC_TRUE;
12633         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12634
12635         if (free_now)
12636                 zonemgr_free(zmgr);
12637         *zmgrp = NULL;
12638 }
12639
12640 isc_result_t
12641 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
12642         dns_zone_t *p;
12643
12644         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12645
12646         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12647         for (p = ISC_LIST_HEAD(zmgr->zones);
12648              p != NULL;
12649              p = ISC_LIST_NEXT(p, link))
12650         {
12651                 dns_zone_maintenance(p);
12652         }
12653         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12654
12655         /*
12656          * Recent configuration changes may have increased the
12657          * amount of available transfers quota.  Make sure any
12658          * transfers currently blocked on quota get started if
12659          * possible.
12660          */
12661         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12662         zmgr_resume_xfrs(zmgr, ISC_TRUE);
12663         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12664         return (ISC_R_SUCCESS);
12665 }
12666
12667 void
12668 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
12669
12670         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12671
12672         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12673         zmgr_resume_xfrs(zmgr, ISC_TRUE);
12674         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12675 }
12676
12677 void
12678 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
12679         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12680
12681         isc_ratelimiter_shutdown(zmgr->rl);
12682
12683         if (zmgr->task != NULL)
12684                 isc_task_destroy(&zmgr->task);
12685         if (zmgr->zonetasks != NULL)
12686                 isc_taskpool_destroy(&zmgr->zonetasks);
12687 }
12688
12689 isc_result_t
12690 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
12691         isc_result_t result;
12692         int ntasks = num_zones / 100;
12693         isc_taskpool_t *pool = NULL;
12694
12695         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12696
12697         /*
12698          * For anything fewer than 1000 zones we use 10 tasks in
12699          * the task pool.  More than that, and we'll scale at one
12700          * task per 100 zones.
12701          */
12702         if (ntasks < 10)
12703                 ntasks = 10;
12704
12705         /* Create or resize the zone task pool. */
12706         if (zmgr->zonetasks == NULL)
12707                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
12708                                              ntasks, 2, &pool);
12709         else
12710                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
12711
12712         if (result == ISC_R_SUCCESS)
12713                 zmgr->zonetasks = pool;
12714
12715         return (result);
12716 }
12717
12718 static void
12719 zonemgr_free(dns_zonemgr_t *zmgr) {
12720         isc_mem_t *mctx;
12721
12722         INSIST(zmgr->refs == 0);
12723         INSIST(ISC_LIST_EMPTY(zmgr->zones));
12724
12725         zmgr->magic = 0;
12726
12727         DESTROYLOCK(&zmgr->iolock);
12728         isc_ratelimiter_detach(&zmgr->rl);
12729
12730         isc_rwlock_destroy(&zmgr->rwlock);
12731         mctx = zmgr->mctx;
12732         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12733         isc_mem_detach(&mctx);
12734 }
12735
12736 void
12737 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12738         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12739
12740         zmgr->transfersin = value;
12741 }
12742
12743 isc_uint32_t
12744 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
12745         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12746
12747         return (zmgr->transfersin);
12748 }
12749
12750 void
12751 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12752         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12753
12754         zmgr->transfersperns = value;
12755 }
12756
12757 isc_uint32_t
12758 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
12759         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12760
12761         return (zmgr->transfersperns);
12762 }
12763
12764 /*
12765  * Try to start a new incoming zone transfer to fill a quota
12766  * slot that was just vacated.
12767  *
12768  * Requires:
12769  *      The zone manager is locked by the caller.
12770  */
12771 static void
12772 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
12773         dns_zone_t *zone;
12774         dns_zone_t *next;
12775
12776         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
12777              zone != NULL;
12778              zone = next)
12779         {
12780                 isc_result_t result;
12781                 next = ISC_LIST_NEXT(zone, statelink);
12782                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
12783                 if (result == ISC_R_SUCCESS) {
12784                         if (multi)
12785                                 continue;
12786                         /*
12787                          * We successfully filled the slot.  We're done.
12788                          */
12789                         break;
12790                 } else if (result == ISC_R_QUOTA) {
12791                         /*
12792                          * Not enough quota.  This is probably the per-server
12793                          * quota, because we usually get called when a unit of
12794                          * global quota has just been freed.  Try the next
12795                          * zone, it may succeed if it uses another master.
12796                          */
12797                         continue;
12798                 } else {
12799                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
12800                                      "starting zone transfer: %s",
12801                                      isc_result_totext(result));
12802                         break;
12803                 }
12804         }
12805 }
12806
12807 /*
12808  * Try to start an incoming zone transfer for 'zone', quota permitting.
12809  *
12810  * Requires:
12811  *      The zone manager is locked by the caller.
12812  *
12813  * Returns:
12814  *      ISC_R_SUCCESS   There was enough quota and we attempted to
12815  *                      start a transfer.  zone_xfrdone() has been or will
12816  *                      be called.
12817  *      ISC_R_QUOTA     Not enough quota.
12818  *      Others          Failure.
12819  */
12820 static isc_result_t
12821 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12822         dns_peer_t *peer = NULL;
12823         isc_netaddr_t masterip;
12824         isc_uint32_t nxfrsin, nxfrsperns;
12825         dns_zone_t *x;
12826         isc_uint32_t maxtransfersin, maxtransfersperns;
12827         isc_event_t *e;
12828
12829         /*
12830          * Find any configured information about the server we'd
12831          * like to transfer this zone from.
12832          */
12833         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12834         (void)dns_peerlist_peerbyaddr(zone->view->peers,
12835                                       &masterip, &peer);
12836
12837         /*
12838          * Determine the total maximum number of simultaneous
12839          * transfers allowed, and the maximum for this specific
12840          * master.
12841          */
12842         maxtransfersin = zmgr->transfersin;
12843         maxtransfersperns = zmgr->transfersperns;
12844         if (peer != NULL)
12845                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
12846
12847         /*
12848          * Count the total number of transfers that are in progress,
12849          * and the number of transfers in progress from this master.
12850          * We linearly scan a list of all transfers; if this turns
12851          * out to be too slow, we could hash on the master address.
12852          */
12853         nxfrsin = nxfrsperns = 0;
12854         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
12855              x != NULL;
12856              x = ISC_LIST_NEXT(x, statelink))
12857         {
12858                 isc_netaddr_t xip;
12859                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
12860                 nxfrsin++;
12861                 if (isc_netaddr_equal(&xip, &masterip))
12862                         nxfrsperns++;
12863         }
12864
12865         /* Enforce quota. */
12866         if (nxfrsin >= maxtransfersin)
12867                 return (ISC_R_QUOTA);
12868
12869         if (nxfrsperns >= maxtransfersperns)
12870                 return (ISC_R_QUOTA);
12871
12872         /*
12873          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
12874          * list and send it an event to let it start the actual transfer in the
12875          * context of its own task.
12876          */
12877         e = isc_event_allocate(zmgr->mctx, zmgr,
12878                                DNS_EVENT_ZONESTARTXFRIN,
12879                                got_transfer_quota, zone,
12880                                sizeof(isc_event_t));
12881         if (e == NULL)
12882                 return (ISC_R_NOMEMORY);
12883
12884         LOCK_ZONE(zone);
12885         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
12886         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
12887         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
12888         zone->statelist = &zmgr->xfrin_in_progress;
12889         isc_task_send(zone->task, &e);
12890         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
12891         UNLOCK_ZONE(zone);
12892
12893         return (ISC_R_SUCCESS);
12894 }
12895
12896 void
12897 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
12898
12899         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12900         REQUIRE(iolimit > 0);
12901
12902         zmgr->iolimit = iolimit;
12903 }
12904
12905 isc_uint32_t
12906 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
12907
12908         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12909
12910         return (zmgr->iolimit);
12911 }
12912
12913 /*
12914  * Get permission to request a file handle from the OS.
12915  * An event will be sent to action when one is available.
12916  * There are two queues available (high and low), the high
12917  * queue will be serviced before the low one.
12918  *
12919  * zonemgr_putio() must be called after the event is delivered to
12920  * 'action'.
12921  */
12922
12923 static isc_result_t
12924 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
12925               isc_task_t *task, isc_taskaction_t action, void *arg,
12926               dns_io_t **iop)
12927 {
12928         dns_io_t *io;
12929         isc_boolean_t queue;
12930
12931         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12932         REQUIRE(iop != NULL && *iop == NULL);
12933
12934         io = isc_mem_get(zmgr->mctx, sizeof(*io));
12935         if (io == NULL)
12936                 return (ISC_R_NOMEMORY);
12937         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
12938                                        action, arg, sizeof(*io->event));
12939         if (io->event == NULL) {
12940                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
12941                 return (ISC_R_NOMEMORY);
12942         }
12943         io->zmgr = zmgr;
12944         io->high = high;
12945         io->task = NULL;
12946         isc_task_attach(task, &io->task);
12947         ISC_LINK_INIT(io, link);
12948         io->magic = IO_MAGIC;
12949
12950         LOCK(&zmgr->iolock);
12951         zmgr->ioactive++;
12952         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
12953         if (queue) {
12954                 if (io->high)
12955                         ISC_LIST_APPEND(zmgr->high, io, link);
12956                 else
12957                         ISC_LIST_APPEND(zmgr->low, io, link);
12958         }
12959         UNLOCK(&zmgr->iolock);
12960         *iop = io;
12961
12962         if (!queue) {
12963                 isc_task_send(io->task, &io->event);
12964         }
12965         return (ISC_R_SUCCESS);
12966 }
12967
12968 static void
12969 zonemgr_putio(dns_io_t **iop) {
12970         dns_io_t *io;
12971         dns_io_t *next;
12972         dns_zonemgr_t *zmgr;
12973
12974         REQUIRE(iop != NULL);
12975         io = *iop;
12976         REQUIRE(DNS_IO_VALID(io));
12977
12978         *iop = NULL;
12979
12980         INSIST(!ISC_LINK_LINKED(io, link));
12981         INSIST(io->event == NULL);
12982
12983         zmgr = io->zmgr;
12984         isc_task_detach(&io->task);
12985         io->magic = 0;
12986         isc_mem_put(zmgr->mctx, io, sizeof(*io));
12987
12988         LOCK(&zmgr->iolock);
12989         INSIST(zmgr->ioactive > 0);
12990         zmgr->ioactive--;
12991         next = HEAD(zmgr->high);
12992         if (next == NULL)
12993                 next = HEAD(zmgr->low);
12994         if (next != NULL) {
12995                 if (next->high)
12996                         ISC_LIST_UNLINK(zmgr->high, next, link);
12997                 else
12998                         ISC_LIST_UNLINK(zmgr->low, next, link);
12999                 INSIST(next->event != NULL);
13000         }
13001         UNLOCK(&zmgr->iolock);
13002         if (next != NULL)
13003                 isc_task_send(next->task, &next->event);
13004 }
13005
13006 static void
13007 zonemgr_cancelio(dns_io_t *io) {
13008         isc_boolean_t send_event = ISC_FALSE;
13009
13010         REQUIRE(DNS_IO_VALID(io));
13011
13012         /*
13013          * If we are queued to be run then dequeue.
13014          */
13015         LOCK(&io->zmgr->iolock);
13016         if (ISC_LINK_LINKED(io, link)) {
13017                 if (io->high)
13018                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
13019                 else
13020                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
13021
13022                 send_event = ISC_TRUE;
13023                 INSIST(io->event != NULL);
13024         }
13025         UNLOCK(&io->zmgr->iolock);
13026         if (send_event) {
13027                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
13028                 isc_task_send(io->task, &io->event);
13029         }
13030 }
13031
13032 static void
13033 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
13034         char *buf;
13035         int buflen;
13036         isc_result_t result;
13037
13038         buflen = strlen(path) + strlen(templat) + 2;
13039
13040         buf = isc_mem_get(zone->mctx, buflen);
13041         if (buf == NULL)
13042                 return;
13043
13044         result = isc_file_template(path, templat, buf, buflen);
13045         if (result != ISC_R_SUCCESS)
13046                 goto cleanup;
13047
13048         result = isc_file_renameunique(path, buf);
13049         if (result != ISC_R_SUCCESS)
13050                 goto cleanup;
13051
13052         dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
13053                      path, buf);
13054
13055  cleanup:
13056         isc_mem_put(zone->mctx, buf, buflen);
13057 }
13058
13059 #if 0
13060 /* Hook for ondestroy notification from a database. */
13061
13062 static void
13063 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
13064         dns_db_t *db = event->sender;
13065         UNUSED(task);
13066
13067         isc_event_free(&event);
13068
13069         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13070                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13071                       "database (%p) destroyed", (void*) db);
13072 }
13073 #endif
13074
13075 void
13076 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
13077         isc_interval_t interval;
13078         isc_uint32_t s, ns;
13079         isc_uint32_t pertic;
13080         isc_result_t result;
13081
13082         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13083
13084         if (value == 0)
13085                 value = 1;
13086
13087         if (value == 1) {
13088                 s = 1;
13089                 ns = 0;
13090                 pertic = 1;
13091         } else if (value <= 10) {
13092                 s = 0;
13093                 ns = 1000000000 / value;
13094                 pertic = 1;
13095         } else {
13096                 s = 0;
13097                 ns = (1000000000 / value) * 10;
13098                 pertic = 10;
13099         }
13100
13101         isc_interval_set(&interval, s, ns);
13102         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
13103         RUNTIME_CHECK(result == ISC_R_SUCCESS);
13104         isc_ratelimiter_setpertic(zmgr->rl, pertic);
13105
13106         zmgr->serialqueryrate = value;
13107 }
13108
13109 unsigned int
13110 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
13111         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13112
13113         return (zmgr->serialqueryrate);
13114 }
13115
13116 static isc_boolean_t
13117 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13118                         isc_sockaddr_t *local, isc_time_t *now)
13119 {
13120         unsigned int i;
13121         isc_rwlocktype_t locktype;
13122         isc_result_t result;
13123         isc_uint32_t seconds = isc_time_seconds(now);
13124
13125         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13126
13127         locktype = isc_rwlocktype_read;
13128         RWLOCK(&zmgr->rwlock, locktype);
13129         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13130                 if (zmgr->unreachable[i].expire >= seconds &&
13131                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13132                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
13133                         result = isc_rwlock_tryupgrade(&zmgr->rwlock);
13134                         if (result == ISC_R_SUCCESS) {
13135                                 locktype = isc_rwlocktype_write;
13136                                 zmgr->unreachable[i].last = seconds;
13137                         }
13138                         break;
13139                 }
13140         }
13141         RWUNLOCK(&zmgr->rwlock, locktype);
13142         return (ISC_TF(i < UNREACH_CHACHE_SIZE));
13143 }
13144
13145 void
13146 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
13147                            isc_sockaddr_t *local, isc_time_t *now)
13148 {
13149         isc_uint32_t seconds = isc_time_seconds(now);
13150         isc_uint32_t last = seconds;
13151         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
13152
13153         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13154
13155         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13156         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
13157                 /* Existing entry? */
13158                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
13159                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
13160                         break;
13161                 /* Empty slot? */
13162                 if (zmgr->unreachable[i].expire < seconds)
13163                         slot = i;
13164                 /* Least recently used slot? */
13165                 if (zmgr->unreachable[i].last < last) {
13166                         last = zmgr->unreachable[i].last;
13167                         oldest = i;
13168                 }
13169         }
13170         if (i < UNREACH_CHACHE_SIZE) {
13171                 /*
13172                  * Found a existing entry.  Update the expire timer and
13173                  * last usage timestamps.
13174                  */
13175                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
13176                 zmgr->unreachable[i].last = seconds;
13177         } else if (slot != UNREACH_CHACHE_SIZE) {
13178                 /*
13179                  * Found a empty slot. Add a new entry to the cache.
13180                  */
13181                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
13182                 zmgr->unreachable[slot].last = seconds;
13183                 zmgr->unreachable[slot].remote = *remote;
13184                 zmgr->unreachable[slot].local = *local;
13185         } else {
13186                 /*
13187                  * Replace the least recently used entry in the cache.
13188                  */
13189                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
13190                 zmgr->unreachable[oldest].last = seconds;
13191                 zmgr->unreachable[oldest].remote = *remote;
13192                 zmgr->unreachable[oldest].local = *local;
13193         }
13194         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
13195 }
13196
13197 void
13198 dns_zone_forcereload(dns_zone_t *zone) {
13199         REQUIRE(DNS_ZONE_VALID(zone));
13200
13201         if (zone->type == dns_zone_master)
13202                 return;
13203
13204         LOCK_ZONE(zone);
13205         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13206         UNLOCK_ZONE(zone);
13207         dns_zone_refresh(zone);
13208 }
13209
13210 isc_boolean_t
13211 dns_zone_isforced(dns_zone_t *zone) {
13212         REQUIRE(DNS_ZONE_VALID(zone));
13213
13214         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
13215 }
13216
13217 isc_result_t
13218 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
13219         /*
13220          * This function is obsoleted.
13221          */
13222         UNUSED(zone);
13223         UNUSED(on);
13224         return (ISC_R_NOTIMPLEMENTED);
13225 }
13226
13227 isc_uint64_t *
13228 dns_zone_getstatscounters(dns_zone_t *zone) {
13229         /*
13230          * This function is obsoleted.
13231          */
13232         UNUSED(zone);
13233         return (NULL);
13234 }
13235
13236 void
13237 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
13238         REQUIRE(DNS_ZONE_VALID(zone));
13239         REQUIRE(zone->stats == NULL);
13240
13241         LOCK_ZONE(zone);
13242         zone->stats = NULL;
13243         isc_stats_attach(stats, &zone->stats);
13244         UNLOCK_ZONE(zone);
13245 }
13246
13247 void
13248 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
13249         REQUIRE(DNS_ZONE_VALID(zone));
13250
13251         LOCK_ZONE(zone);
13252         if (zone->requeststats_on && stats == NULL)
13253                 zone->requeststats_on = ISC_FALSE;
13254         else if (!zone->requeststats_on && stats != NULL) {
13255                 if (zone->requeststats == NULL) {
13256                         isc_stats_attach(stats, &zone->requeststats);
13257                         zone->requeststats_on = ISC_TRUE;
13258                 }
13259         }
13260         UNLOCK_ZONE(zone);
13261
13262         return;
13263 }
13264
13265 isc_stats_t *
13266 dns_zone_getrequeststats(dns_zone_t *zone) {
13267         /*
13268          * We don't lock zone for efficiency reason.  This is not catastrophic
13269          * because requeststats must always be valid when requeststats_on is
13270          * true.
13271          * Some counters may be incremented while requeststats_on is becoming
13272          * false, or some cannot be incremented just after the statistics are
13273          * installed, but it shouldn't matter much in practice.
13274          */
13275         if (zone->requeststats_on)
13276                 return (zone->requeststats);
13277         else
13278                 return (NULL);
13279 }
13280
13281 void
13282 dns_zone_dialup(dns_zone_t *zone) {
13283
13284         REQUIRE(DNS_ZONE_VALID(zone));
13285
13286         zone_debuglog(zone, "dns_zone_dialup", 3,
13287                       "notify = %d, refresh = %d",
13288                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
13289                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
13290
13291         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
13292                 dns_zone_notify(zone);
13293         if (zone->type != dns_zone_master &&
13294             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13295                 dns_zone_refresh(zone);
13296 }
13297
13298 void
13299 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
13300         REQUIRE(DNS_ZONE_VALID(zone));
13301
13302         LOCK_ZONE(zone);
13303         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
13304                          DNS_ZONEFLG_DIALREFRESH |
13305                          DNS_ZONEFLG_NOREFRESH);
13306         switch (dialup) {
13307         case dns_dialuptype_no:
13308                 break;
13309         case dns_dialuptype_yes:
13310                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
13311                                  DNS_ZONEFLG_DIALREFRESH |
13312                                  DNS_ZONEFLG_NOREFRESH));
13313                 break;
13314         case dns_dialuptype_notify:
13315                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13316                 break;
13317         case dns_dialuptype_notifypassive:
13318                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13319                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13320                 break;
13321         case dns_dialuptype_refresh:
13322                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
13323                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13324                 break;
13325         case dns_dialuptype_passive:
13326                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13327                 break;
13328         default:
13329                 INSIST(0);
13330         }
13331         UNLOCK_ZONE(zone);
13332 }
13333
13334 isc_result_t
13335 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
13336         isc_result_t result = ISC_R_SUCCESS;
13337
13338         REQUIRE(DNS_ZONE_VALID(zone));
13339
13340         LOCK_ZONE(zone);
13341         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
13342         UNLOCK_ZONE(zone);
13343
13344         return (result);
13345 }
13346
13347 const char *
13348 dns_zone_getkeydirectory(dns_zone_t *zone) {
13349         REQUIRE(DNS_ZONE_VALID(zone));
13350
13351         return (zone->keydirectory);
13352 }
13353
13354 unsigned int
13355 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
13356         dns_zone_t *zone;
13357         unsigned int count = 0;
13358
13359         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13360
13361         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13362         switch (state) {
13363         case DNS_ZONESTATE_XFERRUNNING:
13364                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13365                      zone != NULL;
13366                      zone = ISC_LIST_NEXT(zone, statelink))
13367                         count++;
13368                 break;
13369         case DNS_ZONESTATE_XFERDEFERRED:
13370                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13371                      zone != NULL;
13372                      zone = ISC_LIST_NEXT(zone, statelink))
13373                         count++;
13374                 break;
13375         case DNS_ZONESTATE_SOAQUERY:
13376                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13377                      zone != NULL;
13378                      zone = ISC_LIST_NEXT(zone, link))
13379                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
13380                                 count++;
13381                 break;
13382         case DNS_ZONESTATE_ANY:
13383                 for (zone = ISC_LIST_HEAD(zmgr->zones);
13384                      zone != NULL;
13385                      zone = ISC_LIST_NEXT(zone, link)) {
13386                         dns_view_t *view = zone->view;
13387                         if (view != NULL && strcmp(view->name, "_bind") == 0)
13388                                 continue;
13389                         count++;
13390                 }
13391                 break;
13392         default:
13393                 INSIST(0);
13394         }
13395
13396         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13397
13398         return (count);
13399 }
13400
13401 isc_result_t
13402 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
13403         isc_boolean_t ok = ISC_TRUE;
13404         isc_boolean_t fail = ISC_FALSE;
13405         char namebuf[DNS_NAME_FORMATSIZE];
13406         char namebuf2[DNS_NAME_FORMATSIZE];
13407         char typebuf[DNS_RDATATYPE_FORMATSIZE];
13408         int level = ISC_LOG_WARNING;
13409         dns_name_t bad;
13410
13411         REQUIRE(DNS_ZONE_VALID(zone));
13412
13413         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
13414                 return (ISC_R_SUCCESS);
13415
13416         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
13417                 level = ISC_LOG_ERROR;
13418                 fail = ISC_TRUE;
13419         }
13420
13421         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
13422         if (!ok) {
13423                 dns_name_format(name, namebuf, sizeof(namebuf));
13424                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13425                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
13426                              dns_result_totext(DNS_R_BADOWNERNAME));
13427                 if (fail)
13428                         return (DNS_R_BADOWNERNAME);
13429         }
13430
13431         dns_name_init(&bad, NULL);
13432         ok = dns_rdata_checknames(rdata, name, &bad);
13433         if (!ok) {
13434                 dns_name_format(name, namebuf, sizeof(namebuf));
13435                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
13436                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13437                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
13438                              namebuf2, dns_result_totext(DNS_R_BADNAME));
13439                 if (fail)
13440                         return (DNS_R_BADNAME);
13441         }
13442
13443         return (ISC_R_SUCCESS);
13444 }
13445
13446 void
13447 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
13448         REQUIRE(DNS_ZONE_VALID(zone));
13449         zone->checkmx = checkmx;
13450 }
13451
13452 void
13453 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
13454         REQUIRE(DNS_ZONE_VALID(zone));
13455         zone->checksrv = checksrv;
13456 }
13457
13458 void
13459 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
13460         REQUIRE(DNS_ZONE_VALID(zone));
13461         zone->checkns = checkns;
13462 }
13463
13464 void
13465 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
13466         REQUIRE(DNS_ZONE_VALID(zone));
13467
13468         LOCK_ZONE(zone);
13469         zone->isself = isself;
13470         zone->isselfarg = arg;
13471         UNLOCK_ZONE(zone);
13472 }
13473
13474 void
13475 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
13476         REQUIRE(DNS_ZONE_VALID(zone));
13477
13478         LOCK_ZONE(zone);
13479         zone->notifydelay = delay;
13480         UNLOCK_ZONE(zone);
13481 }
13482
13483 isc_uint32_t
13484 dns_zone_getnotifydelay(dns_zone_t *zone) {
13485         REQUIRE(DNS_ZONE_VALID(zone));
13486
13487         return (zone->notifydelay);
13488 }
13489
13490 isc_result_t
13491 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
13492                      isc_uint16_t keyid, isc_boolean_t delete)
13493 {
13494         isc_result_t result;
13495         REQUIRE(DNS_ZONE_VALID(zone));
13496
13497         dns_zone_log(zone, ISC_LOG_NOTICE,
13498                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
13499                      algorithm, keyid);
13500         LOCK_ZONE(zone);
13501         result = zone_signwithkey(zone, algorithm, keyid, delete);
13502         UNLOCK_ZONE(zone);
13503
13504         return (result);
13505 }
13506
13507 static const char *hex = "0123456789ABCDEF";
13508
13509 isc_result_t
13510 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
13511         isc_result_t result;
13512         char salt[255*2+1];
13513         unsigned int i, j;
13514
13515         REQUIRE(DNS_ZONE_VALID(zone));
13516
13517         if (nsec3param->salt_length != 0) {
13518                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
13519                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
13520                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
13521                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
13522                 }
13523                 salt[j] = '\0';
13524         } else
13525                 strcpy(salt, "-");
13526         dns_zone_log(zone, ISC_LOG_NOTICE,
13527                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
13528                      nsec3param->hash, nsec3param->iterations,
13529                      salt);
13530         LOCK_ZONE(zone);
13531         result = zone_addnsec3chain(zone, nsec3param);
13532         UNLOCK_ZONE(zone);
13533
13534         return (result);
13535 }
13536
13537 void
13538 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
13539         REQUIRE(DNS_ZONE_VALID(zone));
13540
13541         if (nodes == 0)
13542                 nodes = 1;
13543         zone->nodes = nodes;
13544 }
13545
13546 void
13547 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
13548         REQUIRE(DNS_ZONE_VALID(zone));
13549
13550         /*
13551          * We treat signatures as a signed value so explicitly
13552          * limit its range here.
13553          */
13554         if (signatures > ISC_INT32_MAX)
13555                 signatures = ISC_INT32_MAX;
13556         else if (signatures == 0)
13557                 signatures = 1;
13558         zone->signatures = signatures;
13559 }
13560
13561 void
13562 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
13563         REQUIRE(DNS_ZONE_VALID(zone));
13564         zone->privatetype = type;
13565 }
13566
13567 dns_rdatatype_t
13568 dns_zone_getprivatetype(dns_zone_t *zone) {
13569         REQUIRE(DNS_ZONE_VALID(zone));
13570         return (zone->privatetype);
13571 }
13572
13573 static isc_result_t
13574 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
13575                  isc_boolean_t delete)
13576 {
13577         dns_signing_t *signing;
13578         dns_signing_t *current;
13579         isc_result_t result = ISC_R_SUCCESS;
13580         isc_time_t now;
13581
13582         signing = isc_mem_get(zone->mctx, sizeof *signing);
13583         if (signing == NULL)
13584                 return (ISC_R_NOMEMORY);
13585
13586         signing->magic = 0;
13587         signing->db  = NULL;
13588         signing->dbiterator = NULL;
13589         signing->algorithm = algorithm;
13590         signing->keyid = keyid;
13591         signing->delete = delete;
13592         signing->done = ISC_FALSE;
13593
13594         TIME_NOW(&now);
13595
13596         for (current = ISC_LIST_HEAD(zone->signing);
13597              current != NULL;
13598              current = ISC_LIST_NEXT(current, link)) {
13599                 if (current->db == zone->db &&
13600                     current->algorithm == signing->algorithm &&
13601                     current->keyid == signing->keyid) {
13602                         if (current->delete != signing->delete)
13603                                 current->done = ISC_TRUE;
13604                         else
13605                                 goto cleanup;
13606                 }
13607         }
13608
13609         if (zone->db != NULL) {
13610                 dns_db_attach(zone->db, &signing->db);
13611                 result = dns_db_createiterator(signing->db, 0,
13612                                                &signing->dbiterator);
13613
13614                 if (result == ISC_R_SUCCESS)
13615                         result = dns_dbiterator_first(signing->dbiterator);
13616                 if (result == ISC_R_SUCCESS) {
13617                         dns_dbiterator_pause(signing->dbiterator);
13618                         ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
13619                         signing = NULL;
13620                         if (isc_time_isepoch(&zone->signingtime)) {
13621                                 zone->signingtime = now;
13622                                 if (zone->task != NULL)
13623                                         zone_settimer(zone, &now);
13624                         }
13625                 }
13626         } else
13627                 result = ISC_R_NOTFOUND;
13628
13629  cleanup:
13630         if (signing != NULL) {
13631                 if (signing->db != NULL)
13632                         dns_db_detach(&signing->db);
13633                 if (signing->dbiterator != NULL)
13634                         dns_dbiterator_destroy(&signing->dbiterator);
13635                 isc_mem_put(zone->mctx, signing, sizeof *signing);
13636         }
13637         return (result);
13638 }
13639
13640 static void
13641 logmsg(const char *format, ...) {
13642         va_list args;
13643         va_start(args, format);
13644         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13645                        ISC_LOG_DEBUG(1), format, args);
13646         va_end(args);
13647 }
13648
13649 static void
13650 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
13651         dns_dnsseckey_t *key;
13652         while (!ISC_LIST_EMPTY(*list)) {
13653                 key = ISC_LIST_HEAD(*list);
13654                 ISC_LIST_UNLINK(*list, key, link);
13655                 dns_dnsseckey_destroy(mctx, &key);
13656         }
13657 }
13658
13659 /* Called once; *timep should be set to the current time. */
13660 static isc_result_t
13661 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
13662         isc_result_t result;
13663         isc_stdtime_t now, then = 0, event;
13664         int i;
13665
13666         now = *timep;
13667
13668         for (i = 0; i <= DST_MAX_TIMES; i++) {
13669                 result = dst_key_gettime(key, i, &event);
13670                 if (result == ISC_R_SUCCESS && event > now &&
13671                     (then == 0 || event < then))
13672                         then = event;
13673         }
13674
13675         if (then != 0) {
13676                 *timep = then;
13677                 return (ISC_R_SUCCESS);
13678         }
13679
13680         return (ISC_R_NOTFOUND);
13681 }
13682
13683 static isc_result_t
13684 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
13685           const dns_rdata_t *rdata, isc_boolean_t *flag)
13686 {
13687         dns_rdataset_t rdataset;
13688         dns_dbnode_t *node = NULL;
13689         isc_result_t result;
13690
13691         dns_rdataset_init(&rdataset);
13692         if (rdata->type == dns_rdatatype_nsec3)
13693                 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
13694         else
13695                 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
13696         result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
13697                                      (isc_stdtime_t) 0, &rdataset, NULL);
13698         if (result == ISC_R_NOTFOUND) {
13699                 *flag = ISC_FALSE;
13700                 result = ISC_R_SUCCESS;
13701                 goto failure;
13702         }
13703
13704         for (result = dns_rdataset_first(&rdataset);
13705              result == ISC_R_SUCCESS;
13706              result = dns_rdataset_next(&rdataset)) {
13707                 dns_rdata_t myrdata = DNS_RDATA_INIT;
13708                 dns_rdataset_current(&rdataset, &myrdata);
13709                 if (!dns_rdata_compare(&myrdata, rdata))
13710                         break;
13711         }
13712         dns_rdataset_disassociate(&rdataset);
13713         if (result == ISC_R_SUCCESS) {
13714                 *flag = ISC_TRUE;
13715         } else if (result == ISC_R_NOMORE) {
13716                 *flag = ISC_FALSE;
13717                 result = ISC_R_SUCCESS;
13718         }
13719
13720  failure:
13721         if (node != NULL)
13722                 dns_db_detachnode(db, &node);
13723         return (result);
13724 }
13725
13726 /*
13727  * Add records to signal the state of signing or of key removal.
13728  */
13729 static isc_result_t
13730 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
13731                     dns_dbversion_t *ver, dns_diff_t *diff,
13732                     isc_boolean_t sign_all)
13733 {
13734         dns_difftuple_t *tuple, *newtuple = NULL;
13735         dns_rdata_dnskey_t dnskey;
13736         dns_rdata_t rdata = DNS_RDATA_INIT;
13737         isc_boolean_t flag;
13738         isc_region_t r;
13739         isc_result_t result = ISC_R_SUCCESS;
13740         isc_uint16_t keyid;
13741         unsigned char buf[5];
13742         dns_name_t *name = dns_db_origin(db);
13743
13744         for (tuple = ISC_LIST_HEAD(diff->tuples);
13745              tuple != NULL;
13746              tuple = ISC_LIST_NEXT(tuple, link)) {
13747                 if (tuple->rdata.type != dns_rdatatype_dnskey)
13748                         continue;
13749
13750                 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
13751                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13752                 if ((dnskey.flags &
13753                      (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
13754                          != DNS_KEYOWNER_ZONE)
13755                         continue;
13756
13757                 dns_rdata_toregion(&tuple->rdata, &r);
13758
13759                 keyid = dst_region_computeid(&r, dnskey.algorithm);
13760
13761                 buf[0] = dnskey.algorithm;
13762                 buf[1] = (keyid & 0xff00) >> 8;
13763                 buf[2] = (keyid & 0xff);
13764                 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
13765                 buf[4] = 0;
13766                 rdata.data = buf;
13767                 rdata.length = sizeof(buf);
13768                 rdata.type = privatetype;
13769                 rdata.rdclass = tuple->rdata.rdclass;
13770
13771                 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
13772                         CHECK(rr_exists(db, ver, name, &rdata, &flag));
13773                         if (flag)
13774                                 continue;
13775                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
13776                                                    name, 0, &rdata, &newtuple));
13777                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
13778                         INSIST(newtuple == NULL);
13779                 }
13780
13781                 /*
13782                  * Remove any record which says this operation has already
13783                  * completed.
13784                  */
13785                 buf[4] = 1;
13786                 CHECK(rr_exists(db, ver, name, &rdata, &flag));
13787                 if (flag) {
13788                         CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
13789                                                    name, 0, &rdata, &newtuple));
13790                         CHECK(do_one_tuple(&newtuple, db, ver, diff));
13791                         INSIST(newtuple == NULL);
13792                 }
13793         }
13794  failure:
13795         return (result);
13796 }
13797
13798 static isc_result_t
13799 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
13800           dns_diff_t *diff, dns_diff_t *sig_diff)
13801 {
13802         isc_result_t result;
13803         isc_stdtime_t now, inception, soaexpire;
13804         isc_boolean_t check_ksk, keyset_kskonly;
13805         dst_key_t *zone_keys[MAXZONEKEYS];
13806         unsigned int nkeys = 0, i;
13807         dns_difftuple_t *tuple;
13808
13809         result = find_zone_keys(zone, db, ver, zone->mctx, MAXZONEKEYS,
13810                                 zone_keys, &nkeys);
13811         if (result != ISC_R_SUCCESS) {
13812                 dns_zone_log(zone, ISC_LOG_ERROR,
13813                              "sign_apex:find_zone_keys -> %s\n",
13814                              dns_result_totext(result));
13815                 return (result);
13816         }
13817
13818         isc_stdtime_get(&now);
13819         inception = now - 3600; /* Allow for clock skew. */
13820         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
13821
13822         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
13823         keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
13824
13825         /*
13826          * See if update_sigs will update DNSKEY signature and if not
13827          * cause them to sign so that so that newly activated keys
13828          * are used.
13829          */
13830         for (tuple = ISC_LIST_HEAD(diff->tuples);
13831              tuple != NULL;
13832              tuple = ISC_LIST_NEXT(tuple, link)) {
13833                 if (tuple->rdata.type == dns_rdatatype_dnskey &&
13834                     dns_name_equal(&tuple->name, &zone->origin))
13835                         break;
13836         }
13837
13838         if (tuple == NULL) {
13839                 result = del_sigs(zone, db, ver, &zone->origin,
13840                                   dns_rdatatype_dnskey, sig_diff,
13841                                   zone_keys, nkeys, now, ISC_FALSE);
13842                 if (result != ISC_R_SUCCESS) {
13843                         dns_zone_log(zone, ISC_LOG_ERROR,
13844                                      "sign_apex:del_sigs -> %s\n",
13845                                      dns_result_totext(result));
13846                         goto failure;
13847                 }
13848                 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
13849                                   sig_diff, zone_keys, nkeys, zone->mctx,
13850                                   inception, soaexpire, check_ksk,
13851                                   keyset_kskonly);
13852                 if (result != ISC_R_SUCCESS) {
13853                         dns_zone_log(zone, ISC_LOG_ERROR,
13854                                      "sign_apex:add_sigs -> %s\n",
13855                                      dns_result_totext(result));
13856                         goto failure;
13857                 }
13858         }
13859
13860         result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
13861                              inception, soaexpire, now, check_ksk,
13862                              keyset_kskonly, sig_diff);
13863
13864         if (result != ISC_R_SUCCESS) {
13865                 dns_zone_log(zone, ISC_LOG_ERROR,
13866                              "sign_apex:update_sigs -> %s\n",
13867                              dns_result_totext(result));
13868                 goto failure;
13869         }
13870
13871  failure:
13872         for (i = 0; i < nkeys; i++)
13873                 dst_key_free(&zone_keys[i]);
13874         return (result);
13875 }
13876
13877 /*
13878  * Prevent the zone entering a inconsistent state where
13879  * NSEC only DNSKEYs are present with NSEC3 chains.
13880  * See update.c:check_dnssec()
13881  */
13882 static isc_boolean_t
13883 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
13884             dns_diff_t *diff)
13885 {
13886         isc_result_t result;
13887         dns_difftuple_t *tuple;
13888         isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
13889         dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
13890
13891         /* Scan the tuples for an NSEC-only DNSKEY */
13892         for (tuple = ISC_LIST_HEAD(diff->tuples);
13893              tuple != NULL;
13894              tuple = ISC_LIST_NEXT(tuple, link)) {
13895                 isc_uint8_t alg;
13896                 if (tuple->rdata.type != dns_rdatatype_dnskey ||
13897                     tuple->op != DNS_DIFFOP_ADD)
13898                         continue;
13899
13900                 alg = tuple->rdata.data[3];
13901                 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
13902                     alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
13903                         nseconly = ISC_TRUE;
13904                         break;
13905                 }
13906         }
13907
13908         /* Check existing DB for NSEC-only DNSKEY */
13909         if (!nseconly)
13910                 CHECK(dns_nsec_nseconly(db, ver, &nseconly));
13911
13912         /* Check existing DB for NSEC3 */
13913         if (!nsec3)
13914                 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
13915                                         privatetype, &nsec3));
13916
13917         /* Refuse to allow NSEC3 with NSEC-only keys */
13918         if (nseconly && nsec3) {
13919                 dns_zone_log(zone, ISC_LOG_ERROR,
13920                            "NSEC only DNSKEYs and NSEC3 chains not allowed");
13921                 goto failure;
13922         }
13923
13924         return (ISC_TRUE);
13925
13926  failure:
13927         return (ISC_FALSE);
13928 }
13929
13930 static isc_result_t
13931 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
13932                  dns_diff_t *diff)
13933 {
13934         isc_result_t result;
13935         dns_dbnode_t *node = NULL;
13936         dns_rdataset_t rdataset;
13937
13938         dns_rdataset_init(&rdataset);
13939         CHECK(dns_db_getoriginnode(db, &node));
13940
13941         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
13942                                      dns_rdatatype_none, 0, &rdataset, NULL);
13943         if (dns_rdataset_isassociated(&rdataset))
13944                 dns_rdataset_disassociate(&rdataset);
13945         if (result != ISC_R_NOTFOUND)
13946                 goto failure;
13947
13948         result = dns_nsec3param_deletechains(db, ver, zone, diff);
13949
13950  failure:
13951         if (node != NULL)
13952                 dns_db_detachnode(db, &node);
13953         return (result);
13954 }
13955
13956 /*
13957  * Given an RRSIG rdataset and an algorithm, determine whether there
13958  * are any signatures using that algorithm.
13959  */
13960 static isc_boolean_t
13961 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
13962         dns_rdata_t rdata = DNS_RDATA_INIT;
13963         dns_rdata_rrsig_t rrsig;
13964         isc_result_t result;
13965
13966         REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
13967         if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
13968                 return (ISC_FALSE);
13969         }
13970
13971         for (result = dns_rdataset_first(rdataset);
13972              result == ISC_R_SUCCESS;
13973              result = dns_rdataset_next(rdataset))
13974         {
13975                 dns_rdataset_current(rdataset, &rdata);
13976                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
13977                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13978                 dns_rdata_reset(&rdata);
13979                 if (rrsig.algorithm == alg)
13980                         return (ISC_TRUE);
13981         }
13982
13983         return (ISC_FALSE);
13984 }
13985
13986 static isc_result_t
13987 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
13988            dns_diff_t *diff)
13989 {
13990         dns_name_t *origin;
13991         isc_boolean_t build_nsec3;
13992         isc_result_t result;
13993
13994         origin = dns_db_origin(db);
13995         CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
13996                                  &build_nsec3));
13997         if (build_nsec3)
13998                 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
13999                                            ISC_FALSE, zone->privatetype, diff));
14000         CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
14001
14002  failure:
14003         return (result);
14004 }
14005
14006 static void
14007 zone_rekey(dns_zone_t *zone) {
14008         isc_result_t result;
14009         dns_db_t *db = NULL;
14010         dns_dbnode_t *node = NULL;
14011         dns_dbversion_t *ver = NULL;
14012         dns_rdataset_t soaset, soasigs, keyset, keysigs;
14013         dns_dnsseckeylist_t dnskeys, keys, rmkeys;
14014         dns_dnsseckey_t *key;
14015         dns_diff_t diff, sig_diff;
14016         isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
14017         isc_boolean_t newalg = ISC_FALSE;
14018         isc_boolean_t fullsign;
14019         dns_ttl_t ttl = 3600;
14020         const char *dir;
14021         isc_mem_t *mctx;
14022         isc_stdtime_t now;
14023         isc_time_t timenow;
14024         isc_interval_t ival;
14025         char timebuf[80];
14026
14027         REQUIRE(DNS_ZONE_VALID(zone));
14028
14029         ISC_LIST_INIT(dnskeys);
14030         ISC_LIST_INIT(keys);
14031         ISC_LIST_INIT(rmkeys);
14032         dns_rdataset_init(&soaset);
14033         dns_rdataset_init(&soasigs);
14034         dns_rdataset_init(&keyset);
14035         dns_rdataset_init(&keysigs);
14036         dir = dns_zone_getkeydirectory(zone);
14037         mctx = zone->mctx;
14038         dns_diff_init(mctx, &diff);
14039         dns_diff_init(mctx, &sig_diff);
14040         sig_diff.resign = zone->sigresigninginterval;
14041
14042         CHECK(dns_zone_getdb(zone, &db));
14043         CHECK(dns_db_newversion(db, &ver));
14044         CHECK(dns_db_getoriginnode(db, &node));
14045
14046         dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
14047
14048         /* Get the SOA record's TTL */
14049         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
14050                                   dns_rdatatype_none, 0, &soaset, &soasigs));
14051         ttl = soaset.ttl;
14052         dns_rdataset_disassociate(&soaset);
14053
14054         /* Get the DNSKEY rdataset */
14055         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
14056                                      dns_rdatatype_none, 0, &keyset, &keysigs);
14057         if (result == ISC_R_SUCCESS) {
14058                 ttl = keyset.ttl;
14059                 result = dns_dnssec_keylistfromrdataset(&zone->origin, dir,
14060                                                         mctx, &keyset,
14061                                                         &keysigs, &soasigs,
14062                                                         ISC_FALSE, ISC_FALSE,
14063                                                         &dnskeys);
14064                 /* Can't get keys for some reason; try again later. */
14065                 if (result != ISC_R_SUCCESS)
14066                         goto trylater;
14067         } else if (result != ISC_R_NOTFOUND)
14068                 goto failure;
14069
14070         /*
14071          * True when called from "rndc sign".  Indicates the zone should be
14072          * fully signed now.
14073          */
14074         fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
14075
14076         result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
14077         if (result == ISC_R_SUCCESS) {
14078                 isc_boolean_t check_ksk;
14079                 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
14080
14081                 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
14082                                                &zone->origin, ttl, &diff,
14083                                                ISC_TF(!check_ksk),
14084                                                mctx, logmsg);
14085
14086                 /* Keys couldn't be updated for some reason;
14087                  * try again later. */
14088                 if (result != ISC_R_SUCCESS) {
14089                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
14090                                      "couldn't update zone keys: %s",
14091                                      isc_result_totext(result));
14092                         goto trylater;
14093                 }
14094
14095                 /* See if any pre-existing keys have newly become active;
14096                  * also, see if any new key is for a new algorithm, as in that
14097                  * event, we need to sign the zone fully.  (If there's a new
14098                  * key, but it's for an already-existing algorithm, then
14099                  * the zone signing can be handled incrementally.)
14100                  */
14101                 for (key = ISC_LIST_HEAD(dnskeys);
14102                      key != NULL;
14103                      key = ISC_LIST_NEXT(key, link)) {
14104                         if (!key->first_sign)
14105                                 continue;
14106
14107                         newactive = ISC_TRUE;
14108
14109                         if (!dns_rdataset_isassociated(&keysigs)) {
14110                                 newalg = ISC_TRUE;
14111                                 break;
14112                         }
14113
14114                         if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
14115                                 /*
14116                                  * This isn't a new algorithm; clear
14117                                  * first_sign so we won't sign the
14118                                  * whole zone with this key later
14119                                  */
14120                                 key->first_sign = ISC_FALSE;
14121                         } else {
14122                                 newalg = ISC_TRUE;
14123                                 break;
14124                         }
14125                 }
14126
14127                 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
14128                     dnskey_sane(zone, db, ver, &diff)) {
14129                         CHECK(dns_diff_apply(&diff, db, ver));
14130                         CHECK(clean_nsec3param(zone, db, ver, &diff));
14131                         CHECK(add_signing_records(db, zone->privatetype,
14132                                                   ver, &diff,
14133                                                   ISC_TF(newalg || fullsign)));
14134                         CHECK(increment_soa_serial(db, ver, &diff, mctx));
14135                         CHECK(add_chains(zone, db, ver, &diff));
14136                         CHECK(sign_apex(zone, db, ver, &diff, &sig_diff));
14137                         CHECK(zone_journal(zone, &sig_diff, "zone_rekey"));
14138                         commit = ISC_TRUE;
14139                 }
14140         }
14141
14142         dns_db_closeversion(db, &ver, commit);
14143
14144         if (commit) {
14145                 isc_time_t timenow;
14146                 dns_difftuple_t *tuple;
14147
14148                 LOCK_ZONE(zone);
14149                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14150
14151                 zone_needdump(zone, DNS_DUMP_DELAY);
14152
14153                 TIME_NOW(&timenow);
14154                 zone_settimer(zone, &timenow);
14155
14156                 /* Remove any signatures from removed keys.  */
14157                 if (!ISC_LIST_EMPTY(rmkeys)) {
14158                         for (key = ISC_LIST_HEAD(rmkeys);
14159                              key != NULL;
14160                              key = ISC_LIST_NEXT(key, link)) {
14161                                 result = zone_signwithkey(zone,
14162                                                           dst_key_alg(key->key),
14163                                                           dst_key_id(key->key),
14164                                                           ISC_TRUE);
14165                                 if (result != ISC_R_SUCCESS) {
14166                                         dns_zone_log(zone, ISC_LOG_ERROR,
14167                                              "zone_signwithkey failed: %s",
14168                                              dns_result_totext(result));
14169                                 }
14170                         }
14171                 }
14172
14173                 if (fullsign) {
14174                         /*
14175                          * "rndc sign" was called, so we now sign the zone
14176                          * with all active keys, whether they're new or not.
14177                          */
14178                         for (key = ISC_LIST_HEAD(dnskeys);
14179                              key != NULL;
14180                              key = ISC_LIST_NEXT(key, link)) {
14181                                 if (!key->force_sign && !key->hint_sign)
14182                                         continue;
14183
14184                                 result = zone_signwithkey(zone,
14185                                                           dst_key_alg(key->key),
14186                                                           dst_key_id(key->key),
14187                                                           ISC_FALSE);
14188                                 if (result != ISC_R_SUCCESS) {
14189                                         dns_zone_log(zone, ISC_LOG_ERROR,
14190                                              "zone_signwithkey failed: %s",
14191                                              dns_result_totext(result));
14192                                 }
14193                         }
14194                 } else if (newalg) {
14195                         /*
14196                          * We haven't been told to sign fully, but a new
14197                          * algorithm was added to the DNSKEY.  We sign
14198                          * the full zone, but only with newly active
14199                          * keys.
14200                          */
14201                         for (key = ISC_LIST_HEAD(dnskeys);
14202                              key != NULL;
14203                              key = ISC_LIST_NEXT(key, link)) {
14204                                 if (!key->first_sign)
14205                                         continue;
14206
14207                                 result = zone_signwithkey(zone,
14208                                                           dst_key_alg(key->key),
14209                                                           dst_key_id(key->key),
14210                                                           ISC_FALSE);
14211                                 if (result != ISC_R_SUCCESS) {
14212                                         dns_zone_log(zone, ISC_LOG_ERROR,
14213                                              "zone_signwithkey failed: %s",
14214                                              dns_result_totext(result));
14215                                 }
14216                         }
14217                 }
14218
14219                 /*
14220                  * Clear fullsign flag, if it was set, so we don't do
14221                  * another full signing next time
14222                  */
14223                 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
14224
14225                 /*
14226                  * Cause the zone to add/delete NSEC3 chains for the
14227                  * deferred NSEC3PARAM changes.
14228                  */
14229                 for (tuple = ISC_LIST_HEAD(sig_diff.tuples);
14230                      tuple != NULL;
14231                      tuple = ISC_LIST_NEXT(tuple, link)) {
14232                         unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14233                         dns_rdata_t rdata = DNS_RDATA_INIT;
14234                         dns_rdata_nsec3param_t nsec3param;
14235
14236                         if (tuple->rdata.type != zone->privatetype ||
14237                             tuple->op != DNS_DIFFOP_ADD)
14238                                 continue;
14239
14240                         if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
14241                                                         buf, sizeof(buf)))
14242                                 continue;
14243                         result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
14244                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
14245                         if (nsec3param.flags == 0)
14246                                 continue;
14247
14248                         result = zone_addnsec3chain(zone, &nsec3param);
14249                         if (result != ISC_R_SUCCESS) {
14250                                 dns_zone_log(zone, ISC_LOG_ERROR,
14251                                              "zone_addnsec3chain failed: %s",
14252                                              dns_result_totext(result));
14253                         }
14254                 }
14255
14256                 /*
14257                  * Schedule the next resigning event
14258                  */
14259                 set_resigntime(zone);
14260                 UNLOCK_ZONE(zone);
14261         }
14262
14263         /*
14264          * If we are doing automatic key maintenance and the key metadata
14265          * indicates there is a key change event scheduled in the future,
14266          * set the key refresh timer.
14267          */
14268         isc_stdtime_get(&now);
14269         TIME_NOW(&timenow);
14270         isc_time_settoepoch(&zone->refreshkeytime);
14271
14272         /*
14273          * If we're doing key maintenance, set the key refresh timer to
14274          * the next scheduled key event or to one hour in the future,
14275          * whichever is sooner.
14276          */
14277         if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
14278                 isc_time_t timethen;
14279                 isc_stdtime_t then;
14280
14281                 LOCK_ZONE(zone);
14282                 DNS_ZONE_TIME_ADD(&timenow, HOUR, &timethen);
14283                 zone->refreshkeytime = timethen;
14284                 UNLOCK_ZONE(zone);
14285
14286                 for (key = ISC_LIST_HEAD(dnskeys);
14287                      key != NULL;
14288                      key = ISC_LIST_NEXT(key, link)) {
14289                         then = now;
14290                         result = next_keyevent(key->key, &then);
14291                         if (result != ISC_R_SUCCESS)
14292                                 continue;
14293
14294                         DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
14295                         LOCK_ZONE(zone);
14296                         if (isc_time_compare(&timethen,
14297                                              &zone->refreshkeytime) < 0) {
14298                                 zone->refreshkeytime = timethen;
14299                         }
14300                         UNLOCK_ZONE(zone);
14301                 }
14302
14303                 zone_settimer(zone, &timenow);
14304
14305                 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
14306                 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
14307         }
14308
14309  failure:
14310         dns_diff_clear(&diff);
14311         dns_diff_clear(&sig_diff);
14312
14313         clear_keylist(&dnskeys, mctx);
14314         clear_keylist(&keys, mctx);
14315         clear_keylist(&rmkeys, mctx);
14316
14317         if (ver != NULL)
14318                 dns_db_closeversion(db, &ver, ISC_FALSE);
14319         if (dns_rdataset_isassociated(&keyset))
14320                 dns_rdataset_disassociate(&keyset);
14321         if (dns_rdataset_isassociated(&keysigs))
14322                 dns_rdataset_disassociate(&keysigs);
14323         if (dns_rdataset_isassociated(&soasigs))
14324                 dns_rdataset_disassociate(&soasigs);
14325         if (node != NULL)
14326                 dns_db_detachnode(db, &node);
14327         if (db != NULL)
14328                 dns_db_detach(&db);
14329         return;
14330
14331  trylater:
14332         isc_interval_set(&ival, HOUR, 0);
14333         isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
14334         goto failure;
14335 }
14336
14337 void
14338 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
14339         isc_time_t now;
14340
14341         if (zone->type == dns_zone_master && zone->task != NULL) {
14342                 LOCK_ZONE(zone);
14343
14344                 if (fullsign)
14345                         zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
14346
14347                 TIME_NOW(&now);
14348                 zone->refreshkeytime = now;
14349                 zone_settimer(zone, &now);
14350
14351                 UNLOCK_ZONE(zone);
14352         }
14353 }
14354
14355 isc_result_t
14356 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
14357                  unsigned int *errors)
14358 {
14359         isc_result_t result;
14360         dns_dbnode_t *node = NULL;
14361
14362         REQUIRE(DNS_ZONE_VALID(zone));
14363         REQUIRE(errors != NULL);
14364
14365         result = dns_db_getoriginnode(db, &node);
14366         if (result != ISC_R_SUCCESS)
14367                 return (result);
14368         result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
14369                                   ISC_FALSE);
14370         dns_db_detachnode(db, &node);
14371         return (result);
14372 }
14373
14374 void
14375 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
14376         REQUIRE(DNS_ZONE_VALID(zone));
14377         LOCK_ZONE(zone);
14378         zone->added = added;
14379         UNLOCK_ZONE(zone);
14380 }
14381
14382 isc_boolean_t
14383 dns_zone_getadded(dns_zone_t *zone) {
14384         REQUIRE(DNS_ZONE_VALID(zone));
14385         return (zone->added);
14386 }
14387
14388 isc_result_t
14389 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
14390 {
14391         isc_time_t loadtime;
14392         isc_result_t result;
14393         TIME_NOW(&loadtime);
14394
14395         LOCK_ZONE(zone);
14396         result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14397         UNLOCK_ZONE(zone);
14398         return result;
14399 }