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