]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - contrib/bind9/lib/dns/zone.c
Update to 9.6-ESV-R8.
[FreeBSD/stable/8.git] / contrib / bind9 / lib / dns / zone.c
1 /*
2  * Copyright (C) 2004-2012  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id$ */
19
20 /*! \file */
21
22 #include <config.h>
23 #include <errno.h>
24 #include <stdlib.h>
25
26 #include <isc/file.h>
27 #include <isc/mutex.h>
28 #include <isc/print.h>
29 #include <isc/random.h>
30 #include <isc/ratelimiter.h>
31 #include <isc/refcount.h>
32 #include <isc/rwlock.h>
33 #include <isc/serial.h>
34 #include <isc/strerror.h>
35 #include <isc/stats.h>
36 #include <isc/stdtime.h>
37 #include <isc/string.h>
38 #include <isc/taskpool.h>
39 #include <isc/timer.h>
40 #include <isc/util.h>
41
42 #include <dns/acache.h>
43 #include <dns/acl.h>
44 #include <dns/adb.h>
45 #include <dns/callbacks.h>
46 #include <dns/db.h>
47 #include <dns/dbiterator.h>
48 #include <dns/dnssec.h>
49 #include <dns/events.h>
50 #include <dns/journal.h>
51 #include <dns/keyvalues.h>
52 #include <dns/log.h>
53 #include <dns/master.h>
54 #include <dns/masterdump.h>
55 #include <dns/message.h>
56 #include <dns/name.h>
57 #include <dns/nsec.h>
58 #include <dns/nsec3.h>
59 #include <dns/peer.h>
60 #include <dns/rcode.h>
61 #include <dns/rdataclass.h>
62 #include <dns/rdatalist.h>
63 #include <dns/rdataset.h>
64 #include <dns/rdatasetiter.h>
65 #include <dns/rdatastruct.h>
66 #include <dns/rdatatype.h>
67 #include <dns/request.h>
68 #include <dns/resolver.h>
69 #include <dns/result.h>
70 #include <dns/soa.h>
71 #include <dns/ssu.h>
72 #include <dns/stats.h>
73 #include <dns/time.h>
74 #include <dns/tsig.h>
75 #include <dns/xfrin.h>
76 #include <dns/zone.h>
77
78 #include <dst/dst.h>
79
80 #define ZONE_MAGIC                      ISC_MAGIC('Z', 'O', 'N', 'E')
81 #define DNS_ZONE_VALID(zone)            ISC_MAGIC_VALID(zone, ZONE_MAGIC)
82
83 #define NOTIFY_MAGIC                    ISC_MAGIC('N', 't', 'f', 'y')
84 #define DNS_NOTIFY_VALID(notify)        ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
85
86 #define STUB_MAGIC                      ISC_MAGIC('S', 't', 'u', 'b')
87 #define DNS_STUB_VALID(stub)            ISC_MAGIC_VALID(stub, STUB_MAGIC)
88
89 #define ZONEMGR_MAGIC                   ISC_MAGIC('Z', 'm', 'g', 'r')
90 #define DNS_ZONEMGR_VALID(stub)         ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
91
92 #define LOAD_MAGIC                      ISC_MAGIC('L', 'o', 'a', 'd')
93 #define DNS_LOAD_VALID(load)            ISC_MAGIC_VALID(load, LOAD_MAGIC)
94
95 #define FORWARD_MAGIC                   ISC_MAGIC('F', 'o', 'r', 'w')
96 #define DNS_FORWARD_VALID(load)         ISC_MAGIC_VALID(load, FORWARD_MAGIC)
97
98 #define IO_MAGIC                        ISC_MAGIC('Z', 'm', 'I', 'O')
99 #define DNS_IO_VALID(load)              ISC_MAGIC_VALID(load, IO_MAGIC)
100
101 /*%
102  * Ensure 'a' is at least 'min' but not more than 'max'.
103  */
104 #define RANGE(a, min, max) \
105                 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
106
107 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
108
109 /*
110  * Default values.
111  */
112 #define DNS_DEFAULT_IDLEIN 3600         /*%< 1 hour */
113 #define DNS_DEFAULT_IDLEOUT 3600        /*%< 1 hour */
114 #define MAX_XFER_TIME (2*3600)          /*%< Documented default is 2 hours */
115
116 #ifndef DNS_MAX_EXPIRE
117 #define DNS_MAX_EXPIRE  14515200        /*%< 24 weeks */
118 #endif
119
120 #ifndef DNS_DUMP_DELAY
121 #define DNS_DUMP_DELAY 900              /*%< 15 minutes */
122 #endif
123
124 typedef struct dns_notify dns_notify_t;
125 typedef struct dns_stub dns_stub_t;
126 typedef struct dns_load dns_load_t;
127 typedef struct dns_forward dns_forward_t;
128 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
129 typedef struct dns_io dns_io_t;
130 typedef ISC_LIST(dns_io_t) dns_iolist_t;
131 typedef struct dns_signing dns_signing_t;
132 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
133 typedef struct dns_nsec3chain dns_nsec3chain_t;
134 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
135
136 #define DNS_ZONE_CHECKLOCK
137 #ifdef DNS_ZONE_CHECKLOCK
138 #define LOCK_ZONE(z) \
139          do { LOCK(&(z)->lock); \
140               INSIST((z)->locked == ISC_FALSE); \
141              (z)->locked = ISC_TRUE; \
142                 } while (0)
143 #define UNLOCK_ZONE(z) \
144         do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
145 #define LOCKED_ZONE(z) ((z)->locked)
146 #else
147 #define LOCK_ZONE(z) LOCK(&(z)->lock)
148 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
149 #define LOCKED_ZONE(z) ISC_TRUE
150 #endif
151
152 #ifdef ISC_RWLOCK_USEATOMIC
153 #define ZONEDB_INITLOCK(l)      isc_rwlock_init((l), 0, 0)
154 #define ZONEDB_DESTROYLOCK(l)   isc_rwlock_destroy(l)
155 #define ZONEDB_LOCK(l, t)       RWLOCK((l), (t))
156 #define ZONEDB_UNLOCK(l, t)     RWUNLOCK((l), (t))
157 #else
158 #define ZONEDB_INITLOCK(l)      isc_mutex_init(l)
159 #define ZONEDB_DESTROYLOCK(l)   DESTROYLOCK(l)
160 #define ZONEDB_LOCK(l, t)       LOCK(l)
161 #define ZONEDB_UNLOCK(l, t)     UNLOCK(l)
162 #endif
163
164 struct dns_zone {
165         /* Unlocked */
166         unsigned int            magic;
167         isc_mutex_t             lock;
168 #ifdef DNS_ZONE_CHECKLOCK
169         isc_boolean_t           locked;
170 #endif
171         isc_mem_t               *mctx;
172         isc_refcount_t          erefs;
173
174 #ifdef ISC_RWLOCK_USEATOMIC
175         isc_rwlock_t            dblock;
176 #else
177         isc_mutex_t             dblock;
178 #endif
179         dns_db_t                *db;            /* Locked by dblock */
180
181         /* Locked */
182         dns_zonemgr_t           *zmgr;
183         ISC_LINK(dns_zone_t)    link;           /* Used by zmgr. */
184         isc_timer_t             *timer;
185         unsigned int            irefs;
186         dns_name_t              origin;
187         char                    *masterfile;
188         dns_masterformat_t      masterformat;
189         char                    *journal;
190         isc_int32_t             journalsize;
191         dns_rdataclass_t        rdclass;
192         dns_zonetype_t          type;
193         unsigned int            flags;
194         unsigned int            options;
195         unsigned int            db_argc;
196         char                    **db_argv;
197         isc_time_t              expiretime;
198         isc_time_t              refreshtime;
199         isc_time_t              dumptime;
200         isc_time_t              loadtime;
201         isc_time_t              notifytime;
202         isc_time_t              resigntime;
203         isc_time_t              keywarntime;
204         isc_time_t              signingtime;
205         isc_time_t              nsec3chaintime;
206         isc_uint32_t            refresh;
207         isc_uint32_t            retry;
208         isc_uint32_t            expire;
209         isc_uint32_t            minimum;
210         isc_stdtime_t           key_expiry;
211         char                    *keydirectory;
212
213         isc_uint32_t            maxrefresh;
214         isc_uint32_t            minrefresh;
215         isc_uint32_t            maxretry;
216         isc_uint32_t            minretry;
217
218         isc_sockaddr_t          *masters;
219         dns_name_t              **masterkeynames;
220         isc_boolean_t           *mastersok;
221         unsigned int            masterscnt;
222         unsigned int            curmaster;
223         isc_sockaddr_t          masteraddr;
224         dns_notifytype_t        notifytype;
225         isc_sockaddr_t          *notify;
226         unsigned int            notifycnt;
227         isc_sockaddr_t          notifyfrom;
228         isc_task_t              *task;
229         isc_sockaddr_t          notifysrc4;
230         isc_sockaddr_t          notifysrc6;
231         isc_sockaddr_t          xfrsource4;
232         isc_sockaddr_t          xfrsource6;
233         isc_sockaddr_t          altxfrsource4;
234         isc_sockaddr_t          altxfrsource6;
235         isc_sockaddr_t          sourceaddr;
236         dns_xfrin_ctx_t         *xfr;           /* task locked */
237         dns_tsigkey_t           *tsigkey;       /* key used for xfr */
238         /* Access Control Lists */
239         dns_acl_t               *update_acl;
240         dns_acl_t               *forward_acl;
241         dns_acl_t               *notify_acl;
242         dns_acl_t               *query_acl;
243         dns_acl_t               *queryon_acl;
244         dns_acl_t               *xfr_acl;
245         isc_boolean_t           update_disabled;
246         isc_boolean_t           zero_no_soa_ttl;
247         dns_severity_t          check_names;
248         ISC_LIST(dns_notify_t)  notifies;
249         dns_request_t           *request;
250         dns_loadctx_t           *lctx;
251         dns_io_t                *readio;
252         dns_dumpctx_t           *dctx;
253         dns_io_t                *writeio;
254         isc_uint32_t            maxxfrin;
255         isc_uint32_t            maxxfrout;
256         isc_uint32_t            idlein;
257         isc_uint32_t            idleout;
258         isc_event_t             ctlevent;
259         dns_ssutable_t          *ssutable;
260         isc_uint32_t            sigvalidityinterval;
261         isc_uint32_t            sigresigninginterval;
262         dns_view_t              *view;
263         dns_acache_t            *acache;
264         dns_checkmxfunc_t       checkmx;
265         dns_checksrvfunc_t      checksrv;
266         dns_checknsfunc_t       checkns;
267         /*%
268          * Zones in certain states such as "waiting for zone transfer"
269          * or "zone transfer in progress" are kept on per-state linked lists
270          * in the zone manager using the 'statelink' field.  The 'statelist'
271          * field points at the list the zone is currently on.  It the zone
272          * is not on any such list, statelist is NULL.
273          */
274         ISC_LINK(dns_zone_t)    statelink;
275         dns_zonelist_t          *statelist;
276         /*%
277          * Statistics counters about zone management.
278          */
279         isc_stats_t             *stats;
280         /*%
281          * Optional per-zone statistics counters.  Counted outside of this
282          * module.
283          */
284         isc_boolean_t           requeststats_on;
285         isc_stats_t             *requeststats;
286         isc_uint32_t            notifydelay;
287         dns_isselffunc_t        isself;
288         void                    *isselfarg;
289
290         char *                  strnamerd;
291         char *                  strname;
292         char *                  strrdclass;
293         char *                  strviewname;
294
295         /*%
296          * Serial number for deferred journal compaction.
297          */
298         isc_uint32_t            compact_serial;
299         /*%
300          * Keys that are signing the zone for the first time.
301          */
302         dns_signinglist_t       signing;
303         dns_nsec3chainlist_t    nsec3chain;
304         /*%
305          * Signing / re-signing quantum stopping parameters.
306          */
307         isc_uint32_t            signatures;
308         isc_uint32_t            nodes;
309         dns_rdatatype_t         privatetype;
310
311         /*%
312          * Outstanding forwarded UPDATE requests.
313          */
314         dns_forwardlist_t       forwards;
315 };
316
317 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
318 #define DNS_ZONE_SETFLAG(z,f) do { \
319                 INSIST(LOCKED_ZONE(z)); \
320                 (z)->flags |= (f); \
321                 } while (0)
322 #define DNS_ZONE_CLRFLAG(z,f) do { \
323                 INSIST(LOCKED_ZONE(z)); \
324                 (z)->flags &= ~(f); \
325                 } while (0)
326         /* XXX MPA these may need to go back into zone.h */
327 #define DNS_ZONEFLG_REFRESH     0x00000001U     /*%< refresh check in progress */
328 #define DNS_ZONEFLG_NEEDDUMP    0x00000002U     /*%< zone need consolidation */
329 #define DNS_ZONEFLG_USEVC       0x00000004U     /*%< use tcp for refresh query */
330 #define DNS_ZONEFLG_DUMPING     0x00000008U     /*%< a dump is in progress */
331 #define DNS_ZONEFLG_HASINCLUDE  0x00000010U     /*%< $INCLUDE in zone file */
332 #define DNS_ZONEFLG_LOADED      0x00000020U     /*%< database has loaded */
333 #define DNS_ZONEFLG_EXITING     0x00000040U     /*%< zone is being destroyed */
334 #define DNS_ZONEFLG_EXPIRED     0x00000080U     /*%< zone has expired */
335 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U     /*%< refresh check needed */
336 #define DNS_ZONEFLG_UPTODATE    0x00000200U     /*%< zone contents are
337                                                  * uptodate */
338 #define DNS_ZONEFLG_NEEDNOTIFY  0x00000400U     /*%< need to send out notify
339                                                  * messages */
340 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U    /*%< generate a journal diff on
341                                                  * reload */
342 #define DNS_ZONEFLG_NOMASTERS   0x00001000U     /*%< an attempt to refresh a
343                                                  * zone with no masters
344                                                  * occurred */
345 #define DNS_ZONEFLG_LOADING     0x00002000U     /*%< load from disk in progress*/
346 #define DNS_ZONEFLG_HAVETIMERS  0x00004000U     /*%< timer values have been set
347                                                  * from SOA (if not set, we
348                                                  * are still using
349                                                  * default timer values) */
350 #define DNS_ZONEFLG_FORCEXFER   0x00008000U     /*%< Force a zone xfer */
351 #define DNS_ZONEFLG_NOREFRESH   0x00010000U
352 #define DNS_ZONEFLG_DIALNOTIFY  0x00020000U
353 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
354 #define DNS_ZONEFLG_SHUTDOWN    0x00080000U
355 #define DNS_ZONEFLAG_NOIXFR     0x00100000U     /*%< IXFR failed, force AXFR */
356 #define DNS_ZONEFLG_FLUSH       0x00200000U
357 #define DNS_ZONEFLG_NOEDNS      0x00400000U
358 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
359 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
360 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
361 #define DNS_ZONEFLG_REFRESHING  0x04000000U     /*%< Refreshing keydata */
362 #define DNS_ZONEFLG_THAW        0x08000000U
363
364 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
365
366 /* Flags for zone_load() */
367 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U     /* Do not stat() master files */
368 #define DNS_ZONELOADFLAG_THAW   0x00000002U     /* Thaw the zone on successful
369                                                    load. */
370
371 #define UNREACH_CHACHE_SIZE     10U
372 #define UNREACH_HOLD_TIME       600     /* 10 minutes */
373
374 #define CHECK(op) \
375         do { result = (op); \
376                 if (result != ISC_R_SUCCESS) goto failure; \
377         } while (0)
378
379 struct dns_unreachable {
380         isc_sockaddr_t  remote;
381         isc_sockaddr_t  local;
382         isc_uint32_t    expire;
383         isc_uint32_t    last;
384 };
385
386 struct dns_zonemgr {
387         unsigned int            magic;
388         isc_mem_t *             mctx;
389         int                     refs;           /* Locked by rwlock */
390         isc_taskmgr_t *         taskmgr;
391         isc_timermgr_t *        timermgr;
392         isc_socketmgr_t *       socketmgr;
393         isc_taskpool_t *        zonetasks;
394         isc_task_t *            task;
395         isc_ratelimiter_t *     rl;
396         isc_rwlock_t            rwlock;
397         isc_mutex_t             iolock;
398         isc_rwlock_t            urlock;
399
400         /* Locked by rwlock. */
401         dns_zonelist_t          zones;
402         dns_zonelist_t          waiting_for_xfrin;
403         dns_zonelist_t          xfrin_in_progress;
404
405         /* Configuration data. */
406         isc_uint32_t            transfersin;
407         isc_uint32_t            transfersperns;
408         unsigned int            serialqueryrate;
409
410         /* Locked by iolock */
411         isc_uint32_t            iolimit;
412         isc_uint32_t            ioactive;
413         dns_iolist_t            high;
414         dns_iolist_t            low;
415
416         /* Locked by urlock. */
417         /* LRU cache */
418         struct dns_unreachable  unreachable[UNREACH_CHACHE_SIZE];
419 };
420
421 /*%
422  * Hold notify state.
423  */
424 struct dns_notify {
425         unsigned int            magic;
426         unsigned int            flags;
427         isc_mem_t               *mctx;
428         dns_zone_t              *zone;
429         dns_adbfind_t           *find;
430         dns_request_t           *request;
431         dns_name_t              ns;
432         isc_sockaddr_t          dst;
433         ISC_LINK(dns_notify_t)  link;
434 };
435
436 #define DNS_NOTIFY_NOSOA        0x0001U
437
438 /*%
439  *      dns_stub holds state while performing a 'stub' transfer.
440  *      'db' is the zone's 'db' or a new one if this is the initial
441  *      transfer.
442  */
443
444 struct dns_stub {
445         unsigned int            magic;
446         isc_mem_t               *mctx;
447         dns_zone_t              *zone;
448         dns_db_t                *db;
449         dns_dbversion_t         *version;
450 };
451
452 /*%
453  *      Hold load state.
454  */
455 struct dns_load {
456         unsigned int            magic;
457         isc_mem_t               *mctx;
458         dns_zone_t              *zone;
459         dns_db_t                *db;
460         isc_time_t              loadtime;
461         dns_rdatacallbacks_t    callbacks;
462 };
463
464 /*%
465  *      Hold forward state.
466  */
467 struct dns_forward {
468         unsigned int            magic;
469         isc_mem_t               *mctx;
470         dns_zone_t              *zone;
471         isc_buffer_t            *msgbuf;
472         dns_request_t           *request;
473         isc_uint32_t            which;
474         isc_sockaddr_t          addr;
475         dns_updatecallback_t    callback;
476         void                    *callback_arg;
477         ISC_LINK(dns_forward_t) link;
478 };
479
480 /*%
481  *      Hold IO request state.
482  */
483 struct dns_io {
484         unsigned int    magic;
485         dns_zonemgr_t   *zmgr;
486         isc_boolean_t   high;
487         isc_task_t      *task;
488         ISC_LINK(dns_io_t) link;
489         isc_event_t     *event;
490 };
491
492 /*%
493  *      Hold state for when we are signing a zone with a new
494  *      DNSKEY as result of an update.
495  */
496 struct dns_signing {
497         unsigned int            magic;
498         dns_db_t                *db;
499         dns_dbiterator_t        *dbiterator;
500         dns_secalg_t            algorithm;
501         isc_uint16_t            keyid;
502         isc_boolean_t           delete;
503         isc_boolean_t           done;
504         ISC_LINK(dns_signing_t) link;
505 };
506
507 struct dns_nsec3chain {
508         unsigned int                    magic;
509         dns_db_t                        *db;
510         dns_dbiterator_t                *dbiterator;
511         dns_rdata_nsec3param_t          nsec3param;
512         unsigned char                   salt[255];
513         isc_boolean_t                   done;
514         isc_boolean_t                   seen_nsec;
515         isc_boolean_t                   delete_nsec;
516         isc_boolean_t                   save_delete_nsec;
517         ISC_LINK(dns_nsec3chain_t)      link;
518 };
519 /*%<
520  * 'dbiterator' contains a iterator for the database.  If we are creating
521  * a NSEC3 chain only the non-NSEC3 nodes will be iterated.  If we are
522  * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
523  * iterated.
524  *
525  * 'nsec3param' contains the parameters of the NSEC3 chain being created
526  * or removed.
527  *
528  * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
529  *
530  * 'seen_nsec' will be set to true if, while iterating the zone to create a
531  * NSEC3 chain, a NSEC record is seen.
532  *
533  * 'delete_nsec' will be set to true if, at the completion of the creation
534  * of a NSEC3 chain, 'seen_nsec' is true.  If 'delete_nsec' is true then we
535  * are in the process of deleting the NSEC chain.
536  *
537  * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
538  * so it can be recovered in the event of a error.
539  */
540
541
542 #define SEND_BUFFER_SIZE 2048
543
544 static void zone_settimer(dns_zone_t *, isc_time_t *);
545 static void cancel_refresh(dns_zone_t *);
546 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
547                           const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
548 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
549      ISC_FORMAT_PRINTF(3, 4);
550 static void queue_xfrin(dns_zone_t *zone);
551 static void zone_unload(dns_zone_t *zone);
552 static void zone_expire(dns_zone_t *zone);
553 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
554 static void zone_idetach(dns_zone_t **zonep);
555 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
556                                    isc_boolean_t dump);
557 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
558 static inline void zone_detachdb(dns_zone_t *zone);
559 static isc_result_t default_journal(dns_zone_t *zone);
560 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
561 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
562                                   isc_time_t loadtime, isc_result_t result);
563 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
564 static void zone_shutdown(isc_task_t *, isc_event_t *);
565 static void zone_loaddone(void *arg, isc_result_t result);
566 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
567                                    isc_time_t loadtime);
568 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
569 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
570 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
571 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
572
573 #if 0
574 /* ondestroy example */
575 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
576 #endif
577
578 static void refresh_callback(isc_task_t *, isc_event_t *);
579 static void stub_callback(isc_task_t *, isc_event_t *);
580 static void queue_soa_query(dns_zone_t *zone);
581 static void soa_query(isc_task_t *, isc_event_t *);
582 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
583                      dns_stub_t *stub);
584 static int message_count(dns_message_t *msg, dns_section_t section,
585                          dns_rdatatype_t type);
586 static void notify_cancel(dns_zone_t *zone);
587 static void notify_find_address(dns_notify_t *notify);
588 static void notify_send(dns_notify_t *notify);
589 static isc_result_t notify_createmessage(dns_zone_t *zone,
590                                          unsigned int flags,
591                                          dns_message_t **messagep);
592 static void notify_done(isc_task_t *task, isc_event_t *event);
593 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
594 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
595 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
596 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
597                                              dns_zone_t *zone);
598 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
599 static void zonemgr_free(dns_zonemgr_t *zmgr);
600 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
601                                   isc_task_t *task, isc_taskaction_t action,
602                                   void *arg, dns_io_t **iop);
603 static void zonemgr_putio(dns_io_t **iop);
604 static void zonemgr_cancelio(dns_io_t *io);
605
606 static isc_result_t
607 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
608                  unsigned int *soacount, isc_uint32_t *serial,
609                  isc_uint32_t *refresh, isc_uint32_t *retry,
610                  isc_uint32_t *expire, isc_uint32_t *minimum,
611                  unsigned int *errors);
612
613 static void zone_freedbargs(dns_zone_t *zone);
614 static void forward_callback(isc_task_t *task, isc_event_t *event);
615 static void zone_saveunique(dns_zone_t *zone, const char *path,
616                             const char *templat);
617 static void zone_maintenance(dns_zone_t *zone);
618 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
619 static void dump_done(void *arg, isc_result_t result);
620 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
621                                      isc_uint16_t keyid, isc_boolean_t delete);
622
623 #define ENTER zone_debuglog(zone, me, 1, "enter")
624
625 static const unsigned int dbargc_default = 1;
626 static const char *dbargv_default[] = { "rbt" };
627
628 #define DNS_ZONE_JITTER_ADD(a, b, c) \
629         do { \
630                 isc_interval_t _i; \
631                 isc_uint32_t _j; \
632                 _j = isc_random_jitter((b), (b)/4); \
633                 isc_interval_set(&_i, _j, 0); \
634                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
635                         dns_zone_log(zone, ISC_LOG_WARNING, \
636                                      "epoch approaching: upgrade required: " \
637                                      "now + %s failed", #b); \
638                         isc_interval_set(&_i, _j/2, 0); \
639                         (void)isc_time_add((a), &_i, (c)); \
640                 } \
641         } while (0)
642
643 #define DNS_ZONE_TIME_ADD(a, b, c) \
644         do { \
645                 isc_interval_t _i; \
646                 isc_interval_set(&_i, (b), 0); \
647                 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
648                         dns_zone_log(zone, ISC_LOG_WARNING, \
649                                      "epoch approaching: upgrade required: " \
650                                      "now + %s failed", #b); \
651                         isc_interval_set(&_i, (b)/2, 0); \
652                         (void)isc_time_add((a), &_i, (c)); \
653                 } \
654         } while (0)
655
656 /*%
657  * Increment resolver-related statistics counters.  Zone must be locked.
658  */
659 static inline void
660 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
661         if (zone->stats != NULL)
662                 isc_stats_increment(zone->stats, counter);
663 }
664
665 /***
666  ***    Public functions.
667  ***/
668
669 isc_result_t
670 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
671         isc_result_t result;
672         dns_zone_t *zone;
673         isc_time_t now;
674
675         REQUIRE(zonep != NULL && *zonep == NULL);
676         REQUIRE(mctx != NULL);
677
678         TIME_NOW(&now);
679         zone = isc_mem_get(mctx, sizeof(*zone));
680         if (zone == NULL)
681                 return (ISC_R_NOMEMORY);
682
683         zone->mctx = NULL;
684         isc_mem_attach(mctx, &zone->mctx);
685
686         result = isc_mutex_init(&zone->lock);
687         if (result != ISC_R_SUCCESS)
688                 goto free_zone;
689
690         result = ZONEDB_INITLOCK(&zone->dblock);
691         if (result != ISC_R_SUCCESS)
692                 goto free_mutex;
693
694         /* XXX MPA check that all elements are initialised */
695 #ifdef DNS_ZONE_CHECKLOCK
696         zone->locked = ISC_FALSE;
697 #endif
698         zone->db = NULL;
699         zone->zmgr = NULL;
700         ISC_LINK_INIT(zone, link);
701         result = isc_refcount_init(&zone->erefs, 1);    /* Implicit attach. */
702         if (result != ISC_R_SUCCESS)
703                 goto free_dblock;
704         zone->irefs = 0;
705         dns_name_init(&zone->origin, NULL);
706         zone->strnamerd = NULL;
707         zone->strname = NULL;
708         zone->strrdclass = NULL;
709         zone->strviewname = NULL;
710         zone->masterfile = NULL;
711         zone->masterformat = dns_masterformat_none;
712         zone->keydirectory = NULL;
713         zone->journalsize = -1;
714         zone->journal = NULL;
715         zone->rdclass = dns_rdataclass_none;
716         zone->type = dns_zone_none;
717         zone->flags = 0;
718         zone->options = 0;
719         zone->db_argc = 0;
720         zone->db_argv = NULL;
721         isc_time_settoepoch(&zone->expiretime);
722         isc_time_settoepoch(&zone->refreshtime);
723         isc_time_settoepoch(&zone->dumptime);
724         isc_time_settoepoch(&zone->loadtime);
725         zone->notifytime = now;
726         isc_time_settoepoch(&zone->resigntime);
727         isc_time_settoepoch(&zone->keywarntime);
728         isc_time_settoepoch(&zone->signingtime);
729         isc_time_settoepoch(&zone->nsec3chaintime);
730         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
731         zone->retry = DNS_ZONE_DEFAULTRETRY;
732         zone->expire = 0;
733         zone->minimum = 0;
734         zone->maxrefresh = DNS_ZONE_MAXREFRESH;
735         zone->minrefresh = DNS_ZONE_MINREFRESH;
736         zone->maxretry = DNS_ZONE_MAXRETRY;
737         zone->minretry = DNS_ZONE_MINRETRY;
738         zone->masters = NULL;
739         zone->masterkeynames = NULL;
740         zone->mastersok = NULL;
741         zone->masterscnt = 0;
742         zone->curmaster = 0;
743         zone->notify = NULL;
744         zone->notifytype = dns_notifytype_yes;
745         zone->notifycnt = 0;
746         zone->task = NULL;
747         zone->update_acl = NULL;
748         zone->forward_acl = NULL;
749         zone->notify_acl = NULL;
750         zone->query_acl = NULL;
751         zone->queryon_acl = NULL;
752         zone->xfr_acl = NULL;
753         zone->update_disabled = ISC_FALSE;
754         zone->zero_no_soa_ttl = ISC_TRUE;
755         zone->check_names = dns_severity_ignore;
756         zone->request = NULL;
757         zone->lctx = NULL;
758         zone->readio = NULL;
759         zone->dctx = NULL;
760         zone->writeio = NULL;
761         zone->timer = NULL;
762         zone->idlein = DNS_DEFAULT_IDLEIN;
763         zone->idleout = DNS_DEFAULT_IDLEOUT;
764         ISC_LIST_INIT(zone->notifies);
765         isc_sockaddr_any(&zone->notifysrc4);
766         isc_sockaddr_any6(&zone->notifysrc6);
767         isc_sockaddr_any(&zone->xfrsource4);
768         isc_sockaddr_any6(&zone->xfrsource6);
769         isc_sockaddr_any(&zone->altxfrsource4);
770         isc_sockaddr_any6(&zone->altxfrsource6);
771         zone->xfr = NULL;
772         zone->tsigkey = NULL;
773         zone->maxxfrin = MAX_XFER_TIME;
774         zone->maxxfrout = MAX_XFER_TIME;
775         zone->ssutable = NULL;
776         zone->sigvalidityinterval = 30 * 24 * 3600;
777         zone->sigresigninginterval = 7 * 24 * 3600;
778         zone->view = NULL;
779         zone->acache = NULL;
780         zone->checkmx = NULL;
781         zone->checksrv = NULL;
782         zone->checkns = NULL;
783         ISC_LINK_INIT(zone, statelink);
784         zone->statelist = NULL;
785         zone->stats = NULL;
786         zone->requeststats_on = ISC_FALSE;
787         zone->requeststats = NULL;
788         zone->notifydelay = 5;
789         zone->isself = NULL;
790         zone->isselfarg = NULL;
791         ISC_LIST_INIT(zone->signing);
792         ISC_LIST_INIT(zone->nsec3chain);
793         zone->signatures = 10;
794         zone->nodes = 100;
795         zone->privatetype = (dns_rdatatype_t)0xffffU;
796         ISC_LIST_INIT(zone->forwards);
797
798         zone->magic = ZONE_MAGIC;
799
800         /* Must be after magic is set. */
801         result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
802         if (result != ISC_R_SUCCESS)
803                 goto free_erefs;
804
805         ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
806                        DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
807                        NULL, NULL);
808         *zonep = zone;
809         return (ISC_R_SUCCESS);
810
811  free_erefs:
812         isc_refcount_decrement(&zone->erefs, NULL);
813         isc_refcount_destroy(&zone->erefs);
814
815  free_dblock:
816         ZONEDB_DESTROYLOCK(&zone->dblock);
817
818  free_mutex:
819         DESTROYLOCK(&zone->lock);
820
821  free_zone:
822         isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
823         return (result);
824 }
825
826 /*
827  * Free a zone.  Because we require that there be no more
828  * outstanding events or references, no locking is necessary.
829  */
830 static void
831 zone_free(dns_zone_t *zone) {
832         isc_mem_t *mctx = NULL;
833         dns_signing_t *signing;
834         dns_nsec3chain_t *nsec3chain;
835
836         REQUIRE(DNS_ZONE_VALID(zone));
837         REQUIRE(isc_refcount_current(&zone->erefs) == 0);
838         REQUIRE(zone->irefs == 0);
839         REQUIRE(!LOCKED_ZONE(zone));
840         REQUIRE(zone->timer == NULL);
841
842         /*
843          * Managed objects.  Order is important.
844          */
845         if (zone->request != NULL)
846                 dns_request_destroy(&zone->request); /* XXXMPA */
847         INSIST(zone->readio == NULL);
848         INSIST(zone->statelist == NULL);
849         INSIST(zone->writeio == NULL);
850
851         if (zone->task != NULL)
852                 isc_task_detach(&zone->task);
853         if (zone->zmgr != NULL)
854                 dns_zonemgr_releasezone(zone->zmgr, zone);
855
856         /* Unmanaged objects */
857         for (signing = ISC_LIST_HEAD(zone->signing);
858              signing != NULL;
859              signing = ISC_LIST_HEAD(zone->signing)) {
860                 ISC_LIST_UNLINK(zone->signing, signing, link);
861                 dns_db_detach(&signing->db);
862                 dns_dbiterator_destroy(&signing->dbiterator);
863                 isc_mem_put(zone->mctx, signing, sizeof *signing);
864         }
865         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
866              nsec3chain != NULL;
867              nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
868                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
869                 dns_db_detach(&nsec3chain->db);
870                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
871                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
872         }
873         if (zone->masterfile != NULL)
874                 isc_mem_free(zone->mctx, zone->masterfile);
875         zone->masterfile = NULL;
876         if (zone->keydirectory != NULL)
877                 isc_mem_free(zone->mctx, zone->keydirectory);
878         zone->keydirectory = NULL;
879         zone->journalsize = -1;
880         if (zone->journal != NULL)
881                 isc_mem_free(zone->mctx, zone->journal);
882         zone->journal = NULL;
883         if (zone->stats != NULL)
884                 isc_stats_detach(&zone->stats);
885         if (zone->requeststats != NULL)
886                 isc_stats_detach(&zone->requeststats);
887         if (zone->db != NULL)
888                 zone_detachdb(zone);
889         if (zone->acache != NULL)
890                 dns_acache_detach(&zone->acache);
891         zone_freedbargs(zone);
892         RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
893                       == ISC_R_SUCCESS);
894         RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
895                       == ISC_R_SUCCESS);
896         zone->check_names = dns_severity_ignore;
897         if (zone->update_acl != NULL)
898                 dns_acl_detach(&zone->update_acl);
899         if (zone->forward_acl != NULL)
900                 dns_acl_detach(&zone->forward_acl);
901         if (zone->notify_acl != NULL)
902                 dns_acl_detach(&zone->notify_acl);
903         if (zone->query_acl != NULL)
904                 dns_acl_detach(&zone->query_acl);
905         if (zone->queryon_acl != NULL)
906                 dns_acl_detach(&zone->queryon_acl);
907         if (zone->xfr_acl != NULL)
908                 dns_acl_detach(&zone->xfr_acl);
909         if (dns_name_dynamic(&zone->origin))
910                 dns_name_free(&zone->origin, zone->mctx);
911         if (zone->strnamerd != NULL)
912                 isc_mem_free(zone->mctx, zone->strnamerd);
913         if (zone->strname != NULL)
914                 isc_mem_free(zone->mctx, zone->strname);
915         if (zone->strrdclass != NULL)
916                 isc_mem_free(zone->mctx, zone->strrdclass);
917         if (zone->strviewname != NULL)
918                 isc_mem_free(zone->mctx, zone->strviewname);
919         if (zone->ssutable != NULL)
920                 dns_ssutable_detach(&zone->ssutable);
921
922         /* last stuff */
923         ZONEDB_DESTROYLOCK(&zone->dblock);
924         DESTROYLOCK(&zone->lock);
925         isc_refcount_destroy(&zone->erefs);
926         zone->magic = 0;
927         mctx = zone->mctx;
928         isc_mem_put(mctx, zone, sizeof(*zone));
929         isc_mem_detach(&mctx);
930 }
931
932 /*
933  *      Single shot.
934  */
935 void
936 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
937         char namebuf[1024];
938
939         REQUIRE(DNS_ZONE_VALID(zone));
940         REQUIRE(rdclass != dns_rdataclass_none);
941
942         /*
943          * Test and set.
944          */
945         LOCK_ZONE(zone);
946         REQUIRE(zone->rdclass == dns_rdataclass_none ||
947                 zone->rdclass == rdclass);
948         zone->rdclass = rdclass;
949
950         if (zone->strnamerd != NULL)
951                 isc_mem_free(zone->mctx, zone->strnamerd);
952         if (zone->strrdclass != NULL)
953                 isc_mem_free(zone->mctx, zone->strrdclass);
954
955         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
956         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
957         zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
958         zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
959
960         UNLOCK_ZONE(zone);
961 }
962
963 dns_rdataclass_t
964 dns_zone_getclass(dns_zone_t *zone) {
965         REQUIRE(DNS_ZONE_VALID(zone));
966
967         return (zone->rdclass);
968 }
969
970 void
971 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
972         REQUIRE(DNS_ZONE_VALID(zone));
973
974         LOCK_ZONE(zone);
975         zone->notifytype = notifytype;
976         UNLOCK_ZONE(zone);
977 }
978
979 isc_result_t
980 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
981         isc_result_t result;
982
983         REQUIRE(DNS_ZONE_VALID(zone));
984         REQUIRE(serialp != NULL);
985
986         LOCK_ZONE(zone);
987         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
988         if (zone->db != NULL) {
989                 result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
990                                           NULL, NULL, NULL, NULL, NULL);
991         } else
992                 result = DNS_R_NOTLOADED;
993         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
994         UNLOCK_ZONE(zone);
995
996         return (result);
997 }
998
999 isc_uint32_t
1000 dns_zone_getserial(dns_zone_t *zone) {
1001         isc_result_t result;
1002         isc_uint32_t serial;
1003
1004         result = dns_zone_getserial2(zone, &serial);
1005         if (result != ISC_R_SUCCESS)
1006                 serial = 0; /* XXX: not really correct, but no other choice */
1007
1008         return (serial);
1009 }
1010
1011 /*
1012  *      Single shot.
1013  */
1014 void
1015 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1016
1017         REQUIRE(DNS_ZONE_VALID(zone));
1018         REQUIRE(type != dns_zone_none);
1019
1020         /*
1021          * Test and set.
1022          */
1023         LOCK_ZONE(zone);
1024         REQUIRE(zone->type == dns_zone_none || zone->type == type);
1025         zone->type = type;
1026         UNLOCK_ZONE(zone);
1027 }
1028
1029 static void
1030 zone_freedbargs(dns_zone_t *zone) {
1031         unsigned int i;
1032
1033         /* Free the old database argument list. */
1034         if (zone->db_argv != NULL) {
1035                 for (i = 0; i < zone->db_argc; i++)
1036                         isc_mem_free(zone->mctx, zone->db_argv[i]);
1037                 isc_mem_put(zone->mctx, zone->db_argv,
1038                             zone->db_argc * sizeof(*zone->db_argv));
1039         }
1040         zone->db_argc = 0;
1041         zone->db_argv = NULL;
1042 }
1043
1044 isc_result_t
1045 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1046         size_t size = 0;
1047         unsigned int i;
1048         isc_result_t result = ISC_R_SUCCESS;
1049         void *mem;
1050         char **tmp, *tmp2;
1051
1052         REQUIRE(DNS_ZONE_VALID(zone));
1053         REQUIRE(argv != NULL && *argv == NULL);
1054
1055         LOCK_ZONE(zone);
1056         size = (zone->db_argc + 1) * sizeof(char *);
1057         for (i = 0; i < zone->db_argc; i++)
1058                 size += strlen(zone->db_argv[i]) + 1;
1059         mem = isc_mem_allocate(mctx, size);
1060         if (mem != NULL) {
1061                 tmp = mem;
1062                 tmp2 = mem;
1063                 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1064                 for (i = 0; i < zone->db_argc; i++) {
1065                         *tmp++ = tmp2;
1066                         strcpy(tmp2, zone->db_argv[i]);
1067                         tmp2 += strlen(tmp2) + 1;
1068                 }
1069                 *tmp = NULL;
1070         } else
1071                 result = ISC_R_NOMEMORY;
1072         UNLOCK_ZONE(zone);
1073         *argv = mem;
1074         return (result);
1075 }
1076
1077 isc_result_t
1078 dns_zone_setdbtype(dns_zone_t *zone,
1079                    unsigned int dbargc, const char * const *dbargv) {
1080         isc_result_t result = ISC_R_SUCCESS;
1081         char **new = NULL;
1082         unsigned int i;
1083
1084         REQUIRE(DNS_ZONE_VALID(zone));
1085         REQUIRE(dbargc >= 1);
1086         REQUIRE(dbargv != NULL);
1087
1088         LOCK_ZONE(zone);
1089
1090         /* Set up a new database argument list. */
1091         new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1092         if (new == NULL)
1093                 goto nomem;
1094         for (i = 0; i < dbargc; i++)
1095                 new[i] = NULL;
1096         for (i = 0; i < dbargc; i++) {
1097                 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1098                 if (new[i] == NULL)
1099                         goto nomem;
1100         }
1101
1102         /* Free the old list. */
1103         zone_freedbargs(zone);
1104
1105         zone->db_argc = dbargc;
1106         zone->db_argv = new;
1107         result = ISC_R_SUCCESS;
1108         goto unlock;
1109
1110  nomem:
1111         if (new != NULL) {
1112                 for (i = 0; i < dbargc; i++)
1113                         if (new[i] != NULL)
1114                                 isc_mem_free(zone->mctx, new[i]);
1115                 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1116         }
1117         result = ISC_R_NOMEMORY;
1118
1119  unlock:
1120         UNLOCK_ZONE(zone);
1121         return (result);
1122 }
1123
1124 void
1125 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1126         char namebuf[1024];
1127         REQUIRE(DNS_ZONE_VALID(zone));
1128
1129         LOCK_ZONE(zone);
1130         if (zone->view != NULL)
1131                 dns_view_weakdetach(&zone->view);
1132         dns_view_weakattach(view, &zone->view);
1133
1134         if (zone->strviewname != NULL)
1135                 isc_mem_free(zone->mctx, zone->strviewname);
1136         if (zone->strnamerd != NULL)
1137                 isc_mem_free(zone->mctx, zone->strnamerd);
1138
1139         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1140         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1141         zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1142         zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1143
1144         UNLOCK_ZONE(zone);
1145 }
1146
1147
1148 dns_view_t *
1149 dns_zone_getview(dns_zone_t *zone) {
1150         REQUIRE(DNS_ZONE_VALID(zone));
1151
1152         return (zone->view);
1153 }
1154
1155
1156 isc_result_t
1157 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1158         isc_result_t result;
1159         char namebuf[1024];
1160
1161         REQUIRE(DNS_ZONE_VALID(zone));
1162         REQUIRE(origin != NULL);
1163
1164         LOCK_ZONE(zone);
1165         if (dns_name_dynamic(&zone->origin)) {
1166                 dns_name_free(&zone->origin, zone->mctx);
1167                 dns_name_init(&zone->origin, NULL);
1168         }
1169         result = dns_name_dup(origin, zone->mctx, &zone->origin);
1170
1171         if (zone->strnamerd != NULL)
1172                 isc_mem_free(zone->mctx, zone->strnamerd);
1173         if (zone->strname != NULL)
1174                 isc_mem_free(zone->mctx, zone->strname);
1175
1176         zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1177         zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1178         zone_name_tostr(zone, namebuf, sizeof namebuf);
1179         zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1180
1181         UNLOCK_ZONE(zone);
1182         return (result);
1183 }
1184
1185 void
1186 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1187         REQUIRE(DNS_ZONE_VALID(zone));
1188         REQUIRE(acache != NULL);
1189
1190         LOCK_ZONE(zone);
1191         if (zone->acache != NULL)
1192                 dns_acache_detach(&zone->acache);
1193         dns_acache_attach(acache, &zone->acache);
1194         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1195         if (zone->db != NULL) {
1196                 isc_result_t result;
1197
1198                 /*
1199                  * If the zone reuses an existing DB, the DB needs to be
1200                  * set in the acache explicitly.  We can safely ignore the
1201                  * case where the DB is already set.  If other error happens,
1202                  * the acache will not work effectively.
1203                  */
1204                 result = dns_acache_setdb(acache, zone->db);
1205                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1206                         UNEXPECTED_ERROR(__FILE__, __LINE__,
1207                                          "dns_acache_setdb() failed: %s",
1208                                          isc_result_totext(result));
1209                 }
1210         }
1211         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1212         UNLOCK_ZONE(zone);
1213 }
1214
1215 static isc_result_t
1216 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1217         char *copy;
1218
1219         if (value != NULL) {
1220                 copy = isc_mem_strdup(zone->mctx, value);
1221                 if (copy == NULL)
1222                         return (ISC_R_NOMEMORY);
1223         } else {
1224                 copy = NULL;
1225         }
1226
1227         if (*field != NULL)
1228                 isc_mem_free(zone->mctx, *field);
1229
1230         *field = copy;
1231         return (ISC_R_SUCCESS);
1232 }
1233
1234 isc_result_t
1235 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1236         return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1237 }
1238
1239 isc_result_t
1240 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1241                   dns_masterformat_t format) {
1242         isc_result_t result = ISC_R_SUCCESS;
1243
1244         REQUIRE(DNS_ZONE_VALID(zone));
1245
1246         LOCK_ZONE(zone);
1247         result = dns_zone_setstring(zone, &zone->masterfile, file);
1248         if (result == ISC_R_SUCCESS) {
1249                 zone->masterformat = format;
1250                 result = default_journal(zone);
1251         }
1252         UNLOCK_ZONE(zone);
1253
1254         return (result);
1255 }
1256
1257 const char *
1258 dns_zone_getfile(dns_zone_t *zone) {
1259         REQUIRE(DNS_ZONE_VALID(zone));
1260
1261         return (zone->masterfile);
1262 }
1263
1264 static isc_result_t
1265 default_journal(dns_zone_t *zone) {
1266         isc_result_t result;
1267         char *journal;
1268
1269         REQUIRE(DNS_ZONE_VALID(zone));
1270         REQUIRE(LOCKED_ZONE(zone));
1271
1272         if (zone->masterfile != NULL) {
1273                 /* Calculate string length including '\0'. */
1274                 int len = strlen(zone->masterfile) + sizeof(".jnl");
1275                 journal = isc_mem_allocate(zone->mctx, len);
1276                 if (journal == NULL)
1277                         return (ISC_R_NOMEMORY);
1278                 strcpy(journal, zone->masterfile);
1279                 strcat(journal, ".jnl");
1280         } else {
1281                 journal = NULL;
1282         }
1283         result = dns_zone_setstring(zone, &zone->journal, journal);
1284         if (journal != NULL)
1285                 isc_mem_free(zone->mctx, journal);
1286         return (result);
1287 }
1288
1289 isc_result_t
1290 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1291         isc_result_t result = ISC_R_SUCCESS;
1292
1293         REQUIRE(DNS_ZONE_VALID(zone));
1294
1295         LOCK_ZONE(zone);
1296         result = dns_zone_setstring(zone, &zone->journal, journal);
1297         UNLOCK_ZONE(zone);
1298
1299         return (result);
1300 }
1301
1302 char *
1303 dns_zone_getjournal(dns_zone_t *zone) {
1304         REQUIRE(DNS_ZONE_VALID(zone));
1305
1306         return (zone->journal);
1307 }
1308
1309 /*
1310  * Return true iff the zone is "dynamic", in the sense that the zone's
1311  * master file (if any) is written by the server, rather than being
1312  * updated manually and read by the server.
1313  *
1314  * This is true for slave zones, stub zones, and zones that allow
1315  * dynamic updates either by having an update policy ("ssutable")
1316  * or an "allow-update" ACL with a value other than exactly "{ none; }".
1317  */
1318 static isc_boolean_t
1319 zone_isdynamic(dns_zone_t *zone) {
1320         REQUIRE(DNS_ZONE_VALID(zone));
1321
1322         return (ISC_TF(zone->type == dns_zone_slave ||
1323                        zone->type == dns_zone_stub ||
1324                        (!zone->update_disabled && zone->ssutable != NULL) ||
1325                        (!zone->update_disabled && zone->update_acl != NULL &&
1326                         !dns_acl_isnone(zone->update_acl))));
1327 }
1328
1329
1330 static isc_result_t
1331 zone_load(dns_zone_t *zone, unsigned int flags) {
1332         isc_result_t result;
1333         isc_time_t now;
1334         isc_time_t loadtime, filetime;
1335         dns_db_t *db = NULL;
1336         isc_boolean_t rbt;
1337
1338         REQUIRE(DNS_ZONE_VALID(zone));
1339
1340         LOCK_ZONE(zone);
1341         TIME_NOW(&now);
1342
1343         INSIST(zone->type != dns_zone_none);
1344
1345         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1346                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1347                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1348                 result = DNS_R_CONTINUE;
1349                 goto cleanup;
1350         }
1351
1352
1353         INSIST(zone->db_argc >= 1);
1354
1355         rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1356               strcmp(zone->db_argv[0], "rbt64") == 0;
1357
1358         if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1359                 /*
1360                  * The zone has no master file configured.
1361                  */
1362                 result = ISC_R_SUCCESS;
1363                 goto cleanup;
1364         }
1365
1366         if (zone->db != NULL && zone_isdynamic(zone)) {
1367                 /*
1368                  * This is a slave, stub, or dynamically updated
1369                  * zone being reloaded.  Do nothing - the database
1370                  * we already have is guaranteed to be up-to-date.
1371                  */
1372                 if (zone->type == dns_zone_master)
1373                         result = DNS_R_DYNAMIC;
1374                 else
1375                         result = ISC_R_SUCCESS;
1376                 goto cleanup;
1377         }
1378
1379         /*
1380          * Store the current time before the zone is loaded, so that if the
1381          * file changes between the time of the load and the time that
1382          * zone->loadtime is set, then the file will still be reloaded
1383          * the next time dns_zone_load is called.
1384          */
1385         TIME_NOW(&loadtime);
1386
1387         /*
1388          * Don't do the load if the file that stores the zone is older
1389          * than the last time the zone was loaded.  If the zone has not
1390          * been loaded yet, zone->loadtime will be the epoch.
1391          */
1392         if (zone->masterfile != NULL) {
1393                 /*
1394                  * The file is already loaded.  If we are just doing a
1395                  * "rndc reconfig", we are done.
1396                  */
1397                 if (!isc_time_isepoch(&zone->loadtime) &&
1398                     (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1399                         result = ISC_R_SUCCESS;
1400                         goto cleanup;
1401                 }
1402
1403                 result = isc_file_getmodtime(zone->masterfile, &filetime);
1404                 if (result == ISC_R_SUCCESS) {
1405                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1406                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1407                             isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1408                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1409                                              "skipping load: master file "
1410                                              "older than last load");
1411                                 result = DNS_R_UPTODATE;
1412                                 goto cleanup;
1413                         }
1414                         loadtime = filetime;
1415                 }
1416         }
1417
1418         /*
1419          * Built in zones (with the exception of empty zones) don't need
1420          * to be reloaded.
1421          */
1422         if (zone->type == dns_zone_master &&
1423             strcmp(zone->db_argv[0], "_builtin") == 0 &&
1424             (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1425             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1426                 result = ISC_R_SUCCESS;
1427                 goto cleanup;
1428         }
1429
1430         if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1431             rbt) {
1432                 if (zone->masterfile == NULL ||
1433                     !isc_file_exists(zone->masterfile)) {
1434                         if (zone->masterfile != NULL) {
1435                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1436                                              "no master file");
1437                         }
1438                         zone->refreshtime = now;
1439                         if (zone->task != NULL)
1440                                 zone_settimer(zone, &now);
1441                         result = ISC_R_SUCCESS;
1442                         goto cleanup;
1443                 }
1444         }
1445
1446         dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1447
1448         result = dns_db_create(zone->mctx, zone->db_argv[0],
1449                                &zone->origin, (zone->type == dns_zone_stub) ?
1450                                dns_dbtype_stub : dns_dbtype_zone,
1451                                zone->rdclass,
1452                                zone->db_argc - 1, zone->db_argv + 1,
1453                                &db);
1454
1455         if (result != ISC_R_SUCCESS) {
1456                 dns_zone_log(zone, ISC_LOG_ERROR,
1457                              "loading zone: creating database: %s",
1458                              isc_result_totext(result));
1459                 goto cleanup;
1460         }
1461         dns_db_settask(db, zone->task);
1462
1463         if (! dns_db_ispersistent(db)) {
1464                 if (zone->masterfile != NULL) {
1465                         result = zone_startload(db, zone, loadtime);
1466                 } else {
1467                         result = DNS_R_NOMASTERFILE;
1468                         if (zone->type == dns_zone_master) {
1469                                 dns_zone_log(zone, ISC_LOG_ERROR,
1470                                              "loading zone: "
1471                                              "no master file configured");
1472                                 goto cleanup;
1473                         }
1474                         dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1475                                      "no master file configured: continuing");
1476                 }
1477         }
1478
1479         if (result == DNS_R_CONTINUE) {
1480                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1481                 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1482                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1483                 goto cleanup;
1484         }
1485
1486         result = zone_postload(zone, db, loadtime, result);
1487
1488  cleanup:
1489         UNLOCK_ZONE(zone);
1490         if (db != NULL)
1491                 dns_db_detach(&db);
1492         return (result);
1493 }
1494
1495 isc_result_t
1496 dns_zone_load(dns_zone_t *zone) {
1497         return (zone_load(zone, 0));
1498 }
1499
1500 isc_result_t
1501 dns_zone_loadnew(dns_zone_t *zone) {
1502         return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1503 }
1504
1505 isc_result_t
1506 dns_zone_loadandthaw(dns_zone_t *zone) {
1507         isc_result_t result;
1508
1509         result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1510         switch (result) {
1511         case DNS_R_CONTINUE:
1512                 /* Deferred thaw. */
1513                 break;
1514         case ISC_R_SUCCESS:
1515         case DNS_R_UPTODATE:
1516         case DNS_R_SEENINCLUDE:
1517                 zone->update_disabled = ISC_FALSE;
1518                 break;
1519         case DNS_R_NOMASTERFILE:
1520                 zone->update_disabled = ISC_FALSE;
1521                 break;
1522         default:
1523                 /* Error, remain in disabled state. */
1524                 break;
1525         }
1526         return (result);
1527 }
1528
1529 static unsigned int
1530 get_master_options(dns_zone_t *zone) {
1531         unsigned int options;
1532
1533         options = DNS_MASTER_ZONE;
1534         if (zone->type == dns_zone_slave)
1535                 options |= DNS_MASTER_SLAVE;
1536         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1537                 options |= DNS_MASTER_CHECKNS;
1538         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1539                 options |= DNS_MASTER_FATALNS;
1540         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1541                 options |= DNS_MASTER_CHECKNAMES;
1542         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1543                 options |= DNS_MASTER_CHECKNAMESFAIL;
1544         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1545                 options |= DNS_MASTER_CHECKMX;
1546         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1547                 options |= DNS_MASTER_CHECKMXFAIL;
1548         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1549                 options |= DNS_MASTER_CHECKWILDCARD;
1550         if (zone->type == dns_zone_master &&
1551             ((zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl)) ||
1552               zone->ssutable != NULL))
1553                 options |= DNS_MASTER_RESIGN;
1554         return (options);
1555 }
1556
1557 static void
1558 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1559         dns_load_t *load = event->ev_arg;
1560         isc_result_t result = ISC_R_SUCCESS;
1561         unsigned int options;
1562
1563         REQUIRE(DNS_LOAD_VALID(load));
1564
1565         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1566                 result = ISC_R_CANCELED;
1567         isc_event_free(&event);
1568         if (result == ISC_R_CANCELED)
1569                 goto fail;
1570
1571         options = get_master_options(load->zone);
1572
1573         result = dns_master_loadfileinc3(load->zone->masterfile,
1574                                          dns_db_origin(load->db),
1575                                          dns_db_origin(load->db),
1576                                          load->zone->rdclass,
1577                                          options,
1578                                          load->zone->sigresigninginterval,
1579                                          &load->callbacks, task,
1580                                          zone_loaddone, load,
1581                                          &load->zone->lctx, load->zone->mctx,
1582                                          load->zone->masterformat);
1583         if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1584             result != DNS_R_SEENINCLUDE)
1585                 goto fail;
1586         return;
1587
1588  fail:
1589         zone_loaddone(load, result);
1590 }
1591
1592 static void
1593 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1594         const char me[] = "zone_gotwritehandle";
1595         dns_zone_t *zone = event->ev_arg;
1596         isc_result_t result = ISC_R_SUCCESS;
1597         dns_dbversion_t *version = NULL;
1598
1599         REQUIRE(DNS_ZONE_VALID(zone));
1600         INSIST(task == zone->task);
1601         ENTER;
1602
1603         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1604                 result = ISC_R_CANCELED;
1605         isc_event_free(&event);
1606         if (result == ISC_R_CANCELED)
1607                 goto fail;
1608
1609         LOCK_ZONE(zone);
1610         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1611         if (zone->db != NULL) {
1612                 dns_db_currentversion(zone->db, &version);
1613                 result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1614                                              &dns_master_style_default,
1615                                              zone->masterfile, zone->task,
1616                                              dump_done, zone, &zone->dctx,
1617                                              zone->masterformat);
1618                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1619         } else
1620                 result = ISC_R_CANCELED;
1621         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1622         UNLOCK_ZONE(zone);
1623         if (result != DNS_R_CONTINUE)
1624                 goto fail;
1625         return;
1626
1627  fail:
1628         dump_done(zone, result);
1629 }
1630
1631 static isc_result_t
1632 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1633         dns_load_t *load;
1634         isc_result_t result;
1635         isc_result_t tresult;
1636         unsigned int options;
1637
1638         options = get_master_options(zone);
1639
1640         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1641                 options |= DNS_MASTER_MANYERRORS;
1642
1643         if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1644                 load = isc_mem_get(zone->mctx, sizeof(*load));
1645                 if (load == NULL)
1646                         return (ISC_R_NOMEMORY);
1647
1648                 load->mctx = NULL;
1649                 load->zone = NULL;
1650                 load->db = NULL;
1651                 load->loadtime = loadtime;
1652                 load->magic = LOAD_MAGIC;
1653
1654                 isc_mem_attach(zone->mctx, &load->mctx);
1655                 zone_iattach(zone, &load->zone);
1656                 dns_db_attach(db, &load->db);
1657                 dns_rdatacallbacks_init(&load->callbacks);
1658                 result = dns_db_beginload(db, &load->callbacks.add,
1659                                           &load->callbacks.add_private);
1660                 if (result != ISC_R_SUCCESS)
1661                         goto cleanup;
1662                 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1663                                        zone_gotreadhandle, load,
1664                                        &zone->readio);
1665                 if (result != ISC_R_SUCCESS) {
1666                         /*
1667                          * We can't report multiple errors so ignore
1668                          * the result of dns_db_endload().
1669                          */
1670                         (void)dns_db_endload(load->db,
1671                                              &load->callbacks.add_private);
1672                         goto cleanup;
1673                 } else
1674                         result = DNS_R_CONTINUE;
1675         } else {
1676                 dns_rdatacallbacks_t callbacks;
1677
1678                 dns_rdatacallbacks_init(&callbacks);
1679                 result = dns_db_beginload(db, &callbacks.add,
1680                                           &callbacks.add_private);
1681                 if (result != ISC_R_SUCCESS)
1682                         return (result);
1683                 result = dns_master_loadfile3(zone->masterfile, &zone->origin,
1684                                               &zone->origin, zone->rdclass,
1685                                               options, zone->sigresigninginterval,
1686                                               &callbacks, zone->mctx,
1687                                               zone->masterformat);
1688                 tresult = dns_db_endload(db, &callbacks.add_private);
1689                 if (result == ISC_R_SUCCESS)
1690                         result = tresult;
1691         }
1692
1693         return (result);
1694
1695  cleanup:
1696         load->magic = 0;
1697         dns_db_detach(&load->db);
1698         zone_idetach(&load->zone);
1699         isc_mem_detach(&load->mctx);
1700         isc_mem_put(zone->mctx, load, sizeof(*load));
1701         return (result);
1702 }
1703
1704 static isc_boolean_t
1705 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1706               dns_name_t *owner)
1707 {
1708         isc_result_t result;
1709         char ownerbuf[DNS_NAME_FORMATSIZE];
1710         char namebuf[DNS_NAME_FORMATSIZE];
1711         char altbuf[DNS_NAME_FORMATSIZE];
1712         dns_fixedname_t fixed;
1713         dns_name_t *foundname;
1714         int level;
1715
1716         /*
1717          * "." means the services does not exist.
1718          */
1719         if (dns_name_equal(name, dns_rootname))
1720                 return (ISC_TRUE);
1721
1722         /*
1723          * Outside of zone.
1724          */
1725         if (!dns_name_issubdomain(name, &zone->origin)) {
1726                 if (zone->checkmx != NULL)
1727                         return ((zone->checkmx)(zone, name, owner));
1728                 return (ISC_TRUE);
1729         }
1730
1731         if (zone->type == dns_zone_master)
1732                 level = ISC_LOG_ERROR;
1733         else
1734                 level = ISC_LOG_WARNING;
1735
1736         dns_fixedname_init(&fixed);
1737         foundname = dns_fixedname_name(&fixed);
1738
1739         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1740                              0, 0, NULL, foundname, NULL, NULL);
1741         if (result == ISC_R_SUCCESS)
1742                 return (ISC_TRUE);
1743
1744         if (result == DNS_R_NXRRSET) {
1745                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1746                                      0, 0, NULL, foundname, NULL, NULL);
1747                 if (result == ISC_R_SUCCESS)
1748                         return (ISC_TRUE);
1749         }
1750
1751         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1752         dns_name_format(name, namebuf, sizeof namebuf);
1753         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1754             result == DNS_R_EMPTYNAME) {
1755                 dns_zone_log(zone, level,
1756                              "%s/MX '%s' has no address records (A or AAAA)",
1757                              ownerbuf, namebuf);
1758                 /* XXX950 make fatal for 9.5.0. */
1759                 return (ISC_TRUE);
1760         }
1761
1762         if (result == DNS_R_CNAME) {
1763                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1764                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1765                         level = ISC_LOG_WARNING;
1766                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1767                         dns_zone_log(zone, level,
1768                                      "%s/MX '%s' is a CNAME (illegal)",
1769                                      ownerbuf, namebuf);
1770                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1771         }
1772
1773         if (result == DNS_R_DNAME) {
1774                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1775                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1776                         level = ISC_LOG_WARNING;
1777                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1778                         dns_name_format(foundname, altbuf, sizeof altbuf);
1779                         dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1780                                      " '%s' (illegal)", ownerbuf, namebuf,
1781                                      altbuf);
1782                 }
1783                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1784         }
1785
1786         if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1787                 return ((zone->checkmx)(zone, name, owner));
1788
1789         return (ISC_TRUE);
1790 }
1791
1792 static isc_boolean_t
1793 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1794                dns_name_t *owner)
1795 {
1796         isc_result_t result;
1797         char ownerbuf[DNS_NAME_FORMATSIZE];
1798         char namebuf[DNS_NAME_FORMATSIZE];
1799         char altbuf[DNS_NAME_FORMATSIZE];
1800         dns_fixedname_t fixed;
1801         dns_name_t *foundname;
1802         int level;
1803
1804         /*
1805          * "." means the services does not exist.
1806          */
1807         if (dns_name_equal(name, dns_rootname))
1808                 return (ISC_TRUE);
1809
1810         /*
1811          * Outside of zone.
1812          */
1813         if (!dns_name_issubdomain(name, &zone->origin)) {
1814                 if (zone->checksrv != NULL)
1815                         return ((zone->checksrv)(zone, name, owner));
1816                 return (ISC_TRUE);
1817         }
1818
1819         if (zone->type == dns_zone_master)
1820                 level = ISC_LOG_ERROR;
1821         else
1822                 level = ISC_LOG_WARNING;
1823
1824         dns_fixedname_init(&fixed);
1825         foundname = dns_fixedname_name(&fixed);
1826
1827         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1828                              0, 0, NULL, foundname, NULL, NULL);
1829         if (result == ISC_R_SUCCESS)
1830                 return (ISC_TRUE);
1831
1832         if (result == DNS_R_NXRRSET) {
1833                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1834                                      0, 0, NULL, foundname, NULL, NULL);
1835                 if (result == ISC_R_SUCCESS)
1836                         return (ISC_TRUE);
1837         }
1838
1839         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1840         dns_name_format(name, namebuf, sizeof namebuf);
1841         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1842             result == DNS_R_EMPTYNAME) {
1843                 dns_zone_log(zone, level,
1844                              "%s/SRV '%s' has no address records (A or AAAA)",
1845                              ownerbuf, namebuf);
1846                 /* XXX950 make fatal for 9.5.0. */
1847                 return (ISC_TRUE);
1848         }
1849
1850         if (result == DNS_R_CNAME) {
1851                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1852                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1853                         level = ISC_LOG_WARNING;
1854                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1855                         dns_zone_log(zone, level,
1856                                      "%s/SRV '%s' is a CNAME (illegal)",
1857                                      ownerbuf, namebuf);
1858                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1859         }
1860
1861         if (result == DNS_R_DNAME) {
1862                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1863                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1864                         level = ISC_LOG_WARNING;
1865                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1866                         dns_name_format(foundname, altbuf, sizeof altbuf);
1867                         dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1868                                      "DNAME '%s' (illegal)", ownerbuf, namebuf,
1869                                      altbuf);
1870                 }
1871                 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1872         }
1873
1874         if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1875                 return ((zone->checksrv)(zone, name, owner));
1876
1877         return (ISC_TRUE);
1878 }
1879
1880 static isc_boolean_t
1881 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1882                 dns_name_t *owner)
1883 {
1884         isc_boolean_t answer = ISC_TRUE;
1885         isc_result_t result, tresult;
1886         char ownerbuf[DNS_NAME_FORMATSIZE];
1887         char namebuf[DNS_NAME_FORMATSIZE];
1888         char altbuf[DNS_NAME_FORMATSIZE];
1889         dns_fixedname_t fixed;
1890         dns_name_t *foundname;
1891         dns_rdataset_t a;
1892         dns_rdataset_t aaaa;
1893         int level;
1894
1895         /*
1896          * Outside of zone.
1897          */
1898         if (!dns_name_issubdomain(name, &zone->origin)) {
1899                 if (zone->checkns != NULL)
1900                         return ((zone->checkns)(zone, name, owner, NULL, NULL));
1901                 return (ISC_TRUE);
1902         }
1903
1904         if (zone->type == dns_zone_master)
1905                 level = ISC_LOG_ERROR;
1906         else
1907                 level = ISC_LOG_WARNING;
1908
1909         dns_fixedname_init(&fixed);
1910         foundname = dns_fixedname_name(&fixed);
1911         dns_rdataset_init(&a);
1912         dns_rdataset_init(&aaaa);
1913
1914         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1915                              DNS_DBFIND_GLUEOK, 0, NULL,
1916                              foundname, &a, NULL);
1917
1918         if (result == ISC_R_SUCCESS) {
1919                 dns_rdataset_disassociate(&a);
1920                 return (ISC_TRUE);
1921         } else if (result == DNS_R_DELEGATION)
1922                 dns_rdataset_disassociate(&a);
1923
1924         if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1925             result == DNS_R_GLUE) {
1926                 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1927                                      DNS_DBFIND_GLUEOK, 0, NULL,
1928                                      foundname, &aaaa, NULL);
1929                 if (tresult == ISC_R_SUCCESS) {
1930                         dns_rdataset_disassociate(&aaaa);
1931                         return (ISC_TRUE);
1932                 }
1933                 if (tresult == DNS_R_DELEGATION)
1934                         dns_rdataset_disassociate(&aaaa);
1935                 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
1936                         /*
1937                          * Check glue against child zone.
1938                          */
1939                         if (zone->checkns != NULL)
1940                                 answer = (zone->checkns)(zone, name, owner,
1941                                                          &a, &aaaa);
1942                         if (dns_rdataset_isassociated(&a))
1943                                 dns_rdataset_disassociate(&a);
1944                         if (dns_rdataset_isassociated(&aaaa))
1945                                 dns_rdataset_disassociate(&aaaa);
1946                         return (answer);
1947                 }
1948         }
1949
1950         dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1951         dns_name_format(name, namebuf, sizeof namebuf);
1952         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1953             result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
1954                 const char *what;
1955                 isc_boolean_t required = ISC_FALSE;
1956                 if (dns_name_issubdomain(name, owner)) {
1957                         what = "REQUIRED GLUE ";
1958                         required = ISC_TRUE;
1959                  } else if (result == DNS_R_DELEGATION)
1960                         what = "SIBLING GLUE ";
1961                 else
1962                         what = "";
1963
1964                 if (result != DNS_R_DELEGATION || required ||
1965                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
1966                         dns_zone_log(zone, level, "%s/NS '%s' has no %s"
1967                                      "address records (A or AAAA)",
1968                                      ownerbuf, namebuf, what);
1969                         /*
1970                          * Log missing address record.
1971                          */
1972                         if (result == DNS_R_DELEGATION && zone->checkns != NULL)
1973                                 (void)(zone->checkns)(zone, name, owner,
1974                                                       &a, &aaaa);
1975                         /* XXX950 make fatal for 9.5.0. */
1976                         /* answer = ISC_FALSE; */
1977                 }
1978         } else if (result == DNS_R_CNAME) {
1979                 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
1980                              ownerbuf, namebuf);
1981                 /* XXX950 make fatal for 9.5.0. */
1982                 /* answer = ISC_FALSE; */
1983         } else if (result == DNS_R_DNAME) {
1984                 dns_name_format(foundname, altbuf, sizeof altbuf);
1985                 dns_zone_log(zone, level,
1986                              "%s/NS '%s' is below a DNAME '%s' (illegal)",
1987                              ownerbuf, namebuf, altbuf);
1988                 /* XXX950 make fatal for 9.5.0. */
1989                 /* answer = ISC_FALSE; */
1990         }
1991
1992         if (dns_rdataset_isassociated(&a))
1993                 dns_rdataset_disassociate(&a);
1994         if (dns_rdataset_isassociated(&aaaa))
1995                 dns_rdataset_disassociate(&aaaa);
1996         return (answer);
1997 }
1998
1999 static isc_boolean_t
2000 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2001         dns_dbiterator_t *dbiterator = NULL;
2002         dns_dbnode_t *node = NULL;
2003         dns_rdataset_t rdataset;
2004         dns_fixedname_t fixed;
2005         dns_fixedname_t fixedbottom;
2006         dns_rdata_mx_t mx;
2007         dns_rdata_ns_t ns;
2008         dns_rdata_in_srv_t srv;
2009         dns_rdata_t rdata;
2010         dns_name_t *name;
2011         dns_name_t *bottom;
2012         isc_result_t result;
2013         isc_boolean_t ok = ISC_TRUE;
2014
2015         dns_fixedname_init(&fixed);
2016         name = dns_fixedname_name(&fixed);
2017         dns_fixedname_init(&fixedbottom);
2018         bottom = dns_fixedname_name(&fixedbottom);
2019         dns_rdataset_init(&rdataset);
2020         dns_rdata_init(&rdata);
2021
2022         result = dns_db_createiterator(db, 0, &dbiterator);
2023         if (result != ISC_R_SUCCESS)
2024                 return (ISC_TRUE);
2025
2026         result = dns_dbiterator_first(dbiterator);
2027         while (result == ISC_R_SUCCESS) {
2028                 result = dns_dbiterator_current(dbiterator, &node, name);
2029                 if (result != ISC_R_SUCCESS)
2030                         goto cleanup;
2031
2032                 /*
2033                  * Is this name visible in the zone?
2034                  */
2035                 if (!dns_name_issubdomain(name, &zone->origin) ||
2036                     (dns_name_countlabels(bottom) > 0 &&
2037                      dns_name_issubdomain(name, bottom)))
2038                         goto next;
2039
2040                 /*
2041                  * Don't check the NS records at the origin.
2042                  */
2043                 if (dns_name_equal(name, &zone->origin))
2044                         goto checkmx;
2045
2046                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2047                                              0, 0, &rdataset, NULL);
2048                 if (result != ISC_R_SUCCESS)
2049                         goto checkmx;
2050                 /*
2051                  * Remember bottom of zone.
2052                  */
2053                 dns_name_copy(name, bottom, NULL);
2054
2055                 result = dns_rdataset_first(&rdataset);
2056                 while (result == ISC_R_SUCCESS) {
2057                         dns_rdataset_current(&rdataset, &rdata);
2058                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2059                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2060                         if (!zone_check_glue(zone, db, &ns.name, name))
2061                                 ok = ISC_FALSE;
2062                         dns_rdata_reset(&rdata);
2063                         result = dns_rdataset_next(&rdataset);
2064                 }
2065                 dns_rdataset_disassociate(&rdataset);
2066
2067  checkmx:
2068                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2069                                              0, 0, &rdataset, NULL);
2070                 if (result != ISC_R_SUCCESS)
2071                         goto checksrv;
2072                 result = dns_rdataset_first(&rdataset);
2073                 while (result == ISC_R_SUCCESS) {
2074                         dns_rdataset_current(&rdataset, &rdata);
2075                         result = dns_rdata_tostruct(&rdata, &mx, NULL);
2076                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2077                         if (!zone_check_mx(zone, db, &mx.mx, name))
2078                                 ok = ISC_FALSE;
2079                         dns_rdata_reset(&rdata);
2080                         result = dns_rdataset_next(&rdataset);
2081                 }
2082                 dns_rdataset_disassociate(&rdataset);
2083
2084  checksrv:
2085                 if (zone->rdclass != dns_rdataclass_in)
2086                         goto next;
2087                 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2088                                              0, 0, &rdataset, NULL);
2089                 if (result != ISC_R_SUCCESS)
2090                         goto next;
2091                 result = dns_rdataset_first(&rdataset);
2092                 while (result == ISC_R_SUCCESS) {
2093                         dns_rdataset_current(&rdataset, &rdata);
2094                         result = dns_rdata_tostruct(&rdata, &srv, NULL);
2095                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2096                         if (!zone_check_srv(zone, db, &srv.target, name))
2097                                 ok = ISC_FALSE;
2098                         dns_rdata_reset(&rdata);
2099                         result = dns_rdataset_next(&rdataset);
2100                 }
2101                 dns_rdataset_disassociate(&rdataset);
2102
2103  next:
2104                 dns_db_detachnode(db, &node);
2105                 result = dns_dbiterator_next(dbiterator);
2106         }
2107
2108  cleanup:
2109         if (node != NULL)
2110                 dns_db_detachnode(db, &node);
2111         dns_dbiterator_destroy(&dbiterator);
2112
2113         return (ok);
2114 }
2115
2116 /*
2117  * OpenSSL verification of RSA keys with exponent 3 is known to be
2118  * broken prior OpenSSL 0.9.8c/0.9.7k.  Look for such keys and warn
2119  * if they are in use.
2120  */
2121 static void
2122 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2123         dns_dbnode_t *node = NULL;
2124         dns_dbversion_t *version = NULL;
2125         dns_rdata_dnskey_t dnskey;
2126         dns_rdata_t rdata = DNS_RDATA_INIT;
2127         dns_rdataset_t rdataset;
2128         isc_result_t result;
2129         isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2130         const char *algorithm;
2131
2132         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2133         if (result != ISC_R_SUCCESS)
2134                 goto cleanup;
2135
2136         dns_db_currentversion(db, &version);
2137         dns_rdataset_init(&rdataset);
2138         result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2139                                      dns_rdatatype_none, 0, &rdataset, NULL);
2140         if (result != ISC_R_SUCCESS)
2141                 goto cleanup;
2142
2143         for (result = dns_rdataset_first(&rdataset);
2144              result == ISC_R_SUCCESS;
2145              result = dns_rdataset_next(&rdataset))
2146         {
2147                 dns_rdataset_current(&rdataset, &rdata);
2148                 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2149                 INSIST(result == ISC_R_SUCCESS);
2150
2151                 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2152                      dnskey.algorithm == DST_ALG_RSAMD5) &&
2153                      dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2154                      dnskey.data[1] == 3)
2155                 {
2156                         if (dnskey.algorithm == DST_ALG_RSASHA1) {
2157                                 logit = !foundrsa;
2158                                 foundrsa = ISC_TRUE;
2159                                 algorithm = "RSASHA1";
2160                         } else {
2161                                 logit = !foundmd5;
2162                                 foundmd5 = ISC_TRUE;
2163                                 algorithm = "RSAMD5";
2164                         }
2165                         if (logit)
2166                                 dns_zone_log(zone, ISC_LOG_WARNING,
2167                                              "weak %s (%u) key found "
2168                                              "(exponent=3)", algorithm,
2169                                              dnskey.algorithm);
2170                         if (foundrsa && foundmd5)
2171                                 break;
2172                 }
2173                 dns_rdata_reset(&rdata);
2174         }
2175         dns_rdataset_disassociate(&rdataset);
2176
2177  cleanup:
2178         if (node != NULL)
2179                 dns_db_detachnode(db, &node);
2180         if (version != NULL)
2181                 dns_db_closeversion(db, &version, ISC_FALSE);
2182
2183 }
2184
2185 static void
2186 resume_signingwithkey(dns_zone_t *zone) {
2187         dns_dbnode_t *node = NULL;
2188         dns_dbversion_t *version = NULL;
2189         dns_rdata_t rdata = DNS_RDATA_INIT;
2190         dns_rdataset_t rdataset;
2191         isc_result_t result;
2192
2193         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2194         if (result != ISC_R_SUCCESS)
2195                 goto cleanup;
2196
2197         dns_db_currentversion(zone->db, &version);
2198         dns_rdataset_init(&rdataset);
2199         result = dns_db_findrdataset(zone->db, node, version,
2200                                      zone->privatetype,
2201                                      dns_rdatatype_none, 0,
2202                                      &rdataset, NULL);
2203         if (result != ISC_R_SUCCESS)
2204                 goto cleanup;
2205
2206         for (result = dns_rdataset_first(&rdataset);
2207              result == ISC_R_SUCCESS;
2208              result = dns_rdataset_next(&rdataset))
2209         {
2210                 dns_rdataset_current(&rdataset, &rdata);
2211                 if (rdata.length != 5 || rdata.data[4] != 0) {
2212                         dns_rdata_reset(&rdata);
2213                         continue;
2214                 }
2215
2216                 result = zone_signwithkey(zone, rdata.data[0],
2217                                           (rdata.data[1] << 8) | rdata.data[2],
2218                                           ISC_TF(rdata.data[3]));
2219                 if (result != ISC_R_SUCCESS) {
2220                         dns_zone_log(zone, ISC_LOG_ERROR,
2221                                      "zone_signwithkey failed: %s",
2222                                      dns_result_totext(result));
2223                 }
2224                 dns_rdata_reset(&rdata);
2225         }
2226         dns_rdataset_disassociate(&rdataset);
2227
2228  cleanup:
2229         if (node != NULL)
2230                 dns_db_detachnode(zone->db, &node);
2231         if (version != NULL)
2232                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2233
2234 }
2235
2236 static isc_result_t
2237 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2238         dns_nsec3chain_t *nsec3chain, *current;
2239         isc_result_t result;
2240         isc_time_t now;
2241         unsigned int options = 0;
2242
2243         nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2244         if (nsec3chain == NULL)
2245                 return (ISC_R_NOMEMORY);
2246
2247         nsec3chain->magic = 0;
2248         nsec3chain->done = ISC_FALSE;
2249         nsec3chain->db = NULL;
2250         nsec3chain->dbiterator = NULL;
2251         nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2252         nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2253         nsec3chain->nsec3param.hash = nsec3param->hash;
2254         nsec3chain->nsec3param.iterations = nsec3param->iterations;
2255         nsec3chain->nsec3param.flags = nsec3param->flags;
2256         nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2257         memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2258         nsec3chain->nsec3param.salt = nsec3chain->salt;
2259         nsec3chain->seen_nsec = ISC_FALSE;
2260         nsec3chain->delete_nsec = ISC_FALSE;
2261         nsec3chain->save_delete_nsec = ISC_FALSE;
2262
2263         for (current = ISC_LIST_HEAD(zone->nsec3chain);
2264              current != NULL;
2265              current = ISC_LIST_NEXT(current, link)) {
2266                 if (current->db == zone->db &&
2267                     current->nsec3param.hash == nsec3param->hash &&
2268                     current->nsec3param.iterations == nsec3param->iterations &&
2269                     current->nsec3param.salt_length == nsec3param->salt_length
2270                     && !memcmp(current->nsec3param.salt, nsec3param->salt,
2271                                nsec3param->salt_length))
2272                         current->done = ISC_TRUE;
2273         }
2274
2275         if (zone->db != NULL) {
2276                 dns_db_attach(zone->db, &nsec3chain->db);
2277                 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2278                         options = DNS_DB_NONSEC3;
2279                 result = dns_db_createiterator(nsec3chain->db, options,
2280                                                &nsec3chain->dbiterator);
2281                 if (result == ISC_R_SUCCESS)
2282                         dns_dbiterator_first(nsec3chain->dbiterator);
2283                 if (result == ISC_R_SUCCESS) {
2284                         dns_dbiterator_pause(nsec3chain->dbiterator);
2285                         ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2286                                                nsec3chain, link);
2287                         nsec3chain = NULL;
2288                         if (isc_time_isepoch(&zone->nsec3chaintime)) {
2289                                 TIME_NOW(&now);
2290                                 zone->nsec3chaintime = now;
2291                                 if (zone->task != NULL)
2292                                         zone_settimer(zone, &now);
2293                         }
2294                 }
2295         } else
2296                 result = ISC_R_NOTFOUND;
2297
2298         if (nsec3chain != NULL) {
2299                 if (nsec3chain->db != NULL)
2300                         dns_db_detach(&nsec3chain->db);
2301                 if (nsec3chain->dbiterator != NULL)
2302                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
2303                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2304         }
2305         return (result);
2306 }
2307
2308 static void
2309 resume_addnsec3chain(dns_zone_t *zone) {
2310         dns_dbnode_t *node = NULL;
2311         dns_dbversion_t *version = NULL;
2312         dns_rdata_t rdata = DNS_RDATA_INIT;
2313         dns_rdataset_t rdataset;
2314         isc_result_t result;
2315         dns_rdata_nsec3param_t nsec3param;
2316
2317         result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2318         if (result != ISC_R_SUCCESS)
2319                 goto cleanup;
2320
2321         dns_db_currentversion(zone->db, &version);
2322         dns_rdataset_init(&rdataset);
2323         result = dns_db_findrdataset(zone->db, node, version,
2324                                      dns_rdatatype_nsec3param,
2325                                      dns_rdatatype_none, 0,
2326                                      &rdataset, NULL);
2327         if (result != ISC_R_SUCCESS)
2328                 goto cleanup;
2329
2330         for (result = dns_rdataset_first(&rdataset);
2331              result == ISC_R_SUCCESS;
2332              result = dns_rdataset_next(&rdataset))
2333         {
2334                 dns_rdataset_current(&rdataset, &rdata);
2335                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2336                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2337                 if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
2338                     (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
2339                         result = zone_addnsec3chain(zone, &nsec3param);
2340                         if (result != ISC_R_SUCCESS) {
2341                                 dns_zone_log(zone, ISC_LOG_ERROR,
2342                                              "zone_addnsec3chain failed: %s",
2343                                              dns_result_totext(result));
2344                         }
2345                 }
2346                 dns_rdata_reset(&rdata);
2347         }
2348         dns_rdataset_disassociate(&rdataset);
2349
2350  cleanup:
2351         if (node != NULL)
2352                 dns_db_detachnode(zone->db, &node);
2353         if (version != NULL)
2354                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2355 }
2356
2357 static void
2358 set_resigntime(dns_zone_t *zone) {
2359         dns_rdataset_t rdataset;
2360         dns_fixedname_t fixed;
2361         unsigned int resign;
2362         isc_result_t result;
2363         isc_uint32_t nanosecs;
2364
2365         dns_rdataset_init(&rdataset);
2366         dns_fixedname_init(&fixed);
2367         result  = dns_db_getsigningtime(zone->db, &rdataset,
2368                                         dns_fixedname_name(&fixed));
2369         if (result != ISC_R_SUCCESS) {
2370                 isc_time_settoepoch(&zone->resigntime);
2371                 return;
2372         }
2373         resign = rdataset.resign;
2374         dns_rdataset_disassociate(&rdataset);
2375         isc_random_get(&nanosecs);
2376         nanosecs %= 1000000000;
2377         isc_time_set(&zone->resigntime, resign, nanosecs);
2378 }
2379
2380 static isc_result_t
2381 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2382         dns_dbnode_t *node = NULL;
2383         dns_rdataset_t rdataset;
2384         dns_dbversion_t *version = NULL;
2385         dns_rdata_nsec3param_t nsec3param;
2386         isc_boolean_t ok = ISC_FALSE;
2387         isc_result_t result;
2388         dns_rdata_t rdata = DNS_RDATA_INIT;
2389         isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2390                                 zone_isdynamic(zone) : ISC_FALSE;
2391
2392         dns_rdataset_init(&rdataset);
2393         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2394         if (result != ISC_R_SUCCESS) {
2395                 dns_zone_log(zone, ISC_LOG_ERROR,
2396                              "nsec3param lookup failure: %s",
2397                              dns_result_totext(result));
2398                 return (result);
2399         }
2400         dns_db_currentversion(db, &version);
2401
2402         result = dns_db_findrdataset(db, node, version,
2403                                      dns_rdatatype_nsec3param,
2404                                      dns_rdatatype_none, 0, &rdataset, NULL);
2405         if (result == ISC_R_NOTFOUND) {
2406                 result = ISC_R_SUCCESS;
2407                 goto cleanup;
2408         }
2409         if (result != ISC_R_SUCCESS) {
2410                 dns_zone_log(zone, ISC_LOG_ERROR,
2411                              "nsec3param lookup failure: %s",
2412                              dns_result_totext(result));
2413                 goto cleanup;
2414         }
2415
2416         /*
2417          * For dynamic zones we must support every algorithm so we can
2418          * regenerate all the NSEC3 chains.
2419          * For non-dynamic zones we only need to find a supported algorithm.
2420          */
2421         for (result = dns_rdataset_first(&rdataset);
2422              result == ISC_R_SUCCESS;
2423              result = dns_rdataset_next(&rdataset))
2424         {
2425                 dns_rdataset_current(&rdataset, &rdata);
2426                 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2427                 dns_rdata_reset(&rdata);
2428                 INSIST(result == ISC_R_SUCCESS);
2429                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2430                     nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2431                 {
2432                         dns_zone_log(zone, ISC_LOG_WARNING,
2433                              "nsec3 test \"unknown\" hash algorithm found: %u",
2434                                      nsec3param.hash);
2435                         ok = ISC_TRUE;
2436                 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2437                         if (dynamic) {
2438                                 dns_zone_log(zone, ISC_LOG_ERROR,
2439                                              "unsupported nsec3 hash algorithm"
2440                                              " in dynamic zone: %u",
2441                                              nsec3param.hash);
2442                                 result = DNS_R_BADZONE;
2443                                 /* Stop second error message. */
2444                                 ok = ISC_TRUE;
2445                                 break;
2446                         } else
2447                                 dns_zone_log(zone, ISC_LOG_WARNING,
2448                                      "unsupported nsec3 hash algorithm: %u",
2449                                              nsec3param.hash);
2450                 } else
2451                         ok = ISC_TRUE;
2452         }
2453         if (result == ISC_R_NOMORE)
2454                 result = ISC_R_SUCCESS;
2455
2456         if (!ok) {
2457                 result = DNS_R_BADZONE;
2458                 dns_zone_log(zone, ISC_LOG_ERROR,
2459                              "no supported nsec3 hash algorithm");
2460         }
2461
2462  cleanup:
2463         if (dns_rdataset_isassociated(&rdataset))
2464                 dns_rdataset_disassociate(&rdataset);
2465         dns_db_closeversion(db, &version, ISC_FALSE);
2466         dns_db_detachnode(db, &node);
2467         return (result);
2468 }
2469
2470 static isc_result_t
2471 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
2472               isc_result_t result)
2473 {
2474         unsigned int soacount = 0;
2475         unsigned int nscount = 0;
2476         unsigned int errors = 0;
2477         isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
2478         isc_time_t now;
2479         isc_boolean_t needdump = ISC_FALSE;
2480         isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2481         unsigned int options;
2482
2483         TIME_NOW(&now);
2484
2485         /*
2486          * Initiate zone transfer?  We may need a error code that
2487          * indicates that the "permanent" form does not exist.
2488          * XXX better error feedback to log.
2489          */
2490         if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
2491                 if (zone->type == dns_zone_slave ||
2492                     zone->type == dns_zone_stub) {
2493                         if (result == ISC_R_FILENOTFOUND)
2494                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2495                                              "no master file");
2496                         else if (result != DNS_R_NOMASTERFILE)
2497                                 dns_zone_log(zone, ISC_LOG_ERROR,
2498                                              "loading from master file %s "
2499                                              "failed: %s",
2500                                              zone->masterfile,
2501                                              dns_result_totext(result));
2502                 } else
2503                         dns_zone_log(zone, ISC_LOG_ERROR,
2504                                      "loading from master file %s failed: %s",
2505                                      zone->masterfile,
2506                                      dns_result_totext(result));
2507                 goto cleanup;
2508         }
2509
2510         dns_zone_log(zone, ISC_LOG_DEBUG(2),
2511                      "number of nodes in database: %u",
2512                      dns_db_nodecount(db));
2513
2514         if (result == DNS_R_SEENINCLUDE)
2515                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2516         else
2517                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
2518
2519         /*
2520          * Apply update log, if any, on initial load.
2521          */
2522         if (zone->journal != NULL &&
2523             ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
2524             ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2525         {
2526                 if (zone->type == dns_zone_master &&
2527                     (zone->update_acl != NULL || zone->ssutable != NULL))
2528                         options = DNS_JOURNALOPT_RESIGN;
2529                 else
2530                         options = 0;
2531                 result = dns_journal_rollforward2(zone->mctx, db, options,
2532                                                   zone->sigresigninginterval,
2533                                                   zone->journal);
2534                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
2535                     result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
2536                     result != ISC_R_RANGE) {
2537                         dns_zone_log(zone, ISC_LOG_ERROR,
2538                                      "journal rollforward failed: %s",
2539                                      dns_result_totext(result));
2540                         goto cleanup;
2541                 }
2542                 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
2543                         dns_zone_log(zone, ISC_LOG_ERROR,
2544                                      "journal rollforward failed: "
2545                                      "journal out of sync with zone");
2546                         goto cleanup;
2547                 }
2548                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2549                              "journal rollforward completed "
2550                              "successfully: %s",
2551                              dns_result_totext(result));
2552                 if (result == ISC_R_SUCCESS)
2553                         needdump = ISC_TRUE;
2554         }
2555
2556         dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
2557         /*
2558          * Obtain ns, soa and cname counts for top of zone.
2559          */
2560         INSIST(db != NULL);
2561         result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
2562                                   &refresh, &retry, &expire, &minimum,
2563                                   &errors);
2564         if (result != ISC_R_SUCCESS) {
2565                 dns_zone_log(zone, ISC_LOG_ERROR,
2566                              "could not find NS and/or SOA records");
2567         }
2568
2569         /*
2570          * Master / Slave / Stub zones require both NS and SOA records at
2571          * the top of the zone.
2572          */
2573
2574         switch (zone->type) {
2575         case dns_zone_master:
2576         case dns_zone_slave:
2577         case dns_zone_stub:
2578                 if (soacount != 1) {
2579                         dns_zone_log(zone, ISC_LOG_ERROR,
2580                                      "has %d SOA records", soacount);
2581                         result = DNS_R_BADZONE;
2582                 }
2583                 if (nscount == 0) {
2584                         dns_zone_log(zone, ISC_LOG_ERROR,
2585                                      "has no NS records");
2586                         result = DNS_R_BADZONE;
2587                 }
2588                 if (result != ISC_R_SUCCESS)
2589                         goto cleanup;
2590                 if (zone->type == dns_zone_master && errors != 0) {
2591                         result = DNS_R_BADZONE;
2592                         goto cleanup;
2593                 }
2594                 if (zone->type != dns_zone_stub) {
2595                         result = check_nsec3param(zone, db);
2596                         if (result != ISC_R_SUCCESS)
2597                                 goto cleanup;
2598                 }
2599                 if (zone->type == dns_zone_master &&
2600                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
2601                     !integrity_checks(zone, db)) {
2602                         result = DNS_R_BADZONE;
2603                         goto cleanup;
2604                 }
2605
2606                 if (zone->db != NULL) {
2607                         /*
2608                          * This is checked in zone_replacedb() for slave zones
2609                          * as they don't reload from disk.
2610                          */
2611                         result = zone_get_from_db(zone, zone->db, NULL, NULL,
2612                                                   &oldserial, NULL, NULL, NULL,
2613                                                   NULL, NULL);
2614                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2615                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
2616                             !isc_serial_gt(serial, oldserial)) {
2617                                 isc_uint32_t serialmin, serialmax;
2618
2619                                 INSIST(zone->type == dns_zone_master);
2620
2621                                 serialmin = (oldserial + 1) & 0xffffffffU;
2622                                 serialmax = (oldserial + 0x7fffffffU) &
2623                                              0xffffffffU;
2624                                 dns_zone_log(zone, ISC_LOG_ERROR,
2625                                              "ixfr-from-differences: "
2626                                              "new serial (%u) out of range "
2627                                              "[%u - %u]", serial, serialmin,
2628                                              serialmax);
2629                                 result = DNS_R_BADZONE;
2630                                 goto cleanup;
2631                         } else if (!isc_serial_ge(serial, oldserial))
2632                                 dns_zone_log(zone, ISC_LOG_ERROR,
2633                                              "zone serial has gone backwards");
2634                         else if (serial == oldserial && !hasinclude &&
2635                                  strcmp(zone->db_argv[0], "_builtin") != 0)
2636                                 dns_zone_log(zone, ISC_LOG_ERROR,
2637                                              "zone serial unchanged. "
2638                                              "zone may fail to transfer "
2639                                              "to slaves.");
2640                 }
2641
2642                 if (zone->type == dns_zone_master &&
2643                     (zone->update_acl != NULL || zone->ssutable != NULL) &&
2644                     zone->sigresigninginterval < (3 * refresh) &&
2645                     dns_db_issecure(db))
2646                 {
2647                         dns_zone_log(zone, ISC_LOG_WARNING,
2648                                      "sig-re-signing-interval less than "
2649                                      "3 * refresh.");
2650                 }
2651
2652                 zone->refresh = RANGE(refresh,
2653                                       zone->minrefresh, zone->maxrefresh);
2654                 zone->retry = RANGE(retry,
2655                                     zone->minretry, zone->maxretry);
2656                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
2657                                      DNS_MAX_EXPIRE);
2658                 zone->minimum = minimum;
2659                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
2660
2661                 if (zone->type == dns_zone_slave ||
2662                     zone->type == dns_zone_stub) {
2663                         isc_time_t t;
2664                         isc_uint32_t delay;
2665
2666                         result = isc_file_getmodtime(zone->journal, &t);
2667                         if (result != ISC_R_SUCCESS)
2668                                 result = isc_file_getmodtime(zone->masterfile,
2669                                                              &t);
2670                         if (result == ISC_R_SUCCESS)
2671                                 DNS_ZONE_TIME_ADD(&t, zone->expire,
2672                                                   &zone->expiretime);
2673                         else
2674                                 DNS_ZONE_TIME_ADD(&now, zone->retry,
2675                                                   &zone->expiretime);
2676
2677                         delay = isc_random_jitter(zone->retry,
2678                                                   (zone->retry * 3) / 4);
2679                         DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
2680                         if (isc_time_compare(&zone->refreshtime,
2681                                              &zone->expiretime) >= 0)
2682                                 zone->refreshtime = now;
2683                 }
2684                 break;
2685         default:
2686                 UNEXPECTED_ERROR(__FILE__, __LINE__,
2687                                  "unexpected zone type %d", zone->type);
2688                 result = ISC_R_UNEXPECTED;
2689                 goto cleanup;
2690         }
2691
2692         /*
2693          * Check for weak DNSKEY's.
2694          */
2695         if (zone->type == dns_zone_master)
2696                 zone_check_dnskeys(zone, db);
2697
2698 #if 0
2699         /* destroy notification example. */
2700         {
2701                 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
2702                                                     DNS_EVENT_DBDESTROYED,
2703                                                     dns_zonemgr_dbdestroyed,
2704                                                     zone,
2705                                                     sizeof(isc_event_t));
2706                 dns_db_ondestroy(db, zone->task, &e);
2707         }
2708 #endif
2709
2710         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2711         if (zone->db != NULL) {
2712                 result = zone_replacedb(zone, db, ISC_FALSE);
2713                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2714                 if (result != ISC_R_SUCCESS)
2715                         goto cleanup;
2716         } else {
2717                 zone_attachdb(zone, db);
2718                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2719                 DNS_ZONE_SETFLAG(zone,
2720                                  DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
2721         }
2722         result = ISC_R_SUCCESS;
2723         if (needdump)
2724                 zone_needdump(zone, DNS_DUMP_DELAY);
2725         if (zone->task != NULL) {
2726                 if (zone->type == dns_zone_master) {
2727                         set_resigntime(zone);
2728                         resume_signingwithkey(zone);
2729                         resume_addnsec3chain(zone);
2730                 }
2731                 zone_settimer(zone, &now);
2732         }
2733
2734         if (! dns_db_ispersistent(db))
2735                 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
2736                              dns_db_issecure(db) ? " (signed)" : "");
2737
2738         zone->loadtime = loadtime;
2739         return (result);
2740
2741  cleanup:
2742         if (zone->type == dns_zone_slave ||
2743             zone->type == dns_zone_stub) {
2744                 if (zone->journal != NULL)
2745                         zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
2746                 if (zone->masterfile != NULL)
2747                         zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
2748
2749                 /* Mark the zone for immediate refresh. */
2750                 zone->refreshtime = now;
2751                 if (zone->task != NULL)
2752                         zone_settimer(zone, &now);
2753                 result = ISC_R_SUCCESS;
2754         } else if (zone->type == dns_zone_master)
2755                 dns_zone_log(zone, ISC_LOG_ERROR, "not loaded due to errors.");
2756         return (result);
2757 }
2758
2759 static isc_boolean_t
2760 exit_check(dns_zone_t *zone) {
2761
2762         REQUIRE(LOCKED_ZONE(zone));
2763
2764         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
2765             zone->irefs == 0)
2766         {
2767                 /*
2768                  * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
2769                  */
2770                 INSIST(isc_refcount_current(&zone->erefs) == 0);
2771                 return (ISC_TRUE);
2772         }
2773         return (ISC_FALSE);
2774 }
2775
2776 static isc_boolean_t
2777 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
2778         isc_result_t result;
2779         char namebuf[DNS_NAME_FORMATSIZE];
2780         char altbuf[DNS_NAME_FORMATSIZE];
2781         dns_fixedname_t fixed;
2782         dns_name_t *foundname;
2783         int level;
2784
2785         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
2786                 return (ISC_TRUE);
2787
2788         if (zone->type == dns_zone_master)
2789                 level = ISC_LOG_ERROR;
2790         else
2791                 level = ISC_LOG_WARNING;
2792
2793         dns_fixedname_init(&fixed);
2794         foundname = dns_fixedname_name(&fixed);
2795
2796         result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2797                              0, 0, NULL, foundname, NULL, NULL);
2798         if (result == ISC_R_SUCCESS)
2799                 return (ISC_TRUE);
2800
2801         if (result == DNS_R_NXRRSET) {
2802                 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2803                                      0, 0, NULL, foundname, NULL, NULL);
2804                 if (result == ISC_R_SUCCESS)
2805                         return (ISC_TRUE);
2806         }
2807
2808         dns_name_format(name, namebuf, sizeof namebuf);
2809         if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2810             result == DNS_R_EMPTYNAME) {
2811                 dns_zone_log(zone, level,
2812                              "NS '%s' has no address records (A or AAAA)",
2813                              namebuf);
2814                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2815                 return (ISC_TRUE);
2816         }
2817
2818         if (result == DNS_R_CNAME) {
2819                 dns_zone_log(zone, level, "NS '%s' is a CNAME (illegal)",
2820                              namebuf);
2821                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2822                 return (ISC_TRUE);
2823         }
2824
2825         if (result == DNS_R_DNAME) {
2826                 dns_name_format(foundname, altbuf, sizeof altbuf);
2827                 dns_zone_log(zone, level,
2828                              "NS '%s' is below a DNAME '%s' (illegal)",
2829                              namebuf, altbuf);
2830                 /* XXX950 Make fatal ISC_FALSE for 9.5.0. */
2831                 return (ISC_TRUE);
2832         }
2833
2834         return (ISC_TRUE);
2835 }
2836
2837 static isc_result_t
2838 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
2839                  dns_dbversion_t *version, unsigned int *nscount,
2840                  unsigned int *errors)
2841 {
2842         isc_result_t result;
2843         unsigned int count = 0;
2844         unsigned int ecount = 0;
2845         dns_rdataset_t rdataset;
2846         dns_rdata_t rdata;
2847         dns_rdata_ns_t ns;
2848
2849         dns_rdataset_init(&rdataset);
2850         result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
2851                                      dns_rdatatype_none, 0, &rdataset, NULL);
2852         if (result == ISC_R_NOTFOUND)
2853                 goto success;
2854         if (result != ISC_R_SUCCESS)
2855                 goto invalidate_rdataset;
2856
2857         result = dns_rdataset_first(&rdataset);
2858         while (result == ISC_R_SUCCESS) {
2859                 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
2860                     (zone->type == dns_zone_master ||
2861                      zone->type == dns_zone_slave)) {
2862                         dns_rdata_init(&rdata);
2863                         dns_rdataset_current(&rdataset, &rdata);
2864                         result = dns_rdata_tostruct(&rdata, &ns, NULL);
2865                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2866                         if (dns_name_issubdomain(&ns.name, &zone->origin) &&
2867                             !zone_check_ns(zone, db, &ns.name))
2868                                 ecount++;
2869                 }
2870                 count++;
2871                 result = dns_rdataset_next(&rdataset);
2872         }
2873         dns_rdataset_disassociate(&rdataset);
2874
2875  success:
2876         if (nscount != NULL)
2877                 *nscount = count;
2878         if (errors != NULL)
2879                 *errors = ecount;
2880
2881         result = ISC_R_SUCCESS;
2882
2883  invalidate_rdataset:
2884         dns_rdataset_invalidate(&rdataset);
2885
2886         return (result);
2887 }
2888
2889 static isc_result_t
2890 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
2891                  unsigned int *soacount,
2892                  isc_uint32_t *serial, isc_uint32_t *refresh,
2893                  isc_uint32_t *retry, isc_uint32_t *expire,
2894                  isc_uint32_t *minimum)
2895 {
2896         isc_result_t result;
2897         unsigned int count;
2898         dns_rdataset_t rdataset;
2899         dns_rdata_t rdata = DNS_RDATA_INIT;
2900         dns_rdata_soa_t soa;
2901
2902         dns_rdataset_init(&rdataset);
2903         result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
2904                                      dns_rdatatype_none, 0, &rdataset, NULL);
2905         if (result == ISC_R_NOTFOUND) {
2906                 if (soacount != NULL)
2907                         *soacount = 0;
2908                 if (serial != NULL)
2909                         *serial = 0;
2910                 if (refresh != NULL)
2911                         *refresh = 0;
2912                 if (retry != NULL)
2913                         *retry = 0;
2914                 if (expire != NULL)
2915                         *expire = 0;
2916                 if (minimum != NULL)
2917                         *minimum = 0;
2918                 result = ISC_R_SUCCESS;
2919                 goto invalidate_rdataset;
2920         }
2921         if (result != ISC_R_SUCCESS)
2922                 goto invalidate_rdataset;
2923
2924         count = 0;
2925         result = dns_rdataset_first(&rdataset);
2926         while (result == ISC_R_SUCCESS) {
2927                 dns_rdata_init(&rdata);
2928                 dns_rdataset_current(&rdataset, &rdata);
2929                 count++;
2930                 if (count == 1) {
2931                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
2932                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
2933                 }
2934
2935                 result = dns_rdataset_next(&rdataset);
2936                 dns_rdata_reset(&rdata);
2937         }
2938         dns_rdataset_disassociate(&rdataset);
2939
2940         if (soacount != NULL)
2941                 *soacount = count;
2942
2943         if (count > 0) {
2944                 if (serial != NULL)
2945                         *serial = soa.serial;
2946                 if (refresh != NULL)
2947                         *refresh = soa.refresh;
2948                 if (retry != NULL)
2949                         *retry = soa.retry;
2950                 if (expire != NULL)
2951                         *expire = soa.expire;
2952                 if (minimum != NULL)
2953                         *minimum = soa.minimum;
2954         }
2955
2956         result = ISC_R_SUCCESS;
2957
2958  invalidate_rdataset:
2959         dns_rdataset_invalidate(&rdataset);
2960
2961         return (result);
2962 }
2963
2964 /*
2965  * zone must be locked.
2966  */
2967 static isc_result_t
2968 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
2969                  unsigned int *soacount, isc_uint32_t *serial,
2970                  isc_uint32_t *refresh, isc_uint32_t *retry,
2971                  isc_uint32_t *expire, isc_uint32_t *minimum,
2972                  unsigned int *errors)
2973 {
2974         dns_dbversion_t *version;
2975         isc_result_t result;
2976         isc_result_t answer = ISC_R_SUCCESS;
2977         dns_dbnode_t *node;
2978
2979         REQUIRE(db != NULL);
2980         REQUIRE(zone != NULL);
2981
2982         version = NULL;
2983         dns_db_currentversion(db, &version);
2984
2985         node = NULL;
2986         result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2987         if (result != ISC_R_SUCCESS) {
2988                 answer = result;
2989                 goto closeversion;
2990         }
2991
2992         if (nscount != NULL || errors != NULL) {
2993                 result = zone_count_ns_rr(zone, db, node, version,
2994                                           nscount, errors);
2995                 if (result != ISC_R_SUCCESS)
2996                         answer = result;
2997         }
2998
2999         if (soacount != NULL || serial != NULL || refresh != NULL
3000             || retry != NULL || expire != NULL || minimum != NULL) {
3001                 result = zone_load_soa_rr(db, node, version, soacount,
3002                                           serial, refresh, retry, expire,
3003                                           minimum);
3004                 if (result != ISC_R_SUCCESS)
3005                         answer = result;
3006         }
3007
3008         dns_db_detachnode(db, &node);
3009  closeversion:
3010         dns_db_closeversion(db, &version, ISC_FALSE);
3011
3012         return (answer);
3013 }
3014
3015 void
3016 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
3017         REQUIRE(DNS_ZONE_VALID(source));
3018         REQUIRE(target != NULL && *target == NULL);
3019         isc_refcount_increment(&source->erefs, NULL);
3020         *target = source;
3021 }
3022
3023 void
3024 dns_zone_detach(dns_zone_t **zonep) {
3025         dns_zone_t *zone;
3026         unsigned int refs;
3027         isc_boolean_t free_now = ISC_FALSE;
3028
3029         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3030
3031         zone = *zonep;
3032
3033         isc_refcount_decrement(&zone->erefs, &refs);
3034
3035         if (refs == 0) {
3036                 LOCK_ZONE(zone);
3037                 /*
3038                  * We just detached the last external reference.
3039                  */
3040                 if (zone->task != NULL) {
3041                         /*
3042                          * This zone is being managed.  Post
3043                          * its control event and let it clean
3044                          * up synchronously in the context of
3045                          * its task.
3046                          */
3047                         isc_event_t *ev = &zone->ctlevent;
3048                         isc_task_send(zone->task, &ev);
3049                 } else {
3050                         /*
3051                          * This zone is not being managed; it has
3052                          * no task and can have no outstanding
3053                          * events.  Free it immediately.
3054                          */
3055                         /*
3056                          * Unmanaged zones should not have non-null views;
3057                          * we have no way of detaching from the view here
3058                          * without causing deadlock because this code is called
3059                          * with the view already locked.
3060                          */
3061                         INSIST(zone->view == NULL);
3062                         free_now = ISC_TRUE;
3063                 }
3064                 UNLOCK_ZONE(zone);
3065         }
3066         *zonep = NULL;
3067         if (free_now)
3068                 zone_free(zone);
3069 }
3070
3071 void
3072 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3073         REQUIRE(DNS_ZONE_VALID(source));
3074         REQUIRE(target != NULL && *target == NULL);
3075         LOCK_ZONE(source);
3076         zone_iattach(source, target);
3077         UNLOCK_ZONE(source);
3078 }
3079
3080 static void
3081 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3082
3083         /*
3084          * 'source' locked by caller.
3085          */
3086         REQUIRE(LOCKED_ZONE(source));
3087         REQUIRE(DNS_ZONE_VALID(source));
3088         REQUIRE(target != NULL && *target == NULL);
3089         INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
3090         source->irefs++;
3091         INSIST(source->irefs != 0);
3092         *target = source;
3093 }
3094
3095 static void
3096 zone_idetach(dns_zone_t **zonep) {
3097         dns_zone_t *zone;
3098
3099         /*
3100          * 'zone' locked by caller.
3101          */
3102         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3103         zone = *zonep;
3104         REQUIRE(LOCKED_ZONE(*zonep));
3105         *zonep = NULL;
3106
3107         INSIST(zone->irefs > 0);
3108         zone->irefs--;
3109         INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
3110 }
3111
3112 void
3113 dns_zone_idetach(dns_zone_t **zonep) {
3114         dns_zone_t *zone;
3115         isc_boolean_t free_needed;
3116
3117         REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3118         zone = *zonep;
3119         *zonep = NULL;
3120
3121         LOCK_ZONE(zone);
3122         INSIST(zone->irefs > 0);
3123         zone->irefs--;
3124         free_needed = exit_check(zone);
3125         UNLOCK_ZONE(zone);
3126         if (free_needed)
3127                 zone_free(zone);
3128 }
3129
3130 isc_mem_t *
3131 dns_zone_getmctx(dns_zone_t *zone) {
3132         REQUIRE(DNS_ZONE_VALID(zone));
3133
3134         return (zone->mctx);
3135 }
3136
3137 dns_zonemgr_t *
3138 dns_zone_getmgr(dns_zone_t *zone) {
3139         REQUIRE(DNS_ZONE_VALID(zone));
3140
3141         return (zone->zmgr);
3142 }
3143
3144 void
3145 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
3146         REQUIRE(DNS_ZONE_VALID(zone));
3147
3148         LOCK_ZONE(zone);
3149         if (value)
3150                 DNS_ZONE_SETFLAG(zone, flags);
3151         else
3152                 DNS_ZONE_CLRFLAG(zone, flags);
3153         UNLOCK_ZONE(zone);
3154 }
3155
3156 void
3157 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
3158 {
3159         REQUIRE(DNS_ZONE_VALID(zone));
3160
3161         LOCK_ZONE(zone);
3162         if (value)
3163                 zone->options |= option;
3164         else
3165                 zone->options &= ~option;
3166         UNLOCK_ZONE(zone);
3167 }
3168
3169 unsigned int
3170 dns_zone_getoptions(dns_zone_t *zone) {
3171
3172         REQUIRE(DNS_ZONE_VALID(zone));
3173
3174         return (zone->options);
3175 }
3176
3177 isc_result_t
3178 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
3179         REQUIRE(DNS_ZONE_VALID(zone));
3180
3181         LOCK_ZONE(zone);
3182         zone->xfrsource4 = *xfrsource;
3183         UNLOCK_ZONE(zone);
3184
3185         return (ISC_R_SUCCESS);
3186 }
3187
3188 isc_sockaddr_t *
3189 dns_zone_getxfrsource4(dns_zone_t *zone) {
3190         REQUIRE(DNS_ZONE_VALID(zone));
3191         return (&zone->xfrsource4);
3192 }
3193
3194 isc_result_t
3195 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
3196         REQUIRE(DNS_ZONE_VALID(zone));
3197
3198         LOCK_ZONE(zone);
3199         zone->xfrsource6 = *xfrsource;
3200         UNLOCK_ZONE(zone);
3201
3202         return (ISC_R_SUCCESS);
3203 }
3204
3205 isc_sockaddr_t *
3206 dns_zone_getxfrsource6(dns_zone_t *zone) {
3207         REQUIRE(DNS_ZONE_VALID(zone));
3208         return (&zone->xfrsource6);
3209 }
3210
3211 isc_result_t
3212 dns_zone_setaltxfrsource4(dns_zone_t *zone,
3213                           const isc_sockaddr_t *altxfrsource)
3214 {
3215         REQUIRE(DNS_ZONE_VALID(zone));
3216
3217         LOCK_ZONE(zone);
3218         zone->altxfrsource4 = *altxfrsource;
3219         UNLOCK_ZONE(zone);
3220
3221         return (ISC_R_SUCCESS);
3222 }
3223
3224 isc_sockaddr_t *
3225 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
3226         REQUIRE(DNS_ZONE_VALID(zone));
3227         return (&zone->altxfrsource4);
3228 }
3229
3230 isc_result_t
3231 dns_zone_setaltxfrsource6(dns_zone_t *zone,
3232                           const isc_sockaddr_t *altxfrsource)
3233 {
3234         REQUIRE(DNS_ZONE_VALID(zone));
3235
3236         LOCK_ZONE(zone);
3237         zone->altxfrsource6 = *altxfrsource;
3238         UNLOCK_ZONE(zone);
3239
3240         return (ISC_R_SUCCESS);
3241 }
3242
3243 isc_sockaddr_t *
3244 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
3245         REQUIRE(DNS_ZONE_VALID(zone));
3246         return (&zone->altxfrsource6);
3247 }
3248
3249 isc_result_t
3250 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
3251         REQUIRE(DNS_ZONE_VALID(zone));
3252
3253         LOCK_ZONE(zone);
3254         zone->notifysrc4 = *notifysrc;
3255         UNLOCK_ZONE(zone);
3256
3257         return (ISC_R_SUCCESS);
3258 }
3259
3260 isc_sockaddr_t *
3261 dns_zone_getnotifysrc4(dns_zone_t *zone) {
3262         REQUIRE(DNS_ZONE_VALID(zone));
3263         return (&zone->notifysrc4);
3264 }
3265
3266 isc_result_t
3267 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
3268         REQUIRE(DNS_ZONE_VALID(zone));
3269
3270         LOCK_ZONE(zone);
3271         zone->notifysrc6 = *notifysrc;
3272         UNLOCK_ZONE(zone);
3273
3274         return (ISC_R_SUCCESS);
3275 }
3276
3277 isc_sockaddr_t *
3278 dns_zone_getnotifysrc6(dns_zone_t *zone) {
3279         REQUIRE(DNS_ZONE_VALID(zone));
3280         return (&zone->notifysrc6);
3281 }
3282
3283 isc_result_t
3284 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
3285                        isc_uint32_t count)
3286 {
3287         isc_sockaddr_t *new;
3288
3289         REQUIRE(DNS_ZONE_VALID(zone));
3290         REQUIRE(count == 0 || notify != NULL);
3291
3292         LOCK_ZONE(zone);
3293         if (zone->notify != NULL) {
3294                 isc_mem_put(zone->mctx, zone->notify,
3295                             zone->notifycnt * sizeof(*new));
3296                 zone->notify = NULL;
3297                 zone->notifycnt = 0;
3298         }
3299         if (count != 0) {
3300                 new = isc_mem_get(zone->mctx, count * sizeof(*new));
3301                 if (new == NULL) {
3302                         UNLOCK_ZONE(zone);
3303                         return (ISC_R_NOMEMORY);
3304                 }
3305                 memcpy(new, notify, count * sizeof(*new));
3306                 zone->notify = new;
3307                 zone->notifycnt = count;
3308         }
3309         UNLOCK_ZONE(zone);
3310         return (ISC_R_SUCCESS);
3311 }
3312
3313 isc_result_t
3314 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
3315                     isc_uint32_t count)
3316 {
3317         isc_result_t result;
3318
3319         result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
3320         return (result);
3321 }
3322
3323 static isc_boolean_t
3324 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
3325              isc_uint32_t count)
3326 {
3327         unsigned int i;
3328
3329         for (i = 0; i < count; i++)
3330                 if (!isc_sockaddr_equal(&old[i], &new[i]))
3331                         return (ISC_FALSE);
3332         return (ISC_TRUE);
3333 }
3334
3335 static isc_boolean_t
3336 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
3337         unsigned int i;
3338
3339         if (old == NULL && new == NULL)
3340                 return (ISC_TRUE);
3341         if (old == NULL || new == NULL)
3342                 return (ISC_FALSE);
3343
3344         for (i = 0; i < count; i++) {
3345                 if (old[i] == NULL && new[i] == NULL)
3346                         continue;
3347                 if (old[i] == NULL || new[i] == NULL ||
3348                      !dns_name_equal(old[i], new[i]))
3349                         return (ISC_FALSE);
3350         }
3351         return (ISC_TRUE);
3352 }
3353
3354 isc_result_t
3355 dns_zone_setmasterswithkeys(dns_zone_t *zone,
3356                             const isc_sockaddr_t *masters,
3357                             dns_name_t **keynames,
3358                             isc_uint32_t count)
3359 {
3360         isc_sockaddr_t *new;
3361         isc_result_t result = ISC_R_SUCCESS;
3362         dns_name_t **newname;
3363         isc_boolean_t *newok;
3364         unsigned int i;
3365
3366         REQUIRE(DNS_ZONE_VALID(zone));
3367         REQUIRE(count == 0 || masters != NULL);
3368         if (keynames != NULL) {
3369                 REQUIRE(count != 0);
3370         }
3371
3372         LOCK_ZONE(zone);
3373         /*
3374          * The refresh code assumes that 'masters' wouldn't change under it.
3375          * If it will change then kill off any current refresh in progress
3376          * and update the masters info.  If it won't change then we can just
3377          * unlock and exit.
3378          */
3379         if (count != zone->masterscnt ||
3380             !same_masters(zone->masters, masters, count) ||
3381             !same_keynames(zone->masterkeynames, keynames, count)) {
3382                 if (zone->request != NULL)
3383                         dns_request_cancel(zone->request);
3384         } else
3385                 goto unlock;
3386         if (zone->masters != NULL) {
3387                 isc_mem_put(zone->mctx, zone->masters,
3388                             zone->masterscnt * sizeof(*new));
3389                 zone->masters = NULL;
3390         }
3391         if (zone->masterkeynames != NULL) {
3392                 for (i = 0; i < zone->masterscnt; i++) {
3393                         if (zone->masterkeynames[i] != NULL) {
3394                                 dns_name_free(zone->masterkeynames[i],
3395                                               zone->mctx);
3396                                 isc_mem_put(zone->mctx,
3397                                             zone->masterkeynames[i],
3398                                             sizeof(dns_name_t));
3399                                 zone->masterkeynames[i] = NULL;
3400                         }
3401                 }
3402                 isc_mem_put(zone->mctx, zone->masterkeynames,
3403                             zone->masterscnt * sizeof(dns_name_t *));
3404                 zone->masterkeynames = NULL;
3405         }
3406         if (zone->mastersok != NULL) {
3407                 isc_mem_put(zone->mctx, zone->mastersok,
3408                             zone->masterscnt * sizeof(isc_boolean_t));
3409                 zone->mastersok = NULL;
3410         }
3411         zone->masterscnt = 0;
3412         /*
3413          * If count == 0, don't allocate any space for masters, mastersok or
3414          * keynames so internally, those pointers are NULL if count == 0
3415          */
3416         if (count == 0)
3417                 goto unlock;
3418
3419         /*
3420          * masters must contain count elements!
3421          */
3422         new = isc_mem_get(zone->mctx, count * sizeof(*new));
3423         if (new == NULL) {
3424                 result = ISC_R_NOMEMORY;
3425                 goto unlock;
3426         }
3427         memcpy(new, masters, count * sizeof(*new));
3428
3429         /*
3430          * Similarly for mastersok.
3431          */
3432         newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
3433         if (newok == NULL) {
3434                 result = ISC_R_NOMEMORY;
3435                 isc_mem_put(zone->mctx, new, count * sizeof(*new));
3436                 goto unlock;
3437         };
3438         for (i = 0; i < count; i++)
3439                 newok[i] = ISC_FALSE;
3440
3441         /*
3442          * if keynames is non-NULL, it must contain count elements!
3443          */
3444         newname = NULL;
3445         if (keynames != NULL) {
3446                 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
3447                 if (newname == NULL) {
3448                         result = ISC_R_NOMEMORY;
3449                         isc_mem_put(zone->mctx, new, count * sizeof(*new));
3450                         isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
3451                         goto unlock;
3452                 }
3453                 for (i = 0; i < count; i++)
3454                         newname[i] = NULL;
3455                 for (i = 0; i < count; i++) {
3456                         if (keynames[i] != NULL) {
3457                                 newname[i] = isc_mem_get(zone->mctx,
3458                                                          sizeof(dns_name_t));
3459                                 if (newname[i] == NULL)
3460                                         goto allocfail;
3461                                 dns_name_init(newname[i], NULL);
3462                                 result = dns_name_dup(keynames[i], zone->mctx,
3463                                                       newname[i]);
3464                                 if (result != ISC_R_SUCCESS) {
3465                                 allocfail:
3466                                         for (i = 0; i < count; i++)
3467                                                 if (newname[i] != NULL)
3468                                                         dns_name_free(
3469                                                                newname[i],
3470                                                                zone->mctx);
3471                                         isc_mem_put(zone->mctx, new,
3472                                                     count * sizeof(*new));
3473                                         isc_mem_put(zone->mctx, newok,
3474                                                     count * sizeof(*newok));
3475                                         isc_mem_put(zone->mctx, newname,
3476                                                     count * sizeof(*newname));
3477                                         goto unlock;
3478                                 }
3479                         }
3480                 }
3481         }
3482
3483         /*
3484          * Everything is ok so attach to the zone.
3485          */
3486         zone->curmaster = 0;
3487         zone->masters = new;
3488         zone->mastersok = newok;
3489         zone->masterkeynames = newname;
3490         zone->masterscnt = count;
3491         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
3492
3493  unlock:
3494         UNLOCK_ZONE(zone);
3495         return (result);
3496 }
3497
3498 isc_result_t
3499 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
3500         isc_result_t result = ISC_R_SUCCESS;
3501
3502         REQUIRE(DNS_ZONE_VALID(zone));
3503
3504         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3505         if (zone->db == NULL)
3506                 result = DNS_R_NOTLOADED;
3507         else
3508                 dns_db_attach(zone->db, dpb);
3509         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3510
3511         return (result);
3512 }
3513
3514 /*
3515  * Co-ordinates the starting of routine jobs.
3516  */
3517
3518 void
3519 dns_zone_maintenance(dns_zone_t *zone) {
3520         const char me[] = "dns_zone_maintenance";
3521         isc_time_t now;
3522
3523         REQUIRE(DNS_ZONE_VALID(zone));
3524         ENTER;
3525
3526         LOCK_ZONE(zone);
3527         TIME_NOW(&now);
3528         zone_settimer(zone, &now);
3529         UNLOCK_ZONE(zone);
3530 }
3531
3532 static inline isc_boolean_t
3533 was_dumping(dns_zone_t *zone) {
3534         isc_boolean_t dumping;
3535
3536         REQUIRE(LOCKED_ZONE(zone));
3537
3538         dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
3539         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
3540         if (!dumping) {
3541                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
3542                 isc_time_settoepoch(&zone->dumptime);
3543         }
3544         return (dumping);
3545 }
3546
3547 static isc_result_t
3548 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3549              dns_diff_t *diff)
3550 {
3551         dns_diff_t temp_diff;
3552         isc_result_t result;
3553
3554         /*
3555          * Create a singleton diff.
3556          */
3557         dns_diff_init(diff->mctx, &temp_diff);
3558         temp_diff.resign = diff->resign;
3559         ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3560
3561         /*
3562          * Apply it to the database.
3563          */
3564         result = dns_diff_apply(&temp_diff, db, ver);
3565         ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3566         if (result != ISC_R_SUCCESS) {
3567                 dns_difftuple_free(tuple);
3568                 return (result);
3569         }
3570
3571         /*
3572          * Merge it into the current pending journal entry.
3573          */
3574         dns_diff_appendminimal(diff, tuple);
3575
3576         /*
3577          * Do not clear temp_diff.
3578          */
3579         return (ISC_R_SUCCESS);
3580 }
3581
3582 static isc_result_t
3583 increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
3584                      dns_diff_t *diff, isc_mem_t *mctx)
3585 {
3586         dns_difftuple_t *deltuple = NULL;
3587         dns_difftuple_t *addtuple = NULL;
3588         isc_uint32_t serial;
3589         isc_result_t result;
3590
3591         CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3592         CHECK(dns_difftuple_copy(deltuple, &addtuple));
3593         addtuple->op = DNS_DIFFOP_ADD;
3594
3595         serial = dns_soa_getserial(&addtuple->rdata);
3596
3597         /* RFC1982 */
3598         serial = (serial + 1) & 0xFFFFFFFF;
3599         if (serial == 0)
3600                 serial = 1;
3601
3602         dns_soa_setserial(serial, &addtuple->rdata);
3603         CHECK(do_one_tuple(&deltuple, db, ver, diff));
3604         CHECK(do_one_tuple(&addtuple, db, ver, diff));
3605         result = ISC_R_SUCCESS;
3606
3607         failure:
3608         if (addtuple != NULL)
3609                 dns_difftuple_free(&addtuple);
3610         if (deltuple != NULL)
3611                 dns_difftuple_free(&deltuple);
3612         return (result);
3613 }
3614
3615 static isc_result_t
3616 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3617               dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3618               dns_rdata_t *rdata)
3619 {
3620         dns_difftuple_t *tuple = NULL;
3621         isc_result_t result;
3622         result = dns_difftuple_create(diff->mctx, op,
3623                                       name, ttl, rdata, &tuple);
3624         if (result != ISC_R_SUCCESS)
3625                 return (result);
3626         return (do_one_tuple(&tuple, db, ver, diff));
3627 }
3628
3629 static isc_boolean_t
3630 ksk_sanity(dns_db_t *db, dns_dbversion_t *ver) {
3631         isc_boolean_t ret = ISC_FALSE;
3632         isc_boolean_t have_ksk = ISC_FALSE, have_nonksk = ISC_FALSE;
3633         isc_result_t result;
3634         dns_dbnode_t *node = NULL;
3635         dns_rdataset_t rdataset;
3636         dns_rdata_t rdata = DNS_RDATA_INIT;
3637         dns_rdata_dnskey_t dnskey;
3638
3639         dns_rdataset_init(&rdataset);
3640         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
3641         CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey, 0, 0,
3642                                    &rdataset, NULL));
3643         CHECK(dns_rdataset_first(&rdataset));
3644         while (result == ISC_R_SUCCESS && (!have_ksk || !have_nonksk)) {
3645                 dns_rdataset_current(&rdataset, &rdata);
3646                 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3647                 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
3648                                  == DNS_KEYOWNER_ZONE) {
3649                         if ((dnskey.flags & DNS_KEYFLAG_KSK) != 0)
3650                                 have_ksk = ISC_TRUE;
3651                         else
3652                                 have_nonksk = ISC_TRUE;
3653                 }
3654                 dns_rdata_reset(&rdata);
3655                 result = dns_rdataset_next(&rdataset);
3656         }
3657         if (have_ksk && have_nonksk)
3658                 ret = ISC_TRUE;
3659  failure:
3660         if (dns_rdataset_isassociated(&rdataset))
3661                 dns_rdataset_disassociate(&rdataset);
3662         if (node != NULL)
3663                 dns_db_detachnode(db, &node);
3664         return (ret);
3665 }
3666
3667 static isc_result_t
3668 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3669                isc_mem_t *mctx, unsigned int maxkeys,
3670                dst_key_t **keys, unsigned int *nkeys)
3671 {
3672         isc_result_t result;
3673         dns_dbnode_t *node = NULL;
3674         const char *directory = dns_zone_getkeydirectory(zone);
3675
3676         CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
3677         result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
3678                                           directory, mctx, maxkeys, keys,
3679                                           nkeys);
3680         if (result == ISC_R_NOTFOUND)
3681                 result = ISC_R_SUCCESS;
3682  failure:
3683         if (node != NULL)
3684                 dns_db_detachnode(db, &node);
3685         return (result);
3686 }
3687
3688 static isc_result_t
3689 offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
3690         dns_ttl_t ttl, dns_rdata_t *rdata)
3691 {
3692         isc_result_t result;
3693
3694         if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
3695                 return (ISC_R_SUCCESS);
3696         result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
3697                                name, ttl, rdata);
3698         if (result != ISC_R_SUCCESS)
3699                 return (result);
3700         rdata->flags |= DNS_RDATA_OFFLINE;
3701         result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
3702                                name, ttl, rdata);
3703         return (result);
3704 }
3705
3706 static void
3707 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
3708 {
3709         unsigned int delta;
3710
3711         zone->key_expiry = when;
3712         if (when <= now) {
3713                 dns_zone_log(zone, ISC_LOG_ERROR,
3714                              "DNSKEY RRSIG(s) have expired");
3715                 isc_time_settoepoch(&zone->keywarntime);
3716         } else if (when < now + 7 * 24 * 3600) {
3717                 dns_zone_log(zone, ISC_LOG_WARNING,
3718                              "DNSKEY RRSIG(s) will expire at %u",
3719                              when);     /* XXXMPA convert to date. */
3720                 delta = when - now;
3721                 delta--;                /* loop prevention */
3722                 delta /= 24 * 3600;     /* to whole days */
3723                 delta *= 24 * 3600;     /* to seconds */
3724                 isc_time_set(&zone->keywarntime, when - delta, 0);
3725         }  else {
3726                 dns_zone_log(zone, ISC_LOG_NOTICE, /* XXMPA ISC_LOG_DEBUG(1) */
3727                              "setting keywarntime to %u - 7 days",
3728                              when);     /* XXXMPA convert to date. */
3729                 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
3730         }
3731 }
3732
3733 /*
3734  * Delete expired RRsigs and any RRsigs we are about to re-sign.
3735  * See also update.c:del_keysigs().
3736  */
3737 static isc_result_t
3738 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
3739          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
3740          unsigned int nkeys, isc_stdtime_t now)
3741 {
3742         isc_result_t result;
3743         dns_dbnode_t *node = NULL;
3744         dns_rdataset_t rdataset;
3745         dns_rdata_t rdata = DNS_RDATA_INIT;
3746         unsigned int i;
3747         dns_rdata_rrsig_t rrsig;
3748         isc_boolean_t found;
3749         isc_int64_t warn = 0, maybe = 0;
3750
3751         dns_rdataset_init(&rdataset);
3752
3753         if (type == dns_rdatatype_nsec3)
3754                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
3755         else
3756                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
3757         if (result == ISC_R_NOTFOUND)
3758                 return (ISC_R_SUCCESS);
3759         if (result != ISC_R_SUCCESS)
3760                 goto failure;
3761         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
3762                                      (isc_stdtime_t) 0, &rdataset, NULL);
3763         dns_db_detachnode(db, &node);
3764
3765         if (result == ISC_R_NOTFOUND)
3766                 return (ISC_R_SUCCESS);
3767         if (result != ISC_R_SUCCESS)
3768                 goto failure;
3769
3770         for (result = dns_rdataset_first(&rdataset);
3771              result == ISC_R_SUCCESS;
3772              result = dns_rdataset_next(&rdataset)) {
3773                 dns_rdataset_current(&rdataset, &rdata);
3774                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
3775                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3776
3777                 if (type != dns_rdatatype_dnskey) {
3778                         result = update_one_rr(db, ver, diff,
3779                                                DNS_DIFFOP_DELRESIGN, name,
3780                                                rdataset.ttl, &rdata);
3781                         dns_rdata_reset(&rdata);
3782                         if (result != ISC_R_SUCCESS)
3783                                 break;
3784                         continue;
3785                 }
3786
3787                 /*
3788                  * RRSIG(DNSKEY) requires special processing.
3789                  */
3790                 found = ISC_FALSE;
3791                 for (i = 0; i < nkeys; i++) {
3792                         if (rrsig.algorithm == dst_key_alg(keys[i]) &&
3793                             rrsig.keyid == dst_key_id(keys[i])) {
3794                                 found = ISC_TRUE;
3795                                 /*
3796                                  * Mark offline RRSIG(DNSKEY).
3797                                  * We want the earliest offline expire time
3798                                  * iff there is a new offline signature.
3799                                  */
3800                                 if (!dst_key_isprivate(keys[i])) {
3801                                         isc_int64_t timeexpire =
3802                                            dns_time64_from32(rrsig.timeexpire);
3803                                         if (warn != 0 && warn > timeexpire)
3804                                                 warn = timeexpire;
3805                                         if (rdata.flags & DNS_RDATA_OFFLINE) {
3806                                                 if (maybe == 0 ||
3807                                                     maybe > timeexpire)
3808                                                         maybe = timeexpire;
3809                                                 break;
3810                                         }
3811                                         if (warn == 0)
3812                                                 warn = maybe;
3813                                         if (warn == 0 || warn > timeexpire)
3814                                                 warn = timeexpire;
3815                                         result = offline(db, ver, diff, name,
3816                                                          rdataset.ttl, &rdata);
3817                                         break;
3818                                 }
3819                                 result = update_one_rr(db, ver, diff,
3820                                                        DNS_DIFFOP_DELRESIGN,
3821                                                        name, rdataset.ttl,
3822                                                        &rdata);
3823                                 break;
3824                         }
3825                 }
3826                 /*
3827                  * If there is not a matching DNSKEY then
3828                  * delete the RRSIG.
3829                  */
3830                 if (!found)
3831                         result = update_one_rr(db, ver, diff,
3832                                                DNS_DIFFOP_DELRESIGN, name,
3833                                                rdataset.ttl, &rdata);
3834                 dns_rdata_reset(&rdata);
3835                 if (result != ISC_R_SUCCESS)
3836                         break;
3837         }
3838         dns_rdataset_disassociate(&rdataset);
3839         if (result == ISC_R_NOMORE)
3840                 result = ISC_R_SUCCESS;
3841         if (warn > 0) {
3842 #if defined(STDTIME_ON_32BITS)
3843                 isc_stdtime_t stdwarn = (isc_stdtime_t)warn;
3844                 if (warn == stdwarn)
3845 #endif
3846                         set_key_expiry_warning(zone, (isc_stdtime_t)warn, now);
3847 #if defined(STDTIME_ON_32BITS)
3848                 else
3849                         dns_zone_log(zone, ISC_LOG_ERROR,
3850                                      "key expiry warning time out of range");
3851 #endif
3852         }
3853  failure:
3854         if (node != NULL)
3855                 dns_db_detachnode(db, &node);
3856         return (result);
3857 }
3858
3859 static isc_result_t
3860 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
3861          dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
3862          unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
3863          isc_stdtime_t expire, isc_boolean_t check_ksk)
3864 {
3865         isc_result_t result;
3866         dns_dbnode_t *node = NULL;
3867         dns_rdataset_t rdataset;
3868         dns_rdata_t sig_rdata = DNS_RDATA_INIT;
3869         unsigned char data[1024]; /* XXX */
3870         isc_buffer_t buffer;
3871         unsigned int i;
3872
3873         dns_rdataset_init(&rdataset);
3874         isc_buffer_init(&buffer, data, sizeof(data));
3875
3876         if (type == dns_rdatatype_nsec3)
3877                 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
3878         else
3879                 result = dns_db_findnode(db, name, ISC_FALSE, &node);
3880         if (result == ISC_R_NOTFOUND)
3881                 return (ISC_R_SUCCESS);
3882         if (result != ISC_R_SUCCESS)
3883                 goto failure;
3884         result = dns_db_findrdataset(db, node, ver, type, 0,
3885                                      (isc_stdtime_t) 0, &rdataset, NULL);
3886         dns_db_detachnode(db, &node);
3887         if (result == ISC_R_NOTFOUND)
3888                 return (ISC_R_SUCCESS);
3889         if (result != ISC_R_SUCCESS)
3890                 goto failure;
3891
3892         for (i = 0; i < nkeys; i++) {
3893                 if (check_ksk && type != dns_rdatatype_dnskey &&
3894                     (dst_key_flags(keys[i]) & DNS_KEYFLAG_KSK) != 0)
3895                         continue;
3896                 if (!dst_key_isprivate(keys[i]))
3897                         continue;
3898                 /* Calculate the signature, creating a RRSIG RDATA. */
3899                 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
3900                                       &inception, &expire,
3901                                       mctx, &buffer, &sig_rdata));
3902                 /* Update the database and journal with the RRSIG. */
3903                 /* XXX inefficient - will cause dataset merging */
3904                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
3905                                     name, rdataset.ttl, &sig_rdata));
3906                 dns_rdata_reset(&sig_rdata);
3907                 isc_buffer_init(&buffer, data, sizeof(data));
3908         }
3909
3910  failure:
3911         if (dns_rdataset_isassociated(&rdataset))
3912                 dns_rdataset_disassociate(&rdataset);
3913         if (node != NULL)
3914                 dns_db_detachnode(db, &node);
3915         return (result);
3916 }
3917
3918 static void
3919 zone_resigninc(dns_zone_t *zone) {
3920         const char *journalfile;
3921         dns_db_t *db = NULL;
3922         dns_dbversion_t *version = NULL;
3923         dns_diff_t sig_diff;
3924         dns_fixedname_t fixed;
3925         dns_name_t *name;
3926         dns_rdataset_t rdataset;
3927         dns_rdatatype_t covers;
3928         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
3929         isc_boolean_t check_ksk;
3930         isc_result_t result;
3931         isc_stdtime_t now, inception, soaexpire, expire, stop;
3932         isc_uint32_t jitter;
3933         unsigned int i;
3934         unsigned int nkeys = 0;
3935         unsigned int resign;
3936
3937         dns_rdataset_init(&rdataset);
3938         dns_fixedname_init(&fixed);
3939         dns_diff_init(zone->mctx, &sig_diff);
3940         sig_diff.resign = zone->sigresigninginterval;
3941
3942         /*
3943          * Updates are disabled.  Pause for 5 minutes.
3944          */
3945         if (zone->update_disabled) {
3946                 result = ISC_R_FAILURE;
3947                 goto failure;
3948         }
3949
3950         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3951         dns_db_attach(zone->db, &db);
3952         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3953
3954         result = dns_db_newversion(db, &version);
3955         if (result != ISC_R_SUCCESS) {
3956                 dns_zone_log(zone, ISC_LOG_ERROR,
3957                              "zone_resigninc:dns_db_newversion -> %s",
3958                              dns_result_totext(result));
3959                 goto failure;
3960         }
3961
3962         result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
3963                                 zone_keys, &nkeys);
3964         if (result != ISC_R_SUCCESS) {
3965                 dns_zone_log(zone, ISC_LOG_ERROR,
3966                              "zone_resigninc:find_zone_keys -> %s",
3967                              dns_result_totext(result));
3968                 goto failure;
3969         }
3970
3971         isc_stdtime_get(&now);
3972         inception = now - 3600; /* Allow for clock skew. */
3973         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
3974         /*
3975          * Spread out signatures over time if they happen to be
3976          * clumped.  We don't do this for each add_sigs() call as
3977          * we still want some clustering to occur.
3978          */
3979         isc_random_get(&jitter);
3980         expire = soaexpire - jitter % 3600;
3981         stop = now + 5;
3982
3983         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
3984         if (check_ksk)
3985                 check_ksk = ksk_sanity(db, version);
3986
3987         name = dns_fixedname_name(&fixed);
3988         result = dns_db_getsigningtime(db, &rdataset, name);
3989         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
3990                 dns_zone_log(zone, ISC_LOG_ERROR,
3991                              "zone_resigninc:dns_db_getsigningtime -> %s",
3992                              dns_result_totext(result));
3993         }
3994
3995         i = 0;
3996         while (result == ISC_R_SUCCESS) {
3997                 resign = rdataset.resign;
3998                 covers = rdataset.covers;
3999                 /*
4000                  * Stop if we hit the SOA as that means we have walked the
4001                  * entire zone.  The SOA record should always be the most
4002                  * recent signature.
4003                  */
4004                 /* XXXMPA increase number of RRsets signed pre call */
4005                 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
4006                     resign > stop) {
4007                         /*
4008                          * Ensure that we don't loop resigning the SOA.
4009                          */
4010                         if (covers == dns_rdatatype_soa)
4011                                 dns_db_resigned(db, &rdataset, version);
4012                         dns_rdataset_disassociate(&rdataset);
4013                         break;
4014                 }
4015
4016                 dns_db_resigned(db, &rdataset, version);
4017                 dns_rdataset_disassociate(&rdataset);
4018
4019                 result = del_sigs(zone, db, version, name, covers, &sig_diff,
4020                                   zone_keys, nkeys, now);
4021                 if (result != ISC_R_SUCCESS) {
4022                         dns_zone_log(zone, ISC_LOG_ERROR,
4023                                      "zone_resigninc:del_sigs -> %s",
4024                                      dns_result_totext(result));
4025                         break;
4026                 }
4027                 result = add_sigs(db, version, name, covers, &sig_diff,
4028                                   zone_keys, nkeys, zone->mctx, inception,
4029                                   expire, check_ksk);
4030                 if (result != ISC_R_SUCCESS) {
4031                         dns_zone_log(zone, ISC_LOG_ERROR,
4032                                      "zone_resigninc:add_sigs -> %s",
4033                                      dns_result_totext(result));
4034                         break;
4035                 }
4036                 result  = dns_db_getsigningtime(db, &rdataset,
4037                                                 dns_fixedname_name(&fixed));
4038                 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
4039                         result = ISC_R_SUCCESS;
4040                         break;
4041                 }
4042                 if (result != ISC_R_SUCCESS)
4043                         dns_zone_log(zone, ISC_LOG_ERROR,
4044                              "zone_resigninc:dns_db_getsigningtime -> %s",
4045                                      dns_result_totext(result));
4046         }
4047
4048         if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
4049                 goto failure;
4050
4051         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
4052                           &sig_diff, zone_keys, nkeys, now);
4053         if (result != ISC_R_SUCCESS) {
4054                 dns_zone_log(zone, ISC_LOG_ERROR,
4055                              "zone_resigninc:del_sigs -> %s",
4056                              dns_result_totext(result));
4057                 goto failure;
4058         }
4059
4060         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
4061         if (result != ISC_R_SUCCESS) {
4062                 dns_zone_log(zone, ISC_LOG_ERROR,
4063                              "zone_resigninc:increment_soa_serial -> %s",
4064                              dns_result_totext(result));
4065                 goto failure;
4066         }
4067
4068         /*
4069          * Generate maximum life time signatures so that the above loop
4070          * termination is sensible.
4071          */
4072         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
4073                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
4074                           soaexpire, check_ksk);
4075         if (result != ISC_R_SUCCESS) {
4076                 dns_zone_log(zone, ISC_LOG_ERROR,
4077                              "zone_resigninc:add_sigs -> %s",
4078                              dns_result_totext(result));
4079                 goto failure;
4080         }
4081
4082         journalfile = dns_zone_getjournal(zone);
4083         if (journalfile != NULL) {
4084                 dns_journal_t *journal = NULL;
4085                 result = dns_journal_open(zone->mctx, journalfile,
4086                                           ISC_TRUE, &journal);
4087                 if (result != ISC_R_SUCCESS) {
4088                         dns_zone_log(zone, ISC_LOG_ERROR,
4089                                      "zone_resigninc:dns_journal_open -> %s",
4090                                      dns_result_totext(result));
4091                         goto failure;
4092                 }
4093
4094                 result = dns_journal_write_transaction(journal, &sig_diff);
4095                 dns_journal_destroy(&journal);
4096                 if (result != ISC_R_SUCCESS) {
4097                         dns_zone_log(zone, ISC_LOG_ERROR,
4098                          "zone_resigninc:dns_journal_write_transaction -> %s",
4099                                      dns_result_totext(result));
4100                         goto failure;
4101                 }
4102         }
4103
4104         /*
4105          * Everything has succeeded. Commit the changes.
4106          */
4107         dns_db_closeversion(db, &version, ISC_TRUE);
4108
4109  failure:
4110         dns_diff_clear(&sig_diff);
4111         for (i = 0; i < nkeys; i++)
4112                 dst_key_free(&zone_keys[i]);
4113         if (version != NULL) {
4114                 dns_db_closeversion(zone->db, &version, ISC_FALSE);
4115                 dns_db_detach(&db);
4116         } else if (db != NULL)
4117                 dns_db_detach(&db);
4118         if (result == ISC_R_SUCCESS) {
4119                 set_resigntime(zone);
4120                 LOCK_ZONE(zone);
4121                 zone_needdump(zone, DNS_DUMP_DELAY);
4122                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
4123                 UNLOCK_ZONE(zone);
4124         } else {
4125                 /*
4126                  * Something failed.  Retry in 5 minutes.
4127                  */
4128                 isc_interval_t ival;
4129                 isc_interval_set(&ival, 300, 0);
4130                 isc_time_nowplusinterval(&zone->resigntime, &ival);
4131         }
4132 }
4133
4134 static isc_result_t
4135 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
4136             dns_name_t *newname, isc_boolean_t bottom)
4137 {
4138         isc_result_t result;
4139         dns_dbiterator_t *dbit = NULL;
4140         dns_rdatasetiter_t *rdsit = NULL;
4141         dns_dbnode_t *node = NULL;
4142
4143         CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
4144         CHECK(dns_dbiterator_seek(dbit, oldname));
4145         do {
4146                 result = dns_dbiterator_next(dbit);
4147                 if (result == ISC_R_NOMORE)
4148                         CHECK(dns_dbiterator_first(dbit));
4149                 CHECK(dns_dbiterator_current(dbit, &node, newname));
4150                 if (bottom && dns_name_issubdomain(newname, oldname) &&
4151                     !dns_name_equal(newname, oldname)) {
4152                         dns_db_detachnode(db, &node);
4153                         continue;
4154                 }
4155                 /*
4156                  * Is this node empty?
4157                  */
4158                 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
4159                 result = dns_rdatasetiter_first(rdsit);
4160                 dns_db_detachnode(db, &node);
4161                 dns_rdatasetiter_destroy(&rdsit);
4162                 if (result != ISC_R_NOMORE)
4163                         break;
4164         } while (1);
4165  failure:
4166         if (node != NULL)
4167                 dns_db_detachnode(db, &node);
4168         if (dbit != NULL)
4169                 dns_dbiterator_destroy(&dbit);
4170         return (result);
4171 }
4172
4173 static void
4174 set_bit(unsigned char *array, unsigned int index) {
4175         unsigned int shift, mask;
4176
4177         shift = 7 - (index % 8);
4178         mask = 1 << shift;
4179
4180         array[index / 8] |= mask;
4181 }
4182
4183 static isc_boolean_t
4184 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4185                 dns_rdatatype_t type, dst_key_t *key)
4186 {
4187         isc_result_t result;
4188         dns_rdataset_t rdataset;
4189         dns_rdata_t rdata = DNS_RDATA_INIT;
4190         dns_rdata_rrsig_t rrsig;
4191
4192         dns_rdataset_init(&rdataset);
4193         result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
4194                                      type, 0, &rdataset, NULL);
4195         if (result != ISC_R_SUCCESS)
4196                 return (ISC_FALSE);
4197         for (result = dns_rdataset_first(&rdataset);
4198              result == ISC_R_SUCCESS;
4199              result = dns_rdataset_next(&rdataset)) {
4200                 dns_rdataset_current(&rdataset, &rdata);
4201                 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4202                 INSIST(result == ISC_R_SUCCESS);
4203                 if (rrsig.algorithm == dst_key_alg(key) &&
4204                     rrsig.keyid == dst_key_id(key)) {
4205                         dns_rdataset_disassociate(&rdataset);
4206                         return (ISC_TRUE);
4207                 }
4208                 dns_rdata_reset(&rdata);
4209         }
4210         dns_rdataset_disassociate(&rdataset);
4211         return (ISC_FALSE);
4212 }
4213
4214 static isc_result_t
4215 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
4216          dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
4217          dns_diff_t *diff)
4218 {
4219         dns_fixedname_t fixed;
4220         dns_name_t *next;
4221         dns_rdata_t rdata = DNS_RDATA_INIT;
4222         isc_result_t result;
4223         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
4224
4225         dns_fixedname_init(&fixed);
4226         next = dns_fixedname_name(&fixed);
4227
4228         CHECK(next_active(db, version, name, next, bottom));
4229         CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
4230                                   &rdata));
4231         if (dns_name_equal(dns_db_origin(db), name)) {
4232                 /*
4233                  * Set the OPT bit to indicate that this is a
4234                  * partially secure zone.
4235                  */
4236                 isc_region_t region;
4237
4238                 dns_rdata_toregion(&rdata, &region);
4239                 dns_name_fromregion(next, &region);
4240                 isc_region_consume(&region, next->length);
4241                 INSIST(region.length > (2 + dns_rdatatype_opt / 8) &&
4242                        region.base[0] == 0 &&
4243                        region.base[1] > dns_rdatatype_opt / 8);
4244                 set_bit(region.base + 2, dns_rdatatype_opt);
4245         }
4246         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
4247                             &rdata));
4248  failure:
4249         return (result);
4250 }
4251
4252 static isc_result_t
4253 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
4254             dns_dbversion_t *version, isc_boolean_t build_nsec3,
4255             isc_boolean_t build_nsec, dst_key_t *key,
4256             isc_stdtime_t inception, isc_stdtime_t expire,
4257             unsigned int minimum, isc_boolean_t is_ksk,
4258             isc_boolean_t *delegation, dns_diff_t *diff,
4259             isc_int32_t *signatures, isc_mem_t *mctx)
4260 {
4261         isc_result_t result;
4262         dns_rdatasetiter_t *iterator = NULL;
4263         dns_rdataset_t rdataset;
4264         dns_rdata_t rdata = DNS_RDATA_INIT;
4265         isc_buffer_t buffer;
4266         unsigned char data[1024];
4267         isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
4268                       seen_nsec3, seen_ds;
4269         isc_boolean_t bottom;
4270
4271         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
4272         if (result != ISC_R_SUCCESS) {
4273                 if (result == ISC_R_NOTFOUND)
4274                         result = ISC_R_SUCCESS;
4275                 return (result);
4276         }
4277         dns_rdataset_init(&rdataset);
4278         isc_buffer_init(&buffer, data, sizeof(data));
4279         seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
4280         seen_nsec3 = seen_ds = ISC_FALSE;
4281         for (result = dns_rdatasetiter_first(iterator);
4282              result == ISC_R_SUCCESS;
4283              result = dns_rdatasetiter_next(iterator)) {
4284                 dns_rdatasetiter_current(iterator, &rdataset);
4285                 if (rdataset.type == dns_rdatatype_soa)
4286                         seen_soa = ISC_TRUE;
4287                 else if (rdataset.type == dns_rdatatype_ns)
4288                         seen_ns = ISC_TRUE;
4289                 else if (rdataset.type == dns_rdatatype_ds)
4290                         seen_ds = ISC_TRUE;
4291                 else if (rdataset.type == dns_rdatatype_dname)
4292                         seen_dname = ISC_TRUE;
4293                 else if (rdataset.type == dns_rdatatype_nsec)
4294                         seen_nsec = ISC_TRUE;
4295                 else if (rdataset.type == dns_rdatatype_nsec3)
4296                         seen_nsec3 = ISC_TRUE;
4297                 seen_rr = ISC_TRUE;
4298                 dns_rdataset_disassociate(&rdataset);
4299         }
4300         if (result != ISC_R_NOMORE)
4301                 goto failure;
4302         if (seen_ns && !seen_soa)
4303                 *delegation = ISC_TRUE;
4304         /*
4305          * Going from insecure to NSEC3.
4306          * Don't generate NSEC3 records for NSEC3 records.
4307          */
4308         if (build_nsec3 && !seen_nsec3 && seen_rr) {
4309                 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
4310                 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
4311                                           unsecure, diff));
4312                 (*signatures)--;
4313         }
4314         /*
4315          * Going from insecure to NSEC.
4316          * Don't generate NSEC records for NSEC3 records.
4317          */
4318         if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
4319                 /* Build and add NSEC. */
4320                 bottom = (seen_ns && !seen_soa) || seen_dname;
4321                 CHECK(add_nsec(db, version, name, node, minimum, bottom, diff));
4322                 /* Count a NSEC generation as a signature generation. */
4323                 (*signatures)--;
4324         }
4325         result = dns_rdatasetiter_first(iterator);
4326         while (result == ISC_R_SUCCESS) {
4327                 dns_rdatasetiter_current(iterator, &rdataset);
4328                 if (rdataset.type == dns_rdatatype_soa ||
4329                     rdataset.type == dns_rdatatype_rrsig)
4330                         goto next_rdataset;
4331                 if (is_ksk && rdataset.type != dns_rdatatype_dnskey)
4332                         goto next_rdataset;
4333                 if (*delegation &&
4334                     rdataset.type != dns_rdatatype_ds &&
4335                     rdataset.type != dns_rdatatype_nsec)
4336                         goto next_rdataset;
4337                 if (signed_with_key(db, node, version, rdataset.type, key))
4338                         goto next_rdataset;
4339                 /* Calculate the signature, creating a RRSIG RDATA. */
4340                 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
4341                                       &expire, mctx, &buffer, &rdata));
4342                 /* Update the database and journal with the RRSIG. */
4343                 /* XXX inefficient - will cause dataset merging */
4344                 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
4345                                     name, rdataset.ttl, &rdata));
4346                 dns_rdata_reset(&rdata);
4347                 (*signatures)--;
4348  next_rdataset:
4349                 dns_rdataset_disassociate(&rdataset);
4350                 result = dns_rdatasetiter_next(iterator);
4351         }
4352         if (result == ISC_R_NOMORE)
4353                 result = ISC_R_SUCCESS;
4354         if (seen_dname)
4355                 *delegation = ISC_TRUE;
4356 failure:
4357         if (dns_rdataset_isassociated(&rdataset))
4358                 dns_rdataset_disassociate(&rdataset);
4359         if (iterator != NULL)
4360                 dns_rdatasetiter_destroy(&iterator);
4361         return (result);
4362 }
4363
4364 static isc_result_t
4365 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
4366              dns_ttl_t minimum, isc_boolean_t *secureupdated, dns_diff_t *diff)
4367 {
4368         isc_result_t result;
4369         dns_rdata_t rdata = DNS_RDATA_INIT;
4370         unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
4371         dns_rdataset_t rdataset;
4372         dns_rdata_nsec_t nsec;
4373         dns_dbnode_t *node = NULL;
4374
4375         /*
4376          * Check to see if the OPT bit has already been cleared.
4377          */
4378         CHECK(dns_db_getoriginnode(db, &node));
4379         dns_rdataset_init(&rdataset);
4380         CHECK(dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
4381                                   dns_rdatatype_none, 0, &rdataset, NULL));
4382         CHECK(dns_rdataset_first(&rdataset));
4383         dns_rdataset_current(&rdataset, &rdata);
4384
4385         /*
4386          * Find the NEXT name for building the new record.
4387          */
4388         CHECK(dns_rdata_tostruct(&rdata, &nsec, NULL));
4389
4390         /*
4391          * Delete the old NSEC record.
4392          */
4393         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_DEL, name, minimum,
4394                             &rdata));
4395         dns_rdata_reset(&rdata);
4396
4397         /*
4398          * Add the new NSEC record.
4399          */
4400         CHECK(dns_nsec_buildrdata(db, version, node, &nsec.next, nsecbuffer,
4401                                   &rdata));
4402         CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, minimum,
4403                             &rdata));
4404         dns_rdata_reset(&rdata);
4405
4406         if (secureupdated != NULL)
4407                 *secureupdated = ISC_TRUE;
4408
4409  failure:
4410         if (node != NULL)
4411                 dns_db_detachnode(db, &node);
4412         if (dns_rdataset_isassociated(&rdataset))
4413                 dns_rdataset_disassociate(&rdataset);
4414         return (result);
4415 }
4416
4417 static isc_result_t
4418 updatesignwithkey(dns_signing_t *signing, dns_dbversion_t *version,
4419                   dns_name_t *name, dns_rdatatype_t privatetype,
4420                   dns_diff_t *diff)
4421 {
4422         isc_result_t result;
4423         dns_dbnode_t *node = NULL;
4424         dns_rdataset_t rdataset;
4425         dns_rdata_t rdata = DNS_RDATA_INIT;
4426         unsigned char data[5];
4427         isc_boolean_t seen_done = ISC_FALSE;
4428
4429         dns_rdataset_init(&rdataset);
4430         result = dns_db_getoriginnode(signing->db, &node);
4431         if (result != ISC_R_SUCCESS)
4432                 goto failure;
4433
4434         result = dns_db_findrdataset(signing->db, node, version, privatetype,
4435                                      dns_rdatatype_none, 0, &rdataset, NULL);
4436         if (result == ISC_R_NOTFOUND) {
4437                 result = ISC_R_SUCCESS;
4438                 goto failure;
4439         }
4440         if (result != ISC_R_SUCCESS)
4441                 goto failure;
4442         for (result = dns_rdataset_first(&rdataset);
4443              result == ISC_R_SUCCESS;
4444              result = dns_rdataset_next(&rdataset)) {
4445                 dns_rdataset_current(&rdataset, &rdata);
4446                 if (rdata.length != 5 ||
4447                     rdata.data[0] != signing->algorithm ||
4448                     rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
4449                     rdata.data[2] != (signing->keyid & 0xff)) {
4450                         dns_rdata_reset(&rdata);
4451                         continue;
4452                 }
4453                 if (!signing->delete && rdata.data[4] != 0)
4454                         seen_done = ISC_TRUE;
4455                 else
4456                         CHECK(update_one_rr(signing->db, version, diff,
4457                                             DNS_DIFFOP_DEL, name,
4458                                             rdataset.ttl, &rdata));
4459                 dns_rdata_reset(&rdata);
4460         }
4461         if (result == ISC_R_NOMORE)
4462                 result = ISC_R_SUCCESS;
4463         if (!signing->delete && !seen_done) {
4464
4465                 data[0] = signing->algorithm;
4466                 data[1] = (signing->keyid >> 8) & 0xff;
4467                 data[2] = signing->keyid & 0xff;
4468                 data[3] = 0;
4469                 data[4] = 1;
4470                 rdata.length = sizeof(data);
4471                 rdata.data = data;
4472                 rdata.type = privatetype;
4473                 rdata.rdclass = dns_db_class(signing->db);
4474                 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
4475                                     name, rdataset.ttl, &rdata));
4476         }
4477  failure:
4478         if (dns_rdataset_isassociated(&rdataset))
4479                 dns_rdataset_disassociate(&rdataset);
4480         if (node != NULL)
4481                 dns_db_detachnode(signing->db, &node);
4482         return (result);
4483 }
4484
4485 static isc_result_t
4486 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
4487                  isc_boolean_t active, dns_diff_t *diff)
4488 {
4489         dns_dbnode_t *node = NULL;
4490         dns_name_t *name = dns_db_origin(db);
4491         dns_rdata_t rdata = DNS_RDATA_INIT;
4492         dns_rdataset_t rdataset;
4493         dns_rdata_nsec3param_t nsec3param;
4494         isc_result_t result;
4495         isc_buffer_t buffer;
4496         unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
4497         dns_ttl_t ttl = 0;
4498
4499         dns_rdataset_init(&rdataset);
4500
4501         result = dns_db_getoriginnode(db, &node);
4502         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4503         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
4504                                      0, 0, &rdataset, NULL);
4505         if (result == ISC_R_NOTFOUND)
4506                 goto add;
4507         if (result != ISC_R_SUCCESS)
4508                 goto failure;
4509
4510         /*
4511          * Preserve the existing ttl.
4512          */
4513         ttl = rdataset.ttl;
4514
4515         /*
4516          * Delete all NSEC3PARAM records which match that in nsec3chain.
4517          */
4518         for (result = dns_rdataset_first(&rdataset);
4519              result == ISC_R_SUCCESS;
4520              result = dns_rdataset_next(&rdataset)) {
4521
4522                 dns_rdataset_current(&rdataset, &rdata);
4523                 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
4524
4525                 if (nsec3param.hash != chain->nsec3param.hash ||
4526                     (active && nsec3param.flags != 0) ||
4527                     nsec3param.iterations != chain->nsec3param.iterations ||
4528                     nsec3param.salt_length != chain->nsec3param.salt_length ||
4529                     memcmp(nsec3param.salt, chain->nsec3param.salt,
4530                            nsec3param.salt_length)) {
4531                         dns_rdata_reset(&rdata);
4532                         continue;
4533                 }
4534
4535                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
4536                                     name, rdataset.ttl, &rdata));
4537                 dns_rdata_reset(&rdata);
4538         }
4539         if (result != ISC_R_NOMORE)
4540                 goto failure;
4541
4542   add:
4543         if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
4544                 result = ISC_R_SUCCESS;
4545                 goto failure;
4546         }
4547
4548         /*
4549          * Add a NSEC3PARAM record which matches that in nsec3chain but
4550          * with all flags bits cleared.
4551          *
4552          * Note: we do not clear chain->nsec3param.flags as this change
4553          * may be reversed.
4554          */
4555         isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
4556         CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
4557                                    dns_rdatatype_nsec3param,
4558                                    &chain->nsec3param, &buffer));
4559         rdata.data[1] = 0;      /* Clear flag bits. */
4560         CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
4561
4562   failure:
4563         dns_db_detachnode(db, &node);
4564         if (dns_rdataset_isassociated(&rdataset))
4565                 dns_rdataset_disassociate(&rdataset);
4566         return (result);
4567 }
4568
4569 static isc_result_t
4570 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
4571             dns_name_t *name, dns_diff_t *diff)
4572 {
4573         dns_rdataset_t rdataset;
4574         isc_result_t result;
4575
4576         dns_rdataset_init(&rdataset);
4577
4578         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
4579                                      0, 0, &rdataset, NULL);
4580         if (result == ISC_R_NOTFOUND)
4581                 return (ISC_R_SUCCESS);
4582         if (result != ISC_R_SUCCESS)
4583                 return (result);
4584         for (result = dns_rdataset_first(&rdataset);
4585              result == ISC_R_SUCCESS;
4586              result = dns_rdataset_next(&rdataset)) {
4587                 dns_rdata_t rdata = DNS_RDATA_INIT;
4588
4589                 dns_rdataset_current(&rdataset, &rdata);
4590                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
4591                                     rdataset.ttl, &rdata));
4592         }
4593         if (result == ISC_R_NOMORE)
4594                 result = ISC_R_SUCCESS;
4595  failure:
4596         dns_rdataset_disassociate(&rdataset);
4597         return (result);
4598 }
4599
4600 static isc_result_t
4601 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
4602                     dns_name_t *name, const dns_rdata_nsec3param_t *param,
4603                     dns_diff_t *diff)
4604 {
4605         dns_rdataset_t rdataset;
4606         dns_rdata_nsec3_t nsec3;
4607         isc_result_t result;
4608
4609         dns_rdataset_init(&rdataset);
4610         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
4611                                      0, 0, &rdataset, NULL);
4612         if (result == ISC_R_NOTFOUND)
4613                 return (ISC_R_SUCCESS);
4614         if (result != ISC_R_SUCCESS)
4615                 return (result);
4616
4617         for (result = dns_rdataset_first(&rdataset);
4618              result == ISC_R_SUCCESS;
4619              result = dns_rdataset_next(&rdataset)) {
4620                 dns_rdata_t rdata = DNS_RDATA_INIT;
4621
4622                 dns_rdataset_current(&rdataset, &rdata);
4623                 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
4624                 if (nsec3.hash != param->hash ||
4625                     nsec3.iterations != param->iterations ||
4626                     nsec3.salt_length != param->salt_length ||
4627                     memcmp(nsec3.salt, param->salt, nsec3.salt_length))
4628                         continue;
4629                 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
4630                                     rdataset.ttl, &rdata));
4631         }
4632         if (result == ISC_R_NOMORE)
4633                 result = ISC_R_SUCCESS;
4634  failure:
4635         dns_rdataset_disassociate(&rdataset);
4636         return (result);
4637 }
4638
4639 static isc_result_t
4640 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
4641                 const dns_rdata_nsec3param_t *param,
4642                 isc_boolean_t *answer, isc_boolean_t *updatensec)
4643 {
4644         dns_dbnode_t *node = NULL;
4645         dns_rdata_t rdata = DNS_RDATA_INIT;
4646         dns_rdata_nsec3param_t myparam;
4647         dns_rdataset_t rdataset;
4648         isc_result_t result;
4649
4650         *answer = ISC_FALSE;
4651
4652         result = dns_db_getoriginnode(db, &node);
4653         RUNTIME_CHECK(result == ISC_R_SUCCESS);
4654
4655         dns_rdataset_init(&rdataset);
4656         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
4657                                      0, 0, &rdataset, NULL);
4658         if (result == ISC_R_NOTFOUND)
4659                 goto check_nsec3param;
4660
4661         if (result != ISC_R_SUCCESS)
4662                 goto failure;
4663
4664         CHECK(dns_rdataset_first(&rdataset));
4665         dns_rdataset_current(&rdataset, &rdata);
4666
4667         if (!dns_nsec_typepresent(&rdata, dns_rdatatype_opt)) {
4668                 /*
4669                  * We have a complete NSEC chain.  Signal to update
4670                  * the apex NSEC record.
4671                  */
4672                 *updatensec = ISC_TRUE;
4673                 goto failure;
4674         }
4675         dns_rdataset_disassociate(&rdataset);
4676         dns_rdata_reset(&rdata);
4677
4678  check_nsec3param:
4679         result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
4680                                      0, 0, &rdataset, NULL);
4681         if (result == ISC_R_NOTFOUND) {
4682                 *answer = ISC_TRUE;
4683                 dns_db_detachnode(db, &node);
4684                 return (ISC_R_SUCCESS);
4685         }
4686         if (result != ISC_R_SUCCESS) {
4687                 dns_db_detachnode(db, &node);
4688                 return (result);
4689         }
4690
4691         for (result = dns_rdataset_first(&rdataset);
4692              result == ISC_R_SUCCESS;
4693              result = dns_rdataset_next(&rdataset)) {
4694                 dns_rdataset_current(&rdataset, &rdata);
4695                 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
4696                 dns_rdata_reset(&rdata);
4697                 /*
4698                  * Ignore any NSEC3PARAM removals.
4699                  */
4700                 if (NSEC3REMOVE(myparam.flags))
4701                         continue;
4702                 /*
4703                  * Ignore the chain that we are in the process of deleting.
4704                  */
4705                 if (myparam.hash == param->hash &&
4706                     myparam.iterations == param->iterations &&
4707                     myparam.salt_length == param->salt_length &&
4708                     !memcmp(myparam.salt, param->salt, myparam.salt_length))
4709                         continue;
4710                 /*
4711                  * Found an active NSEC3 chain.
4712                  */
4713                 break;
4714         }
4715         if (result == ISC_R_NOMORE) {
4716                 *answer = ISC_TRUE;
4717                 result = ISC_R_SUCCESS;
4718         }
4719
4720  failure:
4721         if (dns_rdataset_isassociated(&rdataset))
4722                 dns_rdataset_disassociate(&rdataset);
4723         dns_db_detachnode(db, &node);
4724         return (result);
4725 }
4726
4727 /*
4728  * Incrementally build and sign a new NSEC3 chain using the parameters
4729  * requested.
4730  */
4731 static void
4732 zone_nsec3chain(dns_zone_t *zone) {
4733         const char *journalfile;
4734         dns_db_t *db = NULL;
4735         dns_dbnode_t *node = NULL;
4736         dns_dbversion_t *version = NULL;
4737         dns_diff_t sig_diff;
4738         dns_diff_t nsec_diff;
4739         dns_diff_t nsec3_diff;
4740         dns_diff_t param_diff;
4741         dns_fixedname_t fixed;
4742         dns_fixedname_t nextfixed;
4743         dns_name_t *name, *nextname;
4744         dns_rdataset_t rdataset;
4745         dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
4746         dns_nsec3chainlist_t cleanup;
4747         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
4748         isc_int32_t signatures;
4749         isc_boolean_t check_ksk;
4750         isc_boolean_t delegation;
4751         isc_boolean_t first;
4752         isc_result_t result;
4753         isc_stdtime_t now, inception, soaexpire, expire;
4754         isc_uint32_t jitter;
4755         unsigned int i;
4756         unsigned int nkeys = 0;
4757         isc_uint32_t nodes;
4758         isc_boolean_t unsecure = ISC_FALSE;
4759         isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
4760         isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
4761         dns_rdatasetiter_t *iterator = NULL;
4762         dns_difftuple_t *tuple;
4763         isc_boolean_t buildnsecchain;
4764         isc_boolean_t updatensec = ISC_FALSE;
4765
4766         dns_rdataset_init(&rdataset);
4767         dns_fixedname_init(&fixed);
4768         name = dns_fixedname_name(&fixed);
4769         dns_fixedname_init(&nextfixed);
4770         nextname = dns_fixedname_name(&nextfixed);
4771         dns_diff_init(zone->mctx, &param_diff);
4772         dns_diff_init(zone->mctx, &nsec3_diff);
4773         dns_diff_init(zone->mctx, &nsec_diff);
4774         dns_diff_init(zone->mctx, &sig_diff);
4775         sig_diff.resign = zone->sigresigninginterval;
4776         ISC_LIST_INIT(cleanup);
4777
4778         /*
4779          * Updates are disabled.  Pause for 5 minutes.
4780          */
4781         if (zone->update_disabled) {
4782                 result = ISC_R_FAILURE;
4783                 goto failure;
4784         }
4785
4786         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4787         dns_db_attach(zone->db, &db);
4788         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4789
4790         result = dns_db_newversion(db, &version);
4791         if (result != ISC_R_SUCCESS) {
4792                 dns_zone_log(zone, ISC_LOG_ERROR,
4793                              "zone_nsec3chain:dns_db_newversion -> %s",
4794                              dns_result_totext(result));
4795                 goto failure;
4796         }
4797
4798         result = find_zone_keys(zone, db, version, zone->mctx,
4799                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
4800         if (result != ISC_R_SUCCESS) {
4801                 dns_zone_log(zone, ISC_LOG_ERROR,
4802                              "zone_nsec3chain:find_zone_keys -> %s",
4803                              dns_result_totext(result));
4804                 goto failure;
4805         }
4806
4807         isc_stdtime_get(&now);
4808         inception = now - 3600; /* Allow for clock skew. */
4809         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
4810
4811         /*
4812          * Spread out signatures over time if they happen to be
4813          * clumped.  We don't do this for each add_sigs() call as
4814          * we still want some clustering to occur.
4815          */
4816         isc_random_get(&jitter);
4817         expire = soaexpire - jitter % 3600;
4818
4819         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
4820         if (check_ksk)
4821                 check_ksk = ksk_sanity(db, version);
4822
4823         /*
4824          * We keep pulling nodes off each iterator in turn until
4825          * we have no more nodes to pull off or we reach the limits
4826          * for this quantum.
4827          */
4828         nodes = zone->nodes;
4829         signatures = zone->signatures;
4830         LOCK_ZONE(zone);
4831         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
4832         UNLOCK_ZONE(zone);
4833         first = ISC_TRUE;
4834
4835         if (nsec3chain != NULL)
4836                 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
4837         /*
4838          * Generate new NSEC3 chains first.
4839          */
4840         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
4841                 LOCK_ZONE(zone);
4842                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
4843
4844                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4845                 if (nsec3chain->done || nsec3chain->db != zone->db) {
4846                         ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
4847                         ISC_LIST_APPEND(cleanup, nsec3chain, link);
4848                 }
4849                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4850                 UNLOCK_ZONE(zone);
4851                 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
4852                         goto next_addchain;
4853
4854                 /*
4855                  * Possible future db.
4856                  */
4857                 if (nsec3chain->db != db) {
4858                         goto next_addchain;
4859                 }
4860
4861                 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
4862                         goto next_addchain;
4863
4864                 delegation = ISC_FALSE;
4865                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
4866
4867                 if (nsec3chain->delete_nsec) {
4868                         dns_dbiterator_pause(nsec3chain->dbiterator);
4869                         CHECK(delete_nsec(db, version, node, name, &nsec_diff));
4870                         goto next_addnode;
4871                 }
4872
4873                 /*
4874                  * On the first pass we need to check if the current node
4875                  * has not been obscured.
4876                  */
4877                 unsecure = ISC_FALSE;
4878                 if (first) {
4879                         dns_fixedname_t ffound;
4880                         dns_name_t *found;
4881                         dns_fixedname_init(&ffound);
4882                         found = dns_fixedname_name(&ffound);
4883                         result = dns_db_find(db, name, version,
4884                                              dns_rdatatype_soa,
4885                                              DNS_DBFIND_NOWILD, 0, NULL, found,
4886                                              NULL, NULL);
4887                         if ((result == DNS_R_DELEGATION ||
4888                             result == DNS_R_DNAME) &&
4889                             !dns_name_equal(name, found)) {
4890                                 /*
4891                                  * Remember the obscuring name so that
4892                                  * we skip all obscured names.
4893                                  */
4894                                 dns_name_copy(found, name, NULL);
4895                                 delegation = ISC_TRUE;
4896                                 goto next_addnode;
4897                         }
4898                 }
4899
4900                 /*
4901                  * Check to see if this is a bottom of zone node.
4902                  */
4903                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
4904                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
4905                         goto next_addnode;
4906                 if (result != ISC_R_SUCCESS)
4907                         goto failure;
4908
4909                 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
4910                         ISC_FALSE;
4911                 for (result = dns_rdatasetiter_first(iterator);
4912                      result == ISC_R_SUCCESS;
4913                      result = dns_rdatasetiter_next(iterator)) {
4914                         dns_rdatasetiter_current(iterator, &rdataset);
4915                         INSIST(rdataset.type != dns_rdatatype_nsec3);
4916                         if (rdataset.type == dns_rdatatype_soa)
4917                                 seen_soa = ISC_TRUE;
4918                         else if (rdataset.type == dns_rdatatype_ns)
4919                                 seen_ns = ISC_TRUE;
4920                         else if (rdataset.type == dns_rdatatype_dname)
4921                                 seen_dname = ISC_TRUE;
4922                         else if (rdataset.type == dns_rdatatype_ds)
4923                                 seen_ds = ISC_TRUE;
4924                         else if (rdataset.type == dns_rdatatype_nsec)
4925                                 seen_nsec = ISC_TRUE;
4926                         dns_rdataset_disassociate(&rdataset);
4927                 }
4928                 dns_rdatasetiter_destroy(&iterator);
4929                 /*
4930                  * Is there a NSEC chain than needs to be cleaned up?
4931                  */
4932                 if (seen_nsec)
4933                         nsec3chain->seen_nsec = ISC_TRUE;
4934                 if (seen_ns && !seen_soa && !seen_ds)
4935                         unsecure = ISC_TRUE;
4936                 if ((seen_ns && !seen_soa) || seen_dname)
4937                         delegation = ISC_TRUE;
4938
4939                 /*
4940                  * Process one node.
4941                  */
4942                 dns_dbiterator_pause(nsec3chain->dbiterator);
4943                 CHECK(dns_nsec3_addnsec3(db, version, name,
4944                                          &nsec3chain->nsec3param,
4945                                          zone->minimum, unsecure, &nsec3_diff));
4946                 /*
4947                  * Treat each call to dns_nsec3_addnsec3() as if it's cost is
4948                  * two signatures.  Additionally there will, in general, be
4949                  * two signature generated below.
4950                  *
4951                  * If we are only changing the optout flag the cost is half
4952                  * that of the cost of generating a completely new chain.
4953                  */
4954                 signatures -= 4;
4955
4956                 /*
4957                  * Go onto next node.
4958                  */
4959  next_addnode:
4960                 first = ISC_FALSE;
4961                 dns_db_detachnode(db, &node);
4962                 do {
4963                         result = dns_dbiterator_next(nsec3chain->dbiterator);
4964
4965                         if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
4966                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
4967                                                        ISC_FALSE, &param_diff));
4968                                 LOCK_ZONE(zone);
4969                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
4970                                                 link);
4971                                 UNLOCK_ZONE(zone);
4972                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
4973                                 goto next_addchain;
4974                         }
4975                         if (result == ISC_R_NOMORE) {
4976                                 dns_dbiterator_pause(nsec3chain->dbiterator);
4977                                 if (nsec3chain->seen_nsec) {
4978                                         CHECK(fixup_nsec3param(db, version,
4979                                                                nsec3chain,
4980                                                                ISC_TRUE,
4981                                                                &param_diff));
4982                                         nsec3chain->delete_nsec = ISC_TRUE;
4983                                         goto same_addchain;
4984                                 }
4985                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
4986                                                        ISC_FALSE, &param_diff));
4987                                 LOCK_ZONE(zone);
4988                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
4989                                                 link);
4990                                 UNLOCK_ZONE(zone);
4991                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
4992                                 goto next_addchain;
4993                         } else if (result != ISC_R_SUCCESS) {
4994                                 dns_zone_log(zone, ISC_LOG_ERROR,
4995                                              "zone_nsec3chain:"
4996                                              "dns_dbiterator_next -> %s",
4997                                              dns_result_totext(result));
4998                                 goto failure;
4999                         } else if (delegation) {
5000                                 dns_dbiterator_current(nsec3chain->dbiterator,
5001                                                        &node, nextname);
5002                                 dns_db_detachnode(db, &node);
5003                                 if (!dns_name_issubdomain(nextname, name))
5004                                         break;
5005                         } else
5006                                 break;
5007                 } while (1);
5008                 continue;
5009
5010  same_addchain:
5011                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
5012                 first = ISC_TRUE;
5013                 continue;
5014
5015  next_addchain:
5016                 dns_dbiterator_pause(nsec3chain->dbiterator);
5017                 nsec3chain = nextnsec3chain;
5018                 first = ISC_TRUE;
5019                 if (nsec3chain != NULL)
5020                         nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
5021         }
5022
5023         /*
5024          * Process removals.
5025          */
5026         LOCK_ZONE(zone);
5027         nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5028         UNLOCK_ZONE(zone);
5029         first = ISC_TRUE;
5030         buildnsecchain = ISC_FALSE;
5031         while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
5032                 LOCK_ZONE(zone);
5033                 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
5034                 UNLOCK_ZONE(zone);
5035
5036                 if (nsec3chain->db != db)
5037                         goto next_removechain;
5038
5039                 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
5040                         goto next_removechain;
5041
5042                 /*
5043                  * Work out if we need to build a NSEC chain as a consequence
5044                  * of removing this NSEC3 chain.
5045                  */
5046                 if (first && !updatensec &&
5047                     (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
5048                         CHECK(need_nsec_chain(db, version,
5049                                               &nsec3chain->nsec3param,
5050                                               &buildnsecchain, &updatensec));
5051
5052                 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
5053                 delegation = ISC_FALSE;
5054
5055                 if (!buildnsecchain) {
5056                         /*
5057                          * Delete the NSECPARAM record that matches this chain.
5058                          */
5059                         if (first)
5060                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
5061                                                        ISC_TRUE, &param_diff));
5062
5063                         /*
5064                          *  Delete the NSEC3 records.
5065                          */
5066                         CHECK(deletematchingnsec3(db, version, node, name,
5067                                                   &nsec3chain->nsec3param,
5068                                                   &nsec3_diff));
5069                         goto next_removenode;
5070                 }
5071
5072                 if (first) {
5073                         dns_fixedname_t ffound;
5074                         dns_name_t *found;
5075                         dns_fixedname_init(&ffound);
5076                         found = dns_fixedname_name(&ffound);
5077                         result = dns_db_find(db, name, version,
5078                                              dns_rdatatype_soa,
5079                                              DNS_DBFIND_NOWILD, 0, NULL, found,
5080                                              NULL, NULL);
5081                         if ((result == DNS_R_DELEGATION ||
5082                              result == DNS_R_DNAME) &&
5083                             !dns_name_equal(name, found)) {
5084                                 /*
5085                                  * Remember the obscuring name so that
5086                                  * we skip all obscured names.
5087                                  */
5088                                 dns_name_copy(found, name, NULL);
5089                                 delegation = ISC_TRUE;
5090                                 goto next_removenode;
5091                         }
5092                 }
5093
5094                 /*
5095                  * Check to see if this is a bottom of zone node.
5096                  */
5097                 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5098                 if (result == ISC_R_NOTFOUND)   /* Empty node? */
5099                         goto next_removenode;
5100                 if (result != ISC_R_SUCCESS)
5101                         goto failure;
5102
5103                 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
5104                         seen_rr = ISC_FALSE;
5105                 for (result = dns_rdatasetiter_first(iterator);
5106                      result == ISC_R_SUCCESS;
5107                      result = dns_rdatasetiter_next(iterator)) {
5108                         dns_rdatasetiter_current(iterator, &rdataset);
5109                         if (rdataset.type == dns_rdatatype_soa)
5110                                 seen_soa = ISC_TRUE;
5111                         else if (rdataset.type == dns_rdatatype_ns)
5112                                 seen_ns = ISC_TRUE;
5113                         else if (rdataset.type == dns_rdatatype_dname)
5114                                 seen_dname = ISC_TRUE;
5115                         else if (rdataset.type == dns_rdatatype_nsec)
5116                                 seen_nsec = ISC_TRUE;
5117                         else if (rdataset.type == dns_rdatatype_nsec3)
5118                                 seen_nsec3 = ISC_TRUE;
5119                         seen_rr = ISC_TRUE;
5120                         dns_rdataset_disassociate(&rdataset);
5121                 }
5122                 dns_rdatasetiter_destroy(&iterator);
5123
5124                 if (!seen_rr || seen_nsec3 || seen_nsec)
5125                         goto next_removenode;
5126                 if ((seen_ns && !seen_soa) || seen_dname)
5127                         delegation = ISC_TRUE;
5128
5129                 CHECK(add_nsec(db, version, name, node, zone->minimum,
5130                                delegation, &nsec_diff));
5131
5132  next_removenode:
5133                 first = ISC_FALSE;
5134                 dns_db_detachnode(db, &node);
5135                 do {
5136                         result = dns_dbiterator_next(nsec3chain->dbiterator);
5137                         if (result == ISC_R_NOMORE && buildnsecchain) {
5138                                 /*
5139                                  * The NSEC chain should now be built.
5140                                  * We can now remove the NSEC3 chain.
5141                                  */
5142                                 updatensec = ISC_TRUE;
5143                                 goto same_removechain;
5144                         }
5145                         if (result == ISC_R_NOMORE) {
5146                                 LOCK_ZONE(zone);
5147                                 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
5148                                                 link);
5149                                 UNLOCK_ZONE(zone);
5150                                 ISC_LIST_APPEND(cleanup, nsec3chain, link);
5151                                 dns_dbiterator_pause(nsec3chain->dbiterator);
5152                                 CHECK(fixup_nsec3param(db, version, nsec3chain,
5153                                                        ISC_FALSE, &param_diff));
5154                                 goto next_removechain;
5155                         } else if (result != ISC_R_SUCCESS) {
5156                                 dns_zone_log(zone, ISC_LOG_ERROR,
5157                                              "zone_nsec3chain:"
5158                                              "dns_dbiterator_next -> %s",
5159                                              dns_result_totext(result));
5160                                 goto failure;
5161                         } else if (delegation) {
5162                                 dns_dbiterator_current(nsec3chain->dbiterator,
5163                                                        &node, nextname);
5164                                 dns_db_detachnode(db, &node);
5165                                 if (!dns_name_issubdomain(nextname, name))
5166                                         break;
5167                         } else
5168                                 break;
5169                 } while (1);
5170                 continue;
5171
5172  same_removechain:
5173                 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
5174                 buildnsecchain = ISC_FALSE;
5175                 first = ISC_TRUE;
5176                 continue;
5177
5178  next_removechain:
5179                 dns_dbiterator_pause(nsec3chain->dbiterator);
5180                 nsec3chain = nextnsec3chain;
5181                 first = ISC_TRUE;
5182         }
5183
5184         /*
5185          * Add / update signatures for the NSEC3 records.
5186          */
5187         for (tuple = ISC_LIST_HEAD(nsec3_diff.tuples);
5188              tuple != NULL;
5189              tuple = ISC_LIST_HEAD(nsec3_diff.tuples)) {
5190                 /*
5191                  * We have changed the NSEC3 RRset above so we need to update
5192                  * the signatures.
5193                  */
5194                 result = del_sigs(zone, db, version, &tuple->name,
5195                                   dns_rdatatype_nsec3, &sig_diff,
5196                                   zone_keys, nkeys, now);
5197                 if (result != ISC_R_SUCCESS) {
5198                         dns_zone_log(zone, ISC_LOG_ERROR,
5199                                      "zone_nsec3chain:del_sigs -> %s",
5200                                      dns_result_totext(result));
5201                         goto failure;
5202                 }
5203                 result = add_sigs(db, version, &tuple->name,
5204                                   dns_rdatatype_nsec3, &sig_diff, zone_keys,
5205                                   nkeys, zone->mctx, inception, expire,
5206                                   check_ksk);
5207                 if (result != ISC_R_SUCCESS) {
5208                         dns_zone_log(zone, ISC_LOG_ERROR,
5209                                      "zone_nsec3chain:add_sigs -> %s",
5210                                      dns_result_totext(result));
5211                         goto failure;
5212                 }
5213
5214                 do {
5215                         dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
5216                         while (next != NULL &&
5217                                !dns_name_equal(&tuple->name, &next->name))
5218                                 next = ISC_LIST_NEXT(next, link);
5219                         ISC_LIST_UNLINK(nsec3_diff.tuples, tuple, link);
5220                         dns_diff_appendminimal(&sig_diff, &tuple);
5221                         INSIST(tuple == NULL);
5222                         tuple = next;
5223                 } while (tuple != NULL);
5224         }
5225
5226         for (tuple = ISC_LIST_HEAD(param_diff.tuples);
5227              tuple != NULL;
5228              tuple = ISC_LIST_HEAD(param_diff.tuples)) {
5229                 /*
5230                  * We have changed the NSEC3PARAM RRset above so we need to
5231                  * update the signatures.
5232                  */
5233                 result = del_sigs(zone, db, version, &tuple->name,
5234                                   dns_rdatatype_nsec3param, &sig_diff,
5235                                   zone_keys, nkeys, now);
5236                 if (result != ISC_R_SUCCESS) {
5237                         dns_zone_log(zone, ISC_LOG_ERROR,
5238                                      "zone_nsec3chain:del_sigs -> %s",
5239                                      dns_result_totext(result));
5240                         goto failure;
5241                 }
5242                 result = add_sigs(db, version, &tuple->name,
5243                                   dns_rdatatype_nsec3param, &sig_diff,
5244                                   zone_keys, nkeys, zone->mctx, inception,
5245                                   expire, check_ksk);
5246                 if (result != ISC_R_SUCCESS) {
5247                         dns_zone_log(zone, ISC_LOG_ERROR,
5248                                      "zone_nsec3chain:add_sigs -> %s",
5249                                      dns_result_totext(result));
5250                         goto failure;
5251                 }
5252                 ISC_LIST_UNLINK(param_diff.tuples, tuple, link);
5253                 dns_diff_appendminimal(&sig_diff, &tuple);
5254                 INSIST(tuple == NULL);
5255         }
5256
5257         if (updatensec)
5258                 CHECK(updatesecure(db, version, &zone->origin, zone->minimum,
5259                                    NULL, &nsec_diff));
5260
5261         for (tuple = ISC_LIST_HEAD(nsec_diff.tuples);
5262              tuple != NULL;
5263              tuple = ISC_LIST_HEAD(nsec_diff.tuples)) {
5264                 result = del_sigs(zone, db, version, &tuple->name,
5265                                   dns_rdatatype_nsec, &sig_diff,
5266                                   zone_keys, nkeys, now);
5267                 if (result != ISC_R_SUCCESS) {
5268                         dns_zone_log(zone, ISC_LOG_ERROR,
5269                                      "zone_nsec3chain:del_sigs -> %s",
5270                                      dns_result_totext(result));
5271                         goto failure;
5272                 }
5273                 result = add_sigs(db, version, &tuple->name,
5274                                   dns_rdatatype_nsec, &sig_diff,
5275                                   zone_keys, nkeys, zone->mctx, inception,
5276                                   expire, check_ksk);
5277                 if (result != ISC_R_SUCCESS) {
5278                         dns_zone_log(zone, ISC_LOG_ERROR,
5279                                      "zone_nsec3chain:add_sigs -> %s",
5280                                      dns_result_totext(result));
5281                         goto failure;
5282                 }
5283                 ISC_LIST_UNLINK(nsec_diff.tuples, tuple, link);
5284                 dns_diff_appendminimal(&sig_diff, &tuple);
5285                 INSIST(tuple == NULL);
5286         }
5287
5288         /*
5289          * If we made no effective changes to the zone then we can just
5290          * cleanup otherwise we need to increment the serial.
5291          */
5292         if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
5293                 goto done;
5294
5295         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5296                           &sig_diff, zone_keys, nkeys, now);
5297         if (result != ISC_R_SUCCESS) {
5298                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5299                              "del_sigs -> %s", dns_result_totext(result));
5300                 goto failure;
5301         }
5302
5303         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
5304         if (result != ISC_R_SUCCESS) {
5305                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5306                              "increment_soa_serial -> %s",
5307                              dns_result_totext(result));
5308                 goto failure;
5309         }
5310
5311         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5312                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5313                           soaexpire, check_ksk);
5314         if (result != ISC_R_SUCCESS) {
5315                 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5316                              "add_sigs -> %s", dns_result_totext(result));
5317                 goto failure;
5318         }
5319
5320         journalfile = dns_zone_getjournal(zone);
5321         if (journalfile != NULL) {
5322                 dns_journal_t *journal = NULL;
5323                 result = dns_journal_open(zone->mctx, journalfile,
5324                                           ISC_TRUE, &journal);
5325                 if (result != ISC_R_SUCCESS) {
5326                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5327                                      "dns_journal_open -> %s",
5328                                      dns_result_totext(result));
5329                         goto failure;
5330                 }
5331
5332                 result = dns_journal_write_transaction(journal, &sig_diff);
5333                 dns_journal_destroy(&journal);
5334                 if (result != ISC_R_SUCCESS) {
5335                         dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5336                                      "dns_journal_write_transaction -> %s",
5337                                      dns_result_totext(result));
5338                         goto failure;
5339                 }
5340         }
5341
5342         LOCK_ZONE(zone);
5343         zone_needdump(zone, DNS_DUMP_DELAY);
5344         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
5345         UNLOCK_ZONE(zone);
5346
5347  done:
5348         /*
5349          * Pause all iterators so that dns_db_closeversion() can succeed.
5350          */
5351         LOCK_ZONE(zone);
5352         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5353              nsec3chain != NULL;
5354              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
5355                 dns_dbiterator_pause(nsec3chain->dbiterator);
5356         UNLOCK_ZONE(zone);
5357
5358         /*
5359          * Everything has succeeded. Commit the changes.
5360          */
5361         dns_db_closeversion(db, &version, ISC_TRUE);
5362
5363         /*
5364          * Everything succeeded so we can clean these up now.
5365          */
5366         nsec3chain = ISC_LIST_HEAD(cleanup);
5367         while (nsec3chain != NULL) {
5368                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
5369                 dns_db_detach(&nsec3chain->db);
5370                 dns_dbiterator_destroy(&nsec3chain->dbiterator);
5371                 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
5372                 nsec3chain = ISC_LIST_HEAD(cleanup);
5373         }
5374
5375         set_resigntime(zone);
5376
5377  failure:
5378         /*
5379          * On error roll back the current nsec3chain.
5380          */
5381         if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
5382                 if (nsec3chain->done) {
5383                         dns_db_detach(&nsec3chain->db);
5384                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
5385                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
5386                 } else {
5387                         result = dns_dbiterator_first(nsec3chain->dbiterator);
5388                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5389                         dns_dbiterator_pause(nsec3chain->dbiterator);
5390                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
5391                 }
5392         }
5393
5394         /*
5395          * Rollback the cleanup list.
5396          */
5397         nsec3chain = ISC_LIST_TAIL(cleanup);
5398         while (nsec3chain != NULL) {
5399                 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
5400                 if (nsec3chain->done) {
5401                         dns_db_detach(&nsec3chain->db);
5402                         dns_dbiterator_destroy(&nsec3chain->dbiterator);
5403                         isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
5404                 } else {
5405                         LOCK_ZONE(zone);
5406                         ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
5407                         UNLOCK_ZONE(zone);
5408                         result = dns_dbiterator_first(nsec3chain->dbiterator);
5409                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5410                         dns_dbiterator_pause(nsec3chain->dbiterator);
5411                         nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
5412                 }
5413                 nsec3chain = ISC_LIST_TAIL(cleanup);
5414         }
5415
5416         LOCK_ZONE(zone);
5417         for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5418              nsec3chain != NULL;
5419              nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
5420                 dns_dbiterator_pause(nsec3chain->dbiterator);
5421         UNLOCK_ZONE(zone);
5422
5423         dns_diff_clear(&param_diff);
5424         dns_diff_clear(&nsec3_diff);
5425         dns_diff_clear(&nsec_diff);
5426         dns_diff_clear(&sig_diff);
5427
5428         if (iterator != NULL)
5429                 dns_rdatasetiter_destroy(&iterator);
5430
5431         for (i = 0; i < nkeys; i++)
5432                 dst_key_free(&zone_keys[i]);
5433
5434         if (version != NULL) {
5435                 dns_db_closeversion(db, &version, ISC_FALSE);
5436                 dns_db_detach(&db);
5437         } else if (db != NULL)
5438                 dns_db_detach(&db);
5439
5440         LOCK_ZONE(zone);
5441         if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
5442                 isc_interval_t i;
5443                 if (zone->update_disabled || result != ISC_R_SUCCESS)
5444                         isc_interval_set(&i, 60, 0);            /* 1 minute */
5445                 else
5446                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
5447                 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
5448         } else
5449                 isc_time_settoepoch(&zone->nsec3chaintime);
5450         UNLOCK_ZONE(zone);
5451 }
5452
5453 static isc_result_t
5454 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5455         dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
5456         isc_uint16_t keyid, dns_diff_t *diff)
5457 {
5458         dns_rdata_rrsig_t rrsig;
5459         dns_rdataset_t rdataset;
5460         dns_rdatasetiter_t *iterator = NULL;
5461         isc_result_t result;
5462
5463         result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5464         if (result != ISC_R_SUCCESS) {
5465                 if (result == ISC_R_NOTFOUND)
5466                         result = ISC_R_SUCCESS;
5467                 return (result);
5468         }
5469
5470         dns_rdataset_init(&rdataset);
5471         for (result = dns_rdatasetiter_first(iterator);
5472              result == ISC_R_SUCCESS;
5473              result = dns_rdatasetiter_next(iterator)) {
5474                 dns_rdatasetiter_current(iterator, &rdataset);
5475                 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
5476                         for (result = dns_rdataset_first(&rdataset);
5477                              result == ISC_R_SUCCESS;
5478                              result = dns_rdataset_next(&rdataset)) {
5479                                 dns_rdata_t rdata = DNS_RDATA_INIT;
5480                                 dns_rdataset_current(&rdataset, &rdata);
5481                                 CHECK(update_one_rr(db, version, diff,
5482                                                     DNS_DIFFOP_DEL, name,
5483                                                     rdataset.ttl, &rdata));
5484                         }
5485                         if (result != ISC_R_NOMORE)
5486                                 goto failure;
5487                         dns_rdataset_disassociate(&rdataset);
5488                         continue;
5489                 }
5490                 if (rdataset.type != dns_rdatatype_rrsig) {
5491                         dns_rdataset_disassociate(&rdataset);
5492                         continue;
5493                 }
5494                 for (result = dns_rdataset_first(&rdataset);
5495                      result == ISC_R_SUCCESS;
5496                      result = dns_rdataset_next(&rdataset)) {
5497                         dns_rdata_t rdata = DNS_RDATA_INIT;
5498                         dns_rdataset_current(&rdataset, &rdata);
5499                         CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
5500                         if (rrsig.algorithm != algorithm ||
5501                             rrsig.keyid != keyid)
5502                                 continue;
5503                         CHECK(update_one_rr(db, version, diff,
5504                                             DNS_DIFFOP_DELRESIGN, name,
5505                                             rdataset.ttl, &rdata));
5506                 }
5507                 dns_rdataset_disassociate(&rdataset);
5508                 if (result != ISC_R_NOMORE)
5509                         break;
5510         }
5511         if (result == ISC_R_NOMORE)
5512                 result = ISC_R_SUCCESS;
5513  failure:
5514         if (dns_rdataset_isassociated(&rdataset))
5515                 dns_rdataset_disassociate(&rdataset);
5516         dns_rdatasetiter_destroy(&iterator);
5517         return (result);
5518 }
5519
5520 /*
5521  * Incrementally sign the zone using the keys requested.
5522  * Builds the NSEC chain if required.
5523  */
5524 static void
5525 zone_sign(dns_zone_t *zone) {
5526         const char *journalfile;
5527         dns_db_t *db = NULL;
5528         dns_dbnode_t *node = NULL;
5529         dns_dbversion_t *version = NULL;
5530         dns_diff_t sig_diff;
5531         dns_fixedname_t fixed;
5532         dns_fixedname_t nextfixed;
5533         dns_name_t *name, *nextname;
5534         dns_rdataset_t rdataset;
5535         dns_signing_t *signing, *nextsigning;
5536         dns_signinglist_t cleanup;
5537         dst_key_t *zone_keys[DNS_MAXZONEKEYS];
5538         isc_int32_t signatures;
5539         isc_boolean_t check_ksk, is_ksk;
5540         isc_boolean_t commit = ISC_FALSE;
5541         isc_boolean_t delegation;
5542         isc_boolean_t finishedakey = ISC_FALSE;
5543         isc_boolean_t secureupdated = ISC_FALSE;
5544         isc_boolean_t build_nsec3 = ISC_FALSE, build_nsec = ISC_FALSE;
5545         isc_boolean_t first;
5546         isc_result_t result;
5547         isc_stdtime_t now, inception, soaexpire, expire;
5548         isc_uint32_t jitter;
5549         unsigned int i;
5550         unsigned int nkeys = 0;
5551         isc_uint32_t nodes;
5552
5553         dns_rdataset_init(&rdataset);
5554         dns_fixedname_init(&fixed);
5555         name = dns_fixedname_name(&fixed);
5556         dns_fixedname_init(&nextfixed);
5557         nextname = dns_fixedname_name(&nextfixed);
5558         dns_diff_init(zone->mctx, &sig_diff);
5559         sig_diff.resign = zone->sigresigninginterval;
5560         ISC_LIST_INIT(cleanup);
5561
5562         /*
5563          * Updates are disabled.  Pause for 5 minutes.
5564          */
5565         if (zone->update_disabled) {
5566                 result = ISC_R_FAILURE;
5567                 goto failure;
5568         }
5569
5570         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5571         dns_db_attach(zone->db, &db);
5572         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5573
5574         result = dns_db_newversion(db, &version);
5575         if (result != ISC_R_SUCCESS) {
5576                 dns_zone_log(zone, ISC_LOG_ERROR,
5577                              "zone_sign:dns_db_newversion -> %s",
5578                              dns_result_totext(result));
5579                 goto failure;
5580         }
5581
5582         result = find_zone_keys(zone, db, version, zone->mctx,
5583                                 DNS_MAXZONEKEYS, zone_keys, &nkeys);
5584         if (result != ISC_R_SUCCESS) {
5585                 dns_zone_log(zone, ISC_LOG_ERROR,
5586                              "zone_sign:find_zone_keys -> %s",
5587                              dns_result_totext(result));
5588                 goto failure;
5589         }
5590
5591         isc_stdtime_get(&now);
5592         inception = now - 3600; /* Allow for clock skew. */
5593         soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5594
5595         /*
5596          * Spread out signatures over time if they happen to be
5597          * clumped.  We don't do this for each add_sigs() call as
5598          * we still want some clustering to occur.
5599          */
5600         isc_random_get(&jitter);
5601         expire = soaexpire - jitter % 3600;
5602
5603         check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5604         if (check_ksk)
5605                 check_ksk = ksk_sanity(db, version);
5606
5607         /*
5608          * We keep pulling nodes off each iterator in turn until
5609          * we have no more nodes to pull off or we reach the limits
5610          * for this quantum.
5611          */
5612         nodes = zone->nodes;
5613         signatures = zone->signatures;
5614         signing = ISC_LIST_HEAD(zone->signing);
5615         first = ISC_TRUE;
5616         /*
5617          * See if we have a NSEC chain.
5618          */
5619         result = dns_db_getoriginnode(db, &node);
5620         RUNTIME_CHECK(result == ISC_R_SUCCESS);
5621         result = dns_db_findrdataset(db, node, version, dns_rdatatype_nsec,
5622                                      dns_rdatatype_none, 0, &rdataset, NULL);
5623         dns_db_detachnode(db, &node);
5624         if (result == ISC_R_SUCCESS) {
5625                 build_nsec = ISC_TRUE;
5626                 dns_rdataset_disassociate(&rdataset);
5627         } else if (result != ISC_R_NOTFOUND) {
5628                 goto failure;
5629         } else {
5630                 /*
5631                  * No NSEC chain present.
5632                  * See if we need to build a NSEC3 chain?
5633                  */
5634                 result = dns_nsec3_active(db, version, ISC_TRUE, &build_nsec3);
5635                 if (result == ISC_R_SUCCESS) {
5636                         if (build_nsec3)
5637                                 build_nsec3 = ISC_FALSE;
5638                         else  {
5639                                 result = dns_nsec3_active(db, version,
5640                                                           ISC_FALSE,
5641                                                           &build_nsec3);
5642                                 if (build_nsec3)
5643                                         secureupdated = ISC_TRUE;
5644                                 else
5645                                         build_nsec = ISC_TRUE;
5646                         }
5647                 }
5648         }
5649
5650         while (signing != NULL && nodes-- > 0 && signatures > 0) {
5651                 nextsigning = ISC_LIST_NEXT(signing, link);
5652
5653                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5654                 if (signing->done || signing->db != zone->db) {
5655                         /*
5656                          * The zone has been reloaded.  We will have
5657                          * created new signings as part of the reload
5658                          * process so we can destroy this one.
5659                          */
5660                         ISC_LIST_UNLINK(zone->signing, signing, link);
5661                         ISC_LIST_APPEND(cleanup, signing, link);
5662                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5663                         goto next_signing;
5664                 }
5665                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5666
5667                 if (signing->db != db)
5668                         goto next_signing;
5669
5670                 is_ksk = ISC_FALSE;
5671                 delegation = ISC_FALSE;
5672
5673                 dns_dbiterator_current(signing->dbiterator, &node, name);
5674
5675                 if (signing->delete) {
5676                         dns_dbiterator_pause(signing->dbiterator);
5677                         CHECK(del_sig(db, version, name, node, nkeys,
5678                                       signing->algorithm, signing->keyid,
5679                                       &sig_diff));
5680                         goto next_node;
5681                 }
5682                 /*
5683                  * On the first pass we need to check if the current node
5684                  * has not been obscured.
5685                  */
5686                 if (first) {
5687                         dns_fixedname_t ffound;
5688                         dns_name_t *found;
5689                         dns_fixedname_init(&ffound);
5690                         found = dns_fixedname_name(&ffound);
5691                         result = dns_db_find(db, name, version,
5692                                              dns_rdatatype_soa,
5693                                              DNS_DBFIND_NOWILD, 0, NULL, found,
5694                                              NULL, NULL);
5695                         if ((result == DNS_R_DELEGATION ||
5696                             result == DNS_R_DNAME) &&
5697                             !dns_name_equal(name, found)) {
5698                                 /*
5699                                  * Remember the obscuring name so that
5700                                  * we skip all obscured names.
5701                                  */
5702                                 dns_name_copy(found, name, NULL);
5703                                 delegation = ISC_TRUE;
5704                                 goto next_node;
5705                         }
5706                 }
5707
5708                 /*
5709                  * Process one node.
5710                  */
5711                 dns_dbiterator_pause(signing->dbiterator);
5712                 for (i = 0; i < nkeys; i++) {
5713                         /*
5714                          * Find the key we want to sign with.
5715                          */
5716                         if (dst_key_alg(zone_keys[i]) != signing->algorithm ||
5717                             dst_key_id(zone_keys[i]) != signing->keyid ||
5718                             !dst_key_isprivate(zone_keys[i]))
5719                                 continue;
5720                         /*
5721                          * Do we do KSK processing?
5722                          */
5723                         if (check_ksk &&
5724                             (dst_key_flags(zone_keys[i]) & DNS_KEYFLAG_KSK) != 0)
5725                                 is_ksk = ISC_TRUE;
5726                         CHECK(sign_a_node(db, name, node, version, build_nsec3,
5727                                           build_nsec, zone_keys[i], inception,
5728                                           expire, zone->minimum, is_ksk,
5729                                           &delegation, &sig_diff, &signatures,
5730                                           zone->mctx));
5731                         break;
5732                 }
5733                 /*
5734                  * Go onto next node.
5735                  */
5736  next_node:
5737                 first = ISC_FALSE;
5738                 dns_db_detachnode(db, &node);
5739                 do {
5740                         result = dns_dbiterator_next(signing->dbiterator);
5741                         if (result == ISC_R_NOMORE) {
5742                                 ISC_LIST_UNLINK(zone->signing, signing, link);
5743                                 ISC_LIST_APPEND(cleanup, signing, link);
5744                                 dns_dbiterator_pause(signing->dbiterator);
5745                                 finishedakey = ISC_TRUE;
5746                                 if (!is_ksk && !secureupdated && nkeys != 0 &&
5747                                     build_nsec) {
5748                                         /*
5749                                          * We have finished regenerating the
5750                                          * zone with a zone signing key.
5751                                          * The NSEC chain is now complete and
5752                                          * there is a full set of signatures
5753                                          * for the zone.  We can now clear the
5754                                          * OPT bit from the NSEC record.
5755                                          */
5756                                         result = updatesecure(db, version,
5757                                                               &zone->origin,
5758                                                               zone->minimum,
5759                                                               &secureupdated,
5760                                                               &sig_diff);
5761                                         if (result != ISC_R_SUCCESS) {
5762                                                 dns_zone_log(zone,
5763                                                              ISC_LOG_ERROR,
5764                                                     "updatesecure -> %s",
5765                                                     dns_result_totext(result));
5766                                                 goto failure;
5767                                         }
5768                                 }
5769                                 result = updatesignwithkey(signing, version,
5770                                                            &zone->origin,
5771                                                            zone->privatetype,
5772                                                            &sig_diff);
5773                                 if (result != ISC_R_SUCCESS) {
5774                                         dns_zone_log(zone, ISC_LOG_ERROR,
5775                                                      "updatesignwithkey -> %s",
5776                                                      dns_result_totext(result));
5777                                         goto failure;
5778                                 }
5779                                 goto next_signing;
5780                         } else if (result != ISC_R_SUCCESS) {
5781                                 dns_zone_log(zone, ISC_LOG_ERROR,
5782                                         "zone_sign:dns_dbiterator_next -> %s",
5783                                              dns_result_totext(result));
5784                                 goto failure;
5785                         } else if (delegation) {
5786                                 dns_dbiterator_current(signing->dbiterator,
5787                                                        &node, nextname);
5788                                 dns_db_detachnode(db, &node);
5789                                 if (!dns_name_issubdomain(nextname, name))
5790                                         break;
5791                         } else
5792                                 break;
5793                 } while (1);
5794                 continue;
5795
5796  next_signing:
5797                 dns_dbiterator_pause(signing->dbiterator);
5798                 signing = nextsigning;
5799                 first = ISC_TRUE;
5800         }
5801
5802         if (secureupdated) {
5803                 /*
5804                  * We have changed the NSEC RRset above so we need to update
5805                  * the signatures.
5806                  */
5807                 result = del_sigs(zone, db, version, &zone->origin,
5808                                   dns_rdatatype_nsec, &sig_diff, zone_keys,
5809                                   nkeys, now);
5810                 if (result != ISC_R_SUCCESS) {
5811                         dns_zone_log(zone, ISC_LOG_ERROR,
5812                                      "zone_sign:del_sigs -> %s",
5813                                      dns_result_totext(result));
5814                         goto failure;
5815                 }
5816                 result = add_sigs(db, version, &zone->origin,
5817                                   dns_rdatatype_nsec, &sig_diff, zone_keys,
5818                                   nkeys, zone->mctx, inception, soaexpire,
5819                                   check_ksk);
5820                 if (result != ISC_R_SUCCESS) {
5821                         dns_zone_log(zone, ISC_LOG_ERROR,
5822                                      "zone_sign:add_sigs -> %s",
5823                                      dns_result_totext(result));
5824                         goto failure;
5825                 }
5826         }
5827
5828         if (finishedakey) {
5829                 /*
5830                  * We have changed the RRset above so we need to update
5831                  * the signatures.
5832                  */
5833                 result = del_sigs(zone, db, version, &zone->origin,
5834                                   zone->privatetype, &sig_diff,
5835                                   zone_keys, nkeys, now);
5836                 if (result != ISC_R_SUCCESS) {
5837                         dns_zone_log(zone, ISC_LOG_ERROR,
5838                                      "zone_sign:del_sigs -> %s",
5839                                      dns_result_totext(result));
5840                         goto failure;
5841                 }
5842                 result = add_sigs(db, version, &zone->origin,
5843                                   zone->privatetype, &sig_diff,
5844                                   zone_keys, nkeys, zone->mctx, inception,
5845                                   soaexpire, check_ksk);
5846                 if (result != ISC_R_SUCCESS) {
5847                         dns_zone_log(zone, ISC_LOG_ERROR,
5848                                      "zone_sign:add_sigs -> %s",
5849                                      dns_result_totext(result));
5850                         goto failure;
5851                 }
5852         }
5853
5854         /*
5855          * Have we changed anything?
5856          */
5857         if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
5858                 goto pauseall;
5859
5860         commit = ISC_TRUE;
5861
5862         result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
5863                           &sig_diff, zone_keys, nkeys, now);
5864         if (result != ISC_R_SUCCESS) {
5865                 dns_zone_log(zone, ISC_LOG_ERROR,
5866                              "zone_sign:del_sigs -> %s",
5867                              dns_result_totext(result));
5868                 goto failure;
5869         }
5870
5871         result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
5872         if (result != ISC_R_SUCCESS) {
5873                 dns_zone_log(zone, ISC_LOG_ERROR,
5874                              "zone_sign:increment_soa_serial -> %s",
5875                              dns_result_totext(result));
5876                 goto failure;
5877         }
5878
5879         /*
5880          * Generate maximum life time signatures so that the above loop
5881          * termination is sensible.
5882          */
5883         result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
5884                           &sig_diff, zone_keys, nkeys, zone->mctx, inception,
5885                           soaexpire, check_ksk);
5886         if (result != ISC_R_SUCCESS) {
5887                 dns_zone_log(zone, ISC_LOG_ERROR,
5888                              "zone_sign:add_sigs -> %s",
5889                              dns_result_totext(result));
5890                 goto failure;
5891         }
5892
5893         /*
5894          * Write changes to journal file.
5895          */
5896         journalfile = dns_zone_getjournal(zone);
5897         if (journalfile != NULL) {
5898                 dns_journal_t *journal = NULL;
5899                 result = dns_journal_open(zone->mctx, journalfile,
5900                                           ISC_TRUE, &journal);
5901                 if (result != ISC_R_SUCCESS) {
5902                         dns_zone_log(zone, ISC_LOG_ERROR,
5903                                      "zone_sign:dns_journal_open -> %s",
5904                                      dns_result_totext(result));
5905                         goto failure;
5906                 }
5907
5908                 result = dns_journal_write_transaction(journal, &sig_diff);
5909                 dns_journal_destroy(&journal);
5910                 if (result != ISC_R_SUCCESS) {
5911                         dns_zone_log(zone, ISC_LOG_ERROR,
5912                          "zone_sign:dns_journal_write_transaction -> %s",
5913                                      dns_result_totext(result));
5914                         goto failure;
5915                 }
5916         }
5917
5918  pauseall:
5919         /*
5920          * Pause all iterators so that dns_db_closeversion() can succeed.
5921          */
5922         for (signing = ISC_LIST_HEAD(zone->signing);
5923              signing != NULL;
5924              signing = ISC_LIST_NEXT(signing, link))
5925                 dns_dbiterator_pause(signing->dbiterator);
5926
5927         for (signing = ISC_LIST_HEAD(cleanup);
5928              signing != NULL;
5929              signing = ISC_LIST_NEXT(signing, link))
5930                 dns_dbiterator_pause(signing->dbiterator);
5931
5932         /*
5933          * Everything has succeeded. Commit the changes.
5934          */
5935         dns_db_closeversion(db, &version, commit);
5936
5937         /*
5938          * Everything succeeded so we can clean these up now.
5939          */
5940         signing = ISC_LIST_HEAD(cleanup);
5941         while (signing != NULL) {
5942                 ISC_LIST_UNLINK(cleanup, signing, link);
5943                 dns_db_detach(&signing->db);
5944                 dns_dbiterator_destroy(&signing->dbiterator);
5945                 isc_mem_put(zone->mctx, signing, sizeof *signing);
5946                 signing = ISC_LIST_HEAD(cleanup);
5947         }
5948
5949         set_resigntime(zone);
5950
5951         if (commit) {
5952                 LOCK_ZONE(zone);
5953                 zone_needdump(zone, DNS_DUMP_DELAY);
5954                 UNLOCK_ZONE(zone);
5955         }
5956
5957  failure:
5958         /*
5959          * Rollback the cleanup list.
5960          */
5961         signing = ISC_LIST_HEAD(cleanup);
5962         while (signing != NULL) {
5963                 ISC_LIST_UNLINK(cleanup, signing, link);
5964                 ISC_LIST_APPEND(zone->signing, signing, link);
5965                 dns_dbiterator_first(signing->dbiterator);
5966                 dns_dbiterator_pause(signing->dbiterator);
5967                 signing = ISC_LIST_HEAD(cleanup);
5968         }
5969
5970         for (signing = ISC_LIST_HEAD(zone->signing);
5971              signing != NULL;
5972              signing = ISC_LIST_NEXT(signing, link))
5973                 dns_dbiterator_pause(signing->dbiterator);
5974
5975         dns_diff_clear(&sig_diff);
5976
5977         for (i = 0; i < nkeys; i++)
5978                 dst_key_free(&zone_keys[i]);
5979
5980         if (version != NULL) {
5981                 dns_db_closeversion(db, &version, ISC_FALSE);
5982                 dns_db_detach(&db);
5983         } else if (db != NULL)
5984                 dns_db_detach(&db);
5985
5986         if (ISC_LIST_HEAD(zone->signing) != NULL) {
5987                 isc_interval_t i;
5988                 if (zone->update_disabled || result != ISC_R_SUCCESS)
5989                         isc_interval_set(&i, 60, 0);            /* 1 minute */
5990                 else
5991                         isc_interval_set(&i, 0, 10000000);      /* 10 ms */
5992                 isc_time_nowplusinterval(&zone->signingtime, &i);
5993         } else
5994                 isc_time_settoepoch(&zone->signingtime);
5995 }
5996
5997 static void
5998 zone_maintenance(dns_zone_t *zone) {
5999         const char me[] = "zone_maintenance";
6000         isc_time_t now;
6001         isc_result_t result;
6002         isc_boolean_t dumping;
6003
6004         REQUIRE(DNS_ZONE_VALID(zone));
6005         ENTER;
6006
6007         /*
6008          * Configuring the view of this zone may have
6009          * failed, for example because the config file
6010          * had a syntax error.  In that case, the view
6011          * db or resolver will be NULL, and we had better not try
6012          * to do maintenance on it.
6013          */
6014         if (zone->view == NULL || zone->view->adb == NULL)
6015                 return;
6016
6017         TIME_NOW(&now);
6018
6019         /*
6020          * Expire check.
6021          */
6022         switch (zone->type) {
6023         case dns_zone_slave:
6024         case dns_zone_stub:
6025                 LOCK_ZONE(zone);
6026                 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
6027                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
6028                         zone_expire(zone);
6029                         zone->refreshtime = now;
6030                 }
6031                 UNLOCK_ZONE(zone);
6032                 break;
6033         default:
6034                 break;
6035         }
6036
6037         /*
6038          * Up to date check.
6039          */
6040         switch (zone->type) {
6041         case dns_zone_slave:
6042         case dns_zone_stub:
6043                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
6044                     isc_time_compare(&now, &zone->refreshtime) >= 0)
6045                         dns_zone_refresh(zone);
6046                 break;
6047         default:
6048                 break;
6049         }
6050
6051         /*
6052          * Do we need to consolidate the backing store?
6053          */
6054         switch (zone->type) {
6055         case dns_zone_master:
6056         case dns_zone_slave:
6057         case dns_zone_stub:
6058                 LOCK_ZONE(zone);
6059                 if (zone->masterfile != NULL &&
6060                     isc_time_compare(&now, &zone->dumptime) >= 0 &&
6061                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
6062                     DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
6063                         dumping = was_dumping(zone);
6064                 } else
6065                         dumping = ISC_TRUE;
6066                 UNLOCK_ZONE(zone);
6067                 if (!dumping) {
6068                         result = zone_dump(zone, ISC_TRUE); /* task locked */
6069                         if (result != ISC_R_SUCCESS)
6070                                 dns_zone_log(zone, ISC_LOG_WARNING,
6071                                              "dump failed: %s",
6072                                              dns_result_totext(result));
6073                 }
6074                 break;
6075         default:
6076                 break;
6077         }
6078
6079         switch (zone->type) {
6080         case dns_zone_master:
6081         case dns_zone_slave:
6082                 /*
6083                  * Do we need to send out notify messages?
6084                  */
6085                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
6086                     isc_time_compare(&now, &zone->notifytime) >= 0)
6087                         zone_notify(zone, &now);
6088                 /*
6089                  * Do we need to sign/resign some RRsets?
6090                  */
6091                 if (!isc_time_isepoch(&zone->signingtime) &&
6092                     isc_time_compare(&now, &zone->signingtime) >= 0)
6093                         zone_sign(zone);
6094                 else if (!isc_time_isepoch(&zone->resigntime) &&
6095                     isc_time_compare(&now, &zone->resigntime) >= 0)
6096                         zone_resigninc(zone);
6097                 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
6098                         isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
6099                         zone_nsec3chain(zone);
6100                 /*
6101                  * Do we need to issue a key expiry warning.
6102                  */
6103                 if (!isc_time_isepoch(&zone->keywarntime) &&
6104                     isc_time_compare(&now, &zone->keywarntime) >= 0)
6105                         set_key_expiry_warning(zone, zone->key_expiry,
6106                                                isc_time_seconds(&now));
6107                 break;
6108         default:
6109                 break;
6110         }
6111         zone_settimer(zone, &now);
6112 }
6113
6114 void
6115 dns_zone_markdirty(dns_zone_t *zone) {
6116
6117         LOCK_ZONE(zone);
6118         if (zone->type == dns_zone_master)
6119                 set_resigntime(zone);   /* XXXMPA make separate call back */
6120         zone_needdump(zone, DNS_DUMP_DELAY);
6121         UNLOCK_ZONE(zone);
6122 }
6123
6124 void
6125 dns_zone_expire(dns_zone_t *zone) {
6126         REQUIRE(DNS_ZONE_VALID(zone));
6127
6128         LOCK_ZONE(zone);
6129         zone_expire(zone);
6130         UNLOCK_ZONE(zone);
6131 }
6132
6133 static void
6134 zone_expire(dns_zone_t *zone) {
6135         /*
6136          * 'zone' locked by caller.
6137          */
6138
6139         REQUIRE(LOCKED_ZONE(zone));
6140
6141         dns_zone_log(zone, ISC_LOG_WARNING, "expired");
6142
6143         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
6144         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
6145         zone->retry = DNS_ZONE_DEFAULTRETRY;
6146         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
6147         zone_unload(zone);
6148 }
6149
6150 void
6151 dns_zone_refresh(dns_zone_t *zone) {
6152         isc_interval_t i;
6153         isc_uint32_t oldflags;
6154         unsigned int j;
6155         isc_result_t result;
6156
6157         REQUIRE(DNS_ZONE_VALID(zone));
6158
6159         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
6160                 return;
6161
6162         /*
6163          * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
6164          * in progress at a time.
6165          */
6166
6167         LOCK_ZONE(zone);
6168         oldflags = zone->flags;
6169         if (zone->masterscnt == 0) {
6170                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6171                 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
6172                         dns_zone_log(zone, ISC_LOG_ERROR,
6173                                      "cannot refresh: no masters");
6174                 goto unlock;
6175         }
6176         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
6177         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
6178         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
6179         if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
6180                 goto unlock;
6181
6182         /*
6183          * Set the next refresh time as if refresh check has failed.
6184          * Setting this to the retry time will do that.  XXXMLG
6185          * If we are successful it will be reset using zone->refresh.
6186          */
6187         isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
6188                          0);
6189         result = isc_time_nowplusinterval(&zone->refreshtime, &i);
6190         if (result != ISC_R_SUCCESS)
6191                 dns_zone_log(zone, ISC_LOG_WARNING,
6192                              "isc_time_nowplusinterval() failed: %s",
6193                              dns_result_totext(result));
6194
6195         /*
6196          * When lacking user-specified timer values from the SOA,
6197          * do exponential backoff of the retry time up to a
6198          * maximum of six hours.
6199          */
6200         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
6201                 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
6202
6203         zone->curmaster = 0;
6204         for (j = 0; j < zone->masterscnt; j++)
6205                 zone->mastersok[j] = ISC_FALSE;
6206         /* initiate soa query */
6207         queue_soa_query(zone);
6208  unlock:
6209         UNLOCK_ZONE(zone);
6210 }
6211
6212 isc_result_t
6213 dns_zone_flush(dns_zone_t *zone) {
6214         isc_result_t result = ISC_R_SUCCESS;
6215         isc_boolean_t dumping;
6216
6217         REQUIRE(DNS_ZONE_VALID(zone));
6218
6219         LOCK_ZONE(zone);
6220         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
6221         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
6222             zone->masterfile != NULL) {
6223                 result = ISC_R_ALREADYRUNNING;
6224                 dumping = was_dumping(zone);
6225         } else
6226                 dumping = ISC_TRUE;
6227         UNLOCK_ZONE(zone);
6228         if (!dumping)
6229                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
6230         return (result);
6231 }
6232
6233 isc_result_t
6234 dns_zone_dump(dns_zone_t *zone) {
6235         isc_result_t result = ISC_R_ALREADYRUNNING;
6236         isc_boolean_t dumping;
6237
6238         REQUIRE(DNS_ZONE_VALID(zone));
6239
6240         LOCK_ZONE(zone);
6241         dumping = was_dumping(zone);
6242         UNLOCK_ZONE(zone);
6243         if (!dumping)
6244                 result = zone_dump(zone, ISC_FALSE);    /* Unknown task. */
6245         return (result);
6246 }
6247
6248 static void
6249 zone_needdump(dns_zone_t *zone, unsigned int delay) {
6250         isc_time_t dumptime;
6251         isc_time_t now;
6252
6253         /*
6254          * 'zone' locked by caller
6255          */
6256
6257         REQUIRE(DNS_ZONE_VALID(zone));
6258         REQUIRE(LOCKED_ZONE(zone));
6259
6260         /*
6261          * Do we have a place to dump to and are we loaded?
6262          */
6263         if (zone->masterfile == NULL ||
6264             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
6265                 return;
6266
6267         TIME_NOW(&now);
6268         /* add some noise */
6269         DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
6270
6271         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6272         if (isc_time_isepoch(&zone->dumptime) ||
6273             isc_time_compare(&zone->dumptime, &dumptime) > 0)
6274                 zone->dumptime = dumptime;
6275         if (zone->task != NULL)
6276                 zone_settimer(zone, &now);
6277 }
6278
6279 static void
6280 dump_done(void *arg, isc_result_t result) {
6281         const char me[] = "dump_done";
6282         dns_zone_t *zone = arg;
6283         dns_db_t *db;
6284         dns_dbversion_t *version;
6285         isc_boolean_t again = ISC_FALSE;
6286         isc_boolean_t compact = ISC_FALSE;
6287         isc_uint32_t serial;
6288         isc_result_t tresult;
6289
6290         REQUIRE(DNS_ZONE_VALID(zone));
6291
6292         ENTER;
6293
6294         if (result == ISC_R_SUCCESS && zone->journal != NULL &&
6295             zone->journalsize != -1) {
6296
6297                 /*
6298                  * We don't own these, zone->dctx must stay valid.
6299                  */
6300                 db = dns_dumpctx_db(zone->dctx);
6301                 version = dns_dumpctx_version(zone->dctx);
6302
6303                 tresult = dns_db_getsoaserial(db, version, &serial);
6304                 /*
6305                  * Note: we are task locked here so we can test
6306                  * zone->xfr safely.
6307                  */
6308                 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
6309                         tresult = dns_journal_compact(zone->mctx,
6310                                                       zone->journal,
6311                                                       serial,
6312                                                       zone->journalsize);
6313                         switch (tresult) {
6314                         case ISC_R_SUCCESS:
6315                         case ISC_R_NOSPACE:
6316                         case ISC_R_NOTFOUND:
6317                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
6318                                              "dns_journal_compact: %s",
6319                                              dns_result_totext(tresult));
6320                                 break;
6321                         default:
6322                                 dns_zone_log(zone, ISC_LOG_ERROR,
6323                                              "dns_journal_compact failed: %s",
6324                                              dns_result_totext(tresult));
6325                                 break;
6326                         }
6327                 } else if (tresult == ISC_R_SUCCESS) {
6328                         compact = ISC_TRUE;
6329                         zone->compact_serial = serial;
6330                 }
6331         }
6332
6333         LOCK_ZONE(zone);
6334         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
6335         if (compact)
6336                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
6337         if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
6338                 /*
6339                  * Try again in a short while.
6340                  */
6341                 zone_needdump(zone, DNS_DUMP_DELAY);
6342         } else if (result == ISC_R_SUCCESS &&
6343                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
6344                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
6345                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
6346                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6347                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6348                 isc_time_settoepoch(&zone->dumptime);
6349                 again = ISC_TRUE;
6350         } else if (result == ISC_R_SUCCESS)
6351                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
6352
6353         if (zone->dctx != NULL)
6354                 dns_dumpctx_detach(&zone->dctx);
6355         zonemgr_putio(&zone->writeio);
6356         UNLOCK_ZONE(zone);
6357         if (again)
6358                 (void)zone_dump(zone, ISC_FALSE);
6359         dns_zone_idetach(&zone);
6360 }
6361
6362 static isc_result_t
6363 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
6364         const char me[] = "zone_dump";
6365         isc_result_t result;
6366         dns_dbversion_t *version = NULL;
6367         isc_boolean_t again;
6368         dns_db_t *db = NULL;
6369         char *masterfile = NULL;
6370         dns_masterformat_t masterformat = dns_masterformat_none;
6371
6372 /*
6373  * 'compact' MUST only be set if we are task locked.
6374  */
6375
6376         REQUIRE(DNS_ZONE_VALID(zone));
6377         ENTER;
6378
6379  redo:
6380         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6381         if (zone->db != NULL)
6382                 dns_db_attach(zone->db, &db);
6383         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6384         LOCK_ZONE(zone);
6385         if (zone->masterfile != NULL) {
6386                 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
6387                 masterformat = zone->masterformat;
6388         }
6389         UNLOCK_ZONE(zone);
6390         if (db == NULL) {
6391                 result = DNS_R_NOTLOADED;
6392                 goto fail;
6393         }
6394         if (masterfile == NULL) {
6395                 result = DNS_R_NOMASTERFILE;
6396                 goto fail;
6397         }
6398
6399         if (compact && zone->type != dns_zone_stub) {
6400                 dns_zone_t *dummy = NULL;
6401                 LOCK_ZONE(zone);
6402                 zone_iattach(zone, &dummy);
6403                 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
6404                                        zone_gotwritehandle, zone,
6405                                        &zone->writeio);
6406                 if (result != ISC_R_SUCCESS)
6407                         zone_idetach(&dummy);
6408                 else
6409                         result = DNS_R_CONTINUE;
6410                 UNLOCK_ZONE(zone);
6411         } else {
6412                 dns_db_currentversion(db, &version);
6413                 result = dns_master_dump2(zone->mctx, db, version,
6414                                           &dns_master_style_default,
6415                                           masterfile, masterformat);
6416                 dns_db_closeversion(db, &version, ISC_FALSE);
6417         }
6418  fail:
6419         if (db != NULL)
6420                 dns_db_detach(&db);
6421         if (masterfile != NULL)
6422                 isc_mem_free(zone->mctx, masterfile);
6423         masterfile = NULL;
6424
6425         if (result == DNS_R_CONTINUE)
6426                 return (ISC_R_SUCCESS); /* XXXMPA */
6427
6428         again = ISC_FALSE;
6429         LOCK_ZONE(zone);
6430         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
6431         if (result != ISC_R_SUCCESS) {
6432                 /*
6433                  * Try again in a short while.
6434                  */
6435                 zone_needdump(zone, DNS_DUMP_DELAY);
6436         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
6437                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
6438                    DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
6439                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6440                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6441                 isc_time_settoepoch(&zone->dumptime);
6442                 again = ISC_TRUE;
6443         } else
6444                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
6445         UNLOCK_ZONE(zone);
6446         if (again)
6447                 goto redo;
6448
6449         return (result);
6450 }
6451
6452 static isc_result_t
6453 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
6454              dns_masterformat_t format)
6455 {
6456         isc_result_t result;
6457         dns_dbversion_t *version = NULL;
6458         dns_db_t *db = NULL;
6459
6460         REQUIRE(DNS_ZONE_VALID(zone));
6461
6462         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6463         if (zone->db != NULL)
6464                 dns_db_attach(zone->db, &db);
6465         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6466         if (db == NULL)
6467                 return (DNS_R_NOTLOADED);
6468
6469         dns_db_currentversion(db, &version);
6470         result = dns_master_dumptostream2(zone->mctx, db, version, style,
6471                                           format, fd);
6472         dns_db_closeversion(db, &version, ISC_FALSE);
6473         dns_db_detach(&db);
6474         return (result);
6475 }
6476
6477 isc_result_t
6478 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
6479                        const dns_master_style_t *style) {
6480         return dumptostream(zone, fd, style, format);
6481 }
6482
6483 isc_result_t
6484 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
6485         return dumptostream(zone, fd, &dns_master_style_default,
6486                             dns_masterformat_text);
6487 }
6488
6489 isc_result_t
6490 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
6491         return dumptostream(zone, fd, &dns_master_style_full,
6492                             dns_masterformat_text);
6493 }
6494
6495 void
6496 dns_zone_unload(dns_zone_t *zone) {
6497         REQUIRE(DNS_ZONE_VALID(zone));
6498
6499         LOCK_ZONE(zone);
6500         zone_unload(zone);
6501         UNLOCK_ZONE(zone);
6502 }
6503
6504 static void
6505 notify_cancel(dns_zone_t *zone) {
6506         dns_notify_t *notify;
6507
6508         /*
6509          * 'zone' locked by caller.
6510          */
6511
6512         REQUIRE(LOCKED_ZONE(zone));
6513
6514         for (notify = ISC_LIST_HEAD(zone->notifies);
6515              notify != NULL;
6516              notify = ISC_LIST_NEXT(notify, link)) {
6517                 if (notify->find != NULL)
6518                         dns_adb_cancelfind(notify->find);
6519                 if (notify->request != NULL)
6520                         dns_request_cancel(notify->request);
6521         }
6522 }
6523
6524 static void
6525 forward_cancel(dns_zone_t *zone) {
6526         dns_forward_t *forward;
6527
6528         /*
6529          * 'zone' locked by caller.
6530          */
6531
6532         REQUIRE(LOCKED_ZONE(zone));
6533
6534         for (forward = ISC_LIST_HEAD(zone->forwards);
6535              forward != NULL;
6536              forward = ISC_LIST_NEXT(forward, link)) {
6537                 if (forward->request != NULL)
6538                         dns_request_cancel(forward->request);
6539         }
6540 }
6541
6542 static void
6543 zone_unload(dns_zone_t *zone) {
6544
6545         /*
6546          * 'zone' locked by caller.
6547          */
6548
6549         REQUIRE(LOCKED_ZONE(zone));
6550
6551         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
6552             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6553                 if (zone->writeio != NULL)
6554                         zonemgr_cancelio(zone->writeio);
6555
6556                 if (zone->dctx != NULL)
6557                         dns_dumpctx_cancel(zone->dctx);
6558         }
6559         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6560         zone_detachdb(zone);
6561         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6562         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
6563         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6564 }
6565
6566 void
6567 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
6568         REQUIRE(DNS_ZONE_VALID(zone));
6569         REQUIRE(val > 0);
6570
6571         zone->minrefresh = val;
6572 }
6573
6574 void
6575 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
6576         REQUIRE(DNS_ZONE_VALID(zone));
6577         REQUIRE(val > 0);
6578
6579         zone->maxrefresh = val;
6580 }
6581
6582 void
6583 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
6584         REQUIRE(DNS_ZONE_VALID(zone));
6585         REQUIRE(val > 0);
6586
6587         zone->minretry = val;
6588 }
6589
6590 void
6591 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
6592         REQUIRE(DNS_ZONE_VALID(zone));
6593         REQUIRE(val > 0);
6594
6595         zone->maxretry = val;
6596 }
6597
6598 static isc_boolean_t
6599 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
6600         dns_notify_t *notify;
6601
6602         for (notify = ISC_LIST_HEAD(zone->notifies);
6603              notify != NULL;
6604              notify = ISC_LIST_NEXT(notify, link)) {
6605                 if (notify->request != NULL)
6606                         continue;
6607                 if (name != NULL && dns_name_dynamic(&notify->ns) &&
6608                     dns_name_equal(name, &notify->ns))
6609                         return (ISC_TRUE);
6610                 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
6611                         return (ISC_TRUE);
6612         }
6613         return (ISC_FALSE);
6614 }
6615
6616 static isc_boolean_t
6617 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
6618         dns_tsigkey_t *key = NULL;
6619         isc_sockaddr_t src;
6620         isc_sockaddr_t any;
6621         isc_boolean_t isself;
6622         isc_netaddr_t dstaddr;
6623         isc_result_t result;
6624
6625         if (zone->view == NULL || zone->isself == NULL)
6626                 return (ISC_FALSE);
6627
6628         switch (isc_sockaddr_pf(dst)) {
6629         case PF_INET:
6630                 src = zone->notifysrc4;
6631                 isc_sockaddr_any(&any);
6632                 break;
6633         case PF_INET6:
6634                 src = zone->notifysrc6;
6635                 isc_sockaddr_any6(&any);
6636                 break;
6637         default:
6638                 return (ISC_FALSE);
6639         }
6640
6641         /*
6642          * When sending from any the kernel will assign a source address
6643          * that matches the destination address.
6644          */
6645         if (isc_sockaddr_eqaddr(&any, &src))
6646                 src = *dst;
6647
6648         isc_netaddr_fromsockaddr(&dstaddr, dst);
6649         result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
6650         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
6651                 return (ISC_FALSE);
6652         isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
6653                                 zone->isselfarg);
6654         if (key != NULL)
6655                 dns_tsigkey_detach(&key);
6656         return (isself);
6657 }
6658
6659 static void
6660 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
6661         isc_mem_t *mctx;
6662
6663         /*
6664          * Caller holds zone lock.
6665          */
6666         REQUIRE(DNS_NOTIFY_VALID(notify));
6667
6668         if (notify->zone != NULL) {
6669                 if (!locked)
6670                         LOCK_ZONE(notify->zone);
6671                 REQUIRE(LOCKED_ZONE(notify->zone));
6672                 if (ISC_LINK_LINKED(notify, link))
6673                         ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
6674                 if (!locked)
6675                         UNLOCK_ZONE(notify->zone);
6676                 if (locked)
6677                         zone_idetach(&notify->zone);
6678                 else
6679                         dns_zone_idetach(&notify->zone);
6680         }
6681         if (notify->find != NULL)
6682                 dns_adb_destroyfind(&notify->find);
6683         if (notify->request != NULL)
6684                 dns_request_destroy(&notify->request);
6685         if (dns_name_dynamic(&notify->ns))
6686                 dns_name_free(&notify->ns, notify->mctx);
6687         mctx = notify->mctx;
6688         isc_mem_put(notify->mctx, notify, sizeof(*notify));
6689         isc_mem_detach(&mctx);
6690 }
6691
6692 static isc_result_t
6693 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
6694         dns_notify_t *notify;
6695
6696         REQUIRE(notifyp != NULL && *notifyp == NULL);
6697
6698         notify = isc_mem_get(mctx, sizeof(*notify));
6699         if (notify == NULL)
6700                 return (ISC_R_NOMEMORY);
6701
6702         notify->mctx = NULL;
6703         isc_mem_attach(mctx, &notify->mctx);
6704         notify->flags = flags;
6705         notify->zone = NULL;
6706         notify->find = NULL;
6707         notify->request = NULL;
6708         isc_sockaddr_any(&notify->dst);
6709         dns_name_init(&notify->ns, NULL);
6710         ISC_LINK_INIT(notify, link);
6711         notify->magic = NOTIFY_MAGIC;
6712         *notifyp = notify;
6713         return (ISC_R_SUCCESS);
6714 }
6715
6716 /*
6717  * XXXAG should check for DNS_ZONEFLG_EXITING
6718  */
6719 static void
6720 process_adb_event(isc_task_t *task, isc_event_t *ev) {
6721         dns_notify_t *notify;
6722         isc_eventtype_t result;
6723
6724         UNUSED(task);
6725
6726         notify = ev->ev_arg;
6727         REQUIRE(DNS_NOTIFY_VALID(notify));
6728         INSIST(task == notify->zone->task);
6729         result = ev->ev_type;
6730         isc_event_free(&ev);
6731         if (result == DNS_EVENT_ADBMOREADDRESSES) {
6732                 dns_adb_destroyfind(&notify->find);
6733                 notify_find_address(notify);
6734                 return;
6735         }
6736         if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
6737                 LOCK_ZONE(notify->zone);
6738                 notify_send(notify);
6739                 UNLOCK_ZONE(notify->zone);
6740         }
6741         notify_destroy(notify, ISC_FALSE);
6742 }
6743
6744 static void
6745 notify_find_address(dns_notify_t *notify) {
6746         isc_result_t result;
6747         unsigned int options;
6748
6749         REQUIRE(DNS_NOTIFY_VALID(notify));
6750         options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
6751                   DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
6752
6753         if (notify->zone->view->adb == NULL)
6754                 goto destroy;
6755
6756         result = dns_adb_createfind(notify->zone->view->adb,
6757                                     notify->zone->task,
6758                                     process_adb_event, notify,
6759                                     &notify->ns, dns_rootname, 0,
6760                                     options, 0, NULL,
6761                                     notify->zone->view->dstport,
6762                                     &notify->find);
6763
6764         /* Something failed? */
6765         if (result != ISC_R_SUCCESS)
6766                 goto destroy;
6767
6768         /* More addresses pending? */
6769         if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
6770                 return;
6771
6772         /* We have as many addresses as we can get. */
6773         LOCK_ZONE(notify->zone);
6774         notify_send(notify);
6775         UNLOCK_ZONE(notify->zone);
6776
6777  destroy:
6778         notify_destroy(notify, ISC_FALSE);
6779 }
6780
6781
6782 static isc_result_t
6783 notify_send_queue(dns_notify_t *notify) {
6784         isc_event_t *e;
6785         isc_result_t result;
6786
6787         e = isc_event_allocate(notify->mctx, NULL,
6788                                DNS_EVENT_NOTIFYSENDTOADDR,
6789                                notify_send_toaddr,
6790                                notify, sizeof(isc_event_t));
6791         if (e == NULL)
6792                 return (ISC_R_NOMEMORY);
6793         e->ev_arg = notify;
6794         e->ev_sender = NULL;
6795         result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
6796                                          notify->zone->task, &e);
6797         if (result != ISC_R_SUCCESS)
6798                 isc_event_free(&e);
6799         return (result);
6800 }
6801
6802 static void
6803 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
6804         dns_notify_t *notify;
6805         isc_result_t result;
6806         dns_message_t *message = NULL;
6807         isc_netaddr_t dstip;
6808         dns_tsigkey_t *key = NULL;
6809         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
6810         isc_sockaddr_t src;
6811         int timeout;
6812         isc_boolean_t have_notifysource = ISC_FALSE;
6813
6814         notify = event->ev_arg;
6815         REQUIRE(DNS_NOTIFY_VALID(notify));
6816
6817         UNUSED(task);
6818
6819         LOCK_ZONE(notify->zone);
6820
6821         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
6822                 result = ISC_R_CANCELED;
6823                 goto cleanup;
6824         }
6825
6826         if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
6827             DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
6828             notify->zone->view->requestmgr == NULL ||
6829             notify->zone->db == NULL) {
6830                 result = ISC_R_CANCELED;
6831                 goto cleanup;
6832         }
6833
6834         /*
6835          * The raw IPv4 address should also exist.  Don't send to the
6836          * mapped form.
6837          */
6838         if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
6839             IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
6840                 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
6841                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
6842                            "notify: ignoring IPv6 mapped IPV4 address: %s",
6843                            addrbuf);
6844                 result = ISC_R_CANCELED;
6845                 goto cleanup;
6846         }
6847
6848         result = notify_createmessage(notify->zone, notify->flags, &message);
6849         if (result != ISC_R_SUCCESS)
6850                 goto cleanup;
6851
6852         isc_netaddr_fromsockaddr(&dstip, &notify->dst);
6853         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
6854         result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
6855         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6856                 notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not "
6857                            "sent. Peer TSIG key lookup failure.", addrbuf);
6858                 goto cleanup_message;
6859         }
6860
6861         notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
6862                    addrbuf);
6863         if (notify->zone->view->peers != NULL) {
6864                 dns_peer_t *peer = NULL;
6865                 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
6866                                                  &dstip, &peer);
6867                 if (result == ISC_R_SUCCESS) {
6868                         result = dns_peer_getnotifysource(peer, &src);
6869                         if (result == ISC_R_SUCCESS)
6870                                 have_notifysource = ISC_TRUE;
6871                 }
6872         }
6873         switch (isc_sockaddr_pf(&notify->dst)) {
6874         case PF_INET:
6875                 if (!have_notifysource)
6876                         src = notify->zone->notifysrc4;
6877                 break;
6878         case PF_INET6:
6879                 if (!have_notifysource)
6880                         src = notify->zone->notifysrc6;
6881                 break;
6882         default:
6883                 result = ISC_R_NOTIMPLEMENTED;
6884                 goto cleanup_key;
6885         }
6886         timeout = 15;
6887         if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
6888                 timeout = 30;
6889         result = dns_request_createvia2(notify->zone->view->requestmgr,
6890                                         message, &src, &notify->dst, 0, key,
6891                                         timeout * 3, timeout,
6892                                         notify->zone->task, notify_done,
6893                                         notify, &notify->request);
6894         if (result == ISC_R_SUCCESS) {
6895                 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
6896                         inc_stats(notify->zone,
6897                                   dns_zonestatscounter_notifyoutv4);
6898                 } else {
6899                         inc_stats(notify->zone,
6900                                   dns_zonestatscounter_notifyoutv6);
6901                 }
6902         }
6903
6904  cleanup_key:
6905         if (key != NULL)
6906                 dns_tsigkey_detach(&key);
6907  cleanup_message:
6908         dns_message_destroy(&message);
6909  cleanup:
6910         UNLOCK_ZONE(notify->zone);
6911         if (result != ISC_R_SUCCESS)
6912                 notify_destroy(notify, ISC_FALSE);
6913         isc_event_free(&event);
6914 }
6915
6916 static void
6917 notify_send(dns_notify_t *notify) {
6918         dns_adbaddrinfo_t *ai;
6919         isc_sockaddr_t dst;
6920         isc_result_t result;
6921         dns_notify_t *new = NULL;
6922
6923         /*
6924          * Zone lock held by caller.
6925          */
6926         REQUIRE(DNS_NOTIFY_VALID(notify));
6927         REQUIRE(LOCKED_ZONE(notify->zone));
6928
6929         for (ai = ISC_LIST_HEAD(notify->find->list);
6930              ai != NULL;
6931              ai = ISC_LIST_NEXT(ai, publink)) {
6932                 dst = ai->sockaddr;
6933                 if (notify_isqueued(notify->zone, NULL, &dst))
6934                         continue;
6935                 if (notify_isself(notify->zone, &dst))
6936                         continue;
6937                 new = NULL;
6938                 result = notify_create(notify->mctx,
6939                                        (notify->flags & DNS_NOTIFY_NOSOA),
6940                                        &new);
6941                 if (result != ISC_R_SUCCESS)
6942                         goto cleanup;
6943                 zone_iattach(notify->zone, &new->zone);
6944                 ISC_LIST_APPEND(new->zone->notifies, new, link);
6945                 new->dst = dst;
6946                 result = notify_send_queue(new);
6947                 if (result != ISC_R_SUCCESS)
6948                         goto cleanup;
6949                 new = NULL;
6950         }
6951
6952  cleanup:
6953         if (new != NULL)
6954                 notify_destroy(new, ISC_TRUE);
6955 }
6956
6957 void
6958 dns_zone_notify(dns_zone_t *zone) {
6959         isc_time_t now;
6960
6961         REQUIRE(DNS_ZONE_VALID(zone));
6962
6963         LOCK_ZONE(zone);
6964         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6965
6966         TIME_NOW(&now);
6967         zone_settimer(zone, &now);
6968         UNLOCK_ZONE(zone);
6969 }
6970
6971 static void
6972 zone_notify(dns_zone_t *zone, isc_time_t *now) {
6973         dns_dbnode_t *node = NULL;
6974         dns_db_t *zonedb = NULL;
6975         dns_dbversion_t *version = NULL;
6976         dns_name_t *origin = NULL;
6977         dns_name_t master;
6978         dns_rdata_ns_t ns;
6979         dns_rdata_soa_t soa;
6980         isc_uint32_t serial;
6981         dns_rdata_t rdata = DNS_RDATA_INIT;
6982         dns_rdataset_t nsrdset;
6983         dns_rdataset_t soardset;
6984         isc_result_t result;
6985         dns_notify_t *notify = NULL;
6986         unsigned int i;
6987         isc_sockaddr_t dst;
6988         isc_boolean_t isqueued;
6989         dns_notifytype_t notifytype;
6990         unsigned int flags = 0;
6991         isc_boolean_t loggednotify = ISC_FALSE;
6992
6993         REQUIRE(DNS_ZONE_VALID(zone));
6994
6995         LOCK_ZONE(zone);
6996         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6997         notifytype = zone->notifytype;
6998         DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
6999         UNLOCK_ZONE(zone);
7000
7001         if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
7002                 return;
7003
7004         if (notifytype == dns_notifytype_no)
7005                 return;
7006
7007         if (notifytype == dns_notifytype_masteronly &&
7008             zone->type != dns_zone_master)
7009                 return;
7010
7011         origin = &zone->origin;
7012
7013         /*
7014          * If the zone is dialup we are done as we don't want to send
7015          * the current soa so as to force a refresh query.
7016          */
7017         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
7018                 flags |= DNS_NOTIFY_NOSOA;
7019
7020         /*
7021          * Get SOA RRset.
7022          */
7023         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7024         if (zone->db != NULL)
7025                 dns_db_attach(zone->db, &zonedb);
7026         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7027         if (zonedb == NULL)
7028                 return;
7029         dns_db_currentversion(zonedb, &version);
7030         result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
7031         if (result != ISC_R_SUCCESS)
7032                 goto cleanup1;
7033
7034         dns_rdataset_init(&soardset);
7035         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
7036                                      dns_rdatatype_none, 0, &soardset, NULL);
7037         if (result != ISC_R_SUCCESS)
7038                 goto cleanup2;
7039
7040         /*
7041          * Find serial and master server's name.
7042          */
7043         dns_name_init(&master, NULL);
7044         result = dns_rdataset_first(&soardset);
7045         if (result != ISC_R_SUCCESS)
7046                 goto cleanup3;
7047         dns_rdataset_current(&soardset, &rdata);
7048         result = dns_rdata_tostruct(&rdata, &soa, NULL);
7049         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7050         dns_rdata_reset(&rdata);
7051         result = dns_name_dup(&soa.origin, zone->mctx, &master);
7052         serial = soa.serial;
7053         dns_rdataset_disassociate(&soardset);
7054         if (result != ISC_R_SUCCESS)
7055                 goto cleanup3;
7056
7057         /*
7058          * Enqueue notify requests for 'also-notify' servers.
7059          */
7060         LOCK_ZONE(zone);
7061         for (i = 0; i < zone->notifycnt; i++) {
7062                 dst = zone->notify[i];
7063                 if (notify_isqueued(zone, NULL, &dst))
7064                         continue;
7065                 result = notify_create(zone->mctx, flags, &notify);
7066                 if (result != ISC_R_SUCCESS)
7067                         continue;
7068                 zone_iattach(zone, &notify->zone);
7069                 notify->dst = dst;
7070                 ISC_LIST_APPEND(zone->notifies, notify, link);
7071                 result = notify_send_queue(notify);
7072                 if (result != ISC_R_SUCCESS)
7073                         notify_destroy(notify, ISC_TRUE);
7074                 if (!loggednotify) {
7075                         notify_log(zone, ISC_LOG_INFO,
7076                                    "sending notifies (serial %u)",
7077                                    serial);
7078                         loggednotify = ISC_TRUE;
7079                 }
7080                 notify = NULL;
7081         }
7082         UNLOCK_ZONE(zone);
7083
7084         if (notifytype == dns_notifytype_explicit)
7085                 goto cleanup3;
7086
7087         /*
7088          * Process NS RRset to generate notifies.
7089          */
7090
7091         dns_rdataset_init(&nsrdset);
7092         result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
7093                                      dns_rdatatype_none, 0, &nsrdset, NULL);
7094         if (result != ISC_R_SUCCESS)
7095                 goto cleanup3;
7096
7097         result = dns_rdataset_first(&nsrdset);
7098         while (result == ISC_R_SUCCESS) {
7099                 dns_rdataset_current(&nsrdset, &rdata);
7100                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
7101                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7102                 dns_rdata_reset(&rdata);
7103                 /*
7104                  * Don't notify the master server unless explicitly
7105                  * configured to do so.
7106                  */
7107                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
7108                     dns_name_compare(&master, &ns.name) == 0) {
7109                         result = dns_rdataset_next(&nsrdset);
7110                         continue;
7111                 }
7112
7113                 if (!loggednotify) {
7114                         notify_log(zone, ISC_LOG_INFO,
7115                                    "sending notifies (serial %u)",
7116                                    serial);
7117                         loggednotify = ISC_TRUE;
7118                 }
7119
7120                 LOCK_ZONE(zone);
7121                 isqueued = notify_isqueued(zone, &ns.name, NULL);
7122                 UNLOCK_ZONE(zone);
7123                 if (isqueued) {
7124                         result = dns_rdataset_next(&nsrdset);
7125                         continue;
7126                 }
7127                 result = notify_create(zone->mctx, flags, &notify);
7128                 if (result != ISC_R_SUCCESS)
7129                         continue;
7130                 dns_zone_iattach(zone, &notify->zone);
7131                 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
7132                 if (result != ISC_R_SUCCESS) {
7133                         LOCK_ZONE(zone);
7134                         notify_destroy(notify, ISC_TRUE);
7135                         UNLOCK_ZONE(zone);
7136                         continue;
7137                 }
7138                 LOCK_ZONE(zone);
7139                 ISC_LIST_APPEND(zone->notifies, notify, link);
7140                 UNLOCK_ZONE(zone);
7141                 notify_find_address(notify);
7142                 notify = NULL;
7143                 result = dns_rdataset_next(&nsrdset);
7144         }
7145         dns_rdataset_disassociate(&nsrdset);
7146
7147  cleanup3:
7148         if (dns_name_dynamic(&master))
7149                 dns_name_free(&master, zone->mctx);
7150  cleanup2:
7151         dns_db_detachnode(zonedb, &node);
7152  cleanup1:
7153         dns_db_closeversion(zonedb, &version, ISC_FALSE);
7154         dns_db_detach(&zonedb);
7155 }
7156
7157 /***
7158  *** Private
7159  ***/
7160
7161 static inline isc_result_t
7162 save_nsrrset(dns_message_t *message, dns_name_t *name,
7163              dns_db_t *db, dns_dbversion_t *version)
7164 {
7165         dns_rdataset_t *nsrdataset = NULL;
7166         dns_rdataset_t *rdataset = NULL;
7167         dns_dbnode_t *node = NULL;
7168         dns_rdata_ns_t ns;
7169         isc_result_t result;
7170         dns_rdata_t rdata = DNS_RDATA_INIT;
7171
7172         /*
7173          * Extract NS RRset from message.
7174          */
7175         result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
7176                                       dns_rdatatype_ns, dns_rdatatype_none,
7177                                       NULL, &nsrdataset);
7178         if (result != ISC_R_SUCCESS)
7179                 goto fail;
7180
7181         /*
7182          * Add NS rdataset.
7183          */
7184         result = dns_db_findnode(db, name, ISC_TRUE, &node);
7185         if (result != ISC_R_SUCCESS)
7186                 goto fail;
7187         result = dns_db_addrdataset(db, node, version, 0,
7188                                     nsrdataset, 0, NULL);
7189         dns_db_detachnode(db, &node);
7190         if (result != ISC_R_SUCCESS)
7191                 goto fail;
7192         /*
7193          * Add glue rdatasets.
7194          */
7195         for (result = dns_rdataset_first(nsrdataset);
7196              result == ISC_R_SUCCESS;
7197              result = dns_rdataset_next(nsrdataset)) {
7198                 dns_rdataset_current(nsrdataset, &rdata);
7199                 result = dns_rdata_tostruct(&rdata, &ns, NULL);
7200                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7201                 dns_rdata_reset(&rdata);
7202                 if (!dns_name_issubdomain(&ns.name, name))
7203                         continue;
7204                 rdataset = NULL;
7205                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
7206                                               &ns.name, dns_rdatatype_aaaa,
7207                                               dns_rdatatype_none, NULL,
7208                                               &rdataset);
7209                 if (result == ISC_R_SUCCESS) {
7210                         result = dns_db_findnode(db, &ns.name,
7211                                                  ISC_TRUE, &node);
7212                         if (result != ISC_R_SUCCESS)
7213                                 goto fail;
7214                         result = dns_db_addrdataset(db, node, version, 0,
7215                                                     rdataset, 0, NULL);
7216                         dns_db_detachnode(db, &node);
7217                         if (result != ISC_R_SUCCESS)
7218                                 goto fail;
7219                 }
7220                 rdataset = NULL;
7221                 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
7222                                               &ns.name, dns_rdatatype_a,
7223                                               dns_rdatatype_none, NULL,
7224                                               &rdataset);
7225                 if (result == ISC_R_SUCCESS) {
7226                         result = dns_db_findnode(db, &ns.name,
7227                                                  ISC_TRUE, &node);
7228                         if (result != ISC_R_SUCCESS)
7229                                 goto fail;
7230                         result = dns_db_addrdataset(db, node, version, 0,
7231                                                     rdataset, 0, NULL);
7232                         dns_db_detachnode(db, &node);
7233                         if (result != ISC_R_SUCCESS)
7234                                 goto fail;
7235                 }
7236         }
7237         if (result != ISC_R_NOMORE)
7238                 goto fail;
7239
7240         return (ISC_R_SUCCESS);
7241
7242 fail:
7243         return (result);
7244 }
7245
7246 static void
7247 stub_callback(isc_task_t *task, isc_event_t *event) {
7248         const char me[] = "stub_callback";
7249         dns_requestevent_t *revent = (dns_requestevent_t *)event;
7250         dns_stub_t *stub = NULL;
7251         dns_message_t *msg = NULL;
7252         dns_zone_t *zone = NULL;
7253         char master[ISC_SOCKADDR_FORMATSIZE];
7254         char source[ISC_SOCKADDR_FORMATSIZE];
7255         isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
7256         isc_result_t result;
7257         isc_time_t now;
7258         isc_boolean_t exiting = ISC_FALSE;
7259         isc_interval_t i;
7260         unsigned int j;
7261
7262         stub = revent->ev_arg;
7263         INSIST(DNS_STUB_VALID(stub));
7264
7265         UNUSED(task);
7266
7267         zone = stub->zone;
7268
7269         ENTER;
7270
7271         TIME_NOW(&now);
7272
7273         LOCK_ZONE(zone);
7274
7275         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7276                 zone_debuglog(zone, me, 1, "exiting");
7277                 exiting = ISC_TRUE;
7278                 goto next_master;
7279         }
7280
7281         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
7282         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
7283
7284         if (revent->result != ISC_R_SUCCESS) {
7285                 if (revent->result == ISC_R_TIMEDOUT &&
7286                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
7287                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7288                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7289                                      "refreshing stub: timeout retrying "
7290                                      " without EDNS master %s (source %s)",
7291                                      master, source);
7292                         goto same_master;
7293                 }
7294                 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
7295                                            &zone->sourceaddr, &now);
7296                 dns_zone_log(zone, ISC_LOG_INFO,
7297                              "could not refresh stub from master %s"
7298                              " (source %s): %s", master, source,
7299                              dns_result_totext(revent->result));
7300                 goto next_master;
7301         }
7302
7303         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
7304         if (result != ISC_R_SUCCESS)
7305                 goto next_master;
7306
7307         result = dns_request_getresponse(revent->request, msg, 0);
7308         if (result != ISC_R_SUCCESS)
7309                 goto next_master;
7310
7311         /*
7312          * Unexpected rcode.
7313          */
7314         if (msg->rcode != dns_rcode_noerror) {
7315                 char rcode[128];
7316                 isc_buffer_t rb;
7317
7318                 isc_buffer_init(&rb, rcode, sizeof(rcode));
7319                 (void)dns_rcode_totext(msg->rcode, &rb);
7320
7321                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
7322                     (msg->rcode == dns_rcode_servfail ||
7323                      msg->rcode == dns_rcode_notimp ||
7324                      msg->rcode == dns_rcode_formerr)) {
7325                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7326                                      "refreshing stub: rcode (%.*s) retrying "
7327                                      "without EDNS master %s (source %s)",
7328                                      (int)rb.used, rcode, master, source);
7329                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7330                         goto same_master;
7331                 }
7332
7333                 dns_zone_log(zone, ISC_LOG_INFO,
7334                              "refreshing stub: "
7335                              "unexpected rcode (%.*s) from %s (source %s)",
7336                              (int)rb.used, rcode, master, source);
7337                 goto next_master;
7338         }
7339
7340         /*
7341          * We need complete messages.
7342          */
7343         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
7344                 if (dns_request_usedtcp(revent->request)) {
7345                         dns_zone_log(zone, ISC_LOG_INFO,
7346                                      "refreshing stub: truncated TCP "
7347                                      "response from master %s (source %s)",
7348                                      master, source);
7349                         goto next_master;
7350                 }
7351                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
7352                 goto same_master;
7353         }
7354
7355         /*
7356          * If non-auth log and next master.
7357          */
7358         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
7359                 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
7360                              "non-authoritative answer from "
7361                              "master %s (source %s)", master, source);
7362                 goto next_master;
7363         }
7364
7365         /*
7366          * Sanity checks.
7367          */
7368         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
7369         nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
7370
7371         if (cnamecnt != 0) {
7372                 dns_zone_log(zone, ISC_LOG_INFO,
7373                              "refreshing stub: unexpected CNAME response "
7374                              "from master %s (source %s)", master, source);
7375                 goto next_master;
7376         }
7377
7378         if (nscnt == 0) {
7379                 dns_zone_log(zone, ISC_LOG_INFO,
7380                              "refreshing stub: no NS records in response "
7381                              "from master %s (source %s)", master, source);
7382                 goto next_master;
7383         }
7384
7385         /*
7386          * Save answer.
7387          */
7388         result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
7389         if (result != ISC_R_SUCCESS) {
7390                 dns_zone_log(zone, ISC_LOG_INFO,
7391                              "refreshing stub: unable to save NS records "
7392                              "from master %s (source %s)", master, source);
7393                 goto next_master;
7394         }
7395
7396         /*
7397          * Tidy up.
7398          */
7399         dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
7400         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
7401         if (zone->db == NULL)
7402                 zone_attachdb(zone, stub->db);
7403         result = zone_get_from_db(zone, zone->db, NULL, NULL, NULL, &refresh,
7404                                   &retry, &expire, NULL, NULL);
7405         if (result == ISC_R_SUCCESS) {
7406                 zone->refresh = RANGE(refresh, zone->minrefresh,
7407                                       zone->maxrefresh);
7408                 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
7409                 zone->expire = RANGE(expire, zone->refresh + zone->retry,
7410                                      DNS_MAX_EXPIRE);
7411                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
7412         }
7413         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
7414         dns_db_detach(&stub->db);
7415
7416         dns_message_destroy(&msg);
7417         isc_event_free(&event);
7418         dns_request_destroy(&zone->request);
7419
7420         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
7421         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7422         DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
7423         isc_interval_set(&i, zone->expire, 0);
7424         DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
7425
7426         if (zone->masterfile != NULL)
7427                 zone_needdump(zone, 0);
7428
7429         zone_settimer(zone, &now);
7430         goto free_stub;
7431
7432  next_master:
7433         if (stub->version != NULL)
7434                 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
7435         if (stub->db != NULL)
7436                 dns_db_detach(&stub->db);
7437         if (msg != NULL)
7438                 dns_message_destroy(&msg);
7439         isc_event_free(&event);
7440         dns_request_destroy(&zone->request);
7441         /*
7442          * Skip to next failed / untried master.
7443          */
7444         do {
7445                 zone->curmaster++;
7446         } while (zone->curmaster < zone->masterscnt &&
7447                  zone->mastersok[zone->curmaster]);
7448         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
7449         if (exiting || zone->curmaster >= zone->masterscnt) {
7450                 isc_boolean_t done = ISC_TRUE;
7451                 if (!exiting &&
7452                     DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
7453                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
7454                         /*
7455                          * Did we get a good answer from all the masters?
7456                          */
7457                         for (j = 0; j < zone->masterscnt; j++)
7458                                 if (zone->mastersok[j] == ISC_FALSE) {
7459                                         done = ISC_FALSE;
7460                                         break;
7461                                 }
7462                 } else
7463                         done = ISC_TRUE;
7464                 if (!done) {
7465                         zone->curmaster = 0;
7466                         /*
7467                          * Find the next failed master.
7468                          */
7469                         while (zone->curmaster < zone->masterscnt &&
7470                                zone->mastersok[zone->curmaster])
7471                                 zone->curmaster++;
7472                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
7473                 } else {
7474                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
7475
7476                         zone_settimer(zone, &now);
7477                         goto free_stub;
7478                 }
7479         }
7480         queue_soa_query(zone);
7481         goto free_stub;
7482
7483  same_master:
7484         if (msg != NULL)
7485                 dns_message_destroy(&msg);
7486         isc_event_free(&event);
7487         dns_request_destroy(&zone->request);
7488         ns_query(zone, NULL, stub);
7489         UNLOCK_ZONE(zone);
7490         goto done;
7491
7492  free_stub:
7493         UNLOCK_ZONE(zone);
7494         stub->magic = 0;
7495         dns_zone_idetach(&stub->zone);
7496         INSIST(stub->db == NULL);
7497         INSIST(stub->version == NULL);
7498         isc_mem_put(stub->mctx, stub, sizeof(*stub));
7499
7500  done:
7501         INSIST(event == NULL);
7502         return;
7503 }
7504
7505 /*
7506  * An SOA query has finished (successfully or not).
7507  */
7508 static void
7509 refresh_callback(isc_task_t *task, isc_event_t *event) {
7510         const char me[] = "refresh_callback";
7511         dns_requestevent_t *revent = (dns_requestevent_t *)event;
7512         dns_zone_t *zone;
7513         dns_message_t *msg = NULL;
7514         isc_uint32_t soacnt, cnamecnt, soacount, nscount;
7515         isc_time_t now;
7516         char master[ISC_SOCKADDR_FORMATSIZE];
7517         char source[ISC_SOCKADDR_FORMATSIZE];
7518         dns_rdataset_t *rdataset = NULL;
7519         dns_rdata_t rdata = DNS_RDATA_INIT;
7520         dns_rdata_soa_t soa;
7521         isc_result_t result;
7522         isc_uint32_t serial, oldserial = 0;
7523         unsigned int j;
7524         isc_boolean_t do_queue_xfrin = ISC_FALSE;
7525
7526         zone = revent->ev_arg;
7527         INSIST(DNS_ZONE_VALID(zone));
7528
7529         UNUSED(task);
7530
7531         ENTER;
7532
7533         TIME_NOW(&now);
7534
7535         LOCK_ZONE(zone);
7536
7537         /*
7538          * if timeout log and next master;
7539          */
7540
7541         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
7542         isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
7543
7544         if (revent->result != ISC_R_SUCCESS) {
7545                 if (revent->result == ISC_R_TIMEDOUT &&
7546                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
7547                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7548                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7549                                      "refresh: timeout retrying without EDNS "
7550                                      "master %s (source %s)", master, source);
7551                         goto same_master;
7552                 }
7553                 if (revent->result == ISC_R_TIMEDOUT &&
7554                     !dns_request_usedtcp(revent->request)) {
7555                         dns_zone_log(zone, ISC_LOG_INFO,
7556                                      "refresh: retry limit for "
7557                                      "master %s exceeded (source %s)",
7558                                      master, source);
7559                         /* Try with slave with TCP. */
7560                         if (zone->type == dns_zone_slave &&
7561                             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
7562                                 if (!dns_zonemgr_unreachable(zone->zmgr,
7563                                                              &zone->masteraddr,
7564                                                              &zone->sourceaddr,
7565                                                              &now))
7566                                 {
7567                                         DNS_ZONE_SETFLAG(zone,
7568                                                      DNS_ZONEFLG_SOABEFOREAXFR);
7569                                         goto tcp_transfer;
7570                                 }
7571                                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
7572                                              "refresh: skipped tcp fallback "
7573                                              "as master %s (source %s) is "
7574                                              "unreachable (cached)",
7575                                               master, source);
7576                         }
7577                 } else
7578                         dns_zone_log(zone, ISC_LOG_INFO,
7579                                      "refresh: failure trying master "
7580                                      "%s (source %s): %s", master, source,
7581                                      dns_result_totext(revent->result));
7582                 goto next_master;
7583         }
7584
7585         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
7586         if (result != ISC_R_SUCCESS)
7587                 goto next_master;
7588         result = dns_request_getresponse(revent->request, msg, 0);
7589         if (result != ISC_R_SUCCESS) {
7590                 dns_zone_log(zone, ISC_LOG_INFO,
7591                              "refresh: failure trying master "
7592                              "%s (source %s): %s", master, source,
7593                              dns_result_totext(result));
7594                 goto next_master;
7595         }
7596
7597         /*
7598          * Unexpected rcode.
7599          */
7600         if (msg->rcode != dns_rcode_noerror) {
7601                 char rcode[128];
7602                 isc_buffer_t rb;
7603
7604                 isc_buffer_init(&rb, rcode, sizeof(rcode));
7605                 (void)dns_rcode_totext(msg->rcode, &rb);
7606
7607                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
7608                     (msg->rcode == dns_rcode_servfail ||
7609                      msg->rcode == dns_rcode_notimp ||
7610                      msg->rcode == dns_rcode_formerr)) {
7611                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
7612                                      "refresh: rcode (%.*s) retrying without "
7613                                      "EDNS master %s (source %s)",
7614                                      (int)rb.used, rcode, master, source);
7615                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
7616                         goto same_master;
7617                 }
7618                 dns_zone_log(zone, ISC_LOG_INFO,
7619                              "refresh: unexpected rcode (%.*s) from "
7620                              "master %s (source %s)", (int)rb.used, rcode,
7621                              master, source);
7622                 /*
7623                  * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
7624                  */
7625                 if (msg->rcode == dns_rcode_refused &&
7626                     zone->type == dns_zone_slave)
7627                         goto tcp_transfer;
7628                 goto next_master;
7629         }
7630
7631         /*
7632          * If truncated punt to zone transfer which will query again.
7633          */
7634         if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
7635                 if (zone->type == dns_zone_slave) {
7636                         dns_zone_log(zone, ISC_LOG_INFO,
7637                                      "refresh: truncated UDP answer, "
7638                                      "initiating TCP zone xfer "
7639                                      "for master %s (source %s)",
7640                                      master, source);
7641                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
7642                         goto tcp_transfer;
7643                 } else {
7644                         INSIST(zone->type == dns_zone_stub);
7645                         if (dns_request_usedtcp(revent->request)) {
7646                                 dns_zone_log(zone, ISC_LOG_INFO,
7647                                              "refresh: truncated TCP response "
7648                                              "from master %s (source %s)",
7649                                              master, source);
7650                                 goto next_master;
7651                         }
7652                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
7653                         goto same_master;
7654                 }
7655         }
7656
7657         /*
7658          * if non-auth log and next master;
7659          */
7660         if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
7661                 dns_zone_log(zone, ISC_LOG_INFO,
7662                              "refresh: non-authoritative answer from "
7663                              "master %s (source %s)", master, source);
7664                 goto next_master;
7665         }
7666
7667         cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
7668         soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
7669         nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
7670         soacount = message_count(msg, DNS_SECTION_AUTHORITY,
7671                                  dns_rdatatype_soa);
7672
7673         /*
7674          * There should not be a CNAME record at top of zone.
7675          */
7676         if (cnamecnt != 0) {
7677                 dns_zone_log(zone, ISC_LOG_INFO,
7678                              "refresh: CNAME at top of zone "
7679                              "in master %s (source %s)", master, source);
7680                 goto next_master;
7681         }
7682
7683         /*
7684          * if referral log and next master;
7685          */
7686         if (soacnt == 0 && soacount == 0 && nscount != 0) {
7687                 dns_zone_log(zone, ISC_LOG_INFO,
7688                              "refresh: referral response "
7689                              "from master %s (source %s)", master, source);
7690                 goto next_master;
7691         }
7692
7693         /*
7694          * if nodata log and next master;
7695          */
7696         if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
7697                 dns_zone_log(zone, ISC_LOG_INFO,
7698                              "refresh: NODATA response "
7699                              "from master %s (source %s)", master, source);
7700                 goto next_master;
7701         }
7702
7703         /*
7704          * Only one soa at top of zone.
7705          */
7706         if (soacnt != 1) {
7707                 dns_zone_log(zone, ISC_LOG_INFO,
7708                              "refresh: answer SOA count (%d) != 1 "
7709                              "from master %s (source %s)",
7710                              soacnt, master, source);
7711                 goto next_master;
7712         }
7713
7714         /*
7715          * Extract serial
7716          */
7717         rdataset = NULL;
7718         result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
7719                                       dns_rdatatype_soa, dns_rdatatype_none,
7720                                       NULL, &rdataset);
7721         if (result != ISC_R_SUCCESS) {
7722                 dns_zone_log(zone, ISC_LOG_INFO,
7723                              "refresh: unable to get SOA record "
7724                              "from master %s (source %s)", master, source);
7725                 goto next_master;
7726         }
7727
7728         result = dns_rdataset_first(rdataset);
7729         if (result != ISC_R_SUCCESS) {
7730                 dns_zone_log(zone, ISC_LOG_INFO,
7731                              "refresh: dns_rdataset_first() failed");
7732                 goto next_master;
7733         }
7734
7735         dns_rdataset_current(rdataset, &rdata);
7736         result = dns_rdata_tostruct(&rdata, &soa, NULL);
7737         RUNTIME_CHECK(result == ISC_R_SUCCESS);
7738
7739         serial = soa.serial;
7740         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
7741                 result = zone_get_from_db(zone, zone->db, NULL, NULL,
7742                                           &oldserial, NULL, NULL, NULL, NULL,
7743                                           NULL);
7744                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7745                 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
7746                               serial, oldserial);
7747         } else
7748                 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
7749                               serial);
7750
7751         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
7752             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
7753             isc_serial_gt(serial, oldserial)) {
7754                 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
7755                                             &zone->sourceaddr, &now))
7756                 {
7757                         dns_zone_log(zone, ISC_LOG_INFO,
7758                                      "refresh: skipping %s as master %s "
7759                                      "(source %s) is unreachable (cached)",
7760                                      zone->type == dns_zone_slave ?
7761                                      "zone transfer" : "NS query",
7762                                      master, source);
7763                         goto next_master;
7764                 }
7765  tcp_transfer:
7766                 isc_event_free(&event);
7767                 dns_request_destroy(&zone->request);
7768                 if (zone->type == dns_zone_slave) {
7769                         do_queue_xfrin = ISC_TRUE;
7770                 } else {
7771                         INSIST(zone->type == dns_zone_stub);
7772                         ns_query(zone, rdataset, NULL);
7773                 }
7774                 if (msg != NULL)
7775                         dns_message_destroy(&msg);
7776         } else if (isc_serial_eq(soa.serial, oldserial)) {
7777                 if (zone->masterfile != NULL) {
7778                         result = ISC_R_FAILURE;
7779                         if (zone->journal != NULL)
7780                                 result = isc_file_settime(zone->journal, &now);
7781                         if (result == ISC_R_SUCCESS &&
7782                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
7783                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
7784                                 result = isc_file_settime(zone->masterfile,
7785                                                           &now);
7786                         } else if (result != ISC_R_SUCCESS)
7787                                 result = isc_file_settime(zone->masterfile,
7788                                                           &now);
7789                         /* Someone removed the file from underneath us! */
7790                         if (result == ISC_R_FILENOTFOUND) {
7791                                 zone_needdump(zone, DNS_DUMP_DELAY);
7792                         } else if (result != ISC_R_SUCCESS)
7793                                 dns_zone_log(zone, ISC_LOG_ERROR,
7794                                              "refresh: could not set file "
7795                                              "modification time of '%s': %s",
7796                                              zone->masterfile,
7797                                              dns_result_totext(result));
7798                 }
7799                 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
7800                 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
7801                 zone->mastersok[zone->curmaster] = ISC_TRUE;
7802                 goto next_master;
7803         } else {
7804                 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
7805                         dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
7806                                      "received from master %s < ours (%u)",
7807                                      soa.serial, master, oldserial);
7808                 else
7809                         zone_debuglog(zone, me, 1, "ahead");
7810                 zone->mastersok[zone->curmaster] = ISC_TRUE;
7811                 goto next_master;
7812         }
7813         if (msg != NULL)
7814                 dns_message_destroy(&msg);
7815         goto detach;
7816
7817  next_master:
7818         if (msg != NULL)
7819                 dns_message_destroy(&msg);
7820         isc_event_free(&event);
7821         dns_request_destroy(&zone->request);
7822         /*
7823          * Skip to next failed / untried master.
7824          */
7825         do {
7826                 zone->curmaster++;
7827         } while (zone->curmaster < zone->masterscnt &&
7828                  zone->mastersok[zone->curmaster]);
7829         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
7830         if (zone->curmaster >= zone->masterscnt) {
7831                 isc_boolean_t done = ISC_TRUE;
7832                 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
7833                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
7834                         /*
7835                          * Did we get a good answer from all the masters?
7836                          */
7837                         for (j = 0; j < zone->masterscnt; j++)
7838                                 if (zone->mastersok[j] == ISC_FALSE) {
7839                                         done = ISC_FALSE;
7840                                         break;
7841                                 }
7842                 } else
7843                         done = ISC_TRUE;
7844                 if (!done) {
7845                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
7846                         zone->curmaster = 0;
7847                         /*
7848                          * Find the next failed master.
7849                          */
7850                         while (zone->curmaster < zone->masterscnt &&
7851                                zone->mastersok[zone->curmaster])
7852                                 zone->curmaster++;
7853                         goto requeue;
7854                 }
7855                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
7856                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
7857                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
7858                         zone->refreshtime = now;
7859                 }
7860                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
7861                 zone_settimer(zone, &now);
7862                 goto detach;
7863         }
7864
7865  requeue:
7866         queue_soa_query(zone);
7867         goto detach;
7868
7869  same_master:
7870         if (msg != NULL)
7871                 dns_message_destroy(&msg);
7872         isc_event_free(&event);
7873         dns_request_destroy(&zone->request);
7874         queue_soa_query(zone);
7875
7876  detach:
7877         UNLOCK_ZONE(zone);
7878         if (do_queue_xfrin)
7879                 queue_xfrin(zone);
7880         dns_zone_idetach(&zone);
7881         return;
7882 }
7883
7884 static void
7885 queue_soa_query(dns_zone_t *zone) {
7886         const char me[] = "queue_soa_query";
7887         isc_event_t *e;
7888         dns_zone_t *dummy = NULL;
7889         isc_result_t result;
7890
7891         ENTER;
7892         /*
7893          * Locked by caller
7894          */
7895         REQUIRE(LOCKED_ZONE(zone));
7896
7897         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
7898                 cancel_refresh(zone);
7899                 return;
7900         }
7901
7902         e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
7903                                soa_query, zone, sizeof(isc_event_t));
7904         if (e == NULL) {
7905                 cancel_refresh(zone);
7906                 return;
7907         }
7908
7909         /*
7910          * Attach so that we won't clean up
7911          * until the event is delivered.
7912          */
7913         zone_iattach(zone, &dummy);
7914
7915         e->ev_arg = zone;
7916         e->ev_sender = NULL;
7917         result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
7918         if (result != ISC_R_SUCCESS) {
7919                 zone_idetach(&dummy);
7920                 isc_event_free(&e);
7921                 cancel_refresh(zone);
7922         }
7923 }
7924
7925 static inline isc_result_t
7926 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
7927              dns_message_t **messagep)
7928 {
7929         dns_message_t *message = NULL;
7930         dns_name_t *qname = NULL;
7931         dns_rdataset_t *qrdataset = NULL;
7932         isc_result_t result;
7933
7934         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
7935                                     &message);
7936         if (result != ISC_R_SUCCESS)
7937                 goto cleanup;
7938
7939         message->opcode = dns_opcode_query;
7940         message->rdclass = zone->rdclass;
7941
7942         result = dns_message_gettempname(message, &qname);
7943         if (result != ISC_R_SUCCESS)
7944                 goto cleanup;
7945
7946         result = dns_message_gettemprdataset(message, &qrdataset);
7947         if (result != ISC_R_SUCCESS)
7948                 goto cleanup;
7949
7950         /*
7951          * Make question.
7952          */
7953         dns_name_init(qname, NULL);
7954         dns_name_clone(&zone->origin, qname);
7955         dns_rdataset_init(qrdataset);
7956         dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
7957         ISC_LIST_APPEND(qname->list, qrdataset, link);
7958         dns_message_addname(message, qname, DNS_SECTION_QUESTION);
7959
7960         *messagep = message;
7961         return (ISC_R_SUCCESS);
7962
7963  cleanup:
7964         if (qname != NULL)
7965                 dns_message_puttempname(message, &qname);
7966         if (qrdataset != NULL)
7967                 dns_message_puttemprdataset(message, &qrdataset);
7968         if (message != NULL)
7969                 dns_message_destroy(&message);
7970         return (result);
7971 }
7972
7973 static isc_result_t
7974 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
7975         dns_rdataset_t *rdataset = NULL;
7976         dns_rdatalist_t *rdatalist = NULL;
7977         dns_rdata_t *rdata = NULL;
7978         isc_result_t result;
7979
7980         result = dns_message_gettemprdatalist(message, &rdatalist);
7981         if (result != ISC_R_SUCCESS)
7982                 goto cleanup;
7983         result = dns_message_gettemprdata(message, &rdata);
7984         if (result != ISC_R_SUCCESS)
7985                 goto cleanup;
7986         result = dns_message_gettemprdataset(message, &rdataset);
7987         if (result != ISC_R_SUCCESS)
7988                 goto cleanup;
7989         dns_rdataset_init(rdataset);
7990
7991         rdatalist->type = dns_rdatatype_opt;
7992         rdatalist->covers = 0;
7993
7994         /*
7995          * Set Maximum UDP buffer size.
7996          */
7997         rdatalist->rdclass = udpsize;
7998
7999         /*
8000          * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
8001          */
8002         rdatalist->ttl = 0;
8003
8004         /* Set EDNS options if applicable */
8005         if (reqnsid) {
8006                 unsigned char data[4];
8007                 isc_buffer_t buf;
8008
8009                 isc_buffer_init(&buf, data, sizeof(data));
8010                 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
8011                 isc_buffer_putuint16(&buf, 0);
8012                 rdata->data = data;
8013                 rdata->length = sizeof(data);
8014         } else {
8015                 rdata->data = NULL;
8016                 rdata->length = 0;
8017         }
8018
8019         rdata->rdclass = rdatalist->rdclass;
8020         rdata->type = rdatalist->type;
8021         rdata->flags = 0;
8022
8023         ISC_LIST_INIT(rdatalist->rdata);
8024         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
8025         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
8026                       == ISC_R_SUCCESS);
8027
8028         return (dns_message_setopt(message, rdataset));
8029
8030  cleanup:
8031         if (rdatalist != NULL)
8032                 dns_message_puttemprdatalist(message, &rdatalist);
8033         if (rdataset != NULL)
8034                 dns_message_puttemprdataset(message, &rdataset);
8035         if (rdata != NULL)
8036                 dns_message_puttemprdata(message, &rdata);
8037
8038         return (result);
8039 }
8040
8041 static void
8042 soa_query(isc_task_t *task, isc_event_t *event) {
8043         const char me[] = "soa_query";
8044         isc_result_t result = ISC_R_FAILURE;
8045         dns_message_t *message = NULL;
8046         dns_zone_t *zone = event->ev_arg;
8047         dns_zone_t *dummy = NULL;
8048         isc_netaddr_t masterip;
8049         dns_tsigkey_t *key = NULL;
8050         isc_uint32_t options;
8051         isc_boolean_t cancel = ISC_TRUE;
8052         int timeout;
8053         isc_boolean_t have_xfrsource, reqnsid;
8054         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
8055
8056         REQUIRE(DNS_ZONE_VALID(zone));
8057
8058         UNUSED(task);
8059
8060         ENTER;
8061
8062         LOCK_ZONE(zone);
8063         if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
8064             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
8065             zone->view->requestmgr == NULL) {
8066                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8067                         cancel = ISC_FALSE;
8068                 goto cleanup;
8069         }
8070
8071         /*
8072          * XXX Optimisation: Create message when zone is setup and reuse.
8073          */
8074         result = create_query(zone, dns_rdatatype_soa, &message);
8075         if (result != ISC_R_SUCCESS)
8076                 goto cleanup;
8077
8078  again:
8079         INSIST(zone->masterscnt > 0);
8080         INSIST(zone->curmaster < zone->masterscnt);
8081
8082         zone->masteraddr = zone->masters[zone->curmaster];
8083
8084         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
8085         /*
8086          * First, look for a tsig key in the master statement, then
8087          * try for a server key.
8088          */
8089         if ((zone->masterkeynames != NULL) &&
8090             (zone->masterkeynames[zone->curmaster] != NULL)) {
8091                 dns_view_t *view = dns_zone_getview(zone);
8092                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
8093                 result = dns_view_gettsig(view, keyname, &key);
8094                 if (result != ISC_R_SUCCESS) {
8095                         char namebuf[DNS_NAME_FORMATSIZE];
8096                         dns_name_format(keyname, namebuf, sizeof(namebuf));
8097                         dns_zone_log(zone, ISC_LOG_ERROR,
8098                                      "unable to find key: %s", namebuf);
8099                         goto skip_master;
8100                 }
8101         }
8102         if (key == NULL) {
8103                 result = dns_view_getpeertsig(zone->view, &masterip, &key);
8104                 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
8105                         char addrbuf[ISC_NETADDR_FORMATSIZE];
8106                         isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
8107                         dns_zone_log(zone, ISC_LOG_ERROR,
8108                                      "unable to find TSIG key for %s", addrbuf);
8109                         goto skip_master;
8110                 }
8111         }
8112
8113         have_xfrsource = ISC_FALSE;
8114         reqnsid = zone->view->requestnsid;
8115         if (zone->view->peers != NULL) {
8116                 dns_peer_t *peer = NULL;
8117                 isc_boolean_t edns;
8118                 result = dns_peerlist_peerbyaddr(zone->view->peers,
8119                                                  &masterip, &peer);
8120                 if (result == ISC_R_SUCCESS) {
8121                         result = dns_peer_getsupportedns(peer, &edns);
8122                         if (result == ISC_R_SUCCESS && !edns)
8123                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
8124                         result = dns_peer_gettransfersource(peer,
8125                                                             &zone->sourceaddr);
8126                         if (result == ISC_R_SUCCESS)
8127                                 have_xfrsource = ISC_TRUE;
8128                         if (zone->view->resolver != NULL)
8129                                 udpsize =
8130                                   dns_resolver_getudpsize(zone->view->resolver);
8131                         (void)dns_peer_getudpsize(peer, &udpsize);
8132                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
8133                 }
8134         }
8135
8136         switch (isc_sockaddr_pf(&zone->masteraddr)) {
8137         case PF_INET:
8138                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
8139                         if (isc_sockaddr_equal(&zone->altxfrsource4,
8140                                                &zone->xfrsource4))
8141                                 goto skip_master;
8142                         zone->sourceaddr = zone->altxfrsource4;
8143                 } else if (!have_xfrsource)
8144                         zone->sourceaddr = zone->xfrsource4;
8145                 break;
8146         case PF_INET6:
8147                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
8148                         if (isc_sockaddr_equal(&zone->altxfrsource6,
8149                                                &zone->xfrsource6))
8150                                 goto skip_master;
8151                         zone->sourceaddr = zone->altxfrsource6;
8152                 } else if (!have_xfrsource)
8153                         zone->sourceaddr = zone->xfrsource6;
8154                 break;
8155         default:
8156                 result = ISC_R_NOTIMPLEMENTED;
8157                 goto cleanup;
8158         }
8159
8160         options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
8161                   DNS_REQUESTOPT_TCP : 0;
8162
8163         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
8164                 result = add_opt(message, udpsize, reqnsid);
8165                 if (result != ISC_R_SUCCESS)
8166                         zone_debuglog(zone, me, 1,
8167                                       "unable to add opt record: %s",
8168                                       dns_result_totext(result));
8169         }
8170
8171         zone_iattach(zone, &dummy);
8172         timeout = 15;
8173         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
8174                 timeout = 30;
8175         result = dns_request_createvia2(zone->view->requestmgr, message,
8176                                         &zone->sourceaddr, &zone->masteraddr,
8177                                         options, key, timeout * 3, timeout,
8178                                         zone->task, refresh_callback, zone,
8179                                         &zone->request);
8180         if (result != ISC_R_SUCCESS) {
8181                 zone_idetach(&dummy);
8182                 zone_debuglog(zone, me, 1,
8183                               "dns_request_createvia2() failed: %s",
8184                               dns_result_totext(result));
8185                 goto cleanup;
8186         } else {
8187                 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
8188                         inc_stats(zone, dns_zonestatscounter_soaoutv4);
8189                 else
8190                         inc_stats(zone, dns_zonestatscounter_soaoutv6);
8191         }
8192         cancel = ISC_FALSE;
8193
8194  cleanup:
8195         if (key != NULL)
8196                 dns_tsigkey_detach(&key);
8197         if (result != ISC_R_SUCCESS)
8198                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
8199         if (message != NULL)
8200                 dns_message_destroy(&message);
8201         if (cancel)
8202                 cancel_refresh(zone);
8203         isc_event_free(&event);
8204         UNLOCK_ZONE(zone);
8205         dns_zone_idetach(&zone);
8206         return;
8207
8208  skip_master:
8209         if (key != NULL)
8210                 dns_tsigkey_detach(&key);
8211         /*
8212          * Skip to next failed / untried master.
8213          */
8214         do {
8215                 zone->curmaster++;
8216         } while (zone->curmaster < zone->masterscnt &&
8217                  zone->mastersok[zone->curmaster]);
8218         if (zone->curmaster < zone->masterscnt)
8219                 goto again;
8220         zone->curmaster = 0;
8221         goto cleanup;
8222 }
8223
8224 static void
8225 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
8226         const char me[] = "ns_query";
8227         isc_result_t result;
8228         dns_message_t *message = NULL;
8229         isc_netaddr_t masterip;
8230         dns_tsigkey_t *key = NULL;
8231         dns_dbnode_t *node = NULL;
8232         int timeout;
8233         isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
8234         isc_uint16_t udpsize = SEND_BUFFER_SIZE;
8235
8236         REQUIRE(DNS_ZONE_VALID(zone));
8237         REQUIRE(LOCKED_ZONE(zone));
8238         REQUIRE((soardataset != NULL && stub == NULL) ||
8239                 (soardataset == NULL && stub != NULL));
8240         REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
8241
8242         ENTER;
8243
8244         if (stub == NULL) {
8245                 stub = isc_mem_get(zone->mctx, sizeof(*stub));
8246                 if (stub == NULL)
8247                         goto cleanup;
8248                 stub->magic = STUB_MAGIC;
8249                 stub->mctx = zone->mctx;
8250                 stub->zone = NULL;
8251                 stub->db = NULL;
8252                 stub->version = NULL;
8253
8254                 /*
8255                  * Attach so that the zone won't disappear from under us.
8256                  */
8257                 zone_iattach(zone, &stub->zone);
8258
8259                 /*
8260                  * If a db exists we will update it, otherwise we create a
8261                  * new one and attach it to the zone once we have the NS
8262                  * RRset and glue.
8263                  */
8264                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8265                 if (zone->db != NULL) {
8266                         dns_db_attach(zone->db, &stub->db);
8267                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8268                 } else {
8269                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8270
8271                         INSIST(zone->db_argc >= 1);
8272                         result = dns_db_create(zone->mctx, zone->db_argv[0],
8273                                                &zone->origin, dns_dbtype_stub,
8274                                                zone->rdclass,
8275                                                zone->db_argc - 1,
8276                                                zone->db_argv + 1,
8277                                                &stub->db);
8278                         if (result != ISC_R_SUCCESS) {
8279                                 dns_zone_log(zone, ISC_LOG_ERROR,
8280                                              "refreshing stub: "
8281                                              "could not create "
8282                                              "database: %s",
8283                                              dns_result_totext(result));
8284                                 goto cleanup;
8285                         }
8286                         dns_db_settask(stub->db, zone->task);
8287                 }
8288
8289                 dns_db_newversion(stub->db, &stub->version);
8290
8291                 /*
8292                  * Update SOA record.
8293                  */
8294                 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
8295                                          &node);
8296                 if (result != ISC_R_SUCCESS) {
8297                         dns_zone_log(zone, ISC_LOG_INFO,
8298                                      "refreshing stub: "
8299                                      "dns_db_findnode() failed: %s",
8300                                      dns_result_totext(result));
8301                         goto cleanup;
8302                 }
8303
8304                 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
8305                                             soardataset, 0, NULL);
8306                 dns_db_detachnode(stub->db, &node);
8307                 if (result != ISC_R_SUCCESS) {
8308                         dns_zone_log(zone, ISC_LOG_INFO,
8309                                      "refreshing stub: "
8310                                      "dns_db_addrdataset() failed: %s",
8311                                      dns_result_totext(result));
8312                         goto cleanup;
8313                 }
8314         }
8315
8316         /*
8317          * XXX Optimisation: Create message when zone is setup and reuse.
8318          */
8319         result = create_query(zone, dns_rdatatype_ns, &message);
8320         INSIST(result == ISC_R_SUCCESS);
8321
8322         INSIST(zone->masterscnt > 0);
8323         INSIST(zone->curmaster < zone->masterscnt);
8324         zone->masteraddr = zone->masters[zone->curmaster];
8325
8326         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
8327         /*
8328          * First, look for a tsig key in the master statement, then
8329          * try for a server key.
8330          */
8331         if ((zone->masterkeynames != NULL) &&
8332             (zone->masterkeynames[zone->curmaster] != NULL)) {
8333                 dns_view_t *view = dns_zone_getview(zone);
8334                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
8335                 result = dns_view_gettsig(view, keyname, &key);
8336                 if (result != ISC_R_SUCCESS) {
8337                         char namebuf[DNS_NAME_FORMATSIZE];
8338                         dns_name_format(keyname, namebuf, sizeof(namebuf));
8339                         dns_zone_log(zone, ISC_LOG_ERROR,
8340                                      "unable to find key: %s", namebuf);
8341                 }
8342         }
8343         if (key == NULL)
8344                 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
8345
8346         reqnsid = zone->view->requestnsid;
8347         if (zone->view->peers != NULL) {
8348                 dns_peer_t *peer = NULL;
8349                 isc_boolean_t edns;
8350                 result = dns_peerlist_peerbyaddr(zone->view->peers,
8351                                                  &masterip, &peer);
8352                 if (result == ISC_R_SUCCESS) {
8353                         result = dns_peer_getsupportedns(peer, &edns);
8354                         if (result == ISC_R_SUCCESS && !edns)
8355                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
8356                         result = dns_peer_gettransfersource(peer,
8357                                                             &zone->sourceaddr);
8358                         if (result == ISC_R_SUCCESS)
8359                                 have_xfrsource = ISC_TRUE;
8360                         if (zone->view->resolver != NULL)
8361                                 udpsize =
8362                                   dns_resolver_getudpsize(zone->view->resolver);
8363                         (void)dns_peer_getudpsize(peer, &udpsize);
8364                         (void)dns_peer_getrequestnsid(peer, &reqnsid);
8365                 }
8366
8367         }
8368         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
8369                 result = add_opt(message, udpsize, reqnsid);
8370                 if (result != ISC_R_SUCCESS)
8371                         zone_debuglog(zone, me, 1,
8372                                       "unable to add opt record: %s",
8373                                       dns_result_totext(result));
8374         }
8375
8376         /*
8377          * Always use TCP so that we shouldn't truncate in additional section.
8378          */
8379         switch (isc_sockaddr_pf(&zone->masteraddr)) {
8380         case PF_INET:
8381                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
8382                         zone->sourceaddr = zone->altxfrsource4;
8383                 else if (!have_xfrsource)
8384                         zone->sourceaddr = zone->xfrsource4;
8385                 break;
8386         case PF_INET6:
8387                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
8388                         zone->sourceaddr = zone->altxfrsource6;
8389                 else if (!have_xfrsource)
8390                         zone->sourceaddr = zone->xfrsource6;
8391                 break;
8392         default:
8393                 result = ISC_R_NOTIMPLEMENTED;
8394                 POST(result);
8395                 goto cleanup;
8396         }
8397         timeout = 15;
8398         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
8399                 timeout = 30;
8400         result = dns_request_createvia2(zone->view->requestmgr, message,
8401                                         &zone->sourceaddr, &zone->masteraddr,
8402                                         DNS_REQUESTOPT_TCP, key, timeout * 3,
8403                                         timeout, zone->task, stub_callback,
8404                                         stub, &zone->request);
8405         if (result != ISC_R_SUCCESS) {
8406                 zone_debuglog(zone, me, 1,
8407                               "dns_request_createvia() failed: %s",
8408                               dns_result_totext(result));
8409                 goto cleanup;
8410         }
8411         dns_message_destroy(&message);
8412         goto unlock;
8413
8414  cleanup:
8415         cancel_refresh(zone);
8416         if (stub != NULL) {
8417                 stub->magic = 0;
8418                 if (stub->version != NULL)
8419                         dns_db_closeversion(stub->db, &stub->version,
8420                                             ISC_FALSE);
8421                 if (stub->db != NULL)
8422                         dns_db_detach(&stub->db);
8423                 if (stub->zone != NULL)
8424                         zone_idetach(&stub->zone);
8425                 isc_mem_put(stub->mctx, stub, sizeof(*stub));
8426         }
8427         if (message != NULL)
8428                 dns_message_destroy(&message);
8429  unlock:
8430         if (key != NULL)
8431                 dns_tsigkey_detach(&key);
8432         return;
8433 }
8434
8435 /*
8436  * Handle the control event.  Note that although this event causes the zone
8437  * to shut down, it is not a shutdown event in the sense of the task library.
8438  */
8439 static void
8440 zone_shutdown(isc_task_t *task, isc_event_t *event) {
8441         dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
8442         isc_boolean_t free_needed, linked = ISC_FALSE;
8443
8444         UNUSED(task);
8445         REQUIRE(DNS_ZONE_VALID(zone));
8446         INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
8447         INSIST(isc_refcount_current(&zone->erefs) == 0);
8448
8449         zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
8450
8451         /*
8452          * Stop things being restarted after we cancel them below.
8453          */
8454         LOCK_ZONE(zone);
8455         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
8456         UNLOCK_ZONE(zone);
8457
8458         /*
8459          * If we were waiting for xfrin quota, step out of
8460          * the queue.
8461          * If there's no zone manager, we can't be waiting for the
8462          * xfrin quota
8463          */
8464         if (zone->zmgr != NULL) {
8465                 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
8466                 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
8467                         ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
8468                                         statelink);
8469                         linked = ISC_TRUE;
8470                         zone->statelist = NULL;
8471                 }
8472                 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
8473         }
8474
8475         /*
8476          * In task context, no locking required.  See zone_xfrdone().
8477          */
8478         if (zone->xfr != NULL)
8479                 dns_xfrin_shutdown(zone->xfr);
8480
8481         LOCK_ZONE(zone);
8482         if (linked) {
8483                 INSIST(zone->irefs > 0);
8484                 zone->irefs--;
8485         }
8486         if (zone->request != NULL) {
8487                 dns_request_cancel(zone->request);
8488         }
8489
8490         if (zone->readio != NULL)
8491                 zonemgr_cancelio(zone->readio);
8492
8493         if (zone->lctx != NULL)
8494                 dns_loadctx_cancel(zone->lctx);
8495
8496         if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
8497             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8498                 if (zone->writeio != NULL)
8499                         zonemgr_cancelio(zone->writeio);
8500
8501                 if (zone->dctx != NULL)
8502                         dns_dumpctx_cancel(zone->dctx);
8503         }
8504
8505         notify_cancel(zone);
8506
8507         forward_cancel(zone);
8508
8509         if (zone->timer != NULL) {
8510                 isc_timer_detach(&zone->timer);
8511                 INSIST(zone->irefs > 0);
8512                 zone->irefs--;
8513         }
8514
8515         if (zone->view != NULL)
8516                 dns_view_weakdetach(&zone->view);
8517
8518         /*
8519          * We have now canceled everything set the flag to allow exit_check()
8520          * to succeed.  We must not unlock between setting this flag and
8521          * calling exit_check().
8522          */
8523         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
8524         free_needed = exit_check(zone);
8525         UNLOCK_ZONE(zone);
8526         if (free_needed)
8527                 zone_free(zone);
8528 }
8529
8530 static void
8531 zone_timer(isc_task_t *task, isc_event_t *event) {
8532         const char me[] = "zone_timer";
8533         dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
8534
8535         UNUSED(task);
8536         REQUIRE(DNS_ZONE_VALID(zone));
8537
8538         ENTER;
8539
8540         zone_maintenance(zone);
8541
8542         isc_event_free(&event);
8543 }
8544
8545 static void
8546 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
8547         const char me[] = "zone_settimer";
8548         isc_time_t next;
8549         isc_result_t result;
8550
8551         REQUIRE(DNS_ZONE_VALID(zone));
8552         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
8553                 return;
8554
8555         isc_time_settoepoch(&next);
8556
8557         switch (zone->type) {
8558         case dns_zone_master:
8559                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
8560                         next = zone->notifytime;
8561                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8562                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8563                         INSIST(!isc_time_isepoch(&zone->dumptime));
8564                         if (isc_time_isepoch(&next) ||
8565                             isc_time_compare(&zone->dumptime, &next) < 0)
8566                                 next = zone->dumptime;
8567                 }
8568                 if (!isc_time_isepoch(&zone->resigntime)) {
8569                         if (isc_time_isepoch(&next) ||
8570                             isc_time_compare(&zone->resigntime, &next) < 0)
8571                                 next = zone->resigntime;
8572                 }
8573                 if (!isc_time_isepoch(&zone->keywarntime)) {
8574                         if (isc_time_isepoch(&next) ||
8575                             isc_time_compare(&zone->keywarntime, &next) < 0)
8576                                 next = zone->keywarntime;
8577                 }
8578                 if (!isc_time_isepoch(&zone->signingtime)) {
8579                         if (isc_time_isepoch(&next) ||
8580                             isc_time_compare(&zone->signingtime, &next) < 0)
8581                                 next = zone->signingtime;
8582                 }
8583                 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
8584                         if (isc_time_isepoch(&next) ||
8585                             isc_time_compare(&zone->nsec3chaintime, &next) < 0)
8586                                 next = zone->nsec3chaintime;
8587                 }
8588                 break;
8589
8590         case dns_zone_slave:
8591                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
8592                         next = zone->notifytime;
8593                 /*FALLTHROUGH*/
8594
8595         case dns_zone_stub:
8596                 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
8597                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
8598                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
8599                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
8600                         INSIST(!isc_time_isepoch(&zone->refreshtime));
8601                         if (isc_time_isepoch(&next) ||
8602                             isc_time_compare(&zone->refreshtime, &next) < 0)
8603                                 next = zone->refreshtime;
8604                 }
8605                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8606                         INSIST(!isc_time_isepoch(&zone->expiretime));
8607                         if (isc_time_isepoch(&next) ||
8608                             isc_time_compare(&zone->expiretime, &next) < 0)
8609                                 next = zone->expiretime;
8610                 }
8611                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8612                     !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
8613                         INSIST(!isc_time_isepoch(&zone->dumptime));
8614                         if (isc_time_isepoch(&next) ||
8615                             isc_time_compare(&zone->dumptime, &next) < 0)
8616                                 next = zone->dumptime;
8617                 }
8618                 break;
8619
8620         default:
8621                 break;
8622         }
8623
8624         if (isc_time_isepoch(&next)) {
8625                 zone_debuglog(zone, me, 10, "settimer inactive");
8626                 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
8627                                           NULL, NULL, ISC_TRUE);
8628                 if (result != ISC_R_SUCCESS)
8629                         dns_zone_log(zone, ISC_LOG_ERROR,
8630                                      "could not deactivate zone timer: %s",
8631                                      isc_result_totext(result));
8632         } else {
8633                 if (isc_time_compare(&next, now) <= 0)
8634                         next = *now;
8635                 result = isc_timer_reset(zone->timer, isc_timertype_once,
8636                                          &next, NULL, ISC_TRUE);
8637                 if (result != ISC_R_SUCCESS)
8638                         dns_zone_log(zone, ISC_LOG_ERROR,
8639                                      "could not reset zone timer: %s",
8640                                      isc_result_totext(result));
8641         }
8642 }
8643
8644 static void
8645 cancel_refresh(dns_zone_t *zone) {
8646         const char me[] = "cancel_refresh";
8647         isc_time_t now;
8648
8649         /*
8650          * 'zone' locked by caller.
8651          */
8652
8653         REQUIRE(DNS_ZONE_VALID(zone));
8654         REQUIRE(LOCKED_ZONE(zone));
8655
8656         ENTER;
8657
8658         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
8659         TIME_NOW(&now);
8660         zone_settimer(zone, &now);
8661 }
8662
8663 static isc_result_t
8664 notify_createmessage(dns_zone_t *zone, unsigned int flags,
8665                      dns_message_t **messagep)
8666 {
8667         dns_db_t *zonedb = NULL;
8668         dns_dbnode_t *node = NULL;
8669         dns_dbversion_t *version = NULL;
8670         dns_message_t *message = NULL;
8671         dns_rdataset_t rdataset;
8672         dns_rdata_t rdata = DNS_RDATA_INIT;
8673
8674         dns_name_t *tempname = NULL;
8675         dns_rdata_t *temprdata = NULL;
8676         dns_rdatalist_t *temprdatalist = NULL;
8677         dns_rdataset_t *temprdataset = NULL;
8678
8679         isc_result_t result;
8680         isc_region_t r;
8681         isc_buffer_t *b = NULL;
8682
8683         REQUIRE(DNS_ZONE_VALID(zone));
8684         REQUIRE(messagep != NULL && *messagep == NULL);
8685
8686         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
8687                                     &message);
8688         if (result != ISC_R_SUCCESS)
8689                 return (result);
8690
8691         message->opcode = dns_opcode_notify;
8692         message->flags |= DNS_MESSAGEFLAG_AA;
8693         message->rdclass = zone->rdclass;
8694
8695         result = dns_message_gettempname(message, &tempname);
8696         if (result != ISC_R_SUCCESS)
8697                 goto cleanup;
8698
8699         result = dns_message_gettemprdataset(message, &temprdataset);
8700         if (result != ISC_R_SUCCESS)
8701                 goto cleanup;
8702
8703         /*
8704          * Make question.
8705          */
8706         dns_name_init(tempname, NULL);
8707         dns_name_clone(&zone->origin, tempname);
8708         dns_rdataset_init(temprdataset);
8709         dns_rdataset_makequestion(temprdataset, zone->rdclass,
8710                                   dns_rdatatype_soa);
8711         ISC_LIST_APPEND(tempname->list, temprdataset, link);
8712         dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
8713         tempname = NULL;
8714         temprdataset = NULL;
8715
8716         if ((flags & DNS_NOTIFY_NOSOA) != 0)
8717                 goto done;
8718
8719         result = dns_message_gettempname(message, &tempname);
8720         if (result != ISC_R_SUCCESS)
8721                 goto soa_cleanup;
8722         result = dns_message_gettemprdata(message, &temprdata);
8723         if (result != ISC_R_SUCCESS)
8724                 goto soa_cleanup;
8725         result = dns_message_gettemprdataset(message, &temprdataset);
8726         if (result != ISC_R_SUCCESS)
8727                 goto soa_cleanup;
8728         result = dns_message_gettemprdatalist(message, &temprdatalist);
8729         if (result != ISC_R_SUCCESS)
8730                 goto soa_cleanup;
8731
8732         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8733         INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
8734         dns_db_attach(zone->db, &zonedb);
8735         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8736
8737         dns_name_init(tempname, NULL);
8738         dns_name_clone(&zone->origin, tempname);
8739         dns_db_currentversion(zonedb, &version);
8740         result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
8741         if (result != ISC_R_SUCCESS)
8742                 goto soa_cleanup;
8743
8744         dns_rdataset_init(&rdataset);
8745         result = dns_db_findrdataset(zonedb, node, version,
8746                                      dns_rdatatype_soa,
8747                                      dns_rdatatype_none, 0, &rdataset,
8748                                      NULL);
8749         if (result != ISC_R_SUCCESS)
8750                 goto soa_cleanup;
8751         result = dns_rdataset_first(&rdataset);
8752         if (result != ISC_R_SUCCESS)
8753                 goto soa_cleanup;
8754         dns_rdataset_current(&rdataset, &rdata);
8755         dns_rdata_toregion(&rdata, &r);
8756         result = isc_buffer_allocate(zone->mctx, &b, r.length);
8757         if (result != ISC_R_SUCCESS)
8758                 goto soa_cleanup;
8759         isc_buffer_putmem(b, r.base, r.length);
8760         isc_buffer_usedregion(b, &r);
8761         dns_rdata_init(temprdata);
8762         dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
8763         dns_message_takebuffer(message, &b);
8764         result = dns_rdataset_next(&rdataset);
8765         dns_rdataset_disassociate(&rdataset);
8766         if (result != ISC_R_NOMORE)
8767                 goto soa_cleanup;
8768         temprdatalist->rdclass = rdata.rdclass;
8769         temprdatalist->type = rdata.type;
8770         temprdatalist->covers = 0;
8771         temprdatalist->ttl = rdataset.ttl;
8772         ISC_LIST_INIT(temprdatalist->rdata);
8773         ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
8774
8775         dns_rdataset_init(temprdataset);
8776         result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
8777         if (result != ISC_R_SUCCESS)
8778                 goto soa_cleanup;
8779
8780         ISC_LIST_APPEND(tempname->list, temprdataset, link);
8781         dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
8782         temprdatalist = NULL;
8783         temprdataset = NULL;
8784         temprdata = NULL;
8785         tempname = NULL;
8786
8787  soa_cleanup:
8788         if (node != NULL)
8789                 dns_db_detachnode(zonedb, &node);
8790         if (version != NULL)
8791                 dns_db_closeversion(zonedb, &version, ISC_FALSE);
8792         if (zonedb != NULL)
8793                 dns_db_detach(&zonedb);
8794         if (tempname != NULL)
8795                 dns_message_puttempname(message, &tempname);
8796         if (temprdata != NULL)
8797                 dns_message_puttemprdata(message, &temprdata);
8798         if (temprdataset != NULL)
8799                 dns_message_puttemprdataset(message, &temprdataset);
8800         if (temprdatalist != NULL)
8801                 dns_message_puttemprdatalist(message, &temprdatalist);
8802
8803  done:
8804         *messagep = message;
8805         return (ISC_R_SUCCESS);
8806
8807  cleanup:
8808         if (tempname != NULL)
8809                 dns_message_puttempname(message, &tempname);
8810         if (temprdataset != NULL)
8811                 dns_message_puttemprdataset(message, &temprdataset);
8812         dns_message_destroy(&message);
8813         return (result);
8814 }
8815
8816 isc_result_t
8817 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
8818                        dns_message_t *msg)
8819 {
8820         unsigned int i;
8821         dns_rdata_soa_t soa;
8822         dns_rdataset_t *rdataset = NULL;
8823         dns_rdata_t rdata = DNS_RDATA_INIT;
8824         isc_result_t result;
8825         char fromtext[ISC_SOCKADDR_FORMATSIZE];
8826         int match = 0;
8827         isc_netaddr_t netaddr;
8828         isc_sockaddr_t local, remote;
8829
8830         REQUIRE(DNS_ZONE_VALID(zone));
8831
8832         /*
8833          * If type != T_SOA return DNS_R_REFUSED.  We don't yet support
8834          * ROLLOVER.
8835          *
8836          * SOA: RFC1996
8837          * Check that 'from' is a valid notify source, (zone->masters).
8838          *      Return DNS_R_REFUSED if not.
8839          *
8840          * If the notify message contains a serial number check it
8841          * against the zones serial and return if <= current serial
8842          *
8843          * If a refresh check is progress, if so just record the
8844          * fact we received a NOTIFY and from where and return.
8845          * We will perform a new refresh check when the current one
8846          * completes. Return ISC_R_SUCCESS.
8847          *
8848          * Otherwise initiate a refresh check using 'from' as the
8849          * first address to check.  Return ISC_R_SUCCESS.
8850          */
8851
8852         isc_sockaddr_format(from, fromtext, sizeof(fromtext));
8853
8854         /*
8855          *  We only handle NOTIFY (SOA) at the present.
8856          */
8857         LOCK_ZONE(zone);
8858         if (isc_sockaddr_pf(from) == PF_INET)
8859                 inc_stats(zone, dns_zonestatscounter_notifyinv4);
8860         else
8861                 inc_stats(zone, dns_zonestatscounter_notifyinv6);
8862         if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
8863             dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
8864                                  dns_rdatatype_soa, dns_rdatatype_none,
8865                                  NULL, NULL) != ISC_R_SUCCESS) {
8866                 UNLOCK_ZONE(zone);
8867                 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
8868                         dns_zone_log(zone, ISC_LOG_NOTICE,
8869                                      "NOTIFY with no "
8870                                      "question section from: %s", fromtext);
8871                         return (DNS_R_FORMERR);
8872                 }
8873                 dns_zone_log(zone, ISC_LOG_NOTICE,
8874                              "NOTIFY zone does not match");
8875                 return (DNS_R_NOTIMP);
8876         }
8877
8878         /*
8879          * If we are a master zone just succeed.
8880          */
8881         if (zone->type == dns_zone_master) {
8882                 UNLOCK_ZONE(zone);
8883                 return (ISC_R_SUCCESS);
8884         }
8885
8886         isc_netaddr_fromsockaddr(&netaddr, from);
8887         for (i = 0; i < zone->masterscnt; i++) {
8888                 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
8889                         break;
8890                 if (zone->view->aclenv.match_mapped &&
8891                     IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
8892                     isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
8893                         isc_netaddr_t na1, na2;
8894                         isc_netaddr_fromv4mapped(&na1, &netaddr);
8895                         isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
8896                         if (isc_netaddr_equal(&na1, &na2))
8897                                 break;
8898                 }
8899         }
8900
8901         /*
8902          * Accept notify requests from non masters if they are on
8903          * 'zone->notify_acl'.
8904          */
8905         if (i >= zone->masterscnt && zone->notify_acl != NULL &&
8906             dns_acl_match(&netaddr, NULL, zone->notify_acl,
8907                           &zone->view->aclenv,
8908                           &match, NULL) == ISC_R_SUCCESS &&
8909             match > 0)
8910         {
8911                 /* Accept notify. */
8912         } else if (i >= zone->masterscnt) {
8913                 UNLOCK_ZONE(zone);
8914                 dns_zone_log(zone, ISC_LOG_INFO,
8915                              "refused notify from non-master: %s", fromtext);
8916                 inc_stats(zone, dns_zonestatscounter_notifyrej);
8917                 return (DNS_R_REFUSED);
8918         }
8919
8920         /*
8921          * If the zone is loaded and there are answers check the serial
8922          * to see if we need to do a refresh.  Do not worry about this
8923          * check if we are a dialup zone as we use the notify request
8924          * to trigger a refresh check.
8925          */
8926         if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
8927             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
8928             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
8929                 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
8930                                               &zone->origin,
8931                                               dns_rdatatype_soa,
8932                                               dns_rdatatype_none, NULL,
8933                                               &rdataset);
8934                 if (result == ISC_R_SUCCESS)
8935                         result = dns_rdataset_first(rdataset);
8936                 if (result == ISC_R_SUCCESS) {
8937                         isc_uint32_t serial = 0, oldserial;
8938
8939                         dns_rdataset_current(rdataset, &rdata);
8940                         result = dns_rdata_tostruct(&rdata, &soa, NULL);
8941                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8942                         serial = soa.serial;
8943                         /*
8944                          * The following should safely be performed without DB
8945                          * lock and succeed in this context.
8946                          */
8947                         result = zone_get_from_db(zone, zone->db, NULL, NULL,
8948                                                   &oldserial, NULL, NULL, NULL,
8949                                                   NULL, NULL);
8950                         RUNTIME_CHECK(result == ISC_R_SUCCESS);
8951                         if (isc_serial_le(serial, oldserial)) {
8952                           dns_zone_log(zone, ISC_LOG_INFO,
8953                                              "notify from %s: "
8954                                              "zone is up to date",
8955                                              fromtext);
8956                                 UNLOCK_ZONE(zone);
8957                                 return (ISC_R_SUCCESS);
8958                         }
8959                 }
8960         }
8961
8962         /*
8963          * If we got this far and there was a refresh in progress just
8964          * let it complete.  Record where we got the notify from so we
8965          * can perform a refresh check when the current one completes
8966          */
8967         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
8968                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
8969                 zone->notifyfrom = *from;
8970                 UNLOCK_ZONE(zone);
8971                 dns_zone_log(zone, ISC_LOG_INFO,
8972                              "notify from %s: refresh in progress, "
8973                              "refresh check queued",
8974                              fromtext);
8975                 return (ISC_R_SUCCESS);
8976         }
8977         zone->notifyfrom = *from;
8978         local = zone->masteraddr;
8979         remote = zone->sourceaddr;
8980         UNLOCK_ZONE(zone);
8981         dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
8982         dns_zone_refresh(zone);
8983         return (ISC_R_SUCCESS);
8984 }
8985
8986 void
8987 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
8988
8989         REQUIRE(DNS_ZONE_VALID(zone));
8990
8991         LOCK_ZONE(zone);
8992         if (zone->notify_acl != NULL)
8993                 dns_acl_detach(&zone->notify_acl);
8994         dns_acl_attach(acl, &zone->notify_acl);
8995         UNLOCK_ZONE(zone);
8996 }
8997
8998 void
8999 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
9000
9001         REQUIRE(DNS_ZONE_VALID(zone));
9002
9003         LOCK_ZONE(zone);
9004         if (zone->query_acl != NULL)
9005                 dns_acl_detach(&zone->query_acl);
9006         dns_acl_attach(acl, &zone->query_acl);
9007         UNLOCK_ZONE(zone);
9008 }
9009
9010 void
9011 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
9012
9013         REQUIRE(DNS_ZONE_VALID(zone));
9014
9015         LOCK_ZONE(zone);
9016         if (zone->queryon_acl != NULL)
9017                 dns_acl_detach(&zone->queryon_acl);
9018         dns_acl_attach(acl, &zone->queryon_acl);
9019         UNLOCK_ZONE(zone);
9020 }
9021
9022 void
9023 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
9024
9025         REQUIRE(DNS_ZONE_VALID(zone));
9026
9027         LOCK_ZONE(zone);
9028         if (zone->update_acl != NULL)
9029                 dns_acl_detach(&zone->update_acl);
9030         dns_acl_attach(acl, &zone->update_acl);
9031         UNLOCK_ZONE(zone);
9032 }
9033
9034 void
9035 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
9036
9037         REQUIRE(DNS_ZONE_VALID(zone));
9038
9039         LOCK_ZONE(zone);
9040         if (zone->forward_acl != NULL)
9041                 dns_acl_detach(&zone->forward_acl);
9042         dns_acl_attach(acl, &zone->forward_acl);
9043         UNLOCK_ZONE(zone);
9044 }
9045
9046 void
9047 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
9048
9049         REQUIRE(DNS_ZONE_VALID(zone));
9050
9051         LOCK_ZONE(zone);
9052         if (zone->xfr_acl != NULL)
9053                 dns_acl_detach(&zone->xfr_acl);
9054         dns_acl_attach(acl, &zone->xfr_acl);
9055         UNLOCK_ZONE(zone);
9056 }
9057
9058 dns_acl_t *
9059 dns_zone_getnotifyacl(dns_zone_t *zone) {
9060
9061         REQUIRE(DNS_ZONE_VALID(zone));
9062
9063         return (zone->notify_acl);
9064 }
9065
9066 dns_acl_t *
9067 dns_zone_getqueryacl(dns_zone_t *zone) {
9068
9069         REQUIRE(DNS_ZONE_VALID(zone));
9070
9071         return (zone->query_acl);
9072 }
9073
9074 dns_acl_t *
9075 dns_zone_getqueryonacl(dns_zone_t *zone) {
9076
9077         REQUIRE(DNS_ZONE_VALID(zone));
9078
9079         return (zone->queryon_acl);
9080 }
9081
9082 dns_acl_t *
9083 dns_zone_getupdateacl(dns_zone_t *zone) {
9084
9085         REQUIRE(DNS_ZONE_VALID(zone));
9086
9087         return (zone->update_acl);
9088 }
9089
9090 dns_acl_t *
9091 dns_zone_getforwardacl(dns_zone_t *zone) {
9092
9093         REQUIRE(DNS_ZONE_VALID(zone));
9094
9095         return (zone->forward_acl);
9096 }
9097
9098 dns_acl_t *
9099 dns_zone_getxfracl(dns_zone_t *zone) {
9100
9101         REQUIRE(DNS_ZONE_VALID(zone));
9102
9103         return (zone->xfr_acl);
9104 }
9105
9106 void
9107 dns_zone_clearupdateacl(dns_zone_t *zone) {
9108
9109         REQUIRE(DNS_ZONE_VALID(zone));
9110
9111         LOCK_ZONE(zone);
9112         if (zone->update_acl != NULL)
9113                 dns_acl_detach(&zone->update_acl);
9114         UNLOCK_ZONE(zone);
9115 }
9116
9117 void
9118 dns_zone_clearforwardacl(dns_zone_t *zone) {
9119
9120         REQUIRE(DNS_ZONE_VALID(zone));
9121
9122         LOCK_ZONE(zone);
9123         if (zone->forward_acl != NULL)
9124                 dns_acl_detach(&zone->forward_acl);
9125         UNLOCK_ZONE(zone);
9126 }
9127
9128 void
9129 dns_zone_clearnotifyacl(dns_zone_t *zone) {
9130
9131         REQUIRE(DNS_ZONE_VALID(zone));
9132
9133         LOCK_ZONE(zone);
9134         if (zone->notify_acl != NULL)
9135                 dns_acl_detach(&zone->notify_acl);
9136         UNLOCK_ZONE(zone);
9137 }
9138
9139 void
9140 dns_zone_clearqueryacl(dns_zone_t *zone) {
9141
9142         REQUIRE(DNS_ZONE_VALID(zone));
9143
9144         LOCK_ZONE(zone);
9145         if (zone->query_acl != NULL)
9146                 dns_acl_detach(&zone->query_acl);
9147         UNLOCK_ZONE(zone);
9148 }
9149
9150 void
9151 dns_zone_clearqueryonacl(dns_zone_t *zone) {
9152
9153         REQUIRE(DNS_ZONE_VALID(zone));
9154
9155         LOCK_ZONE(zone);
9156         if (zone->queryon_acl != NULL)
9157                 dns_acl_detach(&zone->queryon_acl);
9158         UNLOCK_ZONE(zone);
9159 }
9160
9161 void
9162 dns_zone_clearxfracl(dns_zone_t *zone) {
9163
9164         REQUIRE(DNS_ZONE_VALID(zone));
9165
9166         LOCK_ZONE(zone);
9167         if (zone->xfr_acl != NULL)
9168                 dns_acl_detach(&zone->xfr_acl);
9169         UNLOCK_ZONE(zone);
9170 }
9171
9172 isc_boolean_t
9173 dns_zone_getupdatedisabled(dns_zone_t *zone) {
9174         REQUIRE(DNS_ZONE_VALID(zone));
9175         return (zone->update_disabled);
9176
9177 }
9178
9179 void
9180 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
9181         REQUIRE(DNS_ZONE_VALID(zone));
9182         zone->update_disabled = state;
9183 }
9184
9185 isc_boolean_t
9186 dns_zone_getzeronosoattl(dns_zone_t *zone) {
9187         REQUIRE(DNS_ZONE_VALID(zone));
9188         return (zone->zero_no_soa_ttl);
9189
9190 }
9191
9192 void
9193 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
9194         REQUIRE(DNS_ZONE_VALID(zone));
9195         zone->zero_no_soa_ttl = state;
9196 }
9197
9198 void
9199 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
9200
9201         REQUIRE(DNS_ZONE_VALID(zone));
9202
9203         zone->check_names = severity;
9204 }
9205
9206 dns_severity_t
9207 dns_zone_getchecknames(dns_zone_t *zone) {
9208
9209         REQUIRE(DNS_ZONE_VALID(zone));
9210
9211         return (zone->check_names);
9212 }
9213
9214 void
9215 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
9216
9217         REQUIRE(DNS_ZONE_VALID(zone));
9218
9219         zone->journalsize = size;
9220 }
9221
9222 isc_int32_t
9223 dns_zone_getjournalsize(dns_zone_t *zone) {
9224
9225         REQUIRE(DNS_ZONE_VALID(zone));
9226
9227         return (zone->journalsize);
9228 }
9229
9230 static void
9231 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
9232         isc_result_t result = ISC_R_FAILURE;
9233         isc_buffer_t buffer;
9234
9235         REQUIRE(buf != NULL);
9236         REQUIRE(length > 1U);
9237
9238         /*
9239          * Leave space for terminating '\0'.
9240          */
9241         isc_buffer_init(&buffer, buf, length - 1);
9242         if (dns_name_dynamic(&zone->origin))
9243                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
9244         if (result != ISC_R_SUCCESS &&
9245             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
9246                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
9247
9248         if (isc_buffer_availablelength(&buffer) > 0)
9249                 isc_buffer_putstr(&buffer, "/");
9250         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
9251
9252         if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
9253             strcmp(zone->view->name, "_default") != 0 &&
9254             strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
9255                 isc_buffer_putstr(&buffer, "/");
9256                 isc_buffer_putstr(&buffer, zone->view->name);
9257         }
9258
9259         buf[isc_buffer_usedlength(&buffer)] = '\0';
9260 }
9261
9262 static void
9263 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
9264         isc_result_t result = ISC_R_FAILURE;
9265         isc_buffer_t buffer;
9266
9267         REQUIRE(buf != NULL);
9268         REQUIRE(length > 1U);
9269
9270         /*
9271          * Leave space for terminating '\0'.
9272          */
9273         isc_buffer_init(&buffer, buf, length - 1);
9274         if (dns_name_dynamic(&zone->origin))
9275                 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
9276         if (result != ISC_R_SUCCESS &&
9277             isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
9278                 isc_buffer_putstr(&buffer, "<UNKNOWN>");
9279
9280         buf[isc_buffer_usedlength(&buffer)] = '\0';
9281 }
9282
9283 static void
9284 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
9285         isc_buffer_t buffer;
9286
9287         REQUIRE(buf != NULL);
9288         REQUIRE(length > 1U);
9289
9290         /*
9291          * Leave space for terminating '\0'.
9292          */
9293         isc_buffer_init(&buffer, buf, length - 1);
9294         (void)dns_rdataclass_totext(zone->rdclass, &buffer);
9295
9296         buf[isc_buffer_usedlength(&buffer)] = '\0';
9297 }
9298
9299 static void
9300 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
9301         isc_buffer_t buffer;
9302
9303         REQUIRE(buf != NULL);
9304         REQUIRE(length > 1U);
9305
9306
9307         /*
9308          * Leave space for terminating '\0'.
9309          */
9310         isc_buffer_init(&buffer, buf, length - 1);
9311
9312         if (zone->view == NULL) {
9313                 isc_buffer_putstr(&buffer, "_none");
9314         } else if (strlen(zone->view->name)
9315                    < isc_buffer_availablelength(&buffer)) {
9316                 isc_buffer_putstr(&buffer, zone->view->name);
9317         } else {
9318                 isc_buffer_putstr(&buffer, "_toolong");
9319         }
9320
9321         buf[isc_buffer_usedlength(&buffer)] = '\0';
9322 }
9323
9324 void
9325 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
9326         REQUIRE(DNS_ZONE_VALID(zone));
9327         REQUIRE(buf != NULL);
9328         zone_namerd_tostr(zone, buf, length);
9329 }
9330
9331 static void
9332 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
9333         va_list ap;
9334         char message[4096];
9335
9336         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9337                 return;
9338
9339         va_start(ap, fmt);
9340         vsnprintf(message, sizeof(message), fmt, ap);
9341         va_end(ap);
9342         isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
9343                       level, "zone %s: %s", zone->strnamerd, message);
9344 }
9345
9346 void
9347 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
9348               int level, const char *fmt, ...) {
9349         va_list ap;
9350         char message[4096];
9351
9352         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9353                 return;
9354
9355         va_start(ap, fmt);
9356         vsnprintf(message, sizeof(message), fmt, ap);
9357         va_end(ap);
9358         isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
9359                       level, "zone %s: %s", zone->strnamerd, message);
9360 }
9361
9362 void
9363 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
9364         va_list ap;
9365         char message[4096];
9366
9367         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9368                 return;
9369
9370         va_start(ap, fmt);
9371         vsnprintf(message, sizeof(message), fmt, ap);
9372         va_end(ap);
9373         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
9374                       level, "zone %s: %s", zone->strnamerd, message);
9375 }
9376
9377 static void
9378 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
9379               const char *fmt, ...)
9380 {
9381         va_list ap;
9382         char message[4096];
9383         int level = ISC_LOG_DEBUG(debuglevel);
9384
9385         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
9386                 return;
9387
9388         va_start(ap, fmt);
9389         vsnprintf(message, sizeof(message), fmt, ap);
9390         va_end(ap);
9391         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
9392                       level, "%s: zone %s: %s", me, zone->strnamerd, message);
9393 }
9394
9395 static int
9396 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
9397 {
9398         isc_result_t result;
9399         dns_name_t *name;
9400         dns_rdataset_t *curr;
9401         int count = 0;
9402
9403         result = dns_message_firstname(msg, section);
9404         while (result == ISC_R_SUCCESS) {
9405                 name = NULL;
9406                 dns_message_currentname(msg, section, &name);
9407
9408                 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
9409                      curr = ISC_LIST_PREV(curr, link)) {
9410                         if (curr->type == type)
9411                                 count++;
9412                 }
9413                 result = dns_message_nextname(msg, section);
9414         }
9415
9416         return (count);
9417 }
9418
9419 void
9420 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
9421         REQUIRE(DNS_ZONE_VALID(zone));
9422
9423         zone->maxxfrin = maxxfrin;
9424 }
9425
9426 isc_uint32_t
9427 dns_zone_getmaxxfrin(dns_zone_t *zone) {
9428         REQUIRE(DNS_ZONE_VALID(zone));
9429
9430         return (zone->maxxfrin);
9431 }
9432
9433 void
9434 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
9435         REQUIRE(DNS_ZONE_VALID(zone));
9436         zone->maxxfrout = maxxfrout;
9437 }
9438
9439 isc_uint32_t
9440 dns_zone_getmaxxfrout(dns_zone_t *zone) {
9441         REQUIRE(DNS_ZONE_VALID(zone));
9442
9443         return (zone->maxxfrout);
9444 }
9445
9446 dns_zonetype_t
9447 dns_zone_gettype(dns_zone_t *zone) {
9448         REQUIRE(DNS_ZONE_VALID(zone));
9449
9450         return (zone->type);
9451 }
9452
9453 dns_name_t *
9454 dns_zone_getorigin(dns_zone_t *zone) {
9455         REQUIRE(DNS_ZONE_VALID(zone));
9456
9457         return (&zone->origin);
9458 }
9459
9460 void
9461 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
9462         REQUIRE(DNS_ZONE_VALID(zone));
9463
9464         LOCK_ZONE(zone);
9465         if (zone->task != NULL)
9466                 isc_task_detach(&zone->task);
9467         isc_task_attach(task, &zone->task);
9468         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9469         if (zone->db != NULL)
9470                 dns_db_settask(zone->db, zone->task);
9471         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9472         UNLOCK_ZONE(zone);
9473 }
9474
9475 void
9476 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
9477         REQUIRE(DNS_ZONE_VALID(zone));
9478         isc_task_attach(zone->task, target);
9479 }
9480
9481 void
9482 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
9483         REQUIRE(DNS_ZONE_VALID(zone));
9484
9485         if (idlein == 0)
9486                 idlein = DNS_DEFAULT_IDLEIN;
9487         zone->idlein = idlein;
9488 }
9489
9490 isc_uint32_t
9491 dns_zone_getidlein(dns_zone_t *zone) {
9492         REQUIRE(DNS_ZONE_VALID(zone));
9493
9494         return (zone->idlein);
9495 }
9496
9497 void
9498 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
9499         REQUIRE(DNS_ZONE_VALID(zone));
9500
9501         zone->idleout = idleout;
9502 }
9503
9504 isc_uint32_t
9505 dns_zone_getidleout(dns_zone_t *zone) {
9506         REQUIRE(DNS_ZONE_VALID(zone));
9507
9508         return (zone->idleout);
9509 }
9510
9511 static void
9512 notify_done(isc_task_t *task, isc_event_t *event) {
9513         dns_requestevent_t *revent = (dns_requestevent_t *)event;
9514         dns_notify_t *notify;
9515         isc_result_t result;
9516         dns_message_t *message = NULL;
9517         isc_buffer_t buf;
9518         char rcode[128];
9519         char addrbuf[ISC_SOCKADDR_FORMATSIZE];
9520
9521         UNUSED(task);
9522
9523         notify = event->ev_arg;
9524         REQUIRE(DNS_NOTIFY_VALID(notify));
9525         INSIST(task == notify->zone->task);
9526
9527         isc_buffer_init(&buf, rcode, sizeof(rcode));
9528         isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
9529
9530         result = revent->result;
9531         if (result == ISC_R_SUCCESS)
9532                 result = dns_message_create(notify->zone->mctx,
9533                                             DNS_MESSAGE_INTENTPARSE, &message);
9534         if (result == ISC_R_SUCCESS)
9535                 result = dns_request_getresponse(revent->request, message,
9536                                         DNS_MESSAGEPARSE_PRESERVEORDER);
9537         if (result == ISC_R_SUCCESS)
9538                 result = dns_rcode_totext(message->rcode, &buf);
9539         if (result == ISC_R_SUCCESS)
9540                 notify_log(notify->zone, ISC_LOG_DEBUG(3),
9541                            "notify response from %s: %.*s",
9542                            addrbuf, (int)buf.used, rcode);
9543         else
9544                 notify_log(notify->zone, ISC_LOG_DEBUG(2),
9545                            "notify to %s failed: %s", addrbuf,
9546                            dns_result_totext(result));
9547
9548         /*
9549          * Old bind's return formerr if they see a soa record.  Retry w/o
9550          * the soa if we see a formerr and had sent a SOA.
9551          */
9552         isc_event_free(&event);
9553         if (message != NULL && message->rcode == dns_rcode_formerr &&
9554             (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
9555                 notify->flags |= DNS_NOTIFY_NOSOA;
9556                 dns_request_destroy(&notify->request);
9557                 result = notify_send_queue(notify);
9558                 if (result != ISC_R_SUCCESS)
9559                         notify_destroy(notify, ISC_FALSE);
9560         } else {
9561                 if (result == ISC_R_TIMEDOUT)
9562                         notify_log(notify->zone, ISC_LOG_DEBUG(1),
9563                                    "notify to %s: retries exceeded", addrbuf);
9564                 notify_destroy(notify, ISC_FALSE);
9565         }
9566         if (message != NULL)
9567                 dns_message_destroy(&message);
9568 }
9569
9570 isc_result_t
9571 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
9572         isc_result_t result;
9573
9574         REQUIRE(DNS_ZONE_VALID(zone));
9575         LOCK_ZONE(zone);
9576         ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9577         result = zone_replacedb(zone, db, dump);
9578         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9579         UNLOCK_ZONE(zone);
9580         return (result);
9581 }
9582
9583 static isc_result_t
9584 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
9585         dns_dbversion_t *ver;
9586         isc_result_t result;
9587         unsigned int soacount = 0;
9588         unsigned int nscount = 0;
9589
9590         /*
9591          * 'zone' and 'zonedb' locked by caller.
9592          */
9593         REQUIRE(DNS_ZONE_VALID(zone));
9594         REQUIRE(LOCKED_ZONE(zone));
9595
9596         result = zone_get_from_db(zone, db, &nscount, &soacount,
9597                                   NULL, NULL, NULL, NULL, NULL, NULL);
9598         if (result == ISC_R_SUCCESS) {
9599                 if (soacount != 1) {
9600                         dns_zone_log(zone, ISC_LOG_ERROR,
9601                                      "has %d SOA records", soacount);
9602                         result = DNS_R_BADZONE;
9603                 }
9604                 if (nscount == 0) {
9605                         dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
9606                         result = DNS_R_BADZONE;
9607                 }
9608                 if (result != ISC_R_SUCCESS)
9609                         return (result);
9610         } else {
9611                 dns_zone_log(zone, ISC_LOG_ERROR,
9612                             "retrieving SOA and NS records failed: %s",
9613                             dns_result_totext(result));
9614                 return (result);
9615         }
9616
9617         result = check_nsec3param(zone, db);
9618         if (result != ISC_R_SUCCESS)
9619                 return (result);
9620
9621         ver = NULL;
9622         dns_db_currentversion(db, &ver);
9623
9624         /*
9625          * The initial version of a slave zone is always dumped;
9626          * subsequent versions may be journaled instead if this
9627          * is enabled in the configuration.
9628          */
9629         if (zone->db != NULL && zone->journal != NULL &&
9630             DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
9631             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
9632                 isc_uint32_t serial, oldserial;
9633
9634                 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
9635
9636                 result = dns_db_getsoaserial(db, ver, &serial);
9637                 if (result != ISC_R_SUCCESS) {
9638                         dns_zone_log(zone, ISC_LOG_ERROR,
9639                                      "ixfr-from-differences: unable to get "
9640                                      "new serial");
9641                         goto fail;
9642                 }
9643
9644                 /*
9645                  * This is checked in zone_postload() for master zones.
9646                  */
9647                 result = zone_get_from_db(zone, zone->db, NULL, NULL,
9648                                           &oldserial, NULL, NULL, NULL, NULL,
9649                                           NULL);
9650                 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9651                 if (zone->type == dns_zone_slave &&
9652                     !isc_serial_gt(serial, oldserial)) {
9653                         isc_uint32_t serialmin, serialmax;
9654                         serialmin = (oldserial + 1) & 0xffffffffU;
9655                         serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
9656                         dns_zone_log(zone, ISC_LOG_ERROR,
9657                                      "ixfr-from-differences: failed: "
9658                                      "new serial (%u) out of range [%u - %u]",
9659                                      serial, serialmin, serialmax);
9660                         result = ISC_R_RANGE;
9661                         goto fail;
9662                 }
9663
9664                 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
9665                                      zone->journal);
9666                 if (result != ISC_R_SUCCESS)
9667                         goto fail;
9668                 if (dump)
9669                         zone_needdump(zone, DNS_DUMP_DELAY);
9670                 else if (zone->journalsize != -1) {
9671                         result = dns_journal_compact(zone->mctx, zone->journal,
9672                                                      serial, zone->journalsize);
9673                         switch (result) {
9674                         case ISC_R_SUCCESS:
9675                         case ISC_R_NOSPACE:
9676                         case ISC_R_NOTFOUND:
9677                                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9678                                              "dns_journal_compact: %s",
9679                                              dns_result_totext(result));
9680                                 break;
9681                         default:
9682                                 dns_zone_log(zone, ISC_LOG_ERROR,
9683                                              "dns_journal_compact failed: %s",
9684                                              dns_result_totext(result));
9685                                 break;
9686                         }
9687                 }
9688         } else {
9689                 if (dump && zone->masterfile != NULL) {
9690                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
9691                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
9692                                       "dumping new zone version");
9693                         result = dns_db_dump2(db, ver, zone->masterfile,
9694                                               zone->masterformat);
9695                         if (result != ISC_R_SUCCESS)
9696                                 goto fail;
9697
9698                         /*
9699                          * Update the time the zone was updated, so
9700                          * dns_zone_load can avoid loading it when
9701                          * the server is reloaded.  If isc_time_now
9702                          * fails for some reason, all that happens is
9703                          * the timestamp is not updated.
9704                          */
9705                         TIME_NOW(&zone->loadtime);
9706                 }
9707
9708                 if (dump && zone->journal != NULL) {
9709                         /*
9710                          * The in-memory database just changed, and
9711                          * because 'dump' is set, it didn't change by
9712                          * being loaded from disk.  Also, we have not
9713                          * journaled diffs for this change.
9714                          * Therefore, the on-disk journal is missing
9715                          * the deltas for this change.  Since it can
9716                          * no longer be used to bring the zone
9717                          * up-to-date, it is useless and should be
9718                          * removed.
9719                          */
9720                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
9721                                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
9722                                       "removing journal file");
9723                         if (remove(zone->journal) < 0 && errno != ENOENT) {
9724                                 char strbuf[ISC_STRERRORSIZE];
9725                                 isc__strerror(errno, strbuf, sizeof(strbuf));
9726                                 isc_log_write(dns_lctx,
9727                                               DNS_LOGCATEGORY_GENERAL,
9728                                               DNS_LOGMODULE_ZONE,
9729                                               ISC_LOG_WARNING,
9730                                               "unable to remove journal "
9731                                               "'%s': '%s'",
9732                                               zone->journal, strbuf);
9733                         }
9734                 }
9735         }
9736
9737         dns_db_closeversion(db, &ver, ISC_FALSE);
9738
9739         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
9740                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
9741                       "replacing zone database");
9742
9743         if (zone->db != NULL)
9744                 zone_detachdb(zone);
9745         zone_attachdb(zone, db);
9746         dns_db_settask(zone->db, zone->task);
9747         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
9748         return (ISC_R_SUCCESS);
9749
9750  fail:
9751         dns_db_closeversion(db, &ver, ISC_FALSE);
9752         return (result);
9753 }
9754
9755 /* The caller must hold the dblock as a writer. */
9756 static inline void
9757 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
9758         REQUIRE(zone->db == NULL && db != NULL);
9759
9760         dns_db_attach(db, &zone->db);
9761         if (zone->acache != NULL) {
9762                 isc_result_t result;
9763                 result = dns_acache_setdb(zone->acache, db);
9764                 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
9765                         UNEXPECTED_ERROR(__FILE__, __LINE__,
9766                                          "dns_acache_setdb() failed: %s",
9767                                          isc_result_totext(result));
9768                 }
9769         }
9770 }
9771
9772 /* The caller must hold the dblock as a writer. */
9773 static inline void
9774 zone_detachdb(dns_zone_t *zone) {
9775         REQUIRE(zone->db != NULL);
9776
9777         if (zone->acache != NULL)
9778                 (void)dns_acache_putdb(zone->acache, zone->db);
9779         dns_db_detach(&zone->db);
9780 }
9781
9782 static void
9783 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
9784         isc_time_t now;
9785         isc_boolean_t again = ISC_FALSE;
9786         unsigned int soacount;
9787         unsigned int nscount;
9788         isc_uint32_t serial, refresh, retry, expire, minimum;
9789         isc_result_t xfrresult = result;
9790         isc_boolean_t free_needed;
9791
9792         REQUIRE(DNS_ZONE_VALID(zone));
9793
9794         dns_zone_log(zone, ISC_LOG_DEBUG(1),
9795                      "zone transfer finished: %s", dns_result_totext(result));
9796
9797         LOCK_ZONE(zone);
9798         INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
9799         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9800         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9801
9802         TIME_NOW(&now);
9803         switch (result) {
9804         case ISC_R_SUCCESS:
9805                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9806                 /*FALLTHROUGH*/
9807         case DNS_R_UPTODATE:
9808                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
9809                 /*
9810                  * Has the zone expired underneath us?
9811                  */
9812                 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9813                 if (zone->db == NULL) {
9814                         ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9815                         goto same_master;
9816                 }
9817
9818                 /*
9819                  * Update the zone structure's data from the actual
9820                  * SOA received.
9821                  */
9822                 nscount = 0;
9823                 soacount = 0;
9824                 INSIST(zone->db != NULL);
9825                 result = zone_get_from_db(zone, zone->db, &nscount,
9826                                           &soacount, &serial, &refresh,
9827                                           &retry, &expire, &minimum, NULL);
9828                 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9829                 if (result == ISC_R_SUCCESS) {
9830                         if (soacount != 1)
9831                                 dns_zone_log(zone, ISC_LOG_ERROR,
9832                                              "transferred zone "
9833                                              "has %d SOA record%s", soacount,
9834                                              (soacount != 0) ? "s" : "");
9835                         if (nscount == 0) {
9836                                 dns_zone_log(zone, ISC_LOG_ERROR,
9837                                              "transferred zone "
9838                                              "has no NS records");
9839                                 if (DNS_ZONE_FLAG(zone,
9840                                                   DNS_ZONEFLG_HAVETIMERS)) {
9841                                         zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9842                                         zone->retry = DNS_ZONE_DEFAULTRETRY;
9843                                 }
9844                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9845                                 zone_unload(zone);
9846                                 goto next_master;
9847                         }
9848                         zone->refresh = RANGE(refresh, zone->minrefresh,
9849                                               zone->maxrefresh);
9850                         zone->retry = RANGE(retry, zone->minretry,
9851                                             zone->maxretry);
9852                         zone->expire = RANGE(expire,
9853                                              zone->refresh + zone->retry,
9854                                              DNS_MAX_EXPIRE);
9855                         zone->minimum = minimum;
9856                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9857                 }
9858
9859                 /*
9860                  * Set our next update/expire times.
9861                  */
9862                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
9863                         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
9864                         zone->refreshtime = now;
9865                         DNS_ZONE_TIME_ADD(&now, zone->expire,
9866                                           &zone->expiretime);
9867                 } else {
9868                         DNS_ZONE_JITTER_ADD(&now, zone->refresh,
9869                                             &zone->refreshtime);
9870                         DNS_ZONE_TIME_ADD(&now, zone->expire,
9871                                           &zone->expiretime);
9872                 }
9873                 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
9874                         char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
9875                         if (zone->tsigkey != NULL) {
9876                                 char namebuf[DNS_NAME_FORMATSIZE];
9877                                 dns_name_format(&zone->tsigkey->name, namebuf,
9878                                                 sizeof(namebuf));
9879                                 snprintf(buf, sizeof(buf), ": TSIG '%s'",
9880                                          namebuf);
9881                         } else
9882                                 buf[0] = '\0';
9883                         dns_zone_log(zone, ISC_LOG_INFO,
9884                                      "transferred serial %u%s",
9885                                      serial, buf);
9886                 }
9887
9888                 /*
9889                  * This is not necessary if we just performed a AXFR
9890                  * however it is necessary for an IXFR / UPTODATE and
9891                  * won't hurt with an AXFR.
9892                  */
9893                 if (zone->masterfile != NULL || zone->journal != NULL) {
9894                         result = ISC_R_FAILURE;
9895                         if (zone->journal != NULL)
9896                                 result = isc_file_settime(zone->journal, &now);
9897                         if (result != ISC_R_SUCCESS &&
9898                             zone->masterfile != NULL)
9899                                 result = isc_file_settime(zone->masterfile,
9900                                                           &now);
9901                         /* Someone removed the file from underneath us! */
9902                         if (result == ISC_R_FILENOTFOUND &&
9903                             zone->masterfile != NULL)
9904                                 zone_needdump(zone, DNS_DUMP_DELAY);
9905                         else if (result != ISC_R_SUCCESS)
9906                                 dns_zone_log(zone, ISC_LOG_ERROR,
9907                                              "transfer: could not set file "
9908                                              "modification time of '%s': %s",
9909                                              zone->masterfile,
9910                                              dns_result_totext(result));
9911                 }
9912
9913                 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
9914                 break;
9915
9916         case DNS_R_BADIXFR:
9917                 /* Force retry with AXFR. */
9918                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
9919                 goto same_master;
9920
9921         default:
9922         next_master:
9923                 /*
9924                  * Skip to next failed / untried master.
9925                  */
9926                 do {
9927                         zone->curmaster++;
9928                 } while (zone->curmaster < zone->masterscnt &&
9929                          zone->mastersok[zone->curmaster]);
9930                 /* FALLTHROUGH */
9931         same_master:
9932                 if (zone->curmaster >= zone->masterscnt) {
9933                         zone->curmaster = 0;
9934                         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9935                             !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9936                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9937                                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9938                                 while (zone->curmaster < zone->masterscnt &&
9939                                        zone->mastersok[zone->curmaster])
9940                                         zone->curmaster++;
9941                                 again = ISC_TRUE;
9942                         } else
9943                                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9944                 } else {
9945                         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9946                         again = ISC_TRUE;
9947                 }
9948                 inc_stats(zone, dns_zonestatscounter_xfrfail);
9949                 break;
9950         }
9951         zone_settimer(zone, &now);
9952
9953         /*
9954          * If creating the transfer object failed, zone->xfr is NULL.
9955          * Otherwise, we are called as the done callback of a zone
9956          * transfer object that just entered its shutting-down
9957          * state.  Since we are no longer responsible for shutting
9958          * it down, we can detach our reference.
9959          */
9960         if (zone->xfr != NULL)
9961                 dns_xfrin_detach(&zone->xfr);
9962
9963         if (zone->tsigkey != NULL)
9964                 dns_tsigkey_detach(&zone->tsigkey);
9965
9966         /*
9967          * Handle any deferred journal compaction.
9968          */
9969         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
9970                 result = dns_journal_compact(zone->mctx, zone->journal,
9971                                              zone->compact_serial,
9972                                              zone->journalsize);
9973                 switch (result) {
9974                 case ISC_R_SUCCESS:
9975                 case ISC_R_NOSPACE:
9976                 case ISC_R_NOTFOUND:
9977                         dns_zone_log(zone, ISC_LOG_DEBUG(3),
9978                                      "dns_journal_compact: %s",
9979                                      dns_result_totext(result));
9980                         break;
9981                 default:
9982                         dns_zone_log(zone, ISC_LOG_ERROR,
9983                                      "dns_journal_compact failed: %s",
9984                                      dns_result_totext(result));
9985                         break;
9986                 }
9987                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9988         }
9989
9990         /*
9991          * This transfer finishing freed up a transfer quota slot.
9992          * Let any other zones waiting for quota have it.
9993          */
9994         UNLOCK_ZONE(zone);
9995         RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
9996         ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
9997         zone->statelist = NULL;
9998         zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
9999         RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10000         LOCK_ZONE(zone);
10001
10002         /*
10003          * Retry with a different server if necessary.
10004          */
10005         if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10006                 queue_soa_query(zone);
10007
10008         INSIST(zone->irefs > 0);
10009         zone->irefs--;
10010         free_needed = exit_check(zone);
10011         UNLOCK_ZONE(zone);
10012         if (free_needed)
10013                 zone_free(zone);
10014 }
10015
10016 static void
10017 zone_loaddone(void *arg, isc_result_t result) {
10018         static char me[] = "zone_loaddone";
10019         dns_load_t *load = arg;
10020         dns_zone_t *zone;
10021         isc_result_t tresult;
10022
10023         REQUIRE(DNS_LOAD_VALID(load));
10024         zone = load->zone;
10025
10026         ENTER;
10027
10028         tresult = dns_db_endload(load->db, &load->callbacks.add_private);
10029         if (tresult != ISC_R_SUCCESS &&
10030             (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
10031                 result = tresult;
10032
10033         LOCK_ZONE(load->zone);
10034         (void)zone_postload(load->zone, load->db, load->loadtime, result);
10035         zonemgr_putio(&load->zone->readio);
10036         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
10037         /*
10038          * Leave the zone frozen if the reload fails.
10039          */
10040         if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
10041              DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
10042                 zone->update_disabled = ISC_FALSE;
10043         DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
10044         UNLOCK_ZONE(load->zone);
10045
10046         load->magic = 0;
10047         dns_db_detach(&load->db);
10048         if (load->zone->lctx != NULL)
10049                 dns_loadctx_detach(&load->zone->lctx);
10050         dns_zone_idetach(&load->zone);
10051         isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
10052 }
10053
10054 void
10055 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
10056         REQUIRE(DNS_ZONE_VALID(zone));
10057         REQUIRE(table != NULL);
10058         REQUIRE(*table == NULL);
10059
10060         LOCK_ZONE(zone);
10061         if (zone->ssutable != NULL)
10062                 dns_ssutable_attach(zone->ssutable, table);
10063         UNLOCK_ZONE(zone);
10064 }
10065
10066 void
10067 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
10068         REQUIRE(DNS_ZONE_VALID(zone));
10069
10070         LOCK_ZONE(zone);
10071         if (zone->ssutable != NULL)
10072                 dns_ssutable_detach(&zone->ssutable);
10073         if (table != NULL)
10074                 dns_ssutable_attach(table, &zone->ssutable);
10075         UNLOCK_ZONE(zone);
10076 }
10077
10078 void
10079 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
10080         REQUIRE(DNS_ZONE_VALID(zone));
10081
10082         zone->sigvalidityinterval = interval;
10083 }
10084
10085 isc_uint32_t
10086 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
10087         REQUIRE(DNS_ZONE_VALID(zone));
10088
10089         return (zone->sigvalidityinterval);
10090 }
10091
10092 void
10093 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
10094         REQUIRE(DNS_ZONE_VALID(zone));
10095
10096         zone->sigresigninginterval = interval;
10097 }
10098
10099 isc_uint32_t
10100 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
10101         REQUIRE(DNS_ZONE_VALID(zone));
10102
10103         return (zone->sigresigninginterval);
10104 }
10105
10106 static void
10107 queue_xfrin(dns_zone_t *zone) {
10108         const char me[] = "queue_xfrin";
10109         isc_result_t result;
10110         dns_zonemgr_t *zmgr = zone->zmgr;
10111
10112         ENTER;
10113
10114         INSIST(zone->statelist == NULL);
10115
10116         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10117         ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
10118         LOCK_ZONE(zone);
10119         zone->irefs++;
10120         UNLOCK_ZONE(zone);
10121         zone->statelist = &zmgr->waiting_for_xfrin;
10122         result = zmgr_start_xfrin_ifquota(zmgr, zone);
10123         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10124
10125         if (result == ISC_R_QUOTA) {
10126                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
10127                               "zone transfer deferred due to quota");
10128         } else if (result != ISC_R_SUCCESS) {
10129                 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
10130                               "starting zone transfer: %s",
10131                               isc_result_totext(result));
10132         }
10133 }
10134
10135 /*
10136  * This event callback is called when a zone has received
10137  * any necessary zone transfer quota.  This is the time
10138  * to go ahead and start the transfer.
10139  */
10140 static void
10141 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
10142         isc_result_t result;
10143         dns_peer_t *peer = NULL;
10144         char master[ISC_SOCKADDR_FORMATSIZE];
10145         char source[ISC_SOCKADDR_FORMATSIZE];
10146         dns_rdatatype_t xfrtype;
10147         dns_zone_t *zone = event->ev_arg;
10148         isc_netaddr_t masterip;
10149         isc_sockaddr_t sourceaddr;
10150         isc_sockaddr_t masteraddr;
10151         isc_time_t now;
10152         const char *soa_before = "";
10153
10154         UNUSED(task);
10155
10156         INSIST(task == zone->task);
10157
10158         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10159                 result = ISC_R_CANCELED;
10160                 goto cleanup;
10161         }
10162
10163         TIME_NOW(&now);
10164
10165         isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10166         if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
10167                                     &zone->sourceaddr, &now))
10168         {
10169                 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10170                 dns_zone_log(zone, ISC_LOG_INFO,
10171                              "got_transfer_quota: skipping zone transfer as "
10172                              "master %s (source %s) is unreachable (cached)",
10173                              master, source);
10174                 result = ISC_R_CANCELED;
10175                 goto cleanup;
10176         }
10177
10178         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10179         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
10180
10181         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
10182                 soa_before = "SOA before ";
10183         /*
10184          * Decide whether we should request IXFR or AXFR.
10185          */
10186         if (zone->db == NULL) {
10187                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10188                              "no database exists yet, requesting AXFR of "
10189                              "initial version from %s", master);
10190                 xfrtype = dns_rdatatype_axfr;
10191         } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
10192                 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
10193                              "set, requesting %sAXFR from %s", soa_before,
10194                              master);
10195                 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
10196                         xfrtype = dns_rdatatype_soa;
10197                 else
10198                         xfrtype = dns_rdatatype_axfr;
10199         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
10200                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10201                              "forced reload, requesting AXFR of "
10202                              "initial version from %s", master);
10203                 xfrtype = dns_rdatatype_axfr;
10204         } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
10205                 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10206                              "retrying with AXFR from %s due to "
10207                              "previous IXFR failure", master);
10208                 xfrtype = dns_rdatatype_axfr;
10209                 LOCK_ZONE(zone);
10210                 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
10211                 UNLOCK_ZONE(zone);
10212         } else {
10213                 isc_boolean_t use_ixfr = ISC_TRUE;
10214                 if (peer != NULL &&
10215                     dns_peer_getrequestixfr(peer, &use_ixfr) ==
10216                     ISC_R_SUCCESS) {
10217                         ; /* Using peer setting */
10218                 } else {
10219                         use_ixfr = zone->view->requestixfr;
10220                 }
10221                 if (use_ixfr == ISC_FALSE) {
10222                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10223                                      "IXFR disabled, requesting %sAXFR from %s",
10224                                      soa_before, master);
10225                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
10226                                 xfrtype = dns_rdatatype_soa;
10227                         else
10228                                 xfrtype = dns_rdatatype_axfr;
10229                 } else {
10230                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10231                                      "requesting IXFR from %s", master);
10232                         xfrtype = dns_rdatatype_ixfr;
10233                 }
10234         }
10235
10236         /*
10237          * Determine if we should attempt to sign the request with TSIG.
10238          */
10239         result = ISC_R_NOTFOUND;
10240         /*
10241          * First, look for a tsig key in the master statement, then
10242          * try for a server key.
10243          */
10244         if ((zone->masterkeynames != NULL) &&
10245             (zone->masterkeynames[zone->curmaster] != NULL)) {
10246                 dns_view_t *view = dns_zone_getview(zone);
10247                 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10248                 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
10249         }
10250         if (zone->tsigkey == NULL)
10251                 result = dns_view_getpeertsig(zone->view, &masterip,
10252                                               &zone->tsigkey);
10253
10254         if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10255                 dns_zone_log(zone, ISC_LOG_ERROR,
10256                              "could not get TSIG key for zone transfer: %s",
10257                              isc_result_totext(result));
10258         }
10259
10260         LOCK_ZONE(zone);
10261         masteraddr = zone->masteraddr;
10262         sourceaddr = zone->sourceaddr;
10263         UNLOCK_ZONE(zone);
10264         INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
10265         result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
10266                                    zone->tsigkey, zone->mctx,
10267                                    zone->zmgr->timermgr, zone->zmgr->socketmgr,
10268                                    zone->task, zone_xfrdone, &zone->xfr);
10269         if (result == ISC_R_SUCCESS) {
10270                 LOCK_ZONE(zone);
10271                 if (xfrtype == dns_rdatatype_axfr) {
10272                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
10273                                 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
10274                         else
10275                                 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
10276                 } else if (xfrtype == dns_rdatatype_ixfr) {
10277                         if (isc_sockaddr_pf(&masteraddr) == PF_INET)
10278                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
10279                         else
10280                                 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
10281                 }
10282                 UNLOCK_ZONE(zone);
10283         }
10284  cleanup:
10285         /*
10286          * Any failure in this function is handled like a failed
10287          * zone transfer.  This ensures that we get removed from
10288          * zmgr->xfrin_in_progress.
10289          */
10290         if (result != ISC_R_SUCCESS)
10291                 zone_xfrdone(zone, result);
10292
10293         isc_event_free(&event);
10294 }
10295
10296 /*
10297  * Update forwarding support.
10298  */
10299
10300 static void
10301 forward_destroy(dns_forward_t *forward) {
10302
10303         forward->magic = 0;
10304         if (forward->request != NULL)
10305                 dns_request_destroy(&forward->request);
10306         if (forward->msgbuf != NULL)
10307                 isc_buffer_free(&forward->msgbuf);
10308         if (forward->zone != NULL) {
10309                 LOCK(&forward->zone->lock);
10310                 if (ISC_LINK_LINKED(forward, link))
10311                         ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
10312                 UNLOCK(&forward->zone->lock);
10313                 dns_zone_idetach(&forward->zone);
10314         }
10315         isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
10316 }
10317
10318 static isc_result_t
10319 sendtomaster(dns_forward_t *forward) {
10320         isc_result_t result;
10321         isc_sockaddr_t src;
10322
10323         LOCK_ZONE(forward->zone);
10324
10325         if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
10326                 UNLOCK_ZONE(forward->zone);
10327                 return (ISC_R_CANCELED);
10328         }
10329
10330         if (forward->which >= forward->zone->masterscnt) {
10331                 UNLOCK_ZONE(forward->zone);
10332                 return (ISC_R_NOMORE);
10333         }
10334
10335         forward->addr = forward->zone->masters[forward->which];
10336         /*
10337          * Always use TCP regardless of whether the original update
10338          * used TCP.
10339          * XXX The timeout may but a bit small if we are far down a
10340          * transfer graph and the master has to try several masters.
10341          */
10342         switch (isc_sockaddr_pf(&forward->addr)) {
10343         case PF_INET:
10344                 src = forward->zone->xfrsource4;
10345                 break;
10346         case PF_INET6:
10347                 src = forward->zone->xfrsource6;
10348                 break;
10349         default:
10350                 result = ISC_R_NOTIMPLEMENTED;
10351                 goto unlock;
10352         }
10353         result = dns_request_createraw(forward->zone->view->requestmgr,
10354                                        forward->msgbuf,
10355                                        &src, &forward->addr,
10356                                        DNS_REQUESTOPT_TCP, 15 /* XXX */,
10357                                        forward->zone->task,
10358                                        forward_callback, forward,
10359                                        &forward->request);
10360         if (result == ISC_R_SUCCESS) {
10361                 if (!ISC_LINK_LINKED(forward, link))
10362                         ISC_LIST_APPEND(forward->zone->forwards, forward, link);
10363         }
10364
10365  unlock:
10366         UNLOCK_ZONE(forward->zone);
10367         return (result);
10368 }
10369
10370 static void
10371 forward_callback(isc_task_t *task, isc_event_t *event) {
10372         const char me[] = "forward_callback";
10373         dns_requestevent_t *revent = (dns_requestevent_t *)event;
10374         dns_message_t *msg = NULL;
10375         char master[ISC_SOCKADDR_FORMATSIZE];
10376         isc_result_t result;
10377         dns_forward_t *forward;
10378         dns_zone_t *zone;
10379
10380         UNUSED(task);
10381
10382         forward = revent->ev_arg;
10383         INSIST(DNS_FORWARD_VALID(forward));
10384         zone = forward->zone;
10385         INSIST(DNS_ZONE_VALID(zone));
10386
10387         ENTER;
10388
10389         isc_sockaddr_format(&forward->addr, master, sizeof(master));
10390
10391         if (revent->result != ISC_R_SUCCESS) {
10392                 dns_zone_log(zone, ISC_LOG_INFO,
10393                              "could not forward dynamic update to %s: %s",
10394                              master, dns_result_totext(revent->result));
10395                 goto next_master;
10396         }
10397
10398         result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10399         if (result != ISC_R_SUCCESS)
10400                 goto next_master;
10401
10402         result = dns_request_getresponse(revent->request, msg,
10403                                          DNS_MESSAGEPARSE_PRESERVEORDER |
10404                                          DNS_MESSAGEPARSE_CLONEBUFFER);
10405         if (result != ISC_R_SUCCESS)
10406                 goto next_master;
10407
10408         switch (msg->rcode) {
10409         /*
10410          * Pass these rcodes back to client.
10411          */
10412         case dns_rcode_noerror:
10413         case dns_rcode_yxdomain:
10414         case dns_rcode_yxrrset:
10415         case dns_rcode_nxrrset:
10416         case dns_rcode_refused:
10417         case dns_rcode_nxdomain:
10418                 break;
10419
10420         /* These should not occur if the masters/zone are valid. */
10421         case dns_rcode_notzone:
10422         case dns_rcode_notauth: {
10423                 char rcode[128];
10424                 isc_buffer_t rb;
10425
10426                 isc_buffer_init(&rb, rcode, sizeof(rcode));
10427                 (void)dns_rcode_totext(msg->rcode, &rb);
10428                 dns_zone_log(zone, ISC_LOG_WARNING,
10429                              "forwarding dynamic update: "
10430                              "unexpected response: master %s returned: %.*s",
10431                              master, (int)rb.used, rcode);
10432                 goto next_master;
10433         }
10434
10435         /* Try another server for these rcodes. */
10436         case dns_rcode_formerr:
10437         case dns_rcode_servfail:
10438         case dns_rcode_notimp:
10439         case dns_rcode_badvers:
10440         default:
10441                 goto next_master;
10442         }
10443
10444         /* call callback */
10445         (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
10446         msg = NULL;
10447         dns_request_destroy(&forward->request);
10448         forward_destroy(forward);
10449         isc_event_free(&event);
10450         return;
10451
10452  next_master:
10453         if (msg != NULL)
10454                 dns_message_destroy(&msg);
10455         isc_event_free(&event);
10456         forward->which++;
10457         dns_request_destroy(&forward->request);
10458         result = sendtomaster(forward);
10459         if (result != ISC_R_SUCCESS) {
10460                 /* call callback */
10461                 dns_zone_log(zone, ISC_LOG_DEBUG(3),
10462                              "exhausted dynamic update forwarder list");
10463                 (forward->callback)(forward->callback_arg, result, NULL);
10464                 forward_destroy(forward);
10465         }
10466 }
10467
10468 isc_result_t
10469 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
10470                        dns_updatecallback_t callback, void *callback_arg)
10471 {
10472         dns_forward_t *forward;
10473         isc_result_t result;
10474         isc_region_t *mr;
10475
10476         REQUIRE(DNS_ZONE_VALID(zone));
10477         REQUIRE(msg != NULL);
10478         REQUIRE(callback != NULL);
10479
10480         forward = isc_mem_get(zone->mctx, sizeof(*forward));
10481         if (forward == NULL)
10482                 return (ISC_R_NOMEMORY);
10483
10484         forward->request = NULL;
10485         forward->zone = NULL;
10486         forward->msgbuf = NULL;
10487         forward->which = 0;
10488         forward->mctx = 0;
10489         forward->callback = callback;
10490         forward->callback_arg = callback_arg;
10491         ISC_LINK_INIT(forward, link);
10492         forward->magic = FORWARD_MAGIC;
10493
10494         mr = dns_message_getrawmessage(msg);
10495         if (mr == NULL) {
10496                 result = ISC_R_UNEXPECTEDEND;
10497                 goto cleanup;
10498         }
10499
10500         result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
10501         if (result != ISC_R_SUCCESS)
10502                 goto cleanup;
10503         result = isc_buffer_copyregion(forward->msgbuf, mr);
10504         if (result != ISC_R_SUCCESS)
10505                 goto cleanup;
10506
10507         isc_mem_attach(zone->mctx, &forward->mctx);
10508         dns_zone_iattach(zone, &forward->zone);
10509         result = sendtomaster(forward);
10510
10511  cleanup:
10512         if (result != ISC_R_SUCCESS) {
10513                 forward_destroy(forward);
10514         }
10515         return (result);
10516 }
10517
10518 isc_result_t
10519 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
10520         REQUIRE(DNS_ZONE_VALID(zone));
10521         REQUIRE(next != NULL && *next == NULL);
10522
10523         *next = ISC_LIST_NEXT(zone, link);
10524         if (*next == NULL)
10525                 return (ISC_R_NOMORE);
10526         else
10527                 return (ISC_R_SUCCESS);
10528 }
10529
10530 isc_result_t
10531 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
10532         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10533         REQUIRE(first != NULL && *first == NULL);
10534
10535         *first = ISC_LIST_HEAD(zmgr->zones);
10536         if (*first == NULL)
10537                 return (ISC_R_NOMORE);
10538         else
10539                 return (ISC_R_SUCCESS);
10540 }
10541
10542 /***
10543  ***    Zone manager.
10544  ***/
10545
10546 isc_result_t
10547 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
10548                    isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
10549                    dns_zonemgr_t **zmgrp)
10550 {
10551         dns_zonemgr_t *zmgr;
10552         isc_result_t result;
10553         isc_interval_t interval;
10554
10555         zmgr = isc_mem_get(mctx, sizeof(*zmgr));
10556         if (zmgr == NULL)
10557                 return (ISC_R_NOMEMORY);
10558         zmgr->mctx = NULL;
10559         zmgr->refs = 1;
10560         isc_mem_attach(mctx, &zmgr->mctx);
10561         zmgr->taskmgr = taskmgr;
10562         zmgr->timermgr = timermgr;
10563         zmgr->socketmgr = socketmgr;
10564         zmgr->zonetasks = NULL;
10565         zmgr->task = NULL;
10566         zmgr->rl = NULL;
10567         ISC_LIST_INIT(zmgr->zones);
10568         ISC_LIST_INIT(zmgr->waiting_for_xfrin);
10569         ISC_LIST_INIT(zmgr->xfrin_in_progress);
10570         memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
10571         result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
10572         if (result != ISC_R_SUCCESS)
10573                 goto free_mem;
10574
10575         zmgr->transfersin = 10;
10576         zmgr->transfersperns = 2;
10577
10578         /* Unreachable lock. */
10579         result = isc_rwlock_init(&zmgr->urlock, 0, 0);
10580         if (result != ISC_R_SUCCESS)
10581                 goto free_rwlock;
10582
10583         /* Create a single task for queueing of SOA queries. */
10584         result = isc_task_create(taskmgr, 1, &zmgr->task);
10585         if (result != ISC_R_SUCCESS)
10586                 goto free_urlock;
10587
10588         isc_task_setname(zmgr->task, "zmgr", zmgr);
10589         result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
10590                                         &zmgr->rl);
10591         if (result != ISC_R_SUCCESS)
10592                 goto free_task;
10593
10594         /* default to 20 refresh queries / notifies per second. */
10595         isc_interval_set(&interval, 0, 1000000000/2);
10596         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
10597         RUNTIME_CHECK(result == ISC_R_SUCCESS);
10598         isc_ratelimiter_setpertic(zmgr->rl, 10);
10599
10600         zmgr->iolimit = 1;
10601         zmgr->ioactive = 0;
10602         ISC_LIST_INIT(zmgr->high);
10603         ISC_LIST_INIT(zmgr->low);
10604
10605         result = isc_mutex_init(&zmgr->iolock);
10606         if (result != ISC_R_SUCCESS)
10607                 goto free_rl;
10608
10609         zmgr->magic = ZONEMGR_MAGIC;
10610
10611         *zmgrp = zmgr;
10612         return (ISC_R_SUCCESS);
10613
10614 #if 0
10615  free_iolock:
10616         DESTROYLOCK(&zmgr->iolock);
10617 #endif
10618  free_rl:
10619         isc_ratelimiter_detach(&zmgr->rl);
10620  free_task:
10621         isc_task_detach(&zmgr->task);
10622  free_urlock:
10623         isc_rwlock_destroy(&zmgr->urlock);
10624  free_rwlock:
10625         isc_rwlock_destroy(&zmgr->rwlock);
10626  free_mem:
10627         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
10628         isc_mem_detach(&mctx);
10629         return (result);
10630 }
10631
10632 isc_result_t
10633 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
10634         isc_result_t result;
10635
10636         REQUIRE(DNS_ZONE_VALID(zone));
10637         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10638
10639         if (zmgr->zonetasks == NULL)
10640                 return (ISC_R_FAILURE);
10641
10642         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10643         LOCK_ZONE(zone);
10644         REQUIRE(zone->task == NULL);
10645         REQUIRE(zone->timer == NULL);
10646         REQUIRE(zone->zmgr == NULL);
10647
10648         isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
10649
10650         /*
10651          * Set the task name.  The tag will arbitrarily point to one
10652          * of the zones sharing the task (in practice, the one
10653          * to be managed last).
10654          */
10655         isc_task_setname(zone->task, "zone", zone);
10656
10657         result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
10658                                   NULL, NULL,
10659                                   zone->task, zone_timer, zone,
10660                                   &zone->timer);
10661
10662         if (result != ISC_R_SUCCESS)
10663                 goto cleanup_task;
10664
10665         /*
10666          * The timer "holds" a iref.
10667          */
10668         zone->irefs++;
10669         INSIST(zone->irefs != 0);
10670
10671         ISC_LIST_APPEND(zmgr->zones, zone, link);
10672         zone->zmgr = zmgr;
10673         zmgr->refs++;
10674
10675         goto unlock;
10676
10677  cleanup_task:
10678         isc_task_detach(&zone->task);
10679
10680  unlock:
10681         UNLOCK_ZONE(zone);
10682         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10683         return (result);
10684 }
10685
10686 void
10687 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
10688         isc_boolean_t free_now = ISC_FALSE;
10689
10690         REQUIRE(DNS_ZONE_VALID(zone));
10691         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10692         REQUIRE(zone->zmgr == zmgr);
10693
10694         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10695         LOCK_ZONE(zone);
10696
10697         ISC_LIST_UNLINK(zmgr->zones, zone, link);
10698         zone->zmgr = NULL;
10699         zmgr->refs--;
10700         if (zmgr->refs == 0)
10701                 free_now = ISC_TRUE;
10702
10703         UNLOCK_ZONE(zone);
10704         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10705
10706         if (free_now)
10707                 zonemgr_free(zmgr);
10708         ENSURE(zone->zmgr == NULL);
10709 }
10710
10711 void
10712 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
10713         REQUIRE(DNS_ZONEMGR_VALID(source));
10714         REQUIRE(target != NULL && *target == NULL);
10715
10716         RWLOCK(&source->rwlock, isc_rwlocktype_write);
10717         REQUIRE(source->refs > 0);
10718         source->refs++;
10719         INSIST(source->refs > 0);
10720         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
10721         *target = source;
10722 }
10723
10724 void
10725 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
10726         dns_zonemgr_t *zmgr;
10727         isc_boolean_t free_now = ISC_FALSE;
10728
10729         REQUIRE(zmgrp != NULL);
10730         zmgr = *zmgrp;
10731         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10732
10733         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10734         zmgr->refs--;
10735         if (zmgr->refs == 0)
10736                 free_now = ISC_TRUE;
10737         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10738
10739         if (free_now)
10740                 zonemgr_free(zmgr);
10741         *zmgrp = NULL;
10742 }
10743
10744 isc_result_t
10745 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
10746         dns_zone_t *p;
10747
10748         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10749
10750         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
10751         for (p = ISC_LIST_HEAD(zmgr->zones);
10752              p != NULL;
10753              p = ISC_LIST_NEXT(p, link))
10754         {
10755                 dns_zone_maintenance(p);
10756         }
10757         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
10758
10759         /*
10760          * Recent configuration changes may have increased the
10761          * amount of available transfers quota.  Make sure any
10762          * transfers currently blocked on quota get started if
10763          * possible.
10764          */
10765         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10766         zmgr_resume_xfrs(zmgr, ISC_TRUE);
10767         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10768         return (ISC_R_SUCCESS);
10769 }
10770
10771 void
10772 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
10773
10774         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10775
10776         RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10777         zmgr_resume_xfrs(zmgr, ISC_TRUE);
10778         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
10779 }
10780
10781 void
10782 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
10783         dns_zone_t *zone;
10784
10785         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10786
10787         isc_ratelimiter_shutdown(zmgr->rl);
10788
10789         if (zmgr->task != NULL)
10790                 isc_task_destroy(&zmgr->task);
10791         if (zmgr->zonetasks != NULL)
10792                 isc_taskpool_destroy(&zmgr->zonetasks);
10793
10794         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
10795         for (zone = ISC_LIST_HEAD(zmgr->zones);
10796              zone != NULL;
10797              zone = ISC_LIST_NEXT(zone, link))
10798         {
10799                 LOCK_ZONE(zone);
10800                 forward_cancel(zone);
10801                 UNLOCK_ZONE(zone);
10802         }
10803         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
10804 }
10805
10806 isc_result_t
10807 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
10808         isc_result_t result;
10809         int ntasks = num_zones / 100;
10810         isc_taskpool_t *pool = NULL;
10811
10812         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10813
10814         /*
10815          * For anything fewer than 1000 zones we use 10 tasks in
10816          * the task pool.  More than that, and we'll scale at one
10817          * task per 100 zones.
10818          */
10819         if (ntasks < 10)
10820                 ntasks = 10;
10821
10822         /* Create or resize the zone task pool. */
10823         if (zmgr->zonetasks == NULL)
10824                 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
10825                                              ntasks, 2, &pool);
10826         else
10827                 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
10828
10829         if (result == ISC_R_SUCCESS)
10830                 zmgr->zonetasks = pool;
10831
10832         return (result);
10833 }
10834
10835 static void
10836 zonemgr_free(dns_zonemgr_t *zmgr) {
10837         isc_mem_t *mctx;
10838
10839         INSIST(zmgr->refs == 0);
10840         INSIST(ISC_LIST_EMPTY(zmgr->zones));
10841
10842         zmgr->magic = 0;
10843
10844         DESTROYLOCK(&zmgr->iolock);
10845         isc_ratelimiter_detach(&zmgr->rl);
10846
10847         isc_rwlock_destroy(&zmgr->urlock);
10848         isc_rwlock_destroy(&zmgr->rwlock);
10849         mctx = zmgr->mctx;
10850         isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
10851         isc_mem_detach(&mctx);
10852 }
10853
10854 void
10855 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
10856         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10857
10858         zmgr->transfersin = value;
10859 }
10860
10861 isc_uint32_t
10862 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
10863         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10864
10865         return (zmgr->transfersin);
10866 }
10867
10868 void
10869 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
10870         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10871
10872         zmgr->transfersperns = value;
10873 }
10874
10875 isc_uint32_t
10876 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
10877         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
10878
10879         return (zmgr->transfersperns);
10880 }
10881
10882 /*
10883  * Try to start a new incoming zone transfer to fill a quota
10884  * slot that was just vacated.
10885  *
10886  * Requires:
10887  *      The zone manager is locked by the caller.
10888  */
10889 static void
10890 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
10891         dns_zone_t *zone;
10892         dns_zone_t *next;
10893
10894         for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
10895              zone != NULL;
10896              zone = next)
10897         {
10898                 isc_result_t result;
10899                 next = ISC_LIST_NEXT(zone, statelink);
10900                 result = zmgr_start_xfrin_ifquota(zmgr, zone);
10901                 if (result == ISC_R_SUCCESS) {
10902                         if (multi)
10903                                 continue;
10904                         /*
10905                          * We successfully filled the slot.  We're done.
10906                          */
10907                         break;
10908                 } else if (result == ISC_R_QUOTA) {
10909                         /*
10910                          * Not enough quota.  This is probably the per-server
10911                          * quota, because we usually get called when a unit of
10912                          * global quota has just been freed.  Try the next
10913                          * zone, it may succeed if it uses another master.
10914                          */
10915                         continue;
10916                 } else {
10917                         dns_zone_log(zone, ISC_LOG_DEBUG(1),
10918                                      "starting zone transfer: %s",
10919                                      isc_result_totext(result));
10920                         break;
10921                 }
10922         }
10923 }
10924
10925 /*
10926  * Try to start an incoming zone transfer for 'zone', quota permitting.
10927  *
10928  * Requires:
10929  *      The zone manager is locked by the caller.
10930  *
10931  * Returns:
10932  *      ISC_R_SUCCESS   There was enough quota and we attempted to
10933  *                      start a transfer.  zone_xfrdone() has been or will
10934  *                      be called.
10935  *      ISC_R_QUOTA     Not enough quota.
10936  *      Others          Failure.
10937  */
10938 static isc_result_t
10939 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
10940         dns_peer_t *peer = NULL;
10941         isc_netaddr_t masterip;
10942         isc_uint32_t nxfrsin, nxfrsperns;
10943         dns_zone_t *x;
10944         isc_uint32_t maxtransfersin, maxtransfersperns;
10945         isc_event_t *e;
10946
10947         /*
10948          * If we are exiting just pretend we got quota so the zone will
10949          * be cleaned up in the zone's task context.
10950          */
10951         LOCK_ZONE(zone);
10952         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10953                 UNLOCK_ZONE(zone);
10954                 goto gotquota;
10955         }
10956
10957         /*
10958          * Find any configured information about the server we'd
10959          * like to transfer this zone from.
10960          */
10961         isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10962         (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
10963         UNLOCK_ZONE(zone);
10964
10965         /*
10966          * Determine the total maximum number of simultaneous
10967          * transfers allowed, and the maximum for this specific
10968          * master.
10969          */
10970         maxtransfersin = zmgr->transfersin;
10971         maxtransfersperns = zmgr->transfersperns;
10972         if (peer != NULL)
10973                 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
10974
10975         /*
10976          * Count the total number of transfers that are in progress,
10977          * and the number of transfers in progress from this master.
10978          * We linearly scan a list of all transfers; if this turns
10979          * out to be too slow, we could hash on the master address.
10980          */
10981         nxfrsin = nxfrsperns = 0;
10982         for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
10983              x != NULL;
10984              x = ISC_LIST_NEXT(x, statelink))
10985         {
10986                 isc_netaddr_t xip;
10987
10988                 LOCK_ZONE(x);
10989                 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
10990                 UNLOCK_ZONE(x);
10991
10992                 nxfrsin++;
10993                 if (isc_netaddr_equal(&xip, &masterip))
10994                         nxfrsperns++;
10995         }
10996
10997         /* Enforce quota. */
10998         if (nxfrsin >= maxtransfersin)
10999                 return (ISC_R_QUOTA);
11000
11001         if (nxfrsperns >= maxtransfersperns)
11002                 return (ISC_R_QUOTA);
11003
11004  gotquota:
11005         /*
11006          * We have sufficient quota.  Move the zone to the "xfrin_in_progress"
11007          * list and send it an event to let it start the actual transfer in the
11008          * context of its own task.
11009          */
11010         e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
11011                                got_transfer_quota, zone, sizeof(isc_event_t));
11012         if (e == NULL)
11013                 return (ISC_R_NOMEMORY);
11014
11015         LOCK_ZONE(zone);
11016         INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
11017         ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
11018         ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
11019         zone->statelist = &zmgr->xfrin_in_progress;
11020         isc_task_send(zone->task, &e);
11021         dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
11022         UNLOCK_ZONE(zone);
11023
11024         return (ISC_R_SUCCESS);
11025 }
11026
11027 void
11028 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
11029
11030         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11031         REQUIRE(iolimit > 0);
11032
11033         zmgr->iolimit = iolimit;
11034 }
11035
11036 isc_uint32_t
11037 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
11038
11039         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11040
11041         return (zmgr->iolimit);
11042 }
11043
11044 /*
11045  * Get permission to request a file handle from the OS.
11046  * An event will be sent to action when one is available.
11047  * There are two queues available (high and low), the high
11048  * queue will be serviced before the low one.
11049  *
11050  * zonemgr_putio() must be called after the event is delivered to
11051  * 'action'.
11052  */
11053
11054 static isc_result_t
11055 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
11056               isc_task_t *task, isc_taskaction_t action, void *arg,
11057               dns_io_t **iop)
11058 {
11059         dns_io_t *io;
11060         isc_boolean_t queue;
11061
11062         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11063         REQUIRE(iop != NULL && *iop == NULL);
11064
11065         io = isc_mem_get(zmgr->mctx, sizeof(*io));
11066         if (io == NULL)
11067                 return (ISC_R_NOMEMORY);
11068         io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
11069                                        action, arg, sizeof(*io->event));
11070         if (io->event == NULL) {
11071                 isc_mem_put(zmgr->mctx, io, sizeof(*io));
11072                 return (ISC_R_NOMEMORY);
11073         }
11074         io->zmgr = zmgr;
11075         io->high = high;
11076         io->task = NULL;
11077         isc_task_attach(task, &io->task);
11078         ISC_LINK_INIT(io, link);
11079         io->magic = IO_MAGIC;
11080
11081         LOCK(&zmgr->iolock);
11082         zmgr->ioactive++;
11083         queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
11084         if (queue) {
11085                 if (io->high)
11086                         ISC_LIST_APPEND(zmgr->high, io, link);
11087                 else
11088                         ISC_LIST_APPEND(zmgr->low, io, link);
11089         }
11090         UNLOCK(&zmgr->iolock);
11091         *iop = io;
11092
11093         if (!queue) {
11094                 isc_task_send(io->task, &io->event);
11095         }
11096         return (ISC_R_SUCCESS);
11097 }
11098
11099 static void
11100 zonemgr_putio(dns_io_t **iop) {
11101         dns_io_t *io;
11102         dns_io_t *next;
11103         dns_zonemgr_t *zmgr;
11104
11105         REQUIRE(iop != NULL);
11106         io = *iop;
11107         REQUIRE(DNS_IO_VALID(io));
11108
11109         *iop = NULL;
11110
11111         INSIST(!ISC_LINK_LINKED(io, link));
11112         INSIST(io->event == NULL);
11113
11114         zmgr = io->zmgr;
11115         isc_task_detach(&io->task);
11116         io->magic = 0;
11117         isc_mem_put(zmgr->mctx, io, sizeof(*io));
11118
11119         LOCK(&zmgr->iolock);
11120         INSIST(zmgr->ioactive > 0);
11121         zmgr->ioactive--;
11122         next = HEAD(zmgr->high);
11123         if (next == NULL)
11124                 next = HEAD(zmgr->low);
11125         if (next != NULL) {
11126                 if (next->high)
11127                         ISC_LIST_UNLINK(zmgr->high, next, link);
11128                 else
11129                         ISC_LIST_UNLINK(zmgr->low, next, link);
11130                 INSIST(next->event != NULL);
11131         }
11132         UNLOCK(&zmgr->iolock);
11133         if (next != NULL)
11134                 isc_task_send(next->task, &next->event);
11135 }
11136
11137 static void
11138 zonemgr_cancelio(dns_io_t *io) {
11139         isc_boolean_t send_event = ISC_FALSE;
11140
11141         REQUIRE(DNS_IO_VALID(io));
11142
11143         /*
11144          * If we are queued to be run then dequeue.
11145          */
11146         LOCK(&io->zmgr->iolock);
11147         if (ISC_LINK_LINKED(io, link)) {
11148                 if (io->high)
11149                         ISC_LIST_UNLINK(io->zmgr->high, io, link);
11150                 else
11151                         ISC_LIST_UNLINK(io->zmgr->low, io, link);
11152
11153                 send_event = ISC_TRUE;
11154                 INSIST(io->event != NULL);
11155         }
11156         UNLOCK(&io->zmgr->iolock);
11157         if (send_event) {
11158                 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
11159                 isc_task_send(io->task, &io->event);
11160         }
11161 }
11162
11163 static void
11164 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
11165         char *buf;
11166         int buflen;
11167         isc_result_t result;
11168
11169         buflen = strlen(path) + strlen(templat) + 2;
11170
11171         buf = isc_mem_get(zone->mctx, buflen);
11172         if (buf == NULL)
11173                 return;
11174
11175         result = isc_file_template(path, templat, buf, buflen);
11176         if (result != ISC_R_SUCCESS)
11177                 goto cleanup;
11178
11179         result = isc_file_renameunique(path, buf);
11180         if (result != ISC_R_SUCCESS)
11181                 goto cleanup;
11182
11183         dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
11184                      "renaming file to '%s' for failure analysis and "
11185                      "retransferring.", path, buf);
11186
11187  cleanup:
11188         isc_mem_put(zone->mctx, buf, buflen);
11189 }
11190
11191 #if 0
11192 /* Hook for ondestroy notification from a database. */
11193
11194 static void
11195 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
11196         dns_db_t *db = event->sender;
11197         UNUSED(task);
11198
11199         isc_event_free(&event);
11200
11201         isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11202                       DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11203                       "database (%p) destroyed", (void*) db);
11204 }
11205 #endif
11206
11207 void
11208 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
11209         isc_interval_t interval;
11210         isc_uint32_t s, ns;
11211         isc_uint32_t pertic;
11212         isc_result_t result;
11213
11214         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11215
11216         if (value == 0)
11217                 value = 1;
11218
11219         if (value == 1) {
11220                 s = 1;
11221                 ns = 0;
11222                 pertic = 1;
11223         } else if (value <= 10) {
11224                 s = 0;
11225                 ns = 1000000000 / value;
11226                 pertic = 1;
11227         } else {
11228                 s = 0;
11229                 ns = (1000000000 / value) * 10;
11230                 pertic = 10;
11231         }
11232
11233         isc_interval_set(&interval, s, ns);
11234         result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
11235         RUNTIME_CHECK(result == ISC_R_SUCCESS);
11236         isc_ratelimiter_setpertic(zmgr->rl, pertic);
11237
11238         zmgr->serialqueryrate = value;
11239 }
11240
11241 unsigned int
11242 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
11243         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11244
11245         return (zmgr->serialqueryrate);
11246 }
11247
11248 isc_boolean_t
11249 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
11250                         isc_sockaddr_t *local, isc_time_t *now)
11251 {
11252         unsigned int i;
11253         isc_rwlocktype_t locktype;
11254         isc_result_t result;
11255         isc_uint32_t seconds = isc_time_seconds(now);
11256
11257         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11258
11259         locktype = isc_rwlocktype_read;
11260         RWLOCK(&zmgr->urlock, locktype);
11261         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
11262                 if (zmgr->unreachable[i].expire >= seconds &&
11263                     isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
11264                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
11265                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
11266                         if (result == ISC_R_SUCCESS) {
11267                                 locktype = isc_rwlocktype_write;
11268                                 zmgr->unreachable[i].last = seconds;
11269                         }
11270                         break;
11271                 }
11272         }
11273         RWUNLOCK(&zmgr->urlock, locktype);
11274         return (ISC_TF(i < UNREACH_CHACHE_SIZE));
11275 }
11276
11277 void
11278 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
11279                            isc_sockaddr_t *local)
11280 {
11281         unsigned int i;
11282         isc_rwlocktype_t locktype;
11283         isc_result_t result;
11284
11285         char master[ISC_SOCKADDR_FORMATSIZE];
11286         char source[ISC_SOCKADDR_FORMATSIZE];
11287
11288         isc_sockaddr_format(remote, master, sizeof(master));
11289         isc_sockaddr_format(local, source, sizeof(source));
11290
11291         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11292
11293         locktype = isc_rwlocktype_read;
11294         RWLOCK(&zmgr->urlock, locktype);
11295         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
11296                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
11297                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
11298                         result = isc_rwlock_tryupgrade(&zmgr->urlock);
11299                         if (result == ISC_R_SUCCESS) {
11300                                 locktype = isc_rwlocktype_write;
11301                                 zmgr->unreachable[i].expire = 0;
11302                                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11303                                               DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
11304                                               "master %s (source %s) deleted "
11305                                               "from unreachable cache",
11306                                               master, source);
11307                         }
11308                         break;
11309                 }
11310         }
11311         RWUNLOCK(&zmgr->urlock, locktype);
11312 }
11313
11314 void
11315 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
11316                            isc_sockaddr_t *local, isc_time_t *now)
11317 {
11318         isc_uint32_t seconds = isc_time_seconds(now);
11319         isc_uint32_t last = seconds;
11320         unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
11321
11322         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11323
11324         RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
11325         for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
11326                 /* Existing entry? */
11327                 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
11328                     isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
11329                         break;
11330                 /* Empty slot? */
11331                 if (zmgr->unreachable[i].expire < seconds)
11332                         slot = i;
11333                 /* Least recently used slot? */
11334                 if (zmgr->unreachable[i].last < last) {
11335                         last = zmgr->unreachable[i].last;
11336                         oldest = i;
11337                 }
11338         }
11339         if (i < UNREACH_CHACHE_SIZE) {
11340                 /*
11341                  * Found a existing entry.  Update the expire timer and
11342                  * last usage timestamps.
11343                  */
11344                 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
11345                 zmgr->unreachable[i].last = seconds;
11346         } else if (slot != UNREACH_CHACHE_SIZE) {
11347                 /*
11348                  * Found a empty slot. Add a new entry to the cache.
11349                  */
11350                 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
11351                 zmgr->unreachable[slot].last = seconds;
11352                 zmgr->unreachable[slot].remote = *remote;
11353                 zmgr->unreachable[slot].local = *local;
11354         } else {
11355                 /*
11356                  * Replace the least recently used entry in the cache.
11357                  */
11358                 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
11359                 zmgr->unreachable[oldest].last = seconds;
11360                 zmgr->unreachable[oldest].remote = *remote;
11361                 zmgr->unreachable[oldest].local = *local;
11362         }
11363         RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
11364 }
11365
11366 void
11367 dns_zone_forcereload(dns_zone_t *zone) {
11368         REQUIRE(DNS_ZONE_VALID(zone));
11369
11370         if (zone->type == dns_zone_master)
11371                 return;
11372
11373         LOCK_ZONE(zone);
11374         DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
11375         UNLOCK_ZONE(zone);
11376         dns_zone_refresh(zone);
11377 }
11378
11379 isc_boolean_t
11380 dns_zone_isforced(dns_zone_t *zone) {
11381         REQUIRE(DNS_ZONE_VALID(zone));
11382
11383         return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
11384 }
11385
11386 isc_result_t
11387 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
11388         /*
11389          * This function is obsoleted.
11390          */
11391         UNUSED(zone);
11392         UNUSED(on);
11393         return (ISC_R_NOTIMPLEMENTED);
11394 }
11395
11396 isc_uint64_t *
11397 dns_zone_getstatscounters(dns_zone_t *zone) {
11398         /*
11399          * This function is obsoleted.
11400          */
11401         UNUSED(zone);
11402         return (NULL);
11403 }
11404
11405 void
11406 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
11407         REQUIRE(DNS_ZONE_VALID(zone));
11408         REQUIRE(zone->stats == NULL);
11409
11410         LOCK_ZONE(zone);
11411         zone->stats = NULL;
11412         isc_stats_attach(stats, &zone->stats);
11413         UNLOCK_ZONE(zone);
11414 }
11415
11416 void
11417 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
11418         REQUIRE(DNS_ZONE_VALID(zone));
11419
11420         LOCK_ZONE(zone);
11421         if (zone->requeststats_on && stats == NULL)
11422                 zone->requeststats_on = ISC_FALSE;
11423         else if (!zone->requeststats_on && stats != NULL) {
11424                 if (zone->requeststats == NULL) {
11425                         isc_stats_attach(stats, &zone->requeststats);
11426                         zone->requeststats_on = ISC_TRUE;
11427                 }
11428         }
11429         UNLOCK_ZONE(zone);
11430
11431         return;
11432 }
11433
11434 isc_stats_t *
11435 dns_zone_getrequeststats(dns_zone_t *zone) {
11436         /*
11437          * We don't lock zone for efficiency reason.  This is not catastrophic
11438          * because requeststats must always be valid when requeststats_on is
11439          * true.
11440          * Some counters may be incremented while requeststats_on is becoming
11441          * false, or some cannot be incremented just after the statistics are
11442          * installed, but it shouldn't matter much in practice.
11443          */
11444         if (zone->requeststats_on)
11445                 return (zone->requeststats);
11446         else
11447                 return (NULL);
11448 }
11449
11450 void
11451 dns_zone_dialup(dns_zone_t *zone) {
11452
11453         REQUIRE(DNS_ZONE_VALID(zone));
11454
11455         zone_debuglog(zone, "dns_zone_dialup", 3,
11456                       "notify = %d, refresh = %d",
11457                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
11458                       DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
11459
11460         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
11461                 dns_zone_notify(zone);
11462         if (zone->type != dns_zone_master &&
11463             DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11464                 dns_zone_refresh(zone);
11465 }
11466
11467 void
11468 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
11469         REQUIRE(DNS_ZONE_VALID(zone));
11470
11471         LOCK_ZONE(zone);
11472         DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
11473                          DNS_ZONEFLG_DIALREFRESH |
11474                          DNS_ZONEFLG_NOREFRESH);
11475         switch (dialup) {
11476         case dns_dialuptype_no:
11477                 break;
11478         case dns_dialuptype_yes:
11479                 DNS_ZONE_SETFLAG(zone,  (DNS_ZONEFLG_DIALNOTIFY |
11480                                  DNS_ZONEFLG_DIALREFRESH |
11481                                  DNS_ZONEFLG_NOREFRESH));
11482                 break;
11483         case dns_dialuptype_notify:
11484                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
11485                 break;
11486         case dns_dialuptype_notifypassive:
11487                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
11488                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
11489                 break;
11490         case dns_dialuptype_refresh:
11491                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
11492                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
11493                 break;
11494         case dns_dialuptype_passive:
11495                 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
11496                 break;
11497         default:
11498                 INSIST(0);
11499         }
11500         UNLOCK_ZONE(zone);
11501 }
11502
11503 isc_result_t
11504 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
11505         isc_result_t result = ISC_R_SUCCESS;
11506
11507         REQUIRE(DNS_ZONE_VALID(zone));
11508
11509         LOCK_ZONE(zone);
11510         result = dns_zone_setstring(zone, &zone->keydirectory, directory);
11511         UNLOCK_ZONE(zone);
11512
11513         return (result);
11514 }
11515
11516 const char *
11517 dns_zone_getkeydirectory(dns_zone_t *zone) {
11518         REQUIRE(DNS_ZONE_VALID(zone));
11519
11520         return (zone->keydirectory);
11521 }
11522
11523 unsigned int
11524 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
11525         dns_zone_t *zone;
11526         unsigned int count = 0;
11527
11528         REQUIRE(DNS_ZONEMGR_VALID(zmgr));
11529
11530         RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
11531         switch (state) {
11532         case DNS_ZONESTATE_XFERRUNNING:
11533                 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
11534                      zone != NULL;
11535                      zone = ISC_LIST_NEXT(zone, statelink))
11536                         count++;
11537                 break;
11538         case DNS_ZONESTATE_XFERDEFERRED:
11539                 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
11540                      zone != NULL;
11541                      zone = ISC_LIST_NEXT(zone, statelink))
11542                         count++;
11543                 break;
11544         case DNS_ZONESTATE_SOAQUERY:
11545                 for (zone = ISC_LIST_HEAD(zmgr->zones);
11546                      zone != NULL;
11547                      zone = ISC_LIST_NEXT(zone, link))
11548                         if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
11549                                 count++;
11550                 break;
11551         case DNS_ZONESTATE_ANY:
11552                 for (zone = ISC_LIST_HEAD(zmgr->zones);
11553                      zone != NULL;
11554                      zone = ISC_LIST_NEXT(zone, link)) {
11555                         dns_view_t *view = zone->view;
11556                         if (view != NULL && strcmp(view->name, "_bind") == 0)
11557                                 continue;
11558                         count++;
11559                 }
11560                 break;
11561         default:
11562                 INSIST(0);
11563         }
11564
11565         RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
11566
11567         return (count);
11568 }
11569
11570 isc_result_t
11571 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
11572         isc_boolean_t ok = ISC_TRUE;
11573         isc_boolean_t fail = ISC_FALSE;
11574         char namebuf[DNS_NAME_FORMATSIZE];
11575         char namebuf2[DNS_NAME_FORMATSIZE];
11576         char typebuf[DNS_RDATATYPE_FORMATSIZE];
11577         int level = ISC_LOG_WARNING;
11578         dns_name_t bad;
11579
11580         REQUIRE(DNS_ZONE_VALID(zone));
11581
11582         if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
11583                 return (ISC_R_SUCCESS);
11584
11585         if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
11586                 level = ISC_LOG_ERROR;
11587                 fail = ISC_TRUE;
11588         }
11589
11590         ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
11591         if (!ok) {
11592                 dns_name_format(name, namebuf, sizeof(namebuf));
11593                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
11594                 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
11595                              dns_result_totext(DNS_R_BADOWNERNAME));
11596                 if (fail)
11597                         return (DNS_R_BADOWNERNAME);
11598         }
11599
11600         dns_name_init(&bad, NULL);
11601         ok = dns_rdata_checknames(rdata, name, &bad);
11602         if (!ok) {
11603                 dns_name_format(name, namebuf, sizeof(namebuf));
11604                 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
11605                 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
11606                 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
11607                              namebuf2, dns_result_totext(DNS_R_BADNAME));
11608                 if (fail)
11609                         return (DNS_R_BADNAME);
11610         }
11611
11612         return (ISC_R_SUCCESS);
11613 }
11614
11615 void
11616 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
11617         REQUIRE(DNS_ZONE_VALID(zone));
11618         zone->checkmx = checkmx;
11619 }
11620
11621 void
11622 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
11623         REQUIRE(DNS_ZONE_VALID(zone));
11624         zone->checksrv = checksrv;
11625 }
11626
11627 void
11628 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
11629         REQUIRE(DNS_ZONE_VALID(zone));
11630         zone->checkns = checkns;
11631 }
11632
11633 void
11634 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
11635         REQUIRE(DNS_ZONE_VALID(zone));
11636
11637         LOCK_ZONE(zone);
11638         zone->isself = isself;
11639         zone->isselfarg = arg;
11640         UNLOCK_ZONE(zone);
11641 }
11642
11643 void
11644 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
11645         REQUIRE(DNS_ZONE_VALID(zone));
11646
11647         LOCK_ZONE(zone);
11648         zone->notifydelay = delay;
11649         UNLOCK_ZONE(zone);
11650 }
11651
11652 isc_uint32_t
11653 dns_zone_getnotifydelay(dns_zone_t *zone) {
11654         REQUIRE(DNS_ZONE_VALID(zone));
11655
11656         return (zone->notifydelay);
11657 }
11658
11659 isc_result_t
11660 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
11661                      isc_uint16_t keyid, isc_boolean_t delete)
11662 {
11663         isc_result_t result;
11664         REQUIRE(DNS_ZONE_VALID(zone));
11665
11666         dns_zone_log(zone, ISC_LOG_NOTICE,
11667                      "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
11668                      algorithm, keyid);
11669         LOCK_ZONE(zone);
11670         result = zone_signwithkey(zone, algorithm, keyid, delete);
11671         UNLOCK_ZONE(zone);
11672
11673         return (result);
11674 }
11675
11676 static const char *hex = "0123456789ABCDEF";
11677
11678 isc_result_t
11679 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
11680         isc_result_t result;
11681         char salt[255*2+1];
11682         unsigned int i, j;
11683
11684         REQUIRE(DNS_ZONE_VALID(zone));
11685
11686         if (nsec3param->salt_length != 0) {
11687                 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
11688                 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
11689                         salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
11690                         salt[j++] = hex[nsec3param->salt[i] & 0xf];
11691                 }
11692                 salt[j] = '\0';
11693         } else
11694                 strcpy(salt, "-");
11695         dns_zone_log(zone, ISC_LOG_NOTICE,
11696                      "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
11697                      nsec3param->hash, nsec3param->iterations,
11698                      salt);
11699         LOCK_ZONE(zone);
11700         result = zone_addnsec3chain(zone, nsec3param);
11701         UNLOCK_ZONE(zone);
11702
11703         return (result);
11704 }
11705
11706 void
11707 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
11708         REQUIRE(DNS_ZONE_VALID(zone));
11709
11710         if (nodes == 0)
11711                 nodes = 1;
11712         zone->nodes = nodes;
11713 }
11714
11715 void
11716 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
11717         REQUIRE(DNS_ZONE_VALID(zone));
11718
11719         /*
11720          * We treat signatures as a signed value so explicitly
11721          * limit its range here.
11722          */
11723         if (signatures > ISC_INT32_MAX)
11724                 signatures = ISC_INT32_MAX;
11725         else if (signatures == 0)
11726                 signatures = 1;
11727         zone->signatures = signatures;
11728 }
11729
11730 void
11731 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
11732         REQUIRE(DNS_ZONE_VALID(zone));
11733         zone->privatetype = type;
11734 }
11735
11736 dns_rdatatype_t
11737 dns_zone_getprivatetype(dns_zone_t *zone) {
11738         REQUIRE(DNS_ZONE_VALID(zone));
11739         return (zone->privatetype);
11740 }
11741
11742 static isc_result_t
11743 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
11744                  isc_boolean_t delete)
11745 {
11746         dns_signing_t *signing;
11747         dns_signing_t *current;
11748         isc_result_t result = ISC_R_SUCCESS;
11749         isc_time_t now;
11750
11751         signing = isc_mem_get(zone->mctx, sizeof *signing);
11752         if (signing == NULL)
11753                 return (ISC_R_NOMEMORY);
11754
11755         signing->magic = 0;
11756         signing->db  = NULL;
11757         signing->dbiterator = NULL;
11758         signing->algorithm = algorithm;
11759         signing->keyid = keyid;
11760         signing->delete = delete;
11761         signing->done = ISC_FALSE;
11762
11763         TIME_NOW(&now);
11764
11765         for (current = ISC_LIST_HEAD(zone->signing);
11766              current != NULL;
11767              current = ISC_LIST_NEXT(current, link)) {
11768                 if (current->db == zone->db &&
11769                     current->algorithm == signing->algorithm &&
11770                     current->keyid == signing->keyid) {
11771                         if (current->delete != signing->delete)
11772                                 current->done = ISC_TRUE;
11773                         else
11774                                 goto cleanup;
11775                 }
11776         }
11777
11778         if (zone->db != NULL) {
11779                 dns_db_attach(zone->db, &signing->db);
11780                 result = dns_db_createiterator(signing->db, 0,
11781                                                &signing->dbiterator);
11782
11783                 if (result == ISC_R_SUCCESS)
11784                         result = dns_dbiterator_first(signing->dbiterator);
11785                 if (result == ISC_R_SUCCESS) {
11786                         dns_dbiterator_pause(signing->dbiterator);
11787                         ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
11788                         signing = NULL;
11789                         if (isc_time_isepoch(&zone->signingtime)) {
11790                                 zone->signingtime = now;
11791                                 if (zone->task != NULL)
11792                                         zone_settimer(zone, &now);
11793                         }
11794                 }
11795         } else
11796                 result = ISC_R_NOTFOUND;
11797
11798  cleanup:
11799         if (signing != NULL) {
11800                 if (signing->db != NULL)
11801                         dns_db_detach(&signing->db);
11802                 if (signing->dbiterator != NULL)
11803                         dns_dbiterator_destroy(&signing->dbiterator);
11804                 isc_mem_put(zone->mctx, signing, sizeof *signing);
11805         }
11806         return (result);
11807 }