Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / zone.c
blob96a4f0717b509bc09d63a1a2c08e9f8f4768aff6
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: zone.c,v 1.540 2009/12/07 20:51:12 each Exp */
22 /*! \file */
24 #include <config.h>
25 #include <errno.h>
27 #include <isc/file.h>
28 #include <isc/mutex.h>
29 #include <isc/print.h>
30 #include <isc/random.h>
31 #include <isc/ratelimiter.h>
32 #include <isc/refcount.h>
33 #include <isc/rwlock.h>
34 #include <isc/serial.h>
35 #include <isc/strerror.h>
36 #include <isc/stats.h>
37 #include <isc/stdtime.h>
38 #include <isc/string.h>
39 #include <isc/taskpool.h>
40 #include <isc/timer.h>
41 #include <isc/util.h>
43 #include <dns/acache.h>
44 #include <dns/acl.h>
45 #include <dns/adb.h>
46 #include <dns/callbacks.h>
47 #include <dns/db.h>
48 #include <dns/dbiterator.h>
49 #include <dns/dnssec.h>
50 #include <dns/events.h>
51 #include <dns/journal.h>
52 #include <dns/keydata.h>
53 #include <dns/keytable.h>
54 #include <dns/keyvalues.h>
55 #include <dns/log.h>
56 #include <dns/master.h>
57 #include <dns/masterdump.h>
58 #include <dns/message.h>
59 #include <dns/name.h>
60 #include <dns/nsec.h>
61 #include <dns/nsec3.h>
62 #include <dns/peer.h>
63 #include <dns/private.h>
64 #include <dns/rbt.h>
65 #include <dns/rcode.h>
66 #include <dns/rdataclass.h>
67 #include <dns/rdatalist.h>
68 #include <dns/rdataset.h>
69 #include <dns/rdatasetiter.h>
70 #include <dns/rdatastruct.h>
71 #include <dns/rdatatype.h>
72 #include <dns/request.h>
73 #include <dns/resolver.h>
74 #include <dns/result.h>
75 #include <dns/rriterator.h>
76 #include <dns/soa.h>
77 #include <dns/ssu.h>
78 #include <dns/stats.h>
79 #include <dns/tsig.h>
80 #include <dns/xfrin.h>
81 #include <dns/zone.h>
83 #include <dst/dst.h>
85 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
86 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
88 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
89 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
91 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
92 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
94 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
95 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
97 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
98 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
100 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
101 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
103 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
104 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
107 * Ensure 'a' is at least 'min' but not more than 'max'.
109 #define RANGE(a, min, max) \
110 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
112 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
115 * Default values.
117 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
118 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
119 #define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
121 #ifndef DNS_MAX_EXPIRE
122 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
123 #endif
125 #ifndef DNS_DUMP_DELAY
126 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
127 #endif
129 typedef struct dns_notify dns_notify_t;
130 typedef struct dns_stub dns_stub_t;
131 typedef struct dns_load dns_load_t;
132 typedef struct dns_forward dns_forward_t;
133 typedef struct dns_io dns_io_t;
134 typedef ISC_LIST(dns_io_t) dns_iolist_t;
135 typedef struct dns_signing dns_signing_t;
136 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
137 typedef struct dns_nsec3chain dns_nsec3chain_t;
138 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
139 typedef struct dns_keyfetch dns_keyfetch_t;
141 #define DNS_ZONE_CHECKLOCK
142 #ifdef DNS_ZONE_CHECKLOCK
143 #define LOCK_ZONE(z) \
144 do { LOCK(&(z)->lock); \
145 INSIST((z)->locked == ISC_FALSE); \
146 (z)->locked = ISC_TRUE; \
147 } while (0)
148 #define UNLOCK_ZONE(z) \
149 do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)
150 #define LOCKED_ZONE(z) ((z)->locked)
151 #else
152 #define LOCK_ZONE(z) LOCK(&(z)->lock)
153 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
154 #define LOCKED_ZONE(z) ISC_TRUE
155 #endif
157 #ifdef ISC_RWLOCK_USEATOMIC
158 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
159 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
160 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
161 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
162 #else
163 #define ZONEDB_INITLOCK(l) isc_mutex_init(l)
164 #define ZONEDB_DESTROYLOCK(l) DESTROYLOCK(l)
165 #define ZONEDB_LOCK(l, t) LOCK(l)
166 #define ZONEDB_UNLOCK(l, t) UNLOCK(l)
167 #endif
169 struct dns_zone {
170 /* Unlocked */
171 unsigned int magic;
172 isc_mutex_t lock;
173 #ifdef DNS_ZONE_CHECKLOCK
174 isc_boolean_t locked;
175 #endif
176 isc_mem_t *mctx;
177 isc_refcount_t erefs;
179 #ifdef ISC_RWLOCK_USEATOMIC
180 isc_rwlock_t dblock;
181 #else
182 isc_mutex_t dblock;
183 #endif
184 dns_db_t *db; /* Locked by dblock */
186 /* Locked */
187 dns_zonemgr_t *zmgr;
188 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
189 isc_timer_t *timer;
190 unsigned int irefs;
191 dns_name_t origin;
192 char *masterfile;
193 dns_masterformat_t masterformat;
194 char *journal;
195 isc_int32_t journalsize;
196 dns_rdataclass_t rdclass;
197 dns_zonetype_t type;
198 unsigned int flags;
199 unsigned int options;
200 unsigned int db_argc;
201 char **db_argv;
202 isc_time_t expiretime;
203 isc_time_t refreshtime;
204 isc_time_t dumptime;
205 isc_time_t loadtime;
206 isc_time_t notifytime;
207 isc_time_t resigntime;
208 isc_time_t keywarntime;
209 isc_time_t signingtime;
210 isc_time_t nsec3chaintime;
211 isc_time_t refreshkeytime;
212 isc_uint32_t refreshkeycount;
213 isc_uint32_t refresh;
214 isc_uint32_t retry;
215 isc_uint32_t expire;
216 isc_uint32_t minimum;
217 isc_stdtime_t key_expiry;
218 char *keydirectory;
220 isc_uint32_t maxrefresh;
221 isc_uint32_t minrefresh;
222 isc_uint32_t maxretry;
223 isc_uint32_t minretry;
225 isc_sockaddr_t *masters;
226 dns_name_t **masterkeynames;
227 isc_boolean_t *mastersok;
228 unsigned int masterscnt;
229 unsigned int curmaster;
230 isc_sockaddr_t masteraddr;
231 dns_notifytype_t notifytype;
232 isc_sockaddr_t *notify;
233 unsigned int notifycnt;
234 isc_sockaddr_t notifyfrom;
235 isc_task_t *task;
236 isc_sockaddr_t notifysrc4;
237 isc_sockaddr_t notifysrc6;
238 isc_sockaddr_t xfrsource4;
239 isc_sockaddr_t xfrsource6;
240 isc_sockaddr_t altxfrsource4;
241 isc_sockaddr_t altxfrsource6;
242 isc_sockaddr_t sourceaddr;
243 dns_xfrin_ctx_t *xfr; /* task locked */
244 dns_tsigkey_t *tsigkey; /* key used for xfr */
245 /* Access Control Lists */
246 dns_acl_t *update_acl;
247 dns_acl_t *forward_acl;
248 dns_acl_t *notify_acl;
249 dns_acl_t *query_acl;
250 dns_acl_t *queryon_acl;
251 dns_acl_t *xfr_acl;
252 isc_boolean_t update_disabled;
253 isc_boolean_t zero_no_soa_ttl;
254 dns_severity_t check_names;
255 ISC_LIST(dns_notify_t) notifies;
256 dns_request_t *request;
257 dns_loadctx_t *lctx;
258 dns_io_t *readio;
259 dns_dumpctx_t *dctx;
260 dns_io_t *writeio;
261 isc_uint32_t maxxfrin;
262 isc_uint32_t maxxfrout;
263 isc_uint32_t idlein;
264 isc_uint32_t idleout;
265 isc_event_t ctlevent;
266 dns_ssutable_t *ssutable;
267 isc_uint32_t sigvalidityinterval;
268 isc_uint32_t sigresigninginterval;
269 dns_view_t *view;
270 dns_acache_t *acache;
271 dns_checkmxfunc_t checkmx;
272 dns_checksrvfunc_t checksrv;
273 dns_checknsfunc_t checkns;
275 * Zones in certain states such as "waiting for zone transfer"
276 * or "zone transfer in progress" are kept on per-state linked lists
277 * in the zone manager using the 'statelink' field. The 'statelist'
278 * field points at the list the zone is currently on. It the zone
279 * is not on any such list, statelist is NULL.
281 ISC_LINK(dns_zone_t) statelink;
282 dns_zonelist_t *statelist;
284 * Statistics counters about zone management.
286 isc_stats_t *stats;
288 * Optional per-zone statistics counters. Counted outside of this
289 * module.
291 isc_boolean_t requeststats_on;
292 isc_stats_t *requeststats;
293 isc_uint32_t notifydelay;
294 dns_isselffunc_t isself;
295 void *isselfarg;
297 char * strnamerd;
298 char * strname;
299 char * strrdclass;
300 char * strviewname;
303 * Serial number for deferred journal compaction.
305 isc_uint32_t compact_serial;
307 * Keys that are signing the zone for the first time.
309 dns_signinglist_t signing;
310 dns_nsec3chainlist_t nsec3chain;
312 * Signing / re-signing quantum stopping parameters.
314 isc_uint32_t signatures;
315 isc_uint32_t nodes;
316 dns_rdatatype_t privatetype;
319 * Autosigning/key-maintenance options
321 isc_uint32_t keyopts;
324 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
325 #define DNS_ZONE_SETFLAG(z,f) do { \
326 INSIST(LOCKED_ZONE(z)); \
327 (z)->flags |= (f); \
328 } while (0)
329 #define DNS_ZONE_CLRFLAG(z,f) do { \
330 INSIST(LOCKED_ZONE(z)); \
331 (z)->flags &= ~(f); \
332 } while (0)
333 /* XXX MPA these may need to go back into zone.h */
334 #define DNS_ZONEFLG_REFRESH 0x00000001U /*%< refresh check in progress */
335 #define DNS_ZONEFLG_NEEDDUMP 0x00000002U /*%< zone need consolidation */
336 #define DNS_ZONEFLG_USEVC 0x00000004U /*%< use tcp for refresh query */
337 #define DNS_ZONEFLG_DUMPING 0x00000008U /*%< a dump is in progress */
338 #define DNS_ZONEFLG_HASINCLUDE 0x00000010U /*%< $INCLUDE in zone file */
339 #define DNS_ZONEFLG_LOADED 0x00000020U /*%< database has loaded */
340 #define DNS_ZONEFLG_EXITING 0x00000040U /*%< zone is being destroyed */
341 #define DNS_ZONEFLG_EXPIRED 0x00000080U /*%< zone has expired */
342 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /*%< refresh check needed */
343 #define DNS_ZONEFLG_UPTODATE 0x00000200U /*%< zone contents are
344 * uptodate */
345 #define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /*%< need to send out notify
346 * messages */
347 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /*%< generate a journal diff on
348 * reload */
349 #define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
350 * zone with no masters
351 * occurred */
352 #define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
353 #define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
354 * from SOA (if not set, we
355 * are still using
356 * default timer values) */
357 #define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
358 #define DNS_ZONEFLG_NOREFRESH 0x00010000U
359 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
360 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
361 #define DNS_ZONEFLG_SHUTDOWN 0x00080000U
362 #define DNS_ZONEFLAG_NOIXFR 0x00100000U /*%< IXFR failed, force AXFR */
363 #define DNS_ZONEFLG_FLUSH 0x00200000U
364 #define DNS_ZONEFLG_NOEDNS 0x00400000U
365 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
366 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
367 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
368 #define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */
369 #define DNS_ZONEFLG_THAW 0x08000000U
370 #define DNS_ZONEFLG_NOTIFYRESIGN 0x10000000U
372 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
373 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
375 /* Flags for zone_load() */
376 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
377 #define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
378 load. */
380 #define UNREACH_CHACHE_SIZE 10U
381 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
383 #define CHECK(op) \
384 do { result = (op); \
385 if (result != ISC_R_SUCCESS) goto failure; \
386 } while (0)
388 struct dns_unreachable {
389 isc_sockaddr_t remote;
390 isc_sockaddr_t local;
391 isc_uint32_t expire;
392 isc_uint32_t last;
395 struct dns_zonemgr {
396 unsigned int magic;
397 isc_mem_t * mctx;
398 int refs; /* Locked by rwlock */
399 isc_taskmgr_t * taskmgr;
400 isc_timermgr_t * timermgr;
401 isc_socketmgr_t * socketmgr;
402 isc_taskpool_t * zonetasks;
403 isc_task_t * task;
404 isc_ratelimiter_t * rl;
405 isc_rwlock_t rwlock;
406 isc_mutex_t iolock;
408 /* Locked by rwlock. */
409 dns_zonelist_t zones;
410 dns_zonelist_t waiting_for_xfrin;
411 dns_zonelist_t xfrin_in_progress;
413 /* Configuration data. */
414 isc_uint32_t transfersin;
415 isc_uint32_t transfersperns;
416 unsigned int serialqueryrate;
418 /* Locked by iolock */
419 isc_uint32_t iolimit;
420 isc_uint32_t ioactive;
421 dns_iolist_t high;
422 dns_iolist_t low;
424 /* Locked by rwlock. */
425 /* LRU cache */
426 struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
430 * Hold notify state.
432 struct dns_notify {
433 unsigned int magic;
434 unsigned int flags;
435 isc_mem_t *mctx;
436 dns_zone_t *zone;
437 dns_adbfind_t *find;
438 dns_request_t *request;
439 dns_name_t ns;
440 isc_sockaddr_t dst;
441 ISC_LINK(dns_notify_t) link;
444 #define DNS_NOTIFY_NOSOA 0x0001U
447 * dns_stub holds state while performing a 'stub' transfer.
448 * 'db' is the zone's 'db' or a new one if this is the initial
449 * transfer.
452 struct dns_stub {
453 unsigned int magic;
454 isc_mem_t *mctx;
455 dns_zone_t *zone;
456 dns_db_t *db;
457 dns_dbversion_t *version;
461 * Hold load state.
463 struct dns_load {
464 unsigned int magic;
465 isc_mem_t *mctx;
466 dns_zone_t *zone;
467 dns_db_t *db;
468 isc_time_t loadtime;
469 dns_rdatacallbacks_t callbacks;
473 * Hold forward state.
475 struct dns_forward {
476 unsigned int magic;
477 isc_mem_t *mctx;
478 dns_zone_t *zone;
479 isc_buffer_t *msgbuf;
480 dns_request_t *request;
481 isc_uint32_t which;
482 isc_sockaddr_t addr;
483 dns_updatecallback_t callback;
484 void *callback_arg;
488 * Hold IO request state.
490 struct dns_io {
491 unsigned int magic;
492 dns_zonemgr_t *zmgr;
493 isc_boolean_t high;
494 isc_task_t *task;
495 ISC_LINK(dns_io_t) link;
496 isc_event_t *event;
500 * Hold state for when we are signing a zone with a new
501 * DNSKEY as result of an update.
503 struct dns_signing {
504 unsigned int magic;
505 dns_db_t *db;
506 dns_dbiterator_t *dbiterator;
507 dns_secalg_t algorithm;
508 isc_uint16_t keyid;
509 isc_boolean_t delete;
510 isc_boolean_t done;
511 ISC_LINK(dns_signing_t) link;
514 struct dns_nsec3chain {
515 unsigned int magic;
516 dns_db_t *db;
517 dns_dbiterator_t *dbiterator;
518 dns_rdata_nsec3param_t nsec3param;
519 unsigned char salt[255];
520 isc_boolean_t done;
521 isc_boolean_t seen_nsec;
522 isc_boolean_t delete_nsec;
523 isc_boolean_t save_delete_nsec;
524 ISC_LINK(dns_nsec3chain_t) link;
526 /*%<
527 * 'dbiterator' contains a iterator for the database. If we are creating
528 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
529 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
530 * iterated.
532 * 'nsec3param' contains the parameters of the NSEC3 chain being created
533 * or removed.
535 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
537 * 'seen_nsec' will be set to true if, while iterating the zone to create a
538 * NSEC3 chain, a NSEC record is seen.
540 * 'delete_nsec' will be set to true if, at the completion of the creation
541 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
542 * are in the process of deleting the NSEC chain.
544 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
545 * so it can be recovered in the event of a error.
548 struct dns_keyfetch {
549 dns_fixedname_t name;
550 dns_rdataset_t keydataset;
551 dns_rdataset_t dnskeyset;
552 dns_rdataset_t dnskeysigset;
553 dns_zone_t *zone;
554 dns_db_t *db;
555 dns_fetch_t *fetch;
558 #define HOUR 3600
559 #define DAY (24*HOUR)
560 #define MONTH (30*DAY)
562 #define SEND_BUFFER_SIZE 2048
564 static void zone_settimer(dns_zone_t *, isc_time_t *);
565 static void cancel_refresh(dns_zone_t *);
566 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
567 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
568 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
569 ISC_FORMAT_PRINTF(3, 4);
570 static void queue_xfrin(dns_zone_t *zone);
571 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
572 dns_diff_t *diff, dns_diffop_t op,
573 dns_name_t *name, dns_ttl_t ttl,
574 dns_rdata_t *rdata);
575 static void zone_unload(dns_zone_t *zone);
576 static void zone_expire(dns_zone_t *zone);
577 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
578 static void zone_idetach(dns_zone_t **zonep);
579 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
580 isc_boolean_t dump);
581 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
582 static inline void zone_detachdb(dns_zone_t *zone);
583 static isc_result_t default_journal(dns_zone_t *zone);
584 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
585 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
586 isc_time_t loadtime, isc_result_t result);
587 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
588 static void zone_shutdown(isc_task_t *, isc_event_t *);
589 static void zone_loaddone(void *arg, isc_result_t result);
590 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
591 isc_time_t loadtime);
592 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
593 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
594 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
595 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
597 #if 0
598 /* ondestroy example */
599 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
600 #endif
602 static void refresh_callback(isc_task_t *, isc_event_t *);
603 static void stub_callback(isc_task_t *, isc_event_t *);
604 static void queue_soa_query(dns_zone_t *zone);
605 static void soa_query(isc_task_t *, isc_event_t *);
606 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
607 dns_stub_t *stub);
608 static int message_count(dns_message_t *msg, dns_section_t section,
609 dns_rdatatype_t type);
610 static void notify_cancel(dns_zone_t *zone);
611 static void notify_find_address(dns_notify_t *notify);
612 static void notify_send(dns_notify_t *notify);
613 static isc_result_t notify_createmessage(dns_zone_t *zone,
614 unsigned int flags,
615 dns_message_t **messagep);
616 static void notify_done(isc_task_t *task, isc_event_t *event);
617 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
618 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
619 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
620 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
621 dns_zone_t *zone);
622 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
623 static void zonemgr_free(dns_zonemgr_t *zmgr);
624 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
625 isc_task_t *task, isc_taskaction_t action,
626 void *arg, dns_io_t **iop);
627 static void zonemgr_putio(dns_io_t **iop);
628 static void zonemgr_cancelio(dns_io_t *io);
630 static isc_result_t
631 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
632 unsigned int *soacount, isc_uint32_t *serial,
633 isc_uint32_t *refresh, isc_uint32_t *retry,
634 isc_uint32_t *expire, isc_uint32_t *minimum,
635 unsigned int *errors);
637 static void zone_freedbargs(dns_zone_t *zone);
638 static void forward_callback(isc_task_t *task, isc_event_t *event);
639 static void zone_saveunique(dns_zone_t *zone, const char *path,
640 const char *templat);
641 static void zone_maintenance(dns_zone_t *zone);
642 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
643 static void dump_done(void *arg, isc_result_t result);
644 static isc_boolean_t dns_zonemgr_unreachable(dns_zonemgr_t *zmgr,
645 isc_sockaddr_t *remote,
646 isc_sockaddr_t *local,
647 isc_time_t *now);
648 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
649 isc_uint16_t keyid, isc_boolean_t delete);
650 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
651 dns_dbnode_t *node, dns_name_t *name,
652 dns_diff_t *diff);
653 static isc_result_t zone_rekey(dns_zone_t *zone);
655 #define ENTER zone_debuglog(zone, me, 1, "enter")
657 static const unsigned int dbargc_default = 1;
658 static const char *dbargv_default[] = { "rbt" };
660 #define DNS_ZONE_JITTER_ADD(a, b, c) \
661 do { \
662 isc_interval_t _i; \
663 isc_uint32_t _j; \
664 _j = isc_random_jitter((b), (b)/4); \
665 isc_interval_set(&_i, _j, 0); \
666 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
667 dns_zone_log(zone, ISC_LOG_WARNING, \
668 "epoch approaching: upgrade required: " \
669 "now + %s failed", #b); \
670 isc_interval_set(&_i, _j/2, 0); \
671 (void)isc_time_add((a), &_i, (c)); \
673 } while (0)
675 #define DNS_ZONE_TIME_ADD(a, b, c) \
676 do { \
677 isc_interval_t _i; \
678 isc_interval_set(&_i, (b), 0); \
679 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
680 dns_zone_log(zone, ISC_LOG_WARNING, \
681 "epoch approaching: upgrade required: " \
682 "now + %s failed", #b); \
683 isc_interval_set(&_i, (b)/2, 0); \
684 (void)isc_time_add((a), &_i, (c)); \
686 } while (0)
689 * Increment resolver-related statistics counters. Zone must be locked.
691 static inline void
692 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
693 if (zone->stats != NULL)
694 isc_stats_increment(zone->stats, counter);
697 /***
698 *** Public functions.
699 ***/
701 isc_result_t
702 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
703 isc_result_t result;
704 dns_zone_t *zone;
705 isc_time_t now;
707 REQUIRE(zonep != NULL && *zonep == NULL);
708 REQUIRE(mctx != NULL);
710 TIME_NOW(&now);
711 zone = isc_mem_get(mctx, sizeof(*zone));
712 if (zone == NULL)
713 return (ISC_R_NOMEMORY);
715 zone->mctx = NULL;
716 isc_mem_attach(mctx, &zone->mctx);
718 result = isc_mutex_init(&zone->lock);
719 if (result != ISC_R_SUCCESS)
720 goto free_zone;
722 result = ZONEDB_INITLOCK(&zone->dblock);
723 if (result != ISC_R_SUCCESS)
724 goto free_mutex;
726 /* XXX MPA check that all elements are initialised */
727 #ifdef DNS_ZONE_CHECKLOCK
728 zone->locked = ISC_FALSE;
729 #endif
730 zone->db = NULL;
731 zone->zmgr = NULL;
732 ISC_LINK_INIT(zone, link);
733 result = isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
734 if (result != ISC_R_SUCCESS)
735 goto free_dblock;
736 zone->irefs = 0;
737 dns_name_init(&zone->origin, NULL);
738 zone->strnamerd = NULL;
739 zone->strname = NULL;
740 zone->strrdclass = NULL;
741 zone->strviewname = NULL;
742 zone->masterfile = NULL;
743 zone->masterformat = dns_masterformat_none;
744 zone->keydirectory = NULL;
745 zone->journalsize = -1;
746 zone->journal = NULL;
747 zone->rdclass = dns_rdataclass_none;
748 zone->type = dns_zone_none;
749 zone->flags = 0;
750 zone->options = 0;
751 zone->keyopts = 0;
752 zone->db_argc = 0;
753 zone->db_argv = NULL;
754 isc_time_settoepoch(&zone->expiretime);
755 isc_time_settoepoch(&zone->refreshtime);
756 isc_time_settoepoch(&zone->dumptime);
757 isc_time_settoepoch(&zone->loadtime);
758 zone->notifytime = now;
759 isc_time_settoepoch(&zone->resigntime);
760 isc_time_settoepoch(&zone->keywarntime);
761 isc_time_settoepoch(&zone->signingtime);
762 isc_time_settoepoch(&zone->nsec3chaintime);
763 isc_time_settoepoch(&zone->refreshkeytime);
764 zone->refreshkeycount = 0;
765 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
766 zone->retry = DNS_ZONE_DEFAULTRETRY;
767 zone->expire = 0;
768 zone->minimum = 0;
769 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
770 zone->minrefresh = DNS_ZONE_MINREFRESH;
771 zone->maxretry = DNS_ZONE_MAXRETRY;
772 zone->minretry = DNS_ZONE_MINRETRY;
773 zone->masters = NULL;
774 zone->masterkeynames = NULL;
775 zone->mastersok = NULL;
776 zone->masterscnt = 0;
777 zone->curmaster = 0;
778 zone->notify = NULL;
779 zone->notifytype = dns_notifytype_yes;
780 zone->notifycnt = 0;
781 zone->task = NULL;
782 zone->update_acl = NULL;
783 zone->forward_acl = NULL;
784 zone->notify_acl = NULL;
785 zone->query_acl = NULL;
786 zone->queryon_acl = NULL;
787 zone->xfr_acl = NULL;
788 zone->update_disabled = ISC_FALSE;
789 zone->zero_no_soa_ttl = ISC_TRUE;
790 zone->check_names = dns_severity_ignore;
791 zone->request = NULL;
792 zone->lctx = NULL;
793 zone->readio = NULL;
794 zone->dctx = NULL;
795 zone->writeio = NULL;
796 zone->timer = NULL;
797 zone->idlein = DNS_DEFAULT_IDLEIN;
798 zone->idleout = DNS_DEFAULT_IDLEOUT;
799 ISC_LIST_INIT(zone->notifies);
800 isc_sockaddr_any(&zone->notifysrc4);
801 isc_sockaddr_any6(&zone->notifysrc6);
802 isc_sockaddr_any(&zone->xfrsource4);
803 isc_sockaddr_any6(&zone->xfrsource6);
804 isc_sockaddr_any(&zone->altxfrsource4);
805 isc_sockaddr_any6(&zone->altxfrsource6);
806 zone->xfr = NULL;
807 zone->tsigkey = NULL;
808 zone->maxxfrin = MAX_XFER_TIME;
809 zone->maxxfrout = MAX_XFER_TIME;
810 zone->ssutable = NULL;
811 zone->sigvalidityinterval = 30 * 24 * 3600;
812 zone->sigresigninginterval = 7 * 24 * 3600;
813 zone->view = NULL;
814 zone->acache = NULL;
815 zone->checkmx = NULL;
816 zone->checksrv = NULL;
817 zone->checkns = NULL;
818 ISC_LINK_INIT(zone, statelink);
819 zone->statelist = NULL;
820 zone->stats = NULL;
821 zone->requeststats_on = ISC_FALSE;
822 zone->requeststats = NULL;
823 zone->notifydelay = 5;
824 zone->isself = NULL;
825 zone->isselfarg = NULL;
826 ISC_LIST_INIT(zone->signing);
827 ISC_LIST_INIT(zone->nsec3chain);
828 zone->signatures = 10;
829 zone->nodes = 100;
830 zone->privatetype = (dns_rdatatype_t)0xffffU;
832 zone->magic = ZONE_MAGIC;
834 /* Must be after magic is set. */
835 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
836 if (result != ISC_R_SUCCESS)
837 goto free_erefs;
839 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
840 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
841 NULL, NULL);
842 *zonep = zone;
843 return (ISC_R_SUCCESS);
845 free_erefs:
846 isc_refcount_decrement(&zone->erefs, NULL);
847 isc_refcount_destroy(&zone->erefs);
849 free_dblock:
850 ZONEDB_DESTROYLOCK(&zone->dblock);
852 free_mutex:
853 DESTROYLOCK(&zone->lock);
855 free_zone:
856 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
857 return (result);
861 * Free a zone. Because we require that there be no more
862 * outstanding events or references, no locking is necessary.
864 static void
865 zone_free(dns_zone_t *zone) {
866 isc_mem_t *mctx = NULL;
867 dns_signing_t *signing;
868 dns_nsec3chain_t *nsec3chain;
870 REQUIRE(DNS_ZONE_VALID(zone));
871 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
872 REQUIRE(zone->irefs == 0);
873 REQUIRE(!LOCKED_ZONE(zone));
874 REQUIRE(zone->timer == NULL);
877 * Managed objects. Order is important.
879 if (zone->request != NULL)
880 dns_request_destroy(&zone->request); /* XXXMPA */
881 INSIST(zone->readio == NULL);
882 INSIST(zone->statelist == NULL);
883 INSIST(zone->writeio == NULL);
885 if (zone->task != NULL)
886 isc_task_detach(&zone->task);
887 if (zone->zmgr != NULL)
888 dns_zonemgr_releasezone(zone->zmgr, zone);
890 /* Unmanaged objects */
891 for (signing = ISC_LIST_HEAD(zone->signing);
892 signing != NULL;
893 signing = ISC_LIST_HEAD(zone->signing)) {
894 ISC_LIST_UNLINK(zone->signing, signing, link);
895 dns_db_detach(&signing->db);
896 dns_dbiterator_destroy(&signing->dbiterator);
897 isc_mem_put(zone->mctx, signing, sizeof *signing);
899 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
900 nsec3chain != NULL;
901 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
902 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
903 dns_db_detach(&nsec3chain->db);
904 dns_dbiterator_destroy(&nsec3chain->dbiterator);
905 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
907 if (zone->masterfile != NULL)
908 isc_mem_free(zone->mctx, zone->masterfile);
909 zone->masterfile = NULL;
910 if (zone->keydirectory != NULL)
911 isc_mem_free(zone->mctx, zone->keydirectory);
912 zone->keydirectory = NULL;
913 zone->journalsize = -1;
914 if (zone->journal != NULL)
915 isc_mem_free(zone->mctx, zone->journal);
916 zone->journal = NULL;
917 if (zone->stats != NULL)
918 isc_stats_detach(&zone->stats);
919 if (zone->requeststats != NULL)
920 isc_stats_detach(&zone->requeststats);
921 if (zone->db != NULL)
922 zone_detachdb(zone);
923 if (zone->acache != NULL)
924 dns_acache_detach(&zone->acache);
925 zone_freedbargs(zone);
926 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
927 == ISC_R_SUCCESS);
928 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
929 == ISC_R_SUCCESS);
930 zone->check_names = dns_severity_ignore;
931 if (zone->update_acl != NULL)
932 dns_acl_detach(&zone->update_acl);
933 if (zone->forward_acl != NULL)
934 dns_acl_detach(&zone->forward_acl);
935 if (zone->notify_acl != NULL)
936 dns_acl_detach(&zone->notify_acl);
937 if (zone->query_acl != NULL)
938 dns_acl_detach(&zone->query_acl);
939 if (zone->queryon_acl != NULL)
940 dns_acl_detach(&zone->queryon_acl);
941 if (zone->xfr_acl != NULL)
942 dns_acl_detach(&zone->xfr_acl);
943 if (dns_name_dynamic(&zone->origin))
944 dns_name_free(&zone->origin, zone->mctx);
945 if (zone->strnamerd != NULL)
946 isc_mem_free(zone->mctx, zone->strnamerd);
947 if (zone->strname != NULL)
948 isc_mem_free(zone->mctx, zone->strname);
949 if (zone->strrdclass != NULL)
950 isc_mem_free(zone->mctx, zone->strrdclass);
951 if (zone->strviewname != NULL)
952 isc_mem_free(zone->mctx, zone->strviewname);
953 if (zone->ssutable != NULL)
954 dns_ssutable_detach(&zone->ssutable);
956 /* last stuff */
957 ZONEDB_DESTROYLOCK(&zone->dblock);
958 DESTROYLOCK(&zone->lock);
959 isc_refcount_destroy(&zone->erefs);
960 zone->magic = 0;
961 mctx = zone->mctx;
962 isc_mem_put(mctx, zone, sizeof(*zone));
963 isc_mem_detach(&mctx);
967 * Single shot.
969 void
970 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
971 char namebuf[1024];
973 REQUIRE(DNS_ZONE_VALID(zone));
974 REQUIRE(rdclass != dns_rdataclass_none);
977 * Test and set.
979 LOCK_ZONE(zone);
980 REQUIRE(zone->rdclass == dns_rdataclass_none ||
981 zone->rdclass == rdclass);
982 zone->rdclass = rdclass;
984 if (zone->strnamerd != NULL)
985 isc_mem_free(zone->mctx, zone->strnamerd);
986 if (zone->strrdclass != NULL)
987 isc_mem_free(zone->mctx, zone->strrdclass);
989 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
990 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
991 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
992 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
994 UNLOCK_ZONE(zone);
997 dns_rdataclass_t
998 dns_zone_getclass(dns_zone_t *zone) {
999 REQUIRE(DNS_ZONE_VALID(zone));
1001 return (zone->rdclass);
1004 void
1005 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1006 REQUIRE(DNS_ZONE_VALID(zone));
1008 LOCK_ZONE(zone);
1009 zone->notifytype = notifytype;
1010 UNLOCK_ZONE(zone);
1013 isc_result_t
1014 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1015 isc_result_t result;
1017 REQUIRE(DNS_ZONE_VALID(zone));
1018 REQUIRE(serialp != NULL);
1020 LOCK_ZONE(zone);
1021 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1022 if (zone->db != NULL) {
1023 result = zone_get_from_db(zone, zone->db, NULL, NULL, serialp,
1024 NULL, NULL, NULL, NULL, NULL);
1025 } else
1026 result = DNS_R_NOTLOADED;
1027 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1028 UNLOCK_ZONE(zone);
1030 return (result);
1033 isc_uint32_t
1034 dns_zone_getserial(dns_zone_t *zone) {
1035 isc_result_t result;
1036 isc_uint32_t serial;
1038 result = dns_zone_getserial2(zone, &serial);
1039 if (result != ISC_R_SUCCESS)
1040 serial = 0; /* XXX: not really correct, but no other choice */
1042 return (serial);
1046 * Single shot.
1048 void
1049 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1051 REQUIRE(DNS_ZONE_VALID(zone));
1052 REQUIRE(type != dns_zone_none);
1055 * Test and set.
1057 LOCK_ZONE(zone);
1058 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1059 zone->type = type;
1060 UNLOCK_ZONE(zone);
1063 static void
1064 zone_freedbargs(dns_zone_t *zone) {
1065 unsigned int i;
1067 /* Free the old database argument list. */
1068 if (zone->db_argv != NULL) {
1069 for (i = 0; i < zone->db_argc; i++)
1070 isc_mem_free(zone->mctx, zone->db_argv[i]);
1071 isc_mem_put(zone->mctx, zone->db_argv,
1072 zone->db_argc * sizeof(*zone->db_argv));
1074 zone->db_argc = 0;
1075 zone->db_argv = NULL;
1078 isc_result_t
1079 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1080 size_t size = 0;
1081 unsigned int i;
1082 isc_result_t result = ISC_R_SUCCESS;
1083 void *mem;
1084 char **tmp, *tmp2;
1086 REQUIRE(DNS_ZONE_VALID(zone));
1087 REQUIRE(argv != NULL && *argv == NULL);
1089 LOCK_ZONE(zone);
1090 size = (zone->db_argc + 1) * sizeof(char *);
1091 for (i = 0; i < zone->db_argc; i++)
1092 size += strlen(zone->db_argv[i]) + 1;
1093 mem = isc_mem_allocate(mctx, size);
1094 if (mem != NULL) {
1095 tmp = mem;
1096 tmp2 = mem;
1097 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1098 for (i = 0; i < zone->db_argc; i++) {
1099 *tmp++ = tmp2;
1100 strcpy(tmp2, zone->db_argv[i]);
1101 tmp2 += strlen(tmp2) + 1;
1103 *tmp = NULL;
1104 } else
1105 result = ISC_R_NOMEMORY;
1106 UNLOCK_ZONE(zone);
1107 *argv = mem;
1108 return (result);
1111 isc_result_t
1112 dns_zone_setdbtype(dns_zone_t *zone,
1113 unsigned int dbargc, const char * const *dbargv) {
1114 isc_result_t result = ISC_R_SUCCESS;
1115 char **new = NULL;
1116 unsigned int i;
1118 REQUIRE(DNS_ZONE_VALID(zone));
1119 REQUIRE(dbargc >= 1);
1120 REQUIRE(dbargv != NULL);
1122 LOCK_ZONE(zone);
1124 /* Set up a new database argument list. */
1125 new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1126 if (new == NULL)
1127 goto nomem;
1128 for (i = 0; i < dbargc; i++)
1129 new[i] = NULL;
1130 for (i = 0; i < dbargc; i++) {
1131 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1132 if (new[i] == NULL)
1133 goto nomem;
1136 /* Free the old list. */
1137 zone_freedbargs(zone);
1139 zone->db_argc = dbargc;
1140 zone->db_argv = new;
1141 result = ISC_R_SUCCESS;
1142 goto unlock;
1144 nomem:
1145 if (new != NULL) {
1146 for (i = 0; i < dbargc; i++)
1147 if (new[i] != NULL)
1148 isc_mem_free(zone->mctx, new[i]);
1149 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1151 result = ISC_R_NOMEMORY;
1153 unlock:
1154 UNLOCK_ZONE(zone);
1155 return (result);
1158 void
1159 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1160 char namebuf[1024];
1161 REQUIRE(DNS_ZONE_VALID(zone));
1163 LOCK_ZONE(zone);
1164 if (zone->view != NULL)
1165 dns_view_weakdetach(&zone->view);
1166 dns_view_weakattach(view, &zone->view);
1168 if (zone->strviewname != NULL)
1169 isc_mem_free(zone->mctx, zone->strviewname);
1170 if (zone->strnamerd != NULL)
1171 isc_mem_free(zone->mctx, zone->strnamerd);
1173 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1174 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1175 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1176 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1178 UNLOCK_ZONE(zone);
1182 dns_view_t *
1183 dns_zone_getview(dns_zone_t *zone) {
1184 REQUIRE(DNS_ZONE_VALID(zone));
1186 return (zone->view);
1190 isc_result_t
1191 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1192 isc_result_t result;
1193 char namebuf[1024];
1195 REQUIRE(DNS_ZONE_VALID(zone));
1196 REQUIRE(origin != NULL);
1198 LOCK_ZONE(zone);
1199 if (dns_name_dynamic(&zone->origin)) {
1200 dns_name_free(&zone->origin, zone->mctx);
1201 dns_name_init(&zone->origin, NULL);
1203 result = dns_name_dup(origin, zone->mctx, &zone->origin);
1205 if (zone->strnamerd != NULL)
1206 isc_mem_free(zone->mctx, zone->strnamerd);
1207 if (zone->strname != NULL)
1208 isc_mem_free(zone->mctx, zone->strname);
1210 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1211 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1212 zone_name_tostr(zone, namebuf, sizeof namebuf);
1213 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1215 UNLOCK_ZONE(zone);
1216 return (result);
1219 void
1220 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1221 REQUIRE(DNS_ZONE_VALID(zone));
1222 REQUIRE(acache != NULL);
1224 LOCK_ZONE(zone);
1225 if (zone->acache != NULL)
1226 dns_acache_detach(&zone->acache);
1227 dns_acache_attach(acache, &zone->acache);
1228 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1229 if (zone->db != NULL) {
1230 isc_result_t result;
1233 * If the zone reuses an existing DB, the DB needs to be
1234 * set in the acache explicitly. We can safely ignore the
1235 * case where the DB is already set. If other error happens,
1236 * the acache will not work effectively.
1238 result = dns_acache_setdb(acache, zone->db);
1239 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1240 UNEXPECTED_ERROR(__FILE__, __LINE__,
1241 "dns_acache_setdb() failed: %s",
1242 isc_result_totext(result));
1245 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1246 UNLOCK_ZONE(zone);
1249 static isc_result_t
1250 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1251 char *copy;
1253 if (value != NULL) {
1254 copy = isc_mem_strdup(zone->mctx, value);
1255 if (copy == NULL)
1256 return (ISC_R_NOMEMORY);
1257 } else {
1258 copy = NULL;
1261 if (*field != NULL)
1262 isc_mem_free(zone->mctx, *field);
1264 *field = copy;
1265 return (ISC_R_SUCCESS);
1268 isc_result_t
1269 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1270 return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1273 isc_result_t
1274 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1275 dns_masterformat_t format) {
1276 isc_result_t result = ISC_R_SUCCESS;
1278 REQUIRE(DNS_ZONE_VALID(zone));
1280 LOCK_ZONE(zone);
1281 result = dns_zone_setstring(zone, &zone->masterfile, file);
1282 if (result == ISC_R_SUCCESS) {
1283 zone->masterformat = format;
1284 result = default_journal(zone);
1286 UNLOCK_ZONE(zone);
1288 return (result);
1291 const char *
1292 dns_zone_getfile(dns_zone_t *zone) {
1293 REQUIRE(DNS_ZONE_VALID(zone));
1295 return (zone->masterfile);
1298 static isc_result_t
1299 default_journal(dns_zone_t *zone) {
1300 isc_result_t result;
1301 char *journal;
1303 REQUIRE(DNS_ZONE_VALID(zone));
1304 REQUIRE(LOCKED_ZONE(zone));
1306 if (zone->masterfile != NULL) {
1307 /* Calculate string length including '\0'. */
1308 int len = strlen(zone->masterfile) + sizeof(".jnl");
1309 journal = isc_mem_allocate(zone->mctx, len);
1310 if (journal == NULL)
1311 return (ISC_R_NOMEMORY);
1312 strcpy(journal, zone->masterfile);
1313 strcat(journal, ".jnl");
1314 } else {
1315 journal = NULL;
1317 result = dns_zone_setstring(zone, &zone->journal, journal);
1318 if (journal != NULL)
1319 isc_mem_free(zone->mctx, journal);
1320 return (result);
1323 isc_result_t
1324 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1325 isc_result_t result = ISC_R_SUCCESS;
1327 REQUIRE(DNS_ZONE_VALID(zone));
1329 LOCK_ZONE(zone);
1330 result = dns_zone_setstring(zone, &zone->journal, journal);
1331 UNLOCK_ZONE(zone);
1333 return (result);
1336 char *
1337 dns_zone_getjournal(dns_zone_t *zone) {
1338 REQUIRE(DNS_ZONE_VALID(zone));
1340 return (zone->journal);
1344 * Return true iff the zone is "dynamic", in the sense that the zone's
1345 * master file (if any) is written by the server, rather than being
1346 * updated manually and read by the server.
1348 * This is true for slave zones, stub zones, and zones that allow
1349 * dynamic updates either by having an update policy ("ssutable")
1350 * or an "allow-update" ACL with a value other than exactly "{ none; }".
1352 static isc_boolean_t
1353 zone_isdynamic(dns_zone_t *zone) {
1354 REQUIRE(DNS_ZONE_VALID(zone));
1356 return (ISC_TF(zone->type == dns_zone_slave ||
1357 zone->type == dns_zone_stub ||
1358 zone->type == dns_zone_key ||
1359 (!zone->update_disabled && zone->ssutable != NULL) ||
1360 (!zone->update_disabled && zone->update_acl != NULL &&
1361 !dns_acl_isnone(zone->update_acl))));
1365 static isc_result_t
1366 zone_load(dns_zone_t *zone, unsigned int flags) {
1367 isc_result_t result;
1368 isc_time_t now;
1369 isc_time_t loadtime, filetime;
1370 dns_db_t *db = NULL;
1372 REQUIRE(DNS_ZONE_VALID(zone));
1374 LOCK_ZONE(zone);
1375 TIME_NOW(&now);
1377 INSIST(zone->type != dns_zone_none);
1379 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1380 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1381 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1382 result = DNS_R_CONTINUE;
1383 goto cleanup;
1386 if (zone->db != NULL && zone->masterfile == NULL) {
1388 * The zone has no master file configured, but it already
1389 * has a database. It could be the built-in
1390 * version.bind. CH zone, a zone with a persistent
1391 * database being reloaded, or maybe a zone that
1392 * used to have a master file but whose configuration
1393 * was changed so that it no longer has one. Do nothing.
1395 result = ISC_R_SUCCESS;
1396 goto cleanup;
1399 if (zone->db != NULL && zone_isdynamic(zone)) {
1401 * This is a slave, stub, or dynamically updated
1402 * zone being reloaded. Do nothing - the database
1403 * we already have is guaranteed to be up-to-date.
1405 if (zone->type == dns_zone_master)
1406 result = DNS_R_DYNAMIC;
1407 else
1408 result = ISC_R_SUCCESS;
1409 goto cleanup;
1414 * Store the current time before the zone is loaded, so that if the
1415 * file changes between the time of the load and the time that
1416 * zone->loadtime is set, then the file will still be reloaded
1417 * the next time dns_zone_load is called.
1419 TIME_NOW(&loadtime);
1422 * Don't do the load if the file that stores the zone is older
1423 * than the last time the zone was loaded. If the zone has not
1424 * been loaded yet, zone->loadtime will be the epoch.
1426 if (zone->masterfile != NULL) {
1428 * The file is already loaded. If we are just doing a
1429 * "rndc reconfig", we are done.
1431 if (!isc_time_isepoch(&zone->loadtime) &&
1432 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1433 result = ISC_R_SUCCESS;
1434 goto cleanup;
1437 result = isc_file_getmodtime(zone->masterfile, &filetime);
1438 if (result == ISC_R_SUCCESS) {
1439 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1440 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
1441 isc_time_compare(&filetime, &zone->loadtime) <= 0) {
1442 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1443 "skipping load: master file "
1444 "older than last load");
1445 result = DNS_R_UPTODATE;
1446 goto cleanup;
1448 loadtime = filetime;
1452 INSIST(zone->db_argc >= 1);
1455 * Built in zones don't need to be reloaded.
1457 if (zone->type == dns_zone_master &&
1458 strcmp(zone->db_argv[0], "_builtin") == 0 &&
1459 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1460 result = ISC_R_SUCCESS;
1461 goto cleanup;
1464 if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub) &&
1465 (strcmp(zone->db_argv[0], "rbt") == 0 ||
1466 strcmp(zone->db_argv[0], "rbt64") == 0)) {
1467 if (zone->masterfile == NULL ||
1468 !isc_file_exists(zone->masterfile)) {
1469 if (zone->masterfile != NULL) {
1470 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1471 "no master file");
1473 zone->refreshtime = now;
1474 if (zone->task != NULL)
1475 zone_settimer(zone, &now);
1476 result = ISC_R_SUCCESS;
1477 goto cleanup;
1481 dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1483 result = dns_db_create(zone->mctx, zone->db_argv[0],
1484 &zone->origin, (zone->type == dns_zone_stub) ?
1485 dns_dbtype_stub : dns_dbtype_zone,
1486 zone->rdclass,
1487 zone->db_argc - 1, zone->db_argv + 1,
1488 &db);
1490 if (result != ISC_R_SUCCESS) {
1491 dns_zone_log(zone, ISC_LOG_ERROR,
1492 "loading zone: creating database: %s",
1493 isc_result_totext(result));
1494 goto cleanup;
1496 dns_db_settask(db, zone->task);
1498 if (! dns_db_ispersistent(db)) {
1499 if (zone->masterfile != NULL) {
1500 result = zone_startload(db, zone, loadtime);
1501 } else {
1502 result = DNS_R_NOMASTERFILE;
1503 if (zone->type == dns_zone_master) {
1504 dns_zone_log(zone, ISC_LOG_ERROR,
1505 "loading zone: "
1506 "no master file configured");
1507 goto cleanup;
1509 dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1510 "no master file configured: continuing");
1514 if (result == DNS_R_CONTINUE) {
1515 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1516 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1517 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1518 goto cleanup;
1521 result = zone_postload(zone, db, loadtime, result);
1523 cleanup:
1524 UNLOCK_ZONE(zone);
1525 if (db != NULL)
1526 dns_db_detach(&db);
1527 return (result);
1530 isc_result_t
1531 dns_zone_load(dns_zone_t *zone) {
1532 return (zone_load(zone, 0));
1535 isc_result_t
1536 dns_zone_loadnew(dns_zone_t *zone) {
1537 return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));
1540 isc_result_t
1541 dns_zone_loadandthaw(dns_zone_t *zone) {
1542 isc_result_t result;
1544 result = zone_load(zone, DNS_ZONELOADFLAG_THAW);
1545 switch (result) {
1546 case DNS_R_CONTINUE:
1547 /* Deferred thaw. */
1548 break;
1549 case ISC_R_SUCCESS:
1550 case DNS_R_UPTODATE:
1551 case DNS_R_SEENINCLUDE:
1552 zone->update_disabled = ISC_FALSE;
1553 break;
1554 case DNS_R_NOMASTERFILE:
1555 zone->update_disabled = ISC_FALSE;
1556 break;
1557 default:
1558 /* Error, remain in disabled state. */
1559 break;
1561 return (result);
1564 static unsigned int
1565 get_master_options(dns_zone_t *zone) {
1566 unsigned int options;
1568 options = DNS_MASTER_ZONE;
1569 if (zone->type == dns_zone_slave)
1570 options |= DNS_MASTER_SLAVE;
1571 if (zone->type == dns_zone_key)
1572 options |= DNS_MASTER_KEY;
1573 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
1574 options |= DNS_MASTER_CHECKNS;
1575 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
1576 options |= DNS_MASTER_FATALNS;
1577 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
1578 options |= DNS_MASTER_CHECKNAMES;
1579 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
1580 options |= DNS_MASTER_CHECKNAMESFAIL;
1581 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
1582 options |= DNS_MASTER_CHECKMX;
1583 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1584 options |= DNS_MASTER_CHECKMXFAIL;
1585 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
1586 options |= DNS_MASTER_CHECKWILDCARD;
1587 if (zone->type == dns_zone_master &&
1588 (zone->update_acl != NULL || zone->ssutable != NULL))
1589 options |= DNS_MASTER_RESIGN;
1590 return (options);
1593 static void
1594 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
1595 dns_load_t *load = event->ev_arg;
1596 isc_result_t result = ISC_R_SUCCESS;
1597 unsigned int options;
1599 REQUIRE(DNS_LOAD_VALID(load));
1601 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1602 result = ISC_R_CANCELED;
1603 isc_event_free(&event);
1604 if (result == ISC_R_CANCELED)
1605 goto fail;
1607 options = get_master_options(load->zone);
1609 result = dns_master_loadfileinc3(load->zone->masterfile,
1610 dns_db_origin(load->db),
1611 dns_db_origin(load->db),
1612 load->zone->rdclass,
1613 options,
1614 load->zone->sigresigninginterval,
1615 &load->callbacks, task,
1616 zone_loaddone, load,
1617 &load->zone->lctx, load->zone->mctx,
1618 load->zone->masterformat);
1619 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
1620 result != DNS_R_SEENINCLUDE)
1621 goto fail;
1622 return;
1624 fail:
1625 zone_loaddone(load, result);
1628 static void
1629 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
1630 const char me[] = "zone_gotwritehandle";
1631 dns_zone_t *zone = event->ev_arg;
1632 isc_result_t result = ISC_R_SUCCESS;
1633 dns_dbversion_t *version = NULL;
1635 REQUIRE(DNS_ZONE_VALID(zone));
1636 INSIST(task == zone->task);
1637 ENTER;
1639 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1640 result = ISC_R_CANCELED;
1641 isc_event_free(&event);
1642 if (result == ISC_R_CANCELED)
1643 goto fail;
1645 LOCK_ZONE(zone);
1646 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1647 dns_db_currentversion(zone->db, &version);
1648 result = dns_master_dumpinc2(zone->mctx, zone->db, version,
1649 &dns_master_style_default,
1650 zone->masterfile, zone->task, dump_done,
1651 zone, &zone->dctx, zone->masterformat);
1652 dns_db_closeversion(zone->db, &version, ISC_FALSE);
1653 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1654 UNLOCK_ZONE(zone);
1655 if (result != DNS_R_CONTINUE)
1656 goto fail;
1657 return;
1659 fail:
1660 dump_done(zone, result);
1663 static isc_result_t
1664 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
1665 dns_load_t *load;
1666 isc_result_t result;
1667 isc_result_t tresult;
1668 unsigned int options;
1670 options = get_master_options(zone);
1672 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
1673 options |= DNS_MASTER_MANYERRORS;
1675 if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) {
1676 load = isc_mem_get(zone->mctx, sizeof(*load));
1677 if (load == NULL)
1678 return (ISC_R_NOMEMORY);
1680 load->mctx = NULL;
1681 load->zone = NULL;
1682 load->db = NULL;
1683 load->loadtime = loadtime;
1684 load->magic = LOAD_MAGIC;
1686 isc_mem_attach(zone->mctx, &load->mctx);
1687 zone_iattach(zone, &load->zone);
1688 dns_db_attach(db, &load->db);
1689 dns_rdatacallbacks_init(&load->callbacks);
1690 result = dns_db_beginload(db, &load->callbacks.add,
1691 &load->callbacks.add_private);
1692 if (result != ISC_R_SUCCESS)
1693 goto cleanup;
1694 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task,
1695 zone_gotreadhandle, load,
1696 &zone->readio);
1697 if (result != ISC_R_SUCCESS) {
1699 * We can't report multiple errors so ignore
1700 * the result of dns_db_endload().
1702 (void)dns_db_endload(load->db,
1703 &load->callbacks.add_private);
1704 goto cleanup;
1705 } else
1706 result = DNS_R_CONTINUE;
1707 } else {
1708 dns_rdatacallbacks_t callbacks;
1710 dns_rdatacallbacks_init(&callbacks);
1711 result = dns_db_beginload(db, &callbacks.add,
1712 &callbacks.add_private);
1713 if (result != ISC_R_SUCCESS)
1714 return (result);
1715 result = dns_master_loadfile3(zone->masterfile, &zone->origin,
1716 &zone->origin, zone->rdclass,
1717 options, zone->sigresigninginterval,
1718 &callbacks, zone->mctx,
1719 zone->masterformat);
1720 tresult = dns_db_endload(db, &callbacks.add_private);
1721 if (result == ISC_R_SUCCESS)
1722 result = tresult;
1725 return (result);
1727 cleanup:
1728 load->magic = 0;
1729 dns_db_detach(&load->db);
1730 zone_idetach(&load->zone);
1731 isc_mem_detach(&load->mctx);
1732 isc_mem_put(zone->mctx, load, sizeof(*load));
1733 return (result);
1736 static isc_boolean_t
1737 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1738 dns_name_t *owner)
1740 isc_result_t result;
1741 char ownerbuf[DNS_NAME_FORMATSIZE];
1742 char namebuf[DNS_NAME_FORMATSIZE];
1743 char altbuf[DNS_NAME_FORMATSIZE];
1744 dns_fixedname_t fixed;
1745 dns_name_t *foundname;
1746 int level;
1749 * Outside of zone.
1751 if (!dns_name_issubdomain(name, &zone->origin)) {
1752 if (zone->checkmx != NULL)
1753 return ((zone->checkmx)(zone, name, owner));
1754 return (ISC_TRUE);
1757 if (zone->type == dns_zone_master)
1758 level = ISC_LOG_ERROR;
1759 else
1760 level = ISC_LOG_WARNING;
1762 dns_fixedname_init(&fixed);
1763 foundname = dns_fixedname_name(&fixed);
1765 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1766 0, 0, NULL, foundname, NULL, NULL);
1767 if (result == ISC_R_SUCCESS)
1768 return (ISC_TRUE);
1770 if (result == DNS_R_NXRRSET) {
1771 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1772 0, 0, NULL, foundname, NULL, NULL);
1773 if (result == ISC_R_SUCCESS)
1774 return (ISC_TRUE);
1777 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1778 dns_name_format(name, namebuf, sizeof namebuf);
1779 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1780 result == DNS_R_EMPTYNAME) {
1781 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
1782 level = ISC_LOG_WARNING;
1783 dns_zone_log(zone, level,
1784 "%s/MX '%s' has no address records (A or AAAA)",
1785 ownerbuf, namebuf);
1786 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1789 if (result == DNS_R_CNAME) {
1790 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1791 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1792 level = ISC_LOG_WARNING;
1793 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1794 dns_zone_log(zone, level,
1795 "%s/MX '%s' is a CNAME (illegal)",
1796 ownerbuf, namebuf);
1797 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1800 if (result == DNS_R_DNAME) {
1801 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
1802 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
1803 level = ISC_LOG_WARNING;
1804 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
1805 dns_name_format(foundname, altbuf, sizeof altbuf);
1806 dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
1807 " '%s' (illegal)", ownerbuf, namebuf,
1808 altbuf);
1810 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1813 if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
1814 return ((zone->checkmx)(zone, name, owner));
1816 return (ISC_TRUE);
1819 static isc_boolean_t
1820 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1821 dns_name_t *owner)
1823 isc_result_t result;
1824 char ownerbuf[DNS_NAME_FORMATSIZE];
1825 char namebuf[DNS_NAME_FORMATSIZE];
1826 char altbuf[DNS_NAME_FORMATSIZE];
1827 dns_fixedname_t fixed;
1828 dns_name_t *foundname;
1829 int level;
1832 * "." means the services does not exist.
1834 if (dns_name_equal(name, dns_rootname))
1835 return (ISC_TRUE);
1838 * Outside of zone.
1840 if (!dns_name_issubdomain(name, &zone->origin)) {
1841 if (zone->checksrv != NULL)
1842 return ((zone->checksrv)(zone, name, owner));
1843 return (ISC_TRUE);
1846 if (zone->type == dns_zone_master)
1847 level = ISC_LOG_ERROR;
1848 else
1849 level = ISC_LOG_WARNING;
1851 dns_fixedname_init(&fixed);
1852 foundname = dns_fixedname_name(&fixed);
1854 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1855 0, 0, NULL, foundname, NULL, NULL);
1856 if (result == ISC_R_SUCCESS)
1857 return (ISC_TRUE);
1859 if (result == DNS_R_NXRRSET) {
1860 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1861 0, 0, NULL, foundname, NULL, NULL);
1862 if (result == ISC_R_SUCCESS)
1863 return (ISC_TRUE);
1866 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1867 dns_name_format(name, namebuf, sizeof namebuf);
1868 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1869 result == DNS_R_EMPTYNAME) {
1870 dns_zone_log(zone, level,
1871 "%s/SRV '%s' has no address records (A or AAAA)",
1872 ownerbuf, namebuf);
1873 /* XXX950 make fatal for 9.5.0. */
1874 return (ISC_TRUE);
1877 if (result == DNS_R_CNAME) {
1878 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1879 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1880 level = ISC_LOG_WARNING;
1881 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1882 dns_zone_log(zone, level,
1883 "%s/SRV '%s' is a CNAME (illegal)",
1884 ownerbuf, namebuf);
1885 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1888 if (result == DNS_R_DNAME) {
1889 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
1890 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
1891 level = ISC_LOG_WARNING;
1892 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
1893 dns_name_format(foundname, altbuf, sizeof altbuf);
1894 dns_zone_log(zone, level, "%s/SRV '%s' is below a "
1895 "DNAME '%s' (illegal)", ownerbuf, namebuf,
1896 altbuf);
1898 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
1901 if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
1902 return ((zone->checksrv)(zone, name, owner));
1904 return (ISC_TRUE);
1907 static isc_boolean_t
1908 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
1909 dns_name_t *owner)
1911 isc_boolean_t answer = ISC_TRUE;
1912 isc_result_t result, tresult;
1913 char ownerbuf[DNS_NAME_FORMATSIZE];
1914 char namebuf[DNS_NAME_FORMATSIZE];
1915 char altbuf[DNS_NAME_FORMATSIZE];
1916 dns_fixedname_t fixed;
1917 dns_name_t *foundname;
1918 dns_rdataset_t a;
1919 dns_rdataset_t aaaa;
1920 int level;
1923 * Outside of zone.
1925 if (!dns_name_issubdomain(name, &zone->origin)) {
1926 if (zone->checkns != NULL)
1927 return ((zone->checkns)(zone, name, owner, NULL, NULL));
1928 return (ISC_TRUE);
1931 if (zone->type == dns_zone_master)
1932 level = ISC_LOG_ERROR;
1933 else
1934 level = ISC_LOG_WARNING;
1936 dns_fixedname_init(&fixed);
1937 foundname = dns_fixedname_name(&fixed);
1938 dns_rdataset_init(&a);
1939 dns_rdataset_init(&aaaa);
1941 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
1942 DNS_DBFIND_GLUEOK, 0, NULL,
1943 foundname, &a, NULL);
1945 if (result == ISC_R_SUCCESS) {
1946 dns_rdataset_disassociate(&a);
1947 return (ISC_TRUE);
1948 } else if (result == DNS_R_DELEGATION)
1949 dns_rdataset_disassociate(&a);
1951 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
1952 result == DNS_R_GLUE) {
1953 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
1954 DNS_DBFIND_GLUEOK, 0, NULL,
1955 foundname, &aaaa, NULL);
1956 if (tresult == ISC_R_SUCCESS) {
1957 dns_rdataset_disassociate(&aaaa);
1958 return (ISC_TRUE);
1960 if (tresult == DNS_R_DELEGATION)
1961 dns_rdataset_disassociate(&aaaa);
1962 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
1964 * Check glue against child zone.
1966 if (zone->checkns != NULL)
1967 answer = (zone->checkns)(zone, name, owner,
1968 &a, &aaaa);
1969 if (dns_rdataset_isassociated(&a))
1970 dns_rdataset_disassociate(&a);
1971 if (dns_rdataset_isassociated(&aaaa))
1972 dns_rdataset_disassociate(&aaaa);
1973 return (answer);
1975 } else
1976 tresult = result;
1978 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
1979 dns_name_format(name, namebuf, sizeof namebuf);
1980 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
1981 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
1982 const char *what;
1983 isc_boolean_t required = ISC_FALSE;
1984 if (dns_name_issubdomain(name, owner)) {
1985 what = "REQUIRED GLUE ";
1986 required = ISC_TRUE;
1987 } else if (result == DNS_R_DELEGATION)
1988 what = "SIBLING GLUE ";
1989 else
1990 what = "";
1992 if (result != DNS_R_DELEGATION || required ||
1993 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
1994 dns_zone_log(zone, level, "%s/NS '%s' has no %s"
1995 "address records (A or AAAA)",
1996 ownerbuf, namebuf, what);
1998 * Log missing address record.
2000 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2001 (void)(zone->checkns)(zone, name, owner,
2002 &a, &aaaa);
2003 /* XXX950 make fatal for 9.5.0. */
2004 /* answer = ISC_FALSE; */
2006 } else if (result == DNS_R_CNAME) {
2007 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2008 ownerbuf, namebuf);
2009 /* XXX950 make fatal for 9.5.0. */
2010 /* answer = ISC_FALSE; */
2011 } else if (result == DNS_R_DNAME) {
2012 dns_name_format(foundname, altbuf, sizeof altbuf);
2013 dns_zone_log(zone, level,
2014 "%s/NS '%s' is below a DNAME '%s' (illegal)",
2015 ownerbuf, namebuf, altbuf);
2016 /* XXX950 make fatal for 9.5.0. */
2017 /* answer = ISC_FALSE; */
2020 if (dns_rdataset_isassociated(&a))
2021 dns_rdataset_disassociate(&a);
2022 if (dns_rdataset_isassociated(&aaaa))
2023 dns_rdataset_disassociate(&aaaa);
2024 return (answer);
2027 static isc_boolean_t
2028 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2029 dns_rdataset_t *rdataset)
2031 dns_rdataset_t tmprdataset;
2032 isc_result_t result;
2033 isc_boolean_t answer = ISC_TRUE;
2034 isc_boolean_t format = ISC_TRUE;
2035 int level = ISC_LOG_WARNING;
2036 char ownerbuf[DNS_NAME_FORMATSIZE];
2037 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2038 unsigned int count1 = 0;
2040 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2041 level = ISC_LOG_ERROR;
2043 dns_rdataset_init(&tmprdataset);
2044 for (result = dns_rdataset_first(rdataset);
2045 result == ISC_R_SUCCESS;
2046 result = dns_rdataset_next(rdataset)) {
2047 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2048 unsigned int count2 = 0;
2050 count1++;
2051 dns_rdataset_current(rdataset, &rdata1);
2052 dns_rdataset_clone(rdataset, &tmprdataset);
2053 for (result = dns_rdataset_first(&tmprdataset);
2054 result == ISC_R_SUCCESS;
2055 result = dns_rdataset_next(&tmprdataset)) {
2056 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2057 count2++;
2058 if (count1 >= count2)
2059 continue;
2060 dns_rdataset_current(&tmprdataset, &rdata2);
2061 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2062 if (format) {
2063 dns_name_format(owner, ownerbuf,
2064 sizeof ownerbuf);
2065 dns_rdatatype_format(rdata1.type,
2066 typebuf,
2067 sizeof(typebuf));
2068 format = ISC_FALSE;
2070 dns_zone_log(zone, level, "%s/%s has "
2071 "semantically identical records",
2072 ownerbuf, typebuf);
2073 if (level == ISC_LOG_ERROR)
2074 answer = ISC_FALSE;
2075 break;
2078 dns_rdataset_disassociate(&tmprdataset);
2079 if (!format)
2080 break;
2082 return (answer);
2085 static isc_boolean_t
2086 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2087 dns_dbiterator_t *dbiterator = NULL;
2088 dns_dbnode_t *node = NULL;
2089 dns_fixedname_t fixed;
2090 dns_name_t *name;
2091 dns_rdataset_t rdataset;
2092 dns_rdatasetiter_t *rdsit = NULL;
2093 isc_boolean_t ok = ISC_TRUE;
2094 isc_result_t result;
2096 dns_fixedname_init(&fixed);
2097 name = dns_fixedname_name(&fixed);
2098 dns_rdataset_init(&rdataset);
2100 result = dns_db_createiterator(db, 0, &dbiterator);
2101 if (result != ISC_R_SUCCESS)
2102 return (ISC_TRUE);
2104 for (result = dns_dbiterator_first(dbiterator);
2105 result == ISC_R_SUCCESS;
2106 result = dns_dbiterator_next(dbiterator)) {
2107 result = dns_dbiterator_current(dbiterator, &node, name);
2108 if (result != ISC_R_SUCCESS)
2109 continue;
2111 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2112 if (result != ISC_R_SUCCESS)
2113 continue;
2115 for (result = dns_rdatasetiter_first(rdsit);
2116 result == ISC_R_SUCCESS;
2117 result = dns_rdatasetiter_next(rdsit)) {
2118 dns_rdatasetiter_current(rdsit, &rdataset);
2119 if (!zone_rrset_check_dup(zone, name, &rdataset))
2120 ok = ISC_FALSE;
2121 dns_rdataset_disassociate(&rdataset);
2123 dns_rdatasetiter_destroy(&rdsit);
2124 dns_db_detachnode(db, &node);
2127 if (node != NULL)
2128 dns_db_detachnode(db, &node);
2129 dns_dbiterator_destroy(&dbiterator);
2131 return (ok);
2134 static isc_boolean_t
2135 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2136 dns_dbiterator_t *dbiterator = NULL;
2137 dns_dbnode_t *node = NULL;
2138 dns_rdataset_t rdataset;
2139 dns_fixedname_t fixed;
2140 dns_fixedname_t fixedbottom;
2141 dns_rdata_mx_t mx;
2142 dns_rdata_ns_t ns;
2143 dns_rdata_in_srv_t srv;
2144 dns_rdata_t rdata;
2145 dns_name_t *name;
2146 dns_name_t *bottom;
2147 isc_result_t result;
2148 isc_boolean_t ok = ISC_TRUE;
2150 dns_fixedname_init(&fixed);
2151 name = dns_fixedname_name(&fixed);
2152 dns_fixedname_init(&fixedbottom);
2153 bottom = dns_fixedname_name(&fixedbottom);
2154 dns_rdataset_init(&rdataset);
2155 dns_rdata_init(&rdata);
2157 result = dns_db_createiterator(db, 0, &dbiterator);
2158 if (result != ISC_R_SUCCESS)
2159 return (ISC_TRUE);
2161 result = dns_dbiterator_first(dbiterator);
2162 while (result == ISC_R_SUCCESS) {
2163 result = dns_dbiterator_current(dbiterator, &node, name);
2164 if (result != ISC_R_SUCCESS)
2165 goto cleanup;
2168 * Is this name visible in the zone?
2170 if (!dns_name_issubdomain(name, &zone->origin) ||
2171 (dns_name_countlabels(bottom) > 0 &&
2172 dns_name_issubdomain(name, bottom)))
2173 goto next;
2176 * Don't check the NS records at the origin.
2178 if (dns_name_equal(name, &zone->origin))
2179 goto checkmx;
2181 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2182 0, 0, &rdataset, NULL);
2183 if (result != ISC_R_SUCCESS)
2184 goto checkmx;
2186 * Remember bottom of zone.
2188 dns_name_copy(name, bottom, NULL);
2190 result = dns_rdataset_first(&rdataset);
2191 while (result == ISC_R_SUCCESS) {
2192 dns_rdataset_current(&rdataset, &rdata);
2193 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2194 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2195 if (!zone_check_glue(zone, db, &ns.name, name))
2196 ok = ISC_FALSE;
2197 dns_rdata_reset(&rdata);
2198 result = dns_rdataset_next(&rdataset);
2200 dns_rdataset_disassociate(&rdataset);
2201 goto next;
2203 checkmx:
2204 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2205 0, 0, &rdataset, NULL);
2206 if (result != ISC_R_SUCCESS)
2207 goto checksrv;
2208 result = dns_rdataset_first(&rdataset);
2209 while (result == ISC_R_SUCCESS) {
2210 dns_rdataset_current(&rdataset, &rdata);
2211 result = dns_rdata_tostruct(&rdata, &mx, NULL);
2212 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2213 if (!zone_check_mx(zone, db, &mx.mx, name))
2214 ok = ISC_FALSE;
2215 dns_rdata_reset(&rdata);
2216 result = dns_rdataset_next(&rdataset);
2218 dns_rdataset_disassociate(&rdataset);
2220 checksrv:
2221 if (zone->rdclass != dns_rdataclass_in)
2222 goto next;
2223 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2224 0, 0, &rdataset, NULL);
2225 if (result != ISC_R_SUCCESS)
2226 goto next;
2227 result = dns_rdataset_first(&rdataset);
2228 while (result == ISC_R_SUCCESS) {
2229 dns_rdataset_current(&rdataset, &rdata);
2230 result = dns_rdata_tostruct(&rdata, &srv, NULL);
2231 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2232 if (!zone_check_srv(zone, db, &srv.target, name))
2233 ok = ISC_FALSE;
2234 dns_rdata_reset(&rdata);
2235 result = dns_rdataset_next(&rdataset);
2237 dns_rdataset_disassociate(&rdataset);
2239 next:
2240 dns_db_detachnode(db, &node);
2241 result = dns_dbiterator_next(dbiterator);
2244 cleanup:
2245 if (node != NULL)
2246 dns_db_detachnode(db, &node);
2247 dns_dbiterator_destroy(&dbiterator);
2249 return (ok);
2253 * OpenSSL verification of RSA keys with exponent 3 is known to be
2254 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
2255 * if they are in use.
2257 static void
2258 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2259 dns_dbnode_t *node = NULL;
2260 dns_dbversion_t *version = NULL;
2261 dns_rdata_dnskey_t dnskey;
2262 dns_rdata_t rdata = DNS_RDATA_INIT;
2263 dns_rdataset_t rdataset;
2264 isc_result_t result;
2265 isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2266 const char *algorithm;
2268 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2269 if (result != ISC_R_SUCCESS)
2270 goto cleanup;
2272 dns_db_currentversion(db, &version);
2273 dns_rdataset_init(&rdataset);
2274 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2275 dns_rdatatype_none, 0, &rdataset, NULL);
2276 if (result != ISC_R_SUCCESS)
2277 goto cleanup;
2279 for (result = dns_rdataset_first(&rdataset);
2280 result == ISC_R_SUCCESS;
2281 result = dns_rdataset_next(&rdataset))
2283 dns_rdataset_current(&rdataset, &rdata);
2284 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2285 INSIST(result == ISC_R_SUCCESS);
2287 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2288 dnskey.algorithm == DST_ALG_RSAMD5) &&
2289 dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2290 dnskey.data[1] == 3)
2292 if (dnskey.algorithm == DST_ALG_RSASHA1) {
2293 logit = !foundrsa;
2294 foundrsa = ISC_TRUE;
2295 algorithm = "RSASHA1";
2296 } else {
2297 logit = !foundmd5;
2298 foundmd5 = ISC_TRUE;
2299 algorithm = "RSAMD5";
2301 if (logit)
2302 dns_zone_log(zone, ISC_LOG_WARNING,
2303 "weak %s (%u) key found "
2304 "(exponent=3)", algorithm,
2305 dnskey.algorithm);
2306 if (foundrsa && foundmd5)
2307 break;
2309 dns_rdata_reset(&rdata);
2311 dns_rdataset_disassociate(&rdataset);
2313 cleanup:
2314 if (node != NULL)
2315 dns_db_detachnode(db, &node);
2316 if (version != NULL)
2317 dns_db_closeversion(db, &version, ISC_FALSE);
2320 static void
2321 resume_signingwithkey(dns_zone_t *zone) {
2322 dns_dbnode_t *node = NULL;
2323 dns_dbversion_t *version = NULL;
2324 dns_rdata_t rdata = DNS_RDATA_INIT;
2325 dns_rdataset_t rdataset;
2326 isc_result_t result;
2328 result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2329 if (result != ISC_R_SUCCESS)
2330 goto cleanup;
2332 dns_db_currentversion(zone->db, &version);
2333 dns_rdataset_init(&rdataset);
2334 result = dns_db_findrdataset(zone->db, node, version,
2335 zone->privatetype,
2336 dns_rdatatype_none, 0,
2337 &rdataset, NULL);
2338 if (result != ISC_R_SUCCESS) {
2339 INSIST(!dns_rdataset_isassociated(&rdataset));
2340 goto cleanup;
2343 for (result = dns_rdataset_first(&rdataset);
2344 result == ISC_R_SUCCESS;
2345 result = dns_rdataset_next(&rdataset))
2347 dns_rdataset_current(&rdataset, &rdata);
2348 if (rdata.length != 5 ||
2349 rdata.data[0] == 0 || rdata.data[4] != 0) {
2350 dns_rdata_reset(&rdata);
2351 continue;
2354 result = zone_signwithkey(zone, rdata.data[0],
2355 (rdata.data[1] << 8) | rdata.data[2],
2356 ISC_TF(rdata.data[3]));
2357 if (result != ISC_R_SUCCESS) {
2358 dns_zone_log(zone, ISC_LOG_ERROR,
2359 "zone_signwithkey failed: %s",
2360 dns_result_totext(result));
2362 dns_rdata_reset(&rdata);
2364 dns_rdataset_disassociate(&rdataset);
2366 cleanup:
2367 if (node != NULL)
2368 dns_db_detachnode(zone->db, &node);
2369 if (version != NULL)
2370 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2373 static isc_result_t
2374 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
2375 dns_nsec3chain_t *nsec3chain, *current;
2376 isc_result_t result;
2377 isc_time_t now;
2378 unsigned int options = 0;
2379 char saltbuf[255*2+1];
2380 char flags[sizeof("REMOVE|CREATE|NONSEC|OPTOUT")];
2381 int i;
2383 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
2384 if (nsec3chain == NULL)
2385 return (ISC_R_NOMEMORY);
2387 nsec3chain->magic = 0;
2388 nsec3chain->done = ISC_FALSE;
2389 nsec3chain->db = NULL;
2390 nsec3chain->dbiterator = NULL;
2391 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
2392 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
2393 nsec3chain->nsec3param.hash = nsec3param->hash;
2394 nsec3chain->nsec3param.iterations = nsec3param->iterations;
2395 nsec3chain->nsec3param.flags = nsec3param->flags;
2396 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
2397 memcpy(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
2398 nsec3chain->nsec3param.salt = nsec3chain->salt;
2399 nsec3chain->seen_nsec = ISC_FALSE;
2400 nsec3chain->delete_nsec = ISC_FALSE;
2401 nsec3chain->save_delete_nsec = ISC_FALSE;
2403 if (nsec3param->flags == 0)
2404 strlcpy(flags, "NONE", sizeof(flags));
2405 else {
2406 flags[0] = '\0';
2407 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
2408 strlcat(flags, "REMOVE", sizeof(flags));
2409 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
2410 if (flags[0] == '\0')
2411 strlcpy(flags, "CREATE", sizeof(flags));
2412 else
2413 strlcat(flags, "|CREATE", sizeof(flags));
2415 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
2416 if (flags[0] == '\0')
2417 strlcpy(flags, "NONSEC", sizeof(flags));
2418 else
2419 strlcat(flags, "|NONSEC", sizeof(flags));
2421 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
2422 if (flags[0] == '\0')
2423 strlcpy(flags, "OPTOUT", sizeof(flags));
2424 else
2425 strlcat(flags, "|OPTOUT", sizeof(flags));
2428 if (nsec3param->salt_length == 0)
2429 strlcpy(saltbuf, "-", sizeof(saltbuf));
2430 else
2431 for (i = 0; i < nsec3param->salt_length; i++)
2432 sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
2433 dns_zone_log(zone, ISC_LOG_INFO,
2434 "zone_addnsec3chain(%u,%s,%u,%s)",
2435 nsec3param->hash, flags, nsec3param->iterations,
2436 saltbuf);
2437 for (current = ISC_LIST_HEAD(zone->nsec3chain);
2438 current != NULL;
2439 current = ISC_LIST_NEXT(current, link)) {
2440 if (current->db == zone->db &&
2441 current->nsec3param.hash == nsec3param->hash &&
2442 current->nsec3param.iterations == nsec3param->iterations &&
2443 current->nsec3param.salt_length == nsec3param->salt_length
2444 && !memcmp(current->nsec3param.salt, nsec3param->salt,
2445 nsec3param->salt_length))
2446 current->done = ISC_TRUE;
2449 if (zone->db != NULL) {
2450 dns_db_attach(zone->db, &nsec3chain->db);
2451 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
2452 options = DNS_DB_NONSEC3;
2453 result = dns_db_createiterator(nsec3chain->db, options,
2454 &nsec3chain->dbiterator);
2455 if (result == ISC_R_SUCCESS)
2456 dns_dbiterator_first(nsec3chain->dbiterator);
2457 if (result == ISC_R_SUCCESS) {
2458 dns_dbiterator_pause(nsec3chain->dbiterator);
2459 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
2460 nsec3chain, link);
2461 nsec3chain = NULL;
2462 if (isc_time_isepoch(&zone->nsec3chaintime)) {
2463 TIME_NOW(&now);
2464 zone->nsec3chaintime = now;
2465 if (zone->task != NULL)
2466 zone_settimer(zone, &now);
2469 } else
2470 result = ISC_R_NOTFOUND;
2472 if (nsec3chain != NULL) {
2473 if (nsec3chain->db != NULL)
2474 dns_db_detach(&nsec3chain->db);
2475 if (nsec3chain->dbiterator != NULL)
2476 dns_dbiterator_destroy(&nsec3chain->dbiterator);
2477 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
2479 return (result);
2482 static void
2483 resume_addnsec3chain(dns_zone_t *zone) {
2484 dns_dbnode_t *node = NULL;
2485 dns_dbversion_t *version = NULL;
2486 dns_rdataset_t rdataset;
2487 isc_result_t result;
2488 dns_rdata_nsec3param_t nsec3param;
2490 if (zone->privatetype == 0)
2491 return;
2493 result = dns_db_findnode(zone->db, &zone->origin, ISC_FALSE, &node);
2494 if (result != ISC_R_SUCCESS)
2495 goto cleanup;
2497 dns_db_currentversion(zone->db, &version);
2498 dns_rdataset_init(&rdataset);
2499 result = dns_db_findrdataset(zone->db, node, version,
2500 zone->privatetype, dns_rdatatype_none,
2501 0, &rdataset, NULL);
2502 if (result != ISC_R_SUCCESS) {
2503 INSIST(!dns_rdataset_isassociated(&rdataset));
2504 goto cleanup;
2507 for (result = dns_rdataset_first(&rdataset);
2508 result == ISC_R_SUCCESS;
2509 result = dns_rdataset_next(&rdataset))
2511 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
2512 dns_rdata_t rdata = DNS_RDATA_INIT;
2513 dns_rdata_t private = DNS_RDATA_INIT;
2515 dns_rdataset_current(&rdataset, &private);
2516 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
2517 sizeof(buf)))
2518 continue;
2519 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2520 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2521 if ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 ||
2522 (nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
2523 result = zone_addnsec3chain(zone, &nsec3param);
2524 if (result != ISC_R_SUCCESS) {
2525 dns_zone_log(zone, ISC_LOG_ERROR,
2526 "zone_addnsec3chain failed: %s",
2527 dns_result_totext(result));
2531 dns_rdataset_disassociate(&rdataset);
2532 cleanup:
2533 if (node != NULL)
2534 dns_db_detachnode(zone->db, &node);
2535 if (version != NULL)
2536 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2539 static void
2540 set_resigntime(dns_zone_t *zone) {
2541 dns_rdataset_t rdataset;
2542 dns_fixedname_t fixed;
2543 unsigned int resign;
2544 isc_result_t result;
2545 isc_uint32_t nanosecs;
2547 dns_rdataset_init(&rdataset);
2548 dns_fixedname_init(&fixed);
2549 result = dns_db_getsigningtime(zone->db, &rdataset,
2550 dns_fixedname_name(&fixed));
2551 if (result != ISC_R_SUCCESS) {
2552 isc_time_settoepoch(&zone->resigntime);
2553 return;
2555 resign = rdataset.resign;
2556 dns_rdataset_disassociate(&rdataset);
2557 isc_random_get(&nanosecs);
2558 nanosecs %= 1000000000;
2559 isc_time_set(&zone->resigntime, resign, nanosecs);
2562 static isc_result_t
2563 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
2564 dns_dbnode_t *node = NULL;
2565 dns_rdataset_t rdataset;
2566 dns_dbversion_t *version = NULL;
2567 dns_rdata_nsec3param_t nsec3param;
2568 isc_boolean_t ok = ISC_FALSE;
2569 isc_result_t result;
2570 dns_rdata_t rdata = DNS_RDATA_INIT;
2571 isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
2572 zone_isdynamic(zone) : ISC_FALSE;
2574 dns_rdataset_init(&rdataset);
2575 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2576 if (result != ISC_R_SUCCESS) {
2577 dns_zone_log(zone, ISC_LOG_ERROR,
2578 "nsec3param lookup failure: %s",
2579 dns_result_totext(result));
2580 return (result);
2582 dns_db_currentversion(db, &version);
2584 result = dns_db_findrdataset(db, node, version,
2585 dns_rdatatype_nsec3param,
2586 dns_rdatatype_none, 0, &rdataset, NULL);
2587 if (result == ISC_R_NOTFOUND) {
2588 INSIST(!dns_rdataset_isassociated(&rdataset));
2589 result = ISC_R_SUCCESS;
2590 goto cleanup;
2592 if (result != ISC_R_SUCCESS) {
2593 INSIST(!dns_rdataset_isassociated(&rdataset));
2594 dns_zone_log(zone, ISC_LOG_ERROR,
2595 "nsec3param lookup failure: %s",
2596 dns_result_totext(result));
2597 goto cleanup;
2601 * For dynamic zones we must support every algorithm so we can
2602 * regenerate all the NSEC3 chains.
2603 * For non-dynamic zones we only need to find a supported algorithm.
2605 for (result = dns_rdataset_first(&rdataset);
2606 result == ISC_R_SUCCESS;
2607 result = dns_rdataset_next(&rdataset))
2609 dns_rdataset_current(&rdataset, &rdata);
2610 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
2611 dns_rdata_reset(&rdata);
2612 INSIST(result == ISC_R_SUCCESS);
2613 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
2614 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
2616 dns_zone_log(zone, ISC_LOG_WARNING,
2617 "nsec3 test \"unknown\" hash algorithm found: %u",
2618 nsec3param.hash);
2619 ok = ISC_TRUE;
2620 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
2621 if (dynamic) {
2622 dns_zone_log(zone, ISC_LOG_ERROR,
2623 "unsupported nsec3 hash algorithm"
2624 " in dynamic zone: %u",
2625 nsec3param.hash);
2626 result = DNS_R_BADZONE;
2627 /* Stop second error message. */
2628 ok = ISC_TRUE;
2629 break;
2630 } else
2631 dns_zone_log(zone, ISC_LOG_WARNING,
2632 "unsupported nsec3 hash algorithm: %u",
2633 nsec3param.hash);
2634 } else
2635 ok = ISC_TRUE;
2637 if (result == ISC_R_NOMORE)
2638 result = ISC_R_SUCCESS;
2640 if (!ok) {
2641 result = DNS_R_BADZONE;
2642 dns_zone_log(zone, ISC_LOG_ERROR,
2643 "no supported nsec3 hash algorithm");
2646 cleanup:
2647 if (dns_rdataset_isassociated(&rdataset))
2648 dns_rdataset_disassociate(&rdataset);
2649 dns_db_closeversion(db, &version, ISC_FALSE);
2650 dns_db_detachnode(db, &node);
2651 return (result);
2655 * Set the timer for refreshing the key zone to the soonest future time
2656 * of the set (current timer, keydata->refresh, keydata->addhd,
2657 * keydata->removehd).
2659 static void
2660 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
2661 isc_stdtime_t now) {
2662 const char me[] = "set_refreshkeytimer";
2663 isc_stdtime_t then;
2664 isc_time_t timenow, timethen;
2666 ENTER;
2667 then = key->refresh;
2668 if (key->addhd > now && key->addhd < then)
2669 then = key->addhd;
2670 if (key->removehd > now && key->removehd < then)
2671 then = key->removehd;
2673 isc_time_set(&timenow, now, 0);
2674 isc_time_set(&timethen, ISC_MAX(then, now), 0);
2675 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
2676 isc_time_compare(&timethen, &zone->refreshkeytime) < 0) {
2677 zone->refreshkeytime = timethen;
2679 zone_settimer(zone, &timenow);
2683 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
2684 * If the key zone is changed, set '*changed' to ISC_TRUE.
2686 static isc_result_t
2687 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
2688 dns_diff_t *diff, dns_keytable_t *keytable,
2689 dns_keynode_t **keynodep, isc_boolean_t *changed)
2691 const char me[] = "create_keydata";
2692 isc_result_t result = ISC_R_SUCCESS;
2693 isc_buffer_t keyb, dstb;
2694 unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
2695 dns_rdata_keydata_t keydata;
2696 dns_rdata_dnskey_t dnskey;
2697 dns_rdata_t rdata = DNS_RDATA_INIT;
2698 dns_keynode_t *keynode;
2699 isc_stdtime_t now;
2700 isc_region_t r;
2701 dst_key_t *key;
2703 REQUIRE(keynodep != NULL);
2704 keynode = *keynodep;
2706 ENTER;
2707 isc_stdtime_get(&now);
2709 /* Loop in case there's more than one key. */
2710 while (result == ISC_R_SUCCESS) {
2711 dns_keynode_t *nextnode = NULL;
2713 key = dns_keynode_key(keynode);
2714 if (key == NULL)
2715 goto skip;
2717 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
2718 CHECK(dst_key_todns(key, &dstb));
2720 /* Convert DST key to DNSKEY. */
2721 dns_rdata_reset(&rdata);
2722 isc_buffer_usedregion(&dstb, &r);
2723 dns_rdata_fromregion(&rdata, dst_key_class(key),
2724 dns_rdatatype_dnskey, &r);
2726 /* DSTKEY to KEYDATA. */
2727 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
2728 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
2729 NULL));
2731 /* KEYDATA to rdata. */
2732 dns_rdata_reset(&rdata);
2733 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
2734 CHECK(dns_rdata_fromstruct(&rdata,
2735 zone->rdclass, dns_rdatatype_keydata,
2736 &keydata, &keyb));
2738 /* Add rdata to zone. */
2739 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
2740 dst_key_name(key), 0, &rdata));
2741 *changed = ISC_TRUE;
2743 skip:
2744 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
2745 if (result != ISC_R_NOTFOUND) {
2746 dns_keytable_detachkeynode(keytable, &keynode);
2747 keynode = nextnode;
2751 /* Refresh new keys from the zone apex as soon as possible. */
2752 if (*changed)
2753 set_refreshkeytimer(zone, &keydata, now);
2755 if (keynode != NULL)
2756 dns_keytable_detachkeynode(keytable, &keynode);
2757 *keynodep = NULL;
2759 return (ISC_R_SUCCESS);
2761 failure:
2762 return (result);
2766 * Remove from the key zone all the KEYDATA records found in rdataset.
2768 static isc_result_t
2769 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
2770 dns_name_t *name, dns_rdataset_t *rdataset)
2772 dns_rdata_t rdata = DNS_RDATA_INIT;
2773 isc_result_t result, uresult;
2775 for (result = dns_rdataset_first(rdataset);
2776 result == ISC_R_SUCCESS;
2777 result = dns_rdataset_next(rdataset)) {
2778 dns_rdata_reset(&rdata);
2779 dns_rdataset_current(rdataset, &rdata);
2780 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
2781 name, 0, &rdata);
2782 if (uresult != ISC_R_SUCCESS)
2783 return (uresult);
2785 if (result == ISC_R_NOMORE)
2786 result = ISC_R_SUCCESS;
2787 return (result);
2791 * Compute the DNSSEC key ID for a DNSKEY record.
2793 static isc_result_t
2794 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
2795 dns_keytag_t *tag)
2797 isc_result_t result;
2798 dns_rdata_t rdata = DNS_RDATA_INIT;
2799 unsigned char data[4096];
2800 isc_buffer_t buffer;
2801 dst_key_t *dstkey = NULL;
2803 isc_buffer_init(&buffer, data, sizeof(data));
2804 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2805 dns_rdatatype_dnskey, dnskey, &buffer);
2807 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
2808 if (result == ISC_R_SUCCESS)
2809 *tag = dst_key_id(dstkey);
2810 dst_key_free(&dstkey);
2812 return (result);
2816 * Add key to the security roots for all views.
2818 static void
2819 trust_key(dns_viewlist_t *viewlist, dns_name_t *keyname,
2820 dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
2821 isc_result_t result;
2822 dns_rdata_t rdata = DNS_RDATA_INIT;
2823 unsigned char data[4096];
2824 isc_buffer_t buffer;
2825 dns_view_t *view;
2826 dns_keytable_t *sr = NULL;
2828 /* Convert dnskey to DST key. */
2829 isc_buffer_init(&buffer, data, sizeof(data));
2830 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2831 dns_rdatatype_dnskey, dnskey, &buffer);
2833 for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
2834 view = ISC_LIST_NEXT(view, link)) {
2835 dst_key_t *key = NULL;
2837 result = dns_view_getsecroots(view, &sr);
2838 if (result != ISC_R_SUCCESS)
2839 continue;
2841 CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key));
2842 CHECK(dns_keytable_add(sr, ISC_TRUE, &key));
2843 dns_keytable_detach(&sr);
2846 failure:
2847 if (sr != NULL)
2848 dns_keytable_detach(&sr);
2849 return;
2853 * Remove key from the security roots for all views.
2855 static void
2856 untrust_key(dns_viewlist_t *viewlist, dns_name_t *keyname, isc_mem_t *mctx,
2857 dns_rdata_dnskey_t *dnskey)
2859 isc_result_t result;
2860 unsigned char data[4096];
2861 dns_rdata_t rdata = DNS_RDATA_INIT;
2862 isc_buffer_t buffer;
2863 dns_view_t *view;
2864 dst_key_t *key = NULL;
2867 * Clear the revoke bit, if set, so that the key will match what's
2868 * in secroots now.
2870 dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
2872 /* Convert dnskey to DST key. */
2873 isc_buffer_init(&buffer, data, sizeof(data));
2874 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
2875 dns_rdatatype_dnskey, dnskey, &buffer);
2876 result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
2877 if (result != ISC_R_SUCCESS)
2878 return;
2880 for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
2881 view = ISC_LIST_NEXT(view, link)) {
2882 dns_keytable_t *sr = NULL;
2883 result = dns_view_getsecroots(view, &sr);
2884 if (result != ISC_R_SUCCESS)
2885 continue;
2887 dns_keytable_deletekeynode(sr, key);
2888 dns_keytable_detach(&sr);
2891 dst_key_free(&key);
2895 * Add a null key to the security roots for all views, so that all queries
2896 * to the zone will fail.
2898 static void
2899 fail_secure(dns_viewlist_t *viewlist, dns_name_t *keyname) {
2900 isc_result_t result;
2901 dns_view_t *view;
2903 for (view = ISC_LIST_HEAD(*viewlist);
2904 view != NULL;
2905 view = ISC_LIST_NEXT(view, link)) {
2906 dns_keytable_t *sr = NULL;
2908 result = dns_view_getsecroots(view, &sr);
2909 if (result != ISC_R_SUCCESS)
2910 continue;
2912 dns_keytable_marksecure(sr, keyname);
2913 dns_keytable_detach(&sr);
2918 * Scan a set of KEYDATA records from the key zone. The ones that are
2919 * valid (i.e., the add holddown timer has expired) become trusted keys for
2920 * all views.
2922 static void
2923 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
2924 isc_result_t result;
2925 dns_rdata_t rdata = DNS_RDATA_INIT;
2926 dns_rdata_keydata_t keydata;
2927 dns_rdata_dnskey_t dnskey;
2928 isc_mem_t *mctx = zone->mctx;
2929 dns_view_t *view = zone->view;
2930 dns_viewlist_t *viewlist = view->viewlist;
2931 int trusted = 0, revoked = 0, pending = 0;
2932 isc_stdtime_t now;
2934 isc_stdtime_get(&now);
2936 /* For each view, delete references to this key from secroots. */
2937 for (view = ISC_LIST_HEAD(*viewlist); view != NULL;
2938 view = ISC_LIST_NEXT(view, link)) {
2939 dns_keytable_t *sr = NULL;
2941 result = dns_view_getsecroots(view, &sr);
2942 if (result != ISC_R_SUCCESS)
2943 continue;
2945 dns_keytable_delete(sr, name);
2946 dns_keytable_detach(&sr);
2949 /* Now insert all the accepted trust anchors from this keydata set. */
2950 for (result = dns_rdataset_first(rdataset);
2951 result == ISC_R_SUCCESS;
2952 result = dns_rdataset_next(rdataset)) {
2953 dns_rdata_reset(&rdata);
2954 dns_rdataset_current(rdataset, &rdata);
2956 /* Convert rdata to keydata. */
2957 dns_rdata_tostruct(&rdata, &keydata, NULL);
2959 /* Set the key refresh timer. */
2960 set_refreshkeytimer(zone, &keydata, now);
2962 /* If the removal timer is nonzero, this key was revoked. */
2963 if (keydata.removehd != 0) {
2964 revoked++;
2965 continue;
2969 * If the add timer is still pending, this key is not
2970 * trusted yet.
2972 if (now < keydata.addhd) {
2973 pending++;
2974 continue;
2977 /* Convert keydata to dnskey. */
2978 dns_keydata_todnskey(&keydata, &dnskey, NULL);
2980 /* Add to keytables. */
2981 trusted++;
2982 trust_key(viewlist, name, &dnskey, mctx);
2985 if (trusted == 0 && pending != 0) {
2986 char namebuf[DNS_NAME_FORMATSIZE];
2987 dns_name_format(name, namebuf, sizeof namebuf);
2988 dns_zone_log(zone, ISC_LOG_ERROR,
2989 "No valid trust anchors for '%s'!", namebuf);
2990 dns_zone_log(zone, ISC_LOG_ERROR,
2991 "%d key(s) revoked, %d still pending",
2992 revoked, pending);
2993 dns_zone_log(zone, ISC_LOG_ERROR,
2994 "All queries to '%s' will fail", namebuf);
2995 fail_secure(viewlist, name);
2999 static isc_result_t
3000 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3001 dns_diff_t *diff)
3003 dns_diff_t temp_diff;
3004 isc_result_t result;
3007 * Create a singleton diff.
3009 dns_diff_init(diff->mctx, &temp_diff);
3010 temp_diff.resign = diff->resign;
3011 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3014 * Apply it to the database.
3016 result = dns_diff_apply(&temp_diff, db, ver);
3017 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3018 if (result != ISC_R_SUCCESS) {
3019 dns_difftuple_free(tuple);
3020 return (result);
3024 * Merge it into the current pending journal entry.
3026 dns_diff_appendminimal(diff, tuple);
3029 * Do not clear temp_diff.
3031 return (ISC_R_SUCCESS);
3034 static isc_result_t
3035 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3036 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3037 dns_rdata_t *rdata)
3039 dns_difftuple_t *tuple = NULL;
3040 isc_result_t result;
3041 result = dns_difftuple_create(diff->mctx, op,
3042 name, ttl, rdata, &tuple);
3043 if (result != ISC_R_SUCCESS)
3044 return (result);
3045 return (do_one_tuple(&tuple, db, ver, diff));
3048 static isc_result_t
3049 increment_soa_serial(dns_db_t *db, dns_dbversion_t *ver,
3050 dns_diff_t *diff, isc_mem_t *mctx) {
3051 dns_difftuple_t *deltuple = NULL;
3052 dns_difftuple_t *addtuple = NULL;
3053 isc_uint32_t serial;
3054 isc_result_t result;
3056 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3057 CHECK(dns_difftuple_copy(deltuple, &addtuple));
3058 addtuple->op = DNS_DIFFOP_ADD;
3060 serial = dns_soa_getserial(&addtuple->rdata);
3062 /* RFC1982 */
3063 serial = (serial + 1) & 0xFFFFFFFF;
3064 if (serial == 0)
3065 serial = 1;
3067 dns_soa_setserial(serial, &addtuple->rdata);
3068 CHECK(do_one_tuple(&deltuple, db, ver, diff));
3069 CHECK(do_one_tuple(&addtuple, db, ver, diff));
3070 result = ISC_R_SUCCESS;
3072 failure:
3073 if (addtuple != NULL)
3074 dns_difftuple_free(&addtuple);
3075 if (deltuple != NULL)
3076 dns_difftuple_free(&deltuple);
3077 return (result);
3081 * Write all transactions in 'diff' to the zone journal file.
3083 static void
3084 zone_journal(dns_zone_t *zone, dns_diff_t *diff, const char *caller) {
3085 const char me[] = "zone_journal";
3086 const char *journalfile;
3087 isc_result_t result;
3088 dns_journal_t *journal = NULL;
3090 ENTER;
3091 journalfile = dns_zone_getjournal(zone);
3092 if (journalfile != NULL) {
3093 result = dns_journal_open(zone->mctx, journalfile,
3094 ISC_TRUE, &journal);
3095 if (result != ISC_R_SUCCESS) {
3096 dns_zone_log(zone, ISC_LOG_ERROR,
3097 "%s:dns_journal_open -> %s\n",
3098 caller, dns_result_totext(result));
3099 return;
3102 result = dns_journal_write_transaction(journal, diff);
3103 dns_journal_destroy(&journal);
3104 if (result != ISC_R_SUCCESS) {
3105 dns_zone_log(zone, ISC_LOG_ERROR,
3106 "%s:dns_journal_write_transaction -> %s\n",
3107 caller, dns_result_totext(result));
3108 return;
3114 * Create an SOA record for a newly-created zone
3116 static isc_result_t
3117 add_soa(dns_zone_t *zone, dns_db_t *db) {
3118 isc_result_t result;
3119 dns_rdata_t rdata = DNS_RDATA_INIT;
3120 unsigned char buf[DNS_SOA_BUFFERSIZE];
3121 dns_dbversion_t *ver = NULL;
3122 dns_diff_t diff;
3124 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3126 dns_diff_init(zone->mctx, &diff);
3127 result = dns_db_newversion(db, &ver);
3128 if (result != ISC_R_SUCCESS) {
3129 dns_zone_log(zone, ISC_LOG_ERROR,
3130 "add_soa:dns_db_newversion -> %s\n",
3131 dns_result_totext(result));
3132 goto failure;
3135 /* Build SOA record */
3136 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3137 0, 0, 0, 0, 0, buf, &rdata);
3138 if (result != ISC_R_SUCCESS) {
3139 dns_zone_log(zone, ISC_LOG_ERROR,
3140 "add_soa:dns_soa_buildrdata -> %s\n",
3141 dns_result_totext(result));
3142 goto failure;
3145 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3146 &zone->origin, 0, &rdata);
3148 failure:
3149 dns_diff_clear(&diff);
3150 if (ver != NULL)
3151 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3153 return (result);
3157 * Synchronize the set of initializing keys found in managed-keys {}
3158 * statements with the set of trust anchors found in the managed-keys.bind
3159 * zone. If a domain is no longer named in managed-keys, delete all keys
3160 * from that domain from the key zone. If a domain is mentioned in in
3161 * managed-keys but there are no references to it in the key zone, load
3162 * the key zone with the initializing key(s) for that domain.
3164 static isc_result_t
3165 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3166 isc_result_t result = ISC_R_SUCCESS;
3167 isc_boolean_t changed = ISC_FALSE;
3168 dns_rbtnodechain_t chain;
3169 dns_fixedname_t fn;
3170 dns_name_t foundname, *origin;
3171 dns_keynode_t *keynode = NULL;
3172 dns_view_t *view = zone->view;
3173 dns_keytable_t *sr = NULL;
3174 dns_dbversion_t *ver = NULL;
3175 dns_diff_t diff;
3176 dns_rriterator_t rrit;
3178 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3180 dns_name_init(&foundname, NULL);
3181 dns_fixedname_init(&fn);
3182 origin = dns_fixedname_name(&fn);
3184 dns_diff_init(zone->mctx, &diff);
3186 CHECK(dns_view_getsecroots(view, &sr));
3188 result = dns_db_newversion(db, &ver);
3189 if (result != ISC_R_SUCCESS) {
3190 dns_zone_log(zone, ISC_LOG_ERROR,
3191 "sync_keyzone:dns_db_newversion -> %s\n",
3192 dns_result_totext(result));
3193 goto failure;
3197 * Walk the zone DB. If we find any keys whose names are no longer
3198 * in managed-keys (or *are* in trusted-keys, meaning they are
3199 * permanent and not RFC5011-maintained), delete them from the
3200 * zone. Otherwise call load_secroots(), which loads keys into
3201 * secroots as appropriate.
3203 dns_rriterator_init(&rrit, db, ver, 0);
3204 for (result = dns_rriterator_first(&rrit);
3205 result == ISC_R_SUCCESS;
3206 result = dns_rriterator_nextrrset(&rrit)) {
3207 dns_rdataset_t *rdataset;
3208 dns_name_t *rrname = NULL;
3209 isc_uint32_t ttl;
3211 dns_rriterator_current(&rrit, &rrname, &ttl,
3212 &rdataset, NULL);
3213 if (!dns_rdataset_isassociated(rdataset)) {
3214 dns_rriterator_destroy(&rrit);
3215 goto failure;
3218 if (rdataset->type != dns_rdatatype_keydata)
3219 continue;
3221 result = dns_keytable_find(sr, rrname, &keynode);
3222 if ((result != ISC_R_SUCCESS &&
3223 result != DNS_R_PARTIALMATCH) ||
3224 dns_keynode_managed(keynode) == ISC_FALSE) {
3225 CHECK(delete_keydata(db, ver, &diff,
3226 rrname, rdataset));
3227 changed = ISC_TRUE;
3228 } else {
3229 load_secroots(zone, rrname, rdataset);
3232 if (keynode != NULL)
3233 dns_keytable_detachkeynode(sr, &keynode);
3235 dns_rriterator_destroy(&rrit);
3238 * Now walk secroots to find any managed keys that aren't
3239 * in the zone. If we find any, we add them to the zone.
3241 RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3242 dns_rbtnodechain_init(&chain, zone->mctx);
3243 result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3244 if (result == ISC_R_NOTFOUND)
3245 result = ISC_R_NOMORE;
3246 while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3247 dns_rbtnode_t *rbtnode = NULL;
3249 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3250 if (rbtnode->data == NULL)
3251 goto skip;
3253 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
3254 if (dns_keynode_managed(keynode)) {
3255 dns_fixedname_t fname;
3256 dns_name_t *keyname;
3257 dst_key_t *key;
3258 key = dns_keynode_key(keynode);
3259 dns_fixedname_init(&fname);
3261 if (key == NULL) /* fail_secure() was called. */
3262 goto skip;
3264 keyname = dst_key_name(key);
3265 result = dns_db_find(db, keyname, ver,
3266 dns_rdatatype_keydata,
3267 DNS_DBFIND_NOWILD, 0, NULL,
3268 dns_fixedname_name(&fname),
3269 NULL, NULL);
3270 if (result != ISC_R_SUCCESS)
3271 result = create_keydata(zone, db, ver, &diff,
3272 sr, &keynode, &changed);
3273 if (result != ISC_R_SUCCESS)
3274 break;
3276 skip:
3277 result = dns_rbtnodechain_next(&chain, &foundname, origin);
3278 if (keynode != NULL)
3279 dns_keytable_detachkeynode(sr, &keynode);
3281 RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
3283 if (result == ISC_R_NOMORE)
3284 result = ISC_R_SUCCESS;
3286 if (changed) {
3287 /* Write changes to journal file. */
3288 result = increment_soa_serial(db, ver, &diff, zone->mctx);
3289 if (result == ISC_R_SUCCESS)
3290 zone_journal(zone, &diff, "sync_keyzone");
3292 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
3293 zone_needdump(zone, 30);
3296 failure:
3297 if (keynode != NULL)
3298 dns_keytable_detachkeynode(sr, &keynode);
3299 if (sr != NULL)
3300 dns_keytable_detach(&sr);
3301 if (ver != NULL)
3302 dns_db_closeversion(db, &ver, changed);
3303 dns_diff_clear(&diff);
3305 return (result);
3308 static isc_result_t
3309 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
3310 isc_result_t result)
3312 unsigned int soacount = 0;
3313 unsigned int nscount = 0;
3314 unsigned int errors = 0;
3315 isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
3316 isc_time_t now;
3317 isc_boolean_t needdump = ISC_FALSE;
3318 isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3319 isc_boolean_t nomaster = ISC_FALSE;
3320 unsigned int options;
3322 TIME_NOW(&now);
3325 * Initiate zone transfer? We may need a error code that
3326 * indicates that the "permanent" form does not exist.
3327 * XXX better error feedback to log.
3329 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
3330 if (zone->type == dns_zone_slave ||
3331 zone->type == dns_zone_stub) {
3332 if (result == ISC_R_FILENOTFOUND)
3333 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3334 "no master file");
3335 else if (result != DNS_R_NOMASTERFILE)
3336 dns_zone_log(zone, ISC_LOG_ERROR,
3337 "loading from master file %s "
3338 "failed: %s",
3339 zone->masterfile,
3340 dns_result_totext(result));
3341 } else {
3342 dns_zone_log(zone, ISC_LOG_ERROR,
3343 "loading from master file %s failed: %s",
3344 zone->masterfile,
3345 dns_result_totext(result));
3346 nomaster = ISC_TRUE;
3349 if (zone->type != dns_zone_key)
3350 goto cleanup;
3353 dns_zone_log(zone, ISC_LOG_DEBUG(2),
3354 "number of nodes in database: %u",
3355 dns_db_nodecount(db));
3357 if (result == DNS_R_SEENINCLUDE)
3358 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3359 else
3360 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
3363 * If there's no master file for a key zone, then the zone is new:
3364 * create an SOA record. (We do this now, instead of later, so that
3365 * if there happens to be a journal file, we can roll forward from
3366 * a sane starting point.)
3368 if (nomaster && zone->type == dns_zone_key) {
3369 result = add_soa(zone, db);
3370 if (result != ISC_R_SUCCESS)
3371 goto cleanup;
3375 * Apply update log, if any, on initial load.
3377 if (zone->journal != NULL &&
3378 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
3379 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
3381 if (zone->type == dns_zone_master &&
3382 (zone->update_acl != NULL || zone->ssutable != NULL))
3383 options = DNS_JOURNALOPT_RESIGN;
3384 else
3385 options = 0;
3386 result = dns_journal_rollforward2(zone->mctx, db, options,
3387 zone->sigresigninginterval,
3388 zone->journal);
3389 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
3390 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
3391 result != ISC_R_RANGE) {
3392 dns_zone_log(zone, ISC_LOG_ERROR,
3393 "journal rollforward failed: %s",
3394 dns_result_totext(result));
3395 goto cleanup;
3397 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
3398 dns_zone_log(zone, ISC_LOG_ERROR,
3399 "journal rollforward failed: "
3400 "journal out of sync with zone");
3401 goto cleanup;
3403 dns_zone_log(zone, ISC_LOG_DEBUG(1),
3404 "journal rollforward completed "
3405 "successfully: %s",
3406 dns_result_totext(result));
3407 if (result == ISC_R_SUCCESS)
3408 needdump = ISC_TRUE;
3411 zone->loadtime = loadtime;
3413 dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
3415 * Obtain ns, soa and cname counts for top of zone.
3417 INSIST(db != NULL);
3418 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
3419 &refresh, &retry, &expire, &minimum,
3420 &errors);
3421 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
3422 dns_zone_log(zone, ISC_LOG_ERROR,
3423 "could not find NS and/or SOA records");
3427 * Master / Slave / Stub zones require both NS and SOA records at
3428 * the top of the zone.
3431 switch (zone->type) {
3432 case dns_zone_master:
3433 case dns_zone_slave:
3434 case dns_zone_stub:
3435 if (soacount != 1) {
3436 dns_zone_log(zone, ISC_LOG_ERROR,
3437 "has %d SOA records", soacount);
3438 result = DNS_R_BADZONE;
3440 if (nscount == 0) {
3441 dns_zone_log(zone, ISC_LOG_ERROR,
3442 "has no NS records");
3443 result = DNS_R_BADZONE;
3445 if (result != ISC_R_SUCCESS)
3446 goto cleanup;
3447 if (zone->type == dns_zone_master && errors != 0) {
3448 result = DNS_R_BADZONE;
3449 goto cleanup;
3451 if (zone->type != dns_zone_stub) {
3452 result = check_nsec3param(zone, db);
3453 if (result != ISC_R_SUCCESS)
3454 goto cleanup;
3456 if (zone->type == dns_zone_master &&
3457 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
3458 !integrity_checks(zone, db)) {
3459 result = DNS_R_BADZONE;
3460 goto cleanup;
3463 if (zone->type == dns_zone_master &&
3464 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
3465 !zone_check_dup(zone, db)) {
3466 result = DNS_R_BADZONE;
3467 goto cleanup;
3470 if (zone->db != NULL) {
3472 * This is checked in zone_replacedb() for slave zones
3473 * as they don't reload from disk.
3475 result = zone_get_from_db(zone, zone->db, NULL, NULL,
3476 &oldserial, NULL, NULL, NULL,
3477 NULL, NULL);
3478 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3479 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
3480 !isc_serial_gt(serial, oldserial)) {
3481 isc_uint32_t serialmin, serialmax;
3483 INSIST(zone->type == dns_zone_master);
3485 serialmin = (oldserial + 1) & 0xffffffffU;
3486 serialmax = (oldserial + 0x7fffffffU) &
3487 0xffffffffU;
3488 dns_zone_log(zone, ISC_LOG_ERROR,
3489 "ixfr-from-differences: "
3490 "new serial (%u) out of range "
3491 "[%u - %u]", serial, serialmin,
3492 serialmax);
3493 result = DNS_R_BADZONE;
3494 goto cleanup;
3495 } else if (!isc_serial_ge(serial, oldserial))
3496 dns_zone_log(zone, ISC_LOG_ERROR,
3497 "zone serial (%u/%u) has gone "
3498 "backwards", serial, oldserial);
3499 else if (serial == oldserial && !hasinclude)
3500 dns_zone_log(zone, ISC_LOG_ERROR,
3501 "zone serial (%u) unchanged. "
3502 "zone may fail to transfer "
3503 "to slaves.", serial);
3506 if (zone->type == dns_zone_master &&
3507 (zone->update_acl != NULL || zone->ssutable != NULL) &&
3508 zone->sigresigninginterval < (3 * refresh) &&
3509 dns_db_issecure(db))
3511 dns_zone_log(zone, ISC_LOG_WARNING,
3512 "sig-re-signing-interval less than "
3513 "3 * refresh.");
3516 zone->refresh = RANGE(refresh,
3517 zone->minrefresh, zone->maxrefresh);
3518 zone->retry = RANGE(retry,
3519 zone->minretry, zone->maxretry);
3520 zone->expire = RANGE(expire, zone->refresh + zone->retry,
3521 DNS_MAX_EXPIRE);
3522 zone->minimum = minimum;
3523 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
3525 if (zone->type == dns_zone_slave ||
3526 zone->type == dns_zone_stub) {
3527 isc_time_t t;
3528 isc_uint32_t delay;
3530 result = isc_file_getmodtime(zone->journal, &t);
3531 if (result != ISC_R_SUCCESS)
3532 result = isc_file_getmodtime(zone->masterfile,
3533 &t);
3534 if (result == ISC_R_SUCCESS)
3535 DNS_ZONE_TIME_ADD(&t, zone->expire,
3536 &zone->expiretime);
3537 else
3538 DNS_ZONE_TIME_ADD(&now, zone->retry,
3539 &zone->expiretime);
3541 delay = isc_random_jitter(zone->retry,
3542 (zone->retry * 3) / 4);
3543 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
3544 if (isc_time_compare(&zone->refreshtime,
3545 &zone->expiretime) >= 0)
3546 zone->refreshtime = now;
3548 break;
3550 case dns_zone_key:
3551 result = sync_keyzone(zone, db);
3552 if (result != ISC_R_SUCCESS)
3553 goto cleanup;
3554 break;
3556 default:
3557 UNEXPECTED_ERROR(__FILE__, __LINE__,
3558 "unexpected zone type %d", zone->type);
3559 result = ISC_R_UNEXPECTED;
3560 goto cleanup;
3564 * Check for weak DNSKEY's.
3566 if (zone->type == dns_zone_master)
3567 zone_check_dnskeys(zone, db);
3570 * Schedule DNSSEC key refresh.
3572 if (zone->type == dns_zone_master &&
3573 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
3574 zone->refreshkeytime = now;
3576 #if 0
3577 /* destroy notification example. */
3579 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
3580 DNS_EVENT_DBDESTROYED,
3581 dns_zonemgr_dbdestroyed,
3582 zone,
3583 sizeof(isc_event_t));
3584 dns_db_ondestroy(db, zone->task, &e);
3586 #endif
3588 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
3589 if (zone->db != NULL) {
3590 result = zone_replacedb(zone, db, ISC_FALSE);
3591 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3592 if (result != ISC_R_SUCCESS)
3593 goto cleanup;
3594 } else {
3595 zone_attachdb(zone, db);
3596 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
3597 DNS_ZONE_SETFLAG(zone,
3598 DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
3601 result = ISC_R_SUCCESS;
3603 if (needdump) {
3604 if (zone->type == dns_zone_key)
3605 zone_needdump(zone, 30);
3606 else
3607 zone_needdump(zone, DNS_DUMP_DELAY);
3610 if (zone->task != NULL) {
3611 if (zone->type == dns_zone_master) {
3612 set_resigntime(zone);
3613 resume_signingwithkey(zone);
3614 resume_addnsec3chain(zone);
3616 zone_settimer(zone, &now);
3619 if (! dns_db_ispersistent(db))
3620 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
3621 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
3623 return (result);
3625 cleanup:
3626 if (zone->type == dns_zone_slave ||
3627 zone->type == dns_zone_stub ||
3628 zone->type == dns_zone_key) {
3629 if (zone->journal != NULL)
3630 zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
3631 if (zone->masterfile != NULL)
3632 zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
3634 /* Mark the zone for immediate refresh. */
3635 zone->refreshtime = now;
3636 if (zone->task != NULL)
3637 zone_settimer(zone, &now);
3638 result = ISC_R_SUCCESS;
3640 return (result);
3643 static isc_boolean_t
3644 exit_check(dns_zone_t *zone) {
3646 REQUIRE(LOCKED_ZONE(zone));
3648 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
3649 zone->irefs == 0)
3652 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
3654 INSIST(isc_refcount_current(&zone->erefs) == 0);
3655 return (ISC_TRUE);
3657 return (ISC_FALSE);
3660 static isc_boolean_t
3661 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
3662 isc_boolean_t logit)
3664 isc_result_t result;
3665 char namebuf[DNS_NAME_FORMATSIZE];
3666 char altbuf[DNS_NAME_FORMATSIZE];
3667 dns_fixedname_t fixed;
3668 dns_name_t *foundname;
3669 int level;
3671 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
3672 return (ISC_TRUE);
3674 if (zone->type == dns_zone_master)
3675 level = ISC_LOG_ERROR;
3676 else
3677 level = ISC_LOG_WARNING;
3679 dns_fixedname_init(&fixed);
3680 foundname = dns_fixedname_name(&fixed);
3682 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
3683 0, 0, NULL, foundname, NULL, NULL);
3684 if (result == ISC_R_SUCCESS)
3685 return (ISC_TRUE);
3687 if (result == DNS_R_NXRRSET) {
3688 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
3689 0, 0, NULL, foundname, NULL, NULL);
3690 if (result == ISC_R_SUCCESS)
3691 return (ISC_TRUE);
3694 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3695 result == DNS_R_EMPTYNAME) {
3696 if (logit) {
3697 dns_name_format(name, namebuf, sizeof namebuf);
3698 dns_zone_log(zone, level, "NS '%s' has no address "
3699 "records (A or AAAA)", namebuf);
3701 return (ISC_FALSE);
3704 if (result == DNS_R_CNAME) {
3705 if (logit) {
3706 dns_name_format(name, namebuf, sizeof namebuf);
3707 dns_zone_log(zone, level, "NS '%s' is a CNAME "
3708 "(illegal)", namebuf);
3710 return (ISC_FALSE);
3713 if (result == DNS_R_DNAME) {
3714 if (logit) {
3715 dns_name_format(name, namebuf, sizeof namebuf);
3716 dns_name_format(foundname, altbuf, sizeof altbuf);
3717 dns_zone_log(zone, level, "NS '%s' is below a DNAME "
3718 "'%s' (illegal)", namebuf, altbuf);
3720 return (ISC_FALSE);
3723 return (ISC_TRUE);
3726 static isc_result_t
3727 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
3728 dns_dbversion_t *version, unsigned int *nscount,
3729 unsigned int *errors, isc_boolean_t logit)
3731 isc_result_t result;
3732 unsigned int count = 0;
3733 unsigned int ecount = 0;
3734 dns_rdataset_t rdataset;
3735 dns_rdata_t rdata;
3736 dns_rdata_ns_t ns;
3738 dns_rdataset_init(&rdataset);
3739 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
3740 dns_rdatatype_none, 0, &rdataset, NULL);
3741 if (result == ISC_R_NOTFOUND) {
3742 INSIST(!dns_rdataset_isassociated(&rdataset));
3743 goto success;
3745 if (result != ISC_R_SUCCESS) {
3746 INSIST(!dns_rdataset_isassociated(&rdataset));
3747 goto invalidate_rdataset;
3750 result = dns_rdataset_first(&rdataset);
3751 while (result == ISC_R_SUCCESS) {
3752 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
3753 (zone->type == dns_zone_master ||
3754 zone->type == dns_zone_slave)) {
3755 dns_rdata_init(&rdata);
3756 dns_rdataset_current(&rdataset, &rdata);
3757 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3758 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3759 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
3760 !zone_check_ns(zone, db, &ns.name, logit))
3761 ecount++;
3763 count++;
3764 result = dns_rdataset_next(&rdataset);
3766 dns_rdataset_disassociate(&rdataset);
3768 success:
3769 if (nscount != NULL)
3770 *nscount = count;
3771 if (errors != NULL)
3772 *errors = ecount;
3774 result = ISC_R_SUCCESS;
3776 invalidate_rdataset:
3777 dns_rdataset_invalidate(&rdataset);
3779 return (result);
3782 static isc_result_t
3783 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
3784 unsigned int *soacount,
3785 isc_uint32_t *serial, isc_uint32_t *refresh,
3786 isc_uint32_t *retry, isc_uint32_t *expire,
3787 isc_uint32_t *minimum)
3789 isc_result_t result;
3790 unsigned int count;
3791 dns_rdataset_t rdataset;
3792 dns_rdata_t rdata = DNS_RDATA_INIT;
3793 dns_rdata_soa_t soa;
3795 dns_rdataset_init(&rdataset);
3796 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
3797 dns_rdatatype_none, 0, &rdataset, NULL);
3798 if (result == ISC_R_NOTFOUND) {
3799 INSIST(!dns_rdataset_isassociated(&rdataset));
3800 if (soacount != NULL)
3801 *soacount = 0;
3802 if (serial != NULL)
3803 *serial = 0;
3804 if (refresh != NULL)
3805 *refresh = 0;
3806 if (retry != NULL)
3807 *retry = 0;
3808 if (expire != NULL)
3809 *expire = 0;
3810 if (minimum != NULL)
3811 *minimum = 0;
3812 result = ISC_R_SUCCESS;
3813 goto invalidate_rdataset;
3815 if (result != ISC_R_SUCCESS) {
3816 INSIST(!dns_rdataset_isassociated(&rdataset));
3817 goto invalidate_rdataset;
3820 count = 0;
3821 result = dns_rdataset_first(&rdataset);
3822 while (result == ISC_R_SUCCESS) {
3823 dns_rdata_init(&rdata);
3824 dns_rdataset_current(&rdataset, &rdata);
3825 count++;
3826 if (count == 1) {
3827 result = dns_rdata_tostruct(&rdata, &soa, NULL);
3828 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3831 result = dns_rdataset_next(&rdataset);
3832 dns_rdata_reset(&rdata);
3834 dns_rdataset_disassociate(&rdataset);
3836 if (soacount != NULL)
3837 *soacount = count;
3839 if (count > 0) {
3840 if (serial != NULL)
3841 *serial = soa.serial;
3842 if (refresh != NULL)
3843 *refresh = soa.refresh;
3844 if (retry != NULL)
3845 *retry = soa.retry;
3846 if (expire != NULL)
3847 *expire = soa.expire;
3848 if (minimum != NULL)
3849 *minimum = soa.minimum;
3852 result = ISC_R_SUCCESS;
3854 invalidate_rdataset:
3855 dns_rdataset_invalidate(&rdataset);
3857 return (result);
3861 * zone must be locked.
3863 static isc_result_t
3864 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
3865 unsigned int *soacount, isc_uint32_t *serial,
3866 isc_uint32_t *refresh, isc_uint32_t *retry,
3867 isc_uint32_t *expire, isc_uint32_t *minimum,
3868 unsigned int *errors)
3870 isc_result_t result;
3871 isc_result_t answer = ISC_R_SUCCESS;
3872 dns_dbversion_t *version = NULL;
3873 dns_dbnode_t *node;
3875 REQUIRE(db != NULL);
3876 REQUIRE(zone != NULL);
3878 dns_db_currentversion(db, &version);
3880 node = NULL;
3881 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3882 if (result != ISC_R_SUCCESS) {
3883 answer = result;
3884 goto closeversion;
3887 if (nscount != NULL || errors != NULL) {
3888 result = zone_count_ns_rr(zone, db, node, version,
3889 nscount, errors, ISC_TRUE);
3890 if (result != ISC_R_SUCCESS)
3891 answer = result;
3894 if (soacount != NULL || serial != NULL || refresh != NULL
3895 || retry != NULL || expire != NULL || minimum != NULL) {
3896 result = zone_load_soa_rr(db, node, version, soacount,
3897 serial, refresh, retry, expire,
3898 minimum);
3899 if (result != ISC_R_SUCCESS)
3900 answer = result;
3903 dns_db_detachnode(db, &node);
3904 closeversion:
3905 dns_db_closeversion(db, &version, ISC_FALSE);
3907 return (answer);
3910 void
3911 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
3912 REQUIRE(DNS_ZONE_VALID(source));
3913 REQUIRE(target != NULL && *target == NULL);
3914 isc_refcount_increment(&source->erefs, NULL);
3915 *target = source;
3918 void
3919 dns_zone_detach(dns_zone_t **zonep) {
3920 dns_zone_t *zone;
3921 unsigned int refs;
3922 isc_boolean_t free_now = ISC_FALSE;
3924 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3926 zone = *zonep;
3928 isc_refcount_decrement(&zone->erefs, &refs);
3930 if (refs == 0) {
3931 LOCK_ZONE(zone);
3933 * We just detached the last external reference.
3935 if (zone->task != NULL) {
3937 * This zone is being managed. Post
3938 * its control event and let it clean
3939 * up synchronously in the context of
3940 * its task.
3942 isc_event_t *ev = &zone->ctlevent;
3943 isc_task_send(zone->task, &ev);
3944 } else {
3946 * This zone is not being managed; it has
3947 * no task and can have no outstanding
3948 * events. Free it immediately.
3951 * Unmanaged zones should not have non-null views;
3952 * we have no way of detaching from the view here
3953 * without causing deadlock because this code is called
3954 * with the view already locked.
3956 INSIST(zone->view == NULL);
3957 free_now = ISC_TRUE;
3959 UNLOCK_ZONE(zone);
3961 *zonep = NULL;
3962 if (free_now)
3963 zone_free(zone);
3966 void
3967 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3968 REQUIRE(DNS_ZONE_VALID(source));
3969 REQUIRE(target != NULL && *target == NULL);
3970 LOCK_ZONE(source);
3971 zone_iattach(source, target);
3972 UNLOCK_ZONE(source);
3975 static void
3976 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
3979 * 'source' locked by caller.
3981 REQUIRE(LOCKED_ZONE(source));
3982 REQUIRE(DNS_ZONE_VALID(source));
3983 REQUIRE(target != NULL && *target == NULL);
3984 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
3985 source->irefs++;
3986 INSIST(source->irefs != 0);
3987 *target = source;
3990 static void
3991 zone_idetach(dns_zone_t **zonep) {
3992 dns_zone_t *zone;
3995 * 'zone' locked by caller.
3997 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
3998 zone = *zonep;
3999 REQUIRE(LOCKED_ZONE(*zonep));
4000 *zonep = NULL;
4002 INSIST(zone->irefs > 0);
4003 zone->irefs--;
4004 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
4007 void
4008 dns_zone_idetach(dns_zone_t **zonep) {
4009 dns_zone_t *zone;
4010 isc_boolean_t free_needed;
4012 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4013 zone = *zonep;
4014 *zonep = NULL;
4016 LOCK_ZONE(zone);
4017 INSIST(zone->irefs > 0);
4018 zone->irefs--;
4019 free_needed = exit_check(zone);
4020 UNLOCK_ZONE(zone);
4021 if (free_needed)
4022 zone_free(zone);
4025 isc_mem_t *
4026 dns_zone_getmctx(dns_zone_t *zone) {
4027 REQUIRE(DNS_ZONE_VALID(zone));
4029 return (zone->mctx);
4032 dns_zonemgr_t *
4033 dns_zone_getmgr(dns_zone_t *zone) {
4034 REQUIRE(DNS_ZONE_VALID(zone));
4036 return (zone->zmgr);
4039 void
4040 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
4041 REQUIRE(DNS_ZONE_VALID(zone));
4043 LOCK_ZONE(zone);
4044 if (value)
4045 DNS_ZONE_SETFLAG(zone, flags);
4046 else
4047 DNS_ZONE_CLRFLAG(zone, flags);
4048 UNLOCK_ZONE(zone);
4051 void
4052 dns_zone_setoption(dns_zone_t *zone, unsigned int option, isc_boolean_t value)
4054 REQUIRE(DNS_ZONE_VALID(zone));
4056 LOCK_ZONE(zone);
4057 if (value)
4058 zone->options |= option;
4059 else
4060 zone->options &= ~option;
4061 UNLOCK_ZONE(zone);
4064 unsigned int
4065 dns_zone_getoptions(dns_zone_t *zone) {
4067 REQUIRE(DNS_ZONE_VALID(zone));
4069 return (zone->options);
4072 void
4073 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
4075 REQUIRE(DNS_ZONE_VALID(zone));
4077 LOCK_ZONE(zone);
4078 if (value)
4079 zone->keyopts |= keyopt;
4080 else
4081 zone->keyopts &= ~keyopt;
4082 UNLOCK_ZONE(zone);
4085 unsigned int
4086 dns_zone_getkeyopts(dns_zone_t *zone) {
4088 REQUIRE(DNS_ZONE_VALID(zone));
4090 return (zone->keyopts);
4093 isc_result_t
4094 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4095 REQUIRE(DNS_ZONE_VALID(zone));
4097 LOCK_ZONE(zone);
4098 zone->xfrsource4 = *xfrsource;
4099 UNLOCK_ZONE(zone);
4101 return (ISC_R_SUCCESS);
4104 isc_sockaddr_t *
4105 dns_zone_getxfrsource4(dns_zone_t *zone) {
4106 REQUIRE(DNS_ZONE_VALID(zone));
4107 return (&zone->xfrsource4);
4110 isc_result_t
4111 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
4112 REQUIRE(DNS_ZONE_VALID(zone));
4114 LOCK_ZONE(zone);
4115 zone->xfrsource6 = *xfrsource;
4116 UNLOCK_ZONE(zone);
4118 return (ISC_R_SUCCESS);
4121 isc_sockaddr_t *
4122 dns_zone_getxfrsource6(dns_zone_t *zone) {
4123 REQUIRE(DNS_ZONE_VALID(zone));
4124 return (&zone->xfrsource6);
4127 isc_result_t
4128 dns_zone_setaltxfrsource4(dns_zone_t *zone,
4129 const isc_sockaddr_t *altxfrsource)
4131 REQUIRE(DNS_ZONE_VALID(zone));
4133 LOCK_ZONE(zone);
4134 zone->altxfrsource4 = *altxfrsource;
4135 UNLOCK_ZONE(zone);
4137 return (ISC_R_SUCCESS);
4140 isc_sockaddr_t *
4141 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
4142 REQUIRE(DNS_ZONE_VALID(zone));
4143 return (&zone->altxfrsource4);
4146 isc_result_t
4147 dns_zone_setaltxfrsource6(dns_zone_t *zone,
4148 const isc_sockaddr_t *altxfrsource)
4150 REQUIRE(DNS_ZONE_VALID(zone));
4152 LOCK_ZONE(zone);
4153 zone->altxfrsource6 = *altxfrsource;
4154 UNLOCK_ZONE(zone);
4156 return (ISC_R_SUCCESS);
4159 isc_sockaddr_t *
4160 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
4161 REQUIRE(DNS_ZONE_VALID(zone));
4162 return (&zone->altxfrsource6);
4165 isc_result_t
4166 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4167 REQUIRE(DNS_ZONE_VALID(zone));
4169 LOCK_ZONE(zone);
4170 zone->notifysrc4 = *notifysrc;
4171 UNLOCK_ZONE(zone);
4173 return (ISC_R_SUCCESS);
4176 isc_sockaddr_t *
4177 dns_zone_getnotifysrc4(dns_zone_t *zone) {
4178 REQUIRE(DNS_ZONE_VALID(zone));
4179 return (&zone->notifysrc4);
4182 isc_result_t
4183 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
4184 REQUIRE(DNS_ZONE_VALID(zone));
4186 LOCK_ZONE(zone);
4187 zone->notifysrc6 = *notifysrc;
4188 UNLOCK_ZONE(zone);
4190 return (ISC_R_SUCCESS);
4193 isc_sockaddr_t *
4194 dns_zone_getnotifysrc6(dns_zone_t *zone) {
4195 REQUIRE(DNS_ZONE_VALID(zone));
4196 return (&zone->notifysrc6);
4199 isc_result_t
4200 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
4201 isc_uint32_t count)
4203 isc_sockaddr_t *new;
4205 REQUIRE(DNS_ZONE_VALID(zone));
4206 REQUIRE(count == 0 || notify != NULL);
4208 LOCK_ZONE(zone);
4209 if (zone->notify != NULL) {
4210 isc_mem_put(zone->mctx, zone->notify,
4211 zone->notifycnt * sizeof(*new));
4212 zone->notify = NULL;
4213 zone->notifycnt = 0;
4215 if (count != 0) {
4216 new = isc_mem_get(zone->mctx, count * sizeof(*new));
4217 if (new == NULL) {
4218 UNLOCK_ZONE(zone);
4219 return (ISC_R_NOMEMORY);
4221 memcpy(new, notify, count * sizeof(*new));
4222 zone->notify = new;
4223 zone->notifycnt = count;
4225 UNLOCK_ZONE(zone);
4226 return (ISC_R_SUCCESS);
4229 isc_result_t
4230 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
4231 isc_uint32_t count)
4233 isc_result_t result;
4235 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
4236 return (result);
4239 static isc_boolean_t
4240 same_masters(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
4241 isc_uint32_t count)
4243 unsigned int i;
4245 for (i = 0; i < count; i++)
4246 if (!isc_sockaddr_equal(&old[i], &new[i]))
4247 return (ISC_FALSE);
4248 return (ISC_TRUE);
4251 static isc_boolean_t
4252 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
4253 unsigned int i;
4255 if (old == NULL && new == NULL)
4256 return (ISC_TRUE);
4257 if (old == NULL || new == NULL)
4258 return (ISC_FALSE);
4260 for (i = 0; i < count; i++) {
4261 if (old[i] == NULL && new[i] == NULL)
4262 continue;
4263 if (old[i] == NULL || new[i] == NULL ||
4264 !dns_name_equal(old[i], new[i]))
4265 return (ISC_FALSE);
4267 return (ISC_TRUE);
4270 isc_result_t
4271 dns_zone_setmasterswithkeys(dns_zone_t *zone,
4272 const isc_sockaddr_t *masters,
4273 dns_name_t **keynames,
4274 isc_uint32_t count)
4276 isc_sockaddr_t *new;
4277 isc_result_t result = ISC_R_SUCCESS;
4278 dns_name_t **newname;
4279 isc_boolean_t *newok;
4280 unsigned int i;
4282 REQUIRE(DNS_ZONE_VALID(zone));
4283 REQUIRE(count == 0 || masters != NULL);
4284 if (keynames != NULL) {
4285 REQUIRE(count != 0);
4288 LOCK_ZONE(zone);
4290 * The refresh code assumes that 'masters' wouldn't change under it.
4291 * If it will change then kill off any current refresh in progress
4292 * and update the masters info. If it won't change then we can just
4293 * unlock and exit.
4295 if (count != zone->masterscnt ||
4296 !same_masters(zone->masters, masters, count) ||
4297 !same_keynames(zone->masterkeynames, keynames, count)) {
4298 if (zone->request != NULL)
4299 dns_request_cancel(zone->request);
4300 } else
4301 goto unlock;
4302 if (zone->masters != NULL) {
4303 isc_mem_put(zone->mctx, zone->masters,
4304 zone->masterscnt * sizeof(*new));
4305 zone->masters = NULL;
4307 if (zone->masterkeynames != NULL) {
4308 for (i = 0; i < zone->masterscnt; i++) {
4309 if (zone->masterkeynames[i] != NULL) {
4310 dns_name_free(zone->masterkeynames[i],
4311 zone->mctx);
4312 isc_mem_put(zone->mctx,
4313 zone->masterkeynames[i],
4314 sizeof(dns_name_t));
4315 zone->masterkeynames[i] = NULL;
4318 isc_mem_put(zone->mctx, zone->masterkeynames,
4319 zone->masterscnt * sizeof(dns_name_t *));
4320 zone->masterkeynames = NULL;
4322 if (zone->mastersok != NULL) {
4323 isc_mem_put(zone->mctx, zone->mastersok,
4324 zone->masterscnt * sizeof(isc_boolean_t));
4325 zone->mastersok = NULL;
4327 zone->masterscnt = 0;
4329 * If count == 0, don't allocate any space for masters, mastersok or
4330 * keynames so internally, those pointers are NULL if count == 0
4332 if (count == 0)
4333 goto unlock;
4336 * masters must contain count elements!
4338 new = isc_mem_get(zone->mctx, count * sizeof(*new));
4339 if (new == NULL) {
4340 result = ISC_R_NOMEMORY;
4341 goto unlock;
4343 memcpy(new, masters, count * sizeof(*new));
4346 * Similarly for mastersok.
4348 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
4349 if (newok == NULL) {
4350 result = ISC_R_NOMEMORY;
4351 isc_mem_put(zone->mctx, new, count * sizeof(*new));
4352 goto unlock;
4354 for (i = 0; i < count; i++)
4355 newok[i] = ISC_FALSE;
4358 * if keynames is non-NULL, it must contain count elements!
4360 newname = NULL;
4361 if (keynames != NULL) {
4362 newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
4363 if (newname == NULL) {
4364 result = ISC_R_NOMEMORY;
4365 isc_mem_put(zone->mctx, new, count * sizeof(*new));
4366 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
4367 goto unlock;
4369 for (i = 0; i < count; i++)
4370 newname[i] = NULL;
4371 for (i = 0; i < count; i++) {
4372 if (keynames[i] != NULL) {
4373 newname[i] = isc_mem_get(zone->mctx,
4374 sizeof(dns_name_t));
4375 if (newname[i] == NULL)
4376 goto allocfail;
4377 dns_name_init(newname[i], NULL);
4378 result = dns_name_dup(keynames[i], zone->mctx,
4379 newname[i]);
4380 if (result != ISC_R_SUCCESS) {
4381 allocfail:
4382 for (i = 0; i < count; i++)
4383 if (newname[i] != NULL)
4384 dns_name_free(
4385 newname[i],
4386 zone->mctx);
4387 isc_mem_put(zone->mctx, new,
4388 count * sizeof(*new));
4389 isc_mem_put(zone->mctx, newok,
4390 count * sizeof(*newok));
4391 isc_mem_put(zone->mctx, newname,
4392 count * sizeof(*newname));
4393 goto unlock;
4400 * Everything is ok so attach to the zone.
4402 zone->masters = new;
4403 zone->mastersok = newok;
4404 zone->masterkeynames = newname;
4405 zone->masterscnt = count;
4406 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
4408 unlock:
4409 UNLOCK_ZONE(zone);
4410 return (result);
4413 isc_result_t
4414 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
4415 isc_result_t result = ISC_R_SUCCESS;
4417 REQUIRE(DNS_ZONE_VALID(zone));
4419 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4420 if (zone->db == NULL)
4421 result = DNS_R_NOTLOADED;
4422 else
4423 dns_db_attach(zone->db, dpb);
4424 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4426 return (result);
4430 * Co-ordinates the starting of routine jobs.
4433 void
4434 dns_zone_maintenance(dns_zone_t *zone) {
4435 const char me[] = "dns_zone_maintenance";
4436 isc_time_t now;
4438 REQUIRE(DNS_ZONE_VALID(zone));
4439 ENTER;
4441 LOCK_ZONE(zone);
4442 TIME_NOW(&now);
4443 zone_settimer(zone, &now);
4444 UNLOCK_ZONE(zone);
4447 static inline isc_boolean_t
4448 was_dumping(dns_zone_t *zone) {
4449 isc_boolean_t dumping;
4451 REQUIRE(LOCKED_ZONE(zone));
4453 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
4454 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
4455 if (!dumping) {
4456 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
4457 isc_time_settoepoch(&zone->dumptime);
4459 return (dumping);
4462 #define MAXZONEKEYS 10
4464 static isc_result_t
4465 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4466 isc_mem_t *mctx, unsigned int maxkeys,
4467 dst_key_t **keys, unsigned int *nkeys)
4469 isc_result_t result;
4470 dns_dbnode_t *node = NULL;
4471 const char *directory = dns_zone_getkeydirectory(zone);
4472 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
4473 result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
4474 directory, mctx, maxkeys, keys,
4475 nkeys);
4476 if (result == ISC_R_NOTFOUND)
4477 result = ISC_R_SUCCESS;
4478 failure:
4479 if (node != NULL)
4480 dns_db_detachnode(db, &node);
4481 return (result);
4484 static isc_result_t
4485 offline(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff, dns_name_t *name,
4486 dns_ttl_t ttl, dns_rdata_t *rdata)
4488 isc_result_t result;
4490 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
4491 return (ISC_R_SUCCESS);
4492 result = update_one_rr(db, ver, diff, DNS_DIFFOP_DELRESIGN,
4493 name, ttl, rdata);
4494 if (result != ISC_R_SUCCESS)
4495 return (result);
4496 rdata->flags |= DNS_RDATA_OFFLINE;
4497 result = update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4498 name, ttl, rdata);
4499 return (result);
4502 static void
4503 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
4505 unsigned int delta;
4507 zone->key_expiry = when;
4508 if (when <= now) {
4509 dns_zone_log(zone, ISC_LOG_ERROR,
4510 "DNSKEY RRSIG(s) have expired");
4511 isc_time_settoepoch(&zone->keywarntime);
4512 } else if (when < now + 7 * 24 * 3600) {
4513 dns_zone_log(zone, ISC_LOG_WARNING,
4514 "DNSKEY RRSIG(s) will expire at %u",
4515 when); /* XXXMPA convert to date. */
4516 delta = when - now;
4517 delta--; /* loop prevention */
4518 delta /= 24 * 3600; /* to whole days */
4519 delta *= 24 * 3600; /* to seconds */
4520 isc_time_set(&zone->keywarntime, when - delta, 0);
4521 } else {
4522 dns_zone_log(zone, ISC_LOG_NOTICE, /* XXMPA ISC_LOG_DEBUG(1) */
4523 "setting keywarntime to %u - 7 days",
4524 when); /* XXXMPA convert to date. */
4525 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
4530 * Delete expired RRsigs and any RRsigs we are about to re-sign.
4531 * See also update.c:del_keysigs().
4533 static isc_result_t
4534 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4535 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4536 unsigned int nkeys, isc_stdtime_t now)
4538 isc_result_t result;
4539 dns_dbnode_t *node = NULL;
4540 dns_rdataset_t rdataset;
4541 dns_rdata_t rdata = DNS_RDATA_INIT;
4542 unsigned int i;
4543 dns_rdata_rrsig_t rrsig;
4544 isc_boolean_t found;
4545 isc_stdtime_t warn = 0, maybe = 0;
4547 dns_rdataset_init(&rdataset);
4549 if (type == dns_rdatatype_nsec3)
4550 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4551 else
4552 result = dns_db_findnode(db, name, ISC_FALSE, &node);
4553 if (result == ISC_R_NOTFOUND)
4554 return (ISC_R_SUCCESS);
4555 if (result != ISC_R_SUCCESS)
4556 goto failure;
4557 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
4558 (isc_stdtime_t) 0, &rdataset, NULL);
4559 dns_db_detachnode(db, &node);
4561 if (result == ISC_R_NOTFOUND) {
4562 INSIST(!dns_rdataset_isassociated(&rdataset));
4563 return (ISC_R_SUCCESS);
4565 if (result != ISC_R_SUCCESS) {
4566 INSIST(!dns_rdataset_isassociated(&rdataset));
4567 goto failure;
4570 for (result = dns_rdataset_first(&rdataset);
4571 result == ISC_R_SUCCESS;
4572 result = dns_rdataset_next(&rdataset)) {
4573 dns_rdataset_current(&rdataset, &rdata);
4574 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
4575 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4577 if (type != dns_rdatatype_dnskey) {
4578 result = update_one_rr(db, ver, diff,
4579 DNS_DIFFOP_DEL, name,
4580 rdataset.ttl, &rdata);
4581 dns_rdata_reset(&rdata);
4582 if (result != ISC_R_SUCCESS)
4583 break;
4584 continue;
4588 * RRSIG(DNSKEY) requires special processing.
4590 found = ISC_FALSE;
4591 for (i = 0; i < nkeys; i++) {
4592 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
4593 rrsig.keyid == dst_key_id(keys[i])) {
4594 found = ISC_TRUE;
4596 * Mark offline RRSIG(DNSKEY).
4597 * We want the earliest offline expire time
4598 * iff there is a new offline signature.
4600 if (!dst_key_isprivate(keys[i])) {
4601 if (warn != 0 &&
4602 warn > rrsig.timeexpire)
4603 warn = rrsig.timeexpire;
4604 if (rdata.flags & DNS_RDATA_OFFLINE) {
4605 if (maybe == 0 ||
4606 maybe > rrsig.timeexpire)
4607 maybe =
4608 rrsig.timeexpire;
4609 break;
4611 if (warn == 0)
4612 warn = maybe;
4613 if (warn == 0 ||
4614 warn > rrsig.timeexpire)
4615 warn = rrsig.timeexpire;
4616 result = offline(db, ver, diff, name,
4617 rdataset.ttl, &rdata);
4618 break;
4620 result = update_one_rr(db, ver, diff,
4621 DNS_DIFFOP_DEL,
4622 name, rdataset.ttl,
4623 &rdata);
4624 break;
4628 * If there is not a matching DNSKEY then
4629 * delete the RRSIG.
4631 if (!found)
4632 result = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
4633 name, rdataset.ttl, &rdata);
4634 dns_rdata_reset(&rdata);
4635 if (result != ISC_R_SUCCESS)
4636 break;
4638 dns_rdataset_disassociate(&rdataset);
4639 if (result == ISC_R_NOMORE)
4640 result = ISC_R_SUCCESS;
4641 if (warn != 0)
4642 set_key_expiry_warning(zone, warn, now);
4643 failure:
4644 if (node != NULL)
4645 dns_db_detachnode(db, &node);
4646 return (result);
4649 static isc_result_t
4650 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
4651 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
4652 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
4653 isc_stdtime_t expire, isc_boolean_t check_ksk,
4654 isc_boolean_t keyset_kskonly)
4656 isc_result_t result;
4657 dns_dbnode_t *node = NULL;
4658 dns_rdataset_t rdataset;
4659 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
4660 unsigned char data[1024]; /* XXX */
4661 isc_buffer_t buffer;
4662 unsigned int i, j;
4664 dns_rdataset_init(&rdataset);
4665 isc_buffer_init(&buffer, data, sizeof(data));
4667 if (type == dns_rdatatype_nsec3)
4668 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
4669 else
4670 result = dns_db_findnode(db, name, ISC_FALSE, &node);
4671 if (result == ISC_R_NOTFOUND)
4672 return (ISC_R_SUCCESS);
4673 if (result != ISC_R_SUCCESS)
4674 goto failure;
4675 result = dns_db_findrdataset(db, node, ver, type, 0,
4676 (isc_stdtime_t) 0, &rdataset, NULL);
4677 dns_db_detachnode(db, &node);
4678 if (result == ISC_R_NOTFOUND) {
4679 INSIST(!dns_rdataset_isassociated(&rdataset));
4680 return (ISC_R_SUCCESS);
4682 if (result != ISC_R_SUCCESS) {
4683 INSIST(!dns_rdataset_isassociated(&rdataset));
4684 goto failure;
4687 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
4688 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
4689 #define ALG(x) dst_key_alg(x)
4691 for (i = 0; i < nkeys; i++) {
4692 isc_boolean_t both = ISC_FALSE;
4694 if (!dst_key_isprivate(keys[i]))
4695 continue;
4697 if (check_ksk && !REVOKE(keys[i])) {
4698 isc_boolean_t have_ksk, have_nonksk;
4699 if (KSK(keys[i])) {
4700 have_ksk = ISC_TRUE;
4701 have_nonksk = ISC_FALSE;
4702 } else {
4703 have_ksk = ISC_FALSE;
4704 have_nonksk = ISC_TRUE;
4706 for (j = 0; j < nkeys; j++) {
4707 if (j == i || ALG(keys[i]) != ALG(keys[j]))
4708 continue;
4709 if (REVOKE(keys[j]))
4710 continue;
4711 if (KSK(keys[j]))
4712 have_ksk = ISC_TRUE;
4713 else
4714 have_nonksk = ISC_TRUE;
4715 both = have_ksk && have_nonksk;
4716 if (both)
4717 break;
4720 if (both) {
4721 if (type == dns_rdatatype_dnskey) {
4722 if (!KSK(keys[i]) && keyset_kskonly)
4723 continue;
4724 } else if (KSK(keys[i]))
4725 continue;
4726 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
4727 continue;
4729 /* Calculate the signature, creating a RRSIG RDATA. */
4730 isc_buffer_clear(&buffer);
4731 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
4732 &inception, &expire,
4733 mctx, &buffer, &sig_rdata));
4734 /* Update the database and journal with the RRSIG. */
4735 /* XXX inefficient - will cause dataset merging */
4736 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
4737 name, rdataset.ttl, &sig_rdata));
4738 dns_rdata_reset(&sig_rdata);
4741 failure:
4742 if (dns_rdataset_isassociated(&rdataset))
4743 dns_rdataset_disassociate(&rdataset);
4744 if (node != NULL)
4745 dns_db_detachnode(db, &node);
4746 return (result);
4749 static void
4750 zone_resigninc(dns_zone_t *zone) {
4751 dns_db_t *db = NULL;
4752 dns_dbversion_t *version = NULL;
4753 dns_diff_t sig_diff;
4754 dns_fixedname_t fixed;
4755 dns_name_t *name;
4756 dns_rdataset_t rdataset;
4757 dns_rdatatype_t covers;
4758 dst_key_t *zone_keys[MAXZONEKEYS];
4759 isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
4760 isc_result_t result;
4761 isc_stdtime_t now, inception, soaexpire, expire, stop;
4762 isc_uint32_t jitter;
4763 unsigned int i;
4764 unsigned int nkeys = 0;
4765 unsigned int resign;
4767 dns_rdataset_init(&rdataset);
4768 dns_fixedname_init(&fixed);
4769 dns_diff_init(zone->mctx, &sig_diff);
4770 sig_diff.resign = zone->sigresigninginterval;
4773 * Updates are disabled. Pause for 5 minutes.
4775 if (zone->update_disabled) {
4776 result = ISC_R_FAILURE;
4777 goto failure;
4780 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
4781 dns_db_attach(zone->db, &db);
4782 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
4784 result = dns_db_newversion(db, &version);
4785 if (result != ISC_R_SUCCESS) {
4786 dns_zone_log(zone, ISC_LOG_ERROR,
4787 "zone_resigninc:dns_db_newversion -> %s\n",
4788 dns_result_totext(result));
4789 goto failure;
4792 result = find_zone_keys(zone, db, version, zone->mctx, MAXZONEKEYS,
4793 zone_keys, &nkeys);
4794 if (result != ISC_R_SUCCESS) {
4795 dns_zone_log(zone, ISC_LOG_ERROR,
4796 "zone_resigninc:find_zone_keys -> %s\n",
4797 dns_result_totext(result));
4798 goto failure;
4801 isc_stdtime_get(&now);
4802 inception = now - 3600; /* Allow for clock skew. */
4803 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
4805 * Spread out signatures over time if they happen to be
4806 * clumped. We don't do this for each add_sigs() call as
4807 * we still want some clustering to occur.
4809 isc_random_get(&jitter);
4810 expire = soaexpire - jitter % 3600;
4811 stop = now + 5;
4813 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
4814 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
4816 name = dns_fixedname_name(&fixed);
4817 result = dns_db_getsigningtime(db, &rdataset, name);
4818 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
4819 dns_zone_log(zone, ISC_LOG_ERROR,
4820 "zone_resigninc:dns_db_getsigningtime -> %s\n",
4821 dns_result_totext(result));
4824 i = 0;
4825 while (result == ISC_R_SUCCESS) {
4826 resign = rdataset.resign;
4827 covers = rdataset.covers;
4829 * Stop if we hit the SOA as that means we have walked the
4830 * entire zone. The SOA record should always be the most
4831 * recent signature.
4833 /* XXXMPA increase number of RRsets signed pre call */
4834 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
4835 resign > stop) {
4837 * Ensure that we don't loop resigning the SOA.
4839 if (covers == dns_rdatatype_soa)
4840 dns_db_resigned(db, &rdataset, version);
4841 dns_rdataset_disassociate(&rdataset);
4842 break;
4845 dns_db_resigned(db, &rdataset, version);
4846 dns_rdataset_disassociate(&rdataset);
4848 result = del_sigs(zone, db, version, name, covers, &sig_diff,
4849 zone_keys, nkeys, now);
4850 if (result != ISC_R_SUCCESS) {
4851 dns_zone_log(zone, ISC_LOG_ERROR,
4852 "zone_resigninc:del_sigs -> %s\n",
4853 dns_result_totext(result));
4854 break;
4856 result = add_sigs(db, version, name, covers, &sig_diff,
4857 zone_keys, nkeys, zone->mctx, inception,
4858 expire, check_ksk, keyset_kskonly);
4859 if (result != ISC_R_SUCCESS) {
4860 dns_zone_log(zone, ISC_LOG_ERROR,
4861 "zone_resigninc:add_sigs -> %s\n",
4862 dns_result_totext(result));
4863 break;
4865 result = dns_db_getsigningtime(db, &rdataset,
4866 dns_fixedname_name(&fixed));
4867 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
4868 result = ISC_R_SUCCESS;
4869 break;
4871 if (result != ISC_R_SUCCESS)
4872 dns_zone_log(zone, ISC_LOG_ERROR,
4873 "zone_resigninc:dns_db_getsigningtime -> %s\n",
4874 dns_result_totext(result));
4877 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
4878 goto failure;
4880 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
4881 &sig_diff, zone_keys, nkeys, now);
4882 if (result != ISC_R_SUCCESS) {
4883 dns_zone_log(zone, ISC_LOG_ERROR,
4884 "zone_resigninc:del_sigs -> %s\n",
4885 dns_result_totext(result));
4886 goto failure;
4889 result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
4890 if (result != ISC_R_SUCCESS) {
4891 dns_zone_log(zone, ISC_LOG_ERROR,
4892 "zone_resigninc:increment_soa_serial -> %s\n",
4893 dns_result_totext(result));
4894 goto failure;
4898 * Generate maximum life time signatures so that the above loop
4899 * termination is sensible.
4901 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
4902 &sig_diff, zone_keys, nkeys, zone->mctx, inception,
4903 soaexpire, check_ksk, keyset_kskonly);
4904 if (result != ISC_R_SUCCESS) {
4905 dns_zone_log(zone, ISC_LOG_ERROR,
4906 "zone_resigninc:add_sigs -> %s\n",
4907 dns_result_totext(result));
4908 goto failure;
4911 /* Write changes to journal file. */
4912 zone_journal(zone, &sig_diff, "zone_resigninc");
4914 /* Everything has succeeded. Commit the changes. */
4915 dns_db_closeversion(db, &version, ISC_TRUE);
4917 failure:
4918 dns_diff_clear(&sig_diff);
4919 for (i = 0; i < nkeys; i++)
4920 dst_key_free(&zone_keys[i]);
4921 if (version != NULL) {
4922 dns_db_closeversion(zone->db, &version, ISC_FALSE);
4923 dns_db_detach(&db);
4924 } else if (db != NULL)
4925 dns_db_detach(&db);
4926 if (result == ISC_R_SUCCESS) {
4927 set_resigntime(zone);
4928 LOCK_ZONE(zone);
4929 zone_needdump(zone, DNS_DUMP_DELAY);
4930 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
4931 UNLOCK_ZONE(zone);
4932 } else {
4934 * Something failed. Retry in 5 minutes.
4936 isc_interval_t ival;
4937 isc_interval_set(&ival, 300, 0);
4938 isc_time_nowplusinterval(&zone->resigntime, &ival);
4942 static isc_result_t
4943 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
4944 dns_name_t *newname, isc_boolean_t bottom)
4946 isc_result_t result;
4947 dns_dbiterator_t *dbit = NULL;
4948 dns_rdatasetiter_t *rdsit = NULL;
4949 dns_dbnode_t *node = NULL;
4951 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
4952 CHECK(dns_dbiterator_seek(dbit, oldname));
4953 do {
4954 result = dns_dbiterator_next(dbit);
4955 if (result == ISC_R_NOMORE)
4956 CHECK(dns_dbiterator_first(dbit));
4957 CHECK(dns_dbiterator_current(dbit, &node, newname));
4958 if (bottom && dns_name_issubdomain(newname, oldname) &&
4959 !dns_name_equal(newname, oldname)) {
4960 dns_db_detachnode(db, &node);
4961 continue;
4964 * Is this node empty?
4966 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
4967 result = dns_rdatasetiter_first(rdsit);
4968 dns_db_detachnode(db, &node);
4969 dns_rdatasetiter_destroy(&rdsit);
4970 if (result != ISC_R_NOMORE)
4971 break;
4972 } while (1);
4973 failure:
4974 if (node != NULL)
4975 dns_db_detachnode(db, &node);
4976 if (dbit != NULL)
4977 dns_dbiterator_destroy(&dbit);
4978 return (result);
4981 static isc_boolean_t
4982 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4983 dns_rdatatype_t type, dst_key_t *key)
4985 isc_result_t result;
4986 dns_rdataset_t rdataset;
4987 dns_rdata_t rdata = DNS_RDATA_INIT;
4988 dns_rdata_rrsig_t rrsig;
4990 dns_rdataset_init(&rdataset);
4991 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
4992 type, 0, &rdataset, NULL);
4993 if (result != ISC_R_SUCCESS) {
4994 INSIST(!dns_rdataset_isassociated(&rdataset));
4995 return (ISC_FALSE);
4997 for (result = dns_rdataset_first(&rdataset);
4998 result == ISC_R_SUCCESS;
4999 result = dns_rdataset_next(&rdataset)) {
5000 dns_rdataset_current(&rdataset, &rdata);
5001 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5002 INSIST(result == ISC_R_SUCCESS);
5003 if (rrsig.algorithm == dst_key_alg(key) &&
5004 rrsig.keyid == dst_key_id(key)) {
5005 dns_rdataset_disassociate(&rdataset);
5006 return (ISC_TRUE);
5008 dns_rdata_reset(&rdata);
5010 dns_rdataset_disassociate(&rdataset);
5011 return (ISC_FALSE);
5014 static isc_result_t
5015 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5016 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
5017 dns_diff_t *diff)
5019 dns_fixedname_t fixed;
5020 dns_name_t *next;
5021 dns_rdata_t rdata = DNS_RDATA_INIT;
5022 isc_result_t result;
5023 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
5025 dns_fixedname_init(&fixed);
5026 next = dns_fixedname_name(&fixed);
5028 CHECK(next_active(db, version, name, next, bottom));
5029 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
5030 &rdata));
5031 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
5032 &rdata));
5033 failure:
5034 return (result);
5037 static isc_result_t
5038 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
5039 dns_dbversion_t *version, isc_boolean_t build_nsec3,
5040 isc_boolean_t build_nsec, dst_key_t *key,
5041 isc_stdtime_t inception, isc_stdtime_t expire,
5042 unsigned int minimum, isc_boolean_t is_ksk,
5043 isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
5044 dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
5046 isc_result_t result;
5047 dns_rdatasetiter_t *iterator = NULL;
5048 dns_rdataset_t rdataset;
5049 dns_rdata_t rdata = DNS_RDATA_INIT;
5050 isc_buffer_t buffer;
5051 unsigned char data[1024];
5052 isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
5053 seen_nsec3, seen_ds;
5054 isc_boolean_t bottom;
5056 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5057 if (result != ISC_R_SUCCESS) {
5058 if (result == ISC_R_NOTFOUND)
5059 result = ISC_R_SUCCESS;
5060 return (result);
5063 dns_rdataset_init(&rdataset);
5064 isc_buffer_init(&buffer, data, sizeof(data));
5065 seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
5066 seen_nsec3 = seen_ds = ISC_FALSE;
5067 for (result = dns_rdatasetiter_first(iterator);
5068 result == ISC_R_SUCCESS;
5069 result = dns_rdatasetiter_next(iterator)) {
5070 dns_rdatasetiter_current(iterator, &rdataset);
5071 if (rdataset.type == dns_rdatatype_soa)
5072 seen_soa = ISC_TRUE;
5073 else if (rdataset.type == dns_rdatatype_ns)
5074 seen_ns = ISC_TRUE;
5075 else if (rdataset.type == dns_rdatatype_ds)
5076 seen_ds = ISC_TRUE;
5077 else if (rdataset.type == dns_rdatatype_dname)
5078 seen_dname = ISC_TRUE;
5079 else if (rdataset.type == dns_rdatatype_nsec)
5080 seen_nsec = ISC_TRUE;
5081 else if (rdataset.type == dns_rdatatype_nsec3)
5082 seen_nsec3 = ISC_TRUE;
5083 if (rdataset.type != dns_rdatatype_rrsig)
5084 seen_rr = ISC_TRUE;
5085 dns_rdataset_disassociate(&rdataset);
5087 if (result != ISC_R_NOMORE)
5088 goto failure;
5089 if (seen_ns && !seen_soa)
5090 *delegation = ISC_TRUE;
5092 * Going from insecure to NSEC3.
5093 * Don't generate NSEC3 records for NSEC3 records.
5095 if (build_nsec3 && !seen_nsec3 && seen_rr) {
5096 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
5097 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
5098 unsecure, diff));
5099 (*signatures)--;
5102 * Going from insecure to NSEC.
5103 * Don't generate NSEC records for NSEC3 records.
5105 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
5106 /* Build and add NSEC. */
5107 bottom = (seen_ns && !seen_soa) || seen_dname;
5109 * Build a NSEC record except at the origin.
5111 if (!dns_name_equal(name, dns_db_origin(db))) {
5112 CHECK(add_nsec(db, version, name, node, minimum,
5113 bottom, diff));
5114 /* Count a NSEC generation as a signature generation. */
5115 (*signatures)--;
5118 result = dns_rdatasetiter_first(iterator);
5119 while (result == ISC_R_SUCCESS) {
5120 dns_rdatasetiter_current(iterator, &rdataset);
5121 if (rdataset.type == dns_rdatatype_soa ||
5122 rdataset.type == dns_rdatatype_rrsig)
5123 goto next_rdataset;
5124 if (rdataset.type == dns_rdatatype_dnskey) {
5125 if (!is_ksk && keyset_kskonly)
5126 goto next_rdataset;
5127 } else if (is_ksk)
5128 goto next_rdataset;
5129 if (*delegation &&
5130 rdataset.type != dns_rdatatype_ds &&
5131 rdataset.type != dns_rdatatype_nsec)
5132 goto next_rdataset;
5133 if (signed_with_key(db, node, version, rdataset.type, key))
5134 goto next_rdataset;
5135 /* Calculate the signature, creating a RRSIG RDATA. */
5136 isc_buffer_clear(&buffer);
5137 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
5138 &expire, mctx, &buffer, &rdata));
5139 /* Update the database and journal with the RRSIG. */
5140 /* XXX inefficient - will cause dataset merging */
5141 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
5142 name, rdataset.ttl, &rdata));
5143 dns_rdata_reset(&rdata);
5144 (*signatures)--;
5145 next_rdataset:
5146 dns_rdataset_disassociate(&rdataset);
5147 result = dns_rdatasetiter_next(iterator);
5149 if (result == ISC_R_NOMORE)
5150 result = ISC_R_SUCCESS;
5151 if (seen_dname)
5152 *delegation = ISC_TRUE;
5153 failure:
5154 if (dns_rdataset_isassociated(&rdataset))
5155 dns_rdataset_disassociate(&rdataset);
5156 if (iterator != NULL)
5157 dns_rdatasetiter_destroy(&iterator);
5158 return (result);
5162 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
5164 static isc_result_t
5165 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
5166 dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
5168 isc_result_t result;
5169 dns_rdataset_t rdataset;
5170 dns_dbnode_t *node = NULL;
5172 CHECK(dns_db_getoriginnode(db, &node));
5173 if (update_only) {
5174 dns_rdataset_init(&rdataset);
5175 result = dns_db_findrdataset(db, node, version,
5176 dns_rdatatype_nsec,
5177 dns_rdatatype_none,
5178 0, &rdataset, NULL);
5179 if (dns_rdataset_isassociated(&rdataset))
5180 dns_rdataset_disassociate(&rdataset);
5181 if (result == ISC_R_NOTFOUND)
5182 goto success;
5183 if (result != ISC_R_SUCCESS)
5184 goto failure;
5186 CHECK(delete_nsec(db, version, node, name, diff));
5187 CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
5188 success:
5189 result = ISC_R_SUCCESS;
5190 failure:
5191 if (node != NULL)
5192 dns_db_detachnode(db, &node);
5193 return (result);
5196 static isc_result_t
5197 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
5198 dns_dbversion_t *version, isc_boolean_t build_nsec3,
5199 dns_ttl_t minimum, dns_diff_t *diff)
5201 isc_result_t result;
5202 dns_dbnode_t *node = NULL;
5203 dns_rdataset_t rdataset;
5204 dns_rdata_t rdata = DNS_RDATA_INIT;
5205 unsigned char data[5];
5206 isc_boolean_t seen_done = ISC_FALSE;
5207 isc_boolean_t have_rr = ISC_FALSE;
5209 dns_rdataset_init(&rdataset);
5210 result = dns_db_getoriginnode(signing->db, &node);
5211 if (result != ISC_R_SUCCESS)
5212 goto failure;
5214 result = dns_db_findrdataset(signing->db, node, version,
5215 zone->privatetype, dns_rdatatype_none,
5216 0, &rdataset, NULL);
5217 if (result == ISC_R_NOTFOUND) {
5218 INSIST(!dns_rdataset_isassociated(&rdataset));
5219 result = ISC_R_SUCCESS;
5220 goto failure;
5222 if (result != ISC_R_SUCCESS) {
5223 INSIST(!dns_rdataset_isassociated(&rdataset));
5224 goto failure;
5226 for (result = dns_rdataset_first(&rdataset);
5227 result == ISC_R_SUCCESS;
5228 result = dns_rdataset_next(&rdataset)) {
5229 dns_rdataset_current(&rdataset, &rdata);
5231 * If we don't match the algorithm or keyid skip the record.
5233 if (rdata.length != 5 ||
5234 rdata.data[0] != signing->algorithm ||
5235 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
5236 rdata.data[2] != (signing->keyid & 0xff)) {
5237 have_rr = ISC_TRUE;
5238 dns_rdata_reset(&rdata);
5239 continue;
5242 * We have a match. If we were signing (!signing->delete)
5243 * and we already have a record indicating that we have
5244 * finished signing (rdata.data[4] != 0) then keep it.
5245 * Otherwise it needs to be deleted as we have removed all
5246 * the signatures (signing->delete), so any record indicating
5247 * completion is now out of date, or we have finished signing
5248 * with the new record so we no longer need to remember that
5249 * we need to sign the zone with the matching key across a
5250 * nameserver re-start.
5252 if (!signing->delete && rdata.data[4] != 0) {
5253 seen_done = ISC_TRUE;
5254 have_rr = ISC_TRUE;
5255 } else
5256 CHECK(update_one_rr(signing->db, version, diff,
5257 DNS_DIFFOP_DEL, &zone->origin,
5258 rdataset.ttl, &rdata));
5259 dns_rdata_reset(&rdata);
5261 if (result == ISC_R_NOMORE)
5262 result = ISC_R_SUCCESS;
5263 if (!signing->delete && !seen_done) {
5265 * If we were signing then we need to indicate that we have
5266 * finished signing the zone with this key. If it is already
5267 * there we don't need to add it a second time.
5269 data[0] = signing->algorithm;
5270 data[1] = (signing->keyid >> 8) & 0xff;
5271 data[2] = signing->keyid & 0xff;
5272 data[3] = 0;
5273 data[4] = 1;
5274 rdata.length = sizeof(data);
5275 rdata.data = data;
5276 rdata.type = zone->privatetype;
5277 rdata.rdclass = dns_db_class(signing->db);
5278 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
5279 &zone->origin, rdataset.ttl, &rdata));
5280 } else if (!have_rr) {
5281 dns_name_t *origin = dns_db_origin(signing->db);
5283 * Rebuild the NSEC/NSEC3 record for the origin as we no
5284 * longer have any private records.
5286 if (build_nsec3)
5287 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
5288 minimum, ISC_FALSE, diff));
5289 CHECK(updatesecure(signing->db, version, origin, minimum,
5290 ISC_TRUE, diff));
5293 failure:
5294 if (dns_rdataset_isassociated(&rdataset))
5295 dns_rdataset_disassociate(&rdataset);
5296 if (node != NULL)
5297 dns_db_detachnode(signing->db, &node);
5298 return (result);
5302 * If 'active' is set then we are not done with the chain yet so only
5303 * delete the nsec3param record which indicates a full chain exists
5304 * (flags == 0).
5306 static isc_result_t
5307 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
5308 isc_boolean_t active, dns_rdatatype_t privatetype,
5309 dns_diff_t *diff)
5311 dns_dbnode_t *node = NULL;
5312 dns_name_t *name = dns_db_origin(db);
5313 dns_rdata_t rdata = DNS_RDATA_INIT;
5314 dns_rdataset_t rdataset;
5315 dns_rdata_nsec3param_t nsec3param;
5316 isc_result_t result;
5317 isc_buffer_t buffer;
5318 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
5319 dns_ttl_t ttl = 0;
5321 dns_rdataset_init(&rdataset);
5323 result = dns_db_getoriginnode(db, &node);
5324 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5325 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5326 0, 0, &rdataset, NULL);
5327 if (result == ISC_R_NOTFOUND)
5328 goto try_private;
5329 if (result != ISC_R_SUCCESS)
5330 goto failure;
5333 * Preserve the existing ttl.
5335 ttl = rdataset.ttl;
5338 * Delete all NSEC3PARAM records which match that in nsec3chain.
5340 for (result = dns_rdataset_first(&rdataset);
5341 result == ISC_R_SUCCESS;
5342 result = dns_rdataset_next(&rdataset)) {
5344 dns_rdataset_current(&rdataset, &rdata);
5345 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5347 if (nsec3param.hash != chain->nsec3param.hash ||
5348 (active && nsec3param.flags != 0) ||
5349 nsec3param.iterations != chain->nsec3param.iterations ||
5350 nsec3param.salt_length != chain->nsec3param.salt_length ||
5351 memcmp(nsec3param.salt, chain->nsec3param.salt,
5352 nsec3param.salt_length)) {
5353 dns_rdata_reset(&rdata);
5354 continue;
5357 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5358 name, rdataset.ttl, &rdata));
5359 dns_rdata_reset(&rdata);
5361 if (result != ISC_R_NOMORE)
5362 goto failure;
5364 dns_rdataset_disassociate(&rdataset);
5366 try_private:
5368 if (active)
5369 goto add;
5371 * Delete all private records which match that in nsec3chain.
5373 result = dns_db_findrdataset(db, node, ver, privatetype,
5374 0, 0, &rdataset, NULL);
5375 if (result == ISC_R_NOTFOUND)
5376 goto add;
5377 if (result != ISC_R_SUCCESS)
5378 goto failure;
5380 for (result = dns_rdataset_first(&rdataset);
5381 result == ISC_R_SUCCESS;
5382 result = dns_rdataset_next(&rdataset)) {
5383 dns_rdata_t private = DNS_RDATA_INIT;
5384 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
5386 dns_rdataset_current(&rdataset, &private);
5387 if (!dns_nsec3param_fromprivate(&private, &rdata,
5388 buf, sizeof(buf)))
5389 continue;
5390 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
5392 if (nsec3param.hash != chain->nsec3param.hash ||
5393 nsec3param.iterations != chain->nsec3param.iterations ||
5394 nsec3param.salt_length != chain->nsec3param.salt_length ||
5395 memcmp(nsec3param.salt, chain->nsec3param.salt,
5396 nsec3param.salt_length)) {
5397 dns_rdata_reset(&rdata);
5398 continue;
5401 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
5402 name, rdataset.ttl, &private));
5403 dns_rdata_reset(&rdata);
5405 if (result != ISC_R_NOMORE)
5406 goto failure;
5408 add:
5409 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
5410 result = ISC_R_SUCCESS;
5411 goto failure;
5415 * Add a NSEC3PARAM record which matches that in nsec3chain but
5416 * with all flags bits cleared.
5418 * Note: we do not clear chain->nsec3param.flags as this change
5419 * may be reversed.
5421 isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
5422 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
5423 dns_rdatatype_nsec3param,
5424 &chain->nsec3param, &buffer));
5425 rdata.data[1] = 0; /* Clear flag bits. */
5426 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
5428 failure:
5429 dns_db_detachnode(db, &node);
5430 if (dns_rdataset_isassociated(&rdataset))
5431 dns_rdataset_disassociate(&rdataset);
5432 return (result);
5435 static isc_result_t
5436 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5437 dns_name_t *name, dns_diff_t *diff)
5439 dns_rdataset_t rdataset;
5440 isc_result_t result;
5442 dns_rdataset_init(&rdataset);
5444 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5445 0, 0, &rdataset, NULL);
5446 if (result == ISC_R_NOTFOUND)
5447 return (ISC_R_SUCCESS);
5448 if (result != ISC_R_SUCCESS)
5449 return (result);
5450 for (result = dns_rdataset_first(&rdataset);
5451 result == ISC_R_SUCCESS;
5452 result = dns_rdataset_next(&rdataset)) {
5453 dns_rdata_t rdata = DNS_RDATA_INIT;
5455 dns_rdataset_current(&rdataset, &rdata);
5456 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5457 rdataset.ttl, &rdata));
5459 if (result == ISC_R_NOMORE)
5460 result = ISC_R_SUCCESS;
5461 failure:
5462 dns_rdataset_disassociate(&rdataset);
5463 return (result);
5466 static isc_result_t
5467 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
5468 dns_name_t *name, const dns_rdata_nsec3param_t *param,
5469 dns_diff_t *diff)
5471 dns_rdataset_t rdataset;
5472 dns_rdata_nsec3_t nsec3;
5473 isc_result_t result;
5475 dns_rdataset_init(&rdataset);
5476 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
5477 0, 0, &rdataset, NULL);
5478 if (result == ISC_R_NOTFOUND)
5479 return (ISC_R_SUCCESS);
5480 if (result != ISC_R_SUCCESS)
5481 return (result);
5483 for (result = dns_rdataset_first(&rdataset);
5484 result == ISC_R_SUCCESS;
5485 result = dns_rdataset_next(&rdataset)) {
5486 dns_rdata_t rdata = DNS_RDATA_INIT;
5488 dns_rdataset_current(&rdataset, &rdata);
5489 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
5490 if (nsec3.hash != param->hash ||
5491 nsec3.iterations != param->iterations ||
5492 nsec3.salt_length != param->salt_length ||
5493 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
5494 continue;
5495 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
5496 rdataset.ttl, &rdata));
5498 if (result == ISC_R_NOMORE)
5499 result = ISC_R_SUCCESS;
5500 failure:
5501 dns_rdataset_disassociate(&rdataset);
5502 return (result);
5505 static isc_result_t
5506 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
5507 const dns_rdata_nsec3param_t *param,
5508 isc_boolean_t *answer)
5510 dns_dbnode_t *node = NULL;
5511 dns_rdata_t rdata = DNS_RDATA_INIT;
5512 dns_rdata_nsec3param_t myparam;
5513 dns_rdataset_t rdataset;
5514 isc_result_t result;
5516 *answer = ISC_FALSE;
5518 result = dns_db_getoriginnode(db, &node);
5519 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5521 dns_rdataset_init(&rdataset);
5523 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
5524 0, 0, &rdataset, NULL);
5525 if (result == ISC_R_SUCCESS) {
5526 dns_rdataset_disassociate(&rdataset);
5527 dns_db_detachnode(db, &node);
5528 return (result);
5530 if (result != ISC_R_NOTFOUND) {
5531 dns_db_detachnode(db, &node);
5532 return (result);
5535 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
5536 0, 0, &rdataset, NULL);
5537 if (result == ISC_R_NOTFOUND) {
5538 *answer = ISC_TRUE;
5539 dns_db_detachnode(db, &node);
5540 return (ISC_R_SUCCESS);
5542 if (result != ISC_R_SUCCESS) {
5543 dns_db_detachnode(db, &node);
5544 return (result);
5547 for (result = dns_rdataset_first(&rdataset);
5548 result == ISC_R_SUCCESS;
5549 result = dns_rdataset_next(&rdataset)) {
5550 dns_rdataset_current(&rdataset, &rdata);
5551 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
5552 dns_rdata_reset(&rdata);
5554 * Ignore any NSEC3PARAM removals.
5556 if (NSEC3REMOVE(myparam.flags))
5557 continue;
5559 * Ignore the chain that we are in the process of deleting.
5561 if (myparam.hash == param->hash &&
5562 myparam.iterations == param->iterations &&
5563 myparam.salt_length == param->salt_length &&
5564 !memcmp(myparam.salt, param->salt, myparam.salt_length))
5565 continue;
5567 * Found an active NSEC3 chain.
5569 break;
5571 if (result == ISC_R_NOMORE) {
5572 *answer = ISC_TRUE;
5573 result = ISC_R_SUCCESS;
5576 failure:
5577 if (dns_rdataset_isassociated(&rdataset))
5578 dns_rdataset_disassociate(&rdataset);
5579 dns_db_detachnode(db, &node);
5580 return (result);
5583 static isc_result_t
5584 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
5585 dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
5586 isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
5587 isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
5588 dns_diff_t *sig_diff)
5590 dns_difftuple_t *tuple;
5591 isc_result_t result;
5593 for (tuple = ISC_LIST_HEAD(diff->tuples);
5594 tuple != NULL;
5595 tuple = ISC_LIST_HEAD(diff->tuples)) {
5596 result = del_sigs(zone, db, version, &tuple->name,
5597 tuple->rdata.type, sig_diff,
5598 zone_keys, nkeys, now);
5599 if (result != ISC_R_SUCCESS) {
5600 dns_zone_log(zone, ISC_LOG_ERROR,
5601 "update_sigs:del_sigs -> %s\n",
5602 dns_result_totext(result));
5603 return (result);
5605 result = add_sigs(db, version, &tuple->name,
5606 tuple->rdata.type, sig_diff,
5607 zone_keys, nkeys, zone->mctx, inception,
5608 expire, check_ksk, keyset_kskonly);
5609 if (result != ISC_R_SUCCESS) {
5610 dns_zone_log(zone, ISC_LOG_ERROR,
5611 "update_sigs:add_sigs -> %s\n",
5612 dns_result_totext(result));
5613 return (result);
5616 do {
5617 dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
5618 while (next != NULL &&
5619 (tuple->rdata.type != next->rdata.type ||
5620 !dns_name_equal(&tuple->name, &next->name)))
5621 next = ISC_LIST_NEXT(next, link);
5622 ISC_LIST_UNLINK(diff->tuples, tuple, link);
5623 dns_diff_appendminimal(sig_diff, &tuple);
5624 INSIST(tuple == NULL);
5625 tuple = next;
5626 } while (tuple != NULL);
5628 return (ISC_R_SUCCESS);
5632 * Incrementally build and sign a new NSEC3 chain using the parameters
5633 * requested.
5635 static void
5636 zone_nsec3chain(dns_zone_t *zone) {
5637 dns_db_t *db = NULL;
5638 dns_dbnode_t *node = NULL;
5639 dns_dbversion_t *version = NULL;
5640 dns_diff_t sig_diff;
5641 dns_diff_t nsec_diff;
5642 dns_diff_t nsec3_diff;
5643 dns_diff_t param_diff;
5644 dns_fixedname_t fixed;
5645 dns_fixedname_t nextfixed;
5646 dns_name_t *name, *nextname;
5647 dns_rdataset_t rdataset;
5648 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
5649 dns_nsec3chainlist_t cleanup;
5650 dst_key_t *zone_keys[MAXZONEKEYS];
5651 isc_int32_t signatures;
5652 isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
5653 isc_boolean_t delegation;
5654 isc_boolean_t first;
5655 isc_result_t result;
5656 isc_stdtime_t now, inception, soaexpire, expire, stop;
5657 isc_uint32_t jitter;
5658 unsigned int i;
5659 unsigned int nkeys = 0;
5660 isc_uint32_t nodes;
5661 isc_boolean_t unsecure = ISC_FALSE;
5662 isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
5663 isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
5664 dns_rdatasetiter_t *iterator = NULL;
5665 isc_boolean_t buildnsecchain;
5666 isc_boolean_t updatensec = ISC_FALSE;
5667 dns_rdatatype_t privatetype = zone->privatetype;
5669 dns_rdataset_init(&rdataset);
5670 dns_fixedname_init(&fixed);
5671 name = dns_fixedname_name(&fixed);
5672 dns_fixedname_init(&nextfixed);
5673 nextname = dns_fixedname_name(&nextfixed);
5674 dns_diff_init(zone->mctx, &param_diff);
5675 dns_diff_init(zone->mctx, &nsec3_diff);
5676 dns_diff_init(zone->mctx, &nsec_diff);
5677 dns_diff_init(zone->mctx, &sig_diff);
5678 sig_diff.resign = zone->sigresigninginterval;
5679 ISC_LIST_INIT(cleanup);
5682 * Updates are disabled. Pause for 5 minutes.
5684 if (zone->update_disabled) {
5685 result = ISC_R_FAILURE;
5686 goto failure;
5689 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5690 dns_db_attach(zone->db, &db);
5691 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5693 result = dns_db_newversion(db, &version);
5694 if (result != ISC_R_SUCCESS) {
5695 dns_zone_log(zone, ISC_LOG_ERROR,
5696 "zone_nsec3chain:dns_db_newversion -> %s\n",
5697 dns_result_totext(result));
5698 goto failure;
5701 result = find_zone_keys(zone, db, version, zone->mctx,
5702 MAXZONEKEYS, zone_keys, &nkeys);
5703 if (result != ISC_R_SUCCESS) {
5704 dns_zone_log(zone, ISC_LOG_ERROR,
5705 "zone_nsec3chain:find_zone_keys -> %s\n",
5706 dns_result_totext(result));
5707 goto failure;
5710 isc_stdtime_get(&now);
5711 inception = now - 3600; /* Allow for clock skew. */
5712 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
5715 * Spread out signatures over time if they happen to be
5716 * clumped. We don't do this for each add_sigs() call as
5717 * we still want some clustering to occur.
5719 isc_random_get(&jitter);
5720 expire = soaexpire - jitter % 3600;
5721 stop = now + 5;
5723 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
5724 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
5727 * We keep pulling nodes off each iterator in turn until
5728 * we have no more nodes to pull off or we reach the limits
5729 * for this quantum.
5731 nodes = zone->nodes;
5732 signatures = zone->signatures;
5733 LOCK_ZONE(zone);
5734 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5735 UNLOCK_ZONE(zone);
5736 first = ISC_TRUE;
5738 if (nsec3chain != NULL)
5739 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
5741 * Generate new NSEC3 chains first.
5743 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
5744 LOCK_ZONE(zone);
5745 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
5747 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5748 if (nsec3chain->done || nsec3chain->db != zone->db) {
5749 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
5750 ISC_LIST_APPEND(cleanup, nsec3chain, link);
5752 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5753 UNLOCK_ZONE(zone);
5754 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
5755 goto next_addchain;
5758 * Possible future db.
5760 if (nsec3chain->db != db) {
5761 goto next_addchain;
5764 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
5765 goto next_addchain;
5767 is_ksk = ISC_FALSE;
5768 delegation = ISC_FALSE;
5769 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
5771 if (nsec3chain->delete_nsec) {
5772 delegation = ISC_FALSE;
5773 dns_dbiterator_pause(nsec3chain->dbiterator);
5774 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
5775 goto next_addnode;
5778 * On the first pass we need to check if the current node
5779 * has not been obscured.
5781 delegation = ISC_FALSE;
5782 unsecure = ISC_FALSE;
5783 if (first) {
5784 dns_fixedname_t ffound;
5785 dns_name_t *found;
5786 dns_fixedname_init(&ffound);
5787 found = dns_fixedname_name(&ffound);
5788 result = dns_db_find(db, name, version,
5789 dns_rdatatype_soa,
5790 DNS_DBFIND_NOWILD, 0, NULL, found,
5791 NULL, NULL);
5792 if ((result == DNS_R_DELEGATION ||
5793 result == DNS_R_DNAME) &&
5794 !dns_name_equal(name, found)) {
5796 * Remember the obscuring name so that
5797 * we skip all obscured names.
5799 dns_name_copy(found, name, NULL);
5800 delegation = ISC_TRUE;
5801 goto next_addnode;
5806 * Check to see if this is a bottom of zone node.
5808 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
5809 if (result == ISC_R_NOTFOUND) /* Empty node? */
5810 goto next_addnode;
5811 if (result != ISC_R_SUCCESS)
5812 goto failure;
5814 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
5815 ISC_FALSE;
5816 for (result = dns_rdatasetiter_first(iterator);
5817 result == ISC_R_SUCCESS;
5818 result = dns_rdatasetiter_next(iterator)) {
5819 dns_rdatasetiter_current(iterator, &rdataset);
5820 INSIST(rdataset.type != dns_rdatatype_nsec3);
5821 if (rdataset.type == dns_rdatatype_soa)
5822 seen_soa = ISC_TRUE;
5823 else if (rdataset.type == dns_rdatatype_ns)
5824 seen_ns = ISC_TRUE;
5825 else if (rdataset.type == dns_rdatatype_dname)
5826 seen_dname = ISC_TRUE;
5827 else if (rdataset.type == dns_rdatatype_ds)
5828 seen_ds = ISC_TRUE;
5829 else if (rdataset.type == dns_rdatatype_nsec)
5830 seen_nsec = ISC_TRUE;
5831 dns_rdataset_disassociate(&rdataset);
5833 dns_rdatasetiter_destroy(&iterator);
5835 * Is there a NSEC chain than needs to be cleaned up?
5837 if (seen_nsec)
5838 nsec3chain->seen_nsec = ISC_TRUE;
5839 if (seen_ns && !seen_soa && !seen_ds)
5840 unsecure = ISC_TRUE;
5841 if ((seen_ns && !seen_soa) || seen_dname)
5842 delegation = ISC_TRUE;
5845 * Process one node.
5847 dns_dbiterator_pause(nsec3chain->dbiterator);
5848 result = dns_nsec3_addnsec3(db, version, name,
5849 &nsec3chain->nsec3param,
5850 zone->minimum, unsecure,
5851 &nsec3_diff);
5852 if (result != ISC_R_SUCCESS) {
5853 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
5854 "dns_nsec3_addnsec3 -> %s\n",
5855 dns_result_totext(result));
5856 goto failure;
5860 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
5861 * two signatures. Additionally there will, in general, be
5862 * two signature generated below.
5864 * If we are only changing the optout flag the cost is half
5865 * that of the cost of generating a completely new chain.
5867 signatures -= 4;
5870 * Go onto next node.
5872 next_addnode:
5873 first = ISC_FALSE;
5874 dns_db_detachnode(db, &node);
5875 do {
5876 result = dns_dbiterator_next(nsec3chain->dbiterator);
5878 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
5879 CHECK(fixup_nsec3param(db, version, nsec3chain,
5880 ISC_FALSE, privatetype,
5881 &param_diff));
5882 LOCK_ZONE(zone);
5883 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
5884 link);
5885 UNLOCK_ZONE(zone);
5886 ISC_LIST_APPEND(cleanup, nsec3chain, link);
5887 goto next_addchain;
5889 if (result == ISC_R_NOMORE) {
5890 dns_dbiterator_pause(nsec3chain->dbiterator);
5891 if (nsec3chain->seen_nsec) {
5892 CHECK(fixup_nsec3param(db, version,
5893 nsec3chain,
5894 ISC_TRUE,
5895 privatetype,
5896 &param_diff));
5897 nsec3chain->delete_nsec = ISC_TRUE;
5898 goto same_addchain;
5900 CHECK(fixup_nsec3param(db, version, nsec3chain,
5901 ISC_FALSE, privatetype,
5902 &param_diff));
5903 LOCK_ZONE(zone);
5904 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
5905 link);
5906 UNLOCK_ZONE(zone);
5907 ISC_LIST_APPEND(cleanup, nsec3chain, link);
5908 goto next_addchain;
5909 } else if (result != ISC_R_SUCCESS) {
5910 dns_zone_log(zone, ISC_LOG_ERROR,
5911 "zone_nsec3chain:"
5912 "dns_dbiterator_next -> %s\n",
5913 dns_result_totext(result));
5914 goto failure;
5915 } else if (delegation) {
5916 dns_dbiterator_current(nsec3chain->dbiterator,
5917 &node, nextname);
5918 dns_db_detachnode(db, &node);
5919 if (!dns_name_issubdomain(nextname, name))
5920 break;
5921 } else
5922 break;
5923 } while (1);
5924 continue;
5926 same_addchain:
5927 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
5928 first = ISC_TRUE;
5929 continue;
5931 next_addchain:
5932 dns_dbiterator_pause(nsec3chain->dbiterator);
5933 nsec3chain = nextnsec3chain;
5934 first = ISC_TRUE;
5935 if (nsec3chain != NULL)
5936 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
5940 * Process removals.
5942 LOCK_ZONE(zone);
5943 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
5944 UNLOCK_ZONE(zone);
5945 first = ISC_TRUE;
5946 buildnsecchain = ISC_FALSE;
5947 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
5948 LOCK_ZONE(zone);
5949 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
5950 UNLOCK_ZONE(zone);
5952 if (nsec3chain->db != db)
5953 goto next_removechain;
5955 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
5956 goto next_removechain;
5959 * Work out if we need to build a NSEC chain as a consequence
5960 * of removing this NSEC3 chain.
5962 if (first && !updatensec &&
5963 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0) {
5964 result = need_nsec_chain(db, version,
5965 &nsec3chain->nsec3param,
5966 &buildnsecchain);
5967 if (result != ISC_R_SUCCESS) {
5968 dns_zone_log(zone, ISC_LOG_ERROR,
5969 "zone_nsec3chain:"
5970 "need_nsec_chain -> %s\n",
5971 dns_result_totext(result));
5972 goto failure;
5976 if (first)
5977 dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
5978 "buildnsecchain = %u\n", buildnsecchain);
5980 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
5981 delegation = ISC_FALSE;
5983 if (!buildnsecchain) {
5985 * Delete the NSECPARAM record that matches this chain.
5987 if (first) {
5988 result = fixup_nsec3param(db, version,
5989 nsec3chain,
5990 ISC_TRUE, privatetype,
5991 &param_diff);
5992 if (result != ISC_R_SUCCESS) {
5993 dns_zone_log(zone, ISC_LOG_ERROR,
5994 "zone_nsec3chain:"
5995 "fixup_nsec3param -> %s\n",
5996 dns_result_totext(result));
5997 goto failure;
6002 * Delete the NSEC3 records.
6004 result = deletematchingnsec3(db, version, node, name,
6005 &nsec3chain->nsec3param,
6006 &nsec3_diff);
6007 if (result != ISC_R_SUCCESS) {
6008 dns_zone_log(zone, ISC_LOG_ERROR,
6009 "zone_nsec3chain:"
6010 "deletematchingnsec3 -> %s\n",
6011 dns_result_totext(result));
6012 goto failure;
6014 goto next_removenode;
6017 if (first) {
6018 dns_fixedname_t ffound;
6019 dns_name_t *found;
6020 dns_fixedname_init(&ffound);
6021 found = dns_fixedname_name(&ffound);
6022 result = dns_db_find(db, name, version,
6023 dns_rdatatype_soa,
6024 DNS_DBFIND_NOWILD, 0, NULL, found,
6025 NULL, NULL);
6026 if ((result == DNS_R_DELEGATION ||
6027 result == DNS_R_DNAME) &&
6028 !dns_name_equal(name, found)) {
6030 * Remember the obscuring name so that
6031 * we skip all obscured names.
6033 dns_name_copy(found, name, NULL);
6034 delegation = ISC_TRUE;
6035 goto next_removenode;
6040 * Check to see if this is a bottom of zone node.
6042 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6043 if (result == ISC_R_NOTFOUND) /* Empty node? */
6044 goto next_removenode;
6045 if (result != ISC_R_SUCCESS)
6046 goto failure;
6048 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
6049 seen_rr = ISC_FALSE;
6050 for (result = dns_rdatasetiter_first(iterator);
6051 result == ISC_R_SUCCESS;
6052 result = dns_rdatasetiter_next(iterator)) {
6053 dns_rdatasetiter_current(iterator, &rdataset);
6054 if (rdataset.type == dns_rdatatype_soa)
6055 seen_soa = ISC_TRUE;
6056 else if (rdataset.type == dns_rdatatype_ns)
6057 seen_ns = ISC_TRUE;
6058 else if (rdataset.type == dns_rdatatype_dname)
6059 seen_dname = ISC_TRUE;
6060 else if (rdataset.type == dns_rdatatype_nsec)
6061 seen_nsec = ISC_TRUE;
6062 else if (rdataset.type == dns_rdatatype_nsec3)
6063 seen_nsec3 = ISC_TRUE;
6064 if (rdataset.type != dns_rdatatype_rrsig)
6065 seen_rr = ISC_TRUE;
6066 dns_rdataset_disassociate(&rdataset);
6068 dns_rdatasetiter_destroy(&iterator);
6070 if (!seen_rr || seen_nsec3 || seen_nsec)
6071 goto next_removenode;
6072 if ((seen_ns && !seen_soa) || seen_dname)
6073 delegation = ISC_TRUE;
6076 * Add a NSEC record except at the origin.
6078 if (!dns_name_equal(name, dns_db_origin(db))) {
6079 dns_dbiterator_pause(nsec3chain->dbiterator);
6080 CHECK(add_nsec(db, version, name, node, zone->minimum,
6081 delegation, &nsec_diff));
6084 next_removenode:
6085 first = ISC_FALSE;
6086 dns_db_detachnode(db, &node);
6087 do {
6088 result = dns_dbiterator_next(nsec3chain->dbiterator);
6089 if (result == ISC_R_NOMORE && buildnsecchain) {
6091 * The NSEC chain should now be built.
6092 * We can now remove the NSEC3 chain.
6094 updatensec = ISC_TRUE;
6095 goto same_removechain;
6097 if (result == ISC_R_NOMORE) {
6098 LOCK_ZONE(zone);
6099 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
6100 link);
6101 UNLOCK_ZONE(zone);
6102 ISC_LIST_APPEND(cleanup, nsec3chain, link);
6103 dns_dbiterator_pause(nsec3chain->dbiterator);
6104 result = fixup_nsec3param(db, version,
6105 nsec3chain, ISC_FALSE,
6106 privatetype,
6107 &param_diff);
6108 if (result != ISC_R_SUCCESS) {
6109 dns_zone_log(zone, ISC_LOG_ERROR,
6110 "zone_nsec3chain:"
6111 "fixup_nsec3param -> %s\n",
6112 dns_result_totext(result));
6113 goto failure;
6115 goto next_removechain;
6116 } else if (result != ISC_R_SUCCESS) {
6117 dns_zone_log(zone, ISC_LOG_ERROR,
6118 "zone_nsec3chain:"
6119 "dns_dbiterator_next -> %s\n",
6120 dns_result_totext(result));
6121 goto failure;
6122 } else if (delegation) {
6123 dns_dbiterator_current(nsec3chain->dbiterator,
6124 &node, nextname);
6125 dns_db_detachnode(db, &node);
6126 if (!dns_name_issubdomain(nextname, name))
6127 break;
6128 } else
6129 break;
6130 } while (1);
6131 continue;
6133 same_removechain:
6134 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
6135 buildnsecchain = ISC_FALSE;
6136 first = ISC_TRUE;
6137 continue;
6139 next_removechain:
6140 dns_dbiterator_pause(nsec3chain->dbiterator);
6141 nsec3chain = nextnsec3chain;
6142 first = ISC_TRUE;
6146 * We may need to update the NSEC/NSEC3 records for the zone apex.
6148 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
6149 isc_boolean_t rebuild_nsec = ISC_FALSE,
6150 rebuild_nsec3 = ISC_FALSE;
6151 result = dns_db_getoriginnode(db, &node);
6152 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6153 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6154 for (result = dns_rdatasetiter_first(iterator);
6155 result == ISC_R_SUCCESS;
6156 result = dns_rdatasetiter_next(iterator)) {
6157 dns_rdatasetiter_current(iterator, &rdataset);
6158 if (rdataset.type == dns_rdatatype_nsec)
6159 rebuild_nsec = ISC_TRUE;
6160 if (rdataset.type == dns_rdatatype_nsec3param)
6161 rebuild_nsec3 = ISC_TRUE;
6162 dns_rdataset_disassociate(&rdataset);
6164 dns_rdatasetiter_destroy(&iterator);
6165 dns_db_detachnode(db, &node);
6167 if (rebuild_nsec) {
6168 result = updatesecure(db, version, &zone->origin,
6169 zone->minimum, ISC_TRUE,
6170 &nsec_diff);
6171 if (result != ISC_R_SUCCESS) {
6172 dns_zone_log(zone, ISC_LOG_ERROR,
6173 "zone_nsec3chain:"
6174 "updatesecure -> %s\n",
6175 dns_result_totext(result));
6176 goto failure;
6179 if (rebuild_nsec3) {
6180 result = dns_nsec3_addnsec3s(db, version,
6181 dns_db_origin(db),
6182 zone->minimum, ISC_FALSE,
6183 &nsec3_diff);
6184 if (result != ISC_R_SUCCESS) {
6185 dns_zone_log(zone, ISC_LOG_ERROR,
6186 "zone_nsec3chain:"
6187 "dns_nsec3_addnsec3s -> %s\n",
6188 dns_result_totext(result));
6189 goto failure;
6195 * Add / update signatures for the NSEC3 records.
6197 result = update_sigs(&nsec3_diff, db, version, zone_keys,
6198 nkeys, zone, inception, expire, now,
6199 check_ksk, keyset_kskonly, &sig_diff);
6200 if (result != ISC_R_SUCCESS) {
6201 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6202 "update_sigs -> %s\n", dns_result_totext(result));
6203 goto failure;
6207 * We have changed the NSEC3PARAM or private RRsets
6208 * above so we need to update the signatures.
6210 result = update_sigs(&param_diff, db, version, zone_keys,
6211 nkeys, zone, inception, expire, now,
6212 check_ksk, keyset_kskonly, &sig_diff);
6213 if (result != ISC_R_SUCCESS) {
6214 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6215 "update_sigs -> %s\n", dns_result_totext(result));
6216 goto failure;
6219 if (updatensec) {
6220 result = updatesecure(db, version, &zone->origin,
6221 zone->minimum, ISC_FALSE, &nsec_diff);
6222 if (result != ISC_R_SUCCESS) {
6223 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6224 "updatesecure -> %s\n",
6225 dns_result_totext(result));
6226 goto failure;
6230 result = update_sigs(&nsec_diff, db, version, zone_keys,
6231 nkeys, zone, inception, expire, now,
6232 check_ksk, keyset_kskonly, &sig_diff);
6233 if (result != ISC_R_SUCCESS) {
6234 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6235 "update_sigs -> %s\n", dns_result_totext(result));
6236 goto failure;
6240 * If we made no effective changes to the zone then we can just
6241 * cleanup otherwise we need to increment the serial.
6243 if (ISC_LIST_HEAD(sig_diff.tuples) == NULL)
6244 goto done;
6246 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6247 &sig_diff, zone_keys, nkeys, now);
6248 if (result != ISC_R_SUCCESS) {
6249 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6250 "del_sigs -> %s\n", dns_result_totext(result));
6251 goto failure;
6254 result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6255 if (result != ISC_R_SUCCESS) {
6256 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6257 "increment_soa_serial -> %s\n",
6258 dns_result_totext(result));
6259 goto failure;
6262 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6263 &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6264 soaexpire, check_ksk, keyset_kskonly);
6265 if (result != ISC_R_SUCCESS) {
6266 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
6267 "add_sigs -> %s\n", dns_result_totext(result));
6268 goto failure;
6271 /* Write changes to journal file. */
6272 zone_journal(zone, &sig_diff, "zone_nsec3chain");
6274 LOCK_ZONE(zone);
6275 zone_needdump(zone, DNS_DUMP_DELAY);
6276 UNLOCK_ZONE(zone);
6278 done:
6280 * Pause all iterators so that dns_db_closeversion() can succeed.
6282 LOCK_ZONE(zone);
6283 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6284 nsec3chain != NULL;
6285 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6286 dns_dbiterator_pause(nsec3chain->dbiterator);
6287 UNLOCK_ZONE(zone);
6290 * Everything has succeeded. Commit the changes.
6292 dns_db_closeversion(db, &version, ISC_TRUE);
6295 * Everything succeeded so we can clean these up now.
6297 nsec3chain = ISC_LIST_HEAD(cleanup);
6298 while (nsec3chain != NULL) {
6299 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6300 dns_db_detach(&nsec3chain->db);
6301 dns_dbiterator_destroy(&nsec3chain->dbiterator);
6302 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6303 nsec3chain = ISC_LIST_HEAD(cleanup);
6306 set_resigntime(zone);
6308 failure:
6309 if (result != ISC_R_SUCCESS)
6310 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s\n",
6311 dns_result_totext(result));
6313 * On error roll back the current nsec3chain.
6315 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
6316 if (nsec3chain->done) {
6317 dns_db_detach(&nsec3chain->db);
6318 dns_dbiterator_destroy(&nsec3chain->dbiterator);
6319 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6320 } else {
6321 result = dns_dbiterator_first(nsec3chain->dbiterator);
6322 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6323 dns_dbiterator_pause(nsec3chain->dbiterator);
6324 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6329 * Rollback the cleanup list.
6331 nsec3chain = ISC_LIST_TAIL(cleanup);
6332 while (nsec3chain != NULL) {
6333 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
6334 if (nsec3chain->done) {
6335 dns_db_detach(&nsec3chain->db);
6336 dns_dbiterator_destroy(&nsec3chain->dbiterator);
6337 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
6338 } else {
6339 LOCK_ZONE(zone);
6340 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
6341 UNLOCK_ZONE(zone);
6342 result = dns_dbiterator_first(nsec3chain->dbiterator);
6343 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6344 dns_dbiterator_pause(nsec3chain->dbiterator);
6345 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
6347 nsec3chain = ISC_LIST_TAIL(cleanup);
6350 LOCK_ZONE(zone);
6351 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
6352 nsec3chain != NULL;
6353 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
6354 dns_dbiterator_pause(nsec3chain->dbiterator);
6355 UNLOCK_ZONE(zone);
6357 dns_diff_clear(&param_diff);
6358 dns_diff_clear(&nsec3_diff);
6359 dns_diff_clear(&nsec_diff);
6360 dns_diff_clear(&sig_diff);
6362 if (iterator != NULL)
6363 dns_rdatasetiter_destroy(&iterator);
6365 for (i = 0; i < nkeys; i++)
6366 dst_key_free(&zone_keys[i]);
6368 if (node != NULL)
6369 dns_db_detachnode(db, &node);
6370 if (version != NULL) {
6371 dns_db_closeversion(db, &version, ISC_FALSE);
6372 dns_db_detach(&db);
6373 } else if (db != NULL)
6374 dns_db_detach(&db);
6376 LOCK_ZONE(zone);
6377 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
6378 isc_interval_t i;
6379 if (zone->update_disabled || result != ISC_R_SUCCESS)
6380 isc_interval_set(&i, 60, 0); /* 1 minute */
6381 else
6382 isc_interval_set(&i, 0, 10000000); /* 10 ms */
6383 isc_time_nowplusinterval(&zone->nsec3chaintime, &i);
6384 } else
6385 isc_time_settoepoch(&zone->nsec3chaintime);
6386 UNLOCK_ZONE(zone);
6389 static isc_result_t
6390 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6391 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
6392 isc_uint16_t keyid, dns_diff_t *diff)
6394 dns_rdata_rrsig_t rrsig;
6395 dns_rdataset_t rdataset;
6396 dns_rdatasetiter_t *iterator = NULL;
6397 isc_result_t result;
6399 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6400 if (result != ISC_R_SUCCESS) {
6401 if (result == ISC_R_NOTFOUND)
6402 result = ISC_R_SUCCESS;
6403 return (result);
6406 dns_rdataset_init(&rdataset);
6407 for (result = dns_rdatasetiter_first(iterator);
6408 result == ISC_R_SUCCESS;
6409 result = dns_rdatasetiter_next(iterator)) {
6410 dns_rdatasetiter_current(iterator, &rdataset);
6411 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
6412 for (result = dns_rdataset_first(&rdataset);
6413 result == ISC_R_SUCCESS;
6414 result = dns_rdataset_next(&rdataset)) {
6415 dns_rdata_t rdata = DNS_RDATA_INIT;
6416 dns_rdataset_current(&rdataset, &rdata);
6417 CHECK(update_one_rr(db, version, diff,
6418 DNS_DIFFOP_DEL, name,
6419 rdataset.ttl, &rdata));
6421 if (result != ISC_R_NOMORE)
6422 goto failure;
6423 dns_rdataset_disassociate(&rdataset);
6424 continue;
6426 if (rdataset.type != dns_rdatatype_rrsig) {
6427 dns_rdataset_disassociate(&rdataset);
6428 continue;
6430 for (result = dns_rdataset_first(&rdataset);
6431 result == ISC_R_SUCCESS;
6432 result = dns_rdataset_next(&rdataset)) {
6433 dns_rdata_t rdata = DNS_RDATA_INIT;
6434 dns_rdataset_current(&rdataset, &rdata);
6435 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
6436 if (rrsig.algorithm != algorithm ||
6437 rrsig.keyid != keyid)
6438 continue;
6439 CHECK(update_one_rr(db, version, diff,
6440 DNS_DIFFOP_DEL, name,
6441 rdataset.ttl, &rdata));
6443 dns_rdataset_disassociate(&rdataset);
6444 if (result != ISC_R_NOMORE)
6445 break;
6447 if (result == ISC_R_NOMORE)
6448 result = ISC_R_SUCCESS;
6449 failure:
6450 if (dns_rdataset_isassociated(&rdataset))
6451 dns_rdataset_disassociate(&rdataset);
6452 dns_rdatasetiter_destroy(&iterator);
6453 return (result);
6457 * Incrementally sign the zone using the keys requested.
6458 * Builds the NSEC chain if required.
6460 static void
6461 zone_sign(dns_zone_t *zone) {
6462 dns_db_t *db = NULL;
6463 dns_dbnode_t *node = NULL;
6464 dns_dbversion_t *version = NULL;
6465 dns_diff_t sig_diff;
6466 dns_diff_t post_diff;
6467 dns_fixedname_t fixed;
6468 dns_fixedname_t nextfixed;
6469 dns_name_t *name, *nextname;
6470 dns_rdataset_t rdataset;
6471 dns_signing_t *signing, *nextsigning;
6472 dns_signinglist_t cleanup;
6473 dst_key_t *zone_keys[MAXZONEKEYS];
6474 isc_int32_t signatures;
6475 isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
6476 isc_boolean_t commit = ISC_FALSE;
6477 isc_boolean_t delegation;
6478 isc_boolean_t build_nsec = ISC_FALSE;
6479 isc_boolean_t build_nsec3 = ISC_FALSE;
6480 isc_boolean_t first;
6481 isc_result_t result;
6482 isc_stdtime_t now, inception, soaexpire, expire, stop;
6483 isc_uint32_t jitter;
6484 unsigned int i, j;
6485 unsigned int nkeys = 0;
6486 isc_uint32_t nodes;
6487 isc_boolean_t was_ksk;
6488 isc_time_t when;
6490 dns_rdataset_init(&rdataset);
6491 dns_fixedname_init(&fixed);
6492 name = dns_fixedname_name(&fixed);
6493 dns_fixedname_init(&nextfixed);
6494 nextname = dns_fixedname_name(&nextfixed);
6495 dns_diff_init(zone->mctx, &sig_diff);
6496 sig_diff.resign = zone->sigresigninginterval;
6497 dns_diff_init(zone->mctx, &post_diff);
6498 ISC_LIST_INIT(cleanup);
6501 * Updates are disabled. Pause for 5 minutes.
6503 if (zone->update_disabled) {
6504 result = ISC_R_FAILURE;
6505 goto failure;
6508 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6509 dns_db_attach(zone->db, &db);
6510 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6512 result = dns_db_newversion(db, &version);
6513 if (result != ISC_R_SUCCESS) {
6514 dns_zone_log(zone, ISC_LOG_ERROR,
6515 "zone_sign:dns_db_newversion -> %s\n",
6516 dns_result_totext(result));
6517 goto failure;
6520 result = find_zone_keys(zone, db, version, zone->mctx,
6521 MAXZONEKEYS, zone_keys, &nkeys);
6522 if (result != ISC_R_SUCCESS) {
6523 dns_zone_log(zone, ISC_LOG_ERROR,
6524 "zone_sign:find_zone_keys -> %s\n",
6525 dns_result_totext(result));
6526 goto failure;
6529 isc_stdtime_get(&now);
6530 inception = now - 3600; /* Allow for clock skew. */
6531 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6534 * Spread out signatures over time if they happen to be
6535 * clumped. We don't do this for each add_sigs() call as
6536 * we still want some clustering to occur.
6538 isc_random_get(&jitter);
6539 expire = soaexpire - jitter % 3600;
6540 stop = now + 5;
6543 * We keep pulling nodes off each iterator in turn until
6544 * we have no more nodes to pull off or we reach the limits
6545 * for this quantum.
6547 nodes = zone->nodes;
6548 signatures = zone->signatures;
6549 signing = ISC_LIST_HEAD(zone->signing);
6550 first = ISC_TRUE;
6552 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6553 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6555 /* Determine which type of chain to build */
6556 CHECK(dns_private_chains(db, version, zone->privatetype,
6557 &build_nsec, &build_nsec3));
6559 while (signing != NULL && nodes-- > 0 && signatures > 0) {
6560 nextsigning = ISC_LIST_NEXT(signing, link);
6562 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6563 if (signing->done || signing->db != zone->db) {
6565 * The zone has been reloaded. We will have
6566 * created new signings as part of the reload
6567 * process so we can destroy this one.
6569 ISC_LIST_UNLINK(zone->signing, signing, link);
6570 ISC_LIST_APPEND(cleanup, signing, link);
6571 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6572 goto next_signing;
6574 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6576 if (signing->db != db)
6577 goto next_signing;
6579 delegation = ISC_FALSE;
6581 was_ksk = ISC_FALSE;
6583 if (first && signing->delete) {
6585 * Remove the key we are deleting from consideration.
6587 for (i = 0, j = 0; i < nkeys; i++) {
6589 * Find the key we want to remove.
6591 if (ALG(zone_keys[i]) == signing->algorithm &&
6592 dst_key_id(zone_keys[i]) == signing->keyid)
6594 if (KSK(zone_keys[i]))
6595 dst_key_free(&zone_keys[i]);
6596 continue;
6598 zone_keys[j] = zone_keys[i];
6599 j++;
6601 nkeys = j;
6604 dns_dbiterator_current(signing->dbiterator, &node, name);
6606 if (signing->delete) {
6607 dns_dbiterator_pause(signing->dbiterator);
6608 CHECK(del_sig(db, version, name, node, nkeys,
6609 signing->algorithm, signing->keyid,
6610 &sig_diff));
6614 * On the first pass we need to check if the current node
6615 * has not been obscured.
6617 if (first) {
6618 dns_fixedname_t ffound;
6619 dns_name_t *found;
6620 dns_fixedname_init(&ffound);
6621 found = dns_fixedname_name(&ffound);
6622 result = dns_db_find(db, name, version,
6623 dns_rdatatype_soa,
6624 DNS_DBFIND_NOWILD, 0, NULL, found,
6625 NULL, NULL);
6626 if ((result == DNS_R_DELEGATION ||
6627 result == DNS_R_DNAME) &&
6628 !dns_name_equal(name, found)) {
6630 * Remember the obscuring name so that
6631 * we skip all obscured names.
6633 dns_name_copy(found, name, NULL);
6634 delegation = ISC_TRUE;
6635 goto next_node;
6640 * Process one node.
6642 dns_dbiterator_pause(signing->dbiterator);
6643 for (i = 0; i < nkeys; i++) {
6644 isc_boolean_t both = ISC_FALSE;
6647 * Find the keys we want to sign with.
6649 if (!dst_key_isprivate(zone_keys[i]))
6650 continue;
6653 * When adding look for the specific key.
6655 if (!signing->delete &&
6656 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
6657 dst_key_id(zone_keys[i]) != signing->keyid))
6658 continue;
6661 * When deleting make sure we are properly signed
6662 * with the algorithm that was being removed.
6664 if (signing->delete &&
6665 ALG(zone_keys[i]) != signing->algorithm)
6666 continue;
6669 * Do we do KSK processing?
6671 if (check_ksk && !REVOKE(zone_keys[i])) {
6672 isc_boolean_t have_ksk, have_nonksk;
6673 if (KSK(zone_keys[i])) {
6674 have_ksk = ISC_TRUE;
6675 have_nonksk = ISC_FALSE;
6676 } else {
6677 have_ksk = ISC_FALSE;
6678 have_nonksk = ISC_TRUE;
6680 for (j = 0; j < nkeys; j++) {
6681 if (j == i ||
6682 ALG(zone_keys[i]) !=
6683 ALG(zone_keys[j]))
6684 continue;
6685 if (REVOKE(zone_keys[j]))
6686 continue;
6687 if (KSK(zone_keys[j]))
6688 have_ksk = ISC_TRUE;
6689 else
6690 have_nonksk = ISC_TRUE;
6691 both = have_ksk && have_nonksk;
6692 if (both)
6693 break;
6696 if (both || REVOKE(zone_keys[i]))
6697 is_ksk = KSK(zone_keys[i]);
6698 else
6699 is_ksk = ISC_FALSE;
6701 CHECK(sign_a_node(db, name, node, version, build_nsec3,
6702 build_nsec, zone_keys[i], inception,
6703 expire, zone->minimum, is_ksk,
6704 ISC_TF(both && keyset_kskonly),
6705 &delegation, &sig_diff,
6706 &signatures, zone->mctx));
6708 * If we are adding we are done. Look for other keys
6709 * of the same algorithm if deleting.
6711 if (!signing->delete)
6712 break;
6716 * Go onto next node.
6718 next_node:
6719 first = ISC_FALSE;
6720 dns_db_detachnode(db, &node);
6721 do {
6722 result = dns_dbiterator_next(signing->dbiterator);
6723 if (result == ISC_R_NOMORE) {
6724 ISC_LIST_UNLINK(zone->signing, signing, link);
6725 ISC_LIST_APPEND(cleanup, signing, link);
6726 dns_dbiterator_pause(signing->dbiterator);
6727 if (nkeys != 0 && build_nsec) {
6729 * We have finished regenerating the
6730 * zone with a zone signing key.
6731 * The NSEC chain is now complete and
6732 * there is a full set of signatures
6733 * for the zone. We can now clear the
6734 * OPT bit from the NSEC record.
6736 result = updatesecure(db, version,
6737 &zone->origin,
6738 zone->minimum,
6739 ISC_FALSE,
6740 &post_diff);
6741 if (result != ISC_R_SUCCESS) {
6742 dns_zone_log(zone,
6743 ISC_LOG_ERROR,
6744 "updatesecure -> %s\n",
6745 dns_result_totext(result));
6746 goto failure;
6749 result = updatesignwithkey(zone, signing,
6750 version,
6751 build_nsec3,
6752 zone->minimum,
6753 &post_diff);
6754 if (result != ISC_R_SUCCESS) {
6755 dns_zone_log(zone, ISC_LOG_ERROR,
6756 "updatesignwithkey "
6757 "-> %s\n",
6758 dns_result_totext(result));
6759 goto failure;
6761 build_nsec = ISC_FALSE;
6762 goto next_signing;
6763 } else if (result != ISC_R_SUCCESS) {
6764 dns_zone_log(zone, ISC_LOG_ERROR,
6765 "zone_sign:dns_dbiterator_next -> %s\n",
6766 dns_result_totext(result));
6767 goto failure;
6768 } else if (delegation) {
6769 dns_dbiterator_current(signing->dbiterator,
6770 &node, nextname);
6771 dns_db_detachnode(db, &node);
6772 if (!dns_name_issubdomain(nextname, name))
6773 break;
6774 } else
6775 break;
6776 } while (1);
6777 continue;
6779 next_signing:
6780 dns_dbiterator_pause(signing->dbiterator);
6781 signing = nextsigning;
6782 first = ISC_TRUE;
6785 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
6786 result = update_sigs(&post_diff, db, version, zone_keys,
6787 nkeys, zone, inception, expire, now,
6788 check_ksk, keyset_kskonly, &sig_diff);
6789 if (result != ISC_R_SUCCESS) {
6790 dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
6791 "update_sigs -> %s\n",
6792 dns_result_totext(result));
6793 goto failure;
6798 * Have we changed anything?
6800 if (ISC_LIST_HEAD(sig_diff.tuples) == NULL) {
6801 result = ISC_R_SUCCESS;
6802 goto pauseall;
6805 commit = ISC_TRUE;
6807 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6808 &sig_diff, zone_keys, nkeys, now);
6809 if (result != ISC_R_SUCCESS) {
6810 dns_zone_log(zone, ISC_LOG_ERROR,
6811 "zone_sign:del_sigs -> %s\n",
6812 dns_result_totext(result));
6813 goto failure;
6816 result = increment_soa_serial(db, version, &sig_diff, zone->mctx);
6817 if (result != ISC_R_SUCCESS) {
6818 dns_zone_log(zone, ISC_LOG_ERROR,
6819 "zone_sign:increment_soa_serial -> %s\n",
6820 dns_result_totext(result));
6821 goto failure;
6825 * Generate maximum life time signatures so that the above loop
6826 * termination is sensible.
6828 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6829 &sig_diff, zone_keys, nkeys, zone->mctx, inception,
6830 soaexpire, check_ksk, keyset_kskonly);
6831 if (result != ISC_R_SUCCESS) {
6832 dns_zone_log(zone, ISC_LOG_ERROR,
6833 "zone_sign:add_sigs -> %s\n",
6834 dns_result_totext(result));
6835 goto failure;
6839 * Write changes to journal file.
6841 zone_journal(zone, &sig_diff, "zone_sign");
6844 * Notify slaves, if appropriate.
6846 TIME_NOW(&when);
6847 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOTIFYRESIGN)) {
6848 LOCK_ZONE(zone);
6849 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOTIFYRESIGN);
6850 UNLOCK_ZONE(zone);
6851 zone_notify(zone, &when);
6854 pauseall:
6856 * Pause all iterators so that dns_db_closeversion() can succeed.
6858 for (signing = ISC_LIST_HEAD(zone->signing);
6859 signing != NULL;
6860 signing = ISC_LIST_NEXT(signing, link))
6861 dns_dbiterator_pause(signing->dbiterator);
6863 for (signing = ISC_LIST_HEAD(cleanup);
6864 signing != NULL;
6865 signing = ISC_LIST_NEXT(signing, link))
6866 dns_dbiterator_pause(signing->dbiterator);
6869 * Everything has succeeded. Commit the changes.
6871 dns_db_closeversion(db, &version, commit);
6874 * Everything succeeded so we can clean these up now.
6876 signing = ISC_LIST_HEAD(cleanup);
6877 while (signing != NULL) {
6878 ISC_LIST_UNLINK(cleanup, signing, link);
6879 dns_db_detach(&signing->db);
6880 dns_dbiterator_destroy(&signing->dbiterator);
6881 isc_mem_put(zone->mctx, signing, sizeof *signing);
6882 signing = ISC_LIST_HEAD(cleanup);
6885 set_resigntime(zone);
6887 if (commit) {
6888 LOCK_ZONE(zone);
6889 zone_needdump(zone, DNS_DUMP_DELAY);
6890 UNLOCK_ZONE(zone);
6893 failure:
6895 * Rollback the cleanup list.
6897 signing = ISC_LIST_HEAD(cleanup);
6898 while (signing != NULL) {
6899 ISC_LIST_UNLINK(cleanup, signing, link);
6900 ISC_LIST_PREPEND(zone->signing, signing, link);
6901 dns_dbiterator_first(signing->dbiterator);
6902 dns_dbiterator_pause(signing->dbiterator);
6903 signing = ISC_LIST_HEAD(cleanup);
6906 for (signing = ISC_LIST_HEAD(zone->signing);
6907 signing != NULL;
6908 signing = ISC_LIST_NEXT(signing, link))
6909 dns_dbiterator_pause(signing->dbiterator);
6911 dns_diff_clear(&sig_diff);
6913 for (i = 0; i < nkeys; i++)
6914 dst_key_free(&zone_keys[i]);
6916 if (node != NULL)
6917 dns_db_detachnode(db, &node);
6919 if (version != NULL) {
6920 dns_db_closeversion(db, &version, ISC_FALSE);
6921 dns_db_detach(&db);
6922 } else if (db != NULL)
6923 dns_db_detach(&db);
6925 if (ISC_LIST_HEAD(zone->signing) != NULL) {
6926 isc_interval_t i;
6927 if (zone->update_disabled || result != ISC_R_SUCCESS)
6928 isc_interval_set(&i, 60, 0); /* 1 minute */
6929 else
6930 isc_interval_set(&i, 0, 10000000); /* 10 ms */
6931 isc_time_nowplusinterval(&zone->signingtime, &i);
6932 } else
6933 isc_time_settoepoch(&zone->signingtime);
6936 static void
6937 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
6938 unsigned char *data, int size) {
6939 dns_rdata_dnskey_t dnskey;
6940 dns_rdata_keydata_t keydata;
6941 isc_buffer_t buf;
6943 dns_rdata_reset(target);
6944 isc_buffer_init(&buf, data, size);
6946 switch (rr->type) {
6947 case dns_rdatatype_dnskey:
6948 dns_rdata_tostruct(rr, &dnskey, NULL);
6949 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
6950 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
6951 &dnskey, &buf);
6952 break;
6953 case dns_rdatatype_keydata:
6954 dns_rdata_tostruct(rr, &keydata, NULL);
6955 dns_keydata_todnskey(&keydata, &dnskey, NULL);
6956 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
6957 &dnskey, &buf);
6958 break;
6959 default:
6960 INSIST(0);
6965 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
6966 * a KEYDATA rdataset from the key zone.
6968 * 'rr' contains either a DNSKEY record, or a KEYDATA record
6970 * After normalizing keys to the same format (DNSKEY, with revoke bit
6971 * cleared), return ISC_TRUE if a key that matches 'rr' is found in
6972 * 'rdset', or ISC_FALSE if not.
6975 static isc_boolean_t
6976 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
6977 unsigned char data1[4096], data2[4096];
6978 dns_rdata_t rdata, rdata1, rdata2;
6979 isc_result_t result;
6981 dns_rdata_init(&rdata);
6982 dns_rdata_init(&rdata1);
6983 dns_rdata_init(&rdata2);
6985 normalize_key(rr, &rdata1, data1, sizeof(data1));
6987 for (result = dns_rdataset_first(rdset);
6988 result == ISC_R_SUCCESS;
6989 result = dns_rdataset_next(rdset)) {
6990 dns_rdata_reset(&rdata);
6991 dns_rdataset_current(rdset, &rdata);
6992 normalize_key(&rdata, &rdata2, data2, sizeof(data2));
6993 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
6994 return (ISC_TRUE);
6997 return (ISC_FALSE);
7001 * Calculate the refresh interval for a keydata zone, per
7002 * RFC5011: MAX(1 hr,
7003 * MIN(15 days,
7004 * 1/2 * OrigTTL,
7005 * 1/2 * RRSigExpirationInterval))
7007 static inline isc_stdtime_t
7008 refresh_time(dns_keyfetch_t *kfetch) {
7009 isc_result_t result;
7010 isc_uint32_t t;
7011 dns_rdataset_t *rdset;
7012 dns_rdata_t sigrr = DNS_RDATA_INIT;
7013 dns_rdata_sig_t sig;
7014 isc_stdtime_t now;
7016 isc_stdtime_get(&now);
7018 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7019 rdset = &kfetch->dnskeysigset;
7020 else
7021 return (now + HOUR);
7023 result = dns_rdataset_first(rdset);
7024 if (result != ISC_R_SUCCESS)
7025 return (now + HOUR);
7027 dns_rdataset_current(rdset, &sigrr);
7028 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7030 t = sig.originalttl / 2;
7032 if (isc_serial_gt(sig.timeexpire, now)) {
7033 isc_uint32_t exp = (sig.timeexpire - now) / 2;
7034 if (t > exp)
7035 t = exp;
7038 if (t > (15*DAY))
7039 t = (15*DAY);
7041 if (t < HOUR)
7042 t = HOUR;
7044 return (now + t);
7048 * This routine is called when no changes are needed in a KEYDATA
7049 * record except to simply update the refresh timer. Caller should
7050 * hold zone lock.
7052 static isc_result_t
7053 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
7054 isc_result_t result;
7055 isc_buffer_t keyb;
7056 unsigned char key_buf[4096];
7057 dns_rdata_t rdata = DNS_RDATA_INIT;
7058 dns_rdata_keydata_t keydata;
7059 dns_name_t *name;
7060 dns_zone_t *zone = kfetch->zone;
7061 isc_stdtime_t now;
7063 name = dns_fixedname_name(&kfetch->name);
7064 isc_stdtime_get(&now);
7066 for (result = dns_rdataset_first(&kfetch->keydataset);
7067 result == ISC_R_SUCCESS;
7068 result = dns_rdataset_next(&kfetch->keydataset)) {
7069 dns_rdata_reset(&rdata);
7070 dns_rdataset_current(&kfetch->keydataset, &rdata);
7072 /* Delete old version */
7073 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
7074 name, 0, &rdata));
7076 /* Update refresh timer */
7077 CHECK(dns_rdata_tostruct(&rdata, &keydata, NULL));
7078 keydata.refresh = refresh_time(kfetch);
7079 set_refreshkeytimer(zone, &keydata, now);
7081 dns_rdata_reset(&rdata);
7082 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7083 CHECK(dns_rdata_fromstruct(&rdata,
7084 zone->rdclass, dns_rdatatype_keydata,
7085 &keydata, &keyb));
7087 /* Insert updated version */
7088 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
7089 name, 0, &rdata));
7091 result = ISC_R_SUCCESS;
7092 failure:
7093 return (result);
7097 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
7099 static isc_boolean_t
7100 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
7101 isc_result_t result;
7102 dns_name_t *keyname;
7103 isc_mem_t *mctx;
7104 dns_rdata_t sigrr = DNS_RDATA_INIT;
7105 dns_rdata_t rr = DNS_RDATA_INIT;
7106 dns_rdata_rrsig_t sig;
7107 dns_rdata_dnskey_t dnskey;
7108 dst_key_t *dstkey = NULL;
7109 unsigned char key_buf[4096];
7110 isc_buffer_t keyb;
7111 isc_boolean_t answer = ISC_FALSE;
7113 REQUIRE(kfetch != NULL && keydata != NULL);
7114 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
7116 keyname = dns_fixedname_name(&kfetch->name);
7117 mctx = kfetch->zone->view->mctx;
7119 /* Generate a key from keydata */
7120 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7121 dns_keydata_todnskey(keydata, &dnskey, NULL);
7122 dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
7123 &dnskey, &keyb);
7124 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
7125 if (result != ISC_R_SUCCESS)
7126 return (ISC_FALSE);
7128 /* See if that key generated any of the signatures */
7129 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7130 result == ISC_R_SUCCESS;
7131 result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7132 dns_fixedname_t fixed;
7133 dns_fixedname_init(&fixed);
7135 dns_rdata_reset(&sigrr);
7136 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7137 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7138 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7140 if (dst_key_alg(dstkey) == sig.algorithm &&
7141 (dst_key_id(dstkey) == sig.keyid ||
7142 (sig.algorithm != 1 && sig.keyid ==
7143 ((dst_key_id(dstkey) + 128) & 0xffff)))) {
7144 result = dns_dnssec_verify2(keyname,
7145 &kfetch->dnskeyset,
7146 dstkey, ISC_FALSE, mctx, &sigrr,
7147 dns_fixedname_name(&fixed));
7149 dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
7150 "Confirm revoked DNSKEY is self-signed: "
7151 "%s", dns_result_totext(result));
7153 if (result == ISC_R_SUCCESS) {
7154 answer = ISC_TRUE;
7155 break;
7160 dst_key_free(&dstkey);
7161 return (answer);
7165 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
7166 * anchors are being managed; scan the keyset, and update the key zone and the
7167 * local trust anchors according to RFC5011.
7169 static void
7170 keyfetch_done(isc_task_t *task, isc_event_t *event) {
7171 isc_result_t result, eresult;
7172 dns_fetchevent_t *devent;
7173 dns_keyfetch_t *kfetch;
7174 dns_zone_t *zone;
7175 dns_keytable_t *secroots = NULL;
7176 dns_dbversion_t *ver = NULL;
7177 dns_diff_t diff;
7178 isc_boolean_t changed = ISC_FALSE;
7179 isc_boolean_t alldone = ISC_FALSE;
7180 dns_name_t *keyname;
7181 dns_rdata_t sigrr = DNS_RDATA_INIT;
7182 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
7183 dns_rdata_t keydatarr = DNS_RDATA_INIT;
7184 dns_rdata_rrsig_t sig;
7185 dns_rdata_dnskey_t dnskey;
7186 dns_rdata_keydata_t keydata;
7187 isc_boolean_t initializing;
7188 char namebuf[DNS_NAME_FORMATSIZE];
7189 unsigned char key_buf[4096];
7190 isc_buffer_t keyb;
7191 dst_key_t *dstkey;
7192 isc_stdtime_t now;
7193 int pending = 0;
7195 UNUSED(task);
7196 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
7197 INSIST(event->ev_arg != NULL);
7199 kfetch = event->ev_arg;
7200 zone = kfetch->zone;
7201 keyname = dns_fixedname_name(&kfetch->name);
7203 devent = (dns_fetchevent_t *) event;
7204 eresult = devent->result;
7206 /* Free resources which are not of interest */
7207 if (devent->node != NULL)
7208 dns_db_detachnode(devent->db, &devent->node);
7209 if (devent->db != NULL)
7210 dns_db_detach(&devent->db);
7211 isc_event_free(&event);
7212 dns_resolver_destroyfetch(&kfetch->fetch);
7214 isc_stdtime_get(&now);
7215 dns_name_format(keyname, namebuf, sizeof(namebuf));
7217 result = dns_view_getsecroots(zone->view, &secroots);
7218 INSIST(result == ISC_R_SUCCESS);
7220 LOCK_ZONE(zone);
7221 dns_db_newversion(kfetch->db, &ver);
7222 dns_diff_init(zone->mctx, &diff);
7224 /* Fetch failed */
7225 if (eresult != ISC_R_SUCCESS ||
7226 !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
7227 dns_zone_log(zone, ISC_LOG_WARNING,
7228 "Unable to fetch DNSKEY set "
7229 "'%s': %s", namebuf, dns_result_totext(eresult));
7230 CHECK(minimal_update(kfetch, ver, &diff));
7231 goto failure;
7234 /* No RRSIGs found */
7235 if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
7236 dns_zone_log(zone, ISC_LOG_WARNING,
7237 "No DNSKEY RRSIGs found for "
7238 "'%s': %s", namebuf, dns_result_totext(eresult));
7239 CHECK(minimal_update(kfetch, ver, &diff));
7240 goto failure;
7244 * Validate the dnskeyset against the current trusted keys.
7245 * (Note, if a key has been revoked and isn't RSAMD5, then
7246 * its key ID will have changed.)
7248 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
7249 result == ISC_R_SUCCESS;
7250 result = dns_rdataset_next(&kfetch->dnskeysigset)) {
7251 dns_keynode_t *keynode = NULL;
7253 dns_rdata_reset(&sigrr);
7254 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
7255 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
7256 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7258 result = dns_keytable_find(secroots, keyname, &keynode);
7259 while (result == ISC_R_SUCCESS) {
7260 dns_keynode_t *nextnode = NULL;
7261 dns_fixedname_t fixed;
7262 dns_fixedname_init(&fixed);
7264 dstkey = dns_keynode_key(keynode);
7265 if (dstkey == NULL) /* fail_secure() was called */
7266 break;
7268 if (dst_key_alg(dstkey) == sig.algorithm &&
7269 (dst_key_id(dstkey) == sig.keyid ||
7270 (sig.algorithm != 1 && sig.keyid ==
7271 ((dst_key_id(dstkey) + 128) & 0xffff)))) {
7272 result = dns_dnssec_verify2(keyname,
7273 &kfetch->dnskeyset,
7274 dstkey, ISC_FALSE,
7275 zone->view->mctx, &sigrr,
7276 dns_fixedname_name(&fixed));
7278 dns_zone_log(zone, ISC_LOG_DEBUG(3),
7279 "Verifying DNSKEY set for zone "
7280 "'%s': %s", namebuf,
7281 dns_result_totext(result));
7283 if (result == ISC_R_SUCCESS) {
7284 kfetch->dnskeyset.trust =
7285 dns_trust_secure;
7286 kfetch->dnskeysigset.trust =
7287 dns_trust_secure;
7288 dns_keytable_detachkeynode(secroots,
7289 &keynode);
7290 break;
7294 result = dns_keytable_nextkeynode(secroots,
7295 keynode, &nextnode);
7296 dns_keytable_detachkeynode(secroots, &keynode);
7297 keynode = nextnode;
7300 if (kfetch->dnskeyset.trust == dns_trust_secure)
7301 break;
7304 /* Failed to validate? Let's go home. */
7305 if (kfetch->dnskeyset.trust != dns_trust_secure) {
7306 dns_zone_log(zone, ISC_LOG_WARNING,
7307 "DNSKEY set for zone '%s' failed to validate",
7308 namebuf);
7309 CHECK(minimal_update(kfetch, ver, &diff));
7310 changed = ISC_TRUE;
7311 goto failure;
7315 * First scan keydataset to find keys that are not in dnskeyset
7316 * - Missing keys which are not scheduled for removal,
7317 * log a warning
7318 * - Missing keys which are scheduled for removal and
7319 * the remove hold-down timer has completed should
7320 * be removed from the key zone
7321 * - Missing keys whose acceptance timers have not yet
7322 * completed, log a warning and reset the acceptance
7323 * timer to 30 days in the future
7324 * - All keys not being removed have their refresh timers
7325 * updated
7327 initializing = ISC_TRUE;
7328 for (result = dns_rdataset_first(&kfetch->keydataset);
7329 result == ISC_R_SUCCESS;
7330 result = dns_rdataset_next(&kfetch->keydataset)) {
7331 dns_rdata_reset(&keydatarr);
7332 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7333 dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7336 * If any keydata record has a nonzero add holddown, then
7337 * there was a pre-existing trust anchor for this domain;
7338 * that means we are *not* initializing it and shouldn't
7339 * automatically trust all the keys we find at the zone apex.
7341 initializing = initializing && ISC_TF(keydata.addhd == 0);
7343 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
7344 isc_boolean_t deletekey = ISC_FALSE;
7346 if (now < keydata.addhd) {
7347 dns_zone_log(zone, ISC_LOG_WARNING,
7348 "Pending key unexpectedly missing "
7349 "from %s; restarting acceptance "
7350 "timer", namebuf);
7351 keydata.addhd = now + MONTH;
7352 keydata.refresh = refresh_time(kfetch);
7353 } else if (keydata.addhd == 0) {
7354 keydata.addhd = now;
7355 } else if (keydata.removehd == 0) {
7356 dns_zone_log(zone, ISC_LOG_WARNING,
7357 "Active key unexpectedly missing "
7358 "from %s", namebuf);
7359 keydata.refresh = now + HOUR;
7360 } else if (now > keydata.removehd) {
7361 deletekey = ISC_TRUE;
7362 } else {
7363 keydata.refresh = refresh_time(kfetch);
7366 /* Delete old version */
7367 CHECK(update_one_rr(kfetch->db, ver, &diff,
7368 DNS_DIFFOP_DEL, keyname, 0,
7369 &keydatarr));
7370 changed = ISC_TRUE;
7372 if (deletekey)
7373 continue;
7375 dns_rdata_reset(&keydatarr);
7376 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7377 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7378 dns_rdatatype_keydata,
7379 &keydata, &keyb);
7381 /* Insert updated version */
7382 CHECK(update_one_rr(kfetch->db, ver, &diff,
7383 DNS_DIFFOP_ADD, keyname, 0,
7384 &keydatarr));
7385 changed = ISC_TRUE;
7387 set_refreshkeytimer(zone, &keydata, now);
7392 * Next scan dnskeyset:
7393 * - If new keys are found (i.e., lacking a match in keydataset)
7394 * add them to the key zone and set the acceptance timer
7395 * to 30 days in the future (or to immediately if we've
7396 * determined that we're initializing the zone for the
7397 * first time)
7398 * - Previously-known keys that have been revoked
7399 * must be scheduled for removal from the key zone (or,
7400 * if they hadn't been accepted as trust anchors yet
7401 * anyway, removed at once)
7402 * - Previously-known unrevoked keys whose acceptance timers
7403 * have completed are promoted to trust anchors
7404 * - All keys not being removed have their refresh
7405 * timers updated
7407 for (result = dns_rdataset_first(&kfetch->dnskeyset);
7408 result == ISC_R_SUCCESS;
7409 result = dns_rdataset_next(&kfetch->dnskeyset)) {
7410 isc_boolean_t revoked = ISC_FALSE;
7411 isc_boolean_t newkey = ISC_FALSE;
7412 isc_boolean_t updatekey = ISC_FALSE;
7413 isc_boolean_t deletekey = ISC_FALSE;
7414 isc_boolean_t trustkey = ISC_FALSE;
7416 dns_rdata_reset(&dnskeyrr);
7417 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
7418 dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7420 /* Skip ZSK's */
7421 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
7422 continue;
7424 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
7426 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
7427 dns_rdata_reset(&keydatarr);
7428 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
7429 dns_rdata_tostruct(&keydatarr, &keydata, NULL);
7431 if (revoked) {
7432 if (keydata.addhd > now) {
7434 * Key wasn't trusted yet, and now
7435 * it's been revoked? Just remove it
7437 deletekey = ISC_TRUE;
7438 } else if (keydata.removehd == 0) {
7440 * Newly revoked key? Make sure
7441 * it signed itself
7443 if(! revocable(kfetch, &keydata)) {
7444 dns_zone_log(zone,
7445 ISC_LOG_WARNING,
7446 "Active key for zone "
7447 "'%s' is revoked but "
7448 "did not self-sign; "
7449 "ignoring.", namebuf);
7450 continue;
7453 /* Remove from secroots */
7454 untrust_key(zone->view->viewlist,
7455 keyname, zone->mctx,
7456 &dnskey);
7458 /* If initializing, delete now */
7459 if (keydata.addhd == 0)
7460 deletekey = ISC_TRUE;
7461 else
7462 keydata.removehd = now + MONTH;
7463 } else if (keydata.removehd < now) {
7464 /* Scheduled for removal */
7465 deletekey = ISC_TRUE;
7467 } else {
7468 if (keydata.removehd != 0) {
7470 * Key isn't revoked--but it
7471 * seems it used to be.
7472 * Remove it now and add it
7473 * back as if it were a fresh key.
7475 deletekey = ISC_TRUE;
7476 newkey = ISC_TRUE;
7477 } else if (keydata.addhd > now)
7478 pending++;
7479 else if (keydata.addhd == 0)
7480 keydata.addhd = now;
7482 if (keydata.addhd <= now)
7483 trustkey = ISC_TRUE;
7486 if (!deletekey && !newkey)
7487 updatekey = ISC_TRUE;
7488 } else {
7490 * Key wasn't in the key zone but it's
7491 * revoked now anyway, so just skip it
7493 if (revoked)
7494 continue;
7496 /* Key wasn't in the key zone: add it */
7497 newkey = ISC_TRUE;
7499 if (initializing) {
7500 dns_keytag_t tag = 0;
7501 CHECK(compute_tag(keyname, &dnskey,
7502 zone->mctx, &tag));
7503 dns_zone_log(zone, ISC_LOG_WARNING,
7504 "Initializing automatic trust "
7505 "anchor management for zone '%s'; "
7506 "DNSKEY ID %d is now trusted, "
7507 "waiving the normal 30-day "
7508 "waiting period.",
7509 namebuf, tag);
7510 trustkey = ISC_TRUE;
7514 /* Delete old version */
7515 if (deletekey || !newkey) {
7516 CHECK(update_one_rr(kfetch->db, ver, &diff,
7517 DNS_DIFFOP_DEL, keyname, 0,
7518 &keydatarr));
7519 changed = ISC_TRUE;
7522 if (updatekey) {
7523 /* Set refresh timer */
7524 keydata.refresh = refresh_time(kfetch);
7525 dns_rdata_reset(&keydatarr);
7526 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7527 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7528 dns_rdatatype_keydata,
7529 &keydata, &keyb);
7531 /* Insert updated version */
7532 CHECK(update_one_rr(kfetch->db, ver, &diff,
7533 DNS_DIFFOP_ADD, keyname, 0,
7534 &keydatarr));
7535 changed = ISC_TRUE;
7536 } else if (newkey) {
7537 /* Convert DNSKEY to KEYDATA */
7538 dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7539 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
7540 NULL);
7541 keydata.addhd = initializing ? now : now + MONTH;
7542 keydata.refresh = refresh_time(kfetch);
7543 dns_rdata_reset(&keydatarr);
7544 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
7545 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
7546 dns_rdatatype_keydata,
7547 &keydata, &keyb);
7549 /* Insert into key zone */
7550 CHECK(update_one_rr(kfetch->db, ver, &diff,
7551 DNS_DIFFOP_ADD, keyname, 0,
7552 &keydatarr));
7553 changed = ISC_TRUE;
7556 if (trustkey) {
7557 /* Trust this key in all views */
7558 dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
7559 trust_key(zone->view->viewlist, keyname, &dnskey,
7560 zone->mctx);
7563 if (!deletekey)
7564 set_refreshkeytimer(zone, &keydata, now);
7568 * RFC5011 says, "A trust point that has all of its trust anchors
7569 * revoked is considered deleted and is treated as if the trust
7570 * point was never configured." But if someone revoked their
7571 * active key before the standby was trusted, that would mean the
7572 * zone would suddenly be nonsecured. We avoid this by checking to
7573 * see if there's pending keydata. If so, we put a null key in
7574 * the security roots; then all queries to the zone will fail.
7576 if (pending != 0)
7577 fail_secure(zone->view->viewlist, keyname);
7579 failure:
7580 zone->refreshkeycount--;
7581 alldone = ISC_TF(zone->refreshkeycount == 0);
7583 if (changed) {
7584 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
7585 zone_needdump(zone, 30);
7588 if (alldone)
7589 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
7591 UNLOCK_ZONE(zone);
7593 /* Write changes to journal file. */
7594 if (alldone) {
7595 result = increment_soa_serial(kfetch->db, ver, &diff,
7596 zone->mctx);
7597 if (result == ISC_R_SUCCESS)
7598 zone_journal(zone, &diff, "keyfetch_done");
7601 dns_diff_clear(&diff);
7602 dns_db_closeversion(kfetch->db, &ver, changed);
7603 dns_db_detach(&kfetch->db);
7605 if (dns_rdataset_isassociated(&kfetch->keydataset))
7606 dns_rdataset_disassociate(&kfetch->keydataset);
7607 if (dns_rdataset_isassociated(&kfetch->dnskeyset))
7608 dns_rdataset_disassociate(&kfetch->dnskeyset);
7609 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
7610 dns_rdataset_disassociate(&kfetch->dnskeysigset);
7612 dns_name_free(keyname, zone->mctx);
7613 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
7615 if (secroots != NULL)
7616 dns_keytable_detach(&secroots);
7620 * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
7621 * records from the zone apex.
7623 static void
7624 zone_refreshkeys(dns_zone_t *zone) {
7625 const char me[] = "zone_refreshkeys";
7626 isc_result_t result;
7627 dns_rriterator_t rrit;
7628 dns_db_t *db = NULL;
7629 dns_dbversion_t *ver = NULL;
7630 dns_diff_t diff;
7631 dns_rdata_t rdata = DNS_RDATA_INIT;
7632 dns_rdata_keydata_t kd;
7633 isc_stdtime_t now;
7635 ENTER;
7636 REQUIRE(zone->db != NULL);
7638 isc_stdtime_get(&now);
7640 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7641 dns_db_attach(zone->db, &db);
7642 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7644 LOCK_ZONE(zone);
7645 dns_db_newversion(db, &ver);
7646 dns_diff_init(zone->mctx, &diff);
7648 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
7650 dns_rriterator_init(&rrit, db, ver, 0);
7651 for (result = dns_rriterator_first(&rrit);
7652 result == ISC_R_SUCCESS;
7653 result = dns_rriterator_nextrrset(&rrit)) {
7654 isc_stdtime_t timer = 0xffffffff;
7655 dns_keyfetch_t *kfetch;
7656 dns_rdataset_t *kdset;
7657 dns_name_t *name = NULL;
7658 isc_uint32_t ttl;
7660 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
7661 if (!dns_rdataset_isassociated(kdset))
7662 continue;
7664 if (kdset->type != dns_rdatatype_keydata)
7665 continue;
7668 * Scan the stored keys looking for ones that need
7669 * removal or refreshing
7671 for (result = dns_rdataset_first(kdset);
7672 result == ISC_R_SUCCESS;
7673 result = dns_rdataset_next(kdset)) {
7674 dns_rdata_reset(&rdata);
7675 dns_rdataset_current(kdset, &rdata);
7676 result = dns_rdata_tostruct(&rdata, &kd, NULL);
7677 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7679 /* Removal timer expired? */
7680 if (kd.removehd != 0 && kd.removehd < now) {
7681 CHECK(update_one_rr(db, ver, &diff,
7682 DNS_DIFFOP_DEL, name, ttl,
7683 &rdata));
7684 continue;
7687 /* Acceptance timer expired? */
7688 if (kd.addhd != 0 && kd.addhd < now)
7689 timer = kd.addhd;
7691 /* Or do we just need to refresh the keyset? */
7692 if (timer > kd.refresh)
7693 timer = kd.refresh;
7696 if (timer > now)
7697 continue;
7699 zone->refreshkeycount++;
7701 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
7702 kfetch->zone = zone;
7703 dns_fixedname_init(&kfetch->name);
7704 dns_name_dup(name, zone->mctx,
7705 dns_fixedname_name(&kfetch->name));
7706 dns_rdataset_init(&kfetch->dnskeyset);
7707 dns_rdataset_init(&kfetch->dnskeysigset);
7708 dns_rdataset_init(&kfetch->keydataset);
7709 dns_rdataset_clone(kdset, &kfetch->keydataset);
7710 kfetch->db = NULL;
7711 dns_db_attach(db, &kfetch->db);
7712 kfetch->fetch = NULL;
7714 dns_resolver_createfetch(zone->view->resolver,
7715 dns_fixedname_name(&kfetch->name),
7716 dns_rdatatype_dnskey,
7717 NULL, NULL, NULL,
7718 DNS_FETCHOPT_NOVALIDATE,
7719 zone->task, keyfetch_done, kfetch,
7720 &kfetch->dnskeyset,
7721 &kfetch->dnskeysigset,
7722 &kfetch->fetch);
7724 failure:
7725 UNLOCK_ZONE(zone);
7727 dns_rriterator_destroy(&rrit);
7728 dns_diff_clear(&diff);
7729 dns_db_closeversion(db, &ver, ISC_FALSE);
7730 dns_db_detach(&db);
7733 static void
7734 zone_maintenance(dns_zone_t *zone) {
7735 const char me[] = "zone_maintenance";
7736 isc_time_t now;
7737 isc_result_t result;
7738 isc_boolean_t dumping;
7740 REQUIRE(DNS_ZONE_VALID(zone));
7741 ENTER;
7744 * Configuring the view of this zone may have
7745 * failed, for example because the config file
7746 * had a syntax error. In that case, the view
7747 * adb or resolver, and we had better not try
7748 * to do maintenance on it.
7750 if (zone->view == NULL || zone->view->adb == NULL)
7751 return;
7753 TIME_NOW(&now);
7756 * Expire check.
7758 switch (zone->type) {
7759 case dns_zone_slave:
7760 case dns_zone_stub:
7761 LOCK_ZONE(zone);
7762 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
7763 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
7764 zone_expire(zone);
7765 zone->refreshtime = now;
7767 UNLOCK_ZONE(zone);
7768 break;
7769 default:
7770 break;
7774 * Up to date check.
7776 switch (zone->type) {
7777 case dns_zone_slave:
7778 case dns_zone_stub:
7779 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
7780 isc_time_compare(&now, &zone->refreshtime) >= 0)
7781 dns_zone_refresh(zone);
7782 break;
7783 default:
7784 break;
7788 * Do we need to consolidate the backing store?
7790 switch (zone->type) {
7791 case dns_zone_master:
7792 case dns_zone_slave:
7793 case dns_zone_key:
7794 LOCK_ZONE(zone);
7795 if (zone->masterfile != NULL &&
7796 isc_time_compare(&now, &zone->dumptime) >= 0 &&
7797 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
7798 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
7799 dumping = was_dumping(zone);
7800 } else
7801 dumping = ISC_TRUE;
7802 UNLOCK_ZONE(zone);
7803 if (!dumping) {
7804 result = zone_dump(zone, ISC_TRUE); /* task locked */
7805 if (result != ISC_R_SUCCESS)
7806 dns_zone_log(zone, ISC_LOG_WARNING,
7807 "dump failed: %s",
7808 dns_result_totext(result));
7810 break;
7811 default:
7812 break;
7816 * Do we need to refresh keys?
7818 switch (zone->type) {
7819 case dns_zone_key:
7820 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
7821 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
7822 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
7823 zone_refreshkeys(zone);
7824 break;
7825 case dns_zone_master:
7826 if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN) &&
7827 !isc_time_isepoch(&zone->refreshkeytime) &&
7828 isc_time_compare(&now, &zone->refreshkeytime) >= 0)
7829 dns_zone_rekey(zone);
7830 default:
7831 break;
7834 switch (zone->type) {
7835 case dns_zone_master:
7836 case dns_zone_slave:
7838 * Do we need to send out notify messages?
7840 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) &&
7841 isc_time_compare(&now, &zone->notifytime) >= 0)
7842 zone_notify(zone, &now);
7844 * Do we need to sign/resign some RRsets?
7846 if (!isc_time_isepoch(&zone->signingtime) &&
7847 isc_time_compare(&now, &zone->signingtime) >= 0)
7848 zone_sign(zone);
7849 else if (!isc_time_isepoch(&zone->resigntime) &&
7850 isc_time_compare(&now, &zone->resigntime) >= 0)
7851 zone_resigninc(zone);
7852 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
7853 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
7854 zone_nsec3chain(zone);
7856 * Do we need to issue a key expiry warning.
7858 if (!isc_time_isepoch(&zone->keywarntime) &&
7859 isc_time_compare(&now, &zone->keywarntime) >= 0)
7860 set_key_expiry_warning(zone, zone->key_expiry,
7861 isc_time_seconds(&now));
7862 break;
7863 default:
7864 break;
7866 zone_settimer(zone, &now);
7869 void
7870 dns_zone_markdirty(dns_zone_t *zone) {
7872 LOCK_ZONE(zone);
7873 set_resigntime(zone); /* XXXMPA make separate call back */
7874 zone_needdump(zone, DNS_DUMP_DELAY);
7875 UNLOCK_ZONE(zone);
7878 void
7879 dns_zone_expire(dns_zone_t *zone) {
7880 REQUIRE(DNS_ZONE_VALID(zone));
7882 LOCK_ZONE(zone);
7883 zone_expire(zone);
7884 UNLOCK_ZONE(zone);
7887 static void
7888 zone_expire(dns_zone_t *zone) {
7890 * 'zone' locked by caller.
7893 REQUIRE(LOCKED_ZONE(zone));
7895 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
7897 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
7898 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
7899 zone->retry = DNS_ZONE_DEFAULTRETRY;
7900 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
7901 zone_unload(zone);
7904 void
7905 dns_zone_refresh(dns_zone_t *zone) {
7906 isc_interval_t i;
7907 isc_uint32_t oldflags;
7908 unsigned int j;
7909 isc_result_t result;
7911 REQUIRE(DNS_ZONE_VALID(zone));
7913 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
7914 return;
7917 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
7918 * in progress at a time.
7921 LOCK_ZONE(zone);
7922 oldflags = zone->flags;
7923 if (zone->masterscnt == 0) {
7924 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
7925 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
7926 dns_zone_log(zone, ISC_LOG_ERROR,
7927 "cannot refresh: no masters");
7928 goto unlock;
7930 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
7931 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
7932 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
7933 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
7934 goto unlock;
7937 * Set the next refresh time as if refresh check has failed.
7938 * Setting this to the retry time will do that. XXXMLG
7939 * If we are successful it will be reset using zone->refresh.
7941 isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
7943 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
7944 if (result |= ISC_R_SUCCESS)
7945 dns_zone_log(zone, ISC_LOG_WARNING,
7946 "isc_time_nowplusinterval() failed: %s",
7947 dns_result_totext(result));
7950 * When lacking user-specified timer values from the SOA,
7951 * do exponential backoff of the retry time up to a
7952 * maximum of six hours.
7954 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
7955 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
7957 zone->curmaster = 0;
7958 for (j = 0; j < zone->masterscnt; j++)
7959 zone->mastersok[j] = ISC_FALSE;
7960 /* initiate soa query */
7961 queue_soa_query(zone);
7962 unlock:
7963 UNLOCK_ZONE(zone);
7966 isc_result_t
7967 dns_zone_flush(dns_zone_t *zone) {
7968 isc_result_t result = ISC_R_SUCCESS;
7969 isc_boolean_t dumping;
7971 REQUIRE(DNS_ZONE_VALID(zone));
7973 LOCK_ZONE(zone);
7974 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
7975 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
7976 zone->masterfile != NULL) {
7977 result = ISC_R_ALREADYRUNNING;
7978 dumping = was_dumping(zone);
7979 } else
7980 dumping = ISC_TRUE;
7981 UNLOCK_ZONE(zone);
7982 if (!dumping)
7983 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
7984 return (result);
7987 isc_result_t
7988 dns_zone_dump(dns_zone_t *zone) {
7989 isc_result_t result = ISC_R_ALREADYRUNNING;
7990 isc_boolean_t dumping;
7992 REQUIRE(DNS_ZONE_VALID(zone));
7994 LOCK_ZONE(zone);
7995 dumping = was_dumping(zone);
7996 UNLOCK_ZONE(zone);
7997 if (!dumping)
7998 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
7999 return (result);
8002 static void
8003 zone_needdump(dns_zone_t *zone, unsigned int delay) {
8004 isc_time_t dumptime;
8005 isc_time_t now;
8008 * 'zone' locked by caller
8011 REQUIRE(DNS_ZONE_VALID(zone));
8012 REQUIRE(LOCKED_ZONE(zone));
8015 * Do we have a place to dump to and are we loaded?
8017 if (zone->masterfile == NULL ||
8018 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
8019 return;
8021 TIME_NOW(&now);
8022 /* add some noise */
8023 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
8025 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8026 if (isc_time_isepoch(&zone->dumptime) ||
8027 isc_time_compare(&zone->dumptime, &dumptime) > 0)
8028 zone->dumptime = dumptime;
8029 if (zone->task != NULL)
8030 zone_settimer(zone, &now);
8033 static void
8034 dump_done(void *arg, isc_result_t result) {
8035 const char me[] = "dump_done";
8036 dns_zone_t *zone = arg;
8037 dns_db_t *db;
8038 dns_dbversion_t *version;
8039 isc_boolean_t again = ISC_FALSE;
8040 isc_boolean_t compact = ISC_FALSE;
8041 isc_uint32_t serial;
8042 isc_result_t tresult;
8044 REQUIRE(DNS_ZONE_VALID(zone));
8046 ENTER;
8048 if (result == ISC_R_SUCCESS && zone->journal != NULL &&
8049 zone->journalsize != -1) {
8052 * We don't own these, zone->dctx must stay valid.
8054 db = dns_dumpctx_db(zone->dctx);
8055 version = dns_dumpctx_version(zone->dctx);
8057 tresult = dns_db_getsoaserial(db, version, &serial);
8059 * Note: we are task locked here so we can test
8060 * zone->xfr safely.
8062 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
8063 tresult = dns_journal_compact(zone->mctx,
8064 zone->journal,
8065 serial,
8066 zone->journalsize);
8067 switch (tresult) {
8068 case ISC_R_SUCCESS:
8069 case ISC_R_NOSPACE:
8070 case ISC_R_NOTFOUND:
8071 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8072 "dns_journal_compact: %s",
8073 dns_result_totext(tresult));
8074 break;
8075 default:
8076 dns_zone_log(zone, ISC_LOG_ERROR,
8077 "dns_journal_compact failed: %s",
8078 dns_result_totext(tresult));
8079 break;
8081 } else if (tresult == ISC_R_SUCCESS) {
8082 compact = ISC_TRUE;
8083 zone->compact_serial = serial;
8087 LOCK_ZONE(zone);
8088 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8089 if (compact)
8090 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
8091 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
8093 * Try again in a short while.
8095 zone_needdump(zone, DNS_DUMP_DELAY);
8096 } else if (result == ISC_R_SUCCESS &&
8097 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8098 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8099 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8100 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8101 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8102 isc_time_settoepoch(&zone->dumptime);
8103 again = ISC_TRUE;
8104 } else if (result == ISC_R_SUCCESS)
8105 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8107 if (zone->dctx != NULL)
8108 dns_dumpctx_detach(&zone->dctx);
8109 zonemgr_putio(&zone->writeio);
8110 UNLOCK_ZONE(zone);
8111 if (again)
8112 (void)zone_dump(zone, ISC_FALSE);
8113 dns_zone_idetach(&zone);
8116 static isc_result_t
8117 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
8118 const char me[] = "zone_dump";
8119 isc_result_t result;
8120 dns_dbversion_t *version = NULL;
8121 isc_boolean_t again;
8122 dns_db_t *db = NULL;
8123 char *masterfile = NULL;
8124 dns_masterformat_t masterformat = dns_masterformat_none;
8127 * 'compact' MUST only be set if we are task locked.
8130 REQUIRE(DNS_ZONE_VALID(zone));
8131 ENTER;
8133 redo:
8134 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8135 if (zone->db != NULL)
8136 dns_db_attach(zone->db, &db);
8137 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8138 LOCK_ZONE(zone);
8139 if (zone->masterfile != NULL) {
8140 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
8141 masterformat = zone->masterformat;
8143 UNLOCK_ZONE(zone);
8144 if (db == NULL) {
8145 result = DNS_R_NOTLOADED;
8146 goto fail;
8148 if (masterfile == NULL) {
8149 result = DNS_R_NOMASTERFILE;
8150 goto fail;
8153 if (compact) {
8154 dns_zone_t *dummy = NULL;
8155 LOCK_ZONE(zone);
8156 zone_iattach(zone, &dummy);
8157 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
8158 zone_gotwritehandle, zone,
8159 &zone->writeio);
8160 if (result != ISC_R_SUCCESS)
8161 zone_idetach(&dummy);
8162 else
8163 result = DNS_R_CONTINUE;
8164 UNLOCK_ZONE(zone);
8165 } else {
8166 dns_db_currentversion(db, &version);
8167 result = dns_master_dump2(zone->mctx, db, version,
8168 &dns_master_style_default,
8169 masterfile, masterformat);
8170 dns_db_closeversion(db, &version, ISC_FALSE);
8172 fail:
8173 if (db != NULL)
8174 dns_db_detach(&db);
8175 if (masterfile != NULL)
8176 isc_mem_free(zone->mctx, masterfile);
8177 masterfile = NULL;
8179 if (result == DNS_R_CONTINUE)
8180 return (ISC_R_SUCCESS); /* XXXMPA */
8182 again = ISC_FALSE;
8183 LOCK_ZONE(zone);
8184 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
8185 if (result != ISC_R_SUCCESS) {
8187 * Try again in a short while.
8189 zone_needdump(zone, DNS_DUMP_DELAY);
8190 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
8191 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
8192 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
8193 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8194 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
8195 isc_time_settoepoch(&zone->dumptime);
8196 again = ISC_TRUE;
8197 } else
8198 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
8199 UNLOCK_ZONE(zone);
8200 if (again)
8201 goto redo;
8203 return (result);
8206 static isc_result_t
8207 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
8208 dns_masterformat_t format)
8210 isc_result_t result;
8211 dns_dbversion_t *version = NULL;
8212 dns_db_t *db = NULL;
8214 REQUIRE(DNS_ZONE_VALID(zone));
8216 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8217 if (zone->db != NULL)
8218 dns_db_attach(zone->db, &db);
8219 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8220 if (db == NULL)
8221 return (DNS_R_NOTLOADED);
8223 dns_db_currentversion(db, &version);
8224 result = dns_master_dumptostream2(zone->mctx, db, version, style,
8225 format, fd);
8226 dns_db_closeversion(db, &version, ISC_FALSE);
8227 dns_db_detach(&db);
8228 return (result);
8231 isc_result_t
8232 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
8233 const dns_master_style_t *style) {
8234 return dumptostream(zone, fd, style, format);
8237 isc_result_t
8238 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
8239 return dumptostream(zone, fd, &dns_master_style_default,
8240 dns_masterformat_text);
8243 isc_result_t
8244 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
8245 return dumptostream(zone, fd, &dns_master_style_full,
8246 dns_masterformat_text);
8249 void
8250 dns_zone_unload(dns_zone_t *zone) {
8251 REQUIRE(DNS_ZONE_VALID(zone));
8253 LOCK_ZONE(zone);
8254 zone_unload(zone);
8255 UNLOCK_ZONE(zone);
8258 static void
8259 notify_cancel(dns_zone_t *zone) {
8260 dns_notify_t *notify;
8263 * 'zone' locked by caller.
8266 REQUIRE(LOCKED_ZONE(zone));
8268 for (notify = ISC_LIST_HEAD(zone->notifies);
8269 notify != NULL;
8270 notify = ISC_LIST_NEXT(notify, link)) {
8271 if (notify->find != NULL)
8272 dns_adb_cancelfind(notify->find);
8273 if (notify->request != NULL)
8274 dns_request_cancel(notify->request);
8278 static void
8279 zone_unload(dns_zone_t *zone) {
8282 * 'zone' locked by caller.
8285 REQUIRE(LOCKED_ZONE(zone));
8287 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
8288 zone_detachdb(zone);
8289 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
8290 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
8291 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
8294 void
8295 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8296 REQUIRE(DNS_ZONE_VALID(zone));
8297 REQUIRE(val > 0);
8299 zone->minrefresh = val;
8302 void
8303 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
8304 REQUIRE(DNS_ZONE_VALID(zone));
8305 REQUIRE(val > 0);
8307 zone->maxrefresh = val;
8310 void
8311 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
8312 REQUIRE(DNS_ZONE_VALID(zone));
8313 REQUIRE(val > 0);
8315 zone->minretry = val;
8318 void
8319 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
8320 REQUIRE(DNS_ZONE_VALID(zone));
8321 REQUIRE(val > 0);
8323 zone->maxretry = val;
8326 static isc_boolean_t
8327 notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
8328 dns_notify_t *notify;
8330 for (notify = ISC_LIST_HEAD(zone->notifies);
8331 notify != NULL;
8332 notify = ISC_LIST_NEXT(notify, link)) {
8333 if (notify->request != NULL)
8334 continue;
8335 if (name != NULL && dns_name_dynamic(&notify->ns) &&
8336 dns_name_equal(name, &notify->ns))
8337 return (ISC_TRUE);
8338 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst))
8339 return (ISC_TRUE);
8341 return (ISC_FALSE);
8344 static isc_boolean_t
8345 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
8346 dns_tsigkey_t *key = NULL;
8347 isc_sockaddr_t src;
8348 isc_sockaddr_t any;
8349 isc_boolean_t isself;
8350 isc_netaddr_t dstaddr;
8351 isc_result_t result;
8353 if (zone->view == NULL || zone->isself == NULL)
8354 return (ISC_FALSE);
8356 switch (isc_sockaddr_pf(dst)) {
8357 case PF_INET:
8358 src = zone->notifysrc4;
8359 isc_sockaddr_any(&any);
8360 break;
8361 case PF_INET6:
8362 src = zone->notifysrc6;
8363 isc_sockaddr_any6(&any);
8364 break;
8365 default:
8366 return (ISC_FALSE);
8370 * When sending from any the kernel will assign a source address
8371 * that matches the destination address.
8373 if (isc_sockaddr_eqaddr(&any, &src))
8374 src = *dst;
8376 isc_netaddr_fromsockaddr(&dstaddr, dst);
8377 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
8378 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
8379 return (ISC_FALSE);
8380 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
8381 zone->isselfarg);
8382 if (key != NULL)
8383 dns_tsigkey_detach(&key);
8384 return (isself);
8387 static void
8388 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
8389 isc_mem_t *mctx;
8392 * Caller holds zone lock.
8394 REQUIRE(DNS_NOTIFY_VALID(notify));
8396 if (notify->zone != NULL) {
8397 if (!locked)
8398 LOCK_ZONE(notify->zone);
8399 REQUIRE(LOCKED_ZONE(notify->zone));
8400 if (ISC_LINK_LINKED(notify, link))
8401 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
8402 if (!locked)
8403 UNLOCK_ZONE(notify->zone);
8404 if (locked)
8405 zone_idetach(&notify->zone);
8406 else
8407 dns_zone_idetach(&notify->zone);
8409 if (notify->find != NULL)
8410 dns_adb_destroyfind(&notify->find);
8411 if (notify->request != NULL)
8412 dns_request_destroy(&notify->request);
8413 if (dns_name_dynamic(&notify->ns))
8414 dns_name_free(&notify->ns, notify->mctx);
8415 mctx = notify->mctx;
8416 isc_mem_put(notify->mctx, notify, sizeof(*notify));
8417 isc_mem_detach(&mctx);
8420 static isc_result_t
8421 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
8422 dns_notify_t *notify;
8424 REQUIRE(notifyp != NULL && *notifyp == NULL);
8426 notify = isc_mem_get(mctx, sizeof(*notify));
8427 if (notify == NULL)
8428 return (ISC_R_NOMEMORY);
8430 notify->mctx = NULL;
8431 isc_mem_attach(mctx, &notify->mctx);
8432 notify->flags = flags;
8433 notify->zone = NULL;
8434 notify->find = NULL;
8435 notify->request = NULL;
8436 isc_sockaddr_any(&notify->dst);
8437 dns_name_init(&notify->ns, NULL);
8438 ISC_LINK_INIT(notify, link);
8439 notify->magic = NOTIFY_MAGIC;
8440 *notifyp = notify;
8441 return (ISC_R_SUCCESS);
8445 * XXXAG should check for DNS_ZONEFLG_EXITING
8447 static void
8448 process_adb_event(isc_task_t *task, isc_event_t *ev) {
8449 dns_notify_t *notify;
8450 isc_eventtype_t result;
8452 UNUSED(task);
8454 notify = ev->ev_arg;
8455 REQUIRE(DNS_NOTIFY_VALID(notify));
8456 INSIST(task == notify->zone->task);
8457 result = ev->ev_type;
8458 isc_event_free(&ev);
8459 if (result == DNS_EVENT_ADBMOREADDRESSES) {
8460 dns_adb_destroyfind(&notify->find);
8461 notify_find_address(notify);
8462 return;
8464 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
8465 LOCK_ZONE(notify->zone);
8466 notify_send(notify);
8467 UNLOCK_ZONE(notify->zone);
8469 notify_destroy(notify, ISC_FALSE);
8472 static void
8473 notify_find_address(dns_notify_t *notify) {
8474 isc_result_t result;
8475 unsigned int options;
8477 REQUIRE(DNS_NOTIFY_VALID(notify));
8478 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
8479 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
8481 if (notify->zone->view->adb == NULL)
8482 goto destroy;
8484 result = dns_adb_createfind(notify->zone->view->adb,
8485 notify->zone->task,
8486 process_adb_event, notify,
8487 &notify->ns, dns_rootname, 0,
8488 options, 0, NULL,
8489 notify->zone->view->dstport,
8490 &notify->find);
8492 /* Something failed? */
8493 if (result != ISC_R_SUCCESS)
8494 goto destroy;
8496 /* More addresses pending? */
8497 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
8498 return;
8500 /* We have as many addresses as we can get. */
8501 LOCK_ZONE(notify->zone);
8502 notify_send(notify);
8503 UNLOCK_ZONE(notify->zone);
8505 destroy:
8506 notify_destroy(notify, ISC_FALSE);
8510 static isc_result_t
8511 notify_send_queue(dns_notify_t *notify) {
8512 isc_event_t *e;
8513 isc_result_t result;
8515 e = isc_event_allocate(notify->mctx, NULL,
8516 DNS_EVENT_NOTIFYSENDTOADDR,
8517 notify_send_toaddr,
8518 notify, sizeof(isc_event_t));
8519 if (e == NULL)
8520 return (ISC_R_NOMEMORY);
8521 e->ev_arg = notify;
8522 e->ev_sender = NULL;
8523 result = isc_ratelimiter_enqueue(notify->zone->zmgr->rl,
8524 notify->zone->task, &e);
8525 if (result != ISC_R_SUCCESS)
8526 isc_event_free(&e);
8527 return (result);
8530 static void
8531 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
8532 dns_notify_t *notify;
8533 isc_result_t result;
8534 dns_message_t *message = NULL;
8535 isc_netaddr_t dstip;
8536 dns_tsigkey_t *key = NULL;
8537 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
8538 isc_sockaddr_t src;
8539 int timeout;
8540 isc_boolean_t have_notifysource = ISC_FALSE;
8542 notify = event->ev_arg;
8543 REQUIRE(DNS_NOTIFY_VALID(notify));
8545 UNUSED(task);
8547 LOCK_ZONE(notify->zone);
8549 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
8550 result = ISC_R_CANCELED;
8551 goto cleanup;
8554 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
8555 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
8556 notify->zone->view->requestmgr == NULL ||
8557 notify->zone->db == NULL) {
8558 result = ISC_R_CANCELED;
8559 goto cleanup;
8563 * The raw IPv4 address should also exist. Don't send to the
8564 * mapped form.
8566 if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
8567 IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
8568 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8569 notify_log(notify->zone, ISC_LOG_DEBUG(3),
8570 "notify: ignoring IPv6 mapped IPV4 address: %s",
8571 addrbuf);
8572 result = ISC_R_CANCELED;
8573 goto cleanup;
8576 result = notify_createmessage(notify->zone, notify->flags, &message);
8577 if (result != ISC_R_SUCCESS)
8578 goto cleanup;
8580 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
8581 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
8582 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
8583 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
8584 notify_log(notify->zone, ISC_LOG_ERROR, "NOTIFY to %s not "
8585 "sent. Peer TSIG key lookup failure.", addrbuf);
8586 goto cleanup_message;
8589 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
8590 addrbuf);
8591 if (notify->zone->view->peers != NULL) {
8592 dns_peer_t *peer = NULL;
8593 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
8594 &dstip, &peer);
8595 if (result == ISC_R_SUCCESS) {
8596 result = dns_peer_getnotifysource(peer, &src);
8597 if (result == ISC_R_SUCCESS)
8598 have_notifysource = ISC_TRUE;
8601 switch (isc_sockaddr_pf(&notify->dst)) {
8602 case PF_INET:
8603 if (!have_notifysource)
8604 src = notify->zone->notifysrc4;
8605 break;
8606 case PF_INET6:
8607 if (!have_notifysource)
8608 src = notify->zone->notifysrc6;
8609 break;
8610 default:
8611 result = ISC_R_NOTIMPLEMENTED;
8612 goto cleanup_key;
8614 timeout = 15;
8615 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
8616 timeout = 30;
8617 result = dns_request_createvia2(notify->zone->view->requestmgr,
8618 message, &src, &notify->dst, 0, key,
8619 timeout * 3, timeout,
8620 notify->zone->task, notify_done,
8621 notify, &notify->request);
8622 if (result == ISC_R_SUCCESS) {
8623 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
8624 inc_stats(notify->zone,
8625 dns_zonestatscounter_notifyoutv4);
8626 } else {
8627 inc_stats(notify->zone,
8628 dns_zonestatscounter_notifyoutv6);
8632 cleanup_key:
8633 if (key != NULL)
8634 dns_tsigkey_detach(&key);
8635 cleanup_message:
8636 dns_message_destroy(&message);
8637 cleanup:
8638 UNLOCK_ZONE(notify->zone);
8639 if (result != ISC_R_SUCCESS)
8640 notify_destroy(notify, ISC_FALSE);
8641 isc_event_free(&event);
8644 static void
8645 notify_send(dns_notify_t *notify) {
8646 dns_adbaddrinfo_t *ai;
8647 isc_sockaddr_t dst;
8648 isc_result_t result;
8649 dns_notify_t *new = NULL;
8652 * Zone lock held by caller.
8654 REQUIRE(DNS_NOTIFY_VALID(notify));
8655 REQUIRE(LOCKED_ZONE(notify->zone));
8657 for (ai = ISC_LIST_HEAD(notify->find->list);
8658 ai != NULL;
8659 ai = ISC_LIST_NEXT(ai, publink)) {
8660 dst = ai->sockaddr;
8661 if (notify_isqueued(notify->zone, NULL, &dst))
8662 continue;
8663 if (notify_isself(notify->zone, &dst))
8664 continue;
8665 new = NULL;
8666 result = notify_create(notify->mctx,
8667 (notify->flags & DNS_NOTIFY_NOSOA),
8668 &new);
8669 if (result != ISC_R_SUCCESS)
8670 goto cleanup;
8671 zone_iattach(notify->zone, &new->zone);
8672 ISC_LIST_APPEND(new->zone->notifies, new, link);
8673 new->dst = dst;
8674 result = notify_send_queue(new);
8675 if (result != ISC_R_SUCCESS)
8676 goto cleanup;
8677 new = NULL;
8680 cleanup:
8681 if (new != NULL)
8682 notify_destroy(new, ISC_TRUE);
8685 void
8686 dns_zone_notify(dns_zone_t *zone) {
8687 isc_time_t now;
8689 REQUIRE(DNS_ZONE_VALID(zone));
8691 LOCK_ZONE(zone);
8692 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8694 TIME_NOW(&now);
8695 zone_settimer(zone, &now);
8696 UNLOCK_ZONE(zone);
8699 static void
8700 zone_notify(dns_zone_t *zone, isc_time_t *now) {
8701 dns_dbnode_t *node = NULL;
8702 dns_db_t *zonedb = NULL;
8703 dns_dbversion_t *version = NULL;
8704 dns_name_t *origin = NULL;
8705 dns_name_t master;
8706 dns_rdata_ns_t ns;
8707 dns_rdata_soa_t soa;
8708 isc_uint32_t serial;
8709 dns_rdata_t rdata = DNS_RDATA_INIT;
8710 dns_rdataset_t nsrdset;
8711 dns_rdataset_t soardset;
8712 isc_result_t result;
8713 dns_notify_t *notify = NULL;
8714 unsigned int i;
8715 isc_sockaddr_t dst;
8716 isc_boolean_t isqueued;
8717 dns_notifytype_t notifytype;
8718 unsigned int flags = 0;
8719 isc_boolean_t loggednotify = ISC_FALSE;
8721 REQUIRE(DNS_ZONE_VALID(zone));
8723 LOCK_ZONE(zone);
8724 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8725 notifytype = zone->notifytype;
8726 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
8727 UNLOCK_ZONE(zone);
8729 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
8730 return;
8732 if (notifytype == dns_notifytype_no)
8733 return;
8735 if (notifytype == dns_notifytype_masteronly &&
8736 zone->type != dns_zone_master)
8737 return;
8739 origin = &zone->origin;
8742 * If the zone is dialup we are done as we don't want to send
8743 * the current soa so as to force a refresh query.
8745 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
8746 flags |= DNS_NOTIFY_NOSOA;
8749 * Get SOA RRset.
8751 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8752 if (zone->db != NULL)
8753 dns_db_attach(zone->db, &zonedb);
8754 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8755 if (zonedb == NULL)
8756 return;
8757 dns_db_currentversion(zonedb, &version);
8758 result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
8759 if (result != ISC_R_SUCCESS)
8760 goto cleanup1;
8762 dns_rdataset_init(&soardset);
8763 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
8764 dns_rdatatype_none, 0, &soardset, NULL);
8765 if (result != ISC_R_SUCCESS)
8766 goto cleanup2;
8769 * Find serial and master server's name.
8771 dns_name_init(&master, NULL);
8772 result = dns_rdataset_first(&soardset);
8773 if (result != ISC_R_SUCCESS)
8774 goto cleanup3;
8775 dns_rdataset_current(&soardset, &rdata);
8776 result = dns_rdata_tostruct(&rdata, &soa, NULL);
8777 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8778 dns_rdata_reset(&rdata);
8779 result = dns_name_dup(&soa.origin, zone->mctx, &master);
8780 serial = soa.serial;
8781 dns_rdataset_disassociate(&soardset);
8782 if (result != ISC_R_SUCCESS)
8783 goto cleanup3;
8786 * Enqueue notify requests for 'also-notify' servers.
8788 LOCK_ZONE(zone);
8789 for (i = 0; i < zone->notifycnt; i++) {
8790 dst = zone->notify[i];
8791 if (notify_isqueued(zone, NULL, &dst))
8792 continue;
8793 result = notify_create(zone->mctx, flags, &notify);
8794 if (result != ISC_R_SUCCESS)
8795 continue;
8796 zone_iattach(zone, &notify->zone);
8797 notify->dst = dst;
8798 ISC_LIST_APPEND(zone->notifies, notify, link);
8799 result = notify_send_queue(notify);
8800 if (result != ISC_R_SUCCESS)
8801 notify_destroy(notify, ISC_TRUE);
8802 if (!loggednotify) {
8803 notify_log(zone, ISC_LOG_INFO,
8804 "sending notifies (serial %u)",
8805 serial);
8806 loggednotify = ISC_TRUE;
8808 notify = NULL;
8810 UNLOCK_ZONE(zone);
8812 if (notifytype == dns_notifytype_explicit)
8813 goto cleanup3;
8816 * Process NS RRset to generate notifies.
8819 dns_rdataset_init(&nsrdset);
8820 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
8821 dns_rdatatype_none, 0, &nsrdset, NULL);
8822 if (result != ISC_R_SUCCESS)
8823 goto cleanup3;
8825 result = dns_rdataset_first(&nsrdset);
8826 while (result == ISC_R_SUCCESS) {
8827 dns_rdataset_current(&nsrdset, &rdata);
8828 result = dns_rdata_tostruct(&rdata, &ns, NULL);
8829 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8830 dns_rdata_reset(&rdata);
8832 * Don't notify the master server unless explicitly
8833 * configured to do so.
8835 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
8836 dns_name_compare(&master, &ns.name) == 0) {
8837 result = dns_rdataset_next(&nsrdset);
8838 continue;
8841 if (!loggednotify) {
8842 notify_log(zone, ISC_LOG_INFO,
8843 "sending notifies (serial %u)",
8844 serial);
8845 loggednotify = ISC_TRUE;
8848 LOCK_ZONE(zone);
8849 isqueued = notify_isqueued(zone, &ns.name, NULL);
8850 UNLOCK_ZONE(zone);
8851 if (isqueued) {
8852 result = dns_rdataset_next(&nsrdset);
8853 continue;
8855 result = notify_create(zone->mctx, flags, &notify);
8856 if (result != ISC_R_SUCCESS)
8857 continue;
8858 dns_zone_iattach(zone, &notify->zone);
8859 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
8860 if (result != ISC_R_SUCCESS) {
8861 LOCK_ZONE(zone);
8862 notify_destroy(notify, ISC_TRUE);
8863 UNLOCK_ZONE(zone);
8864 continue;
8866 LOCK_ZONE(zone);
8867 ISC_LIST_APPEND(zone->notifies, notify, link);
8868 UNLOCK_ZONE(zone);
8869 notify_find_address(notify);
8870 notify = NULL;
8871 result = dns_rdataset_next(&nsrdset);
8873 dns_rdataset_disassociate(&nsrdset);
8875 cleanup3:
8876 if (dns_name_dynamic(&master))
8877 dns_name_free(&master, zone->mctx);
8878 cleanup2:
8879 dns_db_detachnode(zonedb, &node);
8880 cleanup1:
8881 dns_db_closeversion(zonedb, &version, ISC_FALSE);
8882 dns_db_detach(&zonedb);
8885 /***
8886 *** Private
8887 ***/
8889 static inline isc_result_t
8890 save_nsrrset(dns_message_t *message, dns_name_t *name,
8891 dns_db_t *db, dns_dbversion_t *version)
8893 dns_rdataset_t *nsrdataset = NULL;
8894 dns_rdataset_t *rdataset = NULL;
8895 dns_dbnode_t *node = NULL;
8896 dns_rdata_ns_t ns;
8897 isc_result_t result;
8898 dns_rdata_t rdata = DNS_RDATA_INIT;
8901 * Extract NS RRset from message.
8903 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
8904 dns_rdatatype_ns, dns_rdatatype_none,
8905 NULL, &nsrdataset);
8906 if (result != ISC_R_SUCCESS)
8907 goto fail;
8910 * Add NS rdataset.
8912 result = dns_db_findnode(db, name, ISC_TRUE, &node);
8913 if (result != ISC_R_SUCCESS)
8914 goto fail;
8915 result = dns_db_addrdataset(db, node, version, 0,
8916 nsrdataset, 0, NULL);
8917 dns_db_detachnode(db, &node);
8918 if (result != ISC_R_SUCCESS)
8919 goto fail;
8921 * Add glue rdatasets.
8923 for (result = dns_rdataset_first(nsrdataset);
8924 result == ISC_R_SUCCESS;
8925 result = dns_rdataset_next(nsrdataset)) {
8926 dns_rdataset_current(nsrdataset, &rdata);
8927 result = dns_rdata_tostruct(&rdata, &ns, NULL);
8928 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8929 dns_rdata_reset(&rdata);
8930 if (!dns_name_issubdomain(&ns.name, name))
8931 continue;
8932 rdataset = NULL;
8933 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
8934 &ns.name, dns_rdatatype_aaaa,
8935 dns_rdatatype_none, NULL,
8936 &rdataset);
8937 if (result == ISC_R_SUCCESS) {
8938 result = dns_db_findnode(db, &ns.name,
8939 ISC_TRUE, &node);
8940 if (result != ISC_R_SUCCESS)
8941 goto fail;
8942 result = dns_db_addrdataset(db, node, version, 0,
8943 rdataset, 0, NULL);
8944 dns_db_detachnode(db, &node);
8945 if (result != ISC_R_SUCCESS)
8946 goto fail;
8948 rdataset = NULL;
8949 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
8950 &ns.name, dns_rdatatype_a,
8951 dns_rdatatype_none, NULL,
8952 &rdataset);
8953 if (result == ISC_R_SUCCESS) {
8954 result = dns_db_findnode(db, &ns.name,
8955 ISC_TRUE, &node);
8956 if (result != ISC_R_SUCCESS)
8957 goto fail;
8958 result = dns_db_addrdataset(db, node, version, 0,
8959 rdataset, 0, NULL);
8960 dns_db_detachnode(db, &node);
8961 if (result != ISC_R_SUCCESS)
8962 goto fail;
8965 if (result != ISC_R_NOMORE)
8966 goto fail;
8968 return (ISC_R_SUCCESS);
8970 fail:
8971 return (result);
8974 static void
8975 stub_callback(isc_task_t *task, isc_event_t *event) {
8976 const char me[] = "stub_callback";
8977 dns_requestevent_t *revent = (dns_requestevent_t *)event;
8978 dns_stub_t *stub = NULL;
8979 dns_message_t *msg = NULL;
8980 dns_zone_t *zone = NULL;
8981 char master[ISC_SOCKADDR_FORMATSIZE];
8982 char source[ISC_SOCKADDR_FORMATSIZE];
8983 isc_uint32_t nscnt, cnamecnt;
8984 isc_result_t result;
8985 isc_time_t now;
8986 isc_boolean_t exiting = ISC_FALSE;
8987 isc_interval_t i;
8988 unsigned int j;
8990 stub = revent->ev_arg;
8991 INSIST(DNS_STUB_VALID(stub));
8993 UNUSED(task);
8995 zone = stub->zone;
8997 ENTER;
8999 TIME_NOW(&now);
9001 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9002 zone_debuglog(zone, me, 1, "exiting");
9003 exiting = ISC_TRUE;
9004 goto next_master;
9007 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9008 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9010 if (revent->result != ISC_R_SUCCESS) {
9011 if (revent->result == ISC_R_TIMEDOUT &&
9012 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9013 LOCK_ZONE(zone);
9014 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9015 UNLOCK_ZONE(zone);
9016 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9017 "refreshing stub: timeout retrying "
9018 " without EDNS master %s (source %s)",
9019 master, source);
9020 goto same_master;
9022 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
9023 &zone->sourceaddr, &now);
9024 dns_zone_log(zone, ISC_LOG_INFO,
9025 "could not refresh stub from master %s"
9026 " (source %s): %s", master, source,
9027 dns_result_totext(revent->result));
9028 goto next_master;
9031 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9032 if (result != ISC_R_SUCCESS)
9033 goto next_master;
9035 result = dns_request_getresponse(revent->request, msg, 0);
9036 if (result != ISC_R_SUCCESS)
9037 goto next_master;
9040 * Unexpected rcode.
9042 if (msg->rcode != dns_rcode_noerror) {
9043 char rcode[128];
9044 isc_buffer_t rb;
9046 isc_buffer_init(&rb, rcode, sizeof(rcode));
9047 (void)dns_rcode_totext(msg->rcode, &rb);
9049 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9050 (msg->rcode == dns_rcode_servfail ||
9051 msg->rcode == dns_rcode_notimp ||
9052 msg->rcode == dns_rcode_formerr)) {
9053 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9054 "refreshing stub: rcode (%.*s) retrying "
9055 "without EDNS master %s (source %s)",
9056 (int)rb.used, rcode, master, source);
9057 LOCK_ZONE(zone);
9058 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9059 UNLOCK_ZONE(zone);
9060 goto same_master;
9063 dns_zone_log(zone, ISC_LOG_INFO,
9064 "refreshing stub: "
9065 "unexpected rcode (%.*s) from %s (source %s)",
9066 (int)rb.used, rcode, master, source);
9067 goto next_master;
9071 * We need complete messages.
9073 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9074 if (dns_request_usedtcp(revent->request)) {
9075 dns_zone_log(zone, ISC_LOG_INFO,
9076 "refreshing stub: truncated TCP "
9077 "response from master %s (source %s)",
9078 master, source);
9079 goto next_master;
9081 LOCK_ZONE(zone);
9082 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9083 UNLOCK_ZONE(zone);
9084 goto same_master;
9088 * If non-auth log and next master.
9090 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9091 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
9092 "non-authoritative answer from "
9093 "master %s (source %s)", master, source);
9094 goto next_master;
9098 * Sanity checks.
9100 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9101 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
9103 if (cnamecnt != 0) {
9104 dns_zone_log(zone, ISC_LOG_INFO,
9105 "refreshing stub: unexpected CNAME response "
9106 "from master %s (source %s)", master, source);
9107 goto next_master;
9110 if (nscnt == 0) {
9111 dns_zone_log(zone, ISC_LOG_INFO,
9112 "refreshing stub: no NS records in response "
9113 "from master %s (source %s)", master, source);
9114 goto next_master;
9118 * Save answer.
9120 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
9121 if (result != ISC_R_SUCCESS) {
9122 dns_zone_log(zone, ISC_LOG_INFO,
9123 "refreshing stub: unable to save NS records "
9124 "from master %s (source %s)", master, source);
9125 goto next_master;
9129 * Tidy up.
9131 dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
9132 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
9133 if (zone->db == NULL)
9134 zone_attachdb(zone, stub->db);
9135 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
9136 dns_db_detach(&stub->db);
9138 if (zone->masterfile != NULL) {
9139 dns_zone_dump(zone);
9140 TIME_NOW(&zone->loadtime);
9143 dns_message_destroy(&msg);
9144 isc_event_free(&event);
9145 LOCK_ZONE(zone);
9146 dns_request_destroy(&zone->request);
9147 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9148 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9149 isc_interval_set(&i, zone->expire, 0);
9150 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9151 zone_settimer(zone, &now);
9152 UNLOCK_ZONE(zone);
9153 goto free_stub;
9155 next_master:
9156 if (stub->version != NULL)
9157 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
9158 if (stub->db != NULL)
9159 dns_db_detach(&stub->db);
9160 if (msg != NULL)
9161 dns_message_destroy(&msg);
9162 isc_event_free(&event);
9163 LOCK_ZONE(zone);
9164 dns_request_destroy(&zone->request);
9166 * Skip to next failed / untried master.
9168 do {
9169 zone->curmaster++;
9170 } while (zone->curmaster < zone->masterscnt &&
9171 zone->mastersok[zone->curmaster]);
9172 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9173 if (exiting || zone->curmaster >= zone->masterscnt) {
9174 isc_boolean_t done = ISC_TRUE;
9175 if (!exiting &&
9176 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9177 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9179 * Did we get a good answer from all the masters?
9181 for (j = 0; j < zone->masterscnt; j++)
9182 if (zone->mastersok[j] == ISC_FALSE) {
9183 done = ISC_FALSE;
9184 break;
9186 } else
9187 done = ISC_TRUE;
9188 if (!done) {
9189 zone->curmaster = 0;
9191 * Find the next failed master.
9193 while (zone->curmaster < zone->masterscnt &&
9194 zone->mastersok[zone->curmaster])
9195 zone->curmaster++;
9196 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9197 } else {
9198 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9200 zone_settimer(zone, &now);
9201 UNLOCK_ZONE(zone);
9202 goto free_stub;
9205 queue_soa_query(zone);
9206 UNLOCK_ZONE(zone);
9207 goto free_stub;
9209 same_master:
9210 if (msg != NULL)
9211 dns_message_destroy(&msg);
9212 isc_event_free(&event);
9213 LOCK_ZONE(zone);
9214 dns_request_destroy(&zone->request);
9215 UNLOCK_ZONE(zone);
9216 ns_query(zone, NULL, stub);
9217 goto done;
9219 free_stub:
9220 stub->magic = 0;
9221 dns_zone_idetach(&stub->zone);
9222 INSIST(stub->db == NULL);
9223 INSIST(stub->version == NULL);
9224 isc_mem_put(stub->mctx, stub, sizeof(*stub));
9226 done:
9227 INSIST(event == NULL);
9228 return;
9232 * An SOA query has finished (successfully or not).
9234 static void
9235 refresh_callback(isc_task_t *task, isc_event_t *event) {
9236 const char me[] = "refresh_callback";
9237 dns_requestevent_t *revent = (dns_requestevent_t *)event;
9238 dns_zone_t *zone;
9239 dns_message_t *msg = NULL;
9240 isc_uint32_t soacnt, cnamecnt, soacount, nscount;
9241 isc_time_t now;
9242 char master[ISC_SOCKADDR_FORMATSIZE];
9243 char source[ISC_SOCKADDR_FORMATSIZE];
9244 dns_rdataset_t *rdataset = NULL;
9245 dns_rdata_t rdata = DNS_RDATA_INIT;
9246 dns_rdata_soa_t soa;
9247 isc_result_t result;
9248 isc_uint32_t serial, oldserial;
9249 unsigned int j;
9251 zone = revent->ev_arg;
9252 INSIST(DNS_ZONE_VALID(zone));
9254 UNUSED(task);
9256 ENTER;
9259 * if timeout log and next master;
9262 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
9263 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
9265 TIME_NOW(&now);
9267 if (revent->result != ISC_R_SUCCESS) {
9268 if (revent->result == ISC_R_TIMEDOUT &&
9269 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9270 LOCK_ZONE(zone);
9271 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9272 UNLOCK_ZONE(zone);
9273 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9274 "refresh: timeout retrying without EDNS "
9275 "master %s (source %s)", master, source);
9276 goto same_master;
9278 if (revent->result == ISC_R_TIMEDOUT &&
9279 !dns_request_usedtcp(revent->request)) {
9280 dns_zone_log(zone, ISC_LOG_INFO,
9281 "refresh: retry limit for "
9282 "master %s exceeded (source %s)",
9283 master, source);
9284 /* Try with slave with TCP. */
9285 if (zone->type == dns_zone_slave &&
9286 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
9287 if (!dns_zonemgr_unreachable(zone->zmgr,
9288 &zone->masteraddr,
9289 &zone->sourceaddr,
9290 &now)) {
9291 LOCK_ZONE(zone);
9292 DNS_ZONE_SETFLAG(zone,
9293 DNS_ZONEFLG_SOABEFOREAXFR);
9294 UNLOCK_ZONE(zone);
9295 goto tcp_transfer;
9297 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9298 "refresh: skipped tcp fallback"
9299 "as master %s (source %s) is "
9300 "unreachable (cached)",
9301 master, source);
9303 } else
9304 dns_zone_log(zone, ISC_LOG_INFO,
9305 "refresh: failure trying master "
9306 "%s (source %s): %s", master, source,
9307 dns_result_totext(revent->result));
9308 goto next_master;
9311 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
9312 if (result != ISC_R_SUCCESS)
9313 goto next_master;
9314 result = dns_request_getresponse(revent->request, msg, 0);
9315 if (result != ISC_R_SUCCESS) {
9316 dns_zone_log(zone, ISC_LOG_INFO,
9317 "refresh: failure trying master "
9318 "%s (source %s): %s", master, source,
9319 dns_result_totext(result));
9320 goto next_master;
9324 * Unexpected rcode.
9326 if (msg->rcode != dns_rcode_noerror) {
9327 char rcode[128];
9328 isc_buffer_t rb;
9330 isc_buffer_init(&rb, rcode, sizeof(rcode));
9331 (void)dns_rcode_totext(msg->rcode, &rb);
9333 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
9334 (msg->rcode == dns_rcode_servfail ||
9335 msg->rcode == dns_rcode_notimp ||
9336 msg->rcode == dns_rcode_formerr)) {
9337 dns_zone_log(zone, ISC_LOG_DEBUG(1),
9338 "refresh: rcode (%.*s) retrying without "
9339 "EDNS master %s (source %s)",
9340 (int)rb.used, rcode, master, source);
9341 LOCK_ZONE(zone);
9342 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9343 UNLOCK_ZONE(zone);
9344 goto same_master;
9346 dns_zone_log(zone, ISC_LOG_INFO,
9347 "refresh: unexpected rcode (%.*s) from "
9348 "master %s (source %s)", (int)rb.used, rcode,
9349 master, source);
9351 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
9353 if (msg->rcode == dns_rcode_refused &&
9354 zone->type == dns_zone_slave)
9355 goto tcp_transfer;
9356 goto next_master;
9360 * If truncated punt to zone transfer which will query again.
9362 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
9363 if (zone->type == dns_zone_slave) {
9364 dns_zone_log(zone, ISC_LOG_INFO,
9365 "refresh: truncated UDP answer, "
9366 "initiating TCP zone xfer "
9367 "for master %s (source %s)",
9368 master, source);
9369 LOCK_ZONE(zone);
9370 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
9371 UNLOCK_ZONE(zone);
9372 goto tcp_transfer;
9373 } else {
9374 INSIST(zone->type == dns_zone_stub);
9375 if (dns_request_usedtcp(revent->request)) {
9376 dns_zone_log(zone, ISC_LOG_INFO,
9377 "refresh: truncated TCP response "
9378 "from master %s (source %s)",
9379 master, source);
9380 goto next_master;
9382 LOCK_ZONE(zone);
9383 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
9384 UNLOCK_ZONE(zone);
9385 goto same_master;
9390 * if non-auth log and next master;
9392 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
9393 dns_zone_log(zone, ISC_LOG_INFO,
9394 "refresh: non-authoritative answer from "
9395 "master %s (source %s)", master, source);
9396 goto next_master;
9399 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
9400 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
9401 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
9402 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
9403 dns_rdatatype_soa);
9406 * There should not be a CNAME record at top of zone.
9408 if (cnamecnt != 0) {
9409 dns_zone_log(zone, ISC_LOG_INFO,
9410 "refresh: CNAME at top of zone "
9411 "in master %s (source %s)", master, source);
9412 goto next_master;
9416 * if referral log and next master;
9418 if (soacnt == 0 && soacount == 0 && nscount != 0) {
9419 dns_zone_log(zone, ISC_LOG_INFO,
9420 "refresh: referral response "
9421 "from master %s (source %s)", master, source);
9422 goto next_master;
9426 * if nodata log and next master;
9428 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
9429 dns_zone_log(zone, ISC_LOG_INFO,
9430 "refresh: NODATA response "
9431 "from master %s (source %s)", master, source);
9432 goto next_master;
9436 * Only one soa at top of zone.
9438 if (soacnt != 1) {
9439 dns_zone_log(zone, ISC_LOG_INFO,
9440 "refresh: answer SOA count (%d) != 1 "
9441 "from master %s (source %s)",
9442 soacnt, master, source);
9443 goto next_master;
9446 * Extract serial
9448 rdataset = NULL;
9449 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
9450 dns_rdatatype_soa, dns_rdatatype_none,
9451 NULL, &rdataset);
9452 if (result != ISC_R_SUCCESS) {
9453 dns_zone_log(zone, ISC_LOG_INFO,
9454 "refresh: unable to get SOA record "
9455 "from master %s (source %s)", master, source);
9456 goto next_master;
9459 result = dns_rdataset_first(rdataset);
9460 if (result != ISC_R_SUCCESS) {
9461 dns_zone_log(zone, ISC_LOG_INFO,
9462 "refresh: dns_rdataset_first() failed");
9463 goto next_master;
9466 dns_rdataset_current(rdataset, &rdata);
9467 result = dns_rdata_tostruct(&rdata, &soa, NULL);
9468 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9470 serial = soa.serial;
9471 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9472 result = dns_zone_getserial2(zone, &oldserial);
9473 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9474 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
9475 serial, oldserial);
9476 } else
9477 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
9478 serial);
9479 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
9480 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
9481 isc_serial_gt(serial, oldserial)) {
9482 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
9483 &zone->sourceaddr, &now)) {
9484 dns_zone_log(zone, ISC_LOG_INFO,
9485 "refresh: skipping %s as master %s "
9486 "(source %s) is unreachable (cached)",
9487 zone->type == dns_zone_slave ?
9488 "zone transfer" : "NS query",
9489 master, source);
9490 goto next_master;
9492 tcp_transfer:
9493 isc_event_free(&event);
9494 LOCK_ZONE(zone);
9495 dns_request_destroy(&zone->request);
9496 UNLOCK_ZONE(zone);
9497 if (zone->type == dns_zone_slave) {
9498 queue_xfrin(zone);
9499 } else {
9500 INSIST(zone->type == dns_zone_stub);
9501 ns_query(zone, rdataset, NULL);
9503 if (msg != NULL)
9504 dns_message_destroy(&msg);
9505 } else if (isc_serial_eq(soa.serial, oldserial)) {
9506 if (zone->masterfile != NULL) {
9507 result = ISC_R_FAILURE;
9508 if (zone->journal != NULL)
9509 result = isc_file_settime(zone->journal, &now);
9510 if (result == ISC_R_SUCCESS &&
9511 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9512 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
9513 result = isc_file_settime(zone->masterfile,
9514 &now);
9515 } else if (result != ISC_R_SUCCESS)
9516 result = isc_file_settime(zone->masterfile,
9517 &now);
9518 /* Someone removed the file from underneath us! */
9519 if (result == ISC_R_FILENOTFOUND) {
9520 LOCK_ZONE(zone);
9521 zone_needdump(zone, DNS_DUMP_DELAY);
9522 UNLOCK_ZONE(zone);
9523 } else if (result != ISC_R_SUCCESS)
9524 dns_zone_log(zone, ISC_LOG_ERROR,
9525 "refresh: could not set file "
9526 "modification time of '%s': %s",
9527 zone->masterfile,
9528 dns_result_totext(result));
9530 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
9531 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
9532 zone->mastersok[zone->curmaster] = ISC_TRUE;
9533 goto next_master;
9534 } else {
9535 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
9536 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
9537 "received from master %s < ours (%u)",
9538 soa.serial, master, oldserial);
9539 else
9540 zone_debuglog(zone, me, 1, "ahead");
9541 zone->mastersok[zone->curmaster] = ISC_TRUE;
9542 goto next_master;
9544 if (msg != NULL)
9545 dns_message_destroy(&msg);
9546 goto detach;
9548 next_master:
9549 if (msg != NULL)
9550 dns_message_destroy(&msg);
9551 isc_event_free(&event);
9552 LOCK_ZONE(zone);
9553 dns_request_destroy(&zone->request);
9555 * Skip to next failed / untried master.
9557 do {
9558 zone->curmaster++;
9559 } while (zone->curmaster < zone->masterscnt &&
9560 zone->mastersok[zone->curmaster]);
9561 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9562 if (zone->curmaster >= zone->masterscnt) {
9563 isc_boolean_t done = ISC_TRUE;
9564 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
9565 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9567 * Did we get a good answer from all the masters?
9569 for (j = 0; j < zone->masterscnt; j++)
9570 if (zone->mastersok[j] == ISC_FALSE) {
9571 done = ISC_FALSE;
9572 break;
9574 } else
9575 done = ISC_TRUE;
9576 if (!done) {
9577 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9578 zone->curmaster = 0;
9580 * Find the next failed master.
9582 while (zone->curmaster < zone->masterscnt &&
9583 zone->mastersok[zone->curmaster])
9584 zone->curmaster++;
9585 goto requeue;
9587 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9588 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
9589 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
9590 zone->refreshtime = now;
9592 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9593 zone_settimer(zone, &now);
9594 UNLOCK_ZONE(zone);
9595 goto detach;
9598 requeue:
9599 queue_soa_query(zone);
9600 UNLOCK_ZONE(zone);
9601 goto detach;
9603 same_master:
9604 if (msg != NULL)
9605 dns_message_destroy(&msg);
9606 isc_event_free(&event);
9607 LOCK_ZONE(zone);
9608 dns_request_destroy(&zone->request);
9609 queue_soa_query(zone);
9610 UNLOCK_ZONE(zone);
9612 detach:
9613 dns_zone_idetach(&zone);
9614 return;
9617 static void
9618 queue_soa_query(dns_zone_t *zone) {
9619 const char me[] = "queue_soa_query";
9620 isc_event_t *e;
9621 dns_zone_t *dummy = NULL;
9622 isc_result_t result;
9624 ENTER;
9626 * Locked by caller
9628 REQUIRE(LOCKED_ZONE(zone));
9630 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9631 cancel_refresh(zone);
9632 return;
9635 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
9636 soa_query, zone, sizeof(isc_event_t));
9637 if (e == NULL) {
9638 cancel_refresh(zone);
9639 return;
9643 * Attach so that we won't clean up
9644 * until the event is delivered.
9646 zone_iattach(zone, &dummy);
9648 e->ev_arg = zone;
9649 e->ev_sender = NULL;
9650 result = isc_ratelimiter_enqueue(zone->zmgr->rl, zone->task, &e);
9651 if (result != ISC_R_SUCCESS) {
9652 zone_idetach(&dummy);
9653 isc_event_free(&e);
9654 cancel_refresh(zone);
9658 static inline isc_result_t
9659 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
9660 dns_message_t **messagep)
9662 dns_message_t *message = NULL;
9663 dns_name_t *qname = NULL;
9664 dns_rdataset_t *qrdataset = NULL;
9665 isc_result_t result;
9667 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
9668 &message);
9669 if (result != ISC_R_SUCCESS)
9670 goto cleanup;
9672 message->opcode = dns_opcode_query;
9673 message->rdclass = zone->rdclass;
9675 result = dns_message_gettempname(message, &qname);
9676 if (result != ISC_R_SUCCESS)
9677 goto cleanup;
9679 result = dns_message_gettemprdataset(message, &qrdataset);
9680 if (result != ISC_R_SUCCESS)
9681 goto cleanup;
9684 * Make question.
9686 dns_name_init(qname, NULL);
9687 dns_name_clone(&zone->origin, qname);
9688 dns_rdataset_init(qrdataset);
9689 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
9690 ISC_LIST_APPEND(qname->list, qrdataset, link);
9691 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
9693 *messagep = message;
9694 return (ISC_R_SUCCESS);
9696 cleanup:
9697 if (qname != NULL)
9698 dns_message_puttempname(message, &qname);
9699 if (qrdataset != NULL)
9700 dns_message_puttemprdataset(message, &qrdataset);
9701 if (message != NULL)
9702 dns_message_destroy(&message);
9703 return (result);
9706 static isc_result_t
9707 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
9708 dns_rdataset_t *rdataset = NULL;
9709 dns_rdatalist_t *rdatalist = NULL;
9710 dns_rdata_t *rdata = NULL;
9711 isc_result_t result;
9713 result = dns_message_gettemprdatalist(message, &rdatalist);
9714 if (result != ISC_R_SUCCESS)
9715 goto cleanup;
9716 result = dns_message_gettemprdata(message, &rdata);
9717 if (result != ISC_R_SUCCESS)
9718 goto cleanup;
9719 result = dns_message_gettemprdataset(message, &rdataset);
9720 if (result != ISC_R_SUCCESS)
9721 goto cleanup;
9722 dns_rdataset_init(rdataset);
9724 rdatalist->type = dns_rdatatype_opt;
9725 rdatalist->covers = 0;
9728 * Set Maximum UDP buffer size.
9730 rdatalist->rdclass = udpsize;
9733 * Set EXTENDED-RCODE, VERSION, DO and Z to 0.
9735 rdatalist->ttl = 0;
9737 /* Set EDNS options if applicable */
9738 if (reqnsid) {
9739 unsigned char data[4];
9740 isc_buffer_t buf;
9742 isc_buffer_init(&buf, data, sizeof(data));
9743 isc_buffer_putuint16(&buf, DNS_OPT_NSID);
9744 isc_buffer_putuint16(&buf, 0);
9745 rdata->data = data;
9746 rdata->length = sizeof(data);
9747 } else {
9748 rdata->data = NULL;
9749 rdata->length = 0;
9752 rdata->rdclass = rdatalist->rdclass;
9753 rdata->type = rdatalist->type;
9754 rdata->flags = 0;
9756 ISC_LIST_INIT(rdatalist->rdata);
9757 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
9758 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset)
9759 == ISC_R_SUCCESS);
9761 return (dns_message_setopt(message, rdataset));
9763 cleanup:
9764 if (rdatalist != NULL)
9765 dns_message_puttemprdatalist(message, &rdatalist);
9766 if (rdataset != NULL)
9767 dns_message_puttemprdataset(message, &rdataset);
9768 if (rdata != NULL)
9769 dns_message_puttemprdata(message, &rdata);
9771 return (result);
9774 static void
9775 soa_query(isc_task_t *task, isc_event_t *event) {
9776 const char me[] = "soa_query";
9777 isc_result_t result = ISC_R_FAILURE;
9778 dns_message_t *message = NULL;
9779 dns_zone_t *zone = event->ev_arg;
9780 dns_zone_t *dummy = NULL;
9781 isc_netaddr_t masterip;
9782 dns_tsigkey_t *key = NULL;
9783 isc_uint32_t options;
9784 isc_boolean_t cancel = ISC_TRUE;
9785 int timeout;
9786 isc_boolean_t have_xfrsource, reqnsid;
9787 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
9789 REQUIRE(DNS_ZONE_VALID(zone));
9791 UNUSED(task);
9793 ENTER;
9795 LOCK_ZONE(zone);
9796 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
9797 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
9798 zone->view->requestmgr == NULL) {
9799 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9800 cancel = ISC_FALSE;
9801 goto cleanup;
9805 * XXX Optimisation: Create message when zone is setup and reuse.
9807 result = create_query(zone, dns_rdatatype_soa, &message);
9808 if (result != ISC_R_SUCCESS)
9809 goto cleanup;
9811 again:
9812 INSIST(zone->masterscnt > 0);
9813 INSIST(zone->curmaster < zone->masterscnt);
9815 zone->masteraddr = zone->masters[zone->curmaster];
9817 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
9819 * First, look for a tsig key in the master statement, then
9820 * try for a server key.
9822 if ((zone->masterkeynames != NULL) &&
9823 (zone->masterkeynames[zone->curmaster] != NULL)) {
9824 dns_view_t *view = dns_zone_getview(zone);
9825 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
9826 result = dns_view_gettsig(view, keyname, &key);
9827 if (result != ISC_R_SUCCESS) {
9828 char namebuf[DNS_NAME_FORMATSIZE];
9829 dns_name_format(keyname, namebuf, sizeof(namebuf));
9830 dns_zone_log(zone, ISC_LOG_ERROR,
9831 "unable to find key: %s", namebuf);
9832 goto skip_master;
9835 if (key == NULL) {
9836 result = dns_view_getpeertsig(zone->view, &masterip, &key);
9837 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
9838 char addrbuf[ISC_NETADDR_FORMATSIZE];
9839 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
9840 dns_zone_log(zone, ISC_LOG_ERROR,
9841 "unable to find TSIG key for %s", addrbuf);
9842 goto skip_master;
9846 have_xfrsource = ISC_FALSE;
9847 reqnsid = zone->view->requestnsid;
9848 if (zone->view->peers != NULL) {
9849 dns_peer_t *peer = NULL;
9850 isc_boolean_t edns;
9851 result = dns_peerlist_peerbyaddr(zone->view->peers,
9852 &masterip, &peer);
9853 if (result == ISC_R_SUCCESS) {
9854 result = dns_peer_getsupportedns(peer, &edns);
9855 if (result == ISC_R_SUCCESS && !edns)
9856 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
9857 result = dns_peer_gettransfersource(peer,
9858 &zone->sourceaddr);
9859 if (result == ISC_R_SUCCESS)
9860 have_xfrsource = ISC_TRUE;
9861 if (zone->view->resolver != NULL)
9862 udpsize =
9863 dns_resolver_getudpsize(zone->view->resolver);
9864 (void)dns_peer_getudpsize(peer, &udpsize);
9865 (void)dns_peer_getrequestnsid(peer, &reqnsid);
9869 switch (isc_sockaddr_pf(&zone->masteraddr)) {
9870 case PF_INET:
9871 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9872 if (isc_sockaddr_equal(&zone->altxfrsource4,
9873 &zone->xfrsource4))
9874 goto skip_master;
9875 zone->sourceaddr = zone->altxfrsource4;
9876 } else if (!have_xfrsource)
9877 zone->sourceaddr = zone->xfrsource4;
9878 break;
9879 case PF_INET6:
9880 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
9881 if (isc_sockaddr_equal(&zone->altxfrsource6,
9882 &zone->xfrsource6))
9883 goto skip_master;
9884 zone->sourceaddr = zone->altxfrsource6;
9885 } else if (!have_xfrsource)
9886 zone->sourceaddr = zone->xfrsource6;
9887 break;
9888 default:
9889 result = ISC_R_NOTIMPLEMENTED;
9890 goto cleanup;
9893 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
9894 DNS_REQUESTOPT_TCP : 0;
9896 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
9897 result = add_opt(message, udpsize, reqnsid);
9898 if (result != ISC_R_SUCCESS)
9899 zone_debuglog(zone, me, 1,
9900 "unable to add opt record: %s",
9901 dns_result_totext(result));
9904 zone_iattach(zone, &dummy);
9905 timeout = 15;
9906 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
9907 timeout = 30;
9908 result = dns_request_createvia2(zone->view->requestmgr, message,
9909 &zone->sourceaddr, &zone->masteraddr,
9910 options, key, timeout * 3, timeout,
9911 zone->task, refresh_callback, zone,
9912 &zone->request);
9913 if (result != ISC_R_SUCCESS) {
9914 zone_idetach(&dummy);
9915 zone_debuglog(zone, me, 1,
9916 "dns_request_createvia2() failed: %s",
9917 dns_result_totext(result));
9918 goto cleanup;
9919 } else {
9920 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
9921 inc_stats(zone, dns_zonestatscounter_soaoutv4);
9922 else
9923 inc_stats(zone, dns_zonestatscounter_soaoutv6);
9925 cancel = ISC_FALSE;
9927 cleanup:
9928 if (key != NULL)
9929 dns_tsigkey_detach(&key);
9930 if (result != ISC_R_SUCCESS)
9931 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
9932 if (message != NULL)
9933 dns_message_destroy(&message);
9934 if (cancel)
9935 cancel_refresh(zone);
9936 isc_event_free(&event);
9937 UNLOCK_ZONE(zone);
9938 dns_zone_idetach(&zone);
9939 return;
9941 skip_master:
9942 if (key != NULL)
9943 dns_tsigkey_detach(&key);
9945 * Skip to next failed / untried master.
9947 do {
9948 zone->curmaster++;
9949 } while (zone->curmaster < zone->masterscnt &&
9950 zone->mastersok[zone->curmaster]);
9951 if (zone->curmaster < zone->masterscnt)
9952 goto again;
9953 zone->curmaster = 0;
9954 goto cleanup;
9957 static void
9958 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
9959 const char me[] = "ns_query";
9960 isc_result_t result;
9961 dns_message_t *message = NULL;
9962 isc_netaddr_t masterip;
9963 dns_tsigkey_t *key = NULL;
9964 dns_dbnode_t *node = NULL;
9965 int timeout;
9966 isc_boolean_t have_xfrsource = ISC_FALSE, reqnsid;
9967 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
9969 REQUIRE(DNS_ZONE_VALID(zone));
9970 REQUIRE((soardataset != NULL && stub == NULL) ||
9971 (soardataset == NULL && stub != NULL));
9972 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
9974 ENTER;
9976 LOCK_ZONE(zone);
9977 if (stub == NULL) {
9978 stub = isc_mem_get(zone->mctx, sizeof(*stub));
9979 if (stub == NULL)
9980 goto cleanup;
9981 stub->magic = STUB_MAGIC;
9982 stub->mctx = zone->mctx;
9983 stub->zone = NULL;
9984 stub->db = NULL;
9985 stub->version = NULL;
9988 * Attach so that the zone won't disappear from under us.
9990 zone_iattach(zone, &stub->zone);
9993 * If a db exists we will update it, otherwise we create a
9994 * new one and attach it to the zone once we have the NS
9995 * RRset and glue.
9997 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9998 if (zone->db != NULL) {
9999 dns_db_attach(zone->db, &stub->db);
10000 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10001 } else {
10002 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10004 INSIST(zone->db_argc >= 1);
10005 result = dns_db_create(zone->mctx, zone->db_argv[0],
10006 &zone->origin, dns_dbtype_stub,
10007 zone->rdclass,
10008 zone->db_argc - 1,
10009 zone->db_argv + 1,
10010 &stub->db);
10011 if (result != ISC_R_SUCCESS) {
10012 dns_zone_log(zone, ISC_LOG_ERROR,
10013 "refreshing stub: "
10014 "could not create "
10015 "database: %s",
10016 dns_result_totext(result));
10017 goto cleanup;
10019 dns_db_settask(stub->db, zone->task);
10022 dns_db_newversion(stub->db, &stub->version);
10025 * Update SOA record.
10027 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
10028 &node);
10029 if (result != ISC_R_SUCCESS) {
10030 dns_zone_log(zone, ISC_LOG_INFO,
10031 "refreshing stub: "
10032 "dns_db_findnode() failed: %s",
10033 dns_result_totext(result));
10034 goto cleanup;
10037 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
10038 soardataset, 0, NULL);
10039 dns_db_detachnode(stub->db, &node);
10040 if (result != ISC_R_SUCCESS) {
10041 dns_zone_log(zone, ISC_LOG_INFO,
10042 "refreshing stub: "
10043 "dns_db_addrdataset() failed: %s",
10044 dns_result_totext(result));
10045 goto cleanup;
10050 * XXX Optimisation: Create message when zone is setup and reuse.
10052 result = create_query(zone, dns_rdatatype_ns, &message);
10054 INSIST(zone->masterscnt > 0);
10055 INSIST(zone->curmaster < zone->masterscnt);
10056 zone->masteraddr = zone->masters[zone->curmaster];
10058 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
10060 * First, look for a tsig key in the master statement, then
10061 * try for a server key.
10063 if ((zone->masterkeynames != NULL) &&
10064 (zone->masterkeynames[zone->curmaster] != NULL)) {
10065 dns_view_t *view = dns_zone_getview(zone);
10066 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
10067 result = dns_view_gettsig(view, keyname, &key);
10068 if (result != ISC_R_SUCCESS) {
10069 char namebuf[DNS_NAME_FORMATSIZE];
10070 dns_name_format(keyname, namebuf, sizeof(namebuf));
10071 dns_zone_log(zone, ISC_LOG_ERROR,
10072 "unable to find key: %s", namebuf);
10075 if (key == NULL)
10076 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
10078 reqnsid = zone->view->requestnsid;
10079 if (zone->view->peers != NULL) {
10080 dns_peer_t *peer = NULL;
10081 isc_boolean_t edns;
10082 result = dns_peerlist_peerbyaddr(zone->view->peers,
10083 &masterip, &peer);
10084 if (result == ISC_R_SUCCESS) {
10085 result = dns_peer_getsupportedns(peer, &edns);
10086 if (result == ISC_R_SUCCESS && !edns)
10087 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10088 result = dns_peer_gettransfersource(peer,
10089 &zone->sourceaddr);
10090 if (result == ISC_R_SUCCESS)
10091 have_xfrsource = ISC_TRUE;
10092 if (zone->view->resolver != NULL)
10093 udpsize =
10094 dns_resolver_getudpsize(zone->view->resolver);
10095 (void)dns_peer_getudpsize(peer, &udpsize);
10096 (void)dns_peer_getrequestnsid(peer, &reqnsid);
10100 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10101 result = add_opt(message, udpsize, reqnsid);
10102 if (result != ISC_R_SUCCESS)
10103 zone_debuglog(zone, me, 1,
10104 "unable to add opt record: %s",
10105 dns_result_totext(result));
10109 * Always use TCP so that we shouldn't truncate in additional section.
10111 switch (isc_sockaddr_pf(&zone->masteraddr)) {
10112 case PF_INET:
10113 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10114 zone->sourceaddr = zone->altxfrsource4;
10115 else if (!have_xfrsource)
10116 zone->sourceaddr = zone->xfrsource4;
10117 break;
10118 case PF_INET6:
10119 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
10120 zone->sourceaddr = zone->altxfrsource6;
10121 else if (!have_xfrsource)
10122 zone->sourceaddr = zone->xfrsource6;
10123 break;
10124 default:
10125 result = ISC_R_NOTIMPLEMENTED;
10126 goto cleanup;
10128 timeout = 15;
10129 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
10130 timeout = 30;
10131 result = dns_request_createvia2(zone->view->requestmgr, message,
10132 &zone->sourceaddr, &zone->masteraddr,
10133 DNS_REQUESTOPT_TCP, key, timeout * 3,
10134 timeout, zone->task, stub_callback,
10135 stub, &zone->request);
10136 if (result != ISC_R_SUCCESS) {
10137 zone_debuglog(zone, me, 1,
10138 "dns_request_createvia() failed: %s",
10139 dns_result_totext(result));
10140 goto cleanup;
10142 dns_message_destroy(&message);
10143 goto unlock;
10145 cleanup:
10146 cancel_refresh(zone);
10147 if (stub != NULL) {
10148 stub->magic = 0;
10149 if (stub->version != NULL)
10150 dns_db_closeversion(stub->db, &stub->version,
10151 ISC_FALSE);
10152 if (stub->db != NULL)
10153 dns_db_detach(&stub->db);
10154 if (stub->zone != NULL)
10155 zone_idetach(&stub->zone);
10156 isc_mem_put(stub->mctx, stub, sizeof(*stub));
10158 if (message != NULL)
10159 dns_message_destroy(&message);
10160 unlock:
10161 if (key != NULL)
10162 dns_tsigkey_detach(&key);
10163 UNLOCK_ZONE(zone);
10164 return;
10168 * Handle the control event. Note that although this event causes the zone
10169 * to shut down, it is not a shutdown event in the sense of the task library.
10171 static void
10172 zone_shutdown(isc_task_t *task, isc_event_t *event) {
10173 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
10174 isc_boolean_t free_needed, linked = ISC_FALSE;
10176 UNUSED(task);
10177 REQUIRE(DNS_ZONE_VALID(zone));
10178 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
10179 INSIST(isc_refcount_current(&zone->erefs) == 0);
10180 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
10183 * Stop things being restarted after we cancel them below.
10185 LOCK_ZONE(zone);
10186 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
10187 UNLOCK_ZONE(zone);
10190 * If we were waiting for xfrin quota, step out of
10191 * the queue.
10192 * If there's no zone manager, we can't be waiting for the
10193 * xfrin quota
10195 if (zone->zmgr != NULL) {
10196 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10197 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
10198 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
10199 statelink);
10200 linked = ISC_TRUE;
10201 zone->statelist = NULL;
10203 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
10207 * In task context, no locking required. See zone_xfrdone().
10209 if (zone->xfr != NULL)
10210 dns_xfrin_shutdown(zone->xfr);
10212 LOCK_ZONE(zone);
10213 if (linked) {
10214 INSIST(zone->irefs > 0);
10215 zone->irefs--;
10217 if (zone->request != NULL) {
10218 dns_request_cancel(zone->request);
10221 if (zone->readio != NULL)
10222 zonemgr_cancelio(zone->readio);
10224 if (zone->lctx != NULL)
10225 dns_loadctx_cancel(zone->lctx);
10227 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10228 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10229 if (zone->writeio != NULL)
10230 zonemgr_cancelio(zone->writeio);
10232 if (zone->dctx != NULL)
10233 dns_dumpctx_cancel(zone->dctx);
10236 notify_cancel(zone);
10238 if (zone->timer != NULL) {
10239 isc_timer_detach(&zone->timer);
10240 INSIST(zone->irefs > 0);
10241 zone->irefs--;
10244 if (zone->view != NULL)
10245 dns_view_weakdetach(&zone->view);
10248 * We have now canceled everything set the flag to allow exit_check()
10249 * to succeed. We must not unlock between setting this flag and
10250 * calling exit_check().
10252 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
10253 free_needed = exit_check(zone);
10254 UNLOCK_ZONE(zone);
10255 if (free_needed)
10256 zone_free(zone);
10259 static void
10260 zone_timer(isc_task_t *task, isc_event_t *event) {
10261 const char me[] = "zone_timer";
10262 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
10264 UNUSED(task);
10265 REQUIRE(DNS_ZONE_VALID(zone));
10267 ENTER;
10269 zone_maintenance(zone);
10271 isc_event_free(&event);
10274 static void
10275 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
10276 const char me[] = "zone_settimer";
10277 isc_time_t next;
10278 isc_result_t result;
10280 ENTER;
10281 REQUIRE(DNS_ZONE_VALID(zone));
10282 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10283 return;
10285 isc_time_settoepoch(&next);
10287 switch (zone->type) {
10288 case dns_zone_master:
10289 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10290 next = zone->notifytime;
10291 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10292 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10293 INSIST(!isc_time_isepoch(&zone->dumptime));
10294 if (isc_time_isepoch(&next) ||
10295 isc_time_compare(&zone->dumptime, &next) < 0)
10296 next = zone->dumptime;
10298 if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN) &&
10299 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10300 if (isc_time_isepoch(&next) ||
10301 (!isc_time_isepoch(&zone->refreshkeytime) &&
10302 isc_time_compare(&zone->refreshkeytime, &next) < 0))
10303 next = zone->refreshkeytime;
10305 if (!isc_time_isepoch(&zone->resigntime)) {
10306 if (isc_time_isepoch(&next) ||
10307 isc_time_compare(&zone->resigntime, &next) < 0)
10308 next = zone->resigntime;
10310 if (!isc_time_isepoch(&zone->keywarntime)) {
10311 if (isc_time_isepoch(&next) ||
10312 isc_time_compare(&zone->keywarntime, &next) < 0)
10313 next = zone->keywarntime;
10315 if (!isc_time_isepoch(&zone->signingtime)) {
10316 if (isc_time_isepoch(&next) ||
10317 isc_time_compare(&zone->signingtime, &next) < 0)
10318 next = zone->signingtime;
10320 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
10321 if (isc_time_isepoch(&next) ||
10322 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
10323 next = zone->nsec3chaintime;
10325 break;
10327 case dns_zone_slave:
10328 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
10329 next = zone->notifytime;
10330 /*FALLTHROUGH*/
10332 case dns_zone_stub:
10333 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
10334 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
10335 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
10336 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
10337 INSIST(!isc_time_isepoch(&zone->refreshtime));
10338 if (isc_time_isepoch(&next) ||
10339 isc_time_compare(&zone->refreshtime, &next) < 0)
10340 next = zone->refreshtime;
10342 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10343 INSIST(!isc_time_isepoch(&zone->expiretime));
10344 if (isc_time_isepoch(&next) ||
10345 isc_time_compare(&zone->expiretime, &next) < 0)
10346 next = zone->expiretime;
10348 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10349 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10350 INSIST(!isc_time_isepoch(&zone->dumptime));
10351 if (isc_time_isepoch(&next) ||
10352 isc_time_compare(&zone->dumptime, &next) < 0)
10353 next = zone->dumptime;
10355 break;
10357 case dns_zone_key:
10358 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10359 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10360 INSIST(!isc_time_isepoch(&zone->dumptime));
10361 if (isc_time_isepoch(&next) ||
10362 isc_time_compare(&zone->dumptime, &next) < 0)
10363 next = zone->dumptime;
10365 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10366 if (isc_time_isepoch(&next) ||
10367 (!isc_time_isepoch(&zone->refreshkeytime) &&
10368 isc_time_compare(&zone->refreshkeytime, &next) < 0))
10369 next = zone->refreshkeytime;
10371 break;
10373 default:
10374 break;
10377 if (isc_time_isepoch(&next)) {
10378 zone_debuglog(zone, me, 10, "settimer inactive");
10379 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
10380 NULL, NULL, ISC_TRUE);
10381 if (result != ISC_R_SUCCESS)
10382 dns_zone_log(zone, ISC_LOG_ERROR,
10383 "could not deactivate zone timer: %s",
10384 isc_result_totext(result));
10385 } else {
10386 if (isc_time_compare(&next, now) <= 0)
10387 next = *now;
10388 result = isc_timer_reset(zone->timer, isc_timertype_once,
10389 &next, NULL, ISC_TRUE);
10390 if (result != ISC_R_SUCCESS)
10391 dns_zone_log(zone, ISC_LOG_ERROR,
10392 "could not reset zone timer: %s",
10393 isc_result_totext(result));
10397 static void
10398 cancel_refresh(dns_zone_t *zone) {
10399 const char me[] = "cancel_refresh";
10400 isc_time_t now;
10403 * 'zone' locked by caller.
10406 REQUIRE(DNS_ZONE_VALID(zone));
10407 REQUIRE(LOCKED_ZONE(zone));
10409 ENTER;
10411 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10412 TIME_NOW(&now);
10413 zone_settimer(zone, &now);
10416 static isc_result_t
10417 notify_createmessage(dns_zone_t *zone, unsigned int flags,
10418 dns_message_t **messagep)
10420 dns_db_t *zonedb = NULL;
10421 dns_dbnode_t *node = NULL;
10422 dns_dbversion_t *version = NULL;
10423 dns_message_t *message = NULL;
10424 dns_rdataset_t rdataset;
10425 dns_rdata_t rdata = DNS_RDATA_INIT;
10427 dns_name_t *tempname = NULL;
10428 dns_rdata_t *temprdata = NULL;
10429 dns_rdatalist_t *temprdatalist = NULL;
10430 dns_rdataset_t *temprdataset = NULL;
10432 isc_result_t result;
10433 isc_region_t r;
10434 isc_buffer_t *b = NULL;
10436 REQUIRE(DNS_ZONE_VALID(zone));
10437 REQUIRE(messagep != NULL && *messagep == NULL);
10439 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
10440 &message);
10441 if (result != ISC_R_SUCCESS)
10442 return (result);
10444 message->opcode = dns_opcode_notify;
10445 message->flags |= DNS_MESSAGEFLAG_AA;
10446 message->rdclass = zone->rdclass;
10448 result = dns_message_gettempname(message, &tempname);
10449 if (result != ISC_R_SUCCESS)
10450 goto cleanup;
10452 result = dns_message_gettemprdataset(message, &temprdataset);
10453 if (result != ISC_R_SUCCESS)
10454 goto cleanup;
10457 * Make question.
10459 dns_name_init(tempname, NULL);
10460 dns_name_clone(&zone->origin, tempname);
10461 dns_rdataset_init(temprdataset);
10462 dns_rdataset_makequestion(temprdataset, zone->rdclass,
10463 dns_rdatatype_soa);
10464 ISC_LIST_APPEND(tempname->list, temprdataset, link);
10465 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
10466 tempname = NULL;
10467 temprdataset = NULL;
10469 if ((flags & DNS_NOTIFY_NOSOA) != 0)
10470 goto done;
10472 result = dns_message_gettempname(message, &tempname);
10473 if (result != ISC_R_SUCCESS)
10474 goto soa_cleanup;
10475 result = dns_message_gettemprdata(message, &temprdata);
10476 if (result != ISC_R_SUCCESS)
10477 goto soa_cleanup;
10478 result = dns_message_gettemprdataset(message, &temprdataset);
10479 if (result != ISC_R_SUCCESS)
10480 goto soa_cleanup;
10481 result = dns_message_gettemprdatalist(message, &temprdatalist);
10482 if (result != ISC_R_SUCCESS)
10483 goto soa_cleanup;
10485 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10486 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
10487 dns_db_attach(zone->db, &zonedb);
10488 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10490 dns_name_init(tempname, NULL);
10491 dns_name_clone(&zone->origin, tempname);
10492 dns_db_currentversion(zonedb, &version);
10493 result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
10494 if (result != ISC_R_SUCCESS)
10495 goto soa_cleanup;
10497 dns_rdataset_init(&rdataset);
10498 result = dns_db_findrdataset(zonedb, node, version,
10499 dns_rdatatype_soa,
10500 dns_rdatatype_none, 0, &rdataset,
10501 NULL);
10502 if (result != ISC_R_SUCCESS)
10503 goto soa_cleanup;
10504 result = dns_rdataset_first(&rdataset);
10505 if (result != ISC_R_SUCCESS)
10506 goto soa_cleanup;
10507 dns_rdataset_current(&rdataset, &rdata);
10508 dns_rdata_toregion(&rdata, &r);
10509 result = isc_buffer_allocate(zone->mctx, &b, r.length);
10510 if (result != ISC_R_SUCCESS)
10511 goto soa_cleanup;
10512 isc_buffer_putmem(b, r.base, r.length);
10513 isc_buffer_usedregion(b, &r);
10514 dns_rdata_init(temprdata);
10515 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
10516 dns_message_takebuffer(message, &b);
10517 result = dns_rdataset_next(&rdataset);
10518 dns_rdataset_disassociate(&rdataset);
10519 if (result != ISC_R_NOMORE)
10520 goto soa_cleanup;
10521 temprdatalist->rdclass = rdata.rdclass;
10522 temprdatalist->type = rdata.type;
10523 temprdatalist->covers = 0;
10524 temprdatalist->ttl = rdataset.ttl;
10525 ISC_LIST_INIT(temprdatalist->rdata);
10526 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
10528 dns_rdataset_init(temprdataset);
10529 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
10530 if (result != ISC_R_SUCCESS)
10531 goto soa_cleanup;
10533 ISC_LIST_APPEND(tempname->list, temprdataset, link);
10534 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
10535 temprdatalist = NULL;
10536 temprdataset = NULL;
10537 temprdata = NULL;
10538 tempname = NULL;
10540 soa_cleanup:
10541 if (node != NULL)
10542 dns_db_detachnode(zonedb, &node);
10543 if (version != NULL)
10544 dns_db_closeversion(zonedb, &version, ISC_FALSE);
10545 if (zonedb != NULL)
10546 dns_db_detach(&zonedb);
10547 if (tempname != NULL)
10548 dns_message_puttempname(message, &tempname);
10549 if (temprdata != NULL)
10550 dns_message_puttemprdata(message, &temprdata);
10551 if (temprdataset != NULL)
10552 dns_message_puttemprdataset(message, &temprdataset);
10553 if (temprdatalist != NULL)
10554 dns_message_puttemprdatalist(message, &temprdatalist);
10556 done:
10557 *messagep = message;
10558 return (ISC_R_SUCCESS);
10560 cleanup:
10561 if (tempname != NULL)
10562 dns_message_puttempname(message, &tempname);
10563 if (temprdataset != NULL)
10564 dns_message_puttemprdataset(message, &temprdataset);
10565 dns_message_destroy(&message);
10566 return (result);
10569 isc_result_t
10570 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
10571 dns_message_t *msg)
10573 unsigned int i;
10574 dns_rdata_soa_t soa;
10575 dns_rdataset_t *rdataset = NULL;
10576 dns_rdata_t rdata = DNS_RDATA_INIT;
10577 isc_result_t result;
10578 char fromtext[ISC_SOCKADDR_FORMATSIZE];
10579 int match = 0;
10580 isc_netaddr_t netaddr;
10582 REQUIRE(DNS_ZONE_VALID(zone));
10585 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
10586 * ROLLOVER.
10588 * SOA: RFC1996
10589 * Check that 'from' is a valid notify source, (zone->masters).
10590 * Return DNS_R_REFUSED if not.
10592 * If the notify message contains a serial number check it
10593 * against the zones serial and return if <= current serial
10595 * If a refresh check is progress, if so just record the
10596 * fact we received a NOTIFY and from where and return.
10597 * We will perform a new refresh check when the current one
10598 * completes. Return ISC_R_SUCCESS.
10600 * Otherwise initiate a refresh check using 'from' as the
10601 * first address to check. Return ISC_R_SUCCESS.
10604 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
10607 * We only handle NOTIFY (SOA) at the present.
10609 LOCK_ZONE(zone);
10610 if (isc_sockaddr_pf(from) == PF_INET)
10611 inc_stats(zone, dns_zonestatscounter_notifyinv4);
10612 else
10613 inc_stats(zone, dns_zonestatscounter_notifyinv6);
10614 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
10615 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
10616 dns_rdatatype_soa, dns_rdatatype_none,
10617 NULL, NULL) != ISC_R_SUCCESS) {
10618 UNLOCK_ZONE(zone);
10619 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
10620 dns_zone_log(zone, ISC_LOG_NOTICE,
10621 "NOTIFY with no "
10622 "question section from: %s", fromtext);
10623 return (DNS_R_FORMERR);
10625 dns_zone_log(zone, ISC_LOG_NOTICE,
10626 "NOTIFY zone does not match");
10627 return (DNS_R_NOTIMP);
10631 * If we are a master zone just succeed.
10633 if (zone->type == dns_zone_master) {
10634 UNLOCK_ZONE(zone);
10635 return (ISC_R_SUCCESS);
10638 isc_netaddr_fromsockaddr(&netaddr, from);
10639 for (i = 0; i < zone->masterscnt; i++) {
10640 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
10641 break;
10642 if (zone->view->aclenv.match_mapped &&
10643 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
10644 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
10645 isc_netaddr_t na1, na2;
10646 isc_netaddr_fromv4mapped(&na1, &netaddr);
10647 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
10648 if (isc_netaddr_equal(&na1, &na2))
10649 break;
10654 * Accept notify requests from non masters if they are on
10655 * 'zone->notify_acl'.
10657 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
10658 dns_acl_match(&netaddr, NULL, zone->notify_acl,
10659 &zone->view->aclenv,
10660 &match, NULL) == ISC_R_SUCCESS &&
10661 match > 0)
10663 /* Accept notify. */
10664 } else if (i >= zone->masterscnt) {
10665 UNLOCK_ZONE(zone);
10666 dns_zone_log(zone, ISC_LOG_INFO,
10667 "refused notify from non-master: %s", fromtext);
10668 inc_stats(zone, dns_zonestatscounter_notifyrej);
10669 return (DNS_R_REFUSED);
10673 * If the zone is loaded and there are answers check the serial
10674 * to see if we need to do a refresh. Do not worry about this
10675 * check if we are a dialup zone as we use the notify request
10676 * to trigger a refresh check.
10678 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
10679 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10680 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
10681 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
10682 &zone->origin,
10683 dns_rdatatype_soa,
10684 dns_rdatatype_none, NULL,
10685 &rdataset);
10686 if (result == ISC_R_SUCCESS)
10687 result = dns_rdataset_first(rdataset);
10688 if (result == ISC_R_SUCCESS) {
10689 isc_uint32_t serial = 0, oldserial;
10691 dns_rdataset_current(rdataset, &rdata);
10692 result = dns_rdata_tostruct(&rdata, &soa, NULL);
10693 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10694 serial = soa.serial;
10696 * The following should safely be performed without DB
10697 * lock and succeed in this context.
10699 result = zone_get_from_db(zone, zone->db, NULL, NULL,
10700 &oldserial, NULL, NULL, NULL,
10701 NULL, NULL);
10702 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10703 if (isc_serial_le(serial, oldserial)) {
10704 dns_zone_log(zone, ISC_LOG_INFO,
10705 "notify from %s: "
10706 "zone is up to date",
10707 fromtext);
10708 UNLOCK_ZONE(zone);
10709 return (ISC_R_SUCCESS);
10715 * If we got this far and there was a refresh in progress just
10716 * let it complete. Record where we got the notify from so we
10717 * can perform a refresh check when the current one completes
10719 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
10720 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
10721 zone->notifyfrom = *from;
10722 UNLOCK_ZONE(zone);
10723 dns_zone_log(zone, ISC_LOG_INFO,
10724 "notify from %s: refresh in progress, "
10725 "refresh check queued",
10726 fromtext);
10727 return (ISC_R_SUCCESS);
10729 zone->notifyfrom = *from;
10730 UNLOCK_ZONE(zone);
10731 dns_zone_refresh(zone);
10732 return (ISC_R_SUCCESS);
10735 void
10736 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
10738 REQUIRE(DNS_ZONE_VALID(zone));
10740 LOCK_ZONE(zone);
10741 if (zone->notify_acl != NULL)
10742 dns_acl_detach(&zone->notify_acl);
10743 dns_acl_attach(acl, &zone->notify_acl);
10744 UNLOCK_ZONE(zone);
10747 void
10748 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
10750 REQUIRE(DNS_ZONE_VALID(zone));
10752 LOCK_ZONE(zone);
10753 if (zone->query_acl != NULL)
10754 dns_acl_detach(&zone->query_acl);
10755 dns_acl_attach(acl, &zone->query_acl);
10756 UNLOCK_ZONE(zone);
10759 void
10760 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
10762 REQUIRE(DNS_ZONE_VALID(zone));
10764 LOCK_ZONE(zone);
10765 if (zone->queryon_acl != NULL)
10766 dns_acl_detach(&zone->queryon_acl);
10767 dns_acl_attach(acl, &zone->queryon_acl);
10768 UNLOCK_ZONE(zone);
10771 void
10772 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
10774 REQUIRE(DNS_ZONE_VALID(zone));
10776 LOCK_ZONE(zone);
10777 if (zone->update_acl != NULL)
10778 dns_acl_detach(&zone->update_acl);
10779 dns_acl_attach(acl, &zone->update_acl);
10780 UNLOCK_ZONE(zone);
10783 void
10784 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
10786 REQUIRE(DNS_ZONE_VALID(zone));
10788 LOCK_ZONE(zone);
10789 if (zone->forward_acl != NULL)
10790 dns_acl_detach(&zone->forward_acl);
10791 dns_acl_attach(acl, &zone->forward_acl);
10792 UNLOCK_ZONE(zone);
10795 void
10796 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
10798 REQUIRE(DNS_ZONE_VALID(zone));
10800 LOCK_ZONE(zone);
10801 if (zone->xfr_acl != NULL)
10802 dns_acl_detach(&zone->xfr_acl);
10803 dns_acl_attach(acl, &zone->xfr_acl);
10804 UNLOCK_ZONE(zone);
10807 dns_acl_t *
10808 dns_zone_getnotifyacl(dns_zone_t *zone) {
10810 REQUIRE(DNS_ZONE_VALID(zone));
10812 return (zone->notify_acl);
10815 dns_acl_t *
10816 dns_zone_getqueryacl(dns_zone_t *zone) {
10818 REQUIRE(DNS_ZONE_VALID(zone));
10820 return (zone->query_acl);
10823 dns_acl_t *
10824 dns_zone_getqueryonacl(dns_zone_t *zone) {
10826 REQUIRE(DNS_ZONE_VALID(zone));
10828 return (zone->queryon_acl);
10831 dns_acl_t *
10832 dns_zone_getupdateacl(dns_zone_t *zone) {
10834 REQUIRE(DNS_ZONE_VALID(zone));
10836 return (zone->update_acl);
10839 dns_acl_t *
10840 dns_zone_getforwardacl(dns_zone_t *zone) {
10842 REQUIRE(DNS_ZONE_VALID(zone));
10844 return (zone->forward_acl);
10847 dns_acl_t *
10848 dns_zone_getxfracl(dns_zone_t *zone) {
10850 REQUIRE(DNS_ZONE_VALID(zone));
10852 return (zone->xfr_acl);
10855 void
10856 dns_zone_clearupdateacl(dns_zone_t *zone) {
10858 REQUIRE(DNS_ZONE_VALID(zone));
10860 LOCK_ZONE(zone);
10861 if (zone->update_acl != NULL)
10862 dns_acl_detach(&zone->update_acl);
10863 UNLOCK_ZONE(zone);
10866 void
10867 dns_zone_clearforwardacl(dns_zone_t *zone) {
10869 REQUIRE(DNS_ZONE_VALID(zone));
10871 LOCK_ZONE(zone);
10872 if (zone->forward_acl != NULL)
10873 dns_acl_detach(&zone->forward_acl);
10874 UNLOCK_ZONE(zone);
10877 void
10878 dns_zone_clearnotifyacl(dns_zone_t *zone) {
10880 REQUIRE(DNS_ZONE_VALID(zone));
10882 LOCK_ZONE(zone);
10883 if (zone->notify_acl != NULL)
10884 dns_acl_detach(&zone->notify_acl);
10885 UNLOCK_ZONE(zone);
10888 void
10889 dns_zone_clearqueryacl(dns_zone_t *zone) {
10891 REQUIRE(DNS_ZONE_VALID(zone));
10893 LOCK_ZONE(zone);
10894 if (zone->query_acl != NULL)
10895 dns_acl_detach(&zone->query_acl);
10896 UNLOCK_ZONE(zone);
10899 void
10900 dns_zone_clearqueryonacl(dns_zone_t *zone) {
10902 REQUIRE(DNS_ZONE_VALID(zone));
10904 LOCK_ZONE(zone);
10905 if (zone->queryon_acl != NULL)
10906 dns_acl_detach(&zone->queryon_acl);
10907 UNLOCK_ZONE(zone);
10910 void
10911 dns_zone_clearxfracl(dns_zone_t *zone) {
10913 REQUIRE(DNS_ZONE_VALID(zone));
10915 LOCK_ZONE(zone);
10916 if (zone->xfr_acl != NULL)
10917 dns_acl_detach(&zone->xfr_acl);
10918 UNLOCK_ZONE(zone);
10921 isc_boolean_t
10922 dns_zone_getupdatedisabled(dns_zone_t *zone) {
10923 REQUIRE(DNS_ZONE_VALID(zone));
10924 return (zone->update_disabled);
10928 void
10929 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
10930 REQUIRE(DNS_ZONE_VALID(zone));
10931 zone->update_disabled = state;
10934 isc_boolean_t
10935 dns_zone_getzeronosoattl(dns_zone_t *zone) {
10936 REQUIRE(DNS_ZONE_VALID(zone));
10937 return (zone->zero_no_soa_ttl);
10941 void
10942 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
10943 REQUIRE(DNS_ZONE_VALID(zone));
10944 zone->zero_no_soa_ttl = state;
10947 void
10948 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
10950 REQUIRE(DNS_ZONE_VALID(zone));
10952 zone->check_names = severity;
10955 dns_severity_t
10956 dns_zone_getchecknames(dns_zone_t *zone) {
10958 REQUIRE(DNS_ZONE_VALID(zone));
10960 return (zone->check_names);
10963 void
10964 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
10966 REQUIRE(DNS_ZONE_VALID(zone));
10968 zone->journalsize = size;
10971 isc_int32_t
10972 dns_zone_getjournalsize(dns_zone_t *zone) {
10974 REQUIRE(DNS_ZONE_VALID(zone));
10976 return (zone->journalsize);
10979 static void
10980 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
10981 isc_result_t result = ISC_R_FAILURE;
10982 isc_buffer_t buffer;
10984 REQUIRE(buf != NULL);
10985 REQUIRE(length > 1U);
10988 * Leave space for terminating '\0'.
10990 isc_buffer_init(&buffer, buf, length - 1);
10991 if (dns_name_dynamic(&zone->origin))
10992 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
10993 if (result != ISC_R_SUCCESS &&
10994 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
10995 isc_buffer_putstr(&buffer, "<UNKNOWN>");
10997 if (isc_buffer_availablelength(&buffer) > 0)
10998 isc_buffer_putstr(&buffer, "/");
10999 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11001 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
11002 strcmp(zone->view->name, "_default") != 0 &&
11003 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
11004 isc_buffer_putstr(&buffer, "/");
11005 isc_buffer_putstr(&buffer, zone->view->name);
11008 buf[isc_buffer_usedlength(&buffer)] = '\0';
11011 static void
11012 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
11013 isc_result_t result = ISC_R_FAILURE;
11014 isc_buffer_t buffer;
11016 REQUIRE(buf != NULL);
11017 REQUIRE(length > 1U);
11020 * Leave space for terminating '\0'.
11022 isc_buffer_init(&buffer, buf, length - 1);
11023 if (dns_name_dynamic(&zone->origin))
11024 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
11025 if (result != ISC_R_SUCCESS &&
11026 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
11027 isc_buffer_putstr(&buffer, "<UNKNOWN>");
11029 buf[isc_buffer_usedlength(&buffer)] = '\0';
11032 static void
11033 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
11034 isc_buffer_t buffer;
11036 REQUIRE(buf != NULL);
11037 REQUIRE(length > 1U);
11040 * Leave space for terminating '\0'.
11042 isc_buffer_init(&buffer, buf, length - 1);
11043 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
11045 buf[isc_buffer_usedlength(&buffer)] = '\0';
11048 static void
11049 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
11050 isc_buffer_t buffer;
11052 REQUIRE(buf != NULL);
11053 REQUIRE(length > 1U);
11057 * Leave space for terminating '\0'.
11059 isc_buffer_init(&buffer, buf, length - 1);
11061 if (zone->view == NULL) {
11062 isc_buffer_putstr(&buffer, "_none");
11063 } else if (strlen(zone->view->name)
11064 < isc_buffer_availablelength(&buffer)) {
11065 isc_buffer_putstr(&buffer, zone->view->name);
11066 } else {
11067 isc_buffer_putstr(&buffer, "_toolong");
11070 buf[isc_buffer_usedlength(&buffer)] = '\0';
11073 void
11074 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
11075 REQUIRE(DNS_ZONE_VALID(zone));
11076 REQUIRE(buf != NULL);
11077 zone_namerd_tostr(zone, buf, length);
11080 static void
11081 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11082 va_list ap;
11083 char message[4096];
11085 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11086 return;
11088 va_start(ap, fmt);
11089 vsnprintf(message, sizeof(message), fmt, ap);
11090 va_end(ap);
11091 isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
11092 level, "zone %s: %s", zone->strnamerd, message);
11095 void
11096 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
11097 int level, const char *fmt, ...) {
11098 va_list ap;
11099 char message[4096];
11101 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11102 return;
11104 va_start(ap, fmt);
11105 vsnprintf(message, sizeof(message), fmt, ap);
11106 va_end(ap);
11107 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
11108 level, "zone %s: %s", zone->strnamerd, message);
11111 void
11112 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
11113 va_list ap;
11114 char message[4096];
11116 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11117 return;
11119 va_start(ap, fmt);
11120 vsnprintf(message, sizeof(message), fmt, ap);
11121 va_end(ap);
11122 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11123 level, "zone %s: %s", zone->strnamerd, message);
11126 static void
11127 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
11128 const char *fmt, ...)
11130 va_list ap;
11131 char message[4096];
11132 int level = ISC_LOG_DEBUG(debuglevel);
11134 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
11135 return;
11137 va_start(ap, fmt);
11138 vsnprintf(message, sizeof(message), fmt, ap);
11139 va_end(ap);
11140 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
11141 level, "%s: zone %s: %s", me, zone->strnamerd, message);
11144 static int
11145 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
11147 isc_result_t result;
11148 dns_name_t *name;
11149 dns_rdataset_t *curr;
11150 int count = 0;
11152 result = dns_message_firstname(msg, section);
11153 while (result == ISC_R_SUCCESS) {
11154 name = NULL;
11155 dns_message_currentname(msg, section, &name);
11157 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
11158 curr = ISC_LIST_PREV(curr, link)) {
11159 if (curr->type == type)
11160 count++;
11162 result = dns_message_nextname(msg, section);
11165 return (count);
11168 void
11169 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
11170 REQUIRE(DNS_ZONE_VALID(zone));
11172 zone->maxxfrin = maxxfrin;
11175 isc_uint32_t
11176 dns_zone_getmaxxfrin(dns_zone_t *zone) {
11177 REQUIRE(DNS_ZONE_VALID(zone));
11179 return (zone->maxxfrin);
11182 void
11183 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
11184 REQUIRE(DNS_ZONE_VALID(zone));
11185 zone->maxxfrout = maxxfrout;
11188 isc_uint32_t
11189 dns_zone_getmaxxfrout(dns_zone_t *zone) {
11190 REQUIRE(DNS_ZONE_VALID(zone));
11192 return (zone->maxxfrout);
11195 dns_zonetype_t
11196 dns_zone_gettype(dns_zone_t *zone) {
11197 REQUIRE(DNS_ZONE_VALID(zone));
11199 return (zone->type);
11202 dns_name_t *
11203 dns_zone_getorigin(dns_zone_t *zone) {
11204 REQUIRE(DNS_ZONE_VALID(zone));
11206 return (&zone->origin);
11209 void
11210 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
11211 REQUIRE(DNS_ZONE_VALID(zone));
11213 LOCK_ZONE(zone);
11214 if (zone->task != NULL)
11215 isc_task_detach(&zone->task);
11216 isc_task_attach(task, &zone->task);
11217 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11218 if (zone->db != NULL)
11219 dns_db_settask(zone->db, zone->task);
11220 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11221 UNLOCK_ZONE(zone);
11224 void
11225 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
11226 REQUIRE(DNS_ZONE_VALID(zone));
11227 isc_task_attach(zone->task, target);
11230 void
11231 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
11232 REQUIRE(DNS_ZONE_VALID(zone));
11234 if (idlein == 0)
11235 idlein = DNS_DEFAULT_IDLEIN;
11236 zone->idlein = idlein;
11239 isc_uint32_t
11240 dns_zone_getidlein(dns_zone_t *zone) {
11241 REQUIRE(DNS_ZONE_VALID(zone));
11243 return (zone->idlein);
11246 void
11247 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
11248 REQUIRE(DNS_ZONE_VALID(zone));
11250 zone->idleout = idleout;
11253 isc_uint32_t
11254 dns_zone_getidleout(dns_zone_t *zone) {
11255 REQUIRE(DNS_ZONE_VALID(zone));
11257 return (zone->idleout);
11260 static void
11261 notify_done(isc_task_t *task, isc_event_t *event) {
11262 dns_requestevent_t *revent = (dns_requestevent_t *)event;
11263 dns_notify_t *notify;
11264 isc_result_t result;
11265 dns_message_t *message = NULL;
11266 isc_buffer_t buf;
11267 char rcode[128];
11268 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11270 UNUSED(task);
11272 notify = event->ev_arg;
11273 REQUIRE(DNS_NOTIFY_VALID(notify));
11274 INSIST(task == notify->zone->task);
11276 isc_buffer_init(&buf, rcode, sizeof(rcode));
11277 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
11279 result = revent->result;
11280 if (result == ISC_R_SUCCESS)
11281 result = dns_message_create(notify->zone->mctx,
11282 DNS_MESSAGE_INTENTPARSE, &message);
11283 if (result == ISC_R_SUCCESS)
11284 result = dns_request_getresponse(revent->request, message,
11285 DNS_MESSAGEPARSE_PRESERVEORDER);
11286 if (result == ISC_R_SUCCESS)
11287 result = dns_rcode_totext(message->rcode, &buf);
11288 if (result == ISC_R_SUCCESS)
11289 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11290 "notify response from %s: %.*s",
11291 addrbuf, (int)buf.used, rcode);
11292 else
11293 notify_log(notify->zone, ISC_LOG_DEBUG(2),
11294 "notify to %s failed: %s", addrbuf,
11295 dns_result_totext(result));
11298 * Old bind's return formerr if they see a soa record. Retry w/o
11299 * the soa if we see a formerr and had sent a SOA.
11301 isc_event_free(&event);
11302 if (message != NULL && message->rcode == dns_rcode_formerr &&
11303 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
11304 notify->flags |= DNS_NOTIFY_NOSOA;
11305 dns_request_destroy(&notify->request);
11306 result = notify_send_queue(notify);
11307 if (result != ISC_R_SUCCESS)
11308 notify_destroy(notify, ISC_FALSE);
11309 } else {
11310 if (result == ISC_R_TIMEDOUT)
11311 notify_log(notify->zone, ISC_LOG_DEBUG(1),
11312 "notify to %s: retries exceeded", addrbuf);
11313 notify_destroy(notify, ISC_FALSE);
11315 if (message != NULL)
11316 dns_message_destroy(&message);
11319 isc_result_t
11320 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11321 isc_result_t result;
11323 REQUIRE(DNS_ZONE_VALID(zone));
11324 LOCK_ZONE(zone);
11325 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11326 result = zone_replacedb(zone, db, dump);
11327 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11328 UNLOCK_ZONE(zone);
11329 return (result);
11332 static isc_result_t
11333 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
11334 dns_dbversion_t *ver;
11335 isc_result_t result;
11336 unsigned int soacount = 0;
11337 unsigned int nscount = 0;
11340 * 'zone' and 'zonedb' locked by caller.
11342 REQUIRE(DNS_ZONE_VALID(zone));
11343 REQUIRE(LOCKED_ZONE(zone));
11345 result = zone_get_from_db(zone, db, &nscount, &soacount,
11346 NULL, NULL, NULL, NULL, NULL, NULL);
11347 if (result == ISC_R_SUCCESS) {
11348 if (soacount != 1) {
11349 dns_zone_log(zone, ISC_LOG_ERROR,
11350 "has %d SOA records", soacount);
11351 result = DNS_R_BADZONE;
11353 if (nscount == 0 && zone->type != dns_zone_key) {
11354 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
11355 result = DNS_R_BADZONE;
11357 if (result != ISC_R_SUCCESS)
11358 return (result);
11359 } else {
11360 dns_zone_log(zone, ISC_LOG_ERROR,
11361 "retrieving SOA and NS records failed: %s",
11362 dns_result_totext(result));
11363 return (result);
11366 result = check_nsec3param(zone, db);
11367 if (result != ISC_R_SUCCESS)
11368 return (result);
11370 ver = NULL;
11371 dns_db_currentversion(db, &ver);
11374 * The initial version of a slave zone is always dumped;
11375 * subsequent versions may be journaled instead if this
11376 * is enabled in the configuration.
11378 if (zone->db != NULL && zone->journal != NULL &&
11379 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
11380 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
11381 isc_uint32_t serial, oldserial;
11383 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
11385 result = dns_db_getsoaserial(db, ver, &serial);
11386 if (result != ISC_R_SUCCESS) {
11387 dns_zone_log(zone, ISC_LOG_ERROR,
11388 "ixfr-from-differences: unable to get "
11389 "new serial");
11390 goto fail;
11394 * This is checked in zone_postload() for master zones.
11396 result = zone_get_from_db(zone, zone->db, NULL, NULL,
11397 &oldserial, NULL, NULL, NULL, NULL,
11398 NULL);
11399 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11400 if (zone->type == dns_zone_slave &&
11401 !isc_serial_gt(serial, oldserial)) {
11402 isc_uint32_t serialmin, serialmax;
11403 serialmin = (oldserial + 1) & 0xffffffffU;
11404 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
11405 dns_zone_log(zone, ISC_LOG_ERROR,
11406 "ixfr-from-differences: failed: "
11407 "new serial (%u) out of range [%u - %u]",
11408 serial, serialmin, serialmax);
11409 result = ISC_R_RANGE;
11410 goto fail;
11413 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
11414 zone->journal);
11415 if (result != ISC_R_SUCCESS)
11416 goto fail;
11417 if (dump)
11418 zone_needdump(zone, DNS_DUMP_DELAY);
11419 else if (zone->journalsize != -1) {
11420 result = dns_journal_compact(zone->mctx, zone->journal,
11421 serial, zone->journalsize);
11422 switch (result) {
11423 case ISC_R_SUCCESS:
11424 case ISC_R_NOSPACE:
11425 case ISC_R_NOTFOUND:
11426 dns_zone_log(zone, ISC_LOG_DEBUG(3),
11427 "dns_journal_compact: %s",
11428 dns_result_totext(result));
11429 break;
11430 default:
11431 dns_zone_log(zone, ISC_LOG_ERROR,
11432 "dns_journal_compact failed: %s",
11433 dns_result_totext(result));
11434 break;
11437 } else {
11438 if (dump && zone->masterfile != NULL) {
11439 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11440 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11441 "dumping new zone version");
11442 result = dns_db_dump2(db, ver, zone->masterfile,
11443 zone->masterformat);
11444 if (result != ISC_R_SUCCESS)
11445 goto fail;
11448 * Update the time the zone was updated, so
11449 * dns_zone_load can avoid loading it when
11450 * the server is reloaded. If isc_time_now
11451 * fails for some reason, all that happens is
11452 * the timestamp is not updated.
11454 TIME_NOW(&zone->loadtime);
11457 if (dump && zone->journal != NULL) {
11459 * The in-memory database just changed, and
11460 * because 'dump' is set, it didn't change by
11461 * being loaded from disk. Also, we have not
11462 * journaled diffs for this change.
11463 * Therefore, the on-disk journal is missing
11464 * the deltas for this change. Since it can
11465 * no longer be used to bring the zone
11466 * up-to-date, it is useless and should be
11467 * removed.
11469 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11470 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11471 "removing journal file");
11472 if (remove(zone->journal) < 0 && errno != ENOENT) {
11473 char strbuf[ISC_STRERRORSIZE];
11474 isc__strerror(errno, strbuf, sizeof(strbuf));
11475 isc_log_write(dns_lctx,
11476 DNS_LOGCATEGORY_GENERAL,
11477 DNS_LOGMODULE_ZONE,
11478 ISC_LOG_WARNING,
11479 "unable to remove journal "
11480 "'%s': '%s'",
11481 zone->journal, strbuf);
11486 dns_db_closeversion(db, &ver, ISC_FALSE);
11488 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
11489 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
11490 "replacing zone database");
11492 if (zone->db != NULL)
11493 zone_detachdb(zone);
11494 zone_attachdb(zone, db);
11495 dns_db_settask(zone->db, zone->task);
11496 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
11497 return (ISC_R_SUCCESS);
11499 fail:
11500 dns_db_closeversion(db, &ver, ISC_FALSE);
11501 return (result);
11504 /* The caller must hold the dblock as a writer. */
11505 static inline void
11506 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
11507 REQUIRE(zone->db == NULL && db != NULL);
11509 dns_db_attach(db, &zone->db);
11510 if (zone->acache != NULL) {
11511 isc_result_t result;
11512 result = dns_acache_setdb(zone->acache, db);
11513 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
11514 UNEXPECTED_ERROR(__FILE__, __LINE__,
11515 "dns_acache_setdb() failed: %s",
11516 isc_result_totext(result));
11521 /* The caller must hold the dblock as a writer. */
11522 static inline void
11523 zone_detachdb(dns_zone_t *zone) {
11524 REQUIRE(zone->db != NULL);
11526 if (zone->acache != NULL)
11527 (void)dns_acache_putdb(zone->acache, zone->db);
11528 dns_db_detach(&zone->db);
11531 static void
11532 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
11533 isc_time_t now;
11534 isc_boolean_t again = ISC_FALSE;
11535 unsigned int soacount;
11536 unsigned int nscount;
11537 isc_uint32_t serial, refresh, retry, expire, minimum;
11538 isc_result_t xfrresult = result;
11539 isc_boolean_t free_needed;
11541 REQUIRE(DNS_ZONE_VALID(zone));
11543 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11544 "zone transfer finished: %s", dns_result_totext(result));
11546 LOCK_ZONE(zone);
11547 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
11548 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11549 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
11551 TIME_NOW(&now);
11552 switch (result) {
11553 case ISC_R_SUCCESS:
11554 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11555 /*FALLTHROUGH*/
11556 case DNS_R_UPTODATE:
11557 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
11559 * Has the zone expired underneath us?
11561 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11562 if (zone->db == NULL) {
11563 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11564 goto same_master;
11568 * Update the zone structure's data from the actual
11569 * SOA received.
11571 nscount = 0;
11572 soacount = 0;
11573 INSIST(zone->db != NULL);
11574 result = zone_get_from_db(zone, zone->db, &nscount,
11575 &soacount, &serial, &refresh,
11576 &retry, &expire, &minimum, NULL);
11577 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11578 if (result == ISC_R_SUCCESS) {
11579 if (soacount != 1)
11580 dns_zone_log(zone, ISC_LOG_ERROR,
11581 "transferred zone "
11582 "has %d SOA record%s", soacount,
11583 (soacount != 0) ? "s" : "");
11584 if (nscount == 0) {
11585 dns_zone_log(zone, ISC_LOG_ERROR,
11586 "transferred zone "
11587 "has no NS records");
11588 if (DNS_ZONE_FLAG(zone,
11589 DNS_ZONEFLG_HAVETIMERS)) {
11590 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11591 zone->retry = DNS_ZONE_DEFAULTRETRY;
11593 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11594 zone_unload(zone);
11595 goto next_master;
11597 zone->refresh = RANGE(refresh, zone->minrefresh,
11598 zone->maxrefresh);
11599 zone->retry = RANGE(retry, zone->minretry,
11600 zone->maxretry);
11601 zone->expire = RANGE(expire,
11602 zone->refresh + zone->retry,
11603 DNS_MAX_EXPIRE);
11604 zone->minimum = minimum;
11605 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11609 * Set our next update/expire times.
11611 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11612 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11613 zone->refreshtime = now;
11614 DNS_ZONE_TIME_ADD(&now, zone->expire,
11615 &zone->expiretime);
11616 } else {
11617 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
11618 &zone->refreshtime);
11619 DNS_ZONE_TIME_ADD(&now, zone->expire,
11620 &zone->expiretime);
11622 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
11623 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
11624 if (zone->tsigkey != NULL) {
11625 char namebuf[DNS_NAME_FORMATSIZE];
11626 dns_name_format(&zone->tsigkey->name, namebuf,
11627 sizeof(namebuf));
11628 snprintf(buf, sizeof(buf), ": TSIG '%s'",
11629 namebuf);
11630 } else
11631 buf[0] = '\0';
11632 dns_zone_log(zone, ISC_LOG_INFO,
11633 "transferred serial %u%s",
11634 serial, buf);
11638 * This is not necessary if we just performed a AXFR
11639 * however it is necessary for an IXFR / UPTODATE and
11640 * won't hurt with an AXFR.
11642 if (zone->masterfile != NULL || zone->journal != NULL) {
11643 result = ISC_R_FAILURE;
11644 if (zone->journal != NULL)
11645 result = isc_file_settime(zone->journal, &now);
11646 if (result != ISC_R_SUCCESS &&
11647 zone->masterfile != NULL)
11648 result = isc_file_settime(zone->masterfile,
11649 &now);
11650 /* Someone removed the file from underneath us! */
11651 if (result == ISC_R_FILENOTFOUND &&
11652 zone->masterfile != NULL)
11653 zone_needdump(zone, DNS_DUMP_DELAY);
11654 else if (result != ISC_R_SUCCESS)
11655 dns_zone_log(zone, ISC_LOG_ERROR,
11656 "transfer: could not set file "
11657 "modification time of '%s': %s",
11658 zone->masterfile,
11659 dns_result_totext(result));
11662 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
11663 break;
11665 case DNS_R_BADIXFR:
11666 /* Force retry with AXFR. */
11667 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
11668 goto same_master;
11670 default:
11671 next_master:
11673 * Skip to next failed / untried master.
11675 do {
11676 zone->curmaster++;
11677 } while (zone->curmaster < zone->masterscnt &&
11678 zone->mastersok[zone->curmaster]);
11679 /* FALLTHROUGH */
11680 same_master:
11681 if (zone->curmaster >= zone->masterscnt) {
11682 zone->curmaster = 0;
11683 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11684 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11685 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11686 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11687 while (zone->curmaster < zone->masterscnt &&
11688 zone->mastersok[zone->curmaster])
11689 zone->curmaster++;
11690 again = ISC_TRUE;
11691 } else
11692 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11693 } else {
11694 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11695 again = ISC_TRUE;
11697 inc_stats(zone, dns_zonestatscounter_xfrfail);
11698 break;
11700 zone_settimer(zone, &now);
11703 * If creating the transfer object failed, zone->xfr is NULL.
11704 * Otherwise, we are called as the done callback of a zone
11705 * transfer object that just entered its shutting-down
11706 * state. Since we are no longer responsible for shutting
11707 * it down, we can detach our reference.
11709 if (zone->xfr != NULL)
11710 dns_xfrin_detach(&zone->xfr);
11712 if (zone->tsigkey != NULL)
11713 dns_tsigkey_detach(&zone->tsigkey);
11716 * Handle any deferred journal compaction.
11718 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
11719 result = dns_journal_compact(zone->mctx, zone->journal,
11720 zone->compact_serial,
11721 zone->journalsize);
11722 switch (result) {
11723 case ISC_R_SUCCESS:
11724 case ISC_R_NOSPACE:
11725 case ISC_R_NOTFOUND:
11726 dns_zone_log(zone, ISC_LOG_DEBUG(3),
11727 "dns_journal_compact: %s",
11728 dns_result_totext(result));
11729 break;
11730 default:
11731 dns_zone_log(zone, ISC_LOG_ERROR,
11732 "dns_journal_compact failed: %s",
11733 dns_result_totext(result));
11734 break;
11736 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11740 * This transfer finishing freed up a transfer quota slot.
11741 * Let any other zones waiting for quota have it.
11743 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11744 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
11745 zone->statelist = NULL;
11746 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
11747 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
11750 * Retry with a different server if necessary.
11752 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11753 queue_soa_query(zone);
11755 INSIST(zone->irefs > 0);
11756 zone->irefs--;
11757 free_needed = exit_check(zone);
11758 UNLOCK_ZONE(zone);
11759 if (free_needed)
11760 zone_free(zone);
11763 static void
11764 zone_loaddone(void *arg, isc_result_t result) {
11765 static char me[] = "zone_loaddone";
11766 dns_load_t *load = arg;
11767 dns_zone_t *zone;
11768 isc_result_t tresult;
11770 REQUIRE(DNS_LOAD_VALID(load));
11771 zone = load->zone;
11773 ENTER;
11775 tresult = dns_db_endload(load->db, &load->callbacks.add_private);
11776 if (tresult != ISC_R_SUCCESS &&
11777 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
11778 result = tresult;
11780 LOCK_ZONE(load->zone);
11781 (void)zone_postload(load->zone, load->db, load->loadtime, result);
11782 zonemgr_putio(&load->zone->readio);
11783 DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADING);
11785 * Leave the zone frozen if the reload fails.
11787 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
11788 DNS_ZONE_FLAG(load->zone, DNS_ZONEFLG_THAW))
11789 zone->update_disabled = ISC_FALSE;
11790 DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_THAW);
11791 UNLOCK_ZONE(load->zone);
11793 load->magic = 0;
11794 dns_db_detach(&load->db);
11795 if (load->zone->lctx != NULL)
11796 dns_loadctx_detach(&load->zone->lctx);
11797 dns_zone_idetach(&load->zone);
11798 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
11801 void
11802 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
11803 REQUIRE(DNS_ZONE_VALID(zone));
11804 REQUIRE(table != NULL);
11805 REQUIRE(*table == NULL);
11807 LOCK_ZONE(zone);
11808 if (zone->ssutable != NULL)
11809 dns_ssutable_attach(zone->ssutable, table);
11810 UNLOCK_ZONE(zone);
11813 void
11814 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
11815 REQUIRE(DNS_ZONE_VALID(zone));
11817 LOCK_ZONE(zone);
11818 if (zone->ssutable != NULL)
11819 dns_ssutable_detach(&zone->ssutable);
11820 if (table != NULL)
11821 dns_ssutable_attach(table, &zone->ssutable);
11822 UNLOCK_ZONE(zone);
11825 void
11826 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
11827 REQUIRE(DNS_ZONE_VALID(zone));
11829 zone->sigvalidityinterval = interval;
11832 isc_uint32_t
11833 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
11834 REQUIRE(DNS_ZONE_VALID(zone));
11836 return (zone->sigvalidityinterval);
11839 void
11840 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
11841 REQUIRE(DNS_ZONE_VALID(zone));
11843 zone->sigresigninginterval = interval;
11846 isc_uint32_t
11847 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
11848 REQUIRE(DNS_ZONE_VALID(zone));
11850 return (zone->sigresigninginterval);
11853 static void
11854 queue_xfrin(dns_zone_t *zone) {
11855 const char me[] = "queue_xfrin";
11856 isc_result_t result;
11857 dns_zonemgr_t *zmgr = zone->zmgr;
11859 ENTER;
11861 INSIST(zone->statelist == NULL);
11863 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
11864 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
11865 LOCK_ZONE(zone);
11866 zone->irefs++;
11867 UNLOCK_ZONE(zone);
11868 zone->statelist = &zmgr->waiting_for_xfrin;
11869 result = zmgr_start_xfrin_ifquota(zmgr, zone);
11870 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
11872 if (result == ISC_R_QUOTA) {
11873 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
11874 "zone transfer deferred due to quota");
11875 } else if (result != ISC_R_SUCCESS) {
11876 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
11877 "starting zone transfer: %s",
11878 isc_result_totext(result));
11883 * This event callback is called when a zone has received
11884 * any necessary zone transfer quota. This is the time
11885 * to go ahead and start the transfer.
11887 static void
11888 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
11889 isc_result_t result;
11890 dns_peer_t *peer = NULL;
11891 char master[ISC_SOCKADDR_FORMATSIZE];
11892 char source[ISC_SOCKADDR_FORMATSIZE];
11893 dns_rdatatype_t xfrtype;
11894 dns_zone_t *zone = event->ev_arg;
11895 isc_netaddr_t masterip;
11896 isc_sockaddr_t sourceaddr;
11897 isc_sockaddr_t masteraddr;
11898 isc_time_t now;
11900 UNUSED(task);
11902 INSIST(task == zone->task);
11904 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11905 result = ISC_R_CANCELED;
11906 goto cleanup;
11909 TIME_NOW(&now);
11911 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
11912 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
11913 &zone->sourceaddr, &now)) {
11914 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
11915 dns_zone_log(zone, ISC_LOG_INFO,
11916 "got_transfer_quota: skipping zone transfer as "
11917 "master %s (source %s) is unreachable (cached)",
11918 master, source);
11919 result = ISC_R_CANCELED;
11920 goto cleanup;
11923 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11924 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
11927 * Decide whether we should request IXFR or AXFR.
11929 if (zone->db == NULL) {
11930 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11931 "no database exists yet, requesting AXFR of "
11932 "initial version from %s", master);
11933 xfrtype = dns_rdatatype_axfr;
11934 } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
11935 dns_zone_log(zone, ISC_LOG_DEBUG(1), "ixfr-from-differences "
11936 "set, requesting AXFR from %s", master);
11937 xfrtype = dns_rdatatype_axfr;
11938 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
11939 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11940 "forced reload, requesting AXFR of "
11941 "initial version from %s", master);
11942 xfrtype = dns_rdatatype_axfr;
11943 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
11944 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11945 "retrying with AXFR from %s due to "
11946 "previous IXFR failure", master);
11947 xfrtype = dns_rdatatype_axfr;
11948 LOCK_ZONE(zone);
11949 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
11950 UNLOCK_ZONE(zone);
11951 } else {
11952 isc_boolean_t use_ixfr = ISC_TRUE;
11953 if (peer != NULL &&
11954 dns_peer_getrequestixfr(peer, &use_ixfr) ==
11955 ISC_R_SUCCESS) {
11956 ; /* Using peer setting */
11957 } else {
11958 use_ixfr = zone->view->requestixfr;
11960 if (use_ixfr == ISC_FALSE) {
11961 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11962 "IXFR disabled, requesting AXFR from %s",
11963 master);
11964 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
11965 xfrtype = dns_rdatatype_soa;
11966 else
11967 xfrtype = dns_rdatatype_axfr;
11968 } else {
11969 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11970 "requesting IXFR from %s", master);
11971 xfrtype = dns_rdatatype_ixfr;
11976 * Determine if we should attempt to sign the request with TSIG.
11978 result = ISC_R_NOTFOUND;
11980 * First, look for a tsig key in the master statement, then
11981 * try for a server key.
11983 if ((zone->masterkeynames != NULL) &&
11984 (zone->masterkeynames[zone->curmaster] != NULL)) {
11985 dns_view_t *view = dns_zone_getview(zone);
11986 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11987 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
11989 if (zone->tsigkey == NULL)
11990 result = dns_view_getpeertsig(zone->view, &masterip,
11991 &zone->tsigkey);
11993 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11994 dns_zone_log(zone, ISC_LOG_ERROR,
11995 "could not get TSIG key for zone transfer: %s",
11996 isc_result_totext(result));
11999 LOCK_ZONE(zone);
12000 masteraddr = zone->masteraddr;
12001 sourceaddr = zone->sourceaddr;
12002 UNLOCK_ZONE(zone);
12003 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
12004 result = dns_xfrin_create2(zone, xfrtype, &masteraddr, &sourceaddr,
12005 zone->tsigkey, zone->mctx,
12006 zone->zmgr->timermgr, zone->zmgr->socketmgr,
12007 zone->task, zone_xfrdone, &zone->xfr);
12008 if (result == ISC_R_SUCCESS) {
12009 LOCK_ZONE(zone);
12010 if (xfrtype == dns_rdatatype_axfr) {
12011 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12012 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
12013 else
12014 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
12015 } else if (xfrtype == dns_rdatatype_ixfr) {
12016 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
12017 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
12018 else
12019 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
12021 UNLOCK_ZONE(zone);
12023 cleanup:
12025 * Any failure in this function is handled like a failed
12026 * zone transfer. This ensures that we get removed from
12027 * zmgr->xfrin_in_progress.
12029 if (result != ISC_R_SUCCESS)
12030 zone_xfrdone(zone, result);
12032 isc_event_free(&event);
12036 * Update forwarding support.
12039 static void
12040 forward_destroy(dns_forward_t *forward) {
12042 forward->magic = 0;
12043 if (forward->request != NULL)
12044 dns_request_destroy(&forward->request);
12045 if (forward->msgbuf != NULL)
12046 isc_buffer_free(&forward->msgbuf);
12047 if (forward->zone != NULL)
12048 dns_zone_idetach(&forward->zone);
12049 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
12052 static isc_result_t
12053 sendtomaster(dns_forward_t *forward) {
12054 isc_result_t result;
12055 isc_sockaddr_t src;
12057 LOCK_ZONE(forward->zone);
12058 if (forward->which >= forward->zone->masterscnt) {
12059 UNLOCK_ZONE(forward->zone);
12060 return (ISC_R_NOMORE);
12063 forward->addr = forward->zone->masters[forward->which];
12065 * Always use TCP regardless of whether the original update
12066 * used TCP.
12067 * XXX The timeout may but a bit small if we are far down a
12068 * transfer graph and the master has to try several masters.
12070 switch (isc_sockaddr_pf(&forward->addr)) {
12071 case PF_INET:
12072 src = forward->zone->xfrsource4;
12073 break;
12074 case PF_INET6:
12075 src = forward->zone->xfrsource6;
12076 break;
12077 default:
12078 result = ISC_R_NOTIMPLEMENTED;
12079 goto unlock;
12081 result = dns_request_createraw(forward->zone->view->requestmgr,
12082 forward->msgbuf,
12083 &src, &forward->addr,
12084 DNS_REQUESTOPT_TCP, 15 /* XXX */,
12085 forward->zone->task,
12086 forward_callback, forward,
12087 &forward->request);
12088 unlock:
12089 UNLOCK_ZONE(forward->zone);
12090 return (result);
12093 static void
12094 forward_callback(isc_task_t *task, isc_event_t *event) {
12095 const char me[] = "forward_callback";
12096 dns_requestevent_t *revent = (dns_requestevent_t *)event;
12097 dns_message_t *msg = NULL;
12098 char master[ISC_SOCKADDR_FORMATSIZE];
12099 isc_result_t result;
12100 dns_forward_t *forward;
12101 dns_zone_t *zone;
12103 UNUSED(task);
12105 forward = revent->ev_arg;
12106 INSIST(DNS_FORWARD_VALID(forward));
12107 zone = forward->zone;
12108 INSIST(DNS_ZONE_VALID(zone));
12110 ENTER;
12112 isc_sockaddr_format(&forward->addr, master, sizeof(master));
12114 if (revent->result != ISC_R_SUCCESS) {
12115 dns_zone_log(zone, ISC_LOG_INFO,
12116 "could not forward dynamic update to %s: %s",
12117 master, dns_result_totext(revent->result));
12118 goto next_master;
12121 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12122 if (result != ISC_R_SUCCESS)
12123 goto next_master;
12125 result = dns_request_getresponse(revent->request, msg,
12126 DNS_MESSAGEPARSE_PRESERVEORDER |
12127 DNS_MESSAGEPARSE_CLONEBUFFER);
12128 if (result != ISC_R_SUCCESS)
12129 goto next_master;
12131 switch (msg->rcode) {
12133 * Pass these rcodes back to client.
12135 case dns_rcode_noerror:
12136 case dns_rcode_yxdomain:
12137 case dns_rcode_yxrrset:
12138 case dns_rcode_nxrrset:
12139 case dns_rcode_refused:
12140 case dns_rcode_nxdomain:
12141 break;
12143 /* These should not occur if the masters/zone are valid. */
12144 case dns_rcode_notzone:
12145 case dns_rcode_notauth: {
12146 char rcode[128];
12147 isc_buffer_t rb;
12149 isc_buffer_init(&rb, rcode, sizeof(rcode));
12150 (void)dns_rcode_totext(msg->rcode, &rb);
12151 dns_zone_log(zone, ISC_LOG_WARNING,
12152 "forwarding dynamic update: "
12153 "unexpected response: master %s returned: %.*s",
12154 master, (int)rb.used, rcode);
12155 goto next_master;
12158 /* Try another server for these rcodes. */
12159 case dns_rcode_formerr:
12160 case dns_rcode_servfail:
12161 case dns_rcode_notimp:
12162 case dns_rcode_badvers:
12163 default:
12164 goto next_master;
12167 /* call callback */
12168 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
12169 msg = NULL;
12170 dns_request_destroy(&forward->request);
12171 forward_destroy(forward);
12172 isc_event_free(&event);
12173 return;
12175 next_master:
12176 if (msg != NULL)
12177 dns_message_destroy(&msg);
12178 isc_event_free(&event);
12179 forward->which++;
12180 dns_request_destroy(&forward->request);
12181 result = sendtomaster(forward);
12182 if (result != ISC_R_SUCCESS) {
12183 /* call callback */
12184 dns_zone_log(zone, ISC_LOG_DEBUG(3),
12185 "exhausted dynamic update forwarder list");
12186 (forward->callback)(forward->callback_arg, result, NULL);
12187 forward_destroy(forward);
12191 isc_result_t
12192 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
12193 dns_updatecallback_t callback, void *callback_arg)
12195 dns_forward_t *forward;
12196 isc_result_t result;
12197 isc_region_t *mr;
12199 REQUIRE(DNS_ZONE_VALID(zone));
12200 REQUIRE(msg != NULL);
12201 REQUIRE(callback != NULL);
12203 forward = isc_mem_get(zone->mctx, sizeof(*forward));
12204 if (forward == NULL)
12205 return (ISC_R_NOMEMORY);
12207 forward->request = NULL;
12208 forward->zone = NULL;
12209 forward->msgbuf = NULL;
12210 forward->which = 0;
12211 forward->mctx = 0;
12212 forward->callback = callback;
12213 forward->callback_arg = callback_arg;
12214 forward->magic = FORWARD_MAGIC;
12216 mr = dns_message_getrawmessage(msg);
12217 if (mr == NULL) {
12218 result = ISC_R_UNEXPECTEDEND;
12219 goto cleanup;
12222 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
12223 if (result != ISC_R_SUCCESS)
12224 goto cleanup;
12225 result = isc_buffer_copyregion(forward->msgbuf, mr);
12226 if (result != ISC_R_SUCCESS)
12227 goto cleanup;
12229 isc_mem_attach(zone->mctx, &forward->mctx);
12230 dns_zone_iattach(zone, &forward->zone);
12231 result = sendtomaster(forward);
12233 cleanup:
12234 if (result != ISC_R_SUCCESS) {
12235 forward_destroy(forward);
12237 return (result);
12240 isc_result_t
12241 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
12242 REQUIRE(DNS_ZONE_VALID(zone));
12243 REQUIRE(next != NULL && *next == NULL);
12245 *next = ISC_LIST_NEXT(zone, link);
12246 if (*next == NULL)
12247 return (ISC_R_NOMORE);
12248 else
12249 return (ISC_R_SUCCESS);
12252 isc_result_t
12253 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
12254 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12255 REQUIRE(first != NULL && *first == NULL);
12257 *first = ISC_LIST_HEAD(zmgr->zones);
12258 if (*first == NULL)
12259 return (ISC_R_NOMORE);
12260 else
12261 return (ISC_R_SUCCESS);
12264 /***
12265 *** Zone manager.
12266 ***/
12268 isc_result_t
12269 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
12270 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
12271 dns_zonemgr_t **zmgrp)
12273 dns_zonemgr_t *zmgr;
12274 isc_result_t result;
12275 isc_interval_t interval;
12277 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
12278 if (zmgr == NULL)
12279 return (ISC_R_NOMEMORY);
12280 zmgr->mctx = NULL;
12281 zmgr->refs = 1;
12282 isc_mem_attach(mctx, &zmgr->mctx);
12283 zmgr->taskmgr = taskmgr;
12284 zmgr->timermgr = timermgr;
12285 zmgr->socketmgr = socketmgr;
12286 zmgr->zonetasks = NULL;
12287 zmgr->task = NULL;
12288 zmgr->rl = NULL;
12289 ISC_LIST_INIT(zmgr->zones);
12290 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
12291 ISC_LIST_INIT(zmgr->xfrin_in_progress);
12292 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
12293 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
12294 if (result != ISC_R_SUCCESS)
12295 goto free_mem;
12297 zmgr->transfersin = 10;
12298 zmgr->transfersperns = 2;
12300 /* Create the zone task pool. */
12301 result = isc_taskpool_create(taskmgr, mctx,
12302 8 /* XXX */, 2, &zmgr->zonetasks);
12303 if (result != ISC_R_SUCCESS)
12304 goto free_rwlock;
12306 /* Create a single task for queueing of SOA queries. */
12307 result = isc_task_create(taskmgr, 1, &zmgr->task);
12308 if (result != ISC_R_SUCCESS)
12309 goto free_taskpool;
12310 isc_task_setname(zmgr->task, "zmgr", zmgr);
12311 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
12312 &zmgr->rl);
12313 if (result != ISC_R_SUCCESS)
12314 goto free_task;
12315 /* default to 20 refresh queries / notifies per second. */
12316 isc_interval_set(&interval, 0, 1000000000/2);
12317 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
12318 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12319 isc_ratelimiter_setpertic(zmgr->rl, 10);
12321 zmgr->iolimit = 1;
12322 zmgr->ioactive = 0;
12323 ISC_LIST_INIT(zmgr->high);
12324 ISC_LIST_INIT(zmgr->low);
12326 result = isc_mutex_init(&zmgr->iolock);
12327 if (result != ISC_R_SUCCESS)
12328 goto free_rl;
12330 zmgr->magic = ZONEMGR_MAGIC;
12332 *zmgrp = zmgr;
12333 return (ISC_R_SUCCESS);
12335 #if 0
12336 free_iolock:
12337 DESTROYLOCK(&zmgr->iolock);
12338 #endif
12339 free_rl:
12340 isc_ratelimiter_detach(&zmgr->rl);
12341 free_task:
12342 isc_task_detach(&zmgr->task);
12343 free_taskpool:
12344 isc_taskpool_destroy(&zmgr->zonetasks);
12345 free_rwlock:
12346 isc_rwlock_destroy(&zmgr->rwlock);
12347 free_mem:
12348 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12349 isc_mem_detach(&mctx);
12350 return (result);
12353 isc_result_t
12354 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12355 isc_result_t result;
12357 REQUIRE(DNS_ZONE_VALID(zone));
12358 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12360 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12361 LOCK_ZONE(zone);
12362 REQUIRE(zone->task == NULL);
12363 REQUIRE(zone->timer == NULL);
12364 REQUIRE(zone->zmgr == NULL);
12366 isc_taskpool_gettask(zmgr->zonetasks,
12367 dns_name_hash(dns_zone_getorigin(zone),
12368 ISC_FALSE),
12369 &zone->task);
12372 * Set the task name. The tag will arbitrarily point to one
12373 * of the zones sharing the task (in practice, the one
12374 * to be managed last).
12376 isc_task_setname(zone->task, "zone", zone);
12378 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
12379 NULL, NULL,
12380 zone->task, zone_timer, zone,
12381 &zone->timer);
12383 if (result != ISC_R_SUCCESS)
12384 goto cleanup_task;
12387 * The timer "holds" a iref.
12389 zone->irefs++;
12390 INSIST(zone->irefs != 0);
12392 ISC_LIST_APPEND(zmgr->zones, zone, link);
12393 zone->zmgr = zmgr;
12394 zmgr->refs++;
12396 goto unlock;
12398 cleanup_task:
12399 isc_task_detach(&zone->task);
12401 unlock:
12402 UNLOCK_ZONE(zone);
12403 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12404 return (result);
12407 void
12408 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12409 isc_boolean_t free_now = ISC_FALSE;
12411 REQUIRE(DNS_ZONE_VALID(zone));
12412 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12413 REQUIRE(zone->zmgr == zmgr);
12415 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12416 LOCK_ZONE(zone);
12418 ISC_LIST_UNLINK(zmgr->zones, zone, link);
12419 zone->zmgr = NULL;
12420 zmgr->refs--;
12421 if (zmgr->refs == 0)
12422 free_now = ISC_TRUE;
12424 UNLOCK_ZONE(zone);
12425 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12427 if (free_now)
12428 zonemgr_free(zmgr);
12429 ENSURE(zone->zmgr == NULL);
12432 void
12433 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
12434 REQUIRE(DNS_ZONEMGR_VALID(source));
12435 REQUIRE(target != NULL && *target == NULL);
12437 RWLOCK(&source->rwlock, isc_rwlocktype_write);
12438 REQUIRE(source->refs > 0);
12439 source->refs++;
12440 INSIST(source->refs > 0);
12441 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
12442 *target = source;
12445 void
12446 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
12447 dns_zonemgr_t *zmgr;
12448 isc_boolean_t free_now = ISC_FALSE;
12450 REQUIRE(zmgrp != NULL);
12451 zmgr = *zmgrp;
12452 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12454 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12455 zmgr->refs--;
12456 if (zmgr->refs == 0)
12457 free_now = ISC_TRUE;
12458 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12460 if (free_now)
12461 zonemgr_free(zmgr);
12464 isc_result_t
12465 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
12466 dns_zone_t *p;
12468 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12470 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12471 for (p = ISC_LIST_HEAD(zmgr->zones);
12472 p != NULL;
12473 p = ISC_LIST_NEXT(p, link))
12475 dns_zone_maintenance(p);
12477 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
12480 * Recent configuration changes may have increased the
12481 * amount of available transfers quota. Make sure any
12482 * transfers currently blocked on quota get started if
12483 * possible.
12485 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12486 zmgr_resume_xfrs(zmgr, ISC_TRUE);
12487 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12488 return (ISC_R_SUCCESS);
12491 void
12492 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
12494 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12496 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12497 zmgr_resume_xfrs(zmgr, ISC_TRUE);
12498 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12501 void
12502 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
12503 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12505 isc_ratelimiter_shutdown(zmgr->rl);
12507 if (zmgr->task != NULL)
12508 isc_task_destroy(&zmgr->task);
12509 if (zmgr->zonetasks != NULL)
12510 isc_taskpool_destroy(&zmgr->zonetasks);
12513 static void
12514 zonemgr_free(dns_zonemgr_t *zmgr) {
12515 isc_mem_t *mctx;
12517 INSIST(zmgr->refs == 0);
12518 INSIST(ISC_LIST_EMPTY(zmgr->zones));
12520 zmgr->magic = 0;
12522 DESTROYLOCK(&zmgr->iolock);
12523 isc_ratelimiter_detach(&zmgr->rl);
12525 isc_rwlock_destroy(&zmgr->rwlock);
12526 mctx = zmgr->mctx;
12527 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
12528 isc_mem_detach(&mctx);
12531 void
12532 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12533 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12535 zmgr->transfersin = value;
12538 isc_uint32_t
12539 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
12540 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12542 return (zmgr->transfersin);
12545 void
12546 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
12547 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12549 zmgr->transfersperns = value;
12552 isc_uint32_t
12553 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
12554 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12556 return (zmgr->transfersperns);
12560 * Try to start a new incoming zone transfer to fill a quota
12561 * slot that was just vacated.
12563 * Requires:
12564 * The zone manager is locked by the caller.
12566 static void
12567 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
12568 dns_zone_t *zone;
12569 dns_zone_t *next;
12571 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
12572 zone != NULL;
12573 zone = next)
12575 isc_result_t result;
12576 next = ISC_LIST_NEXT(zone, statelink);
12577 result = zmgr_start_xfrin_ifquota(zmgr, zone);
12578 if (result == ISC_R_SUCCESS) {
12579 if (multi)
12580 continue;
12582 * We successfully filled the slot. We're done.
12584 break;
12585 } else if (result == ISC_R_QUOTA) {
12587 * Not enough quota. This is probably the per-server
12588 * quota, because we usually get called when a unit of
12589 * global quota has just been freed. Try the next
12590 * zone, it may succeed if it uses another master.
12592 continue;
12593 } else {
12594 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12595 "starting zone transfer: %s",
12596 isc_result_totext(result));
12597 break;
12603 * Try to start an incoming zone transfer for 'zone', quota permitting.
12605 * Requires:
12606 * The zone manager is locked by the caller.
12608 * Returns:
12609 * ISC_R_SUCCESS There was enough quota and we attempted to
12610 * start a transfer. zone_xfrdone() has been or will
12611 * be called.
12612 * ISC_R_QUOTA Not enough quota.
12613 * Others Failure.
12615 static isc_result_t
12616 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
12617 dns_peer_t *peer = NULL;
12618 isc_netaddr_t masterip;
12619 isc_uint32_t nxfrsin, nxfrsperns;
12620 dns_zone_t *x;
12621 isc_uint32_t maxtransfersin, maxtransfersperns;
12622 isc_event_t *e;
12625 * Find any configured information about the server we'd
12626 * like to transfer this zone from.
12628 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12629 (void)dns_peerlist_peerbyaddr(zone->view->peers,
12630 &masterip, &peer);
12633 * Determine the total maximum number of simultaneous
12634 * transfers allowed, and the maximum for this specific
12635 * master.
12637 maxtransfersin = zmgr->transfersin;
12638 maxtransfersperns = zmgr->transfersperns;
12639 if (peer != NULL)
12640 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
12643 * Count the total number of transfers that are in progress,
12644 * and the number of transfers in progress from this master.
12645 * We linearly scan a list of all transfers; if this turns
12646 * out to be too slow, we could hash on the master address.
12648 nxfrsin = nxfrsperns = 0;
12649 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
12650 x != NULL;
12651 x = ISC_LIST_NEXT(x, statelink))
12653 isc_netaddr_t xip;
12654 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
12655 nxfrsin++;
12656 if (isc_netaddr_equal(&xip, &masterip))
12657 nxfrsperns++;
12660 /* Enforce quota. */
12661 if (nxfrsin >= maxtransfersin)
12662 return (ISC_R_QUOTA);
12664 if (nxfrsperns >= maxtransfersperns)
12665 return (ISC_R_QUOTA);
12668 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
12669 * list and send it an event to let it start the actual transfer in the
12670 * context of its own task.
12672 e = isc_event_allocate(zmgr->mctx, zmgr,
12673 DNS_EVENT_ZONESTARTXFRIN,
12674 got_transfer_quota, zone,
12675 sizeof(isc_event_t));
12676 if (e == NULL)
12677 return (ISC_R_NOMEMORY);
12679 LOCK_ZONE(zone);
12680 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
12681 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
12682 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
12683 zone->statelist = &zmgr->xfrin_in_progress;
12684 isc_task_send(zone->task, &e);
12685 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
12686 UNLOCK_ZONE(zone);
12688 return (ISC_R_SUCCESS);
12691 void
12692 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
12694 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12695 REQUIRE(iolimit > 0);
12697 zmgr->iolimit = iolimit;
12700 isc_uint32_t
12701 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
12703 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12705 return (zmgr->iolimit);
12709 * Get permission to request a file handle from the OS.
12710 * An event will be sent to action when one is available.
12711 * There are two queues available (high and low), the high
12712 * queue will be serviced before the low one.
12714 * zonemgr_putio() must be called after the event is delivered to
12715 * 'action'.
12718 static isc_result_t
12719 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
12720 isc_task_t *task, isc_taskaction_t action, void *arg,
12721 dns_io_t **iop)
12723 dns_io_t *io;
12724 isc_boolean_t queue;
12726 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12727 REQUIRE(iop != NULL && *iop == NULL);
12729 io = isc_mem_get(zmgr->mctx, sizeof(*io));
12730 if (io == NULL)
12731 return (ISC_R_NOMEMORY);
12732 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
12733 action, arg, sizeof(*io->event));
12734 if (io->event == NULL) {
12735 isc_mem_put(zmgr->mctx, io, sizeof(*io));
12736 return (ISC_R_NOMEMORY);
12738 io->zmgr = zmgr;
12739 io->high = high;
12740 io->task = NULL;
12741 isc_task_attach(task, &io->task);
12742 ISC_LINK_INIT(io, link);
12743 io->magic = IO_MAGIC;
12745 LOCK(&zmgr->iolock);
12746 zmgr->ioactive++;
12747 queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
12748 if (queue) {
12749 if (io->high)
12750 ISC_LIST_APPEND(zmgr->high, io, link);
12751 else
12752 ISC_LIST_APPEND(zmgr->low, io, link);
12754 UNLOCK(&zmgr->iolock);
12755 *iop = io;
12757 if (!queue) {
12758 isc_task_send(io->task, &io->event);
12760 return (ISC_R_SUCCESS);
12763 static void
12764 zonemgr_putio(dns_io_t **iop) {
12765 dns_io_t *io;
12766 dns_io_t *next;
12767 dns_zonemgr_t *zmgr;
12769 REQUIRE(iop != NULL);
12770 io = *iop;
12771 REQUIRE(DNS_IO_VALID(io));
12773 *iop = NULL;
12775 INSIST(!ISC_LINK_LINKED(io, link));
12776 INSIST(io->event == NULL);
12778 zmgr = io->zmgr;
12779 isc_task_detach(&io->task);
12780 io->magic = 0;
12781 isc_mem_put(zmgr->mctx, io, sizeof(*io));
12783 LOCK(&zmgr->iolock);
12784 INSIST(zmgr->ioactive > 0);
12785 zmgr->ioactive--;
12786 next = HEAD(zmgr->high);
12787 if (next == NULL)
12788 next = HEAD(zmgr->low);
12789 if (next != NULL) {
12790 if (next->high)
12791 ISC_LIST_UNLINK(zmgr->high, next, link);
12792 else
12793 ISC_LIST_UNLINK(zmgr->low, next, link);
12794 INSIST(next->event != NULL);
12796 UNLOCK(&zmgr->iolock);
12797 if (next != NULL)
12798 isc_task_send(next->task, &next->event);
12801 static void
12802 zonemgr_cancelio(dns_io_t *io) {
12803 isc_boolean_t send_event = ISC_FALSE;
12805 REQUIRE(DNS_IO_VALID(io));
12808 * If we are queued to be run then dequeue.
12810 LOCK(&io->zmgr->iolock);
12811 if (ISC_LINK_LINKED(io, link)) {
12812 if (io->high)
12813 ISC_LIST_UNLINK(io->zmgr->high, io, link);
12814 else
12815 ISC_LIST_UNLINK(io->zmgr->low, io, link);
12817 send_event = ISC_TRUE;
12818 INSIST(io->event != NULL);
12820 UNLOCK(&io->zmgr->iolock);
12821 if (send_event) {
12822 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
12823 isc_task_send(io->task, &io->event);
12827 static void
12828 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
12829 char *buf;
12830 int buflen;
12831 isc_result_t result;
12833 buflen = strlen(path) + strlen(templat) + 2;
12835 buf = isc_mem_get(zone->mctx, buflen);
12836 if (buf == NULL)
12837 return;
12839 result = isc_file_template(path, templat, buf, buflen);
12840 if (result != ISC_R_SUCCESS)
12841 goto cleanup;
12843 result = isc_file_renameunique(path, buf);
12844 if (result != ISC_R_SUCCESS)
12845 goto cleanup;
12847 dns_zone_log(zone, ISC_LOG_WARNING, "saved '%s' as '%s'",
12848 path, buf);
12850 cleanup:
12851 isc_mem_put(zone->mctx, buf, buflen);
12854 #if 0
12855 /* Hook for ondestroy notification from a database. */
12857 static void
12858 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
12859 dns_db_t *db = event->sender;
12860 UNUSED(task);
12862 isc_event_free(&event);
12864 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
12865 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
12866 "database (%p) destroyed", (void*) db);
12868 #endif
12870 void
12871 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
12872 isc_interval_t interval;
12873 isc_uint32_t s, ns;
12874 isc_uint32_t pertic;
12875 isc_result_t result;
12877 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12879 if (value == 0)
12880 value = 1;
12882 if (value == 1) {
12883 s = 1;
12884 ns = 0;
12885 pertic = 1;
12886 } else if (value <= 10) {
12887 s = 0;
12888 ns = 1000000000 / value;
12889 pertic = 1;
12890 } else {
12891 s = 0;
12892 ns = (1000000000 / value) * 10;
12893 pertic = 10;
12896 isc_interval_set(&interval, s, ns);
12897 result = isc_ratelimiter_setinterval(zmgr->rl, &interval);
12898 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12899 isc_ratelimiter_setpertic(zmgr->rl, pertic);
12901 zmgr->serialqueryrate = value;
12904 unsigned int
12905 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
12906 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12908 return (zmgr->serialqueryrate);
12911 static isc_boolean_t
12912 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
12913 isc_sockaddr_t *local, isc_time_t *now)
12915 unsigned int i;
12916 isc_rwlocktype_t locktype;
12917 isc_result_t result;
12918 isc_uint32_t seconds = isc_time_seconds(now);
12920 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12922 locktype = isc_rwlocktype_read;
12923 RWLOCK(&zmgr->rwlock, locktype);
12924 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
12925 if (zmgr->unreachable[i].expire >= seconds &&
12926 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
12927 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
12928 result = isc_rwlock_tryupgrade(&zmgr->rwlock);
12929 if (result == ISC_R_SUCCESS) {
12930 locktype = isc_rwlocktype_write;
12931 zmgr->unreachable[i].last = seconds;
12933 break;
12936 RWUNLOCK(&zmgr->rwlock, locktype);
12937 return (ISC_TF(i < UNREACH_CHACHE_SIZE));
12940 void
12941 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
12942 isc_sockaddr_t *local, isc_time_t *now)
12944 isc_uint32_t seconds = isc_time_seconds(now);
12945 isc_uint32_t last = seconds;
12946 unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
12948 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
12950 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12951 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
12952 /* Existing entry? */
12953 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
12954 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
12955 break;
12956 /* Empty slot? */
12957 if (zmgr->unreachable[i].expire < seconds)
12958 slot = i;
12959 /* Least recently used slot? */
12960 if (zmgr->unreachable[i].last < last) {
12961 last = zmgr->unreachable[i].last;
12962 oldest = i;
12965 if (i < UNREACH_CHACHE_SIZE) {
12967 * Found a existing entry. Update the expire timer and
12968 * last usage timestamps.
12970 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
12971 zmgr->unreachable[i].last = seconds;
12972 } else if (slot != UNREACH_CHACHE_SIZE) {
12974 * Found a empty slot. Add a new entry to the cache.
12976 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
12977 zmgr->unreachable[slot].last = seconds;
12978 zmgr->unreachable[slot].remote = *remote;
12979 zmgr->unreachable[slot].local = *local;
12980 } else {
12982 * Replace the least recently used entry in the cache.
12984 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
12985 zmgr->unreachable[oldest].last = seconds;
12986 zmgr->unreachable[oldest].remote = *remote;
12987 zmgr->unreachable[oldest].local = *local;
12989 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
12992 void
12993 dns_zone_forcereload(dns_zone_t *zone) {
12994 REQUIRE(DNS_ZONE_VALID(zone));
12996 if (zone->type == dns_zone_master)
12997 return;
12999 LOCK_ZONE(zone);
13000 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
13001 UNLOCK_ZONE(zone);
13002 dns_zone_refresh(zone);
13005 isc_boolean_t
13006 dns_zone_isforced(dns_zone_t *zone) {
13007 REQUIRE(DNS_ZONE_VALID(zone));
13009 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
13012 isc_result_t
13013 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
13015 * This function is obsoleted.
13017 UNUSED(zone);
13018 UNUSED(on);
13019 return (ISC_R_NOTIMPLEMENTED);
13022 isc_uint64_t *
13023 dns_zone_getstatscounters(dns_zone_t *zone) {
13025 * This function is obsoleted.
13027 UNUSED(zone);
13028 return (NULL);
13031 void
13032 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
13033 REQUIRE(DNS_ZONE_VALID(zone));
13034 REQUIRE(zone->stats == NULL);
13036 LOCK_ZONE(zone);
13037 zone->stats = NULL;
13038 isc_stats_attach(stats, &zone->stats);
13039 UNLOCK_ZONE(zone);
13042 void
13043 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
13044 REQUIRE(DNS_ZONE_VALID(zone));
13046 LOCK_ZONE(zone);
13047 if (zone->requeststats_on && stats == NULL)
13048 zone->requeststats_on = ISC_FALSE;
13049 else if (!zone->requeststats_on && stats != NULL) {
13050 if (zone->requeststats == NULL) {
13051 isc_stats_attach(stats, &zone->requeststats);
13052 zone->requeststats_on = ISC_TRUE;
13055 UNLOCK_ZONE(zone);
13057 return;
13060 isc_stats_t *
13061 dns_zone_getrequeststats(dns_zone_t *zone) {
13063 * We don't lock zone for efficiency reason. This is not catastrophic
13064 * because requeststats must always be valid when requeststats_on is
13065 * true.
13066 * Some counters may be incremented while requeststats_on is becoming
13067 * false, or some cannot be incremented just after the statistics are
13068 * installed, but it shouldn't matter much in practice.
13070 if (zone->requeststats_on)
13071 return (zone->requeststats);
13072 else
13073 return (NULL);
13076 void
13077 dns_zone_dialup(dns_zone_t *zone) {
13079 REQUIRE(DNS_ZONE_VALID(zone));
13081 zone_debuglog(zone, "dns_zone_dialup", 3,
13082 "notify = %d, refresh = %d",
13083 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
13084 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
13086 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
13087 dns_zone_notify(zone);
13088 if (zone->type != dns_zone_master &&
13089 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13090 dns_zone_refresh(zone);
13093 void
13094 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
13095 REQUIRE(DNS_ZONE_VALID(zone));
13097 LOCK_ZONE(zone);
13098 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
13099 DNS_ZONEFLG_DIALREFRESH |
13100 DNS_ZONEFLG_NOREFRESH);
13101 switch (dialup) {
13102 case dns_dialuptype_no:
13103 break;
13104 case dns_dialuptype_yes:
13105 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
13106 DNS_ZONEFLG_DIALREFRESH |
13107 DNS_ZONEFLG_NOREFRESH));
13108 break;
13109 case dns_dialuptype_notify:
13110 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13111 break;
13112 case dns_dialuptype_notifypassive:
13113 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
13114 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13115 break;
13116 case dns_dialuptype_refresh:
13117 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
13118 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13119 break;
13120 case dns_dialuptype_passive:
13121 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
13122 break;
13123 default:
13124 INSIST(0);
13126 UNLOCK_ZONE(zone);
13129 isc_result_t
13130 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
13131 isc_result_t result = ISC_R_SUCCESS;
13133 REQUIRE(DNS_ZONE_VALID(zone));
13135 LOCK_ZONE(zone);
13136 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
13137 UNLOCK_ZONE(zone);
13139 return (result);
13142 const char *
13143 dns_zone_getkeydirectory(dns_zone_t *zone) {
13144 REQUIRE(DNS_ZONE_VALID(zone));
13146 return (zone->keydirectory);
13149 unsigned int
13150 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
13151 dns_zone_t *zone;
13152 unsigned int count = 0;
13154 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
13156 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13157 switch (state) {
13158 case DNS_ZONESTATE_XFERRUNNING:
13159 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
13160 zone != NULL;
13161 zone = ISC_LIST_NEXT(zone, statelink))
13162 count++;
13163 break;
13164 case DNS_ZONESTATE_XFERDEFERRED:
13165 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
13166 zone != NULL;
13167 zone = ISC_LIST_NEXT(zone, statelink))
13168 count++;
13169 break;
13170 case DNS_ZONESTATE_SOAQUERY:
13171 for (zone = ISC_LIST_HEAD(zmgr->zones);
13172 zone != NULL;
13173 zone = ISC_LIST_NEXT(zone, link))
13174 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
13175 count++;
13176 break;
13177 case DNS_ZONESTATE_ANY:
13178 for (zone = ISC_LIST_HEAD(zmgr->zones);
13179 zone != NULL;
13180 zone = ISC_LIST_NEXT(zone, link)) {
13181 dns_view_t *view = zone->view;
13182 if (view != NULL && strcmp(view->name, "_bind") == 0)
13183 continue;
13184 count++;
13186 break;
13187 default:
13188 INSIST(0);
13191 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
13193 return (count);
13196 isc_result_t
13197 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
13198 isc_boolean_t ok = ISC_TRUE;
13199 isc_boolean_t fail = ISC_FALSE;
13200 char namebuf[DNS_NAME_FORMATSIZE];
13201 char namebuf2[DNS_NAME_FORMATSIZE];
13202 char typebuf[DNS_RDATATYPE_FORMATSIZE];
13203 int level = ISC_LOG_WARNING;
13204 dns_name_t bad;
13206 REQUIRE(DNS_ZONE_VALID(zone));
13208 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
13209 return (ISC_R_SUCCESS);
13211 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
13212 level = ISC_LOG_ERROR;
13213 fail = ISC_TRUE;
13216 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
13217 if (!ok) {
13218 dns_name_format(name, namebuf, sizeof(namebuf));
13219 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13220 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
13221 dns_result_totext(DNS_R_BADOWNERNAME));
13222 if (fail)
13223 return (DNS_R_BADOWNERNAME);
13226 dns_name_init(&bad, NULL);
13227 ok = dns_rdata_checknames(rdata, name, &bad);
13228 if (!ok) {
13229 dns_name_format(name, namebuf, sizeof(namebuf));
13230 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
13231 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
13232 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
13233 namebuf2, dns_result_totext(DNS_R_BADNAME));
13234 if (fail)
13235 return (DNS_R_BADNAME);
13238 return (ISC_R_SUCCESS);
13241 void
13242 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
13243 REQUIRE(DNS_ZONE_VALID(zone));
13244 zone->checkmx = checkmx;
13247 void
13248 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
13249 REQUIRE(DNS_ZONE_VALID(zone));
13250 zone->checksrv = checksrv;
13253 void
13254 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
13255 REQUIRE(DNS_ZONE_VALID(zone));
13256 zone->checkns = checkns;
13259 void
13260 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
13261 REQUIRE(DNS_ZONE_VALID(zone));
13263 LOCK_ZONE(zone);
13264 zone->isself = isself;
13265 zone->isselfarg = arg;
13266 UNLOCK_ZONE(zone);
13269 void
13270 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
13271 REQUIRE(DNS_ZONE_VALID(zone));
13273 LOCK_ZONE(zone);
13274 zone->notifydelay = delay;
13275 UNLOCK_ZONE(zone);
13278 isc_uint32_t
13279 dns_zone_getnotifydelay(dns_zone_t *zone) {
13280 REQUIRE(DNS_ZONE_VALID(zone));
13282 return (zone->notifydelay);
13285 isc_result_t
13286 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
13287 isc_uint16_t keyid, isc_boolean_t delete)
13289 isc_result_t result;
13290 REQUIRE(DNS_ZONE_VALID(zone));
13292 dns_zone_log(zone, ISC_LOG_NOTICE,
13293 "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
13294 algorithm, keyid);
13295 LOCK_ZONE(zone);
13296 result = zone_signwithkey(zone, algorithm, keyid, delete);
13297 UNLOCK_ZONE(zone);
13299 return (result);
13302 static const char *hex = "0123456789ABCDEF";
13304 isc_result_t
13305 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
13306 isc_result_t result;
13307 char salt[255*2+1];
13308 unsigned int i, j;
13310 REQUIRE(DNS_ZONE_VALID(zone));
13312 if (nsec3param->salt_length != 0) {
13313 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
13314 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
13315 salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
13316 salt[j++] = hex[nsec3param->salt[i] & 0xf];
13318 salt[j] = '\0';
13319 } else
13320 strcpy(salt, "-");
13321 dns_zone_log(zone, ISC_LOG_NOTICE,
13322 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
13323 nsec3param->hash, nsec3param->iterations,
13324 salt);
13325 LOCK_ZONE(zone);
13326 result = zone_addnsec3chain(zone, nsec3param);
13327 UNLOCK_ZONE(zone);
13329 return (result);
13332 void
13333 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
13334 REQUIRE(DNS_ZONE_VALID(zone));
13336 if (nodes == 0)
13337 nodes = 1;
13338 zone->nodes = nodes;
13341 void
13342 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
13343 REQUIRE(DNS_ZONE_VALID(zone));
13346 * We treat signatures as a signed value so explicitly
13347 * limit its range here.
13349 if (signatures > ISC_INT32_MAX)
13350 signatures = ISC_INT32_MAX;
13351 else if (signatures == 0)
13352 signatures = 1;
13353 zone->signatures = signatures;
13356 void
13357 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
13358 REQUIRE(DNS_ZONE_VALID(zone));
13359 zone->privatetype = type;
13362 dns_rdatatype_t
13363 dns_zone_getprivatetype(dns_zone_t *zone) {
13364 REQUIRE(DNS_ZONE_VALID(zone));
13365 return (zone->privatetype);
13368 static isc_result_t
13369 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
13370 isc_boolean_t delete)
13372 dns_signing_t *signing;
13373 dns_signing_t *current;
13374 isc_result_t result = ISC_R_SUCCESS;
13375 isc_time_t now;
13377 signing = isc_mem_get(zone->mctx, sizeof *signing);
13378 if (signing == NULL)
13379 return (ISC_R_NOMEMORY);
13381 signing->magic = 0;
13382 signing->db = NULL;
13383 signing->dbiterator = NULL;
13384 signing->algorithm = algorithm;
13385 signing->keyid = keyid;
13386 signing->delete = delete;
13387 signing->done = ISC_FALSE;
13389 TIME_NOW(&now);
13391 for (current = ISC_LIST_HEAD(zone->signing);
13392 current != NULL;
13393 current = ISC_LIST_NEXT(current, link)) {
13394 if (current->db == zone->db &&
13395 current->algorithm == signing->algorithm &&
13396 current->keyid == signing->keyid) {
13397 if (current->delete != signing->delete)
13398 current->done = ISC_TRUE;
13399 else
13400 goto cleanup;
13404 if (zone->db != NULL) {
13405 dns_db_attach(zone->db, &signing->db);
13406 result = dns_db_createiterator(signing->db, 0,
13407 &signing->dbiterator);
13409 if (result == ISC_R_SUCCESS)
13410 result = dns_dbiterator_first(signing->dbiterator);
13411 if (result == ISC_R_SUCCESS) {
13412 dns_dbiterator_pause(signing->dbiterator);
13413 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
13414 signing = NULL;
13415 if (isc_time_isepoch(&zone->signingtime)) {
13416 zone->signingtime = now;
13417 if (zone->task != NULL)
13418 zone_settimer(zone, &now);
13421 } else
13422 result = ISC_R_NOTFOUND;
13424 cleanup:
13425 if (signing != NULL) {
13426 if (signing->db != NULL)
13427 dns_db_detach(&signing->db);
13428 if (signing->dbiterator != NULL)
13429 dns_dbiterator_destroy(&signing->dbiterator);
13430 isc_mem_put(zone->mctx, signing, sizeof *signing);
13432 return (result);
13435 static void
13436 logmsg(const char *format, ...) {
13437 va_list args;
13438 va_start(args, format);
13439 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13440 ISC_LOG_DEBUG(1), format, args);
13441 va_end(args);
13444 static void
13445 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
13446 dns_dnsseckey_t *key;
13447 while (!ISC_LIST_EMPTY(*list)) {
13448 key = ISC_LIST_HEAD(*list);
13449 ISC_LIST_UNLINK(*list, key, link);
13450 dns_dnsseckey_destroy(mctx, &key);
13454 static isc_result_t
13455 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
13456 isc_result_t result;
13457 isc_stdtime_t now, then = 0, event;
13458 int i;
13460 isc_stdtime_get(&now);
13462 for (i = 0; i <= DST_MAX_TIMES; i++) {
13463 result = dst_key_gettime(key, i, &event);
13464 if (result == ISC_R_SUCCESS && event > now &&
13465 (then == 0 || event < then))
13466 then = event;
13469 if (then != 0) {
13470 *timep = then;
13471 return (ISC_R_SUCCESS);
13474 return (ISC_R_NOTFOUND);
13477 static isc_result_t
13478 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
13479 const dns_rdata_t *rdata, isc_boolean_t *flag)
13481 dns_rdataset_t rdataset;
13482 dns_dbnode_t *node = NULL;
13483 isc_result_t result;
13485 dns_rdataset_init(&rdataset);
13486 if (rdata->type == dns_rdatatype_nsec3)
13487 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
13488 else
13489 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
13490 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
13491 (isc_stdtime_t) 0, &rdataset, NULL);
13492 if (result == ISC_R_NOTFOUND) {
13493 *flag = ISC_FALSE;
13494 result = ISC_R_SUCCESS;
13495 goto failure;
13498 for (result = dns_rdataset_first(&rdataset);
13499 result == ISC_R_SUCCESS;
13500 result = dns_rdataset_next(&rdataset)) {
13501 dns_rdata_t myrdata = DNS_RDATA_INIT;
13502 dns_rdataset_current(&rdataset, &myrdata);
13503 if (!dns_rdata_compare(&myrdata, rdata))
13504 break;
13506 dns_rdataset_disassociate(&rdataset);
13507 if (result == ISC_R_SUCCESS) {
13508 *flag = ISC_TRUE;
13509 } else if (result == ISC_R_NOMORE) {
13510 *flag = ISC_FALSE;
13511 result = ISC_R_SUCCESS;
13514 failure:
13515 if (node != NULL)
13516 dns_db_detachnode(db, &node);
13517 return (result);
13521 * Add records to signal the state of signing or of key removal.
13523 static isc_result_t
13524 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
13525 dns_dbversion_t *ver, dns_diff_t *diff)
13527 dns_difftuple_t *tuple, *newtuple = NULL;
13528 dns_rdata_dnskey_t dnskey;
13529 dns_rdata_t rdata = DNS_RDATA_INIT;
13530 isc_boolean_t flag;
13531 isc_region_t r;
13532 isc_result_t result = ISC_R_SUCCESS;
13533 isc_uint16_t keyid;
13534 unsigned char buf[5];
13535 dns_name_t *name = dns_db_origin(db);
13537 for (tuple = ISC_LIST_HEAD(diff->tuples);
13538 tuple != NULL;
13539 tuple = ISC_LIST_NEXT(tuple, link)) {
13540 if (tuple->rdata.type != dns_rdatatype_dnskey)
13541 continue;
13543 dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
13544 if ((dnskey.flags &
13545 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
13546 != DNS_KEYOWNER_ZONE)
13547 continue;
13549 dns_rdata_toregion(&tuple->rdata, &r);
13551 keyid = dst_region_computeid(&r, dnskey.algorithm);
13553 buf[0] = dnskey.algorithm;
13554 buf[1] = (keyid & 0xff00) >> 8;
13555 buf[2] = (keyid & 0xff);
13556 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
13557 buf[4] = 0;
13558 rdata.data = buf;
13559 rdata.length = sizeof(buf);
13560 rdata.type = privatetype;
13561 rdata.rdclass = tuple->rdata.rdclass;
13563 CHECK(rr_exists(db, ver, name, &rdata, &flag));
13564 if (flag)
13565 continue;
13566 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
13567 name, 0, &rdata, &newtuple));
13568 CHECK(do_one_tuple(&newtuple, db, ver, diff));
13569 INSIST(newtuple == NULL);
13571 * Remove any record which says this operation has already
13572 * completed.
13574 buf[4] = 1;
13575 CHECK(rr_exists(db, ver, name, &rdata, &flag));
13576 if (flag) {
13577 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
13578 name, 0, &rdata, &newtuple));
13579 CHECK(do_one_tuple(&newtuple, db, ver, diff));
13580 INSIST(newtuple == NULL);
13583 failure:
13584 return (result);
13587 static void
13588 sign_dnskey(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
13589 dns_diff_t *diff)
13591 isc_result_t result;
13592 isc_stdtime_t now, inception, soaexpire;
13593 isc_boolean_t check_ksk, keyset_kskonly;
13594 dst_key_t *zone_keys[MAXZONEKEYS];
13595 unsigned int nkeys = 0, i;
13597 result = find_zone_keys(zone, db, ver, zone->mctx, MAXZONEKEYS,
13598 zone_keys, &nkeys);
13599 if (result != ISC_R_SUCCESS) {
13600 dns_zone_log(zone, ISC_LOG_ERROR,
13601 "sign_dnskey:find_zone_keys -> %s\n",
13602 dns_result_totext(result));
13603 return;
13606 isc_stdtime_get(&now);
13607 inception = now - 3600; /* Allow for clock skew. */
13608 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
13610 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
13611 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
13613 result = del_sigs(zone, db, ver, &zone->origin, dns_rdatatype_dnskey,
13614 diff, zone_keys, nkeys, now);
13615 if (result != ISC_R_SUCCESS) {
13616 dns_zone_log(zone, ISC_LOG_ERROR,
13617 "sign_dnskey:del_sigs -> %s\n",
13618 dns_result_totext(result));
13619 goto failure;
13622 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey, diff,
13623 zone_keys, nkeys, zone->mctx, inception, soaexpire,
13624 check_ksk, keyset_kskonly);
13626 if (result != ISC_R_SUCCESS)
13627 dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:add_sigs -> %s\n",
13628 dns_result_totext(result));
13629 failure:
13630 for (i = 0; i < nkeys; i++)
13631 dst_key_free(&zone_keys[i]);
13634 static isc_result_t
13635 zone_rekey(dns_zone_t *zone) {
13636 isc_result_t result;
13637 dns_db_t *db = NULL;
13638 dns_dbnode_t *node = NULL;
13639 dns_dbversion_t *ver = NULL;
13640 dns_rdataset_t soaset, soasigs, keyset, keysigs;
13641 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
13642 dns_dnsseckey_t *key;
13643 dns_diff_t diff;
13644 isc_boolean_t commit = ISC_FALSE;
13645 dns_ttl_t ttl = 3600;
13646 const char *dir;
13647 isc_mem_t *mctx;
13648 isc_stdtime_t now;
13650 REQUIRE(DNS_ZONE_VALID(zone));
13652 ISC_LIST_INIT(dnskeys);
13653 ISC_LIST_INIT(keys);
13654 ISC_LIST_INIT(rmkeys);
13655 dns_rdataset_init(&soaset);
13656 dns_rdataset_init(&soasigs);
13657 dns_rdataset_init(&keyset);
13658 dns_rdataset_init(&keysigs);
13659 dir = dns_zone_getkeydirectory(zone);
13660 mctx = zone->mctx;
13661 dns_diff_init(mctx, &diff);
13662 isc_stdtime_get(&now);
13664 CHECK(dns_zone_getdb(zone, &db));
13665 CHECK(dns_db_newversion(db, &ver));
13666 CHECK(dns_db_getoriginnode(db, &node));
13668 dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
13670 /* Get the SOA record's TTL */
13671 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
13672 dns_rdatatype_none, 0, &soaset, &soasigs));
13673 ttl = soaset.ttl;
13674 dns_rdataset_disassociate(&soaset);
13676 /* Get the DNSKEY rdataset */
13677 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
13678 dns_rdatatype_none, 0, &keyset, &keysigs);
13679 if (result == ISC_R_SUCCESS) {
13680 ttl = keyset.ttl;
13681 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
13682 mctx, &keyset,
13683 &keysigs, &soasigs,
13684 ISC_FALSE, ISC_FALSE,
13685 &dnskeys));
13686 } else if (result != ISC_R_NOTFOUND)
13687 goto failure;
13689 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
13690 if (result == ISC_R_SUCCESS) {
13691 isc_boolean_t check_ksk;
13692 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
13694 CHECK(dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
13695 &zone->origin, ttl, &diff,
13696 ISC_TF(!check_ksk), mctx, logmsg));
13697 if (!ISC_LIST_EMPTY(diff.tuples)) {
13698 commit = ISC_TRUE;
13699 dns_diff_apply(&diff, db, ver);
13700 sign_dnskey(zone, db, ver, &diff);
13701 add_signing_records(db, zone->privatetype, ver, &diff);
13702 result = increment_soa_serial(db, ver, &diff, mctx);
13703 if (result == ISC_R_SUCCESS)
13704 zone_journal(zone, &diff, "zone_rekey");
13708 dns_db_closeversion(db, &ver, commit);
13710 if (commit) {
13711 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOTIFYRESIGN);
13713 for (key = ISC_LIST_HEAD(rmkeys);
13714 key != NULL;
13715 key = ISC_LIST_NEXT(key, link)) {
13716 zone_signwithkey(zone, dst_key_alg(key->key),
13717 dst_key_id(key->key), ISC_TRUE);
13720 for (key = ISC_LIST_HEAD(dnskeys);
13721 key != NULL;
13722 key = ISC_LIST_NEXT(key, link)) {
13723 if (key->first_sign) {
13724 zone_signwithkey(zone, dst_key_alg(key->key),
13725 dst_key_id(key->key),
13726 ISC_FALSE);
13727 key->is_active = ISC_TRUE;
13728 key->first_sign = ISC_FALSE;
13733 isc_time_settoepoch(&zone->refreshkeytime);
13734 for (key = ISC_LIST_HEAD(dnskeys);
13735 key != NULL;
13736 key = ISC_LIST_NEXT(key, link)) {
13737 isc_stdtime_t then;
13738 isc_time_t timenow, timethen;
13741 * If we are doing automatic key maintenace and the
13742 * key metadata indicates there is a key change event
13743 * scheduled in the future, set the key refresh timer.
13745 if (!DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
13746 break;
13748 result = next_keyevent(key->key, &then);
13749 if (result != ISC_R_SUCCESS)
13750 continue;
13752 isc_time_set(&timethen, then, 0);
13753 if (isc_time_isepoch(&zone->refreshkeytime) ||
13754 isc_time_compare(&timethen, &zone->refreshkeytime) < 0) {
13755 zone->refreshkeytime = timethen;
13756 zone_settimer(zone, &timenow);
13760 result = ISC_R_SUCCESS;
13762 failure:
13763 dns_diff_clear(&diff);
13765 clear_keylist(&dnskeys, mctx);
13766 clear_keylist(&keys, mctx);
13767 clear_keylist(&rmkeys, mctx);
13769 if (ver != NULL)
13770 dns_db_closeversion(db, &ver, ISC_FALSE);
13771 if (dns_rdataset_isassociated(&keyset))
13772 dns_rdataset_disassociate(&keyset);
13773 if (dns_rdataset_isassociated(&keysigs))
13774 dns_rdataset_disassociate(&keysigs);
13775 if (dns_rdataset_isassociated(&soasigs))
13776 dns_rdataset_disassociate(&soasigs);
13777 if (node != NULL)
13778 dns_db_detachnode(db, &node);
13779 if (db != NULL)
13780 dns_db_detach(&db);
13781 return (result);
13784 isc_result_t
13785 dns_zone_rekey(dns_zone_t *zone) {
13786 isc_result_t result;
13788 LOCK_ZONE(zone);
13789 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
13790 result = zone_rekey(zone);
13791 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
13792 UNLOCK_ZONE(zone);
13793 return (result);
13796 isc_result_t
13797 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
13798 unsigned int *errors)
13800 isc_result_t result;
13801 dns_dbnode_t *node = NULL;
13803 REQUIRE(DNS_ZONE_VALID(zone));
13804 REQUIRE(errors != NULL);
13806 result = dns_db_getoriginnode(db, &node);
13807 if (result != ISC_R_SUCCESS)
13808 return (result);
13809 result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
13810 ISC_FALSE);
13811 dns_db_detachnode(db, &node);
13812 return (result);