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