Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / zone.c
blob2f4a58f50d3402bf603edaa2289814a6e68028c8
1 /* $NetBSD: zone.c,v 1.14 2015/07/08 17:28:59 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2015 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 /*! \file */
22 #include <config.h>
23 #include <errno.h>
25 #include <isc/file.h>
26 #include <isc/hex.h>
27 #include <isc/mutex.h>
28 #include <isc/pool.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/stats.h>
36 #include <isc/stdtime.h>
37 #include <isc/strerror.h>
38 #include <isc/string.h>
39 #include <isc/taskpool.h>
40 #include <isc/thread.h>
41 #include <isc/timer.h>
42 #include <isc/util.h>
44 #include <dns/acache.h>
45 #include <dns/acl.h>
46 #include <dns/adb.h>
47 #include <dns/callbacks.h>
48 #include <dns/db.h>
49 #include <dns/dbiterator.h>
50 #include <dns/dlz.h>
51 #include <dns/dnssec.h>
52 #include <dns/events.h>
53 #include <dns/journal.h>
54 #include <dns/keydata.h>
55 #include <dns/keytable.h>
56 #include <dns/keyvalues.h>
57 #include <dns/log.h>
58 #include <dns/master.h>
59 #include <dns/masterdump.h>
60 #include <dns/message.h>
61 #include <dns/name.h>
62 #include <dns/nsec.h>
63 #include <dns/nsec3.h>
64 #include <dns/peer.h>
65 #include <dns/private.h>
66 #include <dns/rbt.h>
67 #include <dns/rcode.h>
68 #include <dns/rdata.h>
69 #include <dns/rdataclass.h>
70 #include <dns/rdatalist.h>
71 #include <dns/rdataset.h>
72 #include <dns/rdatasetiter.h>
73 #include <dns/rdatastruct.h>
74 #include <dns/rdatatype.h>
75 #include <dns/request.h>
76 #include <dns/resolver.h>
77 #include <dns/result.h>
78 #include <dns/rriterator.h>
79 #include <dns/soa.h>
80 #include <dns/ssu.h>
81 #include <dns/stats.h>
82 #include <dns/time.h>
83 #include <dns/tsig.h>
84 #include <dns/update.h>
85 #include <dns/xfrin.h>
86 #include <dns/zone.h>
87 #include <dns/zt.h>
89 #include <dst/dst.h>
91 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
92 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
94 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
95 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
97 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
98 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
100 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
101 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
103 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
104 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
106 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
107 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
109 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
110 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
113 * Ensure 'a' is at least 'min' but not more than 'max'.
115 #define RANGE(a, min, max) \
116 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
118 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
121 * Key flags
123 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
124 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
125 #define ALG(x) dst_key_alg(x)
128 * Default values.
130 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
131 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
132 #define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
133 #define RESIGN_DELAY 3600 /*%< 1 hour */
135 #ifndef DNS_MAX_EXPIRE
136 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
137 #endif
139 #ifndef DNS_DUMP_DELAY
140 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
141 #endif
143 typedef struct dns_notify dns_notify_t;
144 typedef struct dns_stub dns_stub_t;
145 typedef struct dns_load dns_load_t;
146 typedef struct dns_forward dns_forward_t;
147 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
148 typedef struct dns_io dns_io_t;
149 typedef ISC_LIST(dns_io_t) dns_iolist_t;
150 typedef struct dns_signing dns_signing_t;
151 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
152 typedef struct dns_nsec3chain dns_nsec3chain_t;
153 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
154 typedef struct dns_keyfetch dns_keyfetch_t;
155 typedef struct dns_asyncload dns_asyncload_t;
156 typedef struct dns_include dns_include_t;
158 #define DNS_ZONE_CHECKLOCK
159 #ifdef DNS_ZONE_CHECKLOCK
160 #define LOCK_ZONE(z) \
161 do { LOCK(&(z)->lock); \
162 INSIST((z)->locked == ISC_FALSE); \
163 (z)->locked = ISC_TRUE; \
164 } while (/*CONSTCOND*/0)
165 #define UNLOCK_ZONE(z) \
166 do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (/*CONSTCOND*/0)
167 #define LOCKED_ZONE(z) ((z)->locked)
168 #define TRYLOCK_ZONE(result, z) \
169 do { \
170 result = isc_mutex_trylock(&(z)->lock); \
171 if (result == ISC_R_SUCCESS) { \
172 INSIST((z)->locked == ISC_FALSE); \
173 (z)->locked = ISC_TRUE; \
175 } while (/*CONSTCOND*/0)
176 #else
177 #define LOCK_ZONE(z) LOCK(&(z)->lock)
178 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
179 #define LOCKED_ZONE(z) ISC_TRUE
180 #define TRYLOCK_ZONE(result, z) \
181 do { result = isc_mutex_trylock(&(z)->lock); } while (/*CONSTCOND*/0)
182 #endif
184 #ifdef ISC_RWLOCK_USEATOMIC
185 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
186 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
187 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
188 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
189 #else
190 #define ZONEDB_INITLOCK(l) isc_mutex_init(l)
191 #define ZONEDB_DESTROYLOCK(l) DESTROYLOCK(l)
192 #define ZONEDB_LOCK(l, t) LOCK(l)
193 #define ZONEDB_UNLOCK(l, t) UNLOCK(l)
194 #endif
196 struct dns_zone {
197 /* Unlocked */
198 unsigned int magic;
199 isc_mutex_t lock;
200 #ifdef DNS_ZONE_CHECKLOCK
201 isc_boolean_t locked;
202 #endif
203 isc_mem_t *mctx;
204 isc_refcount_t erefs;
206 #ifdef ISC_RWLOCK_USEATOMIC
207 isc_rwlock_t dblock;
208 #else
209 isc_mutex_t dblock;
210 #endif
211 dns_db_t *db; /* Locked by dblock */
213 /* Locked */
214 dns_zonemgr_t *zmgr;
215 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
216 isc_timer_t *timer;
217 unsigned int irefs;
218 dns_name_t origin;
219 char *masterfile;
220 ISC_LIST(dns_include_t) includes; /* Include files */
221 ISC_LIST(dns_include_t) newincludes; /* Loading */
222 unsigned int nincludes;
223 dns_masterformat_t masterformat;
224 char *journal;
225 isc_int32_t journalsize;
226 dns_rdataclass_t rdclass;
227 dns_zonetype_t type;
228 unsigned int flags;
229 unsigned int options;
230 unsigned int options2;
231 unsigned int db_argc;
232 char **db_argv;
233 isc_time_t expiretime;
234 isc_time_t refreshtime;
235 isc_time_t dumptime;
236 isc_time_t loadtime;
237 isc_time_t notifytime;
238 isc_time_t resigntime;
239 isc_time_t keywarntime;
240 isc_time_t signingtime;
241 isc_time_t nsec3chaintime;
242 isc_time_t refreshkeytime;
243 isc_uint32_t refreshkeyinterval;
244 isc_uint32_t refreshkeycount;
245 isc_uint32_t refresh;
246 isc_uint32_t retry;
247 isc_uint32_t expire;
248 isc_uint32_t minimum;
249 isc_stdtime_t key_expiry;
250 isc_stdtime_t log_key_expired_timer;
251 char *keydirectory;
253 isc_uint32_t maxrefresh;
254 isc_uint32_t minrefresh;
255 isc_uint32_t maxretry;
256 isc_uint32_t minretry;
258 isc_sockaddr_t *masters;
259 isc_dscp_t *masterdscps;
260 dns_name_t **masterkeynames;
261 isc_boolean_t *mastersok;
262 unsigned int masterscnt;
263 unsigned int curmaster;
264 isc_sockaddr_t masteraddr;
265 dns_notifytype_t notifytype;
266 isc_sockaddr_t *notify;
267 dns_name_t **notifykeynames;
268 isc_dscp_t *notifydscp;
269 unsigned int notifycnt;
270 isc_sockaddr_t notifyfrom;
271 isc_task_t *task;
272 isc_task_t *loadtask;
273 isc_sockaddr_t notifysrc4;
274 isc_sockaddr_t notifysrc6;
275 isc_sockaddr_t xfrsource4;
276 isc_sockaddr_t xfrsource6;
277 isc_sockaddr_t altxfrsource4;
278 isc_sockaddr_t altxfrsource6;
279 isc_sockaddr_t sourceaddr;
280 isc_dscp_t notifysrc4dscp;
281 isc_dscp_t notifysrc6dscp;
282 isc_dscp_t xfrsource4dscp;
283 isc_dscp_t xfrsource6dscp;
284 isc_dscp_t altxfrsource4dscp;
285 isc_dscp_t altxfrsource6dscp;
286 dns_xfrin_ctx_t *xfr; /* task locked */
287 dns_tsigkey_t *tsigkey; /* key used for xfr */
288 /* Access Control Lists */
289 dns_acl_t *update_acl;
290 dns_acl_t *forward_acl;
291 dns_acl_t *notify_acl;
292 dns_acl_t *query_acl;
293 dns_acl_t *queryon_acl;
294 dns_acl_t *xfr_acl;
295 isc_boolean_t update_disabled;
296 isc_boolean_t zero_no_soa_ttl;
297 dns_severity_t check_names;
298 ISC_LIST(dns_notify_t) notifies;
299 dns_request_t *request;
300 dns_loadctx_t *lctx;
301 dns_io_t *readio;
302 dns_dumpctx_t *dctx;
303 dns_io_t *writeio;
304 isc_uint32_t maxxfrin;
305 isc_uint32_t maxxfrout;
306 isc_uint32_t idlein;
307 isc_uint32_t idleout;
308 isc_event_t ctlevent;
309 dns_ssutable_t *ssutable;
310 isc_uint32_t sigvalidityinterval;
311 isc_uint32_t sigresigninginterval;
312 dns_view_t *view;
313 dns_acache_t *acache;
314 dns_checkmxfunc_t checkmx;
315 dns_checksrvfunc_t checksrv;
316 dns_checknsfunc_t checkns;
318 * Zones in certain states such as "waiting for zone transfer"
319 * or "zone transfer in progress" are kept on per-state linked lists
320 * in the zone manager using the 'statelink' field. The 'statelist'
321 * field points at the list the zone is currently on. It the zone
322 * is not on any such list, statelist is NULL.
324 ISC_LINK(dns_zone_t) statelink;
325 dns_zonelist_t *statelist;
327 * Statistics counters about zone management.
329 isc_stats_t *stats;
331 * Optional per-zone statistics counters. Counted outside of this
332 * module.
334 dns_zonestat_level_t statlevel;
335 isc_boolean_t requeststats_on;
336 isc_stats_t *requeststats;
337 dns_stats_t *rcvquerystats;
338 isc_uint32_t notifydelay;
339 dns_isselffunc_t isself;
340 void *isselfarg;
342 char * strnamerd;
343 char * strname;
344 char * strrdclass;
345 char * strviewname;
348 * Serial number for deferred journal compaction.
350 isc_uint32_t compact_serial;
352 * Keys that are signing the zone for the first time.
354 dns_signinglist_t signing;
355 dns_nsec3chainlist_t nsec3chain;
357 * Signing / re-signing quantum stopping parameters.
359 isc_uint32_t signatures;
360 isc_uint32_t nodes;
361 dns_rdatatype_t privatetype;
364 * Autosigning/key-maintenance options
366 isc_uint32_t keyopts;
369 * True if added by "rndc addzone"
371 isc_boolean_t added;
374 * response policy data to be relayed to the database
376 dns_rpz_zones_t *rpzs;
377 dns_rpz_num_t rpz_num;
380 * Serial number update method.
382 dns_updatemethod_t updatemethod;
385 * whether ixfr is requested
387 isc_boolean_t requestixfr;
390 * Outstanding forwarded UPDATE requests.
392 dns_forwardlist_t forwards;
394 dns_zone_t *raw;
395 dns_zone_t *secure;
397 isc_boolean_t sourceserialset;
398 isc_uint32_t sourceserial;
401 * maximum zone ttl
403 dns_ttl_t maxttl;
407 typedef struct {
408 dns_diff_t *diff;
409 isc_boolean_t offline;
410 } zonediff_t;
412 #define zonediff_init(z, d) \
413 do { \
414 zonediff_t *_z = (z); \
415 (_z)->diff = (d); \
416 (_z)->offline = ISC_FALSE; \
417 } while (/*CONSTCOND*/0)
419 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
420 #define DNS_ZONE_SETFLAG(z,f) do { \
421 INSIST(LOCKED_ZONE(z)); \
422 (z)->flags |= (f); \
423 } while (/*CONSTCOND*/0)
424 #define DNS_ZONE_CLRFLAG(z,f) do { \
425 INSIST(LOCKED_ZONE(z)); \
426 (z)->flags &= ~(f); \
427 } while (/*CONSTCOND*/0)
428 /* XXX MPA these may need to go back into zone.h */
429 #define DNS_ZONEFLG_REFRESH 0x00000001U /*%< refresh check in progress */
430 #define DNS_ZONEFLG_NEEDDUMP 0x00000002U /*%< zone need consolidation */
431 #define DNS_ZONEFLG_USEVC 0x00000004U /*%< use tcp for refresh query */
432 #define DNS_ZONEFLG_DUMPING 0x00000008U /*%< a dump is in progress */
433 #define DNS_ZONEFLG_HASINCLUDE 0x00000010U /*%< $INCLUDE in zone file */
434 #define DNS_ZONEFLG_LOADED 0x00000020U /*%< database has loaded */
435 #define DNS_ZONEFLG_EXITING 0x00000040U /*%< zone is being destroyed */
436 #define DNS_ZONEFLG_EXPIRED 0x00000080U /*%< zone has expired */
437 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /*%< refresh check needed */
438 #define DNS_ZONEFLG_UPTODATE 0x00000200U /*%< zone contents are
439 * uptodate */
440 #define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /*%< need to send out notify
441 * messages */
442 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /*%< generate a journal diff on
443 * reload */
444 #define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
445 * zone with no masters
446 * occurred */
447 #define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
448 #define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
449 * from SOA (if not set, we
450 * are still using
451 * default timer values) */
452 #define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
453 #define DNS_ZONEFLG_NOREFRESH 0x00010000U
454 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
455 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
456 #define DNS_ZONEFLG_SHUTDOWN 0x00080000U
457 #define DNS_ZONEFLAG_NOIXFR 0x00100000U /*%< IXFR failed, force AXFR */
458 #define DNS_ZONEFLG_FLUSH 0x00200000U
459 #define DNS_ZONEFLG_NOEDNS 0x00400000U
460 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
461 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
462 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
463 #define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */
464 #define DNS_ZONEFLG_THAW 0x08000000U
465 #define DNS_ZONEFLG_LOADPENDING 0x10000000U /*%< Loading scheduled */
466 #define DNS_ZONEFLG_NODELAY 0x20000000U
467 #define DNS_ZONEFLG_SENDSECURE 0x40000000U
468 #define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
469 * due to the zone just
470 * being loaded for the
471 * first time. */
473 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
474 #define DNS_ZONE_OPTION2(z,o) (((z)->options2 & (o)) != 0)
475 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
477 /* Flags for zone_load() */
478 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
479 #define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
480 load. */
482 #define UNREACH_CHACHE_SIZE 10U
483 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
485 #define CHECK(op) \
486 do { result = (op); \
487 if (result != ISC_R_SUCCESS) goto failure; \
488 } while (/*CONSTCOND*/0)
490 struct dns_unreachable {
491 isc_sockaddr_t remote;
492 isc_sockaddr_t local;
493 isc_uint32_t expire;
494 isc_uint32_t last;
495 isc_uint32_t count;
498 struct dns_zonemgr {
499 unsigned int magic;
500 isc_mem_t * mctx;
501 int refs; /* Locked by rwlock */
502 isc_taskmgr_t * taskmgr;
503 isc_timermgr_t * timermgr;
504 isc_socketmgr_t * socketmgr;
505 isc_taskpool_t * zonetasks;
506 isc_taskpool_t * loadtasks;
507 isc_task_t * task;
508 isc_pool_t * mctxpool;
509 isc_ratelimiter_t * notifyrl;
510 isc_ratelimiter_t * refreshrl;
511 isc_ratelimiter_t * startupnotifyrl;
512 isc_ratelimiter_t * startuprefreshrl;
513 isc_rwlock_t rwlock;
514 isc_mutex_t iolock;
515 isc_rwlock_t urlock;
517 /* Locked by rwlock. */
518 dns_zonelist_t zones;
519 dns_zonelist_t waiting_for_xfrin;
520 dns_zonelist_t xfrin_in_progress;
522 /* Configuration data. */
523 isc_uint32_t transfersin;
524 isc_uint32_t transfersperns;
525 unsigned int notifyrate;
526 unsigned int startupnotifyrate;
527 unsigned int serialqueryrate;
528 unsigned int startupserialqueryrate;
530 /* Locked by iolock */
531 isc_uint32_t iolimit;
532 isc_uint32_t ioactive;
533 dns_iolist_t high;
534 dns_iolist_t low;
536 /* Locked by urlock. */
537 /* LRU cache */
538 struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
542 * Hold notify state.
544 struct dns_notify {
545 unsigned int magic;
546 unsigned int flags;
547 isc_mem_t *mctx;
548 dns_zone_t *zone;
549 dns_adbfind_t *find;
550 dns_request_t *request;
551 dns_name_t ns;
552 isc_sockaddr_t dst;
553 dns_tsigkey_t *key;
554 isc_dscp_t dscp;
555 ISC_LINK(dns_notify_t) link;
556 isc_event_t *event;
559 #define DNS_NOTIFY_NOSOA 0x0001U
560 #define DNS_NOTIFY_STARTUP 0x0002U
563 * dns_stub holds state while performing a 'stub' transfer.
564 * 'db' is the zone's 'db' or a new one if this is the initial
565 * transfer.
568 struct dns_stub {
569 unsigned int magic;
570 isc_mem_t *mctx;
571 dns_zone_t *zone;
572 dns_db_t *db;
573 dns_dbversion_t *version;
577 * Hold load state.
579 struct dns_load {
580 unsigned int magic;
581 isc_mem_t *mctx;
582 dns_zone_t *zone;
583 dns_db_t *db;
584 isc_time_t loadtime;
585 dns_rdatacallbacks_t callbacks;
589 * Hold forward state.
591 struct dns_forward {
592 unsigned int magic;
593 isc_mem_t *mctx;
594 dns_zone_t *zone;
595 isc_buffer_t *msgbuf;
596 dns_request_t *request;
597 isc_uint32_t which;
598 isc_sockaddr_t addr;
599 dns_updatecallback_t callback;
600 void *callback_arg;
601 unsigned int options;
602 ISC_LINK(dns_forward_t) link;
606 * Hold IO request state.
608 struct dns_io {
609 unsigned int magic;
610 dns_zonemgr_t *zmgr;
611 isc_boolean_t high;
612 isc_task_t *task;
613 ISC_LINK(dns_io_t) link;
614 isc_event_t *event;
618 * Hold state for when we are signing a zone with a new
619 * DNSKEY as result of an update.
621 struct dns_signing {
622 unsigned int magic;
623 dns_db_t *db;
624 dns_dbiterator_t *dbiterator;
625 dns_secalg_t algorithm;
626 isc_uint16_t keyid;
627 isc_boolean_t delete;
628 isc_boolean_t done;
629 ISC_LINK(dns_signing_t) link;
632 struct dns_nsec3chain {
633 unsigned int magic;
634 dns_db_t *db;
635 dns_dbiterator_t *dbiterator;
636 dns_rdata_nsec3param_t nsec3param;
637 unsigned char salt[255];
638 isc_boolean_t done;
639 isc_boolean_t seen_nsec;
640 isc_boolean_t delete_nsec;
641 isc_boolean_t save_delete_nsec;
642 ISC_LINK(dns_nsec3chain_t) link;
644 /*%<
645 * 'dbiterator' contains a iterator for the database. If we are creating
646 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
647 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
648 * iterated.
650 * 'nsec3param' contains the parameters of the NSEC3 chain being created
651 * or removed.
653 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
655 * 'seen_nsec' will be set to true if, while iterating the zone to create a
656 * NSEC3 chain, a NSEC record is seen.
658 * 'delete_nsec' will be set to true if, at the completion of the creation
659 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
660 * are in the process of deleting the NSEC chain.
662 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
663 * so it can be recovered in the event of a error.
666 struct dns_keyfetch {
667 dns_fixedname_t name;
668 dns_rdataset_t keydataset;
669 dns_rdataset_t dnskeyset;
670 dns_rdataset_t dnskeysigset;
671 dns_zone_t *zone;
672 dns_db_t *db;
673 dns_fetch_t *fetch;
677 * Hold state for an asynchronous load
679 struct dns_asyncload {
680 dns_zone_t *zone;
681 dns_zt_zoneloaded_t loaded;
682 void *loaded_arg;
686 * Reference to an include file encountered during loading
688 struct dns_include {
689 char *name;
690 isc_time_t filetime;
691 ISC_LINK(dns_include_t) link;
694 #define HOUR 3600
695 #define DAY (24*HOUR)
696 #define MONTH (30*DAY)
699 * These can be overridden by the -T mkeytimers option on the command
700 * line, so that we can test with shorter periods than specified in
701 * RFC 5011.
703 unsigned int dns_zone_mkey_hour = HOUR;
704 unsigned int dns_zone_mkey_day = (24 * HOUR);
705 unsigned int dns_zone_mkey_month = (30 * DAY);
708 #define SEND_BUFFER_SIZE 2048
710 static void zone_settimer(dns_zone_t *, isc_time_t *);
711 static void cancel_refresh(dns_zone_t *);
712 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
713 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
714 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
715 ISC_FORMAT_PRINTF(3, 4);
716 static void queue_xfrin(dns_zone_t *zone);
717 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
718 dns_diff_t *diff, dns_diffop_t op,
719 dns_name_t *name, dns_ttl_t ttl,
720 dns_rdata_t *rdata);
721 static void zone_unload(dns_zone_t *zone);
722 static void zone_expire(dns_zone_t *zone);
723 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
724 static void zone_idetach(dns_zone_t **zonep);
725 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
726 isc_boolean_t dump);
727 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
728 static inline void zone_detachdb(dns_zone_t *zone);
729 static isc_result_t default_journal(dns_zone_t *zone);
730 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
731 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
732 isc_time_t loadtime, isc_result_t result);
733 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
734 static void zone_shutdown(isc_task_t *, isc_event_t *);
735 static void zone_loaddone(void *arg, isc_result_t result);
736 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
737 isc_time_t loadtime);
738 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
739 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
740 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
741 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
742 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
743 isc_uint32_t serial);
745 #if 0
746 /* ondestroy example */
747 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
748 #endif
750 static void refresh_callback(isc_task_t *, isc_event_t *);
751 static void stub_callback(isc_task_t *, isc_event_t *);
752 static void queue_soa_query(dns_zone_t *zone);
753 static void soa_query(isc_task_t *, isc_event_t *);
754 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
755 dns_stub_t *stub);
756 static int message_count(dns_message_t *msg, dns_section_t section,
757 dns_rdatatype_t type);
758 static void notify_cancel(dns_zone_t *zone);
759 static void notify_find_address(dns_notify_t *notify);
760 static void notify_send(dns_notify_t *notify);
761 static isc_result_t notify_createmessage(dns_zone_t *zone,
762 unsigned int flags,
763 dns_message_t **messagep);
764 static void notify_done(isc_task_t *task, isc_event_t *event);
765 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
766 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
767 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
768 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
769 dns_zone_t *zone);
770 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
771 static void zonemgr_free(dns_zonemgr_t *zmgr);
772 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
773 isc_task_t *task, isc_taskaction_t action,
774 void *arg, dns_io_t **iop);
775 static void zonemgr_putio(dns_io_t **iop);
776 static void zonemgr_cancelio(dns_io_t *io);
778 static isc_result_t
779 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
780 unsigned int *soacount, isc_uint32_t *serial,
781 isc_uint32_t *refresh, isc_uint32_t *retry,
782 isc_uint32_t *expire, isc_uint32_t *minimum,
783 unsigned int *errors);
785 static void zone_freedbargs(dns_zone_t *zone);
786 static void forward_callback(isc_task_t *task, isc_event_t *event);
787 static void zone_saveunique(dns_zone_t *zone, const char *path,
788 const char *templat);
789 static void zone_maintenance(dns_zone_t *zone);
790 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
791 static void dump_done(void *arg, isc_result_t result);
792 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
793 isc_uint16_t keyid, isc_boolean_t delete);
794 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
795 dns_dbnode_t *node, dns_name_t *name,
796 dns_diff_t *diff);
797 static void zone_rekey(dns_zone_t *zone);
798 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
799 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
800 unsigned int value);
802 #define ENTER zone_debuglog(zone, me, 1, "enter")
804 static const unsigned int dbargc_default = 1;
805 static const char *dbargv_default[] = { "rbt" };
807 #define DNS_ZONE_JITTER_ADD(a, b, c) \
808 do { \
809 isc_interval_t _i; \
810 isc_uint32_t _j; \
811 _j = isc_random_jitter((b), (b)/4); \
812 isc_interval_set(&_i, _j, 0); \
813 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
814 dns_zone_log(zone, ISC_LOG_WARNING, \
815 "epoch approaching: upgrade required: " \
816 "now + %s failed", #b); \
817 isc_interval_set(&_i, _j/2, 0); \
818 (void)isc_time_add((a), &_i, (c)); \
820 } while (/*CONSTCOND*/0)
822 #define DNS_ZONE_TIME_ADD(a, b, c) \
823 do { \
824 isc_interval_t _i; \
825 isc_interval_set(&_i, (b), 0); \
826 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
827 dns_zone_log(zone, ISC_LOG_WARNING, \
828 "epoch approaching: upgrade required: " \
829 "now + %s failed", #b); \
830 isc_interval_set(&_i, (b)/2, 0); \
831 (void)isc_time_add((a), &_i, (c)); \
833 } while (/*CONSTCOND*/0)
835 typedef struct nsec3param nsec3param_t;
836 struct nsec3param {
837 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
838 unsigned int length;
839 isc_boolean_t nsec;
840 isc_boolean_t replace;
841 ISC_LINK(nsec3param_t) link;
843 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
844 struct np3event {
845 isc_event_t event;
846 nsec3param_t params;
850 * Increment resolver-related statistics counters. Zone must be locked.
852 static inline void
853 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
854 if (zone->stats != NULL)
855 isc_stats_increment(zone->stats, counter);
858 /***
859 *** Public functions.
860 ***/
862 isc_result_t
863 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
864 isc_result_t result;
865 dns_zone_t *zone;
866 isc_time_t now;
868 REQUIRE(zonep != NULL && *zonep == NULL);
869 REQUIRE(mctx != NULL);
871 TIME_NOW(&now);
872 zone = isc_mem_get(mctx, sizeof(*zone));
873 if (zone == NULL)
874 return (ISC_R_NOMEMORY);
876 zone->mctx = NULL;
877 isc_mem_attach(mctx, &zone->mctx);
879 result = isc_mutex_init(&zone->lock);
880 if (result != ISC_R_SUCCESS)
881 goto free_zone;
883 result = ZONEDB_INITLOCK(&zone->dblock);
884 if (result != ISC_R_SUCCESS)
885 goto free_mutex;
887 /* XXX MPA check that all elements are initialised */
888 #ifdef DNS_ZONE_CHECKLOCK
889 zone->locked = ISC_FALSE;
890 #endif
891 zone->db = NULL;
892 zone->zmgr = NULL;
893 ISC_LINK_INIT(zone, link);
894 result = isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
895 if (result != ISC_R_SUCCESS)
896 goto free_dblock;
897 zone->irefs = 0;
898 dns_name_init(&zone->origin, NULL);
899 zone->strnamerd = NULL;
900 zone->strname = NULL;
901 zone->strrdclass = NULL;
902 zone->strviewname = NULL;
903 zone->masterfile = NULL;
904 ISC_LIST_INIT(zone->includes);
905 ISC_LIST_INIT(zone->newincludes);
906 zone->nincludes = 0;
907 zone->masterformat = dns_masterformat_none;
908 zone->keydirectory = NULL;
909 zone->journalsize = -1;
910 zone->journal = NULL;
911 zone->rdclass = dns_rdataclass_none;
912 zone->type = dns_zone_none;
913 zone->flags = 0;
914 zone->options = 0;
915 zone->keyopts = 0;
916 zone->db_argc = 0;
917 zone->db_argv = NULL;
918 isc_time_settoepoch(&zone->expiretime);
919 isc_time_settoepoch(&zone->refreshtime);
920 isc_time_settoepoch(&zone->dumptime);
921 isc_time_settoepoch(&zone->loadtime);
922 zone->notifytime = now;
923 isc_time_settoepoch(&zone->resigntime);
924 isc_time_settoepoch(&zone->keywarntime);
925 isc_time_settoepoch(&zone->signingtime);
926 isc_time_settoepoch(&zone->nsec3chaintime);
927 isc_time_settoepoch(&zone->refreshkeytime);
928 zone->refreshkeyinterval = 0;
929 zone->refreshkeycount = 0;
930 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
931 zone->retry = DNS_ZONE_DEFAULTRETRY;
932 zone->expire = 0;
933 zone->minimum = 0;
934 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
935 zone->minrefresh = DNS_ZONE_MINREFRESH;
936 zone->maxretry = DNS_ZONE_MAXRETRY;
937 zone->minretry = DNS_ZONE_MINRETRY;
938 zone->masters = NULL;
939 zone->masterdscps = NULL;
940 zone->masterkeynames = NULL;
941 zone->mastersok = NULL;
942 zone->masterscnt = 0;
943 zone->curmaster = 0;
944 zone->maxttl = 0;
945 zone->notify = NULL;
946 zone->notifykeynames = NULL;
947 zone->notifydscp = NULL;
948 zone->notifytype = dns_notifytype_yes;
949 zone->notifycnt = 0;
950 zone->task = NULL;
951 zone->loadtask = NULL;
952 zone->update_acl = NULL;
953 zone->forward_acl = NULL;
954 zone->notify_acl = NULL;
955 zone->query_acl = NULL;
956 zone->queryon_acl = NULL;
957 zone->xfr_acl = NULL;
958 zone->update_disabled = ISC_FALSE;
959 zone->zero_no_soa_ttl = ISC_TRUE;
960 zone->check_names = dns_severity_ignore;
961 zone->request = NULL;
962 zone->lctx = NULL;
963 zone->readio = NULL;
964 zone->dctx = NULL;
965 zone->writeio = NULL;
966 zone->timer = NULL;
967 zone->idlein = DNS_DEFAULT_IDLEIN;
968 zone->idleout = DNS_DEFAULT_IDLEOUT;
969 zone->log_key_expired_timer = 0;
970 ISC_LIST_INIT(zone->notifies);
971 isc_sockaddr_any(&zone->notifysrc4);
972 isc_sockaddr_any6(&zone->notifysrc6);
973 isc_sockaddr_any(&zone->xfrsource4);
974 isc_sockaddr_any6(&zone->xfrsource6);
975 isc_sockaddr_any(&zone->altxfrsource4);
976 isc_sockaddr_any6(&zone->altxfrsource6);
977 zone->notifysrc4dscp = -1;
978 zone->notifysrc6dscp = -1;
979 zone->xfrsource4dscp = -1;
980 zone->xfrsource6dscp = -1;
981 zone->altxfrsource4dscp = -1;
982 zone->altxfrsource6dscp = -1;
983 zone->xfr = NULL;
984 zone->tsigkey = NULL;
985 zone->maxxfrin = MAX_XFER_TIME;
986 zone->maxxfrout = MAX_XFER_TIME;
987 zone->ssutable = NULL;
988 zone->sigvalidityinterval = 30 * 24 * 3600;
989 zone->sigresigninginterval = 7 * 24 * 3600;
990 zone->view = NULL;
991 zone->acache = NULL;
992 zone->checkmx = NULL;
993 zone->checksrv = NULL;
994 zone->checkns = NULL;
995 ISC_LINK_INIT(zone, statelink);
996 zone->statelist = NULL;
997 zone->stats = NULL;
998 zone->requeststats_on = ISC_FALSE;
999 zone->statlevel = dns_zonestat_none;
1000 zone->requeststats = NULL;
1001 zone->rcvquerystats = NULL;
1002 zone->notifydelay = 5;
1003 zone->isself = NULL;
1004 zone->isselfarg = NULL;
1005 ISC_LIST_INIT(zone->signing);
1006 ISC_LIST_INIT(zone->nsec3chain);
1007 zone->signatures = 10;
1008 zone->nodes = 100;
1009 zone->privatetype = (dns_rdatatype_t)0xffffU;
1010 zone->added = ISC_FALSE;
1011 zone->rpzs = NULL;
1012 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1013 ISC_LIST_INIT(zone->forwards);
1014 zone->raw = NULL;
1015 zone->secure = NULL;
1016 zone->sourceserial = 0;
1017 zone->sourceserialset = ISC_FALSE;
1019 zone->magic = ZONE_MAGIC;
1021 /* Must be after magic is set. */
1022 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1023 if (result != ISC_R_SUCCESS)
1024 goto free_erefs;
1026 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1027 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
1028 NULL, NULL);
1029 *zonep = zone;
1030 return (ISC_R_SUCCESS);
1032 free_erefs:
1033 isc_refcount_decrement(&zone->erefs, NULL);
1034 isc_refcount_destroy(&zone->erefs);
1036 free_dblock:
1037 ZONEDB_DESTROYLOCK(&zone->dblock);
1039 free_mutex:
1040 DESTROYLOCK(&zone->lock);
1042 free_zone:
1043 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1044 return (result);
1048 * Free a zone. Because we require that there be no more
1049 * outstanding events or references, no locking is necessary.
1051 static void
1052 zone_free(dns_zone_t *zone) {
1053 isc_mem_t *mctx = NULL;
1054 dns_signing_t *signing;
1055 dns_nsec3chain_t *nsec3chain;
1056 dns_include_t *include;
1058 REQUIRE(DNS_ZONE_VALID(zone));
1059 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
1060 REQUIRE(zone->irefs == 0);
1061 REQUIRE(!LOCKED_ZONE(zone));
1062 REQUIRE(zone->timer == NULL);
1063 REQUIRE(zone->zmgr == NULL);
1066 * Managed objects. Order is important.
1068 if (zone->request != NULL)
1069 dns_request_destroy(&zone->request); /* XXXMPA */
1070 INSIST(zone->readio == NULL);
1071 INSIST(zone->statelist == NULL);
1072 INSIST(zone->writeio == NULL);
1074 if (zone->task != NULL)
1075 isc_task_detach(&zone->task);
1076 if (zone->loadtask != NULL)
1077 isc_task_detach(&zone->loadtask);
1079 /* Unmanaged objects */
1080 for (signing = ISC_LIST_HEAD(zone->signing);
1081 signing != NULL;
1082 signing = ISC_LIST_HEAD(zone->signing)) {
1083 ISC_LIST_UNLINK(zone->signing, signing, link);
1084 dns_db_detach(&signing->db);
1085 dns_dbiterator_destroy(&signing->dbiterator);
1086 isc_mem_put(zone->mctx, signing, sizeof *signing);
1088 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1089 nsec3chain != NULL;
1090 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1091 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1092 dns_db_detach(&nsec3chain->db);
1093 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1094 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1096 for (include = ISC_LIST_HEAD(zone->includes);
1097 include != NULL;
1098 include = ISC_LIST_HEAD(zone->includes)) {
1099 ISC_LIST_UNLINK(zone->includes, include, link);
1100 isc_mem_free(zone->mctx, include->name);
1101 isc_mem_put(zone->mctx, include, sizeof *include);
1103 for (include = ISC_LIST_HEAD(zone->newincludes);
1104 include != NULL;
1105 include = ISC_LIST_HEAD(zone->newincludes)) {
1106 ISC_LIST_UNLINK(zone->newincludes, include, link);
1107 isc_mem_free(zone->mctx, include->name);
1108 isc_mem_put(zone->mctx, include, sizeof *include);
1110 if (zone->masterfile != NULL)
1111 isc_mem_free(zone->mctx, zone->masterfile);
1112 zone->masterfile = NULL;
1113 if (zone->keydirectory != NULL)
1114 isc_mem_free(zone->mctx, zone->keydirectory);
1115 zone->keydirectory = NULL;
1116 zone->journalsize = -1;
1117 if (zone->journal != NULL)
1118 isc_mem_free(zone->mctx, zone->journal);
1119 zone->journal = NULL;
1120 if (zone->stats != NULL)
1121 isc_stats_detach(&zone->stats);
1122 if (zone->requeststats != NULL)
1123 isc_stats_detach(&zone->requeststats);
1124 if (zone->rcvquerystats != NULL)
1125 dns_stats_detach(&zone->rcvquerystats);
1126 if (zone->db != NULL)
1127 zone_detachdb(zone);
1128 if (zone->acache != NULL)
1129 dns_acache_detach(&zone->acache);
1130 if (zone->rpzs != NULL) {
1131 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1132 dns_rpz_detach_rpzs(&zone->rpzs);
1133 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1135 zone_freedbargs(zone);
1136 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL, NULL, 0)
1137 == ISC_R_SUCCESS);
1138 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0)
1139 == ISC_R_SUCCESS);
1140 zone->check_names = dns_severity_ignore;
1141 if (zone->update_acl != NULL)
1142 dns_acl_detach(&zone->update_acl);
1143 if (zone->forward_acl != NULL)
1144 dns_acl_detach(&zone->forward_acl);
1145 if (zone->notify_acl != NULL)
1146 dns_acl_detach(&zone->notify_acl);
1147 if (zone->query_acl != NULL)
1148 dns_acl_detach(&zone->query_acl);
1149 if (zone->queryon_acl != NULL)
1150 dns_acl_detach(&zone->queryon_acl);
1151 if (zone->xfr_acl != NULL)
1152 dns_acl_detach(&zone->xfr_acl);
1153 if (dns_name_dynamic(&zone->origin))
1154 dns_name_free(&zone->origin, zone->mctx);
1155 if (zone->strnamerd != NULL)
1156 isc_mem_free(zone->mctx, zone->strnamerd);
1157 if (zone->strname != NULL)
1158 isc_mem_free(zone->mctx, zone->strname);
1159 if (zone->strrdclass != NULL)
1160 isc_mem_free(zone->mctx, zone->strrdclass);
1161 if (zone->strviewname != NULL)
1162 isc_mem_free(zone->mctx, zone->strviewname);
1163 if (zone->ssutable != NULL)
1164 dns_ssutable_detach(&zone->ssutable);
1166 /* last stuff */
1167 ZONEDB_DESTROYLOCK(&zone->dblock);
1168 DESTROYLOCK(&zone->lock);
1169 isc_refcount_destroy(&zone->erefs);
1170 zone->magic = 0;
1171 mctx = zone->mctx;
1172 isc_mem_put(mctx, zone, sizeof(*zone));
1173 isc_mem_detach(&mctx);
1177 * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
1178 * Caller should hold zone lock.
1180 static inline isc_boolean_t
1181 inline_secure(dns_zone_t *zone) {
1182 REQUIRE(DNS_ZONE_VALID(zone));
1183 if (zone->raw != NULL)
1184 return (ISC_TRUE);
1185 return (ISC_FALSE);
1189 * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1190 * Caller should hold zone lock.
1192 static inline isc_boolean_t
1193 inline_raw(dns_zone_t *zone) {
1194 REQUIRE(DNS_ZONE_VALID(zone));
1195 if (zone->secure != NULL)
1196 return (ISC_TRUE);
1197 return (ISC_FALSE);
1201 * Single shot.
1203 void
1204 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1205 char namebuf[1024];
1207 REQUIRE(DNS_ZONE_VALID(zone));
1208 REQUIRE(rdclass != dns_rdataclass_none);
1211 * Test and set.
1213 LOCK_ZONE(zone);
1214 INSIST(zone != zone->raw);
1215 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1216 zone->rdclass == rdclass);
1217 zone->rdclass = rdclass;
1219 if (zone->strnamerd != NULL)
1220 isc_mem_free(zone->mctx, zone->strnamerd);
1221 if (zone->strrdclass != NULL)
1222 isc_mem_free(zone->mctx, zone->strrdclass);
1224 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1225 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1226 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1227 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1229 if (inline_secure(zone))
1230 dns_zone_setclass(zone->raw, rdclass);
1231 UNLOCK_ZONE(zone);
1234 dns_rdataclass_t
1235 dns_zone_getclass(dns_zone_t *zone) {
1236 REQUIRE(DNS_ZONE_VALID(zone));
1238 return (zone->rdclass);
1241 void
1242 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1243 REQUIRE(DNS_ZONE_VALID(zone));
1245 LOCK_ZONE(zone);
1246 zone->notifytype = notifytype;
1247 UNLOCK_ZONE(zone);
1250 isc_result_t
1251 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1252 isc_result_t result;
1253 unsigned int soacount;
1255 REQUIRE(DNS_ZONE_VALID(zone));
1256 REQUIRE(serialp != NULL);
1258 LOCK_ZONE(zone);
1259 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1260 if (zone->db != NULL) {
1261 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1262 serialp, NULL, NULL, NULL, NULL,
1263 NULL);
1264 if (result == ISC_R_SUCCESS && soacount == 0)
1265 result = ISC_R_FAILURE;
1266 } else
1267 result = DNS_R_NOTLOADED;
1268 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1269 UNLOCK_ZONE(zone);
1271 return (result);
1274 isc_uint32_t
1275 dns_zone_getserial(dns_zone_t *zone) {
1276 isc_result_t result;
1277 isc_uint32_t serial;
1279 result = dns_zone_getserial2(zone, &serial);
1280 if (result != ISC_R_SUCCESS)
1281 serial = 0; /* XXX: not really correct, but no other choice */
1283 return (serial);
1287 * Single shot.
1289 void
1290 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1291 char namebuf[1024];
1293 REQUIRE(DNS_ZONE_VALID(zone));
1294 REQUIRE(type != dns_zone_none);
1297 * Test and set.
1299 LOCK_ZONE(zone);
1300 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1301 zone->type = type;
1303 if (zone->strnamerd != NULL)
1304 isc_mem_free(zone->mctx, zone->strnamerd);
1306 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1307 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1308 UNLOCK_ZONE(zone);
1311 static void
1312 zone_freedbargs(dns_zone_t *zone) {
1313 unsigned int i;
1315 /* Free the old database argument list. */
1316 if (zone->db_argv != NULL) {
1317 for (i = 0; i < zone->db_argc; i++)
1318 isc_mem_free(zone->mctx, zone->db_argv[i]);
1319 isc_mem_put(zone->mctx, zone->db_argv,
1320 zone->db_argc * sizeof(*zone->db_argv));
1322 zone->db_argc = 0;
1323 zone->db_argv = NULL;
1326 isc_result_t
1327 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1328 size_t size = 0;
1329 unsigned int i;
1330 isc_result_t result = ISC_R_SUCCESS;
1331 void *mem;
1332 char **tmp, *tmp2;
1334 REQUIRE(DNS_ZONE_VALID(zone));
1335 REQUIRE(argv != NULL && *argv == NULL);
1337 LOCK_ZONE(zone);
1338 size = (zone->db_argc + 1) * sizeof(char *);
1339 for (i = 0; i < zone->db_argc; i++)
1340 size += strlen(zone->db_argv[i]) + 1;
1341 mem = isc_mem_allocate(mctx, size);
1342 if (mem != NULL) {
1343 tmp = mem;
1344 tmp2 = mem;
1345 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1346 for (i = 0; i < zone->db_argc; i++) {
1347 *tmp++ = tmp2;
1348 strcpy(tmp2, zone->db_argv[i]);
1349 tmp2 += strlen(tmp2) + 1;
1351 *tmp = NULL;
1352 } else
1353 result = ISC_R_NOMEMORY;
1354 UNLOCK_ZONE(zone);
1355 *argv = mem;
1356 return (result);
1359 isc_result_t
1360 dns_zone_setdbtype(dns_zone_t *zone,
1361 unsigned int dbargc, const char * const *dbargv) {
1362 isc_result_t result = ISC_R_SUCCESS;
1363 char **new = NULL;
1364 unsigned int i;
1366 REQUIRE(DNS_ZONE_VALID(zone));
1367 REQUIRE(dbargc >= 1);
1368 REQUIRE(dbargv != NULL);
1370 LOCK_ZONE(zone);
1372 /* Set up a new database argument list. */
1373 new = isc_mem_get(zone->mctx, dbargc * sizeof(*new));
1374 if (new == NULL)
1375 goto nomem;
1376 for (i = 0; i < dbargc; i++)
1377 new[i] = NULL;
1378 for (i = 0; i < dbargc; i++) {
1379 new[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1380 if (new[i] == NULL)
1381 goto nomem;
1384 /* Free the old list. */
1385 zone_freedbargs(zone);
1387 zone->db_argc = dbargc;
1388 zone->db_argv = new;
1389 result = ISC_R_SUCCESS;
1390 goto unlock;
1392 nomem:
1393 if (new != NULL) {
1394 for (i = 0; i < dbargc; i++)
1395 if (new[i] != NULL)
1396 isc_mem_free(zone->mctx, new[i]);
1397 isc_mem_put(zone->mctx, new, dbargc * sizeof(*new));
1399 result = ISC_R_NOMEMORY;
1401 unlock:
1402 UNLOCK_ZONE(zone);
1403 return (result);
1406 void
1407 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1408 char namebuf[1024];
1409 REQUIRE(DNS_ZONE_VALID(zone));
1411 LOCK_ZONE(zone);
1412 INSIST(zone != zone->raw);
1413 if (zone->view != NULL)
1414 dns_view_weakdetach(&zone->view);
1415 dns_view_weakattach(view, &zone->view);
1417 if (zone->strviewname != NULL)
1418 isc_mem_free(zone->mctx, zone->strviewname);
1419 if (zone->strnamerd != NULL)
1420 isc_mem_free(zone->mctx, zone->strnamerd);
1422 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1423 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1424 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1425 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1427 if (inline_secure(zone))
1428 dns_zone_setview(zone->raw, view);
1430 UNLOCK_ZONE(zone);
1433 dns_view_t *
1434 dns_zone_getview(dns_zone_t *zone) {
1435 REQUIRE(DNS_ZONE_VALID(zone));
1437 return (zone->view);
1441 isc_result_t
1442 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1443 isc_result_t result;
1444 char namebuf[1024];
1446 REQUIRE(DNS_ZONE_VALID(zone));
1447 REQUIRE(origin != NULL);
1449 LOCK_ZONE(zone);
1450 INSIST(zone != zone->raw);
1451 if (dns_name_dynamic(&zone->origin)) {
1452 dns_name_free(&zone->origin, zone->mctx);
1453 dns_name_init(&zone->origin, NULL);
1455 result = dns_name_dup(origin, zone->mctx, &zone->origin);
1457 if (zone->strnamerd != NULL)
1458 isc_mem_free(zone->mctx, zone->strnamerd);
1459 if (zone->strname != NULL)
1460 isc_mem_free(zone->mctx, zone->strname);
1462 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1463 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1464 zone_name_tostr(zone, namebuf, sizeof namebuf);
1465 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1467 if (result == ISC_R_SUCCESS && inline_secure(zone))
1468 result = dns_zone_setorigin(zone->raw, origin);
1469 UNLOCK_ZONE(zone);
1470 return (result);
1473 void
1474 dns_zone_setacache(dns_zone_t *zone, dns_acache_t *acache) {
1475 REQUIRE(DNS_ZONE_VALID(zone));
1476 REQUIRE(acache != NULL);
1478 LOCK_ZONE(zone);
1479 if (zone->acache != NULL)
1480 dns_acache_detach(&zone->acache);
1481 dns_acache_attach(acache, &zone->acache);
1482 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1483 if (zone->db != NULL) {
1484 isc_result_t result;
1487 * If the zone reuses an existing DB, the DB needs to be
1488 * set in the acache explicitly. We can safely ignore the
1489 * case where the DB is already set. If other error happens,
1490 * the acache will not work effectively.
1492 result = dns_acache_setdb(acache, zone->db);
1493 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
1494 UNEXPECTED_ERROR(__FILE__, __LINE__,
1495 "dns_acache_setdb() failed: %s",
1496 isc_result_totext(result));
1499 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1500 UNLOCK_ZONE(zone);
1503 static isc_result_t
1504 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1505 char *copy;
1507 if (value != NULL) {
1508 copy = isc_mem_strdup(zone->mctx, value);
1509 if (copy == NULL)
1510 return (ISC_R_NOMEMORY);
1511 } else {
1512 copy = NULL;
1515 if (*field != NULL)
1516 isc_mem_free(zone->mctx, *field);
1518 *field = copy;
1519 return (ISC_R_SUCCESS);
1522 isc_result_t
1523 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1524 return (dns_zone_setfile2(zone, file, dns_masterformat_text));
1527 isc_result_t
1528 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1529 dns_masterformat_t format) {
1530 isc_result_t result = ISC_R_SUCCESS;
1532 REQUIRE(DNS_ZONE_VALID(zone));
1534 LOCK_ZONE(zone);
1535 result = dns_zone_setstring(zone, &zone->masterfile, file);
1536 if (result == ISC_R_SUCCESS) {
1537 zone->masterformat = format;
1538 result = default_journal(zone);
1540 UNLOCK_ZONE(zone);
1542 return (result);
1545 const char *
1546 dns_zone_getfile(dns_zone_t *zone) {
1547 REQUIRE(DNS_ZONE_VALID(zone));
1549 return (zone->masterfile);
1552 dns_ttl_t
1553 dns_zone_getmaxttl(dns_zone_t *zone) {
1554 REQUIRE(DNS_ZONE_VALID(zone));
1556 return (zone->maxttl);
1559 void
1560 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1561 REQUIRE(DNS_ZONE_VALID(zone));
1563 LOCK_ZONE(zone);
1564 if (maxttl != 0)
1565 zone->options2 |= DNS_ZONEOPT2_CHECKTTL;
1566 else
1567 zone->options2 &= ~DNS_ZONEOPT2_CHECKTTL;
1568 zone->maxttl = maxttl;
1569 UNLOCK_ZONE(zone);
1571 return;
1574 static isc_result_t
1575 default_journal(dns_zone_t *zone) {
1576 isc_result_t result;
1577 char *journal;
1579 REQUIRE(DNS_ZONE_VALID(zone));
1580 REQUIRE(LOCKED_ZONE(zone));
1582 if (zone->masterfile != NULL) {
1583 /* Calculate string length including '\0'. */
1584 int len = strlen(zone->masterfile) + sizeof(".jnl");
1585 journal = isc_mem_allocate(zone->mctx, len);
1586 if (journal == NULL)
1587 return (ISC_R_NOMEMORY);
1588 strcpy(journal, zone->masterfile);
1589 strcat(journal, ".jnl");
1590 } else {
1591 journal = NULL;
1593 result = dns_zone_setstring(zone, &zone->journal, journal);
1594 if (journal != NULL)
1595 isc_mem_free(zone->mctx, journal);
1596 return (result);
1599 isc_result_t
1600 dns_zone_setjournal(dns_zone_t *zone, const char *journal) {
1601 isc_result_t result = ISC_R_SUCCESS;
1603 REQUIRE(DNS_ZONE_VALID(zone));
1605 LOCK_ZONE(zone);
1606 result = dns_zone_setstring(zone, &zone->journal, journal);
1607 UNLOCK_ZONE(zone);
1609 return (result);
1612 char *
1613 dns_zone_getjournal(dns_zone_t *zone) {
1614 REQUIRE(DNS_ZONE_VALID(zone));
1616 return (zone->journal);
1620 * Return true iff the zone is "dynamic", in the sense that the zone's
1621 * master file (if any) is written by the server, rather than being
1622 * updated manually and read by the server.
1624 * This is true for slave zones, stub zones, key zones, and zones that
1625 * allow dynamic updates either by having an update policy ("ssutable")
1626 * or an "allow-update" ACL with a value other than exactly "{ none; }".
1628 isc_boolean_t
1629 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1630 REQUIRE(DNS_ZONE_VALID(zone));
1632 if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1633 zone->type == dns_zone_key ||
1634 (zone->type == dns_zone_redirect && zone->masters != NULL))
1635 return (ISC_TRUE);
1637 /* If !ignore_freeze, we need check whether updates are disabled. */
1638 if (zone->type == dns_zone_master &&
1639 (!zone->update_disabled || ignore_freeze) &&
1640 ((zone->ssutable != NULL) ||
1641 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1642 return (ISC_TRUE);
1644 return (ISC_FALSE);
1649 * Set the response policy index and information for a zone.
1651 isc_result_t
1652 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1653 dns_rpz_num_t rpz_num)
1656 * Only RBTDB zones can be used for response policy zones,
1657 * because only they have the code to load the create the summary data.
1658 * Only zones that are loaded instead of mmap()ed create the
1659 * summary data and so can be policy zones.
1661 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1662 strcmp(zone->db_argv[0], "rbt64") != 0)
1663 return (ISC_R_NOTIMPLEMENTED);
1666 * This must happen only once or be redundant.
1668 LOCK_ZONE(zone);
1669 if (zone->rpzs != NULL) {
1670 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1671 } else {
1672 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1673 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1674 zone->rpz_num = rpz_num;
1676 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1677 UNLOCK_ZONE(zone);
1679 return (ISC_R_SUCCESS);
1682 dns_rpz_num_t
1683 dns_zone_get_rpz_num(dns_zone_t *zone) {
1684 return (zone->rpz_num);
1688 * If a zone is a response policy zone, mark its new database.
1690 void
1691 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1692 if (zone->rpz_num != DNS_RPZ_INVALID_NUM) {
1693 REQUIRE(zone->rpzs != NULL);
1694 dns_db_rpz_attach(db, zone->rpzs, zone->rpz_num);
1698 static isc_boolean_t
1699 zone_touched(dns_zone_t *zone) {
1700 isc_result_t result;
1701 isc_time_t modtime;
1702 dns_include_t *include;
1704 REQUIRE(DNS_ZONE_VALID(zone));
1706 result = isc_file_getmodtime(zone->masterfile, &modtime);
1707 if (result != ISC_R_SUCCESS ||
1708 isc_time_compare(&modtime, &zone->loadtime) > 0)
1710 zone->loadtime = modtime;
1711 return (ISC_TRUE);
1714 for (include = ISC_LIST_HEAD(zone->includes);
1715 include != NULL;
1716 include = ISC_LIST_NEXT(include, link))
1718 result = isc_file_getmodtime(include->name, &modtime);
1719 if (result != ISC_R_SUCCESS ||
1720 isc_time_compare(&modtime, &include->filetime) > 0)
1721 return (ISC_TRUE);
1725 return (ISC_FALSE);
1728 static isc_result_t
1729 zone_load(dns_zone_t *zone, unsigned int flags, isc_boolean_t locked) {
1730 isc_result_t result;
1731 isc_time_t now;
1732 isc_time_t loadtime;
1733 dns_db_t *db = NULL;
1734 isc_boolean_t rbt, hasraw;
1736 REQUIRE(DNS_ZONE_VALID(zone));
1738 if (!locked)
1739 LOCK_ZONE(zone);
1741 INSIST(zone != zone->raw);
1742 hasraw = inline_secure(zone);
1743 if (hasraw) {
1744 result = zone_load(zone->raw, flags, ISC_FALSE);
1745 if (result != ISC_R_SUCCESS) {
1746 if (!locked)
1747 UNLOCK_ZONE(zone);
1748 return(result);
1750 LOCK_ZONE(zone->raw);
1753 TIME_NOW(&now);
1755 INSIST(zone->type != dns_zone_none);
1757 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1758 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1759 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1760 result = DNS_R_CONTINUE;
1761 goto cleanup;
1764 INSIST(zone->db_argc >= 1);
1766 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1767 strcmp(zone->db_argv[0], "rbt64") == 0;
1769 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1771 * The zone has no master file configured.
1773 result = ISC_R_SUCCESS;
1774 goto cleanup;
1777 if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1779 * This is a slave, stub, or dynamically updated
1780 * zone being reloaded. Do nothing - the database
1781 * we already have is guaranteed to be up-to-date.
1783 if (zone->type == dns_zone_master)
1784 result = DNS_R_DYNAMIC;
1785 else
1786 result = ISC_R_SUCCESS;
1787 goto cleanup;
1791 * Store the current time before the zone is loaded, so that if the
1792 * file changes between the time of the load and the time that
1793 * zone->loadtime is set, then the file will still be reloaded
1794 * the next time dns_zone_load is called.
1796 TIME_NOW(&loadtime);
1799 * Don't do the load if the file that stores the zone is older
1800 * than the last time the zone was loaded. If the zone has not
1801 * been loaded yet, zone->loadtime will be the epoch.
1803 if (zone->masterfile != NULL) {
1805 * The file is already loaded. If we are just doing a
1806 * "rndc reconfig", we are done.
1808 if (!isc_time_isepoch(&zone->loadtime) &&
1809 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1810 result = ISC_R_SUCCESS;
1811 goto cleanup;
1814 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1815 !zone_touched(zone))
1817 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1818 "skipping load: master file "
1819 "older than last load");
1820 result = DNS_R_UPTODATE;
1821 goto cleanup;
1826 * Built in zones (with the exception of empty zones) don't need
1827 * to be reloaded.
1829 if (zone->type == dns_zone_master &&
1830 strcmp(zone->db_argv[0], "_builtin") == 0 &&
1831 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
1832 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
1833 result = ISC_R_SUCCESS;
1834 goto cleanup;
1838 * Zones associated with a DLZ don't need to be loaded either,
1839 * but we need to associate the database with the zone object.
1841 if (strcmp(zone->db_argv[0], "dlz") == 0) {
1842 dns_dlzdb_t *dlzdb;
1843 dns_dlzfindzone_t findzone;
1845 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
1846 dlzdb != NULL;
1847 dlzdb = ISC_LIST_NEXT(dlzdb, link))
1849 INSIST(DNS_DLZ_VALID(dlzdb));
1850 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
1851 break;
1854 if (dlzdb == NULL) {
1855 dns_zone_log(zone, ISC_LOG_ERROR,
1856 "DLZ %s does not exist or is set "
1857 "to 'search yes;'", zone->db_argv[1]);
1858 result = ISC_R_NOTFOUND;
1859 goto cleanup;
1862 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
1863 /* ask SDLZ driver if the zone is supported */
1864 findzone = dlzdb->implementation->methods->findzone;
1865 result = (*findzone)(dlzdb->implementation->driverarg,
1866 dlzdb->dbdata, dlzdb->mctx,
1867 zone->view->rdclass, &zone->origin,
1868 NULL, NULL, &db);
1869 if (result != ISC_R_NOTFOUND) {
1870 if (zone->db != NULL)
1871 zone_detachdb(zone);
1872 zone_attachdb(zone, db);
1873 dns_db_detach(&db);
1874 result = ISC_R_SUCCESS;
1876 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
1878 if (result == ISC_R_SUCCESS) {
1879 if (dlzdb->configure_callback == NULL)
1880 goto cleanup;
1882 result = (*dlzdb->configure_callback)(zone->view,
1883 dlzdb, zone);
1884 if (result != ISC_R_SUCCESS)
1885 dns_zone_log(zone, ISC_LOG_ERROR,
1886 "DLZ configuration callback: %s",
1887 isc_result_totext(result));
1889 goto cleanup;
1892 if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1893 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
1894 rbt) {
1895 if (zone->masterfile == NULL ||
1896 !isc_file_exists(zone->masterfile)) {
1897 if (zone->masterfile != NULL) {
1898 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1899 "no master file");
1901 zone->refreshtime = now;
1902 if (zone->task != NULL)
1903 zone_settimer(zone, &now);
1904 result = ISC_R_SUCCESS;
1905 goto cleanup;
1909 dns_zone_log(zone, ISC_LOG_DEBUG(1), "starting load");
1911 result = dns_db_create(zone->mctx, zone->db_argv[0],
1912 &zone->origin, (zone->type == dns_zone_stub) ?
1913 dns_dbtype_stub : dns_dbtype_zone,
1914 zone->rdclass,
1915 zone->db_argc - 1, zone->db_argv + 1,
1916 &db);
1918 if (result != ISC_R_SUCCESS) {
1919 dns_zone_log(zone, ISC_LOG_ERROR,
1920 "loading zone: creating database: %s",
1921 isc_result_totext(result));
1922 goto cleanup;
1924 dns_db_settask(db, zone->task);
1926 if (! dns_db_ispersistent(db)) {
1927 if (zone->masterfile != NULL) {
1928 result = zone_startload(db, zone, loadtime);
1929 } else {
1930 result = DNS_R_NOMASTERFILE;
1931 if (zone->type == dns_zone_master ||
1932 (zone->type == dns_zone_redirect &&
1933 zone->masters == NULL)) {
1934 dns_zone_log(zone, ISC_LOG_ERROR,
1935 "loading zone: "
1936 "no master file configured");
1937 goto cleanup;
1939 dns_zone_log(zone, ISC_LOG_INFO, "loading zone: "
1940 "no master file configured: continuing");
1944 if (result == DNS_R_CONTINUE) {
1945 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
1946 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1947 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1948 goto cleanup;
1951 result = zone_postload(zone, db, loadtime, result);
1953 cleanup:
1954 if (hasraw)
1955 UNLOCK_ZONE(zone->raw);
1956 if (!locked)
1957 UNLOCK_ZONE(zone);
1958 if (db != NULL)
1959 dns_db_detach(&db);
1960 return (result);
1963 isc_result_t
1964 dns_zone_load(dns_zone_t *zone) {
1965 return (zone_load(zone, 0, ISC_FALSE));
1968 isc_result_t
1969 dns_zone_loadnew(dns_zone_t *zone) {
1970 return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT, ISC_FALSE));
1973 static void
1974 zone_asyncload(isc_task_t *task, isc_event_t *event) {
1975 dns_asyncload_t *asl = event->ev_arg;
1976 dns_zone_t *zone = asl->zone;
1977 isc_result_t result = ISC_R_SUCCESS;
1978 isc_boolean_t load_pending;
1980 UNUSED(task);
1982 REQUIRE(DNS_ZONE_VALID(zone));
1984 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
1985 result = ISC_R_CANCELED;
1986 isc_event_free(&event);
1988 if (result == ISC_R_CANCELED)
1989 goto cleanup;
1991 /* Make sure load is still pending */
1992 LOCK_ZONE(zone);
1993 load_pending = ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
1995 if (!load_pending) {
1996 UNLOCK_ZONE(zone);
1997 goto cleanup;
2000 zone_load(zone, 0, ISC_TRUE);
2002 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2003 UNLOCK_ZONE(zone);
2005 /* Inform the zone table we've finished loading */
2006 if (asl->loaded != NULL)
2007 (asl->loaded)(asl->loaded_arg, zone, task);
2009 cleanup:
2010 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2011 dns_zone_idetach(&zone);
2014 isc_result_t
2015 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
2016 isc_event_t *e;
2017 dns_asyncload_t *asl = NULL;
2018 isc_result_t result = ISC_R_SUCCESS;
2020 REQUIRE(DNS_ZONE_VALID(zone));
2022 if (zone->zmgr == NULL)
2023 return (ISC_R_FAILURE);
2025 /* If we already have a load pending, stop now */
2026 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
2027 return (ISC_R_ALREADYRUNNING);
2029 asl = isc_mem_get(zone->mctx, sizeof (*asl));
2030 if (asl == NULL)
2031 CHECK(ISC_R_NOMEMORY);
2033 asl->zone = NULL;
2034 asl->loaded = done;
2035 asl->loaded_arg = arg;
2037 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
2038 DNS_EVENT_ZONELOAD,
2039 zone_asyncload, asl,
2040 sizeof(isc_event_t));
2041 if (e == NULL)
2042 CHECK(ISC_R_NOMEMORY);
2044 LOCK_ZONE(zone);
2045 zone_iattach(zone, &asl->zone);
2046 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2047 isc_task_send(zone->loadtask, &e);
2048 UNLOCK_ZONE(zone);
2050 return (ISC_R_SUCCESS);
2052 failure:
2053 if (asl != NULL)
2054 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2055 return (result);
2058 isc_boolean_t
2059 dns__zone_loadpending(dns_zone_t *zone) {
2060 REQUIRE(DNS_ZONE_VALID(zone));
2062 return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
2065 isc_result_t
2066 dns_zone_loadandthaw(dns_zone_t *zone) {
2067 isc_result_t result;
2069 if (inline_raw(zone))
2070 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
2071 ISC_FALSE);
2072 else
2073 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, ISC_FALSE);
2075 switch (result) {
2076 case DNS_R_CONTINUE:
2077 /* Deferred thaw. */
2078 break;
2079 case DNS_R_UPTODATE:
2080 case ISC_R_SUCCESS:
2081 case DNS_R_SEENINCLUDE:
2082 zone->update_disabled = ISC_FALSE;
2083 break;
2084 case DNS_R_NOMASTERFILE:
2085 zone->update_disabled = ISC_FALSE;
2086 break;
2087 default:
2088 /* Error, remain in disabled state. */
2089 break;
2091 return (result);
2094 static unsigned int
2095 get_master_options(dns_zone_t *zone) {
2096 unsigned int options;
2098 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2099 if (zone->type == dns_zone_slave ||
2100 (zone->type == dns_zone_redirect && zone->masters == NULL))
2101 options |= DNS_MASTER_SLAVE;
2102 if (zone->type == dns_zone_key)
2103 options |= DNS_MASTER_KEY;
2104 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
2105 options |= DNS_MASTER_CHECKNS;
2106 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
2107 options |= DNS_MASTER_FATALNS;
2108 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
2109 options |= DNS_MASTER_CHECKNAMES;
2110 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
2111 options |= DNS_MASTER_CHECKNAMESFAIL;
2112 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
2113 options |= DNS_MASTER_CHECKMX;
2114 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2115 options |= DNS_MASTER_CHECKMXFAIL;
2116 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
2117 options |= DNS_MASTER_CHECKWILDCARD;
2118 if (DNS_ZONE_OPTION2(zone, DNS_ZONEOPT2_CHECKTTL))
2119 options |= DNS_MASTER_CHECKTTL;
2120 return (options);
2123 static void
2124 zone_registerinclude(const char *filename, void *arg) {
2125 isc_result_t result;
2126 dns_zone_t *zone = (dns_zone_t *) arg;
2127 dns_include_t *inc = NULL;
2129 REQUIRE(DNS_ZONE_VALID(zone));
2131 if (filename == NULL)
2132 return;
2135 * Suppress duplicates.
2137 for (inc = ISC_LIST_HEAD(zone->newincludes);
2138 inc != NULL;
2139 inc = ISC_LIST_NEXT(inc, link))
2140 if (strcmp(filename, inc->name) == 0)
2141 return;
2143 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2144 if (inc == NULL)
2145 return;
2146 inc->name = isc_mem_strdup(zone->mctx, filename);
2147 if (inc->name == NULL) {
2148 isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
2149 return;
2151 ISC_LINK_INIT(inc, link);
2153 result = isc_file_getmodtime(filename, &inc->filetime);
2154 if (result != ISC_R_SUCCESS)
2155 isc_time_settoepoch(&inc->filetime);
2157 ISC_LIST_APPEND(zone->newincludes, inc, link);
2160 static void
2161 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2162 dns_load_t *load = event->ev_arg;
2163 isc_result_t result = ISC_R_SUCCESS;
2164 unsigned int options;
2166 REQUIRE(DNS_LOAD_VALID(load));
2168 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2169 result = ISC_R_CANCELED;
2170 isc_event_free(&event);
2171 if (result == ISC_R_CANCELED)
2172 goto fail;
2174 options = get_master_options(load->zone);
2176 result = dns_master_loadfileinc5(load->zone->masterfile,
2177 dns_db_origin(load->db),
2178 dns_db_origin(load->db),
2179 load->zone->rdclass, options, 0,
2180 &load->callbacks, task,
2181 zone_loaddone, load,
2182 &load->zone->lctx,
2183 zone_registerinclude,
2184 load->zone, load->zone->mctx,
2185 load->zone->masterformat,
2186 load->zone->maxttl);
2187 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2188 result != DNS_R_SEENINCLUDE)
2189 goto fail;
2190 return;
2192 fail:
2193 zone_loaddone(load, result);
2196 static void
2197 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2198 isc_result_t result;
2199 unsigned int soacount;
2201 LOCK(&raw->lock);
2202 if (raw->db != NULL) {
2203 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2204 &rawdata->sourceserial,
2205 NULL, NULL, NULL, NULL,
2206 NULL);
2207 if (result == ISC_R_SUCCESS && soacount > 0U)
2208 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2210 UNLOCK(&raw->lock);
2213 static void
2214 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2215 const char me[] = "zone_gotwritehandle";
2216 dns_zone_t *zone = event->ev_arg;
2217 isc_result_t result = ISC_R_SUCCESS;
2218 dns_dbversion_t *version = NULL;
2219 dns_masterrawheader_t rawdata;
2221 REQUIRE(DNS_ZONE_VALID(zone));
2222 INSIST(task == zone->task);
2223 ENTER;
2225 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2226 result = ISC_R_CANCELED;
2227 isc_event_free(&event);
2228 if (result == ISC_R_CANCELED)
2229 goto fail;
2231 LOCK_ZONE(zone);
2232 INSIST(zone != zone->raw);
2233 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2234 if (zone->db != NULL) {
2235 const dns_master_style_t *output_style;
2237 dns_db_currentversion(zone->db, &version);
2238 dns_master_initrawheader(&rawdata);
2239 if (inline_secure(zone))
2240 get_raw_serial(zone->raw, &rawdata);
2241 if (zone->type == dns_zone_key)
2242 output_style = &dns_master_style_keyzone;
2243 else
2244 output_style = &dns_master_style_default;
2245 result = dns_master_dumpinc3(zone->mctx, zone->db, version,
2246 output_style, zone->masterfile,
2247 zone->task, dump_done, zone, &zone->dctx, zone->masterformat,
2248 &rawdata);
2249 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2250 } else
2251 result = ISC_R_CANCELED;
2252 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2253 UNLOCK_ZONE(zone);
2254 if (result != DNS_R_CONTINUE)
2255 goto fail;
2256 return;
2258 fail:
2259 dump_done(zone, result);
2263 * Save the raw serial number for inline-signing zones.
2264 * (XXX: Other information from the header will be used
2265 * for other purposes in the future, but for now this is
2266 * all we're interested in.)
2268 static void
2269 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2270 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2271 return;
2273 zone->sourceserial = header->sourceserial;
2274 zone->sourceserialset = ISC_TRUE;
2277 void
2278 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2279 if (zone == NULL)
2280 return;
2282 LOCK_ZONE(zone);
2283 zone_setrawdata(zone, header);
2284 UNLOCK_ZONE(zone);
2287 static isc_result_t
2288 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2289 dns_load_t *load;
2290 isc_result_t result;
2291 isc_result_t tresult;
2292 unsigned int options;
2294 dns_zone_rpz_enable_db(zone, db);
2295 options = get_master_options(zone);
2296 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2297 options |= DNS_MASTER_MANYERRORS;
2299 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2300 load = isc_mem_get(zone->mctx, sizeof(*load));
2301 if (load == NULL)
2302 return (ISC_R_NOMEMORY);
2304 load->mctx = NULL;
2305 load->zone = NULL;
2306 load->db = NULL;
2307 load->loadtime = loadtime;
2308 load->magic = LOAD_MAGIC;
2310 isc_mem_attach(zone->mctx, &load->mctx);
2311 zone_iattach(zone, &load->zone);
2312 dns_db_attach(db, &load->db);
2313 dns_rdatacallbacks_init(&load->callbacks);
2314 load->callbacks.rawdata = zone_setrawdata;
2315 zone_iattach(zone, &load->callbacks.zone);
2316 result = dns_db_beginload(db, &load->callbacks);
2317 if (result != ISC_R_SUCCESS)
2318 goto cleanup;
2319 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
2320 zone_gotreadhandle, load,
2321 &zone->readio);
2322 if (result != ISC_R_SUCCESS) {
2324 * We can't report multiple errors so ignore
2325 * the result of dns_db_endload().
2327 (void)dns_db_endload(load->db, &load->callbacks);
2328 goto cleanup;
2329 } else
2330 result = DNS_R_CONTINUE;
2331 } else {
2332 dns_rdatacallbacks_t callbacks;
2334 dns_rdatacallbacks_init(&callbacks);
2335 callbacks.rawdata = zone_setrawdata;
2336 zone_iattach(zone, &callbacks.zone);
2337 result = dns_db_beginload(db, &callbacks);
2338 if (result != ISC_R_SUCCESS) {
2339 zone_idetach(&callbacks.zone);
2340 return (result);
2342 result = dns_master_loadfile5(zone->masterfile,
2343 &zone->origin, &zone->origin,
2344 zone->rdclass, options, 0,
2345 &callbacks,
2346 zone_registerinclude,
2347 zone, zone->mctx,
2348 zone->masterformat,
2349 zone->maxttl);
2350 tresult = dns_db_endload(db, &callbacks);
2351 if (result == ISC_R_SUCCESS)
2352 result = tresult;
2353 zone_idetach(&callbacks.zone);
2356 return (result);
2358 cleanup:
2359 load->magic = 0;
2360 dns_db_detach(&load->db);
2361 zone_idetach(&load->zone);
2362 zone_idetach(&load->callbacks.zone);
2363 isc_mem_detach(&load->mctx);
2364 isc_mem_put(zone->mctx, load, sizeof(*load));
2365 return (result);
2368 static isc_boolean_t
2369 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2370 dns_name_t *owner)
2372 isc_result_t result;
2373 char ownerbuf[DNS_NAME_FORMATSIZE];
2374 char namebuf[DNS_NAME_FORMATSIZE];
2375 char altbuf[DNS_NAME_FORMATSIZE];
2376 dns_fixedname_t fixed;
2377 dns_name_t *foundname;
2378 int level;
2381 * "." means the services does not exist.
2383 if (dns_name_equal(name, dns_rootname))
2384 return (ISC_TRUE);
2387 * Outside of zone.
2389 if (!dns_name_issubdomain(name, &zone->origin)) {
2390 if (zone->checkmx != NULL)
2391 return ((zone->checkmx)(zone, name, owner));
2392 return (ISC_TRUE);
2395 if (zone->type == dns_zone_master)
2396 level = ISC_LOG_ERROR;
2397 else
2398 level = ISC_LOG_WARNING;
2400 dns_fixedname_init(&fixed);
2401 foundname = dns_fixedname_name(&fixed);
2403 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2404 0, 0, NULL, foundname, NULL, NULL);
2405 if (result == ISC_R_SUCCESS)
2406 return (ISC_TRUE);
2408 if (result == DNS_R_NXRRSET) {
2409 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2410 0, 0, NULL, foundname, NULL, NULL);
2411 if (result == ISC_R_SUCCESS)
2412 return (ISC_TRUE);
2415 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2416 dns_name_format(name, namebuf, sizeof namebuf);
2417 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2418 result == DNS_R_EMPTYNAME) {
2419 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2420 level = ISC_LOG_WARNING;
2421 dns_zone_log(zone, level,
2422 "%s/MX '%s' has no address records (A or AAAA)",
2423 ownerbuf, namebuf);
2424 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2427 if (result == DNS_R_CNAME) {
2428 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2429 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2430 level = ISC_LOG_WARNING;
2431 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2432 dns_zone_log(zone, level,
2433 "%s/MX '%s' is a CNAME (illegal)",
2434 ownerbuf, namebuf);
2435 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2438 if (result == DNS_R_DNAME) {
2439 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2440 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2441 level = ISC_LOG_WARNING;
2442 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2443 dns_name_format(foundname, altbuf, sizeof altbuf);
2444 dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2445 " '%s' (illegal)", ownerbuf, namebuf,
2446 altbuf);
2448 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2451 if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2452 return ((zone->checkmx)(zone, name, owner));
2454 return (ISC_TRUE);
2457 static isc_boolean_t
2458 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2459 dns_name_t *owner)
2461 isc_result_t result;
2462 char ownerbuf[DNS_NAME_FORMATSIZE];
2463 char namebuf[DNS_NAME_FORMATSIZE];
2464 char altbuf[DNS_NAME_FORMATSIZE];
2465 dns_fixedname_t fixed;
2466 dns_name_t *foundname;
2467 int level;
2470 * "." means the services does not exist.
2472 if (dns_name_equal(name, dns_rootname))
2473 return (ISC_TRUE);
2476 * Outside of zone.
2478 if (!dns_name_issubdomain(name, &zone->origin)) {
2479 if (zone->checksrv != NULL)
2480 return ((zone->checksrv)(zone, name, owner));
2481 return (ISC_TRUE);
2484 if (zone->type == dns_zone_master)
2485 level = ISC_LOG_ERROR;
2486 else
2487 level = ISC_LOG_WARNING;
2489 dns_fixedname_init(&fixed);
2490 foundname = dns_fixedname_name(&fixed);
2492 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2493 0, 0, NULL, foundname, NULL, NULL);
2494 if (result == ISC_R_SUCCESS)
2495 return (ISC_TRUE);
2497 if (result == DNS_R_NXRRSET) {
2498 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2499 0, 0, NULL, foundname, NULL, NULL);
2500 if (result == ISC_R_SUCCESS)
2501 return (ISC_TRUE);
2504 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2505 dns_name_format(name, namebuf, sizeof namebuf);
2506 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2507 result == DNS_R_EMPTYNAME) {
2508 dns_zone_log(zone, level,
2509 "%s/SRV '%s' has no address records (A or AAAA)",
2510 ownerbuf, namebuf);
2511 /* XXX950 make fatal for 9.5.0. */
2512 return (ISC_TRUE);
2515 if (result == DNS_R_CNAME) {
2516 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2517 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2518 level = ISC_LOG_WARNING;
2519 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2520 dns_zone_log(zone, level,
2521 "%s/SRV '%s' is a CNAME (illegal)",
2522 ownerbuf, namebuf);
2523 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2526 if (result == DNS_R_DNAME) {
2527 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2528 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2529 level = ISC_LOG_WARNING;
2530 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2531 dns_name_format(foundname, altbuf, sizeof altbuf);
2532 dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2533 "DNAME '%s' (illegal)", ownerbuf, namebuf,
2534 altbuf);
2536 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2539 if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2540 return ((zone->checksrv)(zone, name, owner));
2542 return (ISC_TRUE);
2545 static isc_boolean_t
2546 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2547 dns_name_t *owner)
2549 isc_boolean_t answer = ISC_TRUE;
2550 isc_result_t result, tresult;
2551 char ownerbuf[DNS_NAME_FORMATSIZE];
2552 char namebuf[DNS_NAME_FORMATSIZE];
2553 char altbuf[DNS_NAME_FORMATSIZE];
2554 dns_fixedname_t fixed;
2555 dns_name_t *foundname;
2556 dns_rdataset_t a;
2557 dns_rdataset_t aaaa;
2558 int level;
2561 * Outside of zone.
2563 if (!dns_name_issubdomain(name, &zone->origin)) {
2564 if (zone->checkns != NULL)
2565 return ((zone->checkns)(zone, name, owner, NULL, NULL));
2566 return (ISC_TRUE);
2569 if (zone->type == dns_zone_master)
2570 level = ISC_LOG_ERROR;
2571 else
2572 level = ISC_LOG_WARNING;
2574 dns_fixedname_init(&fixed);
2575 foundname = dns_fixedname_name(&fixed);
2576 dns_rdataset_init(&a);
2577 dns_rdataset_init(&aaaa);
2579 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2580 DNS_DBFIND_GLUEOK, 0, NULL,
2581 foundname, &a, NULL);
2583 if (result == ISC_R_SUCCESS) {
2584 dns_rdataset_disassociate(&a);
2585 return (ISC_TRUE);
2586 } else if (result == DNS_R_DELEGATION)
2587 dns_rdataset_disassociate(&a);
2589 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2590 result == DNS_R_GLUE) {
2591 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2592 DNS_DBFIND_GLUEOK, 0, NULL,
2593 foundname, &aaaa, NULL);
2594 if (tresult == ISC_R_SUCCESS) {
2595 if (dns_rdataset_isassociated(&a))
2596 dns_rdataset_disassociate(&a);
2597 dns_rdataset_disassociate(&aaaa);
2598 return (ISC_TRUE);
2600 if (tresult == DNS_R_DELEGATION)
2601 dns_rdataset_disassociate(&aaaa);
2602 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2604 * Check glue against child zone.
2606 if (zone->checkns != NULL)
2607 answer = (zone->checkns)(zone, name, owner,
2608 &a, &aaaa);
2609 if (dns_rdataset_isassociated(&a))
2610 dns_rdataset_disassociate(&a);
2611 if (dns_rdataset_isassociated(&aaaa))
2612 dns_rdataset_disassociate(&aaaa);
2613 return (answer);
2617 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2618 dns_name_format(name, namebuf, sizeof namebuf);
2619 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2620 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2621 const char *what;
2622 isc_boolean_t required = ISC_FALSE;
2623 if (dns_name_issubdomain(name, owner)) {
2624 what = "REQUIRED GLUE ";
2625 required = ISC_TRUE;
2626 } else if (result == DNS_R_DELEGATION)
2627 what = "SIBLING GLUE ";
2628 else
2629 what = "";
2631 if (result != DNS_R_DELEGATION || required ||
2632 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2633 dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2634 "address records (A or AAAA)",
2635 ownerbuf, namebuf, what);
2637 * Log missing address record.
2639 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2640 (void)(zone->checkns)(zone, name, owner,
2641 &a, &aaaa);
2642 /* XXX950 make fatal for 9.5.0. */
2643 /* answer = ISC_FALSE; */
2645 } else if (result == DNS_R_CNAME) {
2646 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2647 ownerbuf, namebuf);
2648 /* XXX950 make fatal for 9.5.0. */
2649 /* answer = ISC_FALSE; */
2650 } else if (result == DNS_R_DNAME) {
2651 dns_name_format(foundname, altbuf, sizeof altbuf);
2652 dns_zone_log(zone, level,
2653 "%s/NS '%s' is below a DNAME '%s' (illegal)",
2654 ownerbuf, namebuf, altbuf);
2655 /* XXX950 make fatal for 9.5.0. */
2656 /* answer = ISC_FALSE; */
2659 if (dns_rdataset_isassociated(&a))
2660 dns_rdataset_disassociate(&a);
2661 if (dns_rdataset_isassociated(&aaaa))
2662 dns_rdataset_disassociate(&aaaa);
2663 return (answer);
2666 static isc_boolean_t
2667 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2668 dns_rdataset_t *rdataset)
2670 dns_rdataset_t tmprdataset;
2671 isc_result_t result;
2672 isc_boolean_t answer = ISC_TRUE;
2673 isc_boolean_t format = ISC_TRUE;
2674 int level = ISC_LOG_WARNING;
2675 char ownerbuf[DNS_NAME_FORMATSIZE];
2676 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2677 unsigned int count1 = 0;
2679 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2680 level = ISC_LOG_ERROR;
2682 dns_rdataset_init(&tmprdataset);
2683 for (result = dns_rdataset_first(rdataset);
2684 result == ISC_R_SUCCESS;
2685 result = dns_rdataset_next(rdataset)) {
2686 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2687 unsigned int count2 = 0;
2689 count1++;
2690 dns_rdataset_current(rdataset, &rdata1);
2691 dns_rdataset_clone(rdataset, &tmprdataset);
2692 for (result = dns_rdataset_first(&tmprdataset);
2693 result == ISC_R_SUCCESS;
2694 result = dns_rdataset_next(&tmprdataset)) {
2695 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2696 count2++;
2697 if (count1 >= count2)
2698 continue;
2699 dns_rdataset_current(&tmprdataset, &rdata2);
2700 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2701 if (format) {
2702 dns_name_format(owner, ownerbuf,
2703 sizeof ownerbuf);
2704 dns_rdatatype_format(rdata1.type,
2705 typebuf,
2706 sizeof(typebuf));
2707 format = ISC_FALSE;
2709 dns_zone_log(zone, level, "%s/%s has "
2710 "semantically identical records",
2711 ownerbuf, typebuf);
2712 if (level == ISC_LOG_ERROR)
2713 answer = ISC_FALSE;
2714 break;
2717 dns_rdataset_disassociate(&tmprdataset);
2718 if (!format)
2719 break;
2721 return (answer);
2724 static isc_boolean_t
2725 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2726 dns_dbiterator_t *dbiterator = NULL;
2727 dns_dbnode_t *node = NULL;
2728 dns_fixedname_t fixed;
2729 dns_name_t *name;
2730 dns_rdataset_t rdataset;
2731 dns_rdatasetiter_t *rdsit = NULL;
2732 isc_boolean_t ok = ISC_TRUE;
2733 isc_result_t result;
2735 dns_fixedname_init(&fixed);
2736 name = dns_fixedname_name(&fixed);
2737 dns_rdataset_init(&rdataset);
2739 result = dns_db_createiterator(db, 0, &dbiterator);
2740 if (result != ISC_R_SUCCESS)
2741 return (ISC_TRUE);
2743 for (result = dns_dbiterator_first(dbiterator);
2744 result == ISC_R_SUCCESS;
2745 result = dns_dbiterator_next(dbiterator)) {
2746 result = dns_dbiterator_current(dbiterator, &node, name);
2747 if (result != ISC_R_SUCCESS)
2748 continue;
2750 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2751 if (result != ISC_R_SUCCESS)
2752 continue;
2754 for (result = dns_rdatasetiter_first(rdsit);
2755 result == ISC_R_SUCCESS;
2756 result = dns_rdatasetiter_next(rdsit)) {
2757 dns_rdatasetiter_current(rdsit, &rdataset);
2758 if (!zone_rrset_check_dup(zone, name, &rdataset))
2759 ok = ISC_FALSE;
2760 dns_rdataset_disassociate(&rdataset);
2762 dns_rdatasetiter_destroy(&rdsit);
2763 dns_db_detachnode(db, &node);
2766 if (node != NULL)
2767 dns_db_detachnode(db, &node);
2768 dns_dbiterator_destroy(&dbiterator);
2770 return (ok);
2773 static isc_boolean_t
2774 isspf(const dns_rdata_t *rdata) {
2775 char buf[1024];
2776 const unsigned char *data = rdata->data;
2777 unsigned int rdl = rdata->length, i = 0, tl, len;
2779 while (rdl > 0U) {
2780 len = tl = *data;
2781 ++data;
2782 --rdl;
2783 INSIST(tl <= rdl);
2784 if (len > sizeof(buf) - i - 1)
2785 len = sizeof(buf) - i - 1;
2786 memmove(buf + i, data, len);
2787 i += len;
2788 data += tl;
2789 rdl -= tl;
2792 if (i < 6U)
2793 return(ISC_FALSE);
2795 buf[i] = 0;
2796 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
2797 return (ISC_TRUE);
2798 return (ISC_FALSE);
2801 static isc_boolean_t
2802 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
2803 dns_dbiterator_t *dbiterator = NULL;
2804 dns_dbnode_t *node = NULL;
2805 dns_rdataset_t rdataset;
2806 dns_fixedname_t fixed;
2807 dns_fixedname_t fixedbottom;
2808 dns_rdata_mx_t mx;
2809 dns_rdata_ns_t ns;
2810 dns_rdata_in_srv_t srv;
2811 dns_rdata_t rdata;
2812 dns_name_t *name;
2813 dns_name_t *bottom;
2814 isc_result_t result;
2815 isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
2817 dns_fixedname_init(&fixed);
2818 name = dns_fixedname_name(&fixed);
2819 dns_fixedname_init(&fixedbottom);
2820 bottom = dns_fixedname_name(&fixedbottom);
2821 dns_rdataset_init(&rdataset);
2822 dns_rdata_init(&rdata);
2824 result = dns_db_createiterator(db, 0, &dbiterator);
2825 if (result != ISC_R_SUCCESS)
2826 return (ISC_TRUE);
2828 result = dns_dbiterator_first(dbiterator);
2829 while (result == ISC_R_SUCCESS) {
2830 result = dns_dbiterator_current(dbiterator, &node, name);
2831 if (result != ISC_R_SUCCESS)
2832 goto cleanup;
2835 * Is this name visible in the zone?
2837 if (!dns_name_issubdomain(name, &zone->origin) ||
2838 (dns_name_countlabels(bottom) > 0 &&
2839 dns_name_issubdomain(name, bottom)))
2840 goto next;
2843 * Don't check the NS records at the origin.
2845 if (dns_name_equal(name, &zone->origin))
2846 goto checkmx;
2848 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
2849 0, 0, &rdataset, NULL);
2850 if (result != ISC_R_SUCCESS)
2851 goto checkmx;
2853 * Remember bottom of zone.
2855 dns_name_copy(name, bottom, NULL);
2857 result = dns_rdataset_first(&rdataset);
2858 while (result == ISC_R_SUCCESS) {
2859 dns_rdataset_current(&rdataset, &rdata);
2860 result = dns_rdata_tostruct(&rdata, &ns, NULL);
2861 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2862 if (!zone_check_glue(zone, db, &ns.name, name))
2863 ok = ISC_FALSE;
2864 dns_rdata_reset(&rdata);
2865 result = dns_rdataset_next(&rdataset);
2867 dns_rdataset_disassociate(&rdataset);
2868 goto next;
2870 checkmx:
2871 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
2872 0, 0, &rdataset, NULL);
2873 if (result != ISC_R_SUCCESS)
2874 goto checksrv;
2875 result = dns_rdataset_first(&rdataset);
2876 while (result == ISC_R_SUCCESS) {
2877 dns_rdataset_current(&rdataset, &rdata);
2878 result = dns_rdata_tostruct(&rdata, &mx, NULL);
2879 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2880 if (!zone_check_mx(zone, db, &mx.mx, name))
2881 ok = ISC_FALSE;
2882 dns_rdata_reset(&rdata);
2883 result = dns_rdataset_next(&rdataset);
2885 dns_rdataset_disassociate(&rdataset);
2887 checksrv:
2888 if (zone->rdclass != dns_rdataclass_in)
2889 goto next;
2890 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
2891 0, 0, &rdataset, NULL);
2892 if (result != ISC_R_SUCCESS)
2893 goto checkspf;
2894 result = dns_rdataset_first(&rdataset);
2895 while (result == ISC_R_SUCCESS) {
2896 dns_rdataset_current(&rdataset, &rdata);
2897 result = dns_rdata_tostruct(&rdata, &srv, NULL);
2898 RUNTIME_CHECK(result == ISC_R_SUCCESS);
2899 if (!zone_check_srv(zone, db, &srv.target, name))
2900 ok = ISC_FALSE;
2901 dns_rdata_reset(&rdata);
2902 result = dns_rdataset_next(&rdataset);
2904 dns_rdataset_disassociate(&rdataset);
2906 checkspf:
2908 * Check if there is a type SPF record without an
2909 * SPF-formatted type TXT record also being present.
2911 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
2912 goto next;
2913 if (zone->rdclass != dns_rdataclass_in)
2914 goto next;
2915 have_spf = have_txt = ISC_FALSE;
2916 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
2917 0, 0, &rdataset, NULL);
2918 if (result == ISC_R_SUCCESS) {
2919 dns_rdataset_disassociate(&rdataset);
2920 have_spf = ISC_TRUE;
2922 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
2923 0, 0, &rdataset, NULL);
2924 if (result != ISC_R_SUCCESS)
2925 goto notxt;
2926 result = dns_rdataset_first(&rdataset);
2927 while (result == ISC_R_SUCCESS) {
2928 dns_rdataset_current(&rdataset, &rdata);
2929 have_txt = isspf(&rdata);
2930 dns_rdata_reset(&rdata);
2931 if (have_txt)
2932 break;
2933 result = dns_rdataset_next(&rdataset);
2935 dns_rdataset_disassociate(&rdataset);
2937 notxt:
2938 if (have_spf && !have_txt) {
2939 char namebuf[DNS_NAME_FORMATSIZE];
2941 dns_name_format(name, namebuf, sizeof(namebuf));
2942 dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
2943 "SPF record but no SPF TXT record found, "
2944 "add matching type TXT record", namebuf);
2947 next:
2948 dns_db_detachnode(db, &node);
2949 result = dns_dbiterator_next(dbiterator);
2952 cleanup:
2953 if (node != NULL)
2954 dns_db_detachnode(db, &node);
2955 dns_dbiterator_destroy(&dbiterator);
2957 return (ok);
2961 * OpenSSL verification of RSA keys with exponent 3 is known to be
2962 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
2963 * if they are in use.
2965 static void
2966 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
2967 dns_dbnode_t *node = NULL;
2968 dns_dbversion_t *version = NULL;
2969 dns_rdata_dnskey_t dnskey;
2970 dns_rdata_t rdata = DNS_RDATA_INIT;
2971 dns_rdataset_t rdataset;
2972 isc_result_t result;
2973 isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
2974 const char *algorithm;
2976 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
2977 if (result != ISC_R_SUCCESS)
2978 goto cleanup;
2980 dns_db_currentversion(db, &version);
2981 dns_rdataset_init(&rdataset);
2982 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
2983 dns_rdatatype_none, 0, &rdataset, NULL);
2984 if (result != ISC_R_SUCCESS)
2985 goto cleanup;
2987 for (result = dns_rdataset_first(&rdataset);
2988 result == ISC_R_SUCCESS;
2989 result = dns_rdataset_next(&rdataset))
2991 dns_rdataset_current(&rdataset, &rdata);
2992 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
2993 INSIST(result == ISC_R_SUCCESS);
2995 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
2996 dnskey.algorithm == DST_ALG_RSAMD5) &&
2997 dnskey.datalen > 1 && dnskey.data[0] == 1 &&
2998 dnskey.data[1] == 3)
3000 if (dnskey.algorithm == DST_ALG_RSASHA1) {
3001 logit = !foundrsa;
3002 foundrsa = ISC_TRUE;
3003 algorithm = "RSASHA1";
3004 } else {
3005 logit = !foundmd5;
3006 foundmd5 = ISC_TRUE;
3007 algorithm = "RSAMD5";
3009 if (logit)
3010 dns_zone_log(zone, ISC_LOG_WARNING,
3011 "weak %s (%u) key found "
3012 "(exponent=3)", algorithm,
3013 dnskey.algorithm);
3014 if (foundrsa && foundmd5)
3015 break;
3017 dns_rdata_reset(&rdata);
3019 dns_rdataset_disassociate(&rdataset);
3021 cleanup:
3022 if (node != NULL)
3023 dns_db_detachnode(db, &node);
3024 if (version != NULL)
3025 dns_db_closeversion(db, &version, ISC_FALSE);
3028 static void
3029 resume_signingwithkey(dns_zone_t *zone) {
3030 dns_dbnode_t *node = NULL;
3031 dns_dbversion_t *version = NULL;
3032 dns_rdata_t rdata = DNS_RDATA_INIT;
3033 dns_rdataset_t rdataset;
3034 isc_result_t result;
3035 dns_db_t *db = NULL;
3037 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3038 if (zone->db != NULL)
3039 dns_db_attach(zone->db, &db);
3040 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3041 if (db == NULL)
3042 goto cleanup;
3044 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3045 if (result != ISC_R_SUCCESS)
3046 goto cleanup;
3048 dns_db_currentversion(db, &version);
3049 dns_rdataset_init(&rdataset);
3050 result = dns_db_findrdataset(db, node, version,
3051 zone->privatetype,
3052 dns_rdatatype_none, 0,
3053 &rdataset, NULL);
3054 if (result != ISC_R_SUCCESS) {
3055 INSIST(!dns_rdataset_isassociated(&rdataset));
3056 goto cleanup;
3059 for (result = dns_rdataset_first(&rdataset);
3060 result == ISC_R_SUCCESS;
3061 result = dns_rdataset_next(&rdataset))
3063 dns_rdataset_current(&rdataset, &rdata);
3064 if (rdata.length != 5 ||
3065 rdata.data[0] == 0 || rdata.data[4] != 0) {
3066 dns_rdata_reset(&rdata);
3067 continue;
3070 result = zone_signwithkey(zone, rdata.data[0],
3071 (rdata.data[1] << 8) | rdata.data[2],
3072 ISC_TF(rdata.data[3]));
3073 if (result != ISC_R_SUCCESS) {
3074 dns_zone_log(zone, ISC_LOG_ERROR,
3075 "zone_signwithkey failed: %s",
3076 dns_result_totext(result));
3078 dns_rdata_reset(&rdata);
3080 dns_rdataset_disassociate(&rdataset);
3082 cleanup:
3083 if (db != NULL) {
3084 if (node != NULL)
3085 dns_db_detachnode(db, &node);
3086 if (version != NULL)
3087 dns_db_closeversion(db, &version, ISC_FALSE);
3088 dns_db_detach(&db);
3092 static isc_result_t
3093 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3094 dns_nsec3chain_t *nsec3chain, *current;
3095 dns_dbversion_t *version = NULL;
3096 isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
3097 isc_result_t result;
3098 isc_time_t now;
3099 unsigned int options = 0;
3100 char saltbuf[255*2+1];
3101 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3102 dns_db_t *db = NULL;
3103 int i;
3105 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3106 if (zone->db != NULL)
3107 dns_db_attach(zone->db, &db);
3108 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3110 if (db == NULL) {
3111 result = ISC_R_SUCCESS;
3112 goto cleanup;
3115 dns_db_currentversion(db, &version);
3116 result = dns_nsec_nseconly(db, version, &nseconly);
3117 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3118 dns_db_closeversion(db, &version, ISC_FALSE);
3119 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3120 result = ISC_R_SUCCESS;
3121 goto cleanup;
3124 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3125 if (nsec3chain == NULL) {
3126 result = ISC_R_NOMEMORY;
3127 goto cleanup;
3130 nsec3chain->magic = 0;
3131 nsec3chain->done = ISC_FALSE;
3132 nsec3chain->db = NULL;
3133 nsec3chain->dbiterator = NULL;
3134 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3135 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3136 nsec3chain->nsec3param.hash = nsec3param->hash;
3137 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3138 nsec3chain->nsec3param.flags = nsec3param->flags;
3139 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3140 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3141 nsec3chain->nsec3param.salt = nsec3chain->salt;
3142 nsec3chain->seen_nsec = ISC_FALSE;
3143 nsec3chain->delete_nsec = ISC_FALSE;
3144 nsec3chain->save_delete_nsec = ISC_FALSE;
3146 if (nsec3param->flags == 0)
3147 strlcpy(flags, "NONE", sizeof(flags));
3148 else {
3149 flags[0] = '\0';
3150 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
3151 strlcat(flags, "REMOVE", sizeof(flags));
3152 if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
3153 if (flags[0] == '\0')
3154 strlcpy(flags, "INITIAL", sizeof(flags));
3155 else
3156 strlcat(flags, "|INITIAL", sizeof(flags));
3158 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
3159 if (flags[0] == '\0')
3160 strlcpy(flags, "CREATE", sizeof(flags));
3161 else
3162 strlcat(flags, "|CREATE", sizeof(flags));
3164 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
3165 if (flags[0] == '\0')
3166 strlcpy(flags, "NONSEC", sizeof(flags));
3167 else
3168 strlcat(flags, "|NONSEC", sizeof(flags));
3170 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
3171 if (flags[0] == '\0')
3172 strlcpy(flags, "OPTOUT", sizeof(flags));
3173 else
3174 strlcat(flags, "|OPTOUT", sizeof(flags));
3177 if (nsec3param->salt_length == 0)
3178 strlcpy(saltbuf, "-", sizeof(saltbuf));
3179 else
3180 for (i = 0; i < nsec3param->salt_length; i++)
3181 sprintf(&saltbuf[i*2], "%02X", nsec3chain->salt[i]);
3182 dns_zone_log(zone, ISC_LOG_INFO,
3183 "zone_addnsec3chain(%u,%s,%u,%s)",
3184 nsec3param->hash, flags, nsec3param->iterations,
3185 saltbuf);
3187 for (current = ISC_LIST_HEAD(zone->nsec3chain);
3188 current != NULL;
3189 current = ISC_LIST_NEXT(current, link)) {
3190 if (current->db == db &&
3191 current->nsec3param.hash == nsec3param->hash &&
3192 current->nsec3param.iterations == nsec3param->iterations &&
3193 current->nsec3param.salt_length == nsec3param->salt_length
3194 && !memcmp(current->nsec3param.salt, nsec3param->salt,
3195 nsec3param->salt_length))
3196 current->done = ISC_TRUE;
3199 dns_db_attach(db, &nsec3chain->db);
3200 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
3201 options = DNS_DB_NONSEC3;
3202 result = dns_db_createiterator(nsec3chain->db, options,
3203 &nsec3chain->dbiterator);
3204 if (result == ISC_R_SUCCESS)
3205 dns_dbiterator_first(nsec3chain->dbiterator);
3206 if (result == ISC_R_SUCCESS) {
3207 dns_dbiterator_pause(nsec3chain->dbiterator);
3208 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
3209 nsec3chain, link);
3210 nsec3chain = NULL;
3211 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3212 TIME_NOW(&now);
3213 zone->nsec3chaintime = now;
3214 if (zone->task != NULL)
3215 zone_settimer(zone, &now);
3219 if (nsec3chain != NULL) {
3220 if (nsec3chain->db != NULL)
3221 dns_db_detach(&nsec3chain->db);
3222 if (nsec3chain->dbiterator != NULL)
3223 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3224 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3227 cleanup:
3228 if (db != NULL)
3229 dns_db_detach(&db);
3230 return (result);
3233 static void
3234 resume_addnsec3chain(dns_zone_t *zone) {
3235 dns_dbnode_t *node = NULL;
3236 dns_dbversion_t *version = NULL;
3237 dns_rdataset_t rdataset;
3238 isc_result_t result;
3239 dns_rdata_nsec3param_t nsec3param;
3240 isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
3241 dns_db_t *db = NULL;
3243 if (zone->privatetype == 0)
3244 return;
3246 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3247 if (zone->db != NULL)
3248 dns_db_attach(zone->db, &db);
3249 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3250 if (db == NULL)
3251 goto cleanup;
3253 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3254 if (result != ISC_R_SUCCESS)
3255 goto cleanup;
3257 dns_db_currentversion(db, &version);
3259 result = dns_nsec_nseconly(db, version, &nseconly);
3260 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3262 dns_rdataset_init(&rdataset);
3263 result = dns_db_findrdataset(db, node, version,
3264 zone->privatetype, dns_rdatatype_none,
3265 0, &rdataset, NULL);
3266 if (result != ISC_R_SUCCESS) {
3267 INSIST(!dns_rdataset_isassociated(&rdataset));
3268 goto cleanup;
3271 for (result = dns_rdataset_first(&rdataset);
3272 result == ISC_R_SUCCESS;
3273 result = dns_rdataset_next(&rdataset))
3275 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3276 dns_rdata_t rdata = DNS_RDATA_INIT;
3277 dns_rdata_t private = DNS_RDATA_INIT;
3279 dns_rdataset_current(&rdataset, &private);
3280 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3281 sizeof(buf)))
3282 continue;
3283 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3284 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3285 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3286 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3288 result = zone_addnsec3chain(zone, &nsec3param);
3289 if (result != ISC_R_SUCCESS) {
3290 dns_zone_log(zone, ISC_LOG_ERROR,
3291 "zone_addnsec3chain failed: %s",
3292 dns_result_totext(result));
3296 dns_rdataset_disassociate(&rdataset);
3297 cleanup:
3298 if (db != NULL) {
3299 if (node != NULL)
3300 dns_db_detachnode(db, &node);
3301 if (version != NULL)
3302 dns_db_closeversion(db, &version, ISC_FALSE);
3303 dns_db_detach(&db);
3307 static void
3308 set_resigntime(dns_zone_t *zone) {
3309 dns_rdataset_t rdataset;
3310 dns_fixedname_t fixed;
3311 unsigned int resign;
3312 isc_result_t result;
3313 isc_uint32_t nanosecs;
3314 dns_db_t *db = NULL;
3316 /* We only re-sign zones that can be dynamically updated */
3317 if (zone->update_disabled)
3318 return;
3320 if (!inline_secure(zone) && (zone->type != dns_zone_master ||
3321 (zone->ssutable == NULL &&
3322 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3323 return;
3325 dns_rdataset_init(&rdataset);
3326 dns_fixedname_init(&fixed);
3328 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3329 if (zone->db != NULL)
3330 dns_db_attach(zone->db, &db);
3331 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3332 if (db == NULL) {
3333 isc_time_settoepoch(&zone->resigntime);
3334 return;
3337 result = dns_db_getsigningtime(db, &rdataset,
3338 dns_fixedname_name(&fixed));
3339 if (result != ISC_R_SUCCESS) {
3340 isc_time_settoepoch(&zone->resigntime);
3341 goto cleanup;
3344 resign = rdataset.resign - zone->sigresigninginterval;
3345 dns_rdataset_disassociate(&rdataset);
3346 isc_random_get(&nanosecs);
3347 nanosecs %= 1000000000;
3348 isc_time_set(&zone->resigntime, resign, nanosecs);
3349 cleanup:
3350 dns_db_detach(&db);
3351 return;
3354 static isc_result_t
3355 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3356 dns_dbnode_t *node = NULL;
3357 dns_rdataset_t rdataset;
3358 dns_dbversion_t *version = NULL;
3359 dns_rdata_nsec3param_t nsec3param;
3360 isc_boolean_t ok = ISC_FALSE;
3361 isc_result_t result;
3362 dns_rdata_t rdata = DNS_RDATA_INIT;
3363 isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
3364 dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
3366 dns_rdataset_init(&rdataset);
3367 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3368 if (result != ISC_R_SUCCESS) {
3369 dns_zone_log(zone, ISC_LOG_ERROR,
3370 "nsec3param lookup failure: %s",
3371 dns_result_totext(result));
3372 return (result);
3374 dns_db_currentversion(db, &version);
3376 result = dns_db_findrdataset(db, node, version,
3377 dns_rdatatype_nsec3param,
3378 dns_rdatatype_none, 0, &rdataset, NULL);
3379 if (result == ISC_R_NOTFOUND) {
3380 INSIST(!dns_rdataset_isassociated(&rdataset));
3381 result = ISC_R_SUCCESS;
3382 goto cleanup;
3384 if (result != ISC_R_SUCCESS) {
3385 INSIST(!dns_rdataset_isassociated(&rdataset));
3386 dns_zone_log(zone, ISC_LOG_ERROR,
3387 "nsec3param lookup failure: %s",
3388 dns_result_totext(result));
3389 goto cleanup;
3393 * For dynamic zones we must support every algorithm so we can
3394 * regenerate all the NSEC3 chains.
3395 * For non-dynamic zones we only need to find a supported algorithm.
3397 for (result = dns_rdataset_first(&rdataset);
3398 result == ISC_R_SUCCESS;
3399 result = dns_rdataset_next(&rdataset))
3401 dns_rdataset_current(&rdataset, &rdata);
3402 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3403 dns_rdata_reset(&rdata);
3404 INSIST(result == ISC_R_SUCCESS);
3405 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3406 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3408 dns_zone_log(zone, ISC_LOG_WARNING,
3409 "nsec3 test \"unknown\" hash algorithm found: %u",
3410 nsec3param.hash);
3411 ok = ISC_TRUE;
3412 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3413 if (dynamic) {
3414 dns_zone_log(zone, ISC_LOG_ERROR,
3415 "unsupported nsec3 hash algorithm"
3416 " in dynamic zone: %u",
3417 nsec3param.hash);
3418 result = DNS_R_BADZONE;
3419 /* Stop second error message. */
3420 ok = ISC_TRUE;
3421 break;
3422 } else
3423 dns_zone_log(zone, ISC_LOG_WARNING,
3424 "unsupported nsec3 hash algorithm: %u",
3425 nsec3param.hash);
3426 } else
3427 ok = ISC_TRUE;
3429 if (result == ISC_R_NOMORE)
3430 result = ISC_R_SUCCESS;
3432 if (!ok) {
3433 result = DNS_R_BADZONE;
3434 dns_zone_log(zone, ISC_LOG_ERROR,
3435 "no supported nsec3 hash algorithm");
3438 cleanup:
3439 if (dns_rdataset_isassociated(&rdataset))
3440 dns_rdataset_disassociate(&rdataset);
3441 dns_db_closeversion(db, &version, ISC_FALSE);
3442 dns_db_detachnode(db, &node);
3443 return (result);
3447 * Set the timer for refreshing the key zone to the soonest future time
3448 * of the set (current timer, keydata->refresh, keydata->addhd,
3449 * keydata->removehd).
3451 static void
3452 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3453 isc_stdtime_t now, isc_boolean_t force)
3455 const char me[] = "set_refreshkeytimer";
3456 isc_stdtime_t then;
3457 isc_time_t timenow, timethen;
3458 char timebuf[80];
3460 ENTER;
3461 then = key->refresh;
3462 if (force)
3463 then = now;
3464 if (key->addhd > now && key->addhd < then)
3465 then = key->addhd;
3466 if (key->removehd > now && key->removehd < then)
3467 then = key->removehd;
3469 TIME_NOW(&timenow);
3470 if (then > now)
3471 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3472 else
3473 timethen = timenow;
3474 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3475 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3476 zone->refreshkeytime = timethen;
3478 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3479 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3480 zone_settimer(zone, &timenow);
3484 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3485 * If the key zone is changed, set '*changed' to ISC_TRUE.
3487 static isc_result_t
3488 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3489 dns_diff_t *diff, dns_keytable_t *keytable,
3490 dns_keynode_t **keynodep, isc_boolean_t *changed)
3492 const char me[] = "create_keydata";
3493 isc_result_t result = ISC_R_SUCCESS;
3494 isc_buffer_t keyb, dstb;
3495 unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3496 dns_rdata_keydata_t keydata;
3497 dns_rdata_dnskey_t dnskey;
3498 dns_rdata_t rdata = DNS_RDATA_INIT;
3499 dns_keynode_t *keynode;
3500 isc_stdtime_t now;
3501 isc_region_t r;
3502 dst_key_t *key;
3504 REQUIRE(keynodep != NULL);
3505 keynode = *keynodep;
3507 ENTER;
3508 isc_stdtime_get(&now);
3510 /* Loop in case there's more than one key. */
3511 while (result == ISC_R_SUCCESS) {
3512 dns_keynode_t *nextnode = NULL;
3514 key = dns_keynode_key(keynode);
3515 if (key == NULL)
3516 goto skip;
3518 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3519 CHECK(dst_key_todns(key, &dstb));
3521 /* Convert DST key to DNSKEY. */
3522 dns_rdata_reset(&rdata);
3523 isc_buffer_usedregion(&dstb, &r);
3524 dns_rdata_fromregion(&rdata, dst_key_class(key),
3525 dns_rdatatype_dnskey, &r);
3527 /* DSTKEY to KEYDATA. */
3528 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3529 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3530 NULL));
3532 /* KEYDATA to rdata. */
3533 dns_rdata_reset(&rdata);
3534 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3535 CHECK(dns_rdata_fromstruct(&rdata,
3536 zone->rdclass, dns_rdatatype_keydata,
3537 &keydata, &keyb));
3539 /* Add rdata to zone. */
3540 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3541 dst_key_name(key), 0, &rdata));
3542 *changed = ISC_TRUE;
3544 /* Refresh new keys from the zone apex as soon as possible. */
3545 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3547 skip:
3548 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3549 if (result != ISC_R_NOTFOUND) {
3550 dns_keytable_detachkeynode(keytable, &keynode);
3551 keynode = nextnode;
3555 if (keynode != NULL)
3556 dns_keytable_detachkeynode(keytable, &keynode);
3557 *keynodep = NULL;
3559 return (ISC_R_SUCCESS);
3561 failure:
3562 return (result);
3566 * Remove from the key zone all the KEYDATA records found in rdataset.
3568 static isc_result_t
3569 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3570 dns_name_t *name, dns_rdataset_t *rdataset)
3572 dns_rdata_t rdata = DNS_RDATA_INIT;
3573 isc_result_t result, uresult;
3575 for (result = dns_rdataset_first(rdataset);
3576 result == ISC_R_SUCCESS;
3577 result = dns_rdataset_next(rdataset)) {
3578 dns_rdata_reset(&rdata);
3579 dns_rdataset_current(rdataset, &rdata);
3580 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3581 name, 0, &rdata);
3582 if (uresult != ISC_R_SUCCESS)
3583 return (uresult);
3585 if (result == ISC_R_NOMORE)
3586 result = ISC_R_SUCCESS;
3587 return (result);
3591 * Compute the DNSSEC key ID for a DNSKEY record.
3593 static isc_result_t
3594 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3595 dns_keytag_t *tag)
3597 isc_result_t result;
3598 dns_rdata_t rdata = DNS_RDATA_INIT;
3599 unsigned char data[4096];
3600 isc_buffer_t buffer;
3601 dst_key_t *dstkey = NULL;
3603 isc_buffer_init(&buffer, data, sizeof(data));
3604 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3605 dns_rdatatype_dnskey, dnskey, &buffer);
3607 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3608 if (result == ISC_R_SUCCESS)
3609 *tag = dst_key_id(dstkey);
3610 dst_key_free(&dstkey);
3612 return (result);
3616 * Add key to the security roots.
3618 static void
3619 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3620 dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx) {
3621 isc_result_t result;
3622 dns_rdata_t rdata = DNS_RDATA_INIT;
3623 unsigned char data[4096];
3624 isc_buffer_t buffer;
3625 dns_keytable_t *sr = NULL;
3626 dst_key_t *dstkey = NULL;
3628 /* Convert dnskey to DST key. */
3629 isc_buffer_init(&buffer, data, sizeof(data));
3630 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3631 dns_rdatatype_dnskey, dnskey, &buffer);
3633 result = dns_view_getsecroots(zone->view, &sr);
3634 if (result != ISC_R_SUCCESS)
3635 goto failure;
3637 CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3638 CHECK(dns_keytable_add(sr, ISC_TRUE, &dstkey));
3639 dns_keytable_detach(&sr);
3641 failure:
3642 if (dstkey != NULL)
3643 dst_key_free(&dstkey);
3644 if (sr != NULL)
3645 dns_keytable_detach(&sr);
3646 return;
3650 * Add a null key to the security roots for so that all queries
3651 * to the zone will fail.
3653 static void
3654 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3655 isc_result_t result;
3656 dns_keytable_t *sr = NULL;
3658 result = dns_view_getsecroots(zone->view, &sr);
3659 if (result == ISC_R_SUCCESS) {
3660 dns_keytable_marksecure(sr, keyname);
3661 dns_keytable_detach(&sr);
3666 * Scan a set of KEYDATA records from the key zone. The ones that are
3667 * valid (i.e., the add holddown timer has expired) become trusted keys.
3669 static void
3670 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3671 isc_result_t result;
3672 dns_rdata_t rdata = DNS_RDATA_INIT;
3673 dns_rdata_keydata_t keydata;
3674 dns_rdata_dnskey_t dnskey;
3675 isc_mem_t *mctx = zone->mctx;
3676 int trusted = 0, revoked = 0, pending = 0;
3677 isc_stdtime_t now;
3678 dns_keytable_t *sr = NULL;
3680 isc_stdtime_get(&now);
3682 result = dns_view_getsecroots(zone->view, &sr);
3683 if (result == ISC_R_SUCCESS) {
3684 dns_keytable_delete(sr, name);
3685 dns_keytable_detach(&sr);
3688 /* Now insert all the accepted trust anchors from this keydata set. */
3689 for (result = dns_rdataset_first(rdataset);
3690 result == ISC_R_SUCCESS;
3691 result = dns_rdataset_next(rdataset)) {
3692 dns_rdata_reset(&rdata);
3693 dns_rdataset_current(rdataset, &rdata);
3695 /* Convert rdata to keydata. */
3696 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3697 if (result == ISC_R_UNEXPECTEDEND)
3698 continue;
3699 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3701 /* Set the key refresh timer to force a fast refresh. */
3702 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3704 /* If the removal timer is nonzero, this key was revoked. */
3705 if (keydata.removehd != 0) {
3706 revoked++;
3707 continue;
3711 * If the add timer is still pending, this key is not
3712 * trusted yet.
3714 if (now < keydata.addhd) {
3715 pending++;
3716 continue;
3719 /* Convert keydata to dnskey. */
3720 dns_keydata_todnskey(&keydata, &dnskey, NULL);
3722 /* Add to keytables. */
3723 trusted++;
3724 trust_key(zone, name, &dnskey, mctx);
3727 if (trusted == 0 && pending != 0) {
3728 char namebuf[DNS_NAME_FORMATSIZE];
3729 dns_name_format(name, namebuf, sizeof namebuf);
3730 dns_zone_log(zone, ISC_LOG_ERROR,
3731 "No valid trust anchors for '%s'!", namebuf);
3732 dns_zone_log(zone, ISC_LOG_ERROR,
3733 "%d key(s) revoked, %d still pending",
3734 revoked, pending);
3735 dns_zone_log(zone, ISC_LOG_ERROR,
3736 "All queries to '%s' will fail", namebuf);
3737 fail_secure(zone, name);
3741 static isc_result_t
3742 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
3743 dns_diff_t *diff)
3745 dns_diff_t temp_diff;
3746 isc_result_t result;
3749 * Create a singleton diff.
3751 dns_diff_init(diff->mctx, &temp_diff);
3752 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
3755 * Apply it to the database.
3757 result = dns_diff_apply(&temp_diff, db, ver);
3758 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
3759 if (result != ISC_R_SUCCESS) {
3760 dns_difftuple_free(tuple);
3761 return (result);
3765 * Merge it into the current pending journal entry.
3767 dns_diff_appendminimal(diff, tuple);
3770 * Do not clear temp_diff.
3772 return (ISC_R_SUCCESS);
3775 static isc_result_t
3776 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3777 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
3778 dns_rdata_t *rdata)
3780 dns_difftuple_t *tuple = NULL;
3781 isc_result_t result;
3782 result = dns_difftuple_create(diff->mctx, op,
3783 name, ttl, rdata, &tuple);
3784 if (result != ISC_R_SUCCESS)
3785 return (result);
3786 return (do_one_tuple(&tuple, db, ver, diff));
3789 static isc_result_t
3790 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3791 isc_mem_t *mctx, dns_updatemethod_t method) {
3792 dns_difftuple_t *deltuple = NULL;
3793 dns_difftuple_t *addtuple = NULL;
3794 isc_uint32_t serial;
3795 isc_result_t result;
3797 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
3798 CHECK(dns_difftuple_copy(deltuple, &addtuple));
3799 addtuple->op = DNS_DIFFOP_ADD;
3801 serial = dns_soa_getserial(&addtuple->rdata);
3802 serial = dns_update_soaserial(serial, method);
3803 dns_soa_setserial(serial, &addtuple->rdata);
3804 CHECK(do_one_tuple(&deltuple, db, ver, diff));
3805 CHECK(do_one_tuple(&addtuple, db, ver, diff));
3806 result = ISC_R_SUCCESS;
3808 failure:
3809 if (addtuple != NULL)
3810 dns_difftuple_free(&addtuple);
3811 if (deltuple != NULL)
3812 dns_difftuple_free(&deltuple);
3813 return (result);
3817 * Write all transactions in 'diff' to the zone journal file.
3819 static isc_result_t
3820 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
3821 const char *caller)
3823 const char me[] = "zone_journal";
3824 const char *journalfile;
3825 isc_result_t result = ISC_R_SUCCESS;
3826 dns_journal_t *journal = NULL;
3827 unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
3829 ENTER;
3830 journalfile = dns_zone_getjournal(zone);
3831 if (journalfile != NULL) {
3832 result = dns_journal_open(zone->mctx, journalfile, mode,
3833 &journal);
3834 if (result != ISC_R_SUCCESS) {
3835 dns_zone_log(zone, ISC_LOG_ERROR,
3836 "%s:dns_journal_open -> %s",
3837 caller, dns_result_totext(result));
3838 return (result);
3841 if (sourceserial != NULL)
3842 dns_journal_set_sourceserial(journal, *sourceserial);
3844 result = dns_journal_write_transaction(journal, diff);
3845 if (result != ISC_R_SUCCESS) {
3846 dns_zone_log(zone, ISC_LOG_ERROR,
3847 "%s:dns_journal_write_transaction -> %s",
3848 caller, dns_result_totext(result));
3850 dns_journal_destroy(&journal);
3853 return (result);
3857 * Create an SOA record for a newly-created zone
3859 static isc_result_t
3860 add_soa(dns_zone_t *zone, dns_db_t *db) {
3861 isc_result_t result;
3862 dns_rdata_t rdata = DNS_RDATA_INIT;
3863 unsigned char buf[DNS_SOA_BUFFERSIZE];
3864 dns_dbversion_t *ver = NULL;
3865 dns_diff_t diff;
3867 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
3869 dns_diff_init(zone->mctx, &diff);
3870 result = dns_db_newversion(db, &ver);
3871 if (result != ISC_R_SUCCESS) {
3872 dns_zone_log(zone, ISC_LOG_ERROR,
3873 "add_soa:dns_db_newversion -> %s",
3874 dns_result_totext(result));
3875 goto failure;
3878 /* Build SOA record */
3879 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
3880 0, 0, 0, 0, 0, buf, &rdata);
3881 if (result != ISC_R_SUCCESS) {
3882 dns_zone_log(zone, ISC_LOG_ERROR,
3883 "add_soa:dns_soa_buildrdata -> %s",
3884 dns_result_totext(result));
3885 goto failure;
3888 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
3889 &zone->origin, 0, &rdata);
3891 failure:
3892 dns_diff_clear(&diff);
3893 if (ver != NULL)
3894 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
3896 INSIST(ver == NULL);
3898 return (result);
3902 * Synchronize the set of initializing keys found in managed-keys {}
3903 * statements with the set of trust anchors found in the managed-keys.bind
3904 * zone. If a domain is no longer named in managed-keys, delete all keys
3905 * from that domain from the key zone. If a domain is mentioned in in
3906 * managed-keys but there are no references to it in the key zone, load
3907 * the key zone with the initializing key(s) for that domain.
3909 static isc_result_t
3910 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
3911 isc_result_t result = ISC_R_SUCCESS;
3912 isc_boolean_t changed = ISC_FALSE;
3913 isc_boolean_t commit = ISC_FALSE;
3914 dns_rbtnodechain_t chain;
3915 dns_fixedname_t fn;
3916 dns_name_t foundname, *origin;
3917 dns_keynode_t *keynode = NULL;
3918 dns_view_t *view = zone->view;
3919 dns_keytable_t *sr = NULL;
3920 dns_dbversion_t *ver = NULL;
3921 dns_diff_t diff;
3922 dns_rriterator_t rrit;
3924 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
3926 dns_name_init(&foundname, NULL);
3927 dns_fixedname_init(&fn);
3928 origin = dns_fixedname_name(&fn);
3930 dns_diff_init(zone->mctx, &diff);
3932 CHECK(dns_view_getsecroots(view, &sr));
3934 result = dns_db_newversion(db, &ver);
3935 if (result != ISC_R_SUCCESS) {
3936 dns_zone_log(zone, ISC_LOG_ERROR,
3937 "sync_keyzone:dns_db_newversion -> %s",
3938 dns_result_totext(result));
3939 goto failure;
3943 * Walk the zone DB. If we find any keys whose names are no longer
3944 * in managed-keys (or *are* in trusted-keys, meaning they are
3945 * permanent and not RFC5011-maintained), delete them from the
3946 * zone. Otherwise call load_secroots(), which loads keys into
3947 * secroots as appropriate.
3949 dns_rriterator_init(&rrit, db, ver, 0);
3950 for (result = dns_rriterator_first(&rrit);
3951 result == ISC_R_SUCCESS;
3952 result = dns_rriterator_nextrrset(&rrit)) {
3953 dns_rdataset_t *rdataset = NULL;
3954 dns_name_t *rrname = NULL;
3955 isc_uint32_t ttl;
3957 dns_rriterator_current(&rrit, &rrname, &ttl,
3958 &rdataset, NULL);
3959 if (!dns_rdataset_isassociated(rdataset)) {
3960 dns_rriterator_destroy(&rrit);
3961 goto failure;
3964 if (rdataset->type != dns_rdatatype_keydata)
3965 continue;
3967 result = dns_keytable_find(sr, rrname, &keynode);
3968 if ((result != ISC_R_SUCCESS &&
3969 result != DNS_R_PARTIALMATCH) ||
3970 dns_keynode_managed(keynode) == ISC_FALSE)
3972 CHECK(delete_keydata(db, ver, &diff,
3973 rrname, rdataset));
3974 changed = ISC_TRUE;
3975 } else {
3976 load_secroots(zone, rrname, rdataset);
3979 if (keynode != NULL)
3980 dns_keytable_detachkeynode(sr, &keynode);
3982 dns_rriterator_destroy(&rrit);
3985 * Now walk secroots to find any managed keys that aren't
3986 * in the zone. If we find any, we add them to the zone.
3988 RWLOCK(&sr->rwlock, isc_rwlocktype_write);
3989 dns_rbtnodechain_init(&chain, zone->mctx);
3990 result = dns_rbtnodechain_first(&chain, sr->table, &foundname, origin);
3991 if (result == ISC_R_NOTFOUND)
3992 result = ISC_R_NOMORE;
3993 while (result == DNS_R_NEWORIGIN || result == ISC_R_SUCCESS) {
3994 dns_rbtnode_t *rbtnode = NULL;
3996 dns_rbtnodechain_current(&chain, &foundname, origin, &rbtnode);
3997 if (rbtnode->data == NULL)
3998 goto skip;
4000 dns_keytable_attachkeynode(sr, rbtnode->data, &keynode);
4001 if (dns_keynode_managed(keynode)) {
4002 dns_fixedname_t fname;
4003 dns_name_t *keyname;
4004 dst_key_t *key;
4006 key = dns_keynode_key(keynode);
4007 dns_fixedname_init(&fname);
4009 if (key == NULL) /* fail_secure() was called. */
4010 goto skip;
4012 keyname = dst_key_name(key);
4013 result = dns_db_find(db, keyname, ver,
4014 dns_rdatatype_keydata,
4015 DNS_DBFIND_NOWILD, 0, NULL,
4016 dns_fixedname_name(&fname),
4017 NULL, NULL);
4018 if (result != ISC_R_SUCCESS)
4019 result = create_keydata(zone, db, ver, &diff,
4020 sr, &keynode, &changed);
4021 if (result != ISC_R_SUCCESS)
4022 break;
4024 skip:
4025 result = dns_rbtnodechain_next(&chain, &foundname, origin);
4026 if (keynode != NULL)
4027 dns_keytable_detachkeynode(sr, &keynode);
4029 RWUNLOCK(&sr->rwlock, isc_rwlocktype_write);
4031 if (result == ISC_R_NOMORE)
4032 result = ISC_R_SUCCESS;
4034 if (changed) {
4035 /* Write changes to journal file. */
4036 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
4037 zone->updatemethod));
4038 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4040 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4041 zone_needdump(zone, 30);
4042 commit = ISC_TRUE;
4045 failure:
4046 if (result != ISC_R_SUCCESS &&
4047 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
4048 dns_zone_log(zone, ISC_LOG_ERROR,
4049 "unable to synchronize managed keys: %s",
4050 dns_result_totext(result));
4051 isc_time_settoepoch(&zone->refreshkeytime);
4053 if (keynode != NULL)
4054 dns_keytable_detachkeynode(sr, &keynode);
4055 if (sr != NULL)
4056 dns_keytable_detach(&sr);
4057 if (ver != NULL)
4058 dns_db_closeversion(db, &ver, commit);
4059 dns_diff_clear(&diff);
4061 INSIST(ver == NULL);
4063 return (result);
4066 isc_result_t
4067 dns_zone_synckeyzone(dns_zone_t *zone) {
4068 isc_result_t result;
4069 dns_db_t *db = NULL;
4071 if (zone->type != dns_zone_key)
4072 return (DNS_R_BADZONE);
4074 CHECK(dns_zone_getdb(zone, &db));
4076 LOCK_ZONE(zone);
4077 result = sync_keyzone(zone, db);
4078 UNLOCK_ZONE(zone);
4080 failure:
4081 if (db != NULL)
4082 dns_db_detach(&db);
4083 return (result);
4086 static void
4087 maybe_send_secure(dns_zone_t *zone) {
4088 isc_result_t result;
4091 * We've finished loading, or else failed to load, an inline-signing
4092 * 'secure' zone. We now need information about the status of the
4093 * 'raw' zone. If we failed to load, then we need it to send a
4094 * copy of its database; if we succeeded, we need it to send its
4095 * serial number so that we can sync with it. If it has not yet
4096 * loaded, we set a flag so that it will send the necessary
4097 * information when it has finished loading.
4099 if (zone->raw->db != NULL) {
4100 if (zone->db != NULL) {
4101 isc_uint32_t serial;
4102 unsigned int soacount;
4104 result = zone_get_from_db(zone->raw, zone->raw->db,
4105 NULL, &soacount, &serial, NULL,
4106 NULL, NULL, NULL, NULL);
4107 if (result == ISC_R_SUCCESS && soacount > 0U)
4108 zone_send_secureserial(zone->raw, serial);
4109 } else
4110 zone_send_securedb(zone->raw, zone->raw->db);
4112 } else
4113 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4116 static isc_boolean_t
4117 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4118 isc_result_t result;
4119 isc_boolean_t answer = ISC_FALSE;
4120 dns_diff_t diff;
4122 dns_diff_init(mctx, &diff);
4123 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4124 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
4125 answer = ISC_TRUE;
4126 dns_diff_clear(&diff);
4127 return (answer);
4131 * The zone is presumed to be locked.
4132 * If this is a inline_raw zone the secure version is also locked.
4134 static isc_result_t
4135 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4136 isc_result_t result)
4138 unsigned int soacount = 0;
4139 unsigned int nscount = 0;
4140 unsigned int errors = 0;
4141 isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
4142 isc_time_t now;
4143 isc_boolean_t needdump = ISC_FALSE;
4144 isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4145 isc_boolean_t nomaster = ISC_FALSE;
4146 unsigned int options;
4147 dns_include_t *inc;
4149 INSIST(LOCKED_ZONE(zone));
4150 if (inline_raw(zone))
4151 INSIST(LOCKED_ZONE(zone->secure));
4153 TIME_NOW(&now);
4156 * Initiate zone transfer? We may need a error code that
4157 * indicates that the "permanent" form does not exist.
4158 * XXX better error feedback to log.
4160 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4161 if (zone->type == dns_zone_slave ||
4162 zone->type == dns_zone_stub ||
4163 (zone->type == dns_zone_redirect &&
4164 zone->masters == NULL)) {
4165 if (result == ISC_R_FILENOTFOUND)
4166 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4167 "no master file");
4168 else if (result != DNS_R_NOMASTERFILE)
4169 dns_zone_log(zone, ISC_LOG_ERROR,
4170 "loading from master file %s "
4171 "failed: %s",
4172 zone->masterfile,
4173 dns_result_totext(result));
4174 } else if (zone->type == dns_zone_master &&
4175 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4177 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4178 "no master file, requesting db");
4179 maybe_send_secure(zone);
4180 } else {
4181 int level = ISC_LOG_ERROR;
4182 if (zone->type == dns_zone_key &&
4183 result == ISC_R_FILENOTFOUND)
4184 level = ISC_LOG_DEBUG(1);
4185 dns_zone_log(zone, level,
4186 "loading from master file %s failed: %s",
4187 zone->masterfile,
4188 dns_result_totext(result));
4189 nomaster = ISC_TRUE;
4192 if (zone->type != dns_zone_key)
4193 goto cleanup;
4196 dns_zone_log(zone, ISC_LOG_DEBUG(2),
4197 "number of nodes in database: %u",
4198 dns_db_nodecount(db));
4200 if (result == DNS_R_SEENINCLUDE)
4201 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4202 else
4203 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4206 * If there's no master file for a key zone, then the zone is new:
4207 * create an SOA record. (We do this now, instead of later, so that
4208 * if there happens to be a journal file, we can roll forward from
4209 * a sane starting point.)
4211 if (nomaster && zone->type == dns_zone_key) {
4212 result = add_soa(zone, db);
4213 if (result != ISC_R_SUCCESS)
4214 goto cleanup;
4218 * Apply update log, if any, on initial load.
4220 if (zone->journal != NULL &&
4221 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4222 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4224 if (zone->type == dns_zone_master &&
4225 (zone->update_acl != NULL || zone->ssutable != NULL))
4226 options = DNS_JOURNALOPT_RESIGN;
4227 else
4228 options = 0;
4229 result = dns_journal_rollforward(zone->mctx, db, options,
4230 zone->journal);
4231 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4232 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4233 result != ISC_R_RANGE) {
4234 dns_zone_log(zone, ISC_LOG_ERROR,
4235 "journal rollforward failed: %s",
4236 dns_result_totext(result));
4237 goto cleanup;
4241 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4242 dns_zone_log(zone, ISC_LOG_ERROR,
4243 "journal rollforward failed: "
4244 "journal out of sync with zone");
4245 goto cleanup;
4247 dns_zone_log(zone, ISC_LOG_DEBUG(1),
4248 "journal rollforward completed "
4249 "successfully: %s",
4250 dns_result_totext(result));
4251 if (result == ISC_R_SUCCESS)
4252 needdump = ISC_TRUE;
4256 * Obtain ns, soa and cname counts for top of zone.
4258 INSIST(db != NULL);
4259 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4260 &refresh, &retry, &expire, &minimum,
4261 &errors);
4262 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4263 dns_zone_log(zone, ISC_LOG_ERROR,
4264 "could not find NS and/or SOA records");
4268 * Check to make sure the journal is up to date, and remove the
4269 * journal file if it isn't, as we wouldn't be able to apply
4270 * updates otherwise.
4272 if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
4273 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
4274 isc_uint32_t jserial;
4275 dns_journal_t *journal = NULL;
4277 result = dns_journal_open(zone->mctx, zone->journal,
4278 DNS_JOURNAL_READ, &journal);
4279 if (result == ISC_R_SUCCESS) {
4280 jserial = dns_journal_last_serial(journal);
4281 dns_journal_destroy(&journal);
4282 } else {
4283 jserial = serial;
4284 result = ISC_R_SUCCESS;
4287 if (jserial != serial) {
4288 dns_zone_log(zone, ISC_LOG_INFO,
4289 "journal file is out of date: "
4290 "removing journal file");
4291 if (remove(zone->journal) < 0 && errno != ENOENT) {
4292 char strbuf[ISC_STRERRORSIZE];
4293 isc__strerror(errno, strbuf, sizeof(strbuf));
4294 isc_log_write(dns_lctx,
4295 DNS_LOGCATEGORY_GENERAL,
4296 DNS_LOGMODULE_ZONE,
4297 ISC_LOG_WARNING,
4298 "unable to remove journal "
4299 "'%s': '%s'",
4300 zone->journal, strbuf);
4305 dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded; checking validity");
4308 * Master / Slave / Stub zones require both NS and SOA records at
4309 * the top of the zone.
4312 switch (zone->type) {
4313 case dns_zone_dlz:
4314 case dns_zone_master:
4315 case dns_zone_slave:
4316 case dns_zone_stub:
4317 case dns_zone_redirect:
4318 if (soacount != 1) {
4319 dns_zone_log(zone, ISC_LOG_ERROR,
4320 "has %d SOA records", soacount);
4321 result = DNS_R_BADZONE;
4323 if (nscount == 0) {
4324 dns_zone_log(zone, ISC_LOG_ERROR,
4325 "has no NS records");
4326 result = DNS_R_BADZONE;
4328 if (result != ISC_R_SUCCESS)
4329 goto cleanup;
4330 if (zone->type == dns_zone_master && errors != 0) {
4331 result = DNS_R_BADZONE;
4332 goto cleanup;
4334 if (zone->type != dns_zone_stub &&
4335 zone->type != dns_zone_redirect) {
4336 result = check_nsec3param(zone, db);
4337 if (result != ISC_R_SUCCESS)
4338 goto cleanup;
4340 if (zone->type == dns_zone_master &&
4341 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4342 !integrity_checks(zone, db)) {
4343 result = DNS_R_BADZONE;
4344 goto cleanup;
4346 if (zone->type == dns_zone_master &&
4347 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4348 !zone_check_dup(zone, db)) {
4349 result = DNS_R_BADZONE;
4350 goto cleanup;
4353 if (zone->db != NULL) {
4354 unsigned int oldsoacount;
4357 * This is checked in zone_replacedb() for slave zones
4358 * as they don't reload from disk.
4360 result = zone_get_from_db(zone, zone->db, NULL,
4361 &oldsoacount, &oldserial,
4362 NULL, NULL, NULL, NULL,
4363 NULL);
4364 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4365 RUNTIME_CHECK(soacount > 0U);
4366 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4367 !isc_serial_gt(serial, oldserial)) {
4368 isc_uint32_t serialmin, serialmax;
4370 INSIST(zone->type == dns_zone_master);
4372 if (serial == oldserial &&
4373 zone_unchanged(zone->db, db, zone->mctx)) {
4374 dns_zone_log(zone, ISC_LOG_INFO,
4375 "ixfr-from-differences: "
4376 "unchanged");
4377 return(ISC_R_SUCCESS);
4380 serialmin = (oldserial + 1) & 0xffffffffU;
4381 serialmax = (oldserial + 0x7fffffffU) &
4382 0xffffffffU;
4383 dns_zone_log(zone, ISC_LOG_ERROR,
4384 "ixfr-from-differences: "
4385 "new serial (%u) out of range "
4386 "[%u - %u]", serial, serialmin,
4387 serialmax);
4388 result = DNS_R_BADZONE;
4389 goto cleanup;
4390 } else if (!isc_serial_ge(serial, oldserial))
4391 dns_zone_log(zone, ISC_LOG_ERROR,
4392 "zone serial (%u/%u) has gone "
4393 "backwards", serial, oldserial);
4394 else if (serial == oldserial && !hasinclude &&
4395 strcmp(zone->db_argv[0], "_builtin") != 0)
4396 dns_zone_log(zone, ISC_LOG_ERROR,
4397 "zone serial (%u) unchanged. "
4398 "zone may fail to transfer "
4399 "to slaves.", serial);
4402 if (zone->type == dns_zone_master &&
4403 (zone->update_acl != NULL || zone->ssutable != NULL) &&
4404 zone->sigresigninginterval < (3 * refresh) &&
4405 dns_db_issecure(db))
4407 dns_zone_log(zone, ISC_LOG_WARNING,
4408 "sig-re-signing-interval less than "
4409 "3 * refresh.");
4412 zone->refresh = RANGE(refresh,
4413 zone->minrefresh, zone->maxrefresh);
4414 zone->retry = RANGE(retry,
4415 zone->minretry, zone->maxretry);
4416 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4417 DNS_MAX_EXPIRE);
4418 zone->minimum = minimum;
4419 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4421 if (zone->type == dns_zone_slave ||
4422 zone->type == dns_zone_stub ||
4423 (zone->type == dns_zone_redirect &&
4424 zone->masters != NULL)) {
4425 isc_time_t t;
4426 isc_uint32_t delay;
4428 result = isc_file_getmodtime(zone->journal, &t);
4429 if (result != ISC_R_SUCCESS)
4430 result = isc_file_getmodtime(zone->masterfile,
4431 &t);
4432 if (result == ISC_R_SUCCESS)
4433 DNS_ZONE_TIME_ADD(&t, zone->expire,
4434 &zone->expiretime);
4435 else
4436 DNS_ZONE_TIME_ADD(&now, zone->retry,
4437 &zone->expiretime);
4439 delay = isc_random_jitter(zone->retry,
4440 (zone->retry * 3) / 4);
4441 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4442 if (isc_time_compare(&zone->refreshtime,
4443 &zone->expiretime) >= 0)
4444 zone->refreshtime = now;
4447 break;
4449 case dns_zone_key:
4450 result = sync_keyzone(zone, db);
4451 if (result != ISC_R_SUCCESS)
4452 goto cleanup;
4453 break;
4455 default:
4456 UNEXPECTED_ERROR(__FILE__, __LINE__,
4457 "unexpected zone type %d", zone->type);
4458 result = ISC_R_UNEXPECTED;
4459 goto cleanup;
4463 * Check for weak DNSKEY's.
4465 if (zone->type == dns_zone_master)
4466 zone_check_dnskeys(zone, db);
4469 * Schedule DNSSEC key refresh.
4471 if (zone->type == dns_zone_master &&
4472 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4473 zone->refreshkeytime = now;
4475 #if 0
4476 /* destroy notification example. */
4478 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
4479 DNS_EVENT_DBDESTROYED,
4480 dns_zonemgr_dbdestroyed,
4481 zone,
4482 sizeof(isc_event_t));
4483 dns_db_ondestroy(db, zone->task, &e);
4485 #endif
4487 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4488 if (zone->db != NULL) {
4489 result = zone_replacedb(zone, db, ISC_FALSE);
4490 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4491 if (result != ISC_R_SUCCESS)
4492 goto cleanup;
4493 } else {
4494 result = dns_db_rpz_ready(db);
4495 if (result != ISC_R_SUCCESS)
4496 goto cleanup;
4497 zone_attachdb(zone, db);
4498 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4499 DNS_ZONE_SETFLAG(zone,
4500 DNS_ZONEFLG_LOADED|
4501 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
4502 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4503 inline_raw(zone))
4505 if (zone->secure->db == NULL)
4506 zone_send_securedb(zone, db);
4507 else
4508 zone_send_secureserial(zone, serial);
4513 * Finished loading inline-signing zone; need to get status
4514 * from the raw side now.
4516 if (zone->type == dns_zone_master && inline_secure(zone))
4517 maybe_send_secure(zone);
4520 result = ISC_R_SUCCESS;
4522 if (needdump) {
4523 if (zone->type == dns_zone_key)
4524 zone_needdump(zone, 30);
4525 else
4526 zone_needdump(zone, DNS_DUMP_DELAY);
4529 if (zone->task != NULL) {
4530 if (zone->type == dns_zone_master) {
4531 set_resigntime(zone);
4532 resume_signingwithkey(zone);
4533 resume_addnsec3chain(zone);
4536 if (zone->type == dns_zone_master &&
4537 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4538 dns_zone_isdynamic(zone, ISC_FALSE) &&
4539 dns_db_issecure(db)) {
4540 dns_name_t *name;
4541 dns_fixedname_t fixed;
4542 dns_rdataset_t next;
4544 dns_rdataset_init(&next);
4545 dns_fixedname_init(&fixed);
4546 name = dns_fixedname_name(&fixed);
4548 result = dns_db_getsigningtime(db, &next, name);
4549 if (result == ISC_R_SUCCESS) {
4550 isc_stdtime_t timenow;
4551 char namebuf[DNS_NAME_FORMATSIZE];
4552 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4554 isc_stdtime_get(&timenow);
4555 dns_name_format(name, namebuf, sizeof(namebuf));
4556 dns_rdatatype_format(next.covers,
4557 typebuf, sizeof(typebuf));
4558 dns_zone_log(zone, ISC_LOG_DEBUG(3),
4559 "next resign: %s/%s in %d seconds",
4560 namebuf, typebuf,
4561 next.resign - timenow -
4562 zone->sigresigninginterval);
4563 dns_rdataset_disassociate(&next);
4564 } else
4565 dns_zone_log(zone, ISC_LOG_WARNING,
4566 "signed dynamic zone has no "
4567 "resign event scheduled");
4570 zone_settimer(zone, &now);
4574 * Clear old include list.
4576 for (inc = ISC_LIST_HEAD(zone->includes);
4577 inc != NULL;
4578 inc = ISC_LIST_HEAD(zone->includes)) {
4579 ISC_LIST_UNLINK(zone->includes, inc, link);
4580 isc_mem_free(zone->mctx, inc->name);
4581 isc_mem_put(zone->mctx, inc, sizeof(*inc));
4583 zone->nincludes = 0;
4586 * Transfer new include list.
4588 for (inc = ISC_LIST_HEAD(zone->newincludes);
4589 inc != NULL;
4590 inc = ISC_LIST_HEAD(zone->newincludes)) {
4591 ISC_LIST_UNLINK(zone->newincludes, inc, link);
4592 ISC_LIST_APPEND(zone->includes, inc, link);
4593 zone->nincludes++;
4596 if (! dns_db_ispersistent(db))
4597 dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", serial,
4598 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4600 zone->loadtime = loadtime;
4601 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4602 return (result);
4604 cleanup:
4605 for (inc = ISC_LIST_HEAD(zone->newincludes);
4606 inc != NULL;
4607 inc = ISC_LIST_HEAD(zone->newincludes)) {
4608 ISC_LIST_UNLINK(zone->newincludes, inc, link);
4609 isc_mem_free(zone->mctx, inc->name);
4610 isc_mem_put(zone->mctx, inc, sizeof(*inc));
4612 if (zone->type == dns_zone_slave ||
4613 zone->type == dns_zone_stub ||
4614 zone->type == dns_zone_key ||
4615 (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4616 if (zone->journal != NULL)
4617 zone_saveunique(zone, zone->journal, "jn-XXXXXXXX");
4618 if (zone->masterfile != NULL)
4619 zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX");
4621 /* Mark the zone for immediate refresh. */
4622 zone->refreshtime = now;
4623 if (zone->task != NULL)
4624 zone_settimer(zone, &now);
4625 result = ISC_R_SUCCESS;
4626 } else if (zone->type == dns_zone_master ||
4627 zone->type == dns_zone_redirect) {
4628 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4629 dns_zone_log(zone, ISC_LOG_ERROR,
4630 "not loaded due to errors.");
4631 else if (zone->type == dns_zone_master)
4632 result = ISC_R_SUCCESS;
4635 return (result);
4638 static isc_boolean_t
4639 exit_check(dns_zone_t *zone) {
4640 REQUIRE(LOCKED_ZONE(zone));
4642 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
4644 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4646 INSIST(isc_refcount_current(&zone->erefs) == 0);
4647 return (ISC_TRUE);
4649 return (ISC_FALSE);
4652 static isc_boolean_t
4653 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4654 dns_name_t *name, isc_boolean_t logit)
4656 isc_result_t result;
4657 char namebuf[DNS_NAME_FORMATSIZE];
4658 char altbuf[DNS_NAME_FORMATSIZE];
4659 dns_fixedname_t fixed;
4660 dns_name_t *foundname;
4661 int level;
4663 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4664 return (ISC_TRUE);
4666 if (zone->type == dns_zone_master)
4667 level = ISC_LOG_ERROR;
4668 else
4669 level = ISC_LOG_WARNING;
4671 dns_fixedname_init(&fixed);
4672 foundname = dns_fixedname_name(&fixed);
4674 result = dns_db_find(db, name, version, dns_rdatatype_a,
4675 0, 0, NULL, foundname, NULL, NULL);
4676 if (result == ISC_R_SUCCESS)
4677 return (ISC_TRUE);
4679 if (result == DNS_R_NXRRSET) {
4680 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4681 0, 0, NULL, foundname, NULL, NULL);
4682 if (result == ISC_R_SUCCESS)
4683 return (ISC_TRUE);
4686 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
4687 result == DNS_R_EMPTYNAME) {
4688 if (logit) {
4689 dns_name_format(name, namebuf, sizeof namebuf);
4690 dns_zone_log(zone, level, "NS '%s' has no address "
4691 "records (A or AAAA)", namebuf);
4693 return (ISC_FALSE);
4696 if (result == DNS_R_CNAME) {
4697 if (logit) {
4698 dns_name_format(name, namebuf, sizeof namebuf);
4699 dns_zone_log(zone, level, "NS '%s' is a CNAME "
4700 "(illegal)", namebuf);
4702 return (ISC_FALSE);
4705 if (result == DNS_R_DNAME) {
4706 if (logit) {
4707 dns_name_format(name, namebuf, sizeof namebuf);
4708 dns_name_format(foundname, altbuf, sizeof altbuf);
4709 dns_zone_log(zone, level, "NS '%s' is below a DNAME "
4710 "'%s' (illegal)", namebuf, altbuf);
4712 return (ISC_FALSE);
4715 return (ISC_TRUE);
4718 static isc_result_t
4719 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
4720 dns_dbversion_t *version, unsigned int *nscount,
4721 unsigned int *errors, isc_boolean_t logit)
4723 isc_result_t result;
4724 unsigned int count = 0;
4725 unsigned int ecount = 0;
4726 dns_rdataset_t rdataset;
4727 dns_rdata_t rdata;
4728 dns_rdata_ns_t ns;
4730 dns_rdataset_init(&rdataset);
4731 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
4732 dns_rdatatype_none, 0, &rdataset, NULL);
4733 if (result == ISC_R_NOTFOUND) {
4734 INSIST(!dns_rdataset_isassociated(&rdataset));
4735 goto success;
4737 if (result != ISC_R_SUCCESS) {
4738 INSIST(!dns_rdataset_isassociated(&rdataset));
4739 goto invalidate_rdataset;
4742 result = dns_rdataset_first(&rdataset);
4743 while (result == ISC_R_SUCCESS) {
4744 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
4745 (zone->type == dns_zone_master ||
4746 zone->type == dns_zone_slave)) {
4747 dns_rdata_init(&rdata);
4748 dns_rdataset_current(&rdataset, &rdata);
4749 result = dns_rdata_tostruct(&rdata, &ns, NULL);
4750 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4751 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
4752 !zone_check_ns(zone, db, version, &ns.name, logit))
4753 ecount++;
4755 count++;
4756 result = dns_rdataset_next(&rdataset);
4758 dns_rdataset_disassociate(&rdataset);
4760 success:
4761 if (nscount != NULL)
4762 *nscount = count;
4763 if (errors != NULL)
4764 *errors = ecount;
4766 result = ISC_R_SUCCESS;
4768 invalidate_rdataset:
4769 dns_rdataset_invalidate(&rdataset);
4771 return (result);
4774 static isc_result_t
4775 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
4776 unsigned int *soacount,
4777 isc_uint32_t *serial, isc_uint32_t *refresh,
4778 isc_uint32_t *retry, isc_uint32_t *expire,
4779 isc_uint32_t *minimum)
4781 isc_result_t result;
4782 unsigned int count;
4783 dns_rdataset_t rdataset;
4784 dns_rdata_t rdata = DNS_RDATA_INIT;
4785 dns_rdata_soa_t soa;
4787 dns_rdataset_init(&rdataset);
4788 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
4789 dns_rdatatype_none, 0, &rdataset, NULL);
4790 if (result == ISC_R_NOTFOUND) {
4791 INSIST(!dns_rdataset_isassociated(&rdataset));
4792 if (soacount != NULL)
4793 *soacount = 0;
4794 if (serial != NULL)
4795 *serial = 0;
4796 if (refresh != NULL)
4797 *refresh = 0;
4798 if (retry != NULL)
4799 *retry = 0;
4800 if (expire != NULL)
4801 *expire = 0;
4802 if (minimum != NULL)
4803 *minimum = 0;
4804 result = ISC_R_SUCCESS;
4805 goto invalidate_rdataset;
4807 if (result != ISC_R_SUCCESS) {
4808 INSIST(!dns_rdataset_isassociated(&rdataset));
4809 goto invalidate_rdataset;
4812 count = 0;
4813 result = dns_rdataset_first(&rdataset);
4814 while (result == ISC_R_SUCCESS) {
4815 dns_rdata_init(&rdata);
4816 dns_rdataset_current(&rdataset, &rdata);
4817 count++;
4818 if (count == 1) {
4819 result = dns_rdata_tostruct(&rdata, &soa, NULL);
4820 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4823 result = dns_rdataset_next(&rdataset);
4824 dns_rdata_reset(&rdata);
4826 dns_rdataset_disassociate(&rdataset);
4828 if (soacount != NULL)
4829 *soacount = count;
4831 if (count > 0) {
4832 if (serial != NULL)
4833 *serial = soa.serial;
4834 if (refresh != NULL)
4835 *refresh = soa.refresh;
4836 if (retry != NULL)
4837 *retry = soa.retry;
4838 if (expire != NULL)
4839 *expire = soa.expire;
4840 if (minimum != NULL)
4841 *minimum = soa.minimum;
4842 } else {
4843 if (soacount != NULL)
4844 *soacount = 0;
4845 if (serial != NULL)
4846 *serial = 0;
4847 if (refresh != NULL)
4848 *refresh = 0;
4849 if (retry != NULL)
4850 *retry = 0;
4851 if (expire != NULL)
4852 *expire = 0;
4853 if (minimum != NULL)
4854 *minimum = 0;
4857 result = ISC_R_SUCCESS;
4859 invalidate_rdataset:
4860 dns_rdataset_invalidate(&rdataset);
4862 return (result);
4866 * zone must be locked.
4868 static isc_result_t
4869 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
4870 unsigned int *soacount, isc_uint32_t *serial,
4871 isc_uint32_t *refresh, isc_uint32_t *retry,
4872 isc_uint32_t *expire, isc_uint32_t *minimum,
4873 unsigned int *errors)
4875 isc_result_t result;
4876 isc_result_t answer = ISC_R_SUCCESS;
4877 dns_dbversion_t *version = NULL;
4878 dns_dbnode_t *node;
4880 REQUIRE(db != NULL);
4881 REQUIRE(zone != NULL);
4883 dns_db_currentversion(db, &version);
4885 if (nscount != NULL)
4886 *nscount = 0;
4887 if (soacount != NULL)
4888 *soacount = 0;
4889 if (serial != NULL)
4890 *serial = 0;
4891 if (refresh != NULL)
4892 *refresh = 0;
4893 if (retry != NULL)
4894 *retry = 0;
4895 if (expire != NULL)
4896 *expire = 0;
4897 if (errors != NULL)
4898 *errors = 0;
4900 node = NULL;
4901 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
4902 if (result != ISC_R_SUCCESS) {
4903 answer = result;
4904 goto closeversion;
4907 if (nscount != NULL || errors != NULL) {
4908 result = zone_count_ns_rr(zone, db, node, version,
4909 nscount, errors, ISC_TRUE);
4910 if (result != ISC_R_SUCCESS)
4911 answer = result;
4914 if (soacount != NULL || serial != NULL || refresh != NULL
4915 || retry != NULL || expire != NULL || minimum != NULL) {
4916 result = zone_load_soa_rr(db, node, version, soacount,
4917 serial, refresh, retry, expire,
4918 minimum);
4919 if (result != ISC_R_SUCCESS)
4920 answer = result;
4923 dns_db_detachnode(db, &node);
4924 closeversion:
4925 dns_db_closeversion(db, &version, ISC_FALSE);
4927 return (answer);
4930 void
4931 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
4932 REQUIRE(DNS_ZONE_VALID(source));
4933 REQUIRE(target != NULL && *target == NULL);
4934 isc_refcount_increment(&source->erefs, NULL);
4935 *target = source;
4938 void
4939 dns_zone_detach(dns_zone_t **zonep) {
4940 dns_zone_t *zone;
4941 dns_zone_t *raw = NULL;
4942 dns_zone_t *secure = NULL;
4943 unsigned int refs;
4944 isc_boolean_t free_now = ISC_FALSE;
4946 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
4948 zone = *zonep;
4950 isc_refcount_decrement(&zone->erefs, &refs);
4952 if (refs == 0) {
4953 LOCK_ZONE(zone);
4954 INSIST(zone != zone->raw);
4956 * We just detached the last external reference.
4958 if (zone->task != NULL) {
4960 * This zone is being managed. Post
4961 * its control event and let it clean
4962 * up synchronously in the context of
4963 * its task.
4965 isc_event_t *ev = &zone->ctlevent;
4966 isc_task_send(zone->task, &ev);
4967 } else {
4969 * This zone is not being managed; it has
4970 * no task and can have no outstanding
4971 * events. Free it immediately.
4974 * Unmanaged zones should not have non-null views;
4975 * we have no way of detaching from the view here
4976 * without causing deadlock because this code is called
4977 * with the view already locked.
4979 INSIST(zone->view == NULL);
4980 free_now = ISC_TRUE;
4981 raw = zone->raw;
4982 zone->raw = NULL;
4983 secure = zone->secure;
4984 zone->secure = NULL;
4986 UNLOCK_ZONE(zone);
4988 *zonep = NULL;
4989 if (free_now) {
4990 if (raw != NULL)
4991 dns_zone_detach(&raw);
4992 if (secure != NULL)
4993 dns_zone_idetach(&secure);
4994 zone_free(zone);
4998 void
4999 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5000 REQUIRE(DNS_ZONE_VALID(source));
5001 REQUIRE(target != NULL && *target == NULL);
5002 LOCK_ZONE(source);
5003 zone_iattach(source, target);
5004 UNLOCK_ZONE(source);
5007 static void
5008 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5011 * 'source' locked by caller.
5013 REQUIRE(LOCKED_ZONE(source));
5014 REQUIRE(DNS_ZONE_VALID(source));
5015 REQUIRE(target != NULL && *target == NULL);
5016 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
5017 source->irefs++;
5018 INSIST(source->irefs != 0);
5019 *target = source;
5022 static void
5023 zone_idetach(dns_zone_t **zonep) {
5024 dns_zone_t *zone;
5027 * 'zone' locked by caller.
5029 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5030 zone = *zonep;
5031 REQUIRE(LOCKED_ZONE(*zonep));
5032 *zonep = NULL;
5034 INSIST(zone->irefs > 0);
5035 zone->irefs--;
5036 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
5039 void
5040 dns_zone_idetach(dns_zone_t **zonep) {
5041 dns_zone_t *zone;
5042 isc_boolean_t free_needed;
5044 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5045 zone = *zonep;
5046 *zonep = NULL;
5048 LOCK_ZONE(zone);
5049 INSIST(zone->irefs > 0);
5050 zone->irefs--;
5051 free_needed = exit_check(zone);
5052 UNLOCK_ZONE(zone);
5053 if (free_needed)
5054 zone_free(zone);
5057 isc_mem_t *
5058 dns_zone_getmctx(dns_zone_t *zone) {
5059 REQUIRE(DNS_ZONE_VALID(zone));
5061 return (zone->mctx);
5064 dns_zonemgr_t *
5065 dns_zone_getmgr(dns_zone_t *zone) {
5066 REQUIRE(DNS_ZONE_VALID(zone));
5068 return (zone->zmgr);
5071 void
5072 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
5073 REQUIRE(DNS_ZONE_VALID(zone));
5075 LOCK_ZONE(zone);
5076 if (value)
5077 DNS_ZONE_SETFLAG(zone, flags);
5078 else
5079 DNS_ZONE_CLRFLAG(zone, flags);
5080 UNLOCK_ZONE(zone);
5083 void
5084 dns_zone_setoption(dns_zone_t *zone, unsigned int option,
5085 isc_boolean_t value)
5087 REQUIRE(DNS_ZONE_VALID(zone));
5089 LOCK_ZONE(zone);
5090 if (value)
5091 zone->options |= option;
5092 else
5093 zone->options &= ~option;
5094 UNLOCK_ZONE(zone);
5097 void
5098 dns_zone_setoption2(dns_zone_t *zone, unsigned int option,
5099 isc_boolean_t value)
5101 REQUIRE(DNS_ZONE_VALID(zone));
5103 LOCK_ZONE(zone);
5104 if (value)
5105 zone->options2 |= option;
5106 else
5107 zone->options2 &= ~option;
5108 UNLOCK_ZONE(zone);
5111 unsigned int
5112 dns_zone_getoptions(dns_zone_t *zone) {
5113 REQUIRE(DNS_ZONE_VALID(zone));
5115 return (zone->options);
5118 unsigned int
5119 dns_zone_getoptions2(dns_zone_t *zone) {
5120 REQUIRE(DNS_ZONE_VALID(zone));
5122 return (zone->options2);
5125 void
5126 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
5128 REQUIRE(DNS_ZONE_VALID(zone));
5130 LOCK_ZONE(zone);
5131 if (value)
5132 zone->keyopts |= keyopt;
5133 else
5134 zone->keyopts &= ~keyopt;
5135 UNLOCK_ZONE(zone);
5138 unsigned int
5139 dns_zone_getkeyopts(dns_zone_t *zone) {
5141 REQUIRE(DNS_ZONE_VALID(zone));
5143 return (zone->keyopts);
5146 isc_result_t
5147 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5148 REQUIRE(DNS_ZONE_VALID(zone));
5150 LOCK_ZONE(zone);
5151 zone->xfrsource4 = *xfrsource;
5152 UNLOCK_ZONE(zone);
5154 return (ISC_R_SUCCESS);
5157 isc_sockaddr_t *
5158 dns_zone_getxfrsource4(dns_zone_t *zone) {
5159 REQUIRE(DNS_ZONE_VALID(zone));
5160 return (&zone->xfrsource4);
5163 isc_result_t
5164 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5165 REQUIRE(DNS_ZONE_VALID(zone));
5167 LOCK_ZONE(zone);
5168 zone->xfrsource4dscp = dscp;
5169 UNLOCK_ZONE(zone);
5171 return (ISC_R_SUCCESS);
5174 isc_dscp_t
5175 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5176 REQUIRE(DNS_ZONE_VALID(zone));
5177 return (zone->xfrsource4dscp);
5180 isc_result_t
5181 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5182 REQUIRE(DNS_ZONE_VALID(zone));
5184 LOCK_ZONE(zone);
5185 zone->xfrsource6 = *xfrsource;
5186 UNLOCK_ZONE(zone);
5188 return (ISC_R_SUCCESS);
5191 isc_sockaddr_t *
5192 dns_zone_getxfrsource6(dns_zone_t *zone) {
5193 REQUIRE(DNS_ZONE_VALID(zone));
5194 return (&zone->xfrsource6);
5197 isc_dscp_t
5198 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5199 REQUIRE(DNS_ZONE_VALID(zone));
5200 return (zone->xfrsource6dscp);
5203 isc_result_t
5204 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5205 REQUIRE(DNS_ZONE_VALID(zone));
5207 LOCK_ZONE(zone);
5208 zone->xfrsource6dscp = dscp;
5209 UNLOCK_ZONE(zone);
5211 return (ISC_R_SUCCESS);
5214 isc_result_t
5215 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5216 const isc_sockaddr_t *altxfrsource)
5218 REQUIRE(DNS_ZONE_VALID(zone));
5220 LOCK_ZONE(zone);
5221 zone->altxfrsource4 = *altxfrsource;
5222 UNLOCK_ZONE(zone);
5224 return (ISC_R_SUCCESS);
5227 isc_sockaddr_t *
5228 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
5229 REQUIRE(DNS_ZONE_VALID(zone));
5230 return (&zone->altxfrsource4);
5233 isc_result_t
5234 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5235 REQUIRE(DNS_ZONE_VALID(zone));
5237 LOCK_ZONE(zone);
5238 zone->altxfrsource4dscp = dscp;
5239 UNLOCK_ZONE(zone);
5241 return (ISC_R_SUCCESS);
5244 isc_dscp_t
5245 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
5246 REQUIRE(DNS_ZONE_VALID(zone));
5247 return (zone->altxfrsource4dscp);
5250 isc_result_t
5251 dns_zone_setaltxfrsource6(dns_zone_t *zone,
5252 const isc_sockaddr_t *altxfrsource)
5254 REQUIRE(DNS_ZONE_VALID(zone));
5256 LOCK_ZONE(zone);
5257 zone->altxfrsource6 = *altxfrsource;
5258 UNLOCK_ZONE(zone);
5260 return (ISC_R_SUCCESS);
5263 isc_sockaddr_t *
5264 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
5265 REQUIRE(DNS_ZONE_VALID(zone));
5266 return (&zone->altxfrsource6);
5269 isc_result_t
5270 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5271 REQUIRE(DNS_ZONE_VALID(zone));
5273 LOCK_ZONE(zone);
5274 zone->altxfrsource6dscp = dscp;
5275 UNLOCK_ZONE(zone);
5277 return (ISC_R_SUCCESS);
5280 isc_dscp_t
5281 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
5282 REQUIRE(DNS_ZONE_VALID(zone));
5283 return (zone->altxfrsource6dscp);
5286 isc_result_t
5287 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5288 REQUIRE(DNS_ZONE_VALID(zone));
5290 LOCK_ZONE(zone);
5291 zone->notifysrc4 = *notifysrc;
5292 UNLOCK_ZONE(zone);
5294 return (ISC_R_SUCCESS);
5297 isc_sockaddr_t *
5298 dns_zone_getnotifysrc4(dns_zone_t *zone) {
5299 REQUIRE(DNS_ZONE_VALID(zone));
5300 return (&zone->notifysrc4);
5303 isc_result_t
5304 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5305 REQUIRE(DNS_ZONE_VALID(zone));
5307 LOCK_ZONE(zone);
5308 zone->notifysrc4dscp = dscp;
5309 UNLOCK_ZONE(zone);
5311 return (ISC_R_SUCCESS);
5314 isc_dscp_t
5315 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
5316 REQUIRE(DNS_ZONE_VALID(zone));
5317 return (zone->notifysrc4dscp);
5320 isc_result_t
5321 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5322 REQUIRE(DNS_ZONE_VALID(zone));
5324 LOCK_ZONE(zone);
5325 zone->notifysrc6 = *notifysrc;
5326 UNLOCK_ZONE(zone);
5328 return (ISC_R_SUCCESS);
5331 isc_sockaddr_t *
5332 dns_zone_getnotifysrc6(dns_zone_t *zone) {
5333 REQUIRE(DNS_ZONE_VALID(zone));
5334 return (&zone->notifysrc6);
5337 static isc_boolean_t
5338 same_addrs(const isc_sockaddr_t *old, const isc_sockaddr_t *new,
5339 isc_uint32_t count)
5341 unsigned int i;
5343 for (i = 0; i < count; i++)
5344 if (!isc_sockaddr_equal(&old[i], &new[i]))
5345 return (ISC_FALSE);
5346 return (ISC_TRUE);
5349 static isc_boolean_t
5350 same_keynames(dns_name_t **old, dns_name_t **new, isc_uint32_t count) {
5351 unsigned int i;
5353 if (old == NULL && new == NULL)
5354 return (ISC_TRUE);
5355 if (old == NULL || new == NULL)
5356 return (ISC_FALSE);
5358 for (i = 0; i < count; i++) {
5359 if (old[i] == NULL && new[i] == NULL)
5360 continue;
5361 if (old[i] == NULL || new[i] == NULL ||
5362 !dns_name_equal(old[i], new[i]))
5363 return (ISC_FALSE);
5365 return (ISC_TRUE);
5368 static void
5369 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
5370 dns_name_t ***keynamesp, unsigned int *countp,
5371 isc_mem_t *mctx)
5373 unsigned int count;
5374 isc_sockaddr_t *addrs;
5375 isc_dscp_t *dscps;
5376 dns_name_t **keynames;
5378 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
5379 keynamesp != NULL);
5381 count = *countp;
5382 *countp = 0;
5383 addrs = *addrsp;
5384 *addrsp = NULL;
5385 dscps = *dscpsp;
5386 *dscpsp = NULL;
5387 keynames = *keynamesp;
5388 *keynamesp = NULL;
5390 if (addrs != NULL)
5391 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
5393 if (dscps != NULL)
5394 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
5396 if (keynames != NULL) {
5397 unsigned int i;
5398 for (i = 0; i < count; i++) {
5399 if (keynames[i] != NULL) {
5400 dns_name_free(keynames[i], mctx);
5401 isc_mem_put(mctx, keynames[i],
5402 sizeof(dns_name_t));
5403 keynames[i] = NULL;
5406 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
5410 static isc_result_t
5411 set_addrkeylist(unsigned int count,
5412 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
5413 const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
5414 dns_name_t **names, dns_name_t ***newnamesp,
5415 isc_mem_t *mctx)
5417 isc_result_t result;
5418 isc_sockaddr_t *newaddrs = NULL;
5419 isc_dscp_t *newdscp = NULL;
5420 dns_name_t **newnames = NULL;
5421 unsigned int i;
5423 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
5424 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
5425 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
5427 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
5428 if (newaddrs == NULL)
5429 return (ISC_R_NOMEMORY);
5430 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
5432 if (dscp != NULL) {
5433 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
5434 if (newdscp == NULL) {
5435 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5436 return (ISC_R_NOMEMORY);
5438 memmove(newdscp, dscp, count * sizeof(*newdscp));
5439 } else
5440 newdscp = NULL;
5442 if (names != NULL) {
5443 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
5444 if (newnames == NULL) {
5445 if (newdscp != NULL)
5446 isc_mem_put(mctx, newdscp,
5447 count * sizeof(*newdscp));
5448 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5449 return (ISC_R_NOMEMORY);
5451 for (i = 0; i < count; i++)
5452 newnames[i] = NULL;
5453 for (i = 0; i < count; i++) {
5454 if (names[i] != NULL) {
5455 newnames[i] = isc_mem_get(mctx,
5456 sizeof(dns_name_t));
5457 if (newnames[i] == NULL)
5458 goto allocfail;
5459 dns_name_init(newnames[i], NULL);
5460 result = dns_name_dup(names[i], mctx,
5461 newnames[i]);
5462 if (result != ISC_R_SUCCESS) {
5463 allocfail:
5464 for (i = 0; i < count; i++)
5465 if (newnames[i] != NULL)
5466 dns_name_free(
5467 newnames[i],
5468 mctx);
5469 isc_mem_put(mctx, newaddrs,
5470 count * sizeof(*newaddrs));
5471 isc_mem_put(mctx, newdscp,
5472 count * sizeof(*newdscp));
5473 isc_mem_put(mctx, newnames,
5474 count * sizeof(*newnames));
5475 return (ISC_R_NOMEMORY);
5479 } else
5480 newnames = NULL;
5482 *newdscpp = newdscp;
5483 *newaddrsp = newaddrs;
5484 *newnamesp = newnames;
5485 return (ISC_R_SUCCESS);
5488 isc_result_t
5489 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5490 REQUIRE(DNS_ZONE_VALID(zone));
5492 LOCK_ZONE(zone);
5493 zone->notifysrc6dscp = dscp;
5494 UNLOCK_ZONE(zone);
5496 return (ISC_R_SUCCESS);
5499 isc_dscp_t
5500 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
5501 REQUIRE(DNS_ZONE_VALID(zone));
5502 return (zone->notifysrc6dscp);
5505 isc_result_t
5506 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5507 isc_uint32_t count)
5509 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
5510 count));
5513 isc_result_t
5514 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5515 dns_name_t **keynames, isc_uint32_t count)
5517 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
5518 count));
5521 isc_result_t
5522 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5523 const isc_dscp_t *dscps, dns_name_t **keynames,
5524 isc_uint32_t count)
5526 isc_result_t result;
5527 isc_sockaddr_t *newaddrs = NULL;
5528 isc_dscp_t *newdscps = NULL;
5529 dns_name_t **newnames = NULL;
5531 REQUIRE(DNS_ZONE_VALID(zone));
5532 REQUIRE(count == 0 || notify != NULL);
5533 if (keynames != NULL)
5534 REQUIRE(count != 0);
5536 LOCK_ZONE(zone);
5538 if (count == zone->notifycnt &&
5539 same_addrs(zone->notify, notify, count) &&
5540 same_keynames(zone->notifykeynames, keynames, count))
5541 goto unlock;
5543 clear_addresskeylist(&zone->notify, &zone->notifydscp,
5544 &zone->notifykeynames, &zone->notifycnt,
5545 zone->mctx);
5547 if (count == 0)
5548 goto unlock;
5551 * Set up the notify and notifykey lists
5553 result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
5554 keynames, &newnames, zone->mctx);
5555 if (result != ISC_R_SUCCESS)
5556 goto unlock;
5559 * Everything is ok so attach to the zone.
5561 zone->notify = newaddrs;
5562 zone->notifydscp = newdscps;
5563 zone->notifykeynames = newnames;
5564 zone->notifycnt = count;
5565 unlock:
5566 UNLOCK_ZONE(zone);
5567 return (ISC_R_SUCCESS);
5570 isc_result_t
5571 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
5572 isc_uint32_t count)
5574 isc_result_t result;
5576 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
5577 return (result);
5580 isc_result_t
5581 dns_zone_setmasterswithkeys(dns_zone_t *zone,
5582 const isc_sockaddr_t *masters,
5583 dns_name_t **keynames,
5584 isc_uint32_t count)
5586 isc_result_t result = ISC_R_SUCCESS;
5587 isc_sockaddr_t *newaddrs = NULL;
5588 isc_dscp_t *newdscps = NULL;
5589 dns_name_t **newnames = NULL;
5590 isc_boolean_t *newok;
5591 unsigned int i;
5593 REQUIRE(DNS_ZONE_VALID(zone));
5594 REQUIRE(count == 0 || masters != NULL);
5595 if (keynames != NULL) {
5596 REQUIRE(count != 0);
5599 LOCK_ZONE(zone);
5601 * The refresh code assumes that 'masters' wouldn't change under it.
5602 * If it will change then kill off any current refresh in progress
5603 * and update the masters info. If it won't change then we can just
5604 * unlock and exit.
5606 if (count != zone->masterscnt ||
5607 !same_addrs(zone->masters, masters, count) ||
5608 !same_keynames(zone->masterkeynames, keynames, count)) {
5609 if (zone->request != NULL)
5610 dns_request_cancel(zone->request);
5611 } else
5612 goto unlock;
5615 * This needs to happen before clear_addresskeylist() sets
5616 * zone->masterscnt to 0:
5618 if (zone->mastersok != NULL) {
5619 isc_mem_put(zone->mctx, zone->mastersok,
5620 zone->masterscnt * sizeof(isc_boolean_t));
5621 zone->mastersok = NULL;
5623 clear_addresskeylist(&zone->masters, &zone->masterdscps,
5624 &zone->masterkeynames, &zone->masterscnt,
5625 zone->mctx);
5627 * If count == 0, don't allocate any space for masters, mastersok or
5628 * keynames so internally, those pointers are NULL if count == 0
5630 if (count == 0)
5631 goto unlock;
5634 * mastersok must contain count elements
5636 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
5637 if (newok == NULL) {
5638 result = ISC_R_NOMEMORY;
5639 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
5640 goto unlock;
5642 for (i = 0; i < count; i++)
5643 newok[i] = ISC_FALSE;
5646 * Now set up the masters and masterkey lists
5648 result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
5649 keynames, &newnames, zone->mctx);
5650 INSIST(newdscps == NULL);
5651 if (result != ISC_R_SUCCESS) {
5652 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
5653 goto unlock;
5657 * Everything is ok so attach to the zone.
5659 zone->curmaster = 0;
5660 zone->mastersok = newok;
5661 zone->masters = newaddrs;
5662 zone->masterdscps = newdscps;
5663 zone->masterkeynames = newnames;
5664 zone->masterscnt = count;
5665 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
5667 unlock:
5668 UNLOCK_ZONE(zone);
5669 return (result);
5672 isc_result_t
5673 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
5674 isc_result_t result = ISC_R_SUCCESS;
5676 REQUIRE(DNS_ZONE_VALID(zone));
5678 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5679 if (zone->db == NULL)
5680 result = DNS_R_NOTLOADED;
5681 else
5682 dns_db_attach(zone->db, dpb);
5683 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
5685 return (result);
5688 void
5689 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
5690 REQUIRE(DNS_ZONE_VALID(zone));
5691 REQUIRE(zone->type == dns_zone_staticstub);
5693 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5694 REQUIRE(zone->db == NULL);
5695 dns_db_attach(db, &zone->db);
5696 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5700 * Co-ordinates the starting of routine jobs.
5702 void
5703 dns_zone_maintenance(dns_zone_t *zone) {
5704 const char me[] = "dns_zone_maintenance";
5705 isc_time_t now;
5707 REQUIRE(DNS_ZONE_VALID(zone));
5708 ENTER;
5710 LOCK_ZONE(zone);
5711 TIME_NOW(&now);
5712 zone_settimer(zone, &now);
5713 UNLOCK_ZONE(zone);
5716 static inline isc_boolean_t
5717 was_dumping(dns_zone_t *zone) {
5718 isc_boolean_t dumping;
5720 REQUIRE(LOCKED_ZONE(zone));
5722 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
5723 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
5724 if (!dumping) {
5725 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
5726 isc_time_settoepoch(&zone->dumptime);
5728 return (dumping);
5731 static isc_result_t
5732 find_zone_keys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
5733 isc_mem_t *mctx, unsigned int maxkeys,
5734 dst_key_t **keys, unsigned int *nkeys)
5736 isc_result_t result;
5737 dns_dbnode_t *node = NULL;
5738 const char *directory = dns_zone_getkeydirectory(zone);
5740 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
5741 memset(keys, 0, sizeof(*keys) * maxkeys);
5742 result = dns_dnssec_findzonekeys2(db, ver, node, dns_db_origin(db),
5743 directory, mctx, maxkeys, keys,
5744 nkeys);
5745 if (result == ISC_R_NOTFOUND)
5746 result = ISC_R_SUCCESS;
5747 failure:
5748 if (node != NULL)
5749 dns_db_detachnode(db, &node);
5750 return (result);
5753 static isc_result_t
5754 offline(dns_db_t *db, dns_dbversion_t *ver, zonediff_t *zonediff,
5755 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
5757 isc_result_t result;
5759 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
5760 return (ISC_R_SUCCESS);
5761 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
5762 name, ttl, rdata);
5763 if (result != ISC_R_SUCCESS)
5764 return (result);
5765 rdata->flags |= DNS_RDATA_OFFLINE;
5766 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
5767 name, ttl, rdata);
5768 zonediff->offline = ISC_TRUE;
5769 return (result);
5772 static void
5773 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
5775 unsigned int delta;
5776 char timebuf[80];
5778 zone->key_expiry = when;
5779 if (when <= now) {
5780 dns_zone_log(zone, ISC_LOG_ERROR,
5781 "DNSKEY RRSIG(s) have expired");
5782 isc_time_settoepoch(&zone->keywarntime);
5783 } else if (when < now + 7 * 24 * 3600) {
5784 isc_time_t t;
5785 isc_time_set(&t, when, 0);
5786 isc_time_formattimestamp(&t, timebuf, 80);
5787 dns_zone_log(zone, ISC_LOG_WARNING,
5788 "DNSKEY RRSIG(s) will expire within 7 days: %s",
5789 timebuf);
5790 delta = when - now;
5791 delta--; /* loop prevention */
5792 delta /= 24 * 3600; /* to whole days */
5793 delta *= 24 * 3600; /* to seconds */
5794 isc_time_set(&zone->keywarntime, when - delta, 0);
5795 } else {
5796 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
5797 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
5798 dns_zone_log(zone, ISC_LOG_NOTICE,
5799 "setting keywarntime to %s", timebuf);
5804 * Helper function to del_sigs(). We don't want to delete RRSIGs that
5805 * have no new key.
5807 static isc_boolean_t
5808 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
5809 isc_boolean_t *warn)
5811 unsigned int i = 0;
5812 isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
5813 isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
5815 for (i = 0; i < nkeys; i++) {
5816 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
5817 continue;
5818 if (dst_key_isprivate(keys[i])) {
5819 if (KSK(keys[i]))
5820 have_ksk = have_pksk = ISC_TRUE;
5821 else
5822 have_zsk = have_pzsk = ISC_TRUE;
5823 } else {
5824 if (KSK(keys[i]))
5825 have_ksk = ISC_TRUE;
5826 else
5827 have_zsk = ISC_TRUE;
5831 if (have_zsk && have_ksk && !have_pzsk)
5832 *warn = ISC_TRUE;
5835 * It's okay to delete a signature if there is an active key
5836 * with the same algorithm to replace it.
5838 if (have_pksk || have_pzsk)
5839 return (ISC_TRUE);
5842 * Failing that, it is *not* okay to delete a signature
5843 * if the associated public key is still in the DNSKEY RRset
5845 for (i = 0; i < nkeys; i++) {
5846 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
5847 (rrsig_ptr->keyid == dst_key_id(keys[i])))
5848 return (ISC_FALSE);
5852 * But if the key is gone, then go ahead.
5854 return (ISC_TRUE);
5858 * Delete expired RRsigs and any RRsigs we are about to re-sign.
5859 * See also update.c:del_keysigs().
5861 static isc_result_t
5862 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
5863 dns_rdatatype_t type, zonediff_t *zonediff, dst_key_t **keys,
5864 unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
5866 isc_result_t result;
5867 dns_dbnode_t *node = NULL;
5868 dns_rdataset_t rdataset;
5869 unsigned int i;
5870 dns_rdata_rrsig_t rrsig;
5871 isc_boolean_t found;
5872 isc_int64_t timewarn = 0, timemaybe = 0;
5874 dns_rdataset_init(&rdataset);
5876 if (type == dns_rdatatype_nsec3)
5877 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
5878 else
5879 result = dns_db_findnode(db, name, ISC_FALSE, &node);
5880 if (result == ISC_R_NOTFOUND)
5881 return (ISC_R_SUCCESS);
5882 if (result != ISC_R_SUCCESS)
5883 goto failure;
5884 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
5885 (isc_stdtime_t) 0, &rdataset, NULL);
5886 dns_db_detachnode(db, &node);
5888 if (result == ISC_R_NOTFOUND) {
5889 INSIST(!dns_rdataset_isassociated(&rdataset));
5890 return (ISC_R_SUCCESS);
5892 if (result != ISC_R_SUCCESS) {
5893 INSIST(!dns_rdataset_isassociated(&rdataset));
5894 goto failure;
5897 for (result = dns_rdataset_first(&rdataset);
5898 result == ISC_R_SUCCESS;
5899 result = dns_rdataset_next(&rdataset)) {
5900 dns_rdata_t rdata = DNS_RDATA_INIT;
5902 dns_rdataset_current(&rdataset, &rdata);
5903 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
5904 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5906 if (type != dns_rdatatype_dnskey) {
5907 isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
5908 if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
5909 result = update_one_rr(db, ver, zonediff->diff,
5910 DNS_DIFFOP_DELRESIGN, name,
5911 rdataset.ttl, &rdata);
5912 if (result != ISC_R_SUCCESS)
5913 break;
5914 deleted = ISC_TRUE;
5916 if (warn) {
5918 * At this point, we've got an RRSIG,
5919 * which is signed by an inactive key.
5920 * An administrator needs to provide a new
5921 * key/alg, but until that time, we want to
5922 * keep the old RRSIG. Marking the key as
5923 * offline will prevent us spinning waiting
5924 * for the private part.
5926 if (incremental && !deleted) {
5927 result = offline(db, ver, zonediff,
5928 name, rdataset.ttl,
5929 &rdata);
5930 if (result != ISC_R_SUCCESS)
5931 break;
5935 * Log the key id and algorithm of
5936 * the inactive key with no replacement
5938 if (zone->log_key_expired_timer <= now) {
5939 char origin[DNS_NAME_FORMATSIZE];
5940 char algbuf[DNS_NAME_FORMATSIZE];
5941 dns_name_format(&zone->origin, origin,
5942 sizeof(origin));
5943 dns_secalg_format(rrsig.algorithm,
5944 algbuf,
5945 sizeof(algbuf));
5946 dns_zone_log(zone, ISC_LOG_WARNING,
5947 "Key %s/%s/%d "
5948 "missing or inactive "
5949 "and has no replacement: "
5950 "retaining signatures.",
5951 origin, algbuf,
5952 rrsig.keyid);
5953 zone->log_key_expired_timer = now +
5954 3600;
5957 continue;
5961 * RRSIG(DNSKEY) requires special processing.
5963 found = ISC_FALSE;
5964 for (i = 0; i < nkeys; i++) {
5965 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
5966 rrsig.keyid == dst_key_id(keys[i])) {
5967 found = ISC_TRUE;
5969 * Mark offline RRSIG(DNSKEY).
5970 * We want the earliest offline expire time
5971 * iff there is a new offline signature.
5973 if (!dst_key_inactive(keys[i]) &&
5974 !dst_key_isprivate(keys[i]))
5976 isc_int64_t timeexpire =
5977 dns_time64_from32(rrsig.timeexpire);
5978 if (timewarn != 0 &&
5979 timewarn > timeexpire)
5980 timewarn = timeexpire;
5981 if (rdata.flags & DNS_RDATA_OFFLINE) {
5982 if (timemaybe == 0 ||
5983 timemaybe > timeexpire)
5984 timemaybe = timeexpire;
5985 break;
5987 if (timewarn == 0)
5988 timewarn = timemaybe;
5989 if (timewarn == 0 ||
5990 timewarn > timeexpire)
5991 timewarn = timeexpire;
5992 result = offline(db, ver, zonediff,
5993 name, rdataset.ttl,
5994 &rdata);
5995 break;
5997 result = update_one_rr(db, ver, zonediff->diff,
5998 DNS_DIFFOP_DELRESIGN,
5999 name, rdataset.ttl,
6000 &rdata);
6001 break;
6006 * If there is not a matching DNSKEY then
6007 * delete the RRSIG.
6009 if (!found)
6010 result = update_one_rr(db, ver, zonediff->diff,
6011 DNS_DIFFOP_DELRESIGN, name,
6012 rdataset.ttl, &rdata);
6013 if (result != ISC_R_SUCCESS)
6014 break;
6017 dns_rdataset_disassociate(&rdataset);
6018 if (result == ISC_R_NOMORE)
6019 result = ISC_R_SUCCESS;
6020 if (timewarn > 0) {
6021 #if defined(STDTIME_ON_32BITS)
6022 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6023 if (timewarn == stdwarn)
6024 #endif
6025 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6026 now);
6027 #if defined(STDTIME_ON_32BITS)
6028 else
6029 dns_zone_log(zone, ISC_LOG_ERROR,
6030 "key expiry warning time out of range");
6031 #endif
6033 failure:
6034 if (node != NULL)
6035 dns_db_detachnode(db, &node);
6036 return (result);
6039 static isc_result_t
6040 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6041 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6042 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
6043 isc_stdtime_t expire, isc_boolean_t check_ksk,
6044 isc_boolean_t keyset_kskonly)
6046 isc_result_t result;
6047 dns_dbnode_t *node = NULL;
6048 dns_rdataset_t rdataset;
6049 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6050 unsigned char data[1024]; /* XXX */
6051 isc_buffer_t buffer;
6052 unsigned int i, j;
6054 dns_rdataset_init(&rdataset);
6055 isc_buffer_init(&buffer, data, sizeof(data));
6057 if (type == dns_rdatatype_nsec3)
6058 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
6059 else
6060 result = dns_db_findnode(db, name, ISC_FALSE, &node);
6061 if (result == ISC_R_NOTFOUND)
6062 return (ISC_R_SUCCESS);
6063 if (result != ISC_R_SUCCESS)
6064 goto failure;
6065 result = dns_db_findrdataset(db, node, ver, type, 0,
6066 (isc_stdtime_t) 0, &rdataset, NULL);
6067 dns_db_detachnode(db, &node);
6068 if (result == ISC_R_NOTFOUND) {
6069 INSIST(!dns_rdataset_isassociated(&rdataset));
6070 return (ISC_R_SUCCESS);
6072 if (result != ISC_R_SUCCESS) {
6073 INSIST(!dns_rdataset_isassociated(&rdataset));
6074 goto failure;
6077 for (i = 0; i < nkeys; i++) {
6078 isc_boolean_t both = ISC_FALSE;
6080 if (!dst_key_isprivate(keys[i]))
6081 continue;
6083 if (check_ksk && !REVOKE(keys[i])) {
6084 isc_boolean_t have_ksk, have_nonksk;
6085 if (KSK(keys[i])) {
6086 have_ksk = ISC_TRUE;
6087 have_nonksk = ISC_FALSE;
6088 } else {
6089 have_ksk = ISC_FALSE;
6090 have_nonksk = ISC_TRUE;
6092 for (j = 0; j < nkeys; j++) {
6093 if (j == i || ALG(keys[i]) != ALG(keys[j]))
6094 continue;
6095 if (REVOKE(keys[j]))
6096 continue;
6097 if (KSK(keys[j]))
6098 have_ksk = ISC_TRUE;
6099 else
6100 have_nonksk = ISC_TRUE;
6101 both = have_ksk && have_nonksk;
6102 if (both)
6103 break;
6106 if (both) {
6107 if (type == dns_rdatatype_dnskey) {
6108 if (!KSK(keys[i]) && keyset_kskonly)
6109 continue;
6110 } else if (KSK(keys[i]))
6111 continue;
6112 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey)
6113 continue;
6115 /* Calculate the signature, creating a RRSIG RDATA. */
6116 isc_buffer_clear(&buffer);
6117 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
6118 &inception, &expire,
6119 mctx, &buffer, &sig_rdata));
6120 /* Update the database and journal with the RRSIG. */
6121 /* XXX inefficient - will cause dataset merging */
6122 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
6123 name, rdataset.ttl, &sig_rdata));
6124 dns_rdata_reset(&sig_rdata);
6125 isc_buffer_init(&buffer, data, sizeof(data));
6128 failure:
6129 if (dns_rdataset_isassociated(&rdataset))
6130 dns_rdataset_disassociate(&rdataset);
6131 if (node != NULL)
6132 dns_db_detachnode(db, &node);
6133 return (result);
6136 static void
6137 zone_resigninc(dns_zone_t *zone) {
6138 const char *me = "zone_resigninc";
6139 dns_db_t *db = NULL;
6140 dns_dbversion_t *version = NULL;
6141 dns_diff_t _sig_diff;
6142 zonediff_t zonediff;
6143 dns_fixedname_t fixed;
6144 dns_name_t *name;
6145 dns_rdataset_t rdataset;
6146 dns_rdatatype_t covers;
6147 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6148 isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
6149 isc_result_t result;
6150 isc_stdtime_t now, inception, soaexpire, expire, stop;
6151 isc_uint32_t jitter;
6152 unsigned int i;
6153 unsigned int nkeys = 0;
6154 unsigned int resign;
6156 ENTER;
6158 dns_rdataset_init(&rdataset);
6159 dns_fixedname_init(&fixed);
6160 dns_diff_init(zone->mctx, &_sig_diff);
6161 zonediff_init(&zonediff, &_sig_diff);
6164 * Zone is frozen or automatic resigning is disabled.
6165 * Pause for 5 minutes.
6167 if (zone->update_disabled ||
6168 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
6170 result = ISC_R_FAILURE;
6171 goto failure;
6174 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6175 dns_db_attach(zone->db, &db);
6176 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6178 result = dns_db_newversion(db, &version);
6179 if (result != ISC_R_SUCCESS) {
6180 dns_zone_log(zone, ISC_LOG_ERROR,
6181 "zone_resigninc:dns_db_newversion -> %s",
6182 dns_result_totext(result));
6183 goto failure;
6186 result = find_zone_keys(zone, db, version, zone->mctx, DNS_MAXZONEKEYS,
6187 zone_keys, &nkeys);
6188 if (result != ISC_R_SUCCESS) {
6189 dns_zone_log(zone, ISC_LOG_ERROR,
6190 "zone_resigninc:find_zone_keys -> %s",
6191 dns_result_totext(result));
6192 goto failure;
6195 isc_stdtime_get(&now);
6196 inception = now - 3600; /* Allow for clock skew. */
6197 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
6199 * Spread out signatures over time if they happen to be
6200 * clumped. We don't do this for each add_sigs() call as
6201 * we still want some clustering to occur.
6203 isc_random_get(&jitter);
6204 expire = soaexpire - jitter % 3600;
6205 stop = now + 5;
6207 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6208 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6210 name = dns_fixedname_name(&fixed);
6211 result = dns_db_getsigningtime(db, &rdataset, name);
6212 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6213 dns_zone_log(zone, ISC_LOG_ERROR,
6214 "zone_resigninc:dns_db_getsigningtime -> %s",
6215 dns_result_totext(result));
6218 i = 0;
6219 while (result == ISC_R_SUCCESS) {
6220 resign = rdataset.resign - zone->sigresigninginterval;
6221 covers = rdataset.covers;
6222 dns_rdataset_disassociate(&rdataset);
6225 * Stop if we hit the SOA as that means we have walked the
6226 * entire zone. The SOA record should always be the most
6227 * recent signature.
6229 /* XXXMPA increase number of RRsets signed pre call */
6230 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
6231 resign > stop)
6232 break;
6234 result = del_sigs(zone, db, version, name, covers, &zonediff,
6235 zone_keys, nkeys, now, ISC_TRUE);
6236 if (result != ISC_R_SUCCESS) {
6237 dns_zone_log(zone, ISC_LOG_ERROR,
6238 "zone_resigninc:del_sigs -> %s",
6239 dns_result_totext(result));
6240 break;
6243 result = add_sigs(db, version, name, covers, zonediff.diff,
6244 zone_keys, nkeys, zone->mctx, inception,
6245 expire, check_ksk, keyset_kskonly);
6246 if (result != ISC_R_SUCCESS) {
6247 dns_zone_log(zone, ISC_LOG_ERROR,
6248 "zone_resigninc:add_sigs -> %s",
6249 dns_result_totext(result));
6250 break;
6252 result = dns_db_getsigningtime(db, &rdataset, name);
6253 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
6254 result = ISC_R_SUCCESS;
6255 break;
6257 if (result != ISC_R_SUCCESS)
6258 dns_zone_log(zone, ISC_LOG_ERROR,
6259 "zone_resigninc:dns_db_getsigningtime -> %s",
6260 dns_result_totext(result));
6263 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
6264 goto failure;
6266 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6267 &zonediff, zone_keys, nkeys, now, ISC_TRUE);
6268 if (result != ISC_R_SUCCESS) {
6269 dns_zone_log(zone, ISC_LOG_ERROR,
6270 "zone_resigninc:del_sigs -> %s",
6271 dns_result_totext(result));
6272 goto failure;
6276 * Did we change anything in the zone?
6278 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
6280 * Commit the changes if any key has been marked as offline. */
6281 if (zonediff.offline)
6282 dns_db_closeversion(db, &version, ISC_TRUE);
6283 goto failure;
6286 /* Increment SOA serial if we have made changes */
6287 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
6288 zone->updatemethod);
6289 if (result != ISC_R_SUCCESS) {
6290 dns_zone_log(zone, ISC_LOG_ERROR,
6291 "zone_resigninc:update_soa_serial -> %s",
6292 dns_result_totext(result));
6293 goto failure;
6297 * Generate maximum life time signatures so that the above loop
6298 * termination is sensible.
6300 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6301 zonediff.diff, zone_keys, nkeys, zone->mctx,
6302 inception, soaexpire, check_ksk, keyset_kskonly);
6303 if (result != ISC_R_SUCCESS) {
6304 dns_zone_log(zone, ISC_LOG_ERROR,
6305 "zone_resigninc:add_sigs -> %s",
6306 dns_result_totext(result));
6307 goto failure;
6310 /* Write changes to journal file. */
6311 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
6313 /* Everything has succeeded. Commit the changes. */
6314 dns_db_closeversion(db, &version, ISC_TRUE);
6316 failure:
6317 dns_diff_clear(&_sig_diff);
6318 for (i = 0; i < nkeys; i++)
6319 dst_key_free(&zone_keys[i]);
6320 if (version != NULL) {
6321 dns_db_closeversion(zone->db, &version, ISC_FALSE);
6322 dns_db_detach(&db);
6323 } else if (db != NULL)
6324 dns_db_detach(&db);
6325 if (result == ISC_R_SUCCESS) {
6326 set_resigntime(zone);
6327 LOCK_ZONE(zone);
6328 zone_needdump(zone, DNS_DUMP_DELAY);
6329 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6330 UNLOCK_ZONE(zone);
6331 } else {
6333 * Something failed. Retry in 5 minutes.
6335 isc_interval_t ival;
6336 isc_interval_set(&ival, 300, 0);
6337 isc_time_nowplusinterval(&zone->resigntime, &ival);
6340 INSIST(version == NULL);
6343 static isc_result_t
6344 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
6345 dns_name_t *newname, isc_boolean_t bottom)
6347 isc_result_t result;
6348 dns_dbiterator_t *dbit = NULL;
6349 dns_rdatasetiter_t *rdsit = NULL;
6350 dns_dbnode_t *node = NULL;
6352 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
6353 CHECK(dns_dbiterator_seek(dbit, oldname));
6354 do {
6355 result = dns_dbiterator_next(dbit);
6356 if (result == ISC_R_NOMORE)
6357 CHECK(dns_dbiterator_first(dbit));
6358 CHECK(dns_dbiterator_current(dbit, &node, newname));
6359 if (bottom && dns_name_issubdomain(newname, oldname) &&
6360 !dns_name_equal(newname, oldname)) {
6361 dns_db_detachnode(db, &node);
6362 continue;
6365 * Is this node empty?
6367 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
6368 result = dns_rdatasetiter_first(rdsit);
6369 dns_db_detachnode(db, &node);
6370 dns_rdatasetiter_destroy(&rdsit);
6371 if (result != ISC_R_NOMORE)
6372 break;
6373 } while (1);
6374 failure:
6375 if (node != NULL)
6376 dns_db_detachnode(db, &node);
6377 if (dbit != NULL)
6378 dns_dbiterator_destroy(&dbit);
6379 return (result);
6382 static isc_boolean_t
6383 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
6384 dns_rdatatype_t type, dst_key_t *key)
6386 isc_result_t result;
6387 dns_rdataset_t rdataset;
6388 dns_rdata_t rdata = DNS_RDATA_INIT;
6389 dns_rdata_rrsig_t rrsig;
6391 dns_rdataset_init(&rdataset);
6392 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
6393 type, 0, &rdataset, NULL);
6394 if (result != ISC_R_SUCCESS) {
6395 INSIST(!dns_rdataset_isassociated(&rdataset));
6396 return (ISC_FALSE);
6398 for (result = dns_rdataset_first(&rdataset);
6399 result == ISC_R_SUCCESS;
6400 result = dns_rdataset_next(&rdataset)) {
6401 dns_rdataset_current(&rdataset, &rdata);
6402 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6403 INSIST(result == ISC_R_SUCCESS);
6404 if (rrsig.algorithm == dst_key_alg(key) &&
6405 rrsig.keyid == dst_key_id(key)) {
6406 dns_rdataset_disassociate(&rdataset);
6407 return (ISC_TRUE);
6409 dns_rdata_reset(&rdata);
6411 dns_rdataset_disassociate(&rdataset);
6412 return (ISC_FALSE);
6415 static isc_result_t
6416 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6417 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
6418 dns_diff_t *diff)
6420 dns_fixedname_t fixed;
6421 dns_name_t *next;
6422 dns_rdata_t rdata = DNS_RDATA_INIT;
6423 isc_result_t result;
6424 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
6426 dns_fixedname_init(&fixed);
6427 next = dns_fixedname_name(&fixed);
6429 CHECK(next_active(db, version, name, next, bottom));
6430 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
6431 &rdata));
6432 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
6433 &rdata));
6434 failure:
6435 return (result);
6438 static isc_result_t
6439 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
6440 dns_dbversion_t *version, isc_boolean_t build_nsec3,
6441 isc_boolean_t build_nsec, dst_key_t *key,
6442 isc_stdtime_t inception, isc_stdtime_t expire,
6443 unsigned int minimum, isc_boolean_t is_ksk,
6444 isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
6445 dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
6447 isc_result_t result;
6448 dns_rdatasetiter_t *iterator = NULL;
6449 dns_rdataset_t rdataset;
6450 dns_rdata_t rdata = DNS_RDATA_INIT;
6451 isc_buffer_t buffer;
6452 unsigned char data[1024];
6453 isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
6454 seen_nsec3, seen_ds;
6455 isc_boolean_t bottom;
6457 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6458 if (result != ISC_R_SUCCESS) {
6459 if (result == ISC_R_NOTFOUND)
6460 result = ISC_R_SUCCESS;
6461 return (result);
6464 dns_rdataset_init(&rdataset);
6465 isc_buffer_init(&buffer, data, sizeof(data));
6466 seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
6467 seen_nsec3 = seen_ds = ISC_FALSE;
6468 for (result = dns_rdatasetiter_first(iterator);
6469 result == ISC_R_SUCCESS;
6470 result = dns_rdatasetiter_next(iterator)) {
6471 dns_rdatasetiter_current(iterator, &rdataset);
6472 if (rdataset.type == dns_rdatatype_soa)
6473 seen_soa = ISC_TRUE;
6474 else if (rdataset.type == dns_rdatatype_ns)
6475 seen_ns = ISC_TRUE;
6476 else if (rdataset.type == dns_rdatatype_ds)
6477 seen_ds = ISC_TRUE;
6478 else if (rdataset.type == dns_rdatatype_dname)
6479 seen_dname = ISC_TRUE;
6480 else if (rdataset.type == dns_rdatatype_nsec)
6481 seen_nsec = ISC_TRUE;
6482 else if (rdataset.type == dns_rdatatype_nsec3)
6483 seen_nsec3 = ISC_TRUE;
6484 if (rdataset.type != dns_rdatatype_rrsig)
6485 seen_rr = ISC_TRUE;
6486 dns_rdataset_disassociate(&rdataset);
6488 if (result != ISC_R_NOMORE)
6489 goto failure;
6490 if (seen_ns && !seen_soa)
6491 *delegation = ISC_TRUE;
6493 * Going from insecure to NSEC3.
6494 * Don't generate NSEC3 records for NSEC3 records.
6496 if (build_nsec3 && !seen_nsec3 && seen_rr) {
6497 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
6498 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
6499 unsecure, diff));
6500 (*signatures)--;
6503 * Going from insecure to NSEC.
6504 * Don't generate NSEC records for NSEC3 records.
6506 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
6507 /* Build and add NSEC. */
6508 bottom = (seen_ns && !seen_soa) || seen_dname;
6510 * Build a NSEC record except at the origin.
6512 if (!dns_name_equal(name, dns_db_origin(db))) {
6513 CHECK(add_nsec(db, version, name, node, minimum,
6514 bottom, diff));
6515 /* Count a NSEC generation as a signature generation. */
6516 (*signatures)--;
6519 result = dns_rdatasetiter_first(iterator);
6520 while (result == ISC_R_SUCCESS) {
6521 dns_rdatasetiter_current(iterator, &rdataset);
6522 if (rdataset.type == dns_rdatatype_soa ||
6523 rdataset.type == dns_rdatatype_rrsig)
6524 goto next_rdataset;
6525 if (rdataset.type == dns_rdatatype_dnskey) {
6526 if (!is_ksk && keyset_kskonly)
6527 goto next_rdataset;
6528 } else if (is_ksk)
6529 goto next_rdataset;
6530 if (*delegation &&
6531 rdataset.type != dns_rdatatype_ds &&
6532 rdataset.type != dns_rdatatype_nsec)
6533 goto next_rdataset;
6534 if (signed_with_key(db, node, version, rdataset.type, key))
6535 goto next_rdataset;
6536 /* Calculate the signature, creating a RRSIG RDATA. */
6537 isc_buffer_clear(&buffer);
6538 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
6539 &expire, mctx, &buffer, &rdata));
6540 /* Update the database and journal with the RRSIG. */
6541 /* XXX inefficient - will cause dataset merging */
6542 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
6543 name, rdataset.ttl, &rdata));
6544 dns_rdata_reset(&rdata);
6545 (*signatures)--;
6546 next_rdataset:
6547 dns_rdataset_disassociate(&rdataset);
6548 result = dns_rdatasetiter_next(iterator);
6550 if (result == ISC_R_NOMORE)
6551 result = ISC_R_SUCCESS;
6552 if (seen_dname)
6553 *delegation = ISC_TRUE;
6554 failure:
6555 if (dns_rdataset_isassociated(&rdataset))
6556 dns_rdataset_disassociate(&rdataset);
6557 if (iterator != NULL)
6558 dns_rdatasetiter_destroy(&iterator);
6559 return (result);
6563 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
6565 static isc_result_t
6566 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6567 dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
6569 isc_result_t result;
6570 dns_rdataset_t rdataset;
6571 dns_dbnode_t *node = NULL;
6573 CHECK(dns_db_getoriginnode(db, &node));
6574 if (update_only) {
6575 dns_rdataset_init(&rdataset);
6576 result = dns_db_findrdataset(db, node, version,
6577 dns_rdatatype_nsec,
6578 dns_rdatatype_none,
6579 0, &rdataset, NULL);
6580 if (dns_rdataset_isassociated(&rdataset))
6581 dns_rdataset_disassociate(&rdataset);
6582 if (result == ISC_R_NOTFOUND)
6583 goto success;
6584 if (result != ISC_R_SUCCESS)
6585 goto failure;
6587 CHECK(delete_nsec(db, version, node, name, diff));
6588 CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
6589 success:
6590 result = ISC_R_SUCCESS;
6591 failure:
6592 if (node != NULL)
6593 dns_db_detachnode(db, &node);
6594 return (result);
6597 static isc_result_t
6598 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
6599 dns_dbversion_t *version, isc_boolean_t build_nsec3,
6600 dns_ttl_t minimum, dns_diff_t *diff)
6602 isc_result_t result;
6603 dns_dbnode_t *node = NULL;
6604 dns_rdataset_t rdataset;
6605 dns_rdata_t rdata = DNS_RDATA_INIT;
6606 unsigned char data[5];
6607 isc_boolean_t seen_done = ISC_FALSE;
6608 isc_boolean_t have_rr = ISC_FALSE;
6610 dns_rdataset_init(&rdataset);
6611 result = dns_db_getoriginnode(signing->db, &node);
6612 if (result != ISC_R_SUCCESS)
6613 goto failure;
6615 result = dns_db_findrdataset(signing->db, node, version,
6616 zone->privatetype, dns_rdatatype_none,
6617 0, &rdataset, NULL);
6618 if (result == ISC_R_NOTFOUND) {
6619 INSIST(!dns_rdataset_isassociated(&rdataset));
6620 result = ISC_R_SUCCESS;
6621 goto failure;
6623 if (result != ISC_R_SUCCESS) {
6624 INSIST(!dns_rdataset_isassociated(&rdataset));
6625 goto failure;
6627 for (result = dns_rdataset_first(&rdataset);
6628 result == ISC_R_SUCCESS;
6629 result = dns_rdataset_next(&rdataset)) {
6630 dns_rdataset_current(&rdataset, &rdata);
6632 * If we don't match the algorithm or keyid skip the record.
6634 if (rdata.length != 5 ||
6635 rdata.data[0] != signing->algorithm ||
6636 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
6637 rdata.data[2] != (signing->keyid & 0xff)) {
6638 have_rr = ISC_TRUE;
6639 dns_rdata_reset(&rdata);
6640 continue;
6643 * We have a match. If we were signing (!signing->delete)
6644 * and we already have a record indicating that we have
6645 * finished signing (rdata.data[4] != 0) then keep it.
6646 * Otherwise it needs to be deleted as we have removed all
6647 * the signatures (signing->delete), so any record indicating
6648 * completion is now out of date, or we have finished signing
6649 * with the new record so we no longer need to remember that
6650 * we need to sign the zone with the matching key across a
6651 * nameserver re-start.
6653 if (!signing->delete && rdata.data[4] != 0) {
6654 seen_done = ISC_TRUE;
6655 have_rr = ISC_TRUE;
6656 } else
6657 CHECK(update_one_rr(signing->db, version, diff,
6658 DNS_DIFFOP_DEL, &zone->origin,
6659 rdataset.ttl, &rdata));
6660 dns_rdata_reset(&rdata);
6662 if (result == ISC_R_NOMORE)
6663 result = ISC_R_SUCCESS;
6664 if (!signing->delete && !seen_done) {
6666 * If we were signing then we need to indicate that we have
6667 * finished signing the zone with this key. If it is already
6668 * there we don't need to add it a second time.
6670 data[0] = signing->algorithm;
6671 data[1] = (signing->keyid >> 8) & 0xff;
6672 data[2] = signing->keyid & 0xff;
6673 data[3] = 0;
6674 data[4] = 1;
6675 rdata.length = sizeof(data);
6676 rdata.data = data;
6677 rdata.type = zone->privatetype;
6678 rdata.rdclass = dns_db_class(signing->db);
6679 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
6680 &zone->origin, rdataset.ttl, &rdata));
6681 } else if (!have_rr) {
6682 dns_name_t *origin = dns_db_origin(signing->db);
6684 * Rebuild the NSEC/NSEC3 record for the origin as we no
6685 * longer have any private records.
6687 if (build_nsec3)
6688 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
6689 minimum, ISC_FALSE, diff));
6690 CHECK(updatesecure(signing->db, version, origin, minimum,
6691 ISC_TRUE, diff));
6694 failure:
6695 if (dns_rdataset_isassociated(&rdataset))
6696 dns_rdataset_disassociate(&rdataset);
6697 if (node != NULL)
6698 dns_db_detachnode(signing->db, &node);
6699 return (result);
6703 * If 'active' is set then we are not done with the chain yet so only
6704 * delete the nsec3param record which indicates a full chain exists
6705 * (flags == 0).
6707 static isc_result_t
6708 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
6709 isc_boolean_t active, dns_rdatatype_t privatetype,
6710 dns_diff_t *diff)
6712 dns_dbnode_t *node = NULL;
6713 dns_name_t *name = dns_db_origin(db);
6714 dns_rdata_t rdata = DNS_RDATA_INIT;
6715 dns_rdataset_t rdataset;
6716 dns_rdata_nsec3param_t nsec3param;
6717 isc_result_t result;
6718 isc_buffer_t buffer;
6719 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
6720 dns_ttl_t ttl = 0;
6721 isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
6723 dns_rdataset_init(&rdataset);
6725 result = dns_db_getoriginnode(db, &node);
6726 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6727 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6728 0, 0, &rdataset, NULL);
6729 if (result == ISC_R_NOTFOUND)
6730 goto try_private;
6731 if (result != ISC_R_SUCCESS)
6732 goto failure;
6735 * Preserve the existing ttl.
6737 ttl = rdataset.ttl;
6740 * Delete all NSEC3PARAM records which match that in nsec3chain.
6742 for (result = dns_rdataset_first(&rdataset);
6743 result == ISC_R_SUCCESS;
6744 result = dns_rdataset_next(&rdataset)) {
6746 dns_rdataset_current(&rdataset, &rdata);
6747 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6749 if (nsec3param.hash != chain->nsec3param.hash ||
6750 (active && nsec3param.flags != 0) ||
6751 nsec3param.iterations != chain->nsec3param.iterations ||
6752 nsec3param.salt_length != chain->nsec3param.salt_length ||
6753 memcmp(nsec3param.salt, chain->nsec3param.salt,
6754 nsec3param.salt_length)) {
6755 dns_rdata_reset(&rdata);
6756 continue;
6759 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6760 name, rdataset.ttl, &rdata));
6761 dns_rdata_reset(&rdata);
6763 if (result != ISC_R_NOMORE)
6764 goto failure;
6766 dns_rdataset_disassociate(&rdataset);
6768 try_private:
6770 if (active)
6771 goto add;
6773 result = dns_nsec_nseconly(db, ver, &nseconly);
6774 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
6777 * Delete all private records which match that in nsec3chain.
6779 result = dns_db_findrdataset(db, node, ver, privatetype,
6780 0, 0, &rdataset, NULL);
6781 if (result == ISC_R_NOTFOUND)
6782 goto add;
6783 if (result != ISC_R_SUCCESS)
6784 goto failure;
6786 for (result = dns_rdataset_first(&rdataset);
6787 result == ISC_R_SUCCESS;
6788 result = dns_rdataset_next(&rdataset)) {
6789 dns_rdata_t private = DNS_RDATA_INIT;
6790 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
6792 dns_rdataset_current(&rdataset, &private);
6793 if (!dns_nsec3param_fromprivate(&private, &rdata,
6794 buf, sizeof(buf)))
6795 continue;
6796 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
6798 if ((!nsec3ok &&
6799 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
6800 nsec3param.hash != chain->nsec3param.hash ||
6801 nsec3param.iterations != chain->nsec3param.iterations ||
6802 nsec3param.salt_length != chain->nsec3param.salt_length ||
6803 memcmp(nsec3param.salt, chain->nsec3param.salt,
6804 nsec3param.salt_length)) {
6805 dns_rdata_reset(&rdata);
6806 continue;
6809 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
6810 name, rdataset.ttl, &private));
6811 dns_rdata_reset(&rdata);
6813 if (result != ISC_R_NOMORE)
6814 goto failure;
6816 add:
6817 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
6818 result = ISC_R_SUCCESS;
6819 goto failure;
6823 * Add a NSEC3PARAM record which matches that in nsec3chain but
6824 * with all flags bits cleared.
6826 * Note: we do not clear chain->nsec3param.flags as this change
6827 * may be reversed.
6829 isc_buffer_init(&buffer, &parambuf, sizeof(parambuf));
6830 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
6831 dns_rdatatype_nsec3param,
6832 &chain->nsec3param, &buffer));
6833 rdata.data[1] = 0; /* Clear flag bits. */
6834 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
6836 failure:
6837 dns_db_detachnode(db, &node);
6838 if (dns_rdataset_isassociated(&rdataset))
6839 dns_rdataset_disassociate(&rdataset);
6840 return (result);
6843 static isc_result_t
6844 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6845 dns_name_t *name, dns_diff_t *diff)
6847 dns_rdataset_t rdataset;
6848 isc_result_t result;
6850 dns_rdataset_init(&rdataset);
6852 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6853 0, 0, &rdataset, NULL);
6854 if (result == ISC_R_NOTFOUND)
6855 return (ISC_R_SUCCESS);
6856 if (result != ISC_R_SUCCESS)
6857 return (result);
6858 for (result = dns_rdataset_first(&rdataset);
6859 result == ISC_R_SUCCESS;
6860 result = dns_rdataset_next(&rdataset)) {
6861 dns_rdata_t rdata = DNS_RDATA_INIT;
6863 dns_rdataset_current(&rdataset, &rdata);
6864 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6865 rdataset.ttl, &rdata));
6867 if (result == ISC_R_NOMORE)
6868 result = ISC_R_SUCCESS;
6869 failure:
6870 dns_rdataset_disassociate(&rdataset);
6871 return (result);
6874 static isc_result_t
6875 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
6876 dns_name_t *name, const dns_rdata_nsec3param_t *param,
6877 dns_diff_t *diff)
6879 dns_rdataset_t rdataset;
6880 dns_rdata_nsec3_t nsec3;
6881 isc_result_t result;
6883 dns_rdataset_init(&rdataset);
6884 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
6885 0, 0, &rdataset, NULL);
6886 if (result == ISC_R_NOTFOUND)
6887 return (ISC_R_SUCCESS);
6888 if (result != ISC_R_SUCCESS)
6889 return (result);
6891 for (result = dns_rdataset_first(&rdataset);
6892 result == ISC_R_SUCCESS;
6893 result = dns_rdataset_next(&rdataset)) {
6894 dns_rdata_t rdata = DNS_RDATA_INIT;
6896 dns_rdataset_current(&rdataset, &rdata);
6897 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
6898 if (nsec3.hash != param->hash ||
6899 nsec3.iterations != param->iterations ||
6900 nsec3.salt_length != param->salt_length ||
6901 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
6902 continue;
6903 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
6904 rdataset.ttl, &rdata));
6906 if (result == ISC_R_NOMORE)
6907 result = ISC_R_SUCCESS;
6908 failure:
6909 dns_rdataset_disassociate(&rdataset);
6910 return (result);
6913 static isc_result_t
6914 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
6915 const dns_rdata_nsec3param_t *param,
6916 isc_boolean_t *answer)
6918 dns_dbnode_t *node = NULL;
6919 dns_rdata_t rdata = DNS_RDATA_INIT;
6920 dns_rdata_nsec3param_t myparam;
6921 dns_rdataset_t rdataset;
6922 isc_result_t result;
6924 *answer = ISC_FALSE;
6926 result = dns_db_getoriginnode(db, &node);
6927 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6929 dns_rdataset_init(&rdataset);
6931 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
6932 0, 0, &rdataset, NULL);
6933 if (result == ISC_R_SUCCESS) {
6934 dns_rdataset_disassociate(&rdataset);
6935 dns_db_detachnode(db, &node);
6936 return (result);
6938 if (result != ISC_R_NOTFOUND) {
6939 dns_db_detachnode(db, &node);
6940 return (result);
6943 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
6944 0, 0, &rdataset, NULL);
6945 if (result == ISC_R_NOTFOUND) {
6946 *answer = ISC_TRUE;
6947 dns_db_detachnode(db, &node);
6948 return (ISC_R_SUCCESS);
6950 if (result != ISC_R_SUCCESS) {
6951 dns_db_detachnode(db, &node);
6952 return (result);
6955 for (result = dns_rdataset_first(&rdataset);
6956 result == ISC_R_SUCCESS;
6957 result = dns_rdataset_next(&rdataset)) {
6958 dns_rdataset_current(&rdataset, &rdata);
6959 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
6960 dns_rdata_reset(&rdata);
6962 * Ignore any NSEC3PARAM removals.
6964 if (NSEC3REMOVE(myparam.flags))
6965 continue;
6967 * Ignore the chain that we are in the process of deleting.
6969 if (myparam.hash == param->hash &&
6970 myparam.iterations == param->iterations &&
6971 myparam.salt_length == param->salt_length &&
6972 !memcmp(myparam.salt, param->salt, myparam.salt_length))
6973 continue;
6975 * Found an active NSEC3 chain.
6977 break;
6979 if (result == ISC_R_NOMORE) {
6980 *answer = ISC_TRUE;
6981 result = ISC_R_SUCCESS;
6984 failure:
6985 if (dns_rdataset_isassociated(&rdataset))
6986 dns_rdataset_disassociate(&rdataset);
6987 dns_db_detachnode(db, &node);
6988 return (result);
6991 static isc_result_t
6992 update_sigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
6993 dst_key_t *zone_keys[], unsigned int nkeys, dns_zone_t *zone,
6994 isc_stdtime_t inception, isc_stdtime_t expire, isc_stdtime_t now,
6995 isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
6996 zonediff_t *zonediff)
6998 dns_difftuple_t *tuple;
6999 isc_result_t result;
7001 for (tuple = ISC_LIST_HEAD(diff->tuples);
7002 tuple != NULL;
7003 tuple = ISC_LIST_HEAD(diff->tuples)) {
7004 result = del_sigs(zone, db, version, &tuple->name,
7005 tuple->rdata.type, zonediff,
7006 zone_keys, nkeys, now, ISC_FALSE);
7007 if (result != ISC_R_SUCCESS) {
7008 dns_zone_log(zone, ISC_LOG_ERROR,
7009 "update_sigs:del_sigs -> %s",
7010 dns_result_totext(result));
7011 return (result);
7013 result = add_sigs(db, version, &tuple->name,
7014 tuple->rdata.type, zonediff->diff,
7015 zone_keys, nkeys, zone->mctx, inception,
7016 expire, check_ksk, keyset_kskonly);
7017 if (result != ISC_R_SUCCESS) {
7018 dns_zone_log(zone, ISC_LOG_ERROR,
7019 "update_sigs:add_sigs -> %s",
7020 dns_result_totext(result));
7021 return (result);
7024 do {
7025 dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
7026 while (next != NULL &&
7027 (tuple->rdata.type != next->rdata.type ||
7028 !dns_name_equal(&tuple->name, &next->name)))
7029 next = ISC_LIST_NEXT(next, link);
7030 ISC_LIST_UNLINK(diff->tuples, tuple, link);
7031 dns_diff_appendminimal(zonediff->diff, &tuple);
7032 INSIST(tuple == NULL);
7033 tuple = next;
7034 } while (tuple != NULL);
7036 return (ISC_R_SUCCESS);
7040 * Incrementally build and sign a new NSEC3 chain using the parameters
7041 * requested.
7043 static void
7044 zone_nsec3chain(dns_zone_t *zone) {
7045 const char *me = "zone_nsec3chain";
7046 dns_db_t *db = NULL;
7047 dns_dbnode_t *node = NULL;
7048 dns_dbversion_t *version = NULL;
7049 dns_diff_t _sig_diff;
7050 dns_diff_t nsec_diff;
7051 dns_diff_t nsec3_diff;
7052 dns_diff_t param_diff;
7053 zonediff_t zonediff;
7054 dns_fixedname_t fixed;
7055 dns_fixedname_t nextfixed;
7056 dns_name_t *name, *nextname;
7057 dns_rdataset_t rdataset;
7058 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
7059 dns_nsec3chainlist_t cleanup;
7060 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7061 isc_int32_t signatures;
7062 isc_boolean_t check_ksk, keyset_kskonly;
7063 isc_boolean_t delegation;
7064 isc_boolean_t first;
7065 isc_result_t result;
7066 isc_stdtime_t now, inception, soaexpire, expire;
7067 isc_uint32_t jitter;
7068 unsigned int i;
7069 unsigned int nkeys = 0;
7070 isc_uint32_t nodes;
7071 isc_boolean_t unsecure = ISC_FALSE;
7072 isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
7073 isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
7074 dns_rdatasetiter_t *iterator = NULL;
7075 isc_boolean_t buildnsecchain;
7076 isc_boolean_t updatensec = ISC_FALSE;
7077 dns_rdatatype_t privatetype = zone->privatetype;
7079 ENTER;
7081 dns_rdataset_init(&rdataset);
7082 dns_fixedname_init(&fixed);
7083 name = dns_fixedname_name(&fixed);
7084 dns_fixedname_init(&nextfixed);
7085 nextname = dns_fixedname_name(&nextfixed);
7086 dns_diff_init(zone->mctx, &param_diff);
7087 dns_diff_init(zone->mctx, &nsec3_diff);
7088 dns_diff_init(zone->mctx, &nsec_diff);
7089 dns_diff_init(zone->mctx, &_sig_diff);
7090 zonediff_init(&zonediff, &_sig_diff);
7091 ISC_LIST_INIT(cleanup);
7094 * Updates are disabled. Pause for 5 minutes.
7096 if (zone->update_disabled) {
7097 result = ISC_R_FAILURE;
7098 goto failure;
7101 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7102 dns_db_attach(zone->db, &db);
7103 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7105 result = dns_db_newversion(db, &version);
7106 if (result != ISC_R_SUCCESS) {
7107 dns_zone_log(zone, ISC_LOG_ERROR,
7108 "zone_nsec3chain:dns_db_newversion -> %s",
7109 dns_result_totext(result));
7110 goto failure;
7113 result = find_zone_keys(zone, db, version, zone->mctx,
7114 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7115 if (result != ISC_R_SUCCESS) {
7116 dns_zone_log(zone, ISC_LOG_ERROR,
7117 "zone_nsec3chain:find_zone_keys -> %s",
7118 dns_result_totext(result));
7119 goto failure;
7122 isc_stdtime_get(&now);
7123 inception = now - 3600; /* Allow for clock skew. */
7124 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7127 * Spread out signatures over time if they happen to be
7128 * clumped. We don't do this for each add_sigs() call as
7129 * we still want some clustering to occur.
7131 isc_random_get(&jitter);
7132 expire = soaexpire - jitter % 3600;
7134 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7135 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7138 * We keep pulling nodes off each iterator in turn until
7139 * we have no more nodes to pull off or we reach the limits
7140 * for this quantum.
7142 nodes = zone->nodes;
7143 signatures = zone->signatures;
7144 LOCK_ZONE(zone);
7145 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7146 UNLOCK_ZONE(zone);
7147 first = ISC_TRUE;
7149 if (nsec3chain != NULL)
7150 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7152 * Generate new NSEC3 chains first.
7154 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7155 LOCK_ZONE(zone);
7156 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7158 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7159 if (nsec3chain->done || nsec3chain->db != zone->db) {
7160 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
7161 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7163 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7164 UNLOCK_ZONE(zone);
7165 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
7166 goto next_addchain;
7169 * Possible future db.
7171 if (nsec3chain->db != db) {
7172 goto next_addchain;
7175 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
7176 goto next_addchain;
7178 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
7180 if (nsec3chain->delete_nsec) {
7181 delegation = ISC_FALSE;
7182 dns_dbiterator_pause(nsec3chain->dbiterator);
7183 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
7184 goto next_addnode;
7187 * On the first pass we need to check if the current node
7188 * has not been obscured.
7190 delegation = ISC_FALSE;
7191 unsecure = ISC_FALSE;
7192 if (first) {
7193 dns_fixedname_t ffound;
7194 dns_name_t *found;
7195 dns_fixedname_init(&ffound);
7196 found = dns_fixedname_name(&ffound);
7197 result = dns_db_find(db, name, version,
7198 dns_rdatatype_soa,
7199 DNS_DBFIND_NOWILD, 0, NULL, found,
7200 NULL, NULL);
7201 if ((result == DNS_R_DELEGATION ||
7202 result == DNS_R_DNAME) &&
7203 !dns_name_equal(name, found)) {
7205 * Remember the obscuring name so that
7206 * we skip all obscured names.
7208 dns_name_copy(found, name, NULL);
7209 delegation = ISC_TRUE;
7210 goto next_addnode;
7215 * Check to see if this is a bottom of zone node.
7217 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7218 if (result == ISC_R_NOTFOUND) /* Empty node? */
7219 goto next_addnode;
7220 if (result != ISC_R_SUCCESS)
7221 goto failure;
7223 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
7224 ISC_FALSE;
7225 for (result = dns_rdatasetiter_first(iterator);
7226 result == ISC_R_SUCCESS;
7227 result = dns_rdatasetiter_next(iterator)) {
7228 dns_rdatasetiter_current(iterator, &rdataset);
7229 INSIST(rdataset.type != dns_rdatatype_nsec3);
7230 if (rdataset.type == dns_rdatatype_soa)
7231 seen_soa = ISC_TRUE;
7232 else if (rdataset.type == dns_rdatatype_ns)
7233 seen_ns = ISC_TRUE;
7234 else if (rdataset.type == dns_rdatatype_dname)
7235 seen_dname = ISC_TRUE;
7236 else if (rdataset.type == dns_rdatatype_ds)
7237 seen_ds = ISC_TRUE;
7238 else if (rdataset.type == dns_rdatatype_nsec)
7239 seen_nsec = ISC_TRUE;
7240 dns_rdataset_disassociate(&rdataset);
7242 dns_rdatasetiter_destroy(&iterator);
7244 * Is there a NSEC chain than needs to be cleaned up?
7246 if (seen_nsec)
7247 nsec3chain->seen_nsec = ISC_TRUE;
7248 if (seen_ns && !seen_soa && !seen_ds)
7249 unsecure = ISC_TRUE;
7250 if ((seen_ns && !seen_soa) || seen_dname)
7251 delegation = ISC_TRUE;
7254 * Process one node.
7256 dns_dbiterator_pause(nsec3chain->dbiterator);
7257 result = dns_nsec3_addnsec3(db, version, name,
7258 &nsec3chain->nsec3param,
7259 zone->minimum, unsecure,
7260 &nsec3_diff);
7261 if (result != ISC_R_SUCCESS) {
7262 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7263 "dns_nsec3_addnsec3 -> %s",
7264 dns_result_totext(result));
7265 goto failure;
7269 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
7270 * two signatures. Additionally there will, in general, be
7271 * two signature generated below.
7273 * If we are only changing the optout flag the cost is half
7274 * that of the cost of generating a completely new chain.
7276 signatures -= 4;
7279 * Go onto next node.
7281 next_addnode:
7282 first = ISC_FALSE;
7283 dns_db_detachnode(db, &node);
7284 do {
7285 result = dns_dbiterator_next(nsec3chain->dbiterator);
7287 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
7288 dns_dbiterator_pause(nsec3chain->dbiterator);
7289 CHECK(fixup_nsec3param(db, version, nsec3chain,
7290 ISC_FALSE, privatetype,
7291 &param_diff));
7292 LOCK_ZONE(zone);
7293 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7294 link);
7295 UNLOCK_ZONE(zone);
7296 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7297 goto next_addchain;
7299 if (result == ISC_R_NOMORE) {
7300 dns_dbiterator_pause(nsec3chain->dbiterator);
7301 if (nsec3chain->seen_nsec) {
7302 CHECK(fixup_nsec3param(db, version,
7303 nsec3chain,
7304 ISC_TRUE,
7305 privatetype,
7306 &param_diff));
7307 nsec3chain->delete_nsec = ISC_TRUE;
7308 goto same_addchain;
7310 CHECK(fixup_nsec3param(db, version, nsec3chain,
7311 ISC_FALSE, privatetype,
7312 &param_diff));
7313 LOCK_ZONE(zone);
7314 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7315 link);
7316 UNLOCK_ZONE(zone);
7317 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7318 goto next_addchain;
7319 } else if (result != ISC_R_SUCCESS) {
7320 dns_zone_log(zone, ISC_LOG_ERROR,
7321 "zone_nsec3chain:"
7322 "dns_dbiterator_next -> %s",
7323 dns_result_totext(result));
7324 goto failure;
7325 } else if (delegation) {
7326 dns_dbiterator_current(nsec3chain->dbiterator,
7327 &node, nextname);
7328 dns_db_detachnode(db, &node);
7329 if (!dns_name_issubdomain(nextname, name))
7330 break;
7331 } else
7332 break;
7333 } while (1);
7334 continue;
7336 same_addchain:
7337 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7338 first = ISC_TRUE;
7339 continue;
7341 next_addchain:
7342 dns_dbiterator_pause(nsec3chain->dbiterator);
7343 nsec3chain = nextnsec3chain;
7344 first = ISC_TRUE;
7345 if (nsec3chain != NULL)
7346 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7350 * Process removals.
7352 LOCK_ZONE(zone);
7353 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7354 UNLOCK_ZONE(zone);
7355 first = ISC_TRUE;
7356 buildnsecchain = ISC_FALSE;
7357 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7358 LOCK_ZONE(zone);
7359 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7360 UNLOCK_ZONE(zone);
7362 if (nsec3chain->db != db)
7363 goto next_removechain;
7365 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
7366 goto next_removechain;
7369 * Work out if we need to build a NSEC chain as a consequence
7370 * of removing this NSEC3 chain.
7372 if (first && !updatensec &&
7373 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
7375 result = need_nsec_chain(db, version,
7376 &nsec3chain->nsec3param,
7377 &buildnsecchain);
7378 if (result != ISC_R_SUCCESS) {
7379 dns_zone_log(zone, ISC_LOG_ERROR,
7380 "zone_nsec3chain:"
7381 "need_nsec_chain -> %s",
7382 dns_result_totext(result));
7383 goto failure;
7387 if (first)
7388 dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
7389 "buildnsecchain = %u\n", buildnsecchain);
7391 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
7392 delegation = ISC_FALSE;
7394 if (!buildnsecchain) {
7396 * Delete the NSECPARAM record that matches this chain.
7398 if (first) {
7399 result = fixup_nsec3param(db, version,
7400 nsec3chain,
7401 ISC_TRUE, privatetype,
7402 &param_diff);
7403 if (result != ISC_R_SUCCESS) {
7404 dns_zone_log(zone, ISC_LOG_ERROR,
7405 "zone_nsec3chain:"
7406 "fixup_nsec3param -> %s",
7407 dns_result_totext(result));
7408 goto failure;
7413 * Delete the NSEC3 records.
7415 result = deletematchingnsec3(db, version, node, name,
7416 &nsec3chain->nsec3param,
7417 &nsec3_diff);
7418 if (result != ISC_R_SUCCESS) {
7419 dns_zone_log(zone, ISC_LOG_ERROR,
7420 "zone_nsec3chain:"
7421 "deletematchingnsec3 -> %s",
7422 dns_result_totext(result));
7423 goto failure;
7425 goto next_removenode;
7428 if (first) {
7429 dns_fixedname_t ffound;
7430 dns_name_t *found;
7431 dns_fixedname_init(&ffound);
7432 found = dns_fixedname_name(&ffound);
7433 result = dns_db_find(db, name, version,
7434 dns_rdatatype_soa,
7435 DNS_DBFIND_NOWILD, 0, NULL, found,
7436 NULL, NULL);
7437 if ((result == DNS_R_DELEGATION ||
7438 result == DNS_R_DNAME) &&
7439 !dns_name_equal(name, found)) {
7441 * Remember the obscuring name so that
7442 * we skip all obscured names.
7444 dns_name_copy(found, name, NULL);
7445 delegation = ISC_TRUE;
7446 goto next_removenode;
7451 * Check to see if this is a bottom of zone node.
7453 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7454 if (result == ISC_R_NOTFOUND) /* Empty node? */
7455 goto next_removenode;
7456 if (result != ISC_R_SUCCESS)
7457 goto failure;
7459 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
7460 seen_rr = ISC_FALSE;
7461 for (result = dns_rdatasetiter_first(iterator);
7462 result == ISC_R_SUCCESS;
7463 result = dns_rdatasetiter_next(iterator)) {
7464 dns_rdatasetiter_current(iterator, &rdataset);
7465 if (rdataset.type == dns_rdatatype_soa)
7466 seen_soa = ISC_TRUE;
7467 else if (rdataset.type == dns_rdatatype_ns)
7468 seen_ns = ISC_TRUE;
7469 else if (rdataset.type == dns_rdatatype_dname)
7470 seen_dname = ISC_TRUE;
7471 else if (rdataset.type == dns_rdatatype_nsec)
7472 seen_nsec = ISC_TRUE;
7473 else if (rdataset.type == dns_rdatatype_nsec3)
7474 seen_nsec3 = ISC_TRUE;
7475 if (rdataset.type != dns_rdatatype_rrsig)
7476 seen_rr = ISC_TRUE;
7477 dns_rdataset_disassociate(&rdataset);
7479 dns_rdatasetiter_destroy(&iterator);
7481 if (!seen_rr || seen_nsec3 || seen_nsec)
7482 goto next_removenode;
7483 if ((seen_ns && !seen_soa) || seen_dname)
7484 delegation = ISC_TRUE;
7487 * Add a NSEC record except at the origin.
7489 if (!dns_name_equal(name, dns_db_origin(db))) {
7490 dns_dbiterator_pause(nsec3chain->dbiterator);
7491 CHECK(add_nsec(db, version, name, node, zone->minimum,
7492 delegation, &nsec_diff));
7495 next_removenode:
7496 first = ISC_FALSE;
7497 dns_db_detachnode(db, &node);
7498 do {
7499 result = dns_dbiterator_next(nsec3chain->dbiterator);
7500 if (result == ISC_R_NOMORE && buildnsecchain) {
7502 * The NSEC chain should now be built.
7503 * We can now remove the NSEC3 chain.
7505 updatensec = ISC_TRUE;
7506 goto same_removechain;
7508 if (result == ISC_R_NOMORE) {
7509 LOCK_ZONE(zone);
7510 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7511 link);
7512 UNLOCK_ZONE(zone);
7513 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7514 dns_dbiterator_pause(nsec3chain->dbiterator);
7515 result = fixup_nsec3param(db, version,
7516 nsec3chain, ISC_FALSE,
7517 privatetype,
7518 &param_diff);
7519 if (result != ISC_R_SUCCESS) {
7520 dns_zone_log(zone, ISC_LOG_ERROR,
7521 "zone_nsec3chain:"
7522 "fixup_nsec3param -> %s",
7523 dns_result_totext(result));
7524 goto failure;
7526 goto next_removechain;
7527 } else if (result != ISC_R_SUCCESS) {
7528 dns_zone_log(zone, ISC_LOG_ERROR,
7529 "zone_nsec3chain:"
7530 "dns_dbiterator_next -> %s",
7531 dns_result_totext(result));
7532 goto failure;
7533 } else if (delegation) {
7534 dns_dbiterator_current(nsec3chain->dbiterator,
7535 &node, nextname);
7536 dns_db_detachnode(db, &node);
7537 if (!dns_name_issubdomain(nextname, name))
7538 break;
7539 } else
7540 break;
7541 } while (1);
7542 continue;
7544 same_removechain:
7545 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7546 buildnsecchain = ISC_FALSE;
7547 first = ISC_TRUE;
7548 continue;
7550 next_removechain:
7551 dns_dbiterator_pause(nsec3chain->dbiterator);
7552 nsec3chain = nextnsec3chain;
7553 first = ISC_TRUE;
7557 * We may need to update the NSEC/NSEC3 records for the zone apex.
7559 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
7560 isc_boolean_t rebuild_nsec = ISC_FALSE,
7561 rebuild_nsec3 = ISC_FALSE;
7562 result = dns_db_getoriginnode(db, &node);
7563 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7564 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7565 if (result != ISC_R_SUCCESS) {
7566 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7567 "dns_db_allrdatasets -> %s",
7568 dns_result_totext(result));
7569 goto failure;
7571 for (result = dns_rdatasetiter_first(iterator);
7572 result == ISC_R_SUCCESS;
7573 result = dns_rdatasetiter_next(iterator)) {
7574 dns_rdatasetiter_current(iterator, &rdataset);
7575 if (rdataset.type == dns_rdatatype_nsec)
7576 rebuild_nsec = ISC_TRUE;
7577 if (rdataset.type == dns_rdatatype_nsec3param)
7578 rebuild_nsec3 = ISC_TRUE;
7579 dns_rdataset_disassociate(&rdataset);
7581 dns_rdatasetiter_destroy(&iterator);
7582 dns_db_detachnode(db, &node);
7584 if (rebuild_nsec) {
7585 if (nsec3chain != NULL)
7586 dns_dbiterator_pause(nsec3chain->dbiterator);
7588 result = updatesecure(db, version, &zone->origin,
7589 zone->minimum, ISC_TRUE,
7590 &nsec_diff);
7591 if (result != ISC_R_SUCCESS) {
7592 dns_zone_log(zone, ISC_LOG_ERROR,
7593 "zone_nsec3chain:"
7594 "updatesecure -> %s",
7595 dns_result_totext(result));
7596 goto failure;
7600 if (rebuild_nsec3) {
7601 if (nsec3chain != NULL)
7602 dns_dbiterator_pause(nsec3chain->dbiterator);
7604 result = dns_nsec3_addnsec3s(db, version,
7605 dns_db_origin(db),
7606 zone->minimum, ISC_FALSE,
7607 &nsec3_diff);
7608 if (result != ISC_R_SUCCESS) {
7609 dns_zone_log(zone, ISC_LOG_ERROR,
7610 "zone_nsec3chain:"
7611 "dns_nsec3_addnsec3s -> %s",
7612 dns_result_totext(result));
7613 goto failure;
7618 if (nsec3chain != NULL)
7619 dns_dbiterator_pause(nsec3chain->dbiterator);
7622 * Add / update signatures for the NSEC3 records.
7624 if (nsec3chain != NULL)
7625 dns_dbiterator_pause(nsec3chain->dbiterator);
7626 result = update_sigs(&nsec3_diff, db, version, zone_keys,
7627 nkeys, zone, inception, expire, now,
7628 check_ksk, keyset_kskonly, &zonediff);
7629 if (result != ISC_R_SUCCESS) {
7630 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7631 "update_sigs -> %s", dns_result_totext(result));
7632 goto failure;
7636 * We have changed the NSEC3PARAM or private RRsets
7637 * above so we need to update the signatures.
7639 result = update_sigs(&param_diff, db, version, zone_keys,
7640 nkeys, zone, inception, expire, now,
7641 check_ksk, keyset_kskonly, &zonediff);
7642 if (result != ISC_R_SUCCESS) {
7643 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7644 "update_sigs -> %s", dns_result_totext(result));
7645 goto failure;
7648 if (updatensec) {
7649 result = updatesecure(db, version, &zone->origin,
7650 zone->minimum, ISC_FALSE, &nsec_diff);
7651 if (result != ISC_R_SUCCESS) {
7652 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7653 "updatesecure -> %s",
7654 dns_result_totext(result));
7655 goto failure;
7659 result = update_sigs(&nsec_diff, db, version, zone_keys,
7660 nkeys, zone, inception, expire, now,
7661 check_ksk, keyset_kskonly, &zonediff);
7662 if (result != ISC_R_SUCCESS) {
7663 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7664 "update_sigs -> %s", dns_result_totext(result));
7665 goto failure;
7669 * If we made no effective changes to the zone then we can just
7670 * cleanup otherwise we need to increment the serial.
7672 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7674 * No need to call dns_db_closeversion() here as it is
7675 * called with commit = ISC_TRUE below.
7677 goto done;
7680 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7681 &zonediff, zone_keys, nkeys, now, ISC_FALSE);
7682 if (result != ISC_R_SUCCESS) {
7683 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7684 "del_sigs -> %s", dns_result_totext(result));
7685 goto failure;
7688 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
7689 zone->updatemethod);
7690 if (result != ISC_R_SUCCESS) {
7691 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7692 "update_soa_serial -> %s",
7693 dns_result_totext(result));
7694 goto failure;
7697 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
7698 zonediff.diff, zone_keys, nkeys, zone->mctx,
7699 inception, soaexpire, check_ksk, keyset_kskonly);
7700 if (result != ISC_R_SUCCESS) {
7701 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7702 "add_sigs -> %s", dns_result_totext(result));
7703 goto failure;
7706 /* Write changes to journal file. */
7707 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
7709 LOCK_ZONE(zone);
7710 zone_needdump(zone, DNS_DUMP_DELAY);
7711 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7712 UNLOCK_ZONE(zone);
7714 done:
7716 * Pause all iterators so that dns_db_closeversion() can succeed.
7718 LOCK_ZONE(zone);
7719 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7720 nsec3chain != NULL;
7721 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7722 dns_dbiterator_pause(nsec3chain->dbiterator);
7723 UNLOCK_ZONE(zone);
7726 * Everything has succeeded. Commit the changes.
7727 * Unconditionally commit as zonediff.offline not checked above.
7729 dns_db_closeversion(db, &version, ISC_TRUE);
7732 * Everything succeeded so we can clean these up now.
7734 nsec3chain = ISC_LIST_HEAD(cleanup);
7735 while (nsec3chain != NULL) {
7736 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7737 dns_db_detach(&nsec3chain->db);
7738 dns_dbiterator_destroy(&nsec3chain->dbiterator);
7739 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7740 nsec3chain = ISC_LIST_HEAD(cleanup);
7743 set_resigntime(zone);
7745 failure:
7746 if (result != ISC_R_SUCCESS)
7747 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
7748 dns_result_totext(result));
7750 * On error roll back the current nsec3chain.
7752 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
7753 if (nsec3chain->done) {
7754 dns_db_detach(&nsec3chain->db);
7755 dns_dbiterator_destroy(&nsec3chain->dbiterator);
7756 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7757 } else {
7758 result = dns_dbiterator_first(nsec3chain->dbiterator);
7759 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7760 dns_dbiterator_pause(nsec3chain->dbiterator);
7761 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7766 * Rollback the cleanup list.
7768 nsec3chain = ISC_LIST_TAIL(cleanup);
7769 while (nsec3chain != NULL) {
7770 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
7771 if (nsec3chain->done) {
7772 dns_db_detach(&nsec3chain->db);
7773 dns_dbiterator_destroy(&nsec3chain->dbiterator);
7774 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
7775 } else {
7776 LOCK_ZONE(zone);
7777 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
7778 UNLOCK_ZONE(zone);
7779 result = dns_dbiterator_first(nsec3chain->dbiterator);
7780 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7781 dns_dbiterator_pause(nsec3chain->dbiterator);
7782 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
7784 nsec3chain = ISC_LIST_TAIL(cleanup);
7787 LOCK_ZONE(zone);
7788 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7789 nsec3chain != NULL;
7790 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
7791 dns_dbiterator_pause(nsec3chain->dbiterator);
7792 UNLOCK_ZONE(zone);
7794 dns_diff_clear(&param_diff);
7795 dns_diff_clear(&nsec3_diff);
7796 dns_diff_clear(&nsec_diff);
7797 dns_diff_clear(&_sig_diff);
7799 if (iterator != NULL)
7800 dns_rdatasetiter_destroy(&iterator);
7802 for (i = 0; i < nkeys; i++)
7803 dst_key_free(&zone_keys[i]);
7805 if (node != NULL)
7806 dns_db_detachnode(db, &node);
7807 if (version != NULL) {
7808 dns_db_closeversion(db, &version, ISC_FALSE);
7809 dns_db_detach(&db);
7810 } else if (db != NULL)
7811 dns_db_detach(&db);
7813 LOCK_ZONE(zone);
7814 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
7815 isc_interval_t interval;
7816 if (zone->update_disabled || result != ISC_R_SUCCESS)
7817 isc_interval_set(&interval, 60, 0); /* 1 minute */
7818 else
7819 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
7820 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
7821 } else
7822 isc_time_settoepoch(&zone->nsec3chaintime);
7823 UNLOCK_ZONE(zone);
7825 INSIST(version == NULL);
7828 static isc_result_t
7829 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7830 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
7831 isc_uint16_t keyid, dns_diff_t *diff)
7833 dns_rdata_rrsig_t rrsig;
7834 dns_rdataset_t rdataset;
7835 dns_rdatasetiter_t *iterator = NULL;
7836 isc_result_t result;
7838 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7839 if (result != ISC_R_SUCCESS) {
7840 if (result == ISC_R_NOTFOUND)
7841 result = ISC_R_SUCCESS;
7842 return (result);
7845 dns_rdataset_init(&rdataset);
7846 for (result = dns_rdatasetiter_first(iterator);
7847 result == ISC_R_SUCCESS;
7848 result = dns_rdatasetiter_next(iterator)) {
7849 dns_rdatasetiter_current(iterator, &rdataset);
7850 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
7851 for (result = dns_rdataset_first(&rdataset);
7852 result == ISC_R_SUCCESS;
7853 result = dns_rdataset_next(&rdataset)) {
7854 dns_rdata_t rdata = DNS_RDATA_INIT;
7855 dns_rdataset_current(&rdataset, &rdata);
7856 CHECK(update_one_rr(db, version, diff,
7857 DNS_DIFFOP_DEL, name,
7858 rdataset.ttl, &rdata));
7860 if (result != ISC_R_NOMORE)
7861 goto failure;
7862 dns_rdataset_disassociate(&rdataset);
7863 continue;
7865 if (rdataset.type != dns_rdatatype_rrsig) {
7866 dns_rdataset_disassociate(&rdataset);
7867 continue;
7869 for (result = dns_rdataset_first(&rdataset);
7870 result == ISC_R_SUCCESS;
7871 result = dns_rdataset_next(&rdataset)) {
7872 dns_rdata_t rdata = DNS_RDATA_INIT;
7873 dns_rdataset_current(&rdataset, &rdata);
7874 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
7875 if (rrsig.algorithm != algorithm ||
7876 rrsig.keyid != keyid)
7877 continue;
7878 CHECK(update_one_rr(db, version, diff,
7879 DNS_DIFFOP_DELRESIGN, name,
7880 rdataset.ttl, &rdata));
7882 dns_rdataset_disassociate(&rdataset);
7883 if (result != ISC_R_NOMORE)
7884 break;
7886 if (result == ISC_R_NOMORE)
7887 result = ISC_R_SUCCESS;
7888 failure:
7889 if (dns_rdataset_isassociated(&rdataset))
7890 dns_rdataset_disassociate(&rdataset);
7891 dns_rdatasetiter_destroy(&iterator);
7892 return (result);
7896 * Incrementally sign the zone using the keys requested.
7897 * Builds the NSEC chain if required.
7899 static void
7900 zone_sign(dns_zone_t *zone) {
7901 const char *me = "zone_sign";
7902 dns_db_t *db = NULL;
7903 dns_dbnode_t *node = NULL;
7904 dns_dbversion_t *version = NULL;
7905 dns_diff_t _sig_diff;
7906 dns_diff_t post_diff;
7907 zonediff_t zonediff;
7908 dns_fixedname_t fixed;
7909 dns_fixedname_t nextfixed;
7910 dns_name_t *name, *nextname;
7911 dns_rdataset_t rdataset;
7912 dns_signing_t *signing, *nextsigning;
7913 dns_signinglist_t cleanup;
7914 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7915 isc_int32_t signatures;
7916 isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
7917 isc_boolean_t commit = ISC_FALSE;
7918 isc_boolean_t delegation;
7919 isc_boolean_t build_nsec = ISC_FALSE;
7920 isc_boolean_t build_nsec3 = ISC_FALSE;
7921 isc_boolean_t first;
7922 isc_result_t result;
7923 isc_stdtime_t now, inception, soaexpire, expire;
7924 isc_uint32_t jitter;
7925 unsigned int i, j;
7926 unsigned int nkeys = 0;
7927 isc_uint32_t nodes;
7929 ENTER;
7931 dns_rdataset_init(&rdataset);
7932 dns_fixedname_init(&fixed);
7933 name = dns_fixedname_name(&fixed);
7934 dns_fixedname_init(&nextfixed);
7935 nextname = dns_fixedname_name(&nextfixed);
7936 dns_diff_init(zone->mctx, &_sig_diff);
7937 dns_diff_init(zone->mctx, &post_diff);
7938 zonediff_init(&zonediff, &_sig_diff);
7939 ISC_LIST_INIT(cleanup);
7942 * Updates are disabled. Pause for 5 minutes.
7944 if (zone->update_disabled) {
7945 result = ISC_R_FAILURE;
7946 goto failure;
7949 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7950 if (zone->db != NULL)
7951 dns_db_attach(zone->db, &db);
7952 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7953 if (db == NULL) {
7954 result = ISC_R_FAILURE;
7955 goto failure;
7958 result = dns_db_newversion(db, &version);
7959 if (result != ISC_R_SUCCESS) {
7960 dns_zone_log(zone, ISC_LOG_ERROR,
7961 "zone_sign:dns_db_newversion -> %s",
7962 dns_result_totext(result));
7963 goto failure;
7966 result = find_zone_keys(zone, db, version, zone->mctx,
7967 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7968 if (result != ISC_R_SUCCESS) {
7969 dns_zone_log(zone, ISC_LOG_ERROR,
7970 "zone_sign:find_zone_keys -> %s",
7971 dns_result_totext(result));
7972 goto failure;
7975 isc_stdtime_get(&now);
7976 inception = now - 3600; /* Allow for clock skew. */
7977 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
7980 * Spread out signatures over time if they happen to be
7981 * clumped. We don't do this for each add_sigs() call as
7982 * we still want some clustering to occur.
7984 isc_random_get(&jitter);
7985 expire = soaexpire - jitter % 3600;
7988 * We keep pulling nodes off each iterator in turn until
7989 * we have no more nodes to pull off or we reach the limits
7990 * for this quantum.
7992 nodes = zone->nodes;
7993 signatures = zone->signatures;
7994 signing = ISC_LIST_HEAD(zone->signing);
7995 first = ISC_TRUE;
7997 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7998 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8000 /* Determine which type of chain to build */
8001 CHECK(dns_private_chains(db, version, zone->privatetype,
8002 &build_nsec, &build_nsec3));
8004 /* If neither chain is found, default to NSEC */
8005 if (!build_nsec && !build_nsec3)
8006 build_nsec = ISC_TRUE;
8008 while (signing != NULL && nodes-- > 0 && signatures > 0) {
8009 nextsigning = ISC_LIST_NEXT(signing, link);
8011 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8012 if (signing->done || signing->db != zone->db) {
8014 * The zone has been reloaded. We will have
8015 * created new signings as part of the reload
8016 * process so we can destroy this one.
8018 ISC_LIST_UNLINK(zone->signing, signing, link);
8019 ISC_LIST_APPEND(cleanup, signing, link);
8020 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8021 goto next_signing;
8023 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8025 if (signing->db != db)
8026 goto next_signing;
8028 delegation = ISC_FALSE;
8030 if (first && signing->delete) {
8032 * Remove the key we are deleting from consideration.
8034 for (i = 0, j = 0; i < nkeys; i++) {
8036 * Find the key we want to remove.
8038 if (ALG(zone_keys[i]) == signing->algorithm &&
8039 dst_key_id(zone_keys[i]) == signing->keyid)
8041 if (KSK(zone_keys[i]))
8042 dst_key_free(&zone_keys[i]);
8043 continue;
8045 zone_keys[j] = zone_keys[i];
8046 j++;
8048 nkeys = j;
8051 dns_dbiterator_current(signing->dbiterator, &node, name);
8053 if (signing->delete) {
8054 dns_dbiterator_pause(signing->dbiterator);
8055 CHECK(del_sig(db, version, name, node, nkeys,
8056 signing->algorithm, signing->keyid,
8057 zonediff.diff));
8061 * On the first pass we need to check if the current node
8062 * has not been obscured.
8064 if (first) {
8065 dns_fixedname_t ffound;
8066 dns_name_t *found;
8067 dns_fixedname_init(&ffound);
8068 found = dns_fixedname_name(&ffound);
8069 result = dns_db_find(db, name, version,
8070 dns_rdatatype_soa,
8071 DNS_DBFIND_NOWILD, 0, NULL, found,
8072 NULL, NULL);
8073 if ((result == DNS_R_DELEGATION ||
8074 result == DNS_R_DNAME) &&
8075 !dns_name_equal(name, found)) {
8077 * Remember the obscuring name so that
8078 * we skip all obscured names.
8080 dns_name_copy(found, name, NULL);
8081 delegation = ISC_TRUE;
8082 goto next_node;
8087 * Process one node.
8089 dns_dbiterator_pause(signing->dbiterator);
8090 for (i = 0; i < nkeys; i++) {
8091 isc_boolean_t both = ISC_FALSE;
8094 * Find the keys we want to sign with.
8096 if (!dst_key_isprivate(zone_keys[i]))
8097 continue;
8100 * When adding look for the specific key.
8102 if (!signing->delete &&
8103 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
8104 dst_key_id(zone_keys[i]) != signing->keyid))
8105 continue;
8108 * When deleting make sure we are properly signed
8109 * with the algorithm that was being removed.
8111 if (signing->delete &&
8112 ALG(zone_keys[i]) != signing->algorithm)
8113 continue;
8116 * Do we do KSK processing?
8118 if (check_ksk && !REVOKE(zone_keys[i])) {
8119 isc_boolean_t have_ksk, have_nonksk;
8120 if (KSK(zone_keys[i])) {
8121 have_ksk = ISC_TRUE;
8122 have_nonksk = ISC_FALSE;
8123 } else {
8124 have_ksk = ISC_FALSE;
8125 have_nonksk = ISC_TRUE;
8127 for (j = 0; j < nkeys; j++) {
8128 if (j == i ||
8129 ALG(zone_keys[i]) !=
8130 ALG(zone_keys[j]))
8131 continue;
8132 if (REVOKE(zone_keys[j]))
8133 continue;
8134 if (KSK(zone_keys[j]))
8135 have_ksk = ISC_TRUE;
8136 else
8137 have_nonksk = ISC_TRUE;
8138 both = have_ksk && have_nonksk;
8139 if (both)
8140 break;
8143 if (both || REVOKE(zone_keys[i]))
8144 is_ksk = KSK(zone_keys[i]);
8145 else
8146 is_ksk = ISC_FALSE;
8148 CHECK(sign_a_node(db, name, node, version, build_nsec3,
8149 build_nsec, zone_keys[i], inception,
8150 expire, zone->minimum, is_ksk,
8151 ISC_TF(both && keyset_kskonly),
8152 &delegation, zonediff.diff,
8153 &signatures, zone->mctx));
8155 * If we are adding we are done. Look for other keys
8156 * of the same algorithm if deleting.
8158 if (!signing->delete)
8159 break;
8163 * Go onto next node.
8165 next_node:
8166 first = ISC_FALSE;
8167 dns_db_detachnode(db, &node);
8168 do {
8169 result = dns_dbiterator_next(signing->dbiterator);
8170 if (result == ISC_R_NOMORE) {
8171 ISC_LIST_UNLINK(zone->signing, signing, link);
8172 ISC_LIST_APPEND(cleanup, signing, link);
8173 dns_dbiterator_pause(signing->dbiterator);
8174 if (nkeys != 0 && build_nsec) {
8176 * We have finished regenerating the
8177 * zone with a zone signing key.
8178 * The NSEC chain is now complete and
8179 * there is a full set of signatures
8180 * for the zone. We can now clear the
8181 * OPT bit from the NSEC record.
8183 result = updatesecure(db, version,
8184 &zone->origin,
8185 zone->minimum,
8186 ISC_FALSE,
8187 &post_diff);
8188 if (result != ISC_R_SUCCESS) {
8189 dns_zone_log(zone,
8190 ISC_LOG_ERROR,
8191 "updatesecure -> %s",
8192 dns_result_totext(result));
8193 goto failure;
8196 result = updatesignwithkey(zone, signing,
8197 version,
8198 build_nsec3,
8199 zone->minimum,
8200 &post_diff);
8201 if (result != ISC_R_SUCCESS) {
8202 dns_zone_log(zone, ISC_LOG_ERROR,
8203 "updatesignwithkey -> %s",
8204 dns_result_totext(result));
8205 goto failure;
8207 build_nsec = ISC_FALSE;
8208 goto next_signing;
8209 } else if (result != ISC_R_SUCCESS) {
8210 dns_zone_log(zone, ISC_LOG_ERROR,
8211 "zone_sign:dns_dbiterator_next -> %s",
8212 dns_result_totext(result));
8213 goto failure;
8214 } else if (delegation) {
8215 dns_dbiterator_current(signing->dbiterator,
8216 &node, nextname);
8217 dns_db_detachnode(db, &node);
8218 if (!dns_name_issubdomain(nextname, name))
8219 break;
8220 } else
8221 break;
8222 } while (1);
8223 continue;
8225 next_signing:
8226 dns_dbiterator_pause(signing->dbiterator);
8227 signing = nextsigning;
8228 first = ISC_TRUE;
8231 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
8232 result = update_sigs(&post_diff, db, version, zone_keys,
8233 nkeys, zone, inception, expire, now,
8234 check_ksk, keyset_kskonly, &zonediff);
8235 if (result != ISC_R_SUCCESS) {
8236 dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
8237 "update_sigs -> %s",
8238 dns_result_totext(result));
8239 goto failure;
8244 * Have we changed anything?
8246 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8247 if (zonediff.offline)
8248 commit = ISC_TRUE;
8249 result = ISC_R_SUCCESS;
8250 goto pauseall;
8253 commit = ISC_TRUE;
8255 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8256 &zonediff, zone_keys, nkeys, now, ISC_FALSE);
8257 if (result != ISC_R_SUCCESS) {
8258 dns_zone_log(zone, ISC_LOG_ERROR,
8259 "zone_sign:del_sigs -> %s",
8260 dns_result_totext(result));
8261 goto failure;
8264 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
8265 zone->updatemethod);
8266 if (result != ISC_R_SUCCESS) {
8267 dns_zone_log(zone, ISC_LOG_ERROR,
8268 "zone_sign:update_soa_serial -> %s",
8269 dns_result_totext(result));
8270 goto failure;
8274 * Generate maximum life time signatures so that the above loop
8275 * termination is sensible.
8277 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
8278 zonediff.diff, zone_keys, nkeys, zone->mctx,
8279 inception, soaexpire, check_ksk, keyset_kskonly);
8280 if (result != ISC_R_SUCCESS) {
8281 dns_zone_log(zone, ISC_LOG_ERROR,
8282 "zone_sign:add_sigs -> %s",
8283 dns_result_totext(result));
8284 goto failure;
8288 * Write changes to journal file.
8290 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
8292 pauseall:
8294 * Pause all iterators so that dns_db_closeversion() can succeed.
8296 for (signing = ISC_LIST_HEAD(zone->signing);
8297 signing != NULL;
8298 signing = ISC_LIST_NEXT(signing, link))
8299 dns_dbiterator_pause(signing->dbiterator);
8301 for (signing = ISC_LIST_HEAD(cleanup);
8302 signing != NULL;
8303 signing = ISC_LIST_NEXT(signing, link))
8304 dns_dbiterator_pause(signing->dbiterator);
8307 * Everything has succeeded. Commit the changes.
8309 dns_db_closeversion(db, &version, commit);
8312 * Everything succeeded so we can clean these up now.
8314 signing = ISC_LIST_HEAD(cleanup);
8315 while (signing != NULL) {
8316 ISC_LIST_UNLINK(cleanup, signing, link);
8317 dns_db_detach(&signing->db);
8318 dns_dbiterator_destroy(&signing->dbiterator);
8319 isc_mem_put(zone->mctx, signing, sizeof *signing);
8320 signing = ISC_LIST_HEAD(cleanup);
8323 set_resigntime(zone);
8325 if (commit) {
8326 LOCK_ZONE(zone);
8327 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8328 zone_needdump(zone, DNS_DUMP_DELAY);
8329 UNLOCK_ZONE(zone);
8332 failure:
8334 * Rollback the cleanup list.
8336 signing = ISC_LIST_HEAD(cleanup);
8337 while (signing != NULL) {
8338 ISC_LIST_UNLINK(cleanup, signing, link);
8339 ISC_LIST_PREPEND(zone->signing, signing, link);
8340 dns_dbiterator_first(signing->dbiterator);
8341 dns_dbiterator_pause(signing->dbiterator);
8342 signing = ISC_LIST_HEAD(cleanup);
8345 for (signing = ISC_LIST_HEAD(zone->signing);
8346 signing != NULL;
8347 signing = ISC_LIST_NEXT(signing, link))
8348 dns_dbiterator_pause(signing->dbiterator);
8350 dns_diff_clear(&_sig_diff);
8352 for (i = 0; i < nkeys; i++)
8353 dst_key_free(&zone_keys[i]);
8355 if (node != NULL)
8356 dns_db_detachnode(db, &node);
8358 if (version != NULL) {
8359 dns_db_closeversion(db, &version, ISC_FALSE);
8360 dns_db_detach(&db);
8361 } else if (db != NULL)
8362 dns_db_detach(&db);
8364 if (ISC_LIST_HEAD(zone->signing) != NULL) {
8365 isc_interval_t interval;
8366 if (zone->update_disabled || result != ISC_R_SUCCESS)
8367 isc_interval_set(&interval, 60, 0); /* 1 minute */
8368 else
8369 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
8370 isc_time_nowplusinterval(&zone->signingtime, &interval);
8371 } else
8372 isc_time_settoepoch(&zone->signingtime);
8374 INSIST(version == NULL);
8377 static isc_result_t
8378 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
8379 unsigned char *data, int size)
8381 dns_rdata_dnskey_t dnskey;
8382 dns_rdata_keydata_t keydata;
8383 isc_buffer_t buf;
8384 isc_result_t result;
8386 dns_rdata_reset(target);
8387 isc_buffer_init(&buf, data, size);
8389 switch (rr->type) {
8390 case dns_rdatatype_dnskey:
8391 result = dns_rdata_tostruct(rr, &dnskey, NULL);
8392 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8393 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
8394 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
8395 &dnskey, &buf);
8396 break;
8397 case dns_rdatatype_keydata:
8398 result = dns_rdata_tostruct(rr, &keydata, NULL);
8399 if (result == ISC_R_UNEXPECTEDEND)
8400 return (result);
8401 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8402 dns_keydata_todnskey(&keydata, &dnskey, NULL);
8403 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
8404 &dnskey, &buf);
8405 break;
8406 default:
8407 INSIST(0);
8409 return (ISC_R_SUCCESS);
8413 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
8414 * a KEYDATA rdataset from the key zone.
8416 * 'rr' contains either a DNSKEY record, or a KEYDATA record
8418 * After normalizing keys to the same format (DNSKEY, with revoke bit
8419 * cleared), return ISC_TRUE if a key that matches 'rr' is found in
8420 * 'rdset', or ISC_FALSE if not.
8423 static isc_boolean_t
8424 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
8425 unsigned char data1[4096], data2[4096];
8426 dns_rdata_t rdata, rdata1, rdata2;
8427 isc_result_t result;
8429 dns_rdata_init(&rdata);
8430 dns_rdata_init(&rdata1);
8431 dns_rdata_init(&rdata2);
8433 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
8434 if (result != ISC_R_SUCCESS)
8435 return (ISC_FALSE);
8437 for (result = dns_rdataset_first(rdset);
8438 result == ISC_R_SUCCESS;
8439 result = dns_rdataset_next(rdset)) {
8440 dns_rdata_reset(&rdata);
8441 dns_rdataset_current(rdset, &rdata);
8442 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
8443 if (result != ISC_R_SUCCESS)
8444 continue;
8445 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
8446 return (ISC_TRUE);
8449 return (ISC_FALSE);
8453 * Calculate the refresh interval for a keydata zone, per
8454 * RFC5011: MAX(1 hr,
8455 * MIN(15 days,
8456 * 1/2 * OrigTTL,
8457 * 1/2 * RRSigExpirationInterval))
8458 * or for retries: MAX(1 hr,
8459 * MIN(1 day,
8460 * 1/10 * OrigTTL,
8461 * 1/10 * RRSigExpirationInterval))
8463 static inline isc_stdtime_t
8464 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
8465 isc_result_t result;
8466 isc_uint32_t t;
8467 dns_rdataset_t *rdset;
8468 dns_rdata_t sigrr = DNS_RDATA_INIT;
8469 dns_rdata_sig_t sig;
8470 isc_stdtime_t now;
8472 isc_stdtime_get(&now);
8474 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
8475 rdset = &kfetch->dnskeysigset;
8476 else
8477 return (now + dns_zone_mkey_hour);
8479 result = dns_rdataset_first(rdset);
8480 if (result != ISC_R_SUCCESS)
8481 return (now + dns_zone_mkey_hour);
8483 dns_rdataset_current(rdset, &sigrr);
8484 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8485 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8487 if (!retry) {
8488 t = sig.originalttl / 2;
8490 if (isc_serial_gt(sig.timeexpire, now)) {
8491 isc_uint32_t exp = (sig.timeexpire - now) / 2;
8492 if (t > exp)
8493 t = exp;
8496 if (t > (15 * dns_zone_mkey_day))
8497 t = (15 * dns_zone_mkey_day);
8499 if (t < dns_zone_mkey_hour)
8500 t = dns_zone_mkey_hour;
8501 } else {
8502 t = sig.originalttl / 10;
8504 if (isc_serial_gt(sig.timeexpire, now)) {
8505 isc_uint32_t exp = (sig.timeexpire - now) / 10;
8506 if (t > exp)
8507 t = exp;
8510 if (t > dns_zone_mkey_day)
8511 t = dns_zone_mkey_day;
8513 if (t < dns_zone_mkey_hour)
8514 t = dns_zone_mkey_hour;
8517 return (now + t);
8521 * This routine is called when no changes are needed in a KEYDATA
8522 * record except to simply update the refresh timer. Caller should
8523 * hold zone lock.
8525 static isc_result_t
8526 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
8528 isc_result_t result;
8529 isc_buffer_t keyb;
8530 unsigned char key_buf[4096];
8531 dns_rdata_t rdata = DNS_RDATA_INIT;
8532 dns_rdata_keydata_t keydata;
8533 dns_name_t *name;
8534 dns_zone_t *zone = kfetch->zone;
8535 isc_stdtime_t now;
8537 name = dns_fixedname_name(&kfetch->name);
8538 isc_stdtime_get(&now);
8540 for (result = dns_rdataset_first(&kfetch->keydataset);
8541 result == ISC_R_SUCCESS;
8542 result = dns_rdataset_next(&kfetch->keydataset)) {
8543 dns_rdata_reset(&rdata);
8544 dns_rdataset_current(&kfetch->keydataset, &rdata);
8546 /* Delete old version */
8547 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
8548 name, 0, &rdata));
8550 /* Update refresh timer */
8551 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
8552 if (result == ISC_R_UNEXPECTEDEND)
8553 continue;
8554 if (result != ISC_R_SUCCESS)
8555 goto failure;
8556 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
8557 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8559 dns_rdata_reset(&rdata);
8560 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8561 CHECK(dns_rdata_fromstruct(&rdata,
8562 zone->rdclass, dns_rdatatype_keydata,
8563 &keydata, &keyb));
8565 /* Insert updated version */
8566 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
8567 name, 0, &rdata));
8569 result = ISC_R_SUCCESS;
8570 failure:
8571 return (result);
8575 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
8577 static isc_boolean_t
8578 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
8579 isc_result_t result;
8580 dns_name_t *keyname;
8581 isc_mem_t *mctx;
8582 dns_rdata_t sigrr = DNS_RDATA_INIT;
8583 dns_rdata_t rr = DNS_RDATA_INIT;
8584 dns_rdata_rrsig_t sig;
8585 dns_rdata_dnskey_t dnskey;
8586 dst_key_t *dstkey = NULL;
8587 unsigned char key_buf[4096];
8588 isc_buffer_t keyb;
8589 isc_boolean_t answer = ISC_FALSE;
8591 REQUIRE(kfetch != NULL && keydata != NULL);
8592 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
8594 keyname = dns_fixedname_name(&kfetch->name);
8595 mctx = kfetch->zone->view->mctx;
8597 /* Generate a key from keydata */
8598 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8599 dns_keydata_todnskey(keydata, &dnskey, NULL);
8600 dns_rdata_fromstruct(&rr, keydata->common.rdclass,
8601 dns_rdatatype_dnskey, &dnskey, &keyb);
8602 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
8603 if (result != ISC_R_SUCCESS)
8604 return (ISC_FALSE);
8606 /* See if that key generated any of the signatures */
8607 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8608 result == ISC_R_SUCCESS;
8609 result = dns_rdataset_next(&kfetch->dnskeysigset))
8611 dns_fixedname_t fixed;
8612 dns_fixedname_init(&fixed);
8614 dns_rdata_reset(&sigrr);
8615 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8616 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8617 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8619 if (dst_key_alg(dstkey) == sig.algorithm &&
8620 dst_key_rid(dstkey) == sig.keyid)
8622 result = dns_dnssec_verify2(keyname,
8623 &kfetch->dnskeyset,
8624 dstkey, ISC_FALSE, mctx, &sigrr,
8625 dns_fixedname_name(&fixed));
8627 dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
8628 "Confirm revoked DNSKEY is self-signed: "
8629 "%s", dns_result_totext(result));
8631 if (result == ISC_R_SUCCESS) {
8632 answer = ISC_TRUE;
8633 break;
8638 dst_key_free(&dstkey);
8639 return (answer);
8643 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
8644 * anchors are being managed; scan the keyset, and update the key zone and the
8645 * local trust anchors according to RFC5011.
8647 static void
8648 keyfetch_done(isc_task_t *task, isc_event_t *event) {
8649 isc_result_t result, eresult;
8650 dns_fetchevent_t *devent;
8651 dns_keyfetch_t *kfetch;
8652 dns_zone_t *zone;
8653 isc_mem_t *mctx = NULL;
8654 dns_keytable_t *secroots = NULL;
8655 dns_dbversion_t *ver = NULL;
8656 dns_diff_t diff;
8657 isc_boolean_t alldone = ISC_FALSE;
8658 isc_boolean_t commit = ISC_FALSE;
8659 dns_name_t *keyname;
8660 dns_rdata_t sigrr = DNS_RDATA_INIT;
8661 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
8662 dns_rdata_t keydatarr = DNS_RDATA_INIT;
8663 dns_rdata_rrsig_t sig;
8664 dns_rdata_dnskey_t dnskey;
8665 dns_rdata_keydata_t keydata;
8666 isc_boolean_t initializing;
8667 char namebuf[DNS_NAME_FORMATSIZE];
8668 unsigned char key_buf[4096];
8669 isc_buffer_t keyb;
8670 dst_key_t *dstkey;
8671 isc_stdtime_t now;
8672 int pending = 0;
8673 isc_boolean_t secure;
8674 isc_boolean_t free_needed;
8676 UNUSED(task);
8677 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
8678 INSIST(event->ev_arg != NULL);
8680 kfetch = event->ev_arg;
8681 zone = kfetch->zone;
8682 isc_mem_attach(zone->mctx, &mctx);
8683 keyname = dns_fixedname_name(&kfetch->name);
8685 devent = (dns_fetchevent_t *) event;
8686 eresult = devent->result;
8688 /* Free resources which are not of interest */
8689 if (devent->node != NULL)
8690 dns_db_detachnode(devent->db, &devent->node);
8691 if (devent->db != NULL)
8692 dns_db_detach(&devent->db);
8693 isc_event_free(&event);
8694 dns_resolver_destroyfetch(&kfetch->fetch);
8696 LOCK_ZONE(zone);
8697 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
8698 goto cleanup;
8700 isc_stdtime_get(&now);
8701 dns_name_format(keyname, namebuf, sizeof(namebuf));
8703 result = dns_view_getsecroots(zone->view, &secroots);
8704 INSIST(result == ISC_R_SUCCESS);
8706 dns_diff_init(mctx, &diff);
8708 CHECK(dns_db_newversion(kfetch->db, &ver));
8710 zone->refreshkeycount--;
8711 alldone = ISC_TF(zone->refreshkeycount == 0);
8713 if (alldone)
8714 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
8716 /* Fetch failed */
8717 if (eresult != ISC_R_SUCCESS ||
8718 !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
8719 dns_zone_log(zone, ISC_LOG_WARNING,
8720 "Unable to fetch DNSKEY set "
8721 "'%s': %s", namebuf, dns_result_totext(eresult));
8722 CHECK(minimal_update(kfetch, ver, &diff));
8723 goto done;
8726 /* No RRSIGs found */
8727 if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
8728 dns_zone_log(zone, ISC_LOG_WARNING,
8729 "No DNSKEY RRSIGs found for "
8730 "'%s': %s", namebuf, dns_result_totext(eresult));
8731 CHECK(minimal_update(kfetch, ver, &diff));
8732 goto done;
8736 * Clear any cached trust level, as we need to run validation
8737 * over again; trusted keys might have changed.
8739 kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
8742 * Validate the dnskeyset against the current trusted keys.
8744 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
8745 result == ISC_R_SUCCESS;
8746 result = dns_rdataset_next(&kfetch->dnskeysigset)) {
8747 dns_keynode_t *keynode = NULL;
8749 dns_rdata_reset(&sigrr);
8750 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
8751 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
8752 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8754 result = dns_keytable_find(secroots, keyname, &keynode);
8755 while (result == ISC_R_SUCCESS) {
8756 dns_keynode_t *nextnode = NULL;
8757 dns_fixedname_t fixed;
8758 dns_fixedname_init(&fixed);
8760 dstkey = dns_keynode_key(keynode);
8761 if (dstkey == NULL) /* fail_secure() was called */
8762 break;
8764 if (dst_key_alg(dstkey) == sig.algorithm &&
8765 dst_key_id(dstkey) == sig.keyid) {
8766 result = dns_dnssec_verify2(keyname,
8767 &kfetch->dnskeyset,
8768 dstkey, ISC_FALSE,
8769 zone->view->mctx, &sigrr,
8770 dns_fixedname_name(&fixed));
8772 dns_zone_log(zone, ISC_LOG_DEBUG(3),
8773 "Verifying DNSKEY set for zone "
8774 "'%s' using key %d/%d: %s",
8775 namebuf, sig.keyid, sig.algorithm,
8776 dns_result_totext(result));
8778 if (result == ISC_R_SUCCESS) {
8779 kfetch->dnskeyset.trust =
8780 dns_trust_secure;
8781 kfetch->dnskeysigset.trust =
8782 dns_trust_secure;
8783 break;
8787 result = dns_keytable_nextkeynode(secroots,
8788 keynode, &nextnode);
8789 dns_keytable_detachkeynode(secroots, &keynode);
8790 keynode = nextnode;
8793 if (keynode != NULL)
8794 dns_keytable_detachkeynode(secroots, &keynode);
8796 if (kfetch->dnskeyset.trust == dns_trust_secure)
8797 break;
8801 * If we were not able to verify the answer using the current
8802 * trusted keys then all we can do is look at any revoked keys.
8804 secure = ISC_TF(kfetch->dnskeyset.trust == dns_trust_secure);
8807 * First scan keydataset to find keys that are not in dnskeyset
8808 * - Missing keys which are not scheduled for removal,
8809 * log a warning
8810 * - Missing keys which are scheduled for removal and
8811 * the remove hold-down timer has completed should
8812 * be removed from the key zone
8813 * - Missing keys whose acceptance timers have not yet
8814 * completed, log a warning and reset the acceptance
8815 * timer to 30 days in the future
8816 * - All keys not being removed have their refresh timers
8817 * updated
8819 initializing = ISC_TRUE;
8820 for (result = dns_rdataset_first(&kfetch->keydataset);
8821 result == ISC_R_SUCCESS;
8822 result = dns_rdataset_next(&kfetch->keydataset)) {
8823 dns_rdata_reset(&keydatarr);
8824 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8825 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8826 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8829 * If any keydata record has a nonzero add holddown, then
8830 * there was a pre-existing trust anchor for this domain;
8831 * that means we are *not* initializing it and shouldn't
8832 * automatically trust all the keys we find at the zone apex.
8834 initializing = initializing && ISC_TF(keydata.addhd == 0);
8836 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
8837 isc_boolean_t deletekey = ISC_FALSE;
8839 if (!secure) {
8840 if (keydata.removehd != 0 &&
8841 keydata.removehd <= now)
8842 deletekey = ISC_TRUE;
8843 } else if (keydata.addhd == 0) {
8844 deletekey = ISC_TRUE;
8845 } else if (keydata.addhd > now) {
8846 dns_zone_log(zone, ISC_LOG_WARNING,
8847 "Pending key unexpectedly missing "
8848 "from %s; restarting acceptance "
8849 "timer", namebuf);
8850 if (keydata.addhd < now + dns_zone_mkey_month)
8851 keydata.addhd =
8852 now + dns_zone_mkey_month;
8853 keydata.refresh = refresh_time(kfetch,
8854 ISC_FALSE);
8855 } else if (keydata.removehd == 0) {
8856 dns_zone_log(zone, ISC_LOG_WARNING,
8857 "Active key unexpectedly missing "
8858 "from %s", namebuf);
8859 keydata.refresh = now + dns_zone_mkey_hour;
8860 } else if (keydata.removehd <= now) {
8861 deletekey = ISC_TRUE;
8862 } else {
8863 keydata.refresh = refresh_time(kfetch,
8864 ISC_FALSE);
8867 if (secure || deletekey) {
8868 /* Delete old version */
8869 CHECK(update_one_rr(kfetch->db, ver, &diff,
8870 DNS_DIFFOP_DEL, keyname, 0,
8871 &keydatarr));
8874 if (!secure || deletekey)
8875 continue;
8877 dns_rdata_reset(&keydatarr);
8878 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
8879 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
8880 dns_rdatatype_keydata,
8881 &keydata, &keyb);
8883 /* Insert updated version */
8884 CHECK(update_one_rr(kfetch->db, ver, &diff,
8885 DNS_DIFFOP_ADD, keyname, 0,
8886 &keydatarr));
8888 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
8893 * Next scan dnskeyset:
8894 * - If new keys are found (i.e., lacking a match in keydataset)
8895 * add them to the key zone and set the acceptance timer
8896 * to 30 days in the future (or to immediately if we've
8897 * determined that we're initializing the zone for the
8898 * first time)
8899 * - Previously-known keys that have been revoked
8900 * must be scheduled for removal from the key zone (or,
8901 * if they hadn't been accepted as trust anchors yet
8902 * anyway, removed at once)
8903 * - Previously-known unrevoked keys whose acceptance timers
8904 * have completed are promoted to trust anchors
8905 * - All keys not being removed have their refresh
8906 * timers updated
8908 for (result = dns_rdataset_first(&kfetch->dnskeyset);
8909 result == ISC_R_SUCCESS;
8910 result = dns_rdataset_next(&kfetch->dnskeyset))
8912 isc_boolean_t revoked = ISC_FALSE;
8913 isc_boolean_t newkey = ISC_FALSE;
8914 isc_boolean_t updatekey = ISC_FALSE;
8915 isc_boolean_t deletekey = ISC_FALSE;
8916 isc_boolean_t trustkey = ISC_FALSE;
8918 dns_rdata_reset(&dnskeyrr);
8919 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
8920 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
8921 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8923 /* Skip ZSK's */
8924 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
8925 continue;
8927 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
8929 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
8930 dns_rdata_reset(&keydatarr);
8931 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
8932 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
8933 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8935 if (revoked && revocable(kfetch, &keydata)) {
8936 if (keydata.addhd > now) {
8938 * Key wasn't trusted yet, and now
8939 * it's been revoked? Just remove it
8941 deletekey = ISC_TRUE;
8942 } else if (keydata.removehd == 0) {
8943 /* Remove from secroots */
8944 dns_view_untrust(zone->view, keyname,
8945 &dnskey, mctx);
8947 /* But ensure there's a null key */
8948 fail_secure(zone, keyname);
8950 /* If initializing, delete now */
8951 if (keydata.addhd == 0)
8952 deletekey = ISC_TRUE;
8953 else {
8954 keydata.removehd = now +
8955 dns_zone_mkey_month;
8956 keydata.flags |=
8957 DNS_KEYFLAG_REVOKE;
8959 } else if (keydata.removehd < now) {
8960 /* Scheduled for removal */
8961 deletekey = ISC_TRUE;
8963 } else if (revoked && keydata.removehd == 0) {
8964 dns_zone_log(zone, ISC_LOG_WARNING,
8965 "Active key for zone "
8966 "'%s' is revoked but "
8967 "did not self-sign; "
8968 "ignoring.", namebuf);
8969 continue;
8970 } else if (secure) {
8971 if (keydata.removehd != 0) {
8973 * Key isn't revoked--but it
8974 * seems it used to be.
8975 * Remove it now and add it
8976 * back as if it were a fresh key,
8977 * with a 30 day acceptance timer.
8979 deletekey = ISC_TRUE;
8980 newkey = ISC_TRUE;
8981 keydata.removehd = 0;
8982 keydata.addhd =
8983 now + dns_zone_mkey_month;
8984 } else if (keydata.addhd > now)
8985 pending++;
8986 else if (keydata.addhd == 0)
8987 keydata.addhd = now;
8989 if (keydata.addhd <= now)
8990 trustkey = ISC_TRUE;
8991 } else if (keydata.addhd > now) {
8993 * Not secure, and key is pending:
8994 * reset the acceptance timer
8996 pending++;
8997 keydata.addhd = now + dns_zone_mkey_month;
9000 if (!deletekey && !newkey)
9001 updatekey = ISC_TRUE;
9002 } else if (secure) {
9004 * Key wasn't in the key zone but it's
9005 * revoked now anyway, so just skip it
9007 if (revoked)
9008 continue;
9010 /* Key wasn't in the key zone: add it */
9011 newkey = ISC_TRUE;
9013 if (initializing) {
9014 dns_keytag_t tag = 0;
9015 CHECK(compute_tag(keyname, &dnskey,
9016 mctx, &tag));
9017 dns_zone_log(zone, ISC_LOG_WARNING,
9018 "Initializing automatic trust "
9019 "anchor management for zone '%s'; "
9020 "DNSKEY ID %d is now trusted, "
9021 "waiving the normal 30-day "
9022 "waiting period.",
9023 namebuf, tag);
9024 trustkey = ISC_TRUE;
9026 } else {
9028 * No previously known key, and the key is not
9029 * secure, so skip it.
9031 continue;
9034 /* Delete old version */
9035 if (deletekey || !newkey)
9036 CHECK(update_one_rr(kfetch->db, ver, &diff,
9037 DNS_DIFFOP_DEL, keyname, 0,
9038 &keydatarr));
9040 if (updatekey) {
9041 /* Set refresh timer */
9042 keydata.refresh = refresh_time(kfetch, ISC_FALSE);
9043 dns_rdata_reset(&keydatarr);
9044 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9045 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9046 dns_rdatatype_keydata,
9047 &keydata, &keyb);
9049 /* Insert updated version */
9050 CHECK(update_one_rr(kfetch->db, ver, &diff,
9051 DNS_DIFFOP_ADD, keyname, 0,
9052 &keydatarr));
9053 } else if (newkey) {
9054 /* Convert DNSKEY to KEYDATA */
9055 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9056 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9057 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
9058 NULL);
9059 keydata.addhd = initializing
9060 ? now : now + dns_zone_mkey_month;
9061 keydata.refresh = refresh_time(kfetch, ISC_FALSE);
9062 dns_rdata_reset(&keydatarr);
9063 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9064 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9065 dns_rdatatype_keydata,
9066 &keydata, &keyb);
9068 /* Insert into key zone */
9069 CHECK(update_one_rr(kfetch->db, ver, &diff,
9070 DNS_DIFFOP_ADD, keyname, 0,
9071 &keydatarr));
9074 if (trustkey) {
9075 /* Trust this key. */
9076 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9077 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9078 trust_key(zone, keyname, &dnskey, mctx);
9081 if (secure && !deletekey) {
9082 INSIST(newkey || updatekey);
9083 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
9088 * RFC5011 says, "A trust point that has all of its trust anchors
9089 * revoked is considered deleted and is treated as if the trust
9090 * point was never configured." But if someone revoked their
9091 * active key before the standby was trusted, that would mean the
9092 * zone would suddenly be nonsecured. We avoid this by checking to
9093 * see if there's pending keydata. If so, we put a null key in
9094 * the security roots; then all queries to the zone will fail.
9096 if (pending != 0)
9097 fail_secure(zone, keyname);
9099 done:
9101 if (!ISC_LIST_EMPTY(diff.tuples)) {
9102 /* Write changes to journal file. */
9103 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
9104 zone->updatemethod));
9105 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
9106 commit = ISC_TRUE;
9108 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9109 zone_needdump(zone, 30);
9112 failure:
9114 dns_diff_clear(&diff);
9115 if (ver != NULL)
9116 dns_db_closeversion(kfetch->db, &ver, commit);
9118 cleanup:
9119 dns_db_detach(&kfetch->db);
9121 INSIST(zone->irefs > 0);
9122 zone->irefs--;
9123 kfetch->zone = NULL;
9125 if (dns_rdataset_isassociated(&kfetch->keydataset))
9126 dns_rdataset_disassociate(&kfetch->keydataset);
9127 if (dns_rdataset_isassociated(&kfetch->dnskeyset))
9128 dns_rdataset_disassociate(&kfetch->dnskeyset);
9129 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
9130 dns_rdataset_disassociate(&kfetch->dnskeysigset);
9132 dns_name_free(keyname, mctx);
9133 isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
9134 isc_mem_detach(&mctx);
9136 if (secroots != NULL)
9137 dns_keytable_detach(&secroots);
9139 free_needed = exit_check(zone);
9140 UNLOCK_ZONE(zone);
9141 if (free_needed)
9142 zone_free(zone);
9144 INSIST(ver == NULL);
9148 * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
9149 * records from the zone apex.
9151 static void
9152 zone_refreshkeys(dns_zone_t *zone) {
9153 const char me[] = "zone_refreshkeys";
9154 isc_result_t result;
9155 dns_rriterator_t rrit;
9156 dns_db_t *db = NULL;
9157 dns_dbversion_t *ver = NULL;
9158 dns_diff_t diff;
9159 dns_rdata_t rdata = DNS_RDATA_INIT;
9160 dns_rdata_keydata_t kd;
9161 isc_stdtime_t now;
9162 isc_boolean_t commit = ISC_FALSE;
9163 isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
9165 ENTER;
9166 REQUIRE(zone->db != NULL);
9168 isc_stdtime_get(&now);
9170 LOCK_ZONE(zone);
9171 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9172 isc_time_settoepoch(&zone->refreshkeytime);
9173 UNLOCK_ZONE(zone);
9174 return;
9177 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9178 dns_db_attach(zone->db, &db);
9179 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9181 dns_diff_init(zone->mctx, &diff);
9183 CHECK(dns_db_newversion(db, &ver));
9185 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
9187 dns_rriterator_init(&rrit, db, ver, 0);
9188 for (result = dns_rriterator_first(&rrit);
9189 result == ISC_R_SUCCESS;
9190 result = dns_rriterator_nextrrset(&rrit)) {
9191 isc_stdtime_t timer = 0xffffffff;
9192 dns_name_t *name = NULL, *kname = NULL;
9193 dns_rdataset_t *kdset = NULL;
9194 dns_keyfetch_t *kfetch;
9195 isc_uint32_t ttl;
9197 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
9198 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
9199 !dns_rdataset_isassociated(kdset))
9200 continue;
9203 * Scan the stored keys looking for ones that need
9204 * removal or refreshing
9206 for (result = dns_rdataset_first(kdset);
9207 result == ISC_R_SUCCESS;
9208 result = dns_rdataset_next(kdset)) {
9209 dns_rdata_reset(&rdata);
9210 dns_rdataset_current(kdset, &rdata);
9211 result = dns_rdata_tostruct(&rdata, &kd, NULL);
9212 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9214 /* Removal timer expired? */
9215 if (kd.removehd != 0 && kd.removehd < now) {
9216 CHECK(update_one_rr(db, ver, &diff,
9217 DNS_DIFFOP_DEL, name, ttl,
9218 &rdata));
9219 continue;
9222 /* Acceptance timer expired? */
9223 if (kd.addhd != 0 && kd.addhd < now)
9224 timer = kd.addhd;
9226 /* Or do we just need to refresh the keyset? */
9227 if (timer > kd.refresh)
9228 timer = kd.refresh;
9231 if (timer > now)
9232 continue;
9234 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
9235 if (kfetch == NULL) {
9236 fetch_err = ISC_TRUE;
9237 goto failure;
9240 zone->refreshkeycount++;
9241 kfetch->zone = zone;
9242 zone->irefs++;
9243 INSIST(zone->irefs != 0);
9244 dns_fixedname_init(&kfetch->name);
9245 kname = dns_fixedname_name(&kfetch->name);
9246 dns_name_dup(name, zone->mctx, kname);
9247 dns_rdataset_init(&kfetch->dnskeyset);
9248 dns_rdataset_init(&kfetch->dnskeysigset);
9249 dns_rdataset_init(&kfetch->keydataset);
9250 dns_rdataset_clone(kdset, &kfetch->keydataset);
9251 kfetch->db = NULL;
9252 dns_db_attach(db, &kfetch->db);
9253 kfetch->fetch = NULL;
9255 result = dns_resolver_createfetch(zone->view->resolver,
9256 kname, dns_rdatatype_dnskey,
9257 NULL, NULL, NULL,
9258 DNS_FETCHOPT_NOVALIDATE,
9259 zone->task,
9260 keyfetch_done, kfetch,
9261 &kfetch->dnskeyset,
9262 &kfetch->dnskeysigset,
9263 &kfetch->fetch);
9264 if (result == ISC_R_SUCCESS)
9265 fetching = ISC_TRUE;
9266 else {
9267 zone->refreshkeycount--;
9268 zone->irefs--;
9269 dns_db_detach(&kfetch->db);
9270 dns_rdataset_disassociate(&kfetch->keydataset);
9271 dns_name_free(kname, zone->mctx);
9272 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
9273 dns_zone_log(zone, ISC_LOG_WARNING,
9274 "Failed to create fetch for "
9275 "DNSKEY update");
9276 fetch_err = ISC_TRUE;
9279 if (!ISC_LIST_EMPTY(diff.tuples)) {
9280 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
9281 zone->updatemethod));
9282 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
9283 commit = ISC_TRUE;
9284 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9285 zone_needdump(zone, 30);
9288 failure:
9289 if (fetch_err) {
9291 * Error during a key fetch; retry in an hour.
9293 isc_time_t timenow, timethen;
9294 char timebuf[80];
9296 TIME_NOW(&timenow);
9297 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
9298 zone->refreshkeytime = timethen;
9299 zone_settimer(zone, &timenow);
9301 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
9302 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
9303 timebuf);
9305 if (!fetching)
9306 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
9309 UNLOCK_ZONE(zone);
9311 dns_diff_clear(&diff);
9312 if (ver != NULL) {
9313 dns_rriterator_destroy(&rrit);
9314 dns_db_closeversion(db, &ver, commit);
9316 dns_db_detach(&db);
9318 INSIST(ver == NULL);
9321 static void
9322 zone_maintenance(dns_zone_t *zone) {
9323 const char me[] = "zone_maintenance";
9324 isc_time_t now;
9325 isc_result_t result;
9326 isc_boolean_t dumping;
9328 REQUIRE(DNS_ZONE_VALID(zone));
9329 ENTER;
9332 * Are we pending load/reload?
9334 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
9335 return;
9338 * Configuring the view of this zone may have
9339 * failed, for example because the config file
9340 * had a syntax error. In that case, the view
9341 * adb or resolver will be NULL, and we had better not try
9342 * to do further maintenance on it.
9344 if (zone->view == NULL || zone->view->adb == NULL)
9345 return;
9347 TIME_NOW(&now);
9350 * Expire check.
9352 switch (zone->type) {
9353 case dns_zone_redirect:
9354 if (zone->masters == NULL)
9355 break;
9356 case dns_zone_slave:
9357 case dns_zone_stub:
9358 LOCK_ZONE(zone);
9359 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
9360 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9361 zone_expire(zone);
9362 zone->refreshtime = now;
9364 UNLOCK_ZONE(zone);
9365 break;
9366 default:
9367 break;
9371 * Up to date check.
9373 switch (zone->type) {
9374 case dns_zone_redirect:
9375 if (zone->masters == NULL)
9376 break;
9377 case dns_zone_slave:
9378 case dns_zone_stub:
9379 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
9380 isc_time_compare(&now, &zone->refreshtime) >= 0)
9381 dns_zone_refresh(zone);
9382 break;
9383 default:
9384 break;
9388 * Slaves send notifies before backing up to disk, masters after.
9390 if (zone->type == dns_zone_slave &&
9391 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
9392 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
9393 isc_time_compare(&now, &zone->notifytime) >= 0)
9394 zone_notify(zone, &now);
9397 * Do we need to consolidate the backing store?
9399 switch (zone->type) {
9400 case dns_zone_master:
9401 case dns_zone_slave:
9402 case dns_zone_key:
9403 case dns_zone_redirect:
9404 case dns_zone_stub:
9405 LOCK_ZONE(zone);
9406 if (zone->masterfile != NULL &&
9407 isc_time_compare(&now, &zone->dumptime) >= 0 &&
9408 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
9409 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
9410 dumping = was_dumping(zone);
9411 } else
9412 dumping = ISC_TRUE;
9413 UNLOCK_ZONE(zone);
9414 if (!dumping) {
9415 result = zone_dump(zone, ISC_TRUE); /* task locked */
9416 if (result != ISC_R_SUCCESS)
9417 dns_zone_log(zone, ISC_LOG_WARNING,
9418 "dump failed: %s",
9419 dns_result_totext(result));
9421 break;
9422 default:
9423 break;
9427 * Master/redirect zones send notifies now, if needed
9429 switch (zone->type) {
9430 case dns_zone_master:
9431 case dns_zone_redirect:
9432 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
9433 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
9434 isc_time_compare(&now, &zone->notifytime) >= 0)
9435 zone_notify(zone, &now);
9436 default:
9437 break;
9441 * Do we need to refresh keys?
9443 switch (zone->type) {
9444 case dns_zone_key:
9445 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
9446 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
9447 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
9448 zone_refreshkeys(zone);
9451 break;
9452 case dns_zone_master:
9453 if (!isc_time_isepoch(&zone->refreshkeytime) &&
9454 isc_time_compare(&now, &zone->refreshkeytime) >= 0)
9455 zone_rekey(zone);
9456 default:
9457 break;
9460 switch (zone->type) {
9461 case dns_zone_master:
9462 case dns_zone_redirect:
9463 case dns_zone_slave:
9465 * Do we need to sign/resign some RRsets?
9467 if (!isc_time_isepoch(&zone->signingtime) &&
9468 isc_time_compare(&now, &zone->signingtime) >= 0)
9469 zone_sign(zone);
9470 else if (!isc_time_isepoch(&zone->resigntime) &&
9471 isc_time_compare(&now, &zone->resigntime) >= 0)
9472 zone_resigninc(zone);
9473 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
9474 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
9475 zone_nsec3chain(zone);
9477 * Do we need to issue a key expiry warning?
9479 if (!isc_time_isepoch(&zone->keywarntime) &&
9480 isc_time_compare(&now, &zone->keywarntime) >= 0)
9481 set_key_expiry_warning(zone, zone->key_expiry,
9482 isc_time_seconds(&now));
9483 break;
9485 default:
9486 break;
9488 zone_settimer(zone, &now);
9491 void
9492 dns_zone_markdirty(dns_zone_t *zone) {
9493 isc_uint32_t serial;
9494 isc_result_t result = ISC_R_SUCCESS;
9495 dns_zone_t *secure = NULL;
9498 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
9499 * could result in a deadlock due to a LOR so we will spin if we
9500 * can't obtain the both locks.
9502 again:
9503 LOCK_ZONE(zone);
9504 if (zone->type == dns_zone_master) {
9505 if (inline_raw(zone)) {
9506 unsigned int soacount;
9507 secure = zone->secure;
9508 INSIST(secure != zone);
9509 TRYLOCK_ZONE(result, secure);
9510 if (result != ISC_R_SUCCESS) {
9511 UNLOCK_ZONE(zone);
9512 secure = NULL;
9513 #ifdef ISC_PLATFORM_USETHREADS
9514 isc_thread_yield();
9515 #endif
9516 goto again;
9519 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9520 if (zone->db != NULL) {
9521 result = zone_get_from_db(zone, zone->db, NULL,
9522 &soacount, &serial,
9523 NULL, NULL, NULL,
9524 NULL, NULL);
9525 } else
9526 result = DNS_R_NOTLOADED;
9527 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9528 if (result == ISC_R_SUCCESS && soacount > 0U)
9529 zone_send_secureserial(zone, serial);
9532 /* XXXMPA make separate call back */
9533 if (result == ISC_R_SUCCESS)
9534 set_resigntime(zone);
9536 if (secure != NULL)
9537 UNLOCK_ZONE(secure);
9538 zone_needdump(zone, DNS_DUMP_DELAY);
9539 UNLOCK_ZONE(zone);
9542 void
9543 dns_zone_expire(dns_zone_t *zone) {
9544 REQUIRE(DNS_ZONE_VALID(zone));
9546 LOCK_ZONE(zone);
9547 zone_expire(zone);
9548 UNLOCK_ZONE(zone);
9551 static void
9552 zone_expire(dns_zone_t *zone) {
9554 * 'zone' locked by caller.
9557 REQUIRE(LOCKED_ZONE(zone));
9559 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
9561 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
9562 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
9563 zone->retry = DNS_ZONE_DEFAULTRETRY;
9564 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
9565 zone_unload(zone);
9568 void
9569 dns_zone_refresh(dns_zone_t *zone) {
9570 isc_interval_t i;
9571 isc_uint32_t oldflags;
9572 unsigned int j;
9573 isc_result_t result;
9575 REQUIRE(DNS_ZONE_VALID(zone));
9577 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
9578 return;
9581 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
9582 * in progress at a time.
9585 LOCK_ZONE(zone);
9586 oldflags = zone->flags;
9587 if (zone->masterscnt == 0) {
9588 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
9589 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
9590 dns_zone_log(zone, ISC_LOG_ERROR,
9591 "cannot refresh: no masters");
9592 goto unlock;
9594 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
9595 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
9596 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
9597 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
9598 goto unlock;
9601 * Set the next refresh time as if refresh check has failed.
9602 * Setting this to the retry time will do that. XXXMLG
9603 * If we are successful it will be reset using zone->refresh.
9605 isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
9607 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
9608 if (result != ISC_R_SUCCESS)
9609 dns_zone_log(zone, ISC_LOG_WARNING,
9610 "isc_time_nowplusinterval() failed: %s",
9611 dns_result_totext(result));
9614 * When lacking user-specified timer values from the SOA,
9615 * do exponential backoff of the retry time up to a
9616 * maximum of six hours.
9618 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
9619 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
9621 zone->curmaster = 0;
9622 for (j = 0; j < zone->masterscnt; j++)
9623 zone->mastersok[j] = ISC_FALSE;
9624 /* initiate soa query */
9625 queue_soa_query(zone);
9626 unlock:
9627 UNLOCK_ZONE(zone);
9630 isc_result_t
9631 dns_zone_flush(dns_zone_t *zone) {
9632 isc_result_t result = ISC_R_SUCCESS;
9633 isc_boolean_t dumping;
9635 REQUIRE(DNS_ZONE_VALID(zone));
9637 LOCK_ZONE(zone);
9638 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
9639 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9640 zone->masterfile != NULL) {
9641 result = ISC_R_ALREADYRUNNING;
9642 dumping = was_dumping(zone);
9643 } else
9644 dumping = ISC_TRUE;
9645 UNLOCK_ZONE(zone);
9646 if (!dumping)
9647 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
9648 return (result);
9651 isc_result_t
9652 dns_zone_dump(dns_zone_t *zone) {
9653 isc_result_t result = ISC_R_ALREADYRUNNING;
9654 isc_boolean_t dumping;
9656 REQUIRE(DNS_ZONE_VALID(zone));
9658 LOCK_ZONE(zone);
9659 dumping = was_dumping(zone);
9660 UNLOCK_ZONE(zone);
9661 if (!dumping)
9662 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
9663 return (result);
9666 static void
9667 zone_needdump(dns_zone_t *zone, unsigned int delay) {
9668 const char me[] = "zone_needdump";
9669 isc_time_t dumptime;
9670 isc_time_t now;
9673 * 'zone' locked by caller
9676 REQUIRE(DNS_ZONE_VALID(zone));
9677 REQUIRE(LOCKED_ZONE(zone));
9678 ENTER;
9681 * Do we have a place to dump to and are we loaded?
9683 if (zone->masterfile == NULL ||
9684 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
9685 return;
9687 TIME_NOW(&now);
9688 /* add some noise */
9689 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
9691 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9692 if (isc_time_isepoch(&zone->dumptime) ||
9693 isc_time_compare(&zone->dumptime, &dumptime) > 0)
9694 zone->dumptime = dumptime;
9695 if (zone->task != NULL)
9696 zone_settimer(zone, &now);
9699 static void
9700 dump_done(void *arg, isc_result_t result) {
9701 const char me[] = "dump_done";
9702 dns_zone_t *zone = arg;
9703 dns_db_t *db;
9704 dns_dbversion_t *version;
9705 isc_boolean_t again = ISC_FALSE;
9706 isc_boolean_t compact = ISC_FALSE;
9707 isc_uint32_t serial;
9708 isc_result_t tresult;
9710 REQUIRE(DNS_ZONE_VALID(zone));
9712 ENTER;
9714 if (result == ISC_R_SUCCESS && zone->journal != NULL &&
9715 zone->journalsize != -1) {
9718 * We don't own these, zone->dctx must stay valid.
9720 db = dns_dumpctx_db(zone->dctx);
9721 version = dns_dumpctx_version(zone->dctx);
9723 tresult = dns_db_getsoaserial(db, version, &serial);
9725 * If there is a secure version of this zone
9726 * use its serial if it is less than ours.
9728 if (tresult == ISC_R_SUCCESS && inline_raw(zone) &&
9729 zone->secure->db != NULL)
9731 isc_uint32_t sserial;
9732 isc_result_t mresult;
9734 mresult = dns_db_getsoaserial(zone->secure->db,
9735 NULL, &sserial);
9736 if (mresult == ISC_R_SUCCESS &&
9737 isc_serial_lt(sserial, serial))
9738 serial = sserial;
9741 * Note: we are task locked here so we can test
9742 * zone->xfr safely.
9744 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
9745 tresult = dns_journal_compact(zone->mctx,
9746 zone->journal,
9747 serial,
9748 zone->journalsize);
9749 switch (tresult) {
9750 case ISC_R_SUCCESS:
9751 case ISC_R_NOSPACE:
9752 case ISC_R_NOTFOUND:
9753 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9754 "dns_journal_compact: %s",
9755 dns_result_totext(tresult));
9756 break;
9757 default:
9758 dns_zone_log(zone, ISC_LOG_ERROR,
9759 "dns_journal_compact failed: %s",
9760 dns_result_totext(tresult));
9761 break;
9763 } else if (tresult == ISC_R_SUCCESS) {
9764 compact = ISC_TRUE;
9765 zone->compact_serial = serial;
9769 LOCK_ZONE(zone);
9770 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9771 if (compact)
9772 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
9773 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
9775 * Try again in a short while.
9777 zone_needdump(zone, DNS_DUMP_DELAY);
9778 } else if (result == ISC_R_SUCCESS &&
9779 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9780 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9781 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9782 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9783 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9784 isc_time_settoepoch(&zone->dumptime);
9785 again = ISC_TRUE;
9786 } else if (result == ISC_R_SUCCESS)
9787 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9789 if (zone->dctx != NULL)
9790 dns_dumpctx_detach(&zone->dctx);
9791 zonemgr_putio(&zone->writeio);
9792 UNLOCK_ZONE(zone);
9793 if (again)
9794 (void)zone_dump(zone, ISC_FALSE);
9795 dns_zone_idetach(&zone);
9798 static isc_result_t
9799 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
9800 const char me[] = "zone_dump";
9801 isc_result_t result;
9802 dns_dbversion_t *version = NULL;
9803 isc_boolean_t again;
9804 dns_db_t *db = NULL;
9805 char *masterfile = NULL;
9806 dns_masterformat_t masterformat = dns_masterformat_none;
9809 * 'compact' MUST only be set if we are task locked.
9812 REQUIRE(DNS_ZONE_VALID(zone));
9813 ENTER;
9815 redo:
9816 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9817 if (zone->db != NULL)
9818 dns_db_attach(zone->db, &db);
9819 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9820 LOCK_ZONE(zone);
9821 if (zone->masterfile != NULL) {
9822 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
9823 masterformat = zone->masterformat;
9825 UNLOCK_ZONE(zone);
9826 if (db == NULL) {
9827 result = DNS_R_NOTLOADED;
9828 goto fail;
9830 if (masterfile == NULL) {
9831 result = DNS_R_NOMASTERFILE;
9832 goto fail;
9835 if (compact && zone->type != dns_zone_stub) {
9836 dns_zone_t *dummy = NULL;
9837 LOCK_ZONE(zone);
9838 zone_iattach(zone, &dummy);
9839 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
9840 zone_gotwritehandle, zone,
9841 &zone->writeio);
9842 if (result != ISC_R_SUCCESS)
9843 zone_idetach(&dummy);
9844 else
9845 result = DNS_R_CONTINUE;
9846 UNLOCK_ZONE(zone);
9847 } else {
9848 const dns_master_style_t *output_style;
9850 dns_masterrawheader_t rawdata;
9851 dns_db_currentversion(db, &version);
9852 dns_master_initrawheader(&rawdata);
9853 if (inline_secure(zone))
9854 get_raw_serial(zone->raw, &rawdata);
9855 if (zone->type == dns_zone_key)
9856 output_style = &dns_master_style_keyzone;
9857 else
9858 output_style = &dns_master_style_default;
9859 result = dns_master_dump3(zone->mctx, db, version,
9860 output_style, masterfile,
9861 masterformat, &rawdata);
9862 dns_db_closeversion(db, &version, ISC_FALSE);
9864 fail:
9865 if (db != NULL)
9866 dns_db_detach(&db);
9867 if (masterfile != NULL)
9868 isc_mem_free(zone->mctx, masterfile);
9869 masterfile = NULL;
9871 if (result == DNS_R_CONTINUE)
9872 return (ISC_R_SUCCESS); /* XXXMPA */
9874 again = ISC_FALSE;
9875 LOCK_ZONE(zone);
9876 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
9877 if (result != ISC_R_SUCCESS) {
9879 * Try again in a short while.
9881 zone_needdump(zone, DNS_DUMP_DELAY);
9882 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
9883 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
9884 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
9885 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
9886 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
9887 isc_time_settoepoch(&zone->dumptime);
9888 again = ISC_TRUE;
9889 } else
9890 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
9891 UNLOCK_ZONE(zone);
9892 if (again)
9893 goto redo;
9895 return (result);
9898 static isc_result_t
9899 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
9900 dns_masterformat_t format, const isc_uint32_t rawversion)
9902 isc_result_t result;
9903 dns_dbversion_t *version = NULL;
9904 dns_db_t *db = NULL;
9905 dns_masterrawheader_t rawdata;
9907 REQUIRE(DNS_ZONE_VALID(zone));
9909 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9910 if (zone->db != NULL)
9911 dns_db_attach(zone->db, &db);
9912 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9913 if (db == NULL)
9914 return (DNS_R_NOTLOADED);
9916 dns_db_currentversion(db, &version);
9917 dns_master_initrawheader(&rawdata);
9918 if (rawversion == 0)
9919 rawdata.flags |= DNS_MASTERRAW_COMPAT;
9920 else if (inline_secure(zone))
9921 get_raw_serial(zone->raw, &rawdata);
9922 else if (zone->sourceserialset) {
9923 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
9924 rawdata.sourceserial = zone->sourceserial;
9926 result = dns_master_dumptostream3(zone->mctx, db, version, style,
9927 format, &rawdata, fd);
9928 dns_db_closeversion(db, &version, ISC_FALSE);
9929 dns_db_detach(&db);
9930 return (result);
9933 isc_result_t
9934 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9935 const dns_master_style_t *style,
9936 const isc_uint32_t rawversion)
9938 return (dumptostream(zone, fd, style, format, rawversion));
9941 isc_result_t
9942 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
9943 const dns_master_style_t *style) {
9944 return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
9947 isc_result_t
9948 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
9949 return (dumptostream(zone, fd, &dns_master_style_default,
9950 dns_masterformat_text, 0));
9953 isc_result_t
9954 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
9955 return (dumptostream(zone, fd, &dns_master_style_full,
9956 dns_masterformat_text, 0));
9959 void
9960 dns_zone_unload(dns_zone_t *zone) {
9961 REQUIRE(DNS_ZONE_VALID(zone));
9963 LOCK_ZONE(zone);
9964 zone_unload(zone);
9965 UNLOCK_ZONE(zone);
9968 static void
9969 notify_cancel(dns_zone_t *zone) {
9970 dns_notify_t *notify;
9973 * 'zone' locked by caller.
9976 REQUIRE(LOCKED_ZONE(zone));
9978 for (notify = ISC_LIST_HEAD(zone->notifies);
9979 notify != NULL;
9980 notify = ISC_LIST_NEXT(notify, link)) {
9981 if (notify->find != NULL)
9982 dns_adb_cancelfind(notify->find);
9983 if (notify->request != NULL)
9984 dns_request_cancel(notify->request);
9988 static void
9989 forward_cancel(dns_zone_t *zone) {
9990 dns_forward_t *forward;
9993 * 'zone' locked by caller.
9996 REQUIRE(LOCKED_ZONE(zone));
9998 for (forward = ISC_LIST_HEAD(zone->forwards);
9999 forward != NULL;
10000 forward = ISC_LIST_NEXT(forward, link)) {
10001 if (forward->request != NULL)
10002 dns_request_cancel(forward->request);
10006 static void
10007 zone_unload(dns_zone_t *zone) {
10009 * 'zone' locked by caller.
10012 REQUIRE(LOCKED_ZONE(zone));
10014 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10015 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10016 if (zone->writeio != NULL)
10017 zonemgr_cancelio(zone->writeio);
10019 if (zone->dctx != NULL)
10020 dns_dumpctx_cancel(zone->dctx);
10022 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10023 zone_detachdb(zone);
10024 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10025 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
10026 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10029 void
10030 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
10031 REQUIRE(DNS_ZONE_VALID(zone));
10032 REQUIRE(val > 0);
10034 zone->minrefresh = val;
10037 void
10038 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
10039 REQUIRE(DNS_ZONE_VALID(zone));
10040 REQUIRE(val > 0);
10042 zone->maxrefresh = val;
10045 void
10046 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
10047 REQUIRE(DNS_ZONE_VALID(zone));
10048 REQUIRE(val > 0);
10050 zone->minretry = val;
10053 void
10054 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
10055 REQUIRE(DNS_ZONE_VALID(zone));
10056 REQUIRE(val > 0);
10058 zone->maxretry = val;
10061 static isc_boolean_t
10062 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
10063 isc_sockaddr_t *addr, dns_tsigkey_t *key)
10065 dns_notify_t *notify;
10066 dns_zonemgr_t *zmgr;
10067 isc_result_t result;
10069 for (notify = ISC_LIST_HEAD(zone->notifies);
10070 notify != NULL;
10071 notify = ISC_LIST_NEXT(notify, link)) {
10072 if (notify->request != NULL)
10073 continue;
10074 if ((flags & DNS_NOTIFY_STARTUP) == 0)
10075 notify->flags &= ~DNS_NOTIFY_STARTUP;
10076 if (name != NULL && dns_name_dynamic(&notify->ns) &&
10077 dns_name_equal(name, &notify->ns))
10078 goto requeue;
10079 if (addr != NULL && isc_sockaddr_equal(addr, &notify->dst) &&
10080 notify->key == key)
10081 goto requeue;
10083 return (ISC_FALSE);
10085 requeue:
10087 * If we are enqueued on the startup ratelimiter and this is
10088 * not a startup notify, re-enqueue on the normal notify
10089 * ratelimiter.
10091 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0) {
10092 zmgr = notify->zone->zmgr;
10093 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
10094 notify->event);
10095 if (result != ISC_R_SUCCESS)
10096 return (ISC_TRUE);
10097 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
10098 notify->zone->task,
10099 &notify->event);
10100 if (result != ISC_R_SUCCESS) {
10101 isc_event_free(&notify->event);
10102 return (ISC_FALSE);
10106 return (ISC_TRUE);
10109 static isc_boolean_t
10110 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
10111 dns_tsigkey_t *key = NULL;
10112 isc_sockaddr_t src;
10113 isc_sockaddr_t any;
10114 isc_boolean_t isself;
10115 isc_netaddr_t dstaddr;
10116 isc_result_t result;
10118 if (zone->view == NULL || zone->isself == NULL)
10119 return (ISC_FALSE);
10121 switch (isc_sockaddr_pf(dst)) {
10122 case PF_INET:
10123 src = zone->notifysrc4;
10124 isc_sockaddr_any(&any);
10125 break;
10126 case PF_INET6:
10127 src = zone->notifysrc6;
10128 isc_sockaddr_any6(&any);
10129 break;
10130 default:
10131 return (ISC_FALSE);
10135 * When sending from any the kernel will assign a source address
10136 * that matches the destination address.
10138 if (isc_sockaddr_eqaddr(&any, &src))
10139 src = *dst;
10141 isc_netaddr_fromsockaddr(&dstaddr, dst);
10142 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
10143 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
10144 return (ISC_FALSE);
10145 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
10146 zone->isselfarg);
10147 if (key != NULL)
10148 dns_tsigkey_detach(&key);
10149 return (isself);
10152 static void
10153 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
10154 isc_mem_t *mctx;
10157 * Caller holds zone lock.
10159 REQUIRE(DNS_NOTIFY_VALID(notify));
10161 if (notify->zone != NULL) {
10162 if (!locked)
10163 LOCK_ZONE(notify->zone);
10164 REQUIRE(LOCKED_ZONE(notify->zone));
10165 if (ISC_LINK_LINKED(notify, link))
10166 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
10167 if (!locked)
10168 UNLOCK_ZONE(notify->zone);
10169 if (locked)
10170 zone_idetach(&notify->zone);
10171 else
10172 dns_zone_idetach(&notify->zone);
10174 if (notify->find != NULL)
10175 dns_adb_destroyfind(&notify->find);
10176 if (notify->request != NULL)
10177 dns_request_destroy(&notify->request);
10178 if (dns_name_dynamic(&notify->ns))
10179 dns_name_free(&notify->ns, notify->mctx);
10180 if (notify->key != NULL)
10181 dns_tsigkey_detach(&notify->key);
10182 mctx = notify->mctx;
10183 isc_mem_put(notify->mctx, notify, sizeof(*notify));
10184 isc_mem_detach(&mctx);
10187 static isc_result_t
10188 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
10189 dns_notify_t *notify;
10191 REQUIRE(notifyp != NULL && *notifyp == NULL);
10193 notify = isc_mem_get(mctx, sizeof(*notify));
10194 if (notify == NULL)
10195 return (ISC_R_NOMEMORY);
10197 notify->mctx = NULL;
10198 isc_mem_attach(mctx, &notify->mctx);
10199 notify->flags = flags;
10200 notify->zone = NULL;
10201 notify->find = NULL;
10202 notify->request = NULL;
10203 notify->key = NULL;
10204 notify->event = NULL;
10205 isc_sockaddr_any(&notify->dst);
10206 dns_name_init(&notify->ns, NULL);
10207 ISC_LINK_INIT(notify, link);
10208 notify->magic = NOTIFY_MAGIC;
10209 *notifyp = notify;
10210 return (ISC_R_SUCCESS);
10214 * XXXAG should check for DNS_ZONEFLG_EXITING
10216 static void
10217 process_adb_event(isc_task_t *task, isc_event_t *ev) {
10218 dns_notify_t *notify;
10219 isc_eventtype_t result;
10221 UNUSED(task);
10223 notify = ev->ev_arg;
10224 REQUIRE(DNS_NOTIFY_VALID(notify));
10225 INSIST(task == notify->zone->task);
10226 result = ev->ev_type;
10227 isc_event_free(&ev);
10228 if (result == DNS_EVENT_ADBMOREADDRESSES) {
10229 dns_adb_destroyfind(&notify->find);
10230 notify_find_address(notify);
10231 return;
10233 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
10234 LOCK_ZONE(notify->zone);
10235 notify_send(notify);
10236 UNLOCK_ZONE(notify->zone);
10238 notify_destroy(notify, ISC_FALSE);
10241 static void
10242 notify_find_address(dns_notify_t *notify) {
10243 isc_result_t result;
10244 unsigned int options;
10246 REQUIRE(DNS_NOTIFY_VALID(notify));
10247 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
10248 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
10250 if (notify->zone->view->adb == NULL)
10251 goto destroy;
10253 result = dns_adb_createfind(notify->zone->view->adb,
10254 notify->zone->task,
10255 process_adb_event, notify,
10256 &notify->ns, dns_rootname, 0,
10257 options, 0, NULL,
10258 notify->zone->view->dstport,
10259 &notify->find);
10261 /* Something failed? */
10262 if (result != ISC_R_SUCCESS)
10263 goto destroy;
10265 /* More addresses pending? */
10266 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
10267 return;
10269 /* We have as many addresses as we can get. */
10270 LOCK_ZONE(notify->zone);
10271 notify_send(notify);
10272 UNLOCK_ZONE(notify->zone);
10274 destroy:
10275 notify_destroy(notify, ISC_FALSE);
10279 static isc_result_t
10280 notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) {
10281 isc_event_t *e;
10282 isc_result_t result;
10284 INSIST(notify->event == NULL);
10285 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
10286 notify_send_toaddr, notify, sizeof(isc_event_t));
10287 if (e == NULL)
10288 return (ISC_R_NOMEMORY);
10289 if (startup)
10290 notify->event = e;
10291 e->ev_arg = notify;
10292 e->ev_sender = NULL;
10293 result = isc_ratelimiter_enqueue(startup
10294 ? notify->zone->zmgr->startupnotifyrl
10295 : notify->zone->zmgr->notifyrl,
10296 notify->zone->task, &e);
10297 if (result != ISC_R_SUCCESS) {
10298 isc_event_free(&e);
10299 notify->event = NULL;
10301 return (result);
10304 static void
10305 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
10306 dns_notify_t *notify;
10307 isc_result_t result;
10308 dns_message_t *message = NULL;
10309 isc_netaddr_t dstip;
10310 dns_tsigkey_t *key = NULL;
10311 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
10312 isc_sockaddr_t src;
10313 int timeout;
10314 isc_boolean_t have_notifysource = ISC_FALSE;
10315 isc_boolean_t have_notifydscp = ISC_FALSE;
10316 isc_dscp_t dscp = -1;
10318 notify = event->ev_arg;
10319 REQUIRE(DNS_NOTIFY_VALID(notify));
10321 UNUSED(task);
10323 LOCK_ZONE(notify->zone);
10325 notify->event = NULL;
10327 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
10328 result = ISC_R_CANCELED;
10329 goto cleanup;
10332 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
10333 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
10334 notify->zone->view->requestmgr == NULL ||
10335 notify->zone->db == NULL) {
10336 result = ISC_R_CANCELED;
10337 goto cleanup;
10341 * The raw IPv4 address should also exist. Don't send to the
10342 * mapped form.
10344 if (isc_sockaddr_pf(&notify->dst) == PF_INET6 &&
10345 IN6_IS_ADDR_V4MAPPED(&notify->dst.type.sin6.sin6_addr)) {
10346 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
10347 notify_log(notify->zone, ISC_LOG_DEBUG(3),
10348 "notify: ignoring IPv6 mapped IPV4 address: %s",
10349 addrbuf);
10350 result = ISC_R_CANCELED;
10351 goto cleanup;
10354 result = notify_createmessage(notify->zone, notify->flags, &message);
10355 if (result != ISC_R_SUCCESS)
10356 goto cleanup;
10358 if (notify->key != NULL) {
10359 /* Transfer ownership of key */
10360 key = notify->key;
10361 notify->key = NULL;
10362 } else {
10363 isc_netaddr_fromsockaddr(&dstip, &notify->dst);
10364 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
10365 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
10366 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
10367 notify_log(notify->zone, ISC_LOG_ERROR,
10368 "NOTIFY to %s not sent. "
10369 "Peer TSIG key lookup failure.", addrbuf);
10370 goto cleanup_message;
10374 /* XXX: should we log the tsig key too? */
10375 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
10376 addrbuf);
10377 if (notify->zone->view->peers != NULL) {
10378 dns_peer_t *peer = NULL;
10379 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
10380 &dstip, &peer);
10381 if (result == ISC_R_SUCCESS) {
10382 result = dns_peer_getnotifysource(peer, &src);
10383 if (result == ISC_R_SUCCESS)
10384 have_notifysource = ISC_TRUE;
10385 dns_peer_getnotifydscp(peer, &dscp);
10386 if (dscp != -1)
10387 have_notifydscp = ISC_TRUE;
10390 switch (isc_sockaddr_pf(&notify->dst)) {
10391 case PF_INET:
10392 if (!have_notifysource)
10393 src = notify->zone->notifysrc4;
10394 if (!have_notifydscp)
10395 dscp = notify->zone->notifysrc4dscp;
10396 break;
10397 case PF_INET6:
10398 if (!have_notifysource)
10399 src = notify->zone->notifysrc6;
10400 if (!have_notifydscp)
10401 dscp = notify->zone->notifysrc6dscp;
10402 break;
10403 default:
10404 result = ISC_R_NOTIMPLEMENTED;
10405 goto cleanup_key;
10407 timeout = 15;
10408 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
10409 timeout = 30;
10410 result = dns_request_createvia4(notify->zone->view->requestmgr,
10411 message, &src, &notify->dst, dscp,
10412 0, key, timeout * 3, timeout, 0,
10413 notify->zone->task, notify_done,
10414 notify, &notify->request);
10415 if (result == ISC_R_SUCCESS) {
10416 if (isc_sockaddr_pf(&notify->dst) == AF_INET) {
10417 inc_stats(notify->zone,
10418 dns_zonestatscounter_notifyoutv4);
10419 } else {
10420 inc_stats(notify->zone,
10421 dns_zonestatscounter_notifyoutv6);
10425 cleanup_key:
10426 if (key != NULL)
10427 dns_tsigkey_detach(&key);
10428 cleanup_message:
10429 dns_message_destroy(&message);
10430 cleanup:
10431 UNLOCK_ZONE(notify->zone);
10432 isc_event_free(&event);
10433 if (result != ISC_R_SUCCESS)
10434 notify_destroy(notify, ISC_FALSE);
10437 static void
10438 notify_send(dns_notify_t *notify) {
10439 dns_adbaddrinfo_t *ai;
10440 isc_sockaddr_t dst;
10441 isc_result_t result;
10442 dns_notify_t *new = NULL;
10443 unsigned int flags;
10444 isc_boolean_t startup;
10447 * Zone lock held by caller.
10449 REQUIRE(DNS_NOTIFY_VALID(notify));
10450 REQUIRE(LOCKED_ZONE(notify->zone));
10452 for (ai = ISC_LIST_HEAD(notify->find->list);
10453 ai != NULL;
10454 ai = ISC_LIST_NEXT(ai, publink)) {
10455 dst = ai->sockaddr;
10456 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
10457 NULL))
10458 continue;
10459 if (notify_isself(notify->zone, &dst))
10460 continue;
10461 new = NULL;
10462 flags = notify->flags & DNS_NOTIFY_NOSOA;
10463 result = notify_create(notify->mctx, flags, &new);
10464 if (result != ISC_R_SUCCESS)
10465 goto cleanup;
10466 zone_iattach(notify->zone, &new->zone);
10467 ISC_LIST_APPEND(new->zone->notifies, new, link);
10468 new->dst = dst;
10469 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
10470 result = notify_send_queue(new, startup);
10471 if (result != ISC_R_SUCCESS)
10472 goto cleanup;
10473 new = NULL;
10476 cleanup:
10477 if (new != NULL)
10478 notify_destroy(new, ISC_TRUE);
10481 void
10482 dns_zone_notify(dns_zone_t *zone) {
10483 isc_time_t now;
10485 REQUIRE(DNS_ZONE_VALID(zone));
10487 LOCK_ZONE(zone);
10488 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10490 TIME_NOW(&now);
10491 zone_settimer(zone, &now);
10492 UNLOCK_ZONE(zone);
10495 static void
10496 zone_notify(dns_zone_t *zone, isc_time_t *now) {
10497 dns_dbnode_t *node = NULL;
10498 dns_db_t *zonedb = NULL;
10499 dns_dbversion_t *version = NULL;
10500 dns_name_t *origin = NULL;
10501 dns_name_t master;
10502 dns_rdata_ns_t ns;
10503 dns_rdata_soa_t soa;
10504 isc_uint32_t serial;
10505 dns_rdata_t rdata = DNS_RDATA_INIT;
10506 dns_rdataset_t nsrdset;
10507 dns_rdataset_t soardset;
10508 isc_result_t result;
10509 unsigned int i;
10510 isc_sockaddr_t dst;
10511 isc_boolean_t isqueued;
10512 dns_notifytype_t notifytype;
10513 unsigned int flags = 0;
10514 isc_boolean_t loggednotify = ISC_FALSE;
10515 isc_boolean_t startup;
10517 REQUIRE(DNS_ZONE_VALID(zone));
10519 LOCK_ZONE(zone);
10520 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10521 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
10522 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
10523 notifytype = zone->notifytype;
10524 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
10525 UNLOCK_ZONE(zone);
10527 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
10528 return;
10530 if (notifytype == dns_notifytype_no)
10531 return;
10533 if (notifytype == dns_notifytype_masteronly &&
10534 zone->type != dns_zone_master)
10535 return;
10537 origin = &zone->origin;
10540 * If the zone is dialup we are done as we don't want to send
10541 * the current soa so as to force a refresh query.
10543 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
10544 flags |= DNS_NOTIFY_NOSOA;
10547 * Record that this was a notify due to starting up.
10549 if (startup)
10550 flags |= DNS_NOTIFY_STARTUP;
10553 * Get SOA RRset.
10555 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10556 if (zone->db != NULL)
10557 dns_db_attach(zone->db, &zonedb);
10558 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10559 if (zonedb == NULL)
10560 return;
10561 dns_db_currentversion(zonedb, &version);
10562 result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
10563 if (result != ISC_R_SUCCESS)
10564 goto cleanup1;
10566 dns_rdataset_init(&soardset);
10567 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
10568 dns_rdatatype_none, 0, &soardset, NULL);
10569 if (result != ISC_R_SUCCESS)
10570 goto cleanup2;
10573 * Find serial and master server's name.
10575 dns_name_init(&master, NULL);
10576 result = dns_rdataset_first(&soardset);
10577 if (result != ISC_R_SUCCESS)
10578 goto cleanup3;
10579 dns_rdataset_current(&soardset, &rdata);
10580 result = dns_rdata_tostruct(&rdata, &soa, NULL);
10581 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10582 dns_rdata_reset(&rdata);
10583 result = dns_name_dup(&soa.origin, zone->mctx, &master);
10584 serial = soa.serial;
10585 dns_rdataset_disassociate(&soardset);
10586 if (result != ISC_R_SUCCESS)
10587 goto cleanup3;
10590 * Enqueue notify requests for 'also-notify' servers.
10592 LOCK_ZONE(zone);
10593 for (i = 0; i < zone->notifycnt; i++) {
10594 dns_tsigkey_t *key = NULL;
10595 dns_notify_t *notify = NULL;
10597 if ((zone->notifykeynames != NULL) &&
10598 (zone->notifykeynames[i] != NULL)) {
10599 dns_view_t *view = dns_zone_getview(zone);
10600 dns_name_t *keyname = zone->notifykeynames[i];
10601 (void)dns_view_gettsig(view, keyname, &key);
10604 dst = zone->notify[i];
10605 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
10606 if (key != NULL)
10607 dns_tsigkey_detach(&key);
10608 continue;
10611 result = notify_create(zone->mctx, flags, &notify);
10612 if (result != ISC_R_SUCCESS) {
10613 if (key != NULL)
10614 dns_tsigkey_detach(&key);
10615 continue;
10618 zone_iattach(zone, &notify->zone);
10619 notify->dst = dst;
10621 INSIST(notify->key == NULL);
10623 if (key != NULL) {
10624 notify->key = key;
10625 key = NULL;
10628 ISC_LIST_APPEND(zone->notifies, notify, link);
10629 result = notify_send_queue(notify, startup);
10630 if (result != ISC_R_SUCCESS)
10631 notify_destroy(notify, ISC_TRUE);
10632 if (!loggednotify) {
10633 notify_log(zone, ISC_LOG_INFO,
10634 "sending notifies (serial %u)",
10635 serial);
10636 loggednotify = ISC_TRUE;
10639 UNLOCK_ZONE(zone);
10641 if (notifytype == dns_notifytype_explicit)
10642 goto cleanup3;
10645 * Process NS RRset to generate notifies.
10648 dns_rdataset_init(&nsrdset);
10649 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
10650 dns_rdatatype_none, 0, &nsrdset, NULL);
10651 if (result != ISC_R_SUCCESS)
10652 goto cleanup3;
10654 result = dns_rdataset_first(&nsrdset);
10655 while (result == ISC_R_SUCCESS) {
10656 dns_notify_t *notify = NULL;
10658 dns_rdataset_current(&nsrdset, &rdata);
10659 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10660 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10661 dns_rdata_reset(&rdata);
10663 * Don't notify the master server unless explicitly
10664 * configured to do so.
10666 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
10667 dns_name_compare(&master, &ns.name) == 0) {
10668 result = dns_rdataset_next(&nsrdset);
10669 continue;
10672 if (!loggednotify) {
10673 notify_log(zone, ISC_LOG_INFO,
10674 "sending notifies (serial %u)",
10675 serial);
10676 loggednotify = ISC_TRUE;
10679 LOCK_ZONE(zone);
10680 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
10681 UNLOCK_ZONE(zone);
10682 if (isqueued) {
10683 result = dns_rdataset_next(&nsrdset);
10684 continue;
10686 result = notify_create(zone->mctx, flags, &notify);
10687 if (result != ISC_R_SUCCESS)
10688 continue;
10689 dns_zone_iattach(zone, &notify->zone);
10690 result = dns_name_dup(&ns.name, zone->mctx, &notify->ns);
10691 if (result != ISC_R_SUCCESS) {
10692 LOCK_ZONE(zone);
10693 notify_destroy(notify, ISC_TRUE);
10694 UNLOCK_ZONE(zone);
10695 continue;
10697 LOCK_ZONE(zone);
10698 ISC_LIST_APPEND(zone->notifies, notify, link);
10699 UNLOCK_ZONE(zone);
10700 notify_find_address(notify);
10701 result = dns_rdataset_next(&nsrdset);
10703 dns_rdataset_disassociate(&nsrdset);
10705 cleanup3:
10706 if (dns_name_dynamic(&master))
10707 dns_name_free(&master, zone->mctx);
10708 cleanup2:
10709 dns_db_detachnode(zonedb, &node);
10710 cleanup1:
10711 dns_db_closeversion(zonedb, &version, ISC_FALSE);
10712 dns_db_detach(&zonedb);
10715 /***
10716 *** Private
10717 ***/
10719 static inline isc_result_t
10720 save_nsrrset(dns_message_t *message, dns_name_t *name,
10721 dns_db_t *db, dns_dbversion_t *version)
10723 dns_rdataset_t *nsrdataset = NULL;
10724 dns_rdataset_t *rdataset = NULL;
10725 dns_dbnode_t *node = NULL;
10726 dns_rdata_ns_t ns;
10727 isc_result_t result;
10728 dns_rdata_t rdata = DNS_RDATA_INIT;
10731 * Extract NS RRset from message.
10733 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
10734 dns_rdatatype_ns, dns_rdatatype_none,
10735 NULL, &nsrdataset);
10736 if (result != ISC_R_SUCCESS)
10737 goto fail;
10740 * Add NS rdataset.
10742 result = dns_db_findnode(db, name, ISC_TRUE, &node);
10743 if (result != ISC_R_SUCCESS)
10744 goto fail;
10745 result = dns_db_addrdataset(db, node, version, 0,
10746 nsrdataset, 0, NULL);
10747 dns_db_detachnode(db, &node);
10748 if (result != ISC_R_SUCCESS)
10749 goto fail;
10751 * Add glue rdatasets.
10753 for (result = dns_rdataset_first(nsrdataset);
10754 result == ISC_R_SUCCESS;
10755 result = dns_rdataset_next(nsrdataset)) {
10756 dns_rdataset_current(nsrdataset, &rdata);
10757 result = dns_rdata_tostruct(&rdata, &ns, NULL);
10758 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10759 dns_rdata_reset(&rdata);
10760 if (!dns_name_issubdomain(&ns.name, name))
10761 continue;
10762 rdataset = NULL;
10763 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10764 &ns.name, dns_rdatatype_aaaa,
10765 dns_rdatatype_none, NULL,
10766 &rdataset);
10767 if (result == ISC_R_SUCCESS) {
10768 result = dns_db_findnode(db, &ns.name,
10769 ISC_TRUE, &node);
10770 if (result != ISC_R_SUCCESS)
10771 goto fail;
10772 result = dns_db_addrdataset(db, node, version, 0,
10773 rdataset, 0, NULL);
10774 dns_db_detachnode(db, &node);
10775 if (result != ISC_R_SUCCESS)
10776 goto fail;
10778 rdataset = NULL;
10779 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
10780 &ns.name, dns_rdatatype_a,
10781 dns_rdatatype_none, NULL,
10782 &rdataset);
10783 if (result == ISC_R_SUCCESS) {
10784 result = dns_db_findnode(db, &ns.name,
10785 ISC_TRUE, &node);
10786 if (result != ISC_R_SUCCESS)
10787 goto fail;
10788 result = dns_db_addrdataset(db, node, version, 0,
10789 rdataset, 0, NULL);
10790 dns_db_detachnode(db, &node);
10791 if (result != ISC_R_SUCCESS)
10792 goto fail;
10795 if (result != ISC_R_NOMORE)
10796 goto fail;
10798 return (ISC_R_SUCCESS);
10800 fail:
10801 return (result);
10804 static void
10805 stub_callback(isc_task_t *task, isc_event_t *event) {
10806 const char me[] = "stub_callback";
10807 dns_requestevent_t *revent = (dns_requestevent_t *)event;
10808 dns_stub_t *stub = NULL;
10809 dns_message_t *msg = NULL;
10810 dns_zone_t *zone = NULL;
10811 char master[ISC_SOCKADDR_FORMATSIZE];
10812 char source[ISC_SOCKADDR_FORMATSIZE];
10813 isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
10814 isc_result_t result;
10815 isc_time_t now;
10816 isc_boolean_t exiting = ISC_FALSE;
10817 isc_interval_t i;
10818 unsigned int j, soacount;
10820 stub = revent->ev_arg;
10821 INSIST(DNS_STUB_VALID(stub));
10823 UNUSED(task);
10825 zone = stub->zone;
10827 ENTER;
10829 TIME_NOW(&now);
10831 LOCK_ZONE(zone);
10833 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10834 zone_debuglog(zone, me, 1, "exiting");
10835 exiting = ISC_TRUE;
10836 goto next_master;
10839 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
10840 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
10842 if (revent->result != ISC_R_SUCCESS) {
10843 if (revent->result == ISC_R_TIMEDOUT &&
10844 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
10845 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10846 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10847 "refreshing stub: timeout retrying "
10848 " without EDNS master %s (source %s)",
10849 master, source);
10850 goto same_master;
10852 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
10853 &zone->sourceaddr, &now);
10854 dns_zone_log(zone, ISC_LOG_INFO,
10855 "could not refresh stub from master %s"
10856 " (source %s): %s", master, source,
10857 dns_result_totext(revent->result));
10858 goto next_master;
10861 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
10862 if (result != ISC_R_SUCCESS)
10863 goto next_master;
10865 result = dns_request_getresponse(revent->request, msg, 0);
10866 if (result != ISC_R_SUCCESS)
10867 goto next_master;
10870 * Unexpected rcode.
10872 if (msg->rcode != dns_rcode_noerror) {
10873 char rcode[128];
10874 isc_buffer_t rb;
10876 isc_buffer_init(&rb, rcode, sizeof(rcode));
10877 (void)dns_rcode_totext(msg->rcode, &rb);
10879 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
10880 (msg->rcode == dns_rcode_servfail ||
10881 msg->rcode == dns_rcode_notimp ||
10882 msg->rcode == dns_rcode_formerr)) {
10883 dns_zone_log(zone, ISC_LOG_DEBUG(1),
10884 "refreshing stub: rcode (%.*s) retrying "
10885 "without EDNS master %s (source %s)",
10886 (int)rb.used, rcode, master, source);
10887 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
10888 goto same_master;
10891 dns_zone_log(zone, ISC_LOG_INFO,
10892 "refreshing stub: "
10893 "unexpected rcode (%.*s) from %s (source %s)",
10894 (int)rb.used, rcode, master, source);
10895 goto next_master;
10899 * We need complete messages.
10901 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
10902 if (dns_request_usedtcp(revent->request)) {
10903 dns_zone_log(zone, ISC_LOG_INFO,
10904 "refreshing stub: truncated TCP "
10905 "response from master %s (source %s)",
10906 master, source);
10907 goto next_master;
10909 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
10910 goto same_master;
10914 * If non-auth log and next master.
10916 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
10917 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
10918 "non-authoritative answer from "
10919 "master %s (source %s)", master, source);
10920 goto next_master;
10924 * Sanity checks.
10926 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
10927 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
10929 if (cnamecnt != 0) {
10930 dns_zone_log(zone, ISC_LOG_INFO,
10931 "refreshing stub: unexpected CNAME response "
10932 "from master %s (source %s)", master, source);
10933 goto next_master;
10936 if (nscnt == 0) {
10937 dns_zone_log(zone, ISC_LOG_INFO,
10938 "refreshing stub: no NS records in response "
10939 "from master %s (source %s)", master, source);
10940 goto next_master;
10944 * Save answer.
10946 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
10947 if (result != ISC_R_SUCCESS) {
10948 dns_zone_log(zone, ISC_LOG_INFO,
10949 "refreshing stub: unable to save NS records "
10950 "from master %s (source %s)", master, source);
10951 goto next_master;
10955 * Tidy up.
10957 dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
10958 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10959 if (zone->db == NULL)
10960 zone_attachdb(zone, stub->db);
10961 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
10962 &refresh, &retry, &expire, NULL, NULL);
10963 if (result == ISC_R_SUCCESS && soacount > 0U) {
10964 zone->refresh = RANGE(refresh, zone->minrefresh,
10965 zone->maxrefresh);
10966 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
10967 zone->expire = RANGE(expire, zone->refresh + zone->retry,
10968 DNS_MAX_EXPIRE);
10969 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10971 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10972 dns_db_detach(&stub->db);
10974 dns_message_destroy(&msg);
10975 isc_event_free(&event);
10976 dns_request_destroy(&zone->request);
10978 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
10979 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10980 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
10981 isc_interval_set(&i, zone->expire, 0);
10982 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
10984 if (zone->masterfile != NULL)
10985 zone_needdump(zone, 0);
10987 zone_settimer(zone, &now);
10988 goto free_stub;
10990 next_master:
10991 if (stub->version != NULL)
10992 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
10993 if (stub->db != NULL)
10994 dns_db_detach(&stub->db);
10995 if (msg != NULL)
10996 dns_message_destroy(&msg);
10997 isc_event_free(&event);
10998 dns_request_destroy(&zone->request);
11000 * Skip to next failed / untried master.
11002 do {
11003 zone->curmaster++;
11004 } while (zone->curmaster < zone->masterscnt &&
11005 zone->mastersok[zone->curmaster]);
11006 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11007 if (exiting || zone->curmaster >= zone->masterscnt) {
11008 isc_boolean_t done = ISC_TRUE;
11009 if (!exiting &&
11010 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11011 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11013 * Did we get a good answer from all the masters?
11015 for (j = 0; j < zone->masterscnt; j++)
11016 if (zone->mastersok[j] == ISC_FALSE) {
11017 done = ISC_FALSE;
11018 break;
11020 } else
11021 done = ISC_TRUE;
11022 if (!done) {
11023 zone->curmaster = 0;
11025 * Find the next failed master.
11027 while (zone->curmaster < zone->masterscnt &&
11028 zone->mastersok[zone->curmaster])
11029 zone->curmaster++;
11030 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11031 } else {
11032 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11034 zone_settimer(zone, &now);
11035 goto free_stub;
11038 queue_soa_query(zone);
11039 goto free_stub;
11041 same_master:
11042 if (msg != NULL)
11043 dns_message_destroy(&msg);
11044 isc_event_free(&event);
11045 dns_request_destroy(&zone->request);
11046 ns_query(zone, NULL, stub);
11047 UNLOCK_ZONE(zone);
11048 goto done;
11050 free_stub:
11051 UNLOCK_ZONE(zone);
11052 stub->magic = 0;
11053 dns_zone_idetach(&stub->zone);
11054 INSIST(stub->db == NULL);
11055 INSIST(stub->version == NULL);
11056 isc_mem_put(stub->mctx, stub, sizeof(*stub));
11058 done:
11059 INSIST(event == NULL);
11060 return;
11064 * An SOA query has finished (successfully or not).
11066 static void
11067 refresh_callback(isc_task_t *task, isc_event_t *event) {
11068 const char me[] = "refresh_callback";
11069 dns_requestevent_t *revent = (dns_requestevent_t *)event;
11070 dns_zone_t *zone;
11071 dns_message_t *msg = NULL;
11072 isc_uint32_t soacnt, cnamecnt, soacount, nscount;
11073 isc_time_t now;
11074 char master[ISC_SOCKADDR_FORMATSIZE];
11075 char source[ISC_SOCKADDR_FORMATSIZE];
11076 dns_rdataset_t *rdataset = NULL;
11077 dns_rdata_t rdata = DNS_RDATA_INIT;
11078 dns_rdata_soa_t soa;
11079 isc_result_t result;
11080 isc_uint32_t serial, oldserial = 0;
11081 unsigned int j;
11082 isc_boolean_t do_queue_xfrin = ISC_FALSE;
11084 zone = revent->ev_arg;
11085 INSIST(DNS_ZONE_VALID(zone));
11087 UNUSED(task);
11089 ENTER;
11091 TIME_NOW(&now);
11093 LOCK_ZONE(zone);
11095 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11096 isc_event_free(&event);
11097 dns_request_destroy(&zone->request);
11098 goto detach;
11102 * if timeout log and next master;
11105 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
11106 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
11108 if (revent->result != ISC_R_SUCCESS) {
11109 if (revent->result == ISC_R_TIMEDOUT &&
11110 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11111 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11112 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11113 "refresh: timeout retrying without EDNS "
11114 "master %s (source %s)", master, source);
11115 goto same_master;
11117 if (revent->result == ISC_R_TIMEDOUT &&
11118 !dns_request_usedtcp(revent->request)) {
11119 dns_zone_log(zone, ISC_LOG_INFO,
11120 "refresh: retry limit for "
11121 "master %s exceeded (source %s)",
11122 master, source);
11123 /* Try with slave with TCP. */
11124 if ((zone->type == dns_zone_slave ||
11125 zone->type == dns_zone_redirect) &&
11126 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
11127 if (!dns_zonemgr_unreachable(zone->zmgr,
11128 &zone->masteraddr,
11129 &zone->sourceaddr,
11130 &now))
11132 DNS_ZONE_SETFLAG(zone,
11133 DNS_ZONEFLG_SOABEFOREAXFR);
11134 goto tcp_transfer;
11136 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11137 "refresh: skipped tcp fallback "
11138 "as master %s (source %s) is "
11139 "unreachable (cached)",
11140 master, source);
11142 } else
11143 dns_zone_log(zone, ISC_LOG_INFO,
11144 "refresh: failure trying master "
11145 "%s (source %s): %s", master, source,
11146 dns_result_totext(revent->result));
11147 goto next_master;
11150 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
11151 if (result != ISC_R_SUCCESS)
11152 goto next_master;
11153 result = dns_request_getresponse(revent->request, msg, 0);
11154 if (result != ISC_R_SUCCESS) {
11155 dns_zone_log(zone, ISC_LOG_INFO,
11156 "refresh: failure trying master "
11157 "%s (source %s): %s", master, source,
11158 dns_result_totext(result));
11159 goto next_master;
11163 * Unexpected rcode.
11165 if (msg->rcode != dns_rcode_noerror) {
11166 char rcode[128];
11167 isc_buffer_t rb;
11169 isc_buffer_init(&rb, rcode, sizeof(rcode));
11170 (void)dns_rcode_totext(msg->rcode, &rb);
11172 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
11173 (msg->rcode == dns_rcode_servfail ||
11174 msg->rcode == dns_rcode_notimp ||
11175 msg->rcode == dns_rcode_formerr)) {
11176 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11177 "refresh: rcode (%.*s) retrying without "
11178 "EDNS master %s (source %s)",
11179 (int)rb.used, rcode, master, source);
11180 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11181 goto same_master;
11183 dns_zone_log(zone, ISC_LOG_INFO,
11184 "refresh: unexpected rcode (%.*s) from "
11185 "master %s (source %s)", (int)rb.used, rcode,
11186 master, source);
11188 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
11190 if (msg->rcode == dns_rcode_refused &&
11191 (zone->type == dns_zone_slave ||
11192 zone->type == dns_zone_redirect))
11193 goto tcp_transfer;
11194 goto next_master;
11198 * If truncated punt to zone transfer which will query again.
11200 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
11201 if (zone->type == dns_zone_slave ||
11202 zone->type == dns_zone_redirect) {
11203 dns_zone_log(zone, ISC_LOG_INFO,
11204 "refresh: truncated UDP answer, "
11205 "initiating TCP zone xfer "
11206 "for master %s (source %s)",
11207 master, source);
11208 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
11209 goto tcp_transfer;
11210 } else {
11211 INSIST(zone->type == dns_zone_stub);
11212 if (dns_request_usedtcp(revent->request)) {
11213 dns_zone_log(zone, ISC_LOG_INFO,
11214 "refresh: truncated TCP response "
11215 "from master %s (source %s)",
11216 master, source);
11217 goto next_master;
11219 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
11220 goto same_master;
11225 * if non-auth log and next master;
11227 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
11228 dns_zone_log(zone, ISC_LOG_INFO,
11229 "refresh: non-authoritative answer from "
11230 "master %s (source %s)", master, source);
11231 goto next_master;
11234 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
11235 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
11236 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
11237 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
11238 dns_rdatatype_soa);
11241 * There should not be a CNAME record at top of zone.
11243 if (cnamecnt != 0) {
11244 dns_zone_log(zone, ISC_LOG_INFO,
11245 "refresh: CNAME at top of zone "
11246 "in master %s (source %s)", master, source);
11247 goto next_master;
11251 * if referral log and next master;
11253 if (soacnt == 0 && soacount == 0 && nscount != 0) {
11254 dns_zone_log(zone, ISC_LOG_INFO,
11255 "refresh: referral response "
11256 "from master %s (source %s)", master, source);
11257 goto next_master;
11261 * if nodata log and next master;
11263 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
11264 dns_zone_log(zone, ISC_LOG_INFO,
11265 "refresh: NODATA response "
11266 "from master %s (source %s)", master, source);
11267 goto next_master;
11271 * Only one soa at top of zone.
11273 if (soacnt != 1) {
11274 dns_zone_log(zone, ISC_LOG_INFO,
11275 "refresh: answer SOA count (%d) != 1 "
11276 "from master %s (source %s)",
11277 soacnt, master, source);
11278 goto next_master;
11282 * Extract serial
11284 rdataset = NULL;
11285 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
11286 dns_rdatatype_soa, dns_rdatatype_none,
11287 NULL, &rdataset);
11288 if (result != ISC_R_SUCCESS) {
11289 dns_zone_log(zone, ISC_LOG_INFO,
11290 "refresh: unable to get SOA record "
11291 "from master %s (source %s)", master, source);
11292 goto next_master;
11295 result = dns_rdataset_first(rdataset);
11296 if (result != ISC_R_SUCCESS) {
11297 dns_zone_log(zone, ISC_LOG_INFO,
11298 "refresh: dns_rdataset_first() failed");
11299 goto next_master;
11302 dns_rdataset_current(rdataset, &rdata);
11303 result = dns_rdata_tostruct(&rdata, &soa, NULL);
11304 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11306 serial = soa.serial;
11307 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
11308 unsigned int dbsoacount;
11309 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
11310 &oldserial, NULL, NULL, NULL, NULL,
11311 NULL);
11312 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11313 RUNTIME_CHECK(dbsoacount > 0U);
11314 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
11315 serial, oldserial);
11316 } else
11317 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
11318 serial);
11320 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
11321 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
11322 isc_serial_gt(serial, oldserial)) {
11323 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
11324 &zone->sourceaddr, &now))
11326 dns_zone_log(zone, ISC_LOG_INFO,
11327 "refresh: skipping %s as master %s "
11328 "(source %s) is unreachable (cached)",
11329 (zone->type == dns_zone_slave ||
11330 zone->type == dns_zone_redirect) ?
11331 "zone transfer" : "NS query",
11332 master, source);
11333 goto next_master;
11335 tcp_transfer:
11336 isc_event_free(&event);
11337 dns_request_destroy(&zone->request);
11338 if (zone->type == dns_zone_slave ||
11339 zone->type == dns_zone_redirect) {
11340 do_queue_xfrin = ISC_TRUE;
11341 } else {
11342 INSIST(zone->type == dns_zone_stub);
11343 ns_query(zone, rdataset, NULL);
11345 if (msg != NULL)
11346 dns_message_destroy(&msg);
11347 } else if (isc_serial_eq(soa.serial, oldserial)) {
11348 if (zone->masterfile != NULL) {
11349 result = ISC_R_FAILURE;
11350 if (zone->journal != NULL)
11351 result = isc_file_settime(zone->journal, &now);
11352 if (result == ISC_R_SUCCESS &&
11353 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11354 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11355 result = isc_file_settime(zone->masterfile,
11356 &now);
11357 } else if (result != ISC_R_SUCCESS)
11358 result = isc_file_settime(zone->masterfile,
11359 &now);
11360 /* Someone removed the file from underneath us! */
11361 if (result == ISC_R_FILENOTFOUND) {
11362 zone_needdump(zone, DNS_DUMP_DELAY);
11363 } else if (result != ISC_R_SUCCESS)
11364 dns_zone_log(zone, ISC_LOG_ERROR,
11365 "refresh: could not set file "
11366 "modification time of '%s': %s",
11367 zone->masterfile,
11368 dns_result_totext(result));
11370 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
11371 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
11372 zone->mastersok[zone->curmaster] = ISC_TRUE;
11373 goto next_master;
11374 } else {
11375 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
11376 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
11377 "received from master %s < ours (%u)",
11378 soa.serial, master, oldserial);
11379 else
11380 zone_debuglog(zone, me, 1, "ahead");
11381 zone->mastersok[zone->curmaster] = ISC_TRUE;
11382 goto next_master;
11384 if (msg != NULL)
11385 dns_message_destroy(&msg);
11386 goto detach;
11388 next_master:
11389 if (msg != NULL)
11390 dns_message_destroy(&msg);
11391 isc_event_free(&event);
11392 dns_request_destroy(&zone->request);
11394 * Skip to next failed / untried master.
11396 do {
11397 zone->curmaster++;
11398 } while (zone->curmaster < zone->masterscnt &&
11399 zone->mastersok[zone->curmaster]);
11400 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11401 if (zone->curmaster >= zone->masterscnt) {
11402 isc_boolean_t done = ISC_TRUE;
11403 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11404 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11406 * Did we get a good answer from all the masters?
11408 for (j = 0; j < zone->masterscnt; j++)
11409 if (zone->mastersok[j] == ISC_FALSE) {
11410 done = ISC_FALSE;
11411 break;
11413 } else
11414 done = ISC_TRUE;
11415 if (!done) {
11416 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11417 zone->curmaster = 0;
11419 * Find the next failed master.
11421 while (zone->curmaster < zone->masterscnt &&
11422 zone->mastersok[zone->curmaster])
11423 zone->curmaster++;
11424 goto requeue;
11426 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11427 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
11428 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
11429 zone->refreshtime = now;
11431 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11432 zone_settimer(zone, &now);
11433 goto detach;
11436 requeue:
11437 queue_soa_query(zone);
11438 goto detach;
11440 same_master:
11441 if (msg != NULL)
11442 dns_message_destroy(&msg);
11443 isc_event_free(&event);
11444 dns_request_destroy(&zone->request);
11445 queue_soa_query(zone);
11447 detach:
11448 UNLOCK_ZONE(zone);
11449 if (do_queue_xfrin)
11450 queue_xfrin(zone);
11451 dns_zone_idetach(&zone);
11452 return;
11455 static void
11456 queue_soa_query(dns_zone_t *zone) {
11457 const char me[] = "queue_soa_query";
11458 isc_event_t *e;
11459 dns_zone_t *dummy = NULL;
11460 isc_result_t result;
11462 ENTER;
11464 * Locked by caller
11466 REQUIRE(LOCKED_ZONE(zone));
11468 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11469 cancel_refresh(zone);
11470 return;
11473 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
11474 soa_query, zone, sizeof(isc_event_t));
11475 if (e == NULL) {
11476 cancel_refresh(zone);
11477 return;
11481 * Attach so that we won't clean up
11482 * until the event is delivered.
11484 zone_iattach(zone, &dummy);
11486 e->ev_arg = zone;
11487 e->ev_sender = NULL;
11488 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
11489 if (result != ISC_R_SUCCESS) {
11490 zone_idetach(&dummy);
11491 isc_event_free(&e);
11492 cancel_refresh(zone);
11496 static inline isc_result_t
11497 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
11498 dns_message_t **messagep)
11500 dns_message_t *message = NULL;
11501 dns_name_t *qname = NULL;
11502 dns_rdataset_t *qrdataset = NULL;
11503 isc_result_t result;
11505 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
11506 &message);
11507 if (result != ISC_R_SUCCESS)
11508 goto cleanup;
11510 message->opcode = dns_opcode_query;
11511 message->rdclass = zone->rdclass;
11513 result = dns_message_gettempname(message, &qname);
11514 if (result != ISC_R_SUCCESS)
11515 goto cleanup;
11517 result = dns_message_gettemprdataset(message, &qrdataset);
11518 if (result != ISC_R_SUCCESS)
11519 goto cleanup;
11522 * Make question.
11524 dns_name_init(qname, NULL);
11525 dns_name_clone(&zone->origin, qname);
11526 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
11527 ISC_LIST_APPEND(qname->list, qrdataset, link);
11528 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
11530 *messagep = message;
11531 return (ISC_R_SUCCESS);
11533 cleanup:
11534 if (qname != NULL)
11535 dns_message_puttempname(message, &qname);
11536 if (qrdataset != NULL)
11537 dns_message_puttemprdataset(message, &qrdataset);
11538 if (message != NULL)
11539 dns_message_destroy(&message);
11540 return (result);
11543 static isc_result_t
11544 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid) {
11545 isc_result_t result;
11546 dns_rdataset_t *rdataset = NULL;
11547 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
11548 int count = 0;
11550 /* Set EDNS options if applicable */
11551 if (reqnsid) {
11552 INSIST(count < DNS_EDNSOPTIONS);
11553 ednsopts[count].code = DNS_OPT_NSID;
11554 ednsopts[count].length = 0;
11555 ednsopts[count].value = NULL;
11556 count++;
11558 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
11559 ednsopts, count);
11560 if (result != ISC_R_SUCCESS)
11561 return (result);
11563 return (dns_message_setopt(message, rdataset));
11566 static void
11567 soa_query(isc_task_t *task, isc_event_t *event) {
11568 const char me[] = "soa_query";
11569 isc_result_t result = ISC_R_FAILURE;
11570 dns_message_t *message = NULL;
11571 dns_zone_t *zone = event->ev_arg;
11572 dns_zone_t *dummy = NULL;
11573 isc_netaddr_t masterip;
11574 dns_tsigkey_t *key = NULL;
11575 isc_uint32_t options;
11576 isc_boolean_t cancel = ISC_TRUE;
11577 int timeout;
11578 isc_boolean_t have_xfrsource, have_xfrdscp, reqnsid;
11579 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11580 isc_dscp_t dscp = -1;
11582 REQUIRE(DNS_ZONE_VALID(zone));
11584 UNUSED(task);
11586 ENTER;
11588 LOCK_ZONE(zone);
11589 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
11590 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11591 zone->view->requestmgr == NULL) {
11592 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
11593 cancel = ISC_FALSE;
11594 goto cleanup;
11597 again:
11598 result = create_query(zone, dns_rdatatype_soa, &message);
11599 if (result != ISC_R_SUCCESS)
11600 goto cleanup;
11602 INSIST(zone->masterscnt > 0);
11603 INSIST(zone->curmaster < zone->masterscnt);
11605 zone->masteraddr = zone->masters[zone->curmaster];
11607 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11609 * First, look for a tsig key in the master statement, then
11610 * try for a server key.
11612 if ((zone->masterkeynames != NULL) &&
11613 (zone->masterkeynames[zone->curmaster] != NULL)) {
11614 dns_view_t *view = dns_zone_getview(zone);
11615 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11616 result = dns_view_gettsig(view, keyname, &key);
11617 if (result != ISC_R_SUCCESS) {
11618 char namebuf[DNS_NAME_FORMATSIZE];
11619 dns_name_format(keyname, namebuf, sizeof(namebuf));
11620 dns_zone_log(zone, ISC_LOG_ERROR,
11621 "unable to find key: %s", namebuf);
11622 goto skip_master;
11625 if (key == NULL) {
11626 result = dns_view_getpeertsig(zone->view, &masterip, &key);
11627 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11628 char addrbuf[ISC_NETADDR_FORMATSIZE];
11629 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
11630 dns_zone_log(zone, ISC_LOG_ERROR,
11631 "unable to find TSIG key for %s", addrbuf);
11632 goto skip_master;
11636 have_xfrsource = have_xfrdscp = ISC_FALSE;
11637 reqnsid = zone->view->requestnsid;
11638 if (zone->view->peers != NULL) {
11639 dns_peer_t *peer = NULL;
11640 isc_boolean_t edns;
11641 result = dns_peerlist_peerbyaddr(zone->view->peers,
11642 &masterip, &peer);
11643 if (result == ISC_R_SUCCESS) {
11644 result = dns_peer_getsupportedns(peer, &edns);
11645 if (result == ISC_R_SUCCESS && !edns)
11646 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11647 result = dns_peer_gettransfersource(peer,
11648 &zone->sourceaddr);
11649 if (result == ISC_R_SUCCESS)
11650 have_xfrsource = ISC_TRUE;
11651 (void)dns_peer_gettransferdscp(peer, &dscp);
11652 if (dscp != -1)
11653 have_xfrdscp = ISC_TRUE;
11654 if (zone->view->resolver != NULL)
11655 udpsize =
11656 dns_resolver_getudpsize(zone->view->resolver);
11657 (void)dns_peer_getudpsize(peer, &udpsize);
11658 (void)dns_peer_getrequestnsid(peer, &reqnsid);
11662 switch (isc_sockaddr_pf(&zone->masteraddr)) {
11663 case PF_INET:
11664 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11665 if (isc_sockaddr_equal(&zone->altxfrsource4,
11666 &zone->xfrsource4))
11667 goto skip_master;
11668 zone->sourceaddr = zone->altxfrsource4;
11669 if (!have_xfrdscp)
11670 dscp = zone->altxfrsource4dscp;
11671 } else if (!have_xfrsource) {
11672 zone->sourceaddr = zone->xfrsource4;
11673 if (!have_xfrdscp)
11674 dscp = zone->xfrsource4dscp;
11676 break;
11677 case PF_INET6:
11678 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11679 if (isc_sockaddr_equal(&zone->altxfrsource6,
11680 &zone->xfrsource6))
11681 goto skip_master;
11682 zone->sourceaddr = zone->altxfrsource6;
11683 if (!have_xfrdscp)
11684 dscp = zone->altxfrsource6dscp;
11685 } else if (!have_xfrsource) {
11686 zone->sourceaddr = zone->xfrsource6;
11687 if (!have_xfrdscp)
11688 dscp = zone->xfrsource6dscp;
11690 break;
11691 default:
11692 result = ISC_R_NOTIMPLEMENTED;
11693 goto cleanup;
11696 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
11697 DNS_REQUESTOPT_TCP : 0;
11699 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11700 result = add_opt(message, udpsize, reqnsid);
11701 if (result != ISC_R_SUCCESS)
11702 zone_debuglog(zone, me, 1,
11703 "unable to add opt record: %s",
11704 dns_result_totext(result));
11707 zone_iattach(zone, &dummy);
11708 timeout = 15;
11709 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11710 timeout = 30;
11711 result = dns_request_createvia4(zone->view->requestmgr, message,
11712 &zone->sourceaddr, &zone->masteraddr,
11713 dscp, options, key, timeout * 3,
11714 timeout, 0, zone->task,
11715 refresh_callback, zone, &zone->request);
11716 if (result != ISC_R_SUCCESS) {
11717 zone_idetach(&dummy);
11718 zone_debuglog(zone, me, 1,
11719 "dns_request_createvia4() failed: %s",
11720 dns_result_totext(result));
11721 goto skip_master;
11722 } else {
11723 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
11724 inc_stats(zone, dns_zonestatscounter_soaoutv4);
11725 else
11726 inc_stats(zone, dns_zonestatscounter_soaoutv6);
11728 cancel = ISC_FALSE;
11730 cleanup:
11731 if (key != NULL)
11732 dns_tsigkey_detach(&key);
11733 if (result != ISC_R_SUCCESS)
11734 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11735 if (message != NULL)
11736 dns_message_destroy(&message);
11737 if (cancel)
11738 cancel_refresh(zone);
11739 isc_event_free(&event);
11740 UNLOCK_ZONE(zone);
11741 dns_zone_idetach(&zone);
11742 return;
11744 skip_master:
11745 if (key != NULL)
11746 dns_tsigkey_detach(&key);
11747 dns_message_destroy(&message);
11749 * Skip to next failed / untried master.
11751 do {
11752 zone->curmaster++;
11753 } while (zone->curmaster < zone->masterscnt &&
11754 zone->mastersok[zone->curmaster]);
11755 if (zone->curmaster < zone->masterscnt)
11756 goto again;
11757 zone->curmaster = 0;
11758 goto cleanup;
11761 static void
11762 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
11763 const char me[] = "ns_query";
11764 isc_result_t result;
11765 dns_message_t *message = NULL;
11766 isc_netaddr_t masterip;
11767 dns_tsigkey_t *key = NULL;
11768 dns_dbnode_t *node = NULL;
11769 int timeout;
11770 isc_boolean_t have_xfrsource = ISC_FALSE, have_xfrdscp = ISC_FALSE;
11771 isc_boolean_t reqnsid;
11772 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
11773 isc_dscp_t dscp = -1;
11775 REQUIRE(DNS_ZONE_VALID(zone));
11776 REQUIRE(LOCKED_ZONE(zone));
11777 REQUIRE((soardataset != NULL && stub == NULL) ||
11778 (soardataset == NULL && stub != NULL));
11779 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
11781 ENTER;
11783 if (stub == NULL) {
11784 stub = isc_mem_get(zone->mctx, sizeof(*stub));
11785 if (stub == NULL)
11786 goto cleanup;
11787 stub->magic = STUB_MAGIC;
11788 stub->mctx = zone->mctx;
11789 stub->zone = NULL;
11790 stub->db = NULL;
11791 stub->version = NULL;
11794 * Attach so that the zone won't disappear from under us.
11796 zone_iattach(zone, &stub->zone);
11799 * If a db exists we will update it, otherwise we create a
11800 * new one and attach it to the zone once we have the NS
11801 * RRset and glue.
11803 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11804 if (zone->db != NULL) {
11805 dns_db_attach(zone->db, &stub->db);
11806 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11807 } else {
11808 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11810 INSIST(zone->db_argc >= 1);
11811 result = dns_db_create(zone->mctx, zone->db_argv[0],
11812 &zone->origin, dns_dbtype_stub,
11813 zone->rdclass,
11814 zone->db_argc - 1,
11815 zone->db_argv + 1,
11816 &stub->db);
11817 if (result != ISC_R_SUCCESS) {
11818 dns_zone_log(zone, ISC_LOG_ERROR,
11819 "refreshing stub: "
11820 "could not create "
11821 "database: %s",
11822 dns_result_totext(result));
11823 goto cleanup;
11825 dns_db_settask(stub->db, zone->task);
11828 result = dns_db_newversion(stub->db, &stub->version);
11829 if (result != ISC_R_SUCCESS) {
11830 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11831 "dns_db_newversion() failed: %s",
11832 dns_result_totext(result));
11833 goto cleanup;
11837 * Update SOA record.
11839 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
11840 &node);
11841 if (result != ISC_R_SUCCESS) {
11842 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11843 "dns_db_findnode() failed: %s",
11844 dns_result_totext(result));
11845 goto cleanup;
11848 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
11849 soardataset, 0, NULL);
11850 dns_db_detachnode(stub->db, &node);
11851 if (result != ISC_R_SUCCESS) {
11852 dns_zone_log(zone, ISC_LOG_INFO,
11853 "refreshing stub: "
11854 "dns_db_addrdataset() failed: %s",
11855 dns_result_totext(result));
11856 goto cleanup;
11861 * XXX Optimisation: Create message when zone is setup and reuse.
11863 result = create_query(zone, dns_rdatatype_ns, &message);
11864 INSIST(result == ISC_R_SUCCESS);
11866 INSIST(zone->masterscnt > 0);
11867 INSIST(zone->curmaster < zone->masterscnt);
11868 zone->masteraddr = zone->masters[zone->curmaster];
11870 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
11872 * First, look for a tsig key in the master statement, then
11873 * try for a server key.
11875 if ((zone->masterkeynames != NULL) &&
11876 (zone->masterkeynames[zone->curmaster] != NULL)) {
11877 dns_view_t *view = dns_zone_getview(zone);
11878 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
11879 result = dns_view_gettsig(view, keyname, &key);
11880 if (result != ISC_R_SUCCESS) {
11881 char namebuf[DNS_NAME_FORMATSIZE];
11882 dns_name_format(keyname, namebuf, sizeof(namebuf));
11883 dns_zone_log(zone, ISC_LOG_ERROR,
11884 "unable to find key: %s", namebuf);
11887 if (key == NULL)
11888 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
11890 reqnsid = zone->view->requestnsid;
11891 if (zone->view->peers != NULL) {
11892 dns_peer_t *peer = NULL;
11893 isc_boolean_t edns;
11894 result = dns_peerlist_peerbyaddr(zone->view->peers,
11895 &masterip, &peer);
11896 if (result == ISC_R_SUCCESS) {
11897 result = dns_peer_getsupportedns(peer, &edns);
11898 if (result == ISC_R_SUCCESS && !edns)
11899 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11900 result = dns_peer_gettransfersource(peer,
11901 &zone->sourceaddr);
11902 if (result == ISC_R_SUCCESS)
11903 have_xfrsource = ISC_TRUE;
11904 result = dns_peer_gettransferdscp(peer, &dscp);
11905 if (result == ISC_R_SUCCESS && dscp != -1)
11906 have_xfrdscp = ISC_TRUE;
11907 if (zone->view->resolver != NULL)
11908 udpsize =
11909 dns_resolver_getudpsize(zone->view->resolver);
11910 (void)dns_peer_getudpsize(peer, &udpsize);
11911 (void)dns_peer_getrequestnsid(peer, &reqnsid);
11915 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11916 result = add_opt(message, udpsize, reqnsid);
11917 if (result != ISC_R_SUCCESS)
11918 zone_debuglog(zone, me, 1,
11919 "unable to add opt record: %s",
11920 dns_result_totext(result));
11924 * Always use TCP so that we shouldn't truncate in additional section.
11926 switch (isc_sockaddr_pf(&zone->masteraddr)) {
11927 case PF_INET:
11928 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11929 zone->sourceaddr = zone->altxfrsource4;
11930 if (!have_xfrdscp)
11931 dscp = zone->altxfrsource4dscp;
11932 } else if (!have_xfrsource) {
11933 zone->sourceaddr = zone->xfrsource4;
11934 if (!have_xfrdscp)
11935 dscp = zone->xfrsource4dscp;
11937 break;
11938 case PF_INET6:
11939 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11940 zone->sourceaddr = zone->altxfrsource6;
11941 if (!have_xfrdscp)
11942 dscp = zone->altxfrsource6dscp;
11943 } else if (!have_xfrsource) {
11944 zone->sourceaddr = zone->xfrsource6;
11945 if (!have_xfrdscp)
11946 dscp = zone->xfrsource6dscp;
11948 break;
11949 default:
11950 result = ISC_R_NOTIMPLEMENTED;
11951 POST(result);
11952 goto cleanup;
11954 timeout = 15;
11955 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
11956 timeout = 30;
11957 result = dns_request_createvia4(zone->view->requestmgr, message,
11958 &zone->sourceaddr, &zone->masteraddr,
11959 dscp, DNS_REQUESTOPT_TCP, key,
11960 timeout * 3, timeout, 0, zone->task,
11961 stub_callback, stub, &zone->request);
11962 if (result != ISC_R_SUCCESS) {
11963 zone_debuglog(zone, me, 1,
11964 "dns_request_createvia() failed: %s",
11965 dns_result_totext(result));
11966 goto cleanup;
11968 dns_message_destroy(&message);
11969 goto unlock;
11971 cleanup:
11972 cancel_refresh(zone);
11973 if (stub != NULL) {
11974 stub->magic = 0;
11975 if (stub->version != NULL)
11976 dns_db_closeversion(stub->db, &stub->version,
11977 ISC_FALSE);
11978 if (stub->db != NULL)
11979 dns_db_detach(&stub->db);
11980 if (stub->zone != NULL)
11981 zone_idetach(&stub->zone);
11982 isc_mem_put(stub->mctx, stub, sizeof(*stub));
11984 if (message != NULL)
11985 dns_message_destroy(&message);
11986 unlock:
11987 if (key != NULL)
11988 dns_tsigkey_detach(&key);
11989 return;
11993 * Handle the control event. Note that although this event causes the zone
11994 * to shut down, it is not a shutdown event in the sense of the task library.
11996 static void
11997 zone_shutdown(isc_task_t *task, isc_event_t *event) {
11998 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
11999 isc_boolean_t free_needed, linked = ISC_FALSE;
12000 dns_zone_t *raw = NULL, *secure = NULL;
12002 UNUSED(task);
12003 REQUIRE(DNS_ZONE_VALID(zone));
12004 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
12005 INSIST(isc_refcount_current(&zone->erefs) == 0);
12007 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
12010 * Stop things being restarted after we cancel them below.
12012 LOCK_ZONE(zone);
12013 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
12014 UNLOCK_ZONE(zone);
12017 * If we were waiting for xfrin quota, step out of
12018 * the queue.
12019 * If there's no zone manager, we can't be waiting for the
12020 * xfrin quota
12022 if (zone->zmgr != NULL) {
12023 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12024 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
12025 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
12026 statelink);
12027 linked = ISC_TRUE;
12028 zone->statelist = NULL;
12030 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
12031 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
12032 statelink);
12033 zone->statelist = NULL;
12034 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
12036 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12040 * In task context, no locking required. See zone_xfrdone().
12042 if (zone->xfr != NULL)
12043 dns_xfrin_shutdown(zone->xfr);
12045 /* Safe to release the zone now */
12046 if (zone->zmgr != NULL)
12047 dns_zonemgr_releasezone(zone->zmgr, zone);
12049 LOCK_ZONE(zone);
12050 INSIST(zone != zone->raw);
12051 if (linked) {
12052 INSIST(zone->irefs > 0);
12053 zone->irefs--;
12055 if (zone->request != NULL) {
12056 dns_request_cancel(zone->request);
12059 if (zone->readio != NULL)
12060 zonemgr_cancelio(zone->readio);
12062 if (zone->lctx != NULL)
12063 dns_loadctx_cancel(zone->lctx);
12065 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12066 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12067 if (zone->writeio != NULL)
12068 zonemgr_cancelio(zone->writeio);
12070 if (zone->dctx != NULL)
12071 dns_dumpctx_cancel(zone->dctx);
12074 notify_cancel(zone);
12076 forward_cancel(zone);
12078 if (zone->timer != NULL) {
12079 isc_timer_detach(&zone->timer);
12080 INSIST(zone->irefs > 0);
12081 zone->irefs--;
12084 if (zone->view != NULL)
12085 dns_view_weakdetach(&zone->view);
12088 * We have now canceled everything set the flag to allow exit_check()
12089 * to succeed. We must not unlock between setting this flag and
12090 * calling exit_check().
12092 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
12093 free_needed = exit_check(zone);
12094 if (inline_secure(zone)) {
12095 raw = zone->raw;
12096 zone->raw = NULL;
12098 if (inline_raw(zone)) {
12099 secure = zone->secure;
12100 zone->secure = NULL;
12102 UNLOCK_ZONE(zone);
12103 if (raw != NULL)
12104 dns_zone_detach(&raw);
12105 if (secure != NULL)
12106 dns_zone_idetach(&secure);
12107 if (free_needed)
12108 zone_free(zone);
12111 static void
12112 zone_timer(isc_task_t *task, isc_event_t *event) {
12113 const char me[] = "zone_timer";
12114 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
12116 UNUSED(task);
12117 REQUIRE(DNS_ZONE_VALID(zone));
12119 ENTER;
12121 zone_maintenance(zone);
12123 isc_event_free(&event);
12126 static void
12127 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
12128 const char me[] = "zone_settimer";
12129 isc_time_t next;
12130 isc_result_t result;
12132 REQUIRE(DNS_ZONE_VALID(zone));
12133 ENTER;
12135 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12136 return;
12138 isc_time_settoepoch(&next);
12140 switch (zone->type) {
12141 case dns_zone_redirect:
12142 if (zone->masters != NULL)
12143 goto treat_as_slave;
12144 /* FALLTHROUGH */
12146 case dns_zone_master:
12147 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
12148 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
12149 next = zone->notifytime;
12150 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12151 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12152 INSIST(!isc_time_isepoch(&zone->dumptime));
12153 if (isc_time_isepoch(&next) ||
12154 isc_time_compare(&zone->dumptime, &next) < 0)
12155 next = zone->dumptime;
12157 if (zone->type == dns_zone_redirect)
12158 break;
12159 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
12160 !isc_time_isepoch(&zone->refreshkeytime)) {
12161 if (isc_time_isepoch(&next) ||
12162 isc_time_compare(&zone->refreshkeytime, &next) < 0)
12163 next = zone->refreshkeytime;
12165 if (!isc_time_isepoch(&zone->resigntime)) {
12166 if (isc_time_isepoch(&next) ||
12167 isc_time_compare(&zone->resigntime, &next) < 0)
12168 next = zone->resigntime;
12170 if (!isc_time_isepoch(&zone->keywarntime)) {
12171 if (isc_time_isepoch(&next) ||
12172 isc_time_compare(&zone->keywarntime, &next) < 0)
12173 next = zone->keywarntime;
12175 if (!isc_time_isepoch(&zone->signingtime)) {
12176 if (isc_time_isepoch(&next) ||
12177 isc_time_compare(&zone->signingtime, &next) < 0)
12178 next = zone->signingtime;
12180 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
12181 if (isc_time_isepoch(&next) ||
12182 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
12183 next = zone->nsec3chaintime;
12185 break;
12187 case dns_zone_slave:
12188 treat_as_slave:
12189 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY))
12190 next = zone->notifytime;
12191 /* FALLTHROUGH */
12193 case dns_zone_stub:
12194 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
12195 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
12196 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
12197 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
12198 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
12199 !isc_time_isepoch(&zone->refreshtime) &&
12200 (isc_time_isepoch(&next) ||
12201 isc_time_compare(&zone->refreshtime, &next) < 0))
12202 next = zone->refreshtime;
12203 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
12204 !isc_time_isepoch(&zone->expiretime)) {
12205 if (isc_time_isepoch(&next) ||
12206 isc_time_compare(&zone->expiretime, &next) < 0)
12207 next = zone->expiretime;
12209 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12210 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12211 INSIST(!isc_time_isepoch(&zone->dumptime));
12212 if (isc_time_isepoch(&next) ||
12213 isc_time_compare(&zone->dumptime, &next) < 0)
12214 next = zone->dumptime;
12216 break;
12218 case dns_zone_key:
12219 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12220 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12221 INSIST(!isc_time_isepoch(&zone->dumptime));
12222 if (isc_time_isepoch(&next) ||
12223 isc_time_compare(&zone->dumptime, &next) < 0)
12224 next = zone->dumptime;
12226 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
12227 if (isc_time_isepoch(&next) ||
12228 (!isc_time_isepoch(&zone->refreshkeytime) &&
12229 isc_time_compare(&zone->refreshkeytime, &next) < 0))
12230 next = zone->refreshkeytime;
12232 break;
12234 default:
12235 break;
12238 if (isc_time_isepoch(&next)) {
12239 zone_debuglog(zone, me, 10, "settimer inactive");
12240 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
12241 NULL, NULL, ISC_TRUE);
12242 if (result != ISC_R_SUCCESS)
12243 dns_zone_log(zone, ISC_LOG_ERROR,
12244 "could not deactivate zone timer: %s",
12245 isc_result_totext(result));
12246 } else {
12247 if (isc_time_compare(&next, now) <= 0)
12248 next = *now;
12249 result = isc_timer_reset(zone->timer, isc_timertype_once,
12250 &next, NULL, ISC_TRUE);
12251 if (result != ISC_R_SUCCESS)
12252 dns_zone_log(zone, ISC_LOG_ERROR,
12253 "could not reset zone timer: %s",
12254 isc_result_totext(result));
12258 static void
12259 cancel_refresh(dns_zone_t *zone) {
12260 const char me[] = "cancel_refresh";
12261 isc_time_t now;
12264 * 'zone' locked by caller.
12267 REQUIRE(DNS_ZONE_VALID(zone));
12268 REQUIRE(LOCKED_ZONE(zone));
12270 ENTER;
12272 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12273 TIME_NOW(&now);
12274 zone_settimer(zone, &now);
12277 static isc_result_t
12278 notify_createmessage(dns_zone_t *zone, unsigned int flags,
12279 dns_message_t **messagep)
12281 dns_db_t *zonedb = NULL;
12282 dns_dbnode_t *node = NULL;
12283 dns_dbversion_t *version = NULL;
12284 dns_message_t *message = NULL;
12285 dns_rdataset_t rdataset;
12286 dns_rdata_t rdata = DNS_RDATA_INIT;
12288 dns_name_t *tempname = NULL;
12289 dns_rdata_t *temprdata = NULL;
12290 dns_rdatalist_t *temprdatalist = NULL;
12291 dns_rdataset_t *temprdataset = NULL;
12293 isc_result_t result;
12294 isc_region_t r;
12295 isc_buffer_t *b = NULL;
12297 REQUIRE(DNS_ZONE_VALID(zone));
12298 REQUIRE(messagep != NULL && *messagep == NULL);
12300 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
12301 &message);
12302 if (result != ISC_R_SUCCESS)
12303 return (result);
12305 message->opcode = dns_opcode_notify;
12306 message->flags |= DNS_MESSAGEFLAG_AA;
12307 message->rdclass = zone->rdclass;
12309 result = dns_message_gettempname(message, &tempname);
12310 if (result != ISC_R_SUCCESS)
12311 goto cleanup;
12313 result = dns_message_gettemprdataset(message, &temprdataset);
12314 if (result != ISC_R_SUCCESS)
12315 goto cleanup;
12318 * Make question.
12320 dns_name_init(tempname, NULL);
12321 dns_name_clone(&zone->origin, tempname);
12322 dns_rdataset_makequestion(temprdataset, zone->rdclass,
12323 dns_rdatatype_soa);
12324 ISC_LIST_APPEND(tempname->list, temprdataset, link);
12325 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
12326 tempname = NULL;
12327 temprdataset = NULL;
12329 if ((flags & DNS_NOTIFY_NOSOA) != 0)
12330 goto done;
12332 result = dns_message_gettempname(message, &tempname);
12333 if (result != ISC_R_SUCCESS)
12334 goto soa_cleanup;
12335 result = dns_message_gettemprdata(message, &temprdata);
12336 if (result != ISC_R_SUCCESS)
12337 goto soa_cleanup;
12338 result = dns_message_gettemprdataset(message, &temprdataset);
12339 if (result != ISC_R_SUCCESS)
12340 goto soa_cleanup;
12341 result = dns_message_gettemprdatalist(message, &temprdatalist);
12342 if (result != ISC_R_SUCCESS)
12343 goto soa_cleanup;
12345 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12346 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
12347 dns_db_attach(zone->db, &zonedb);
12348 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12350 dns_name_init(tempname, NULL);
12351 dns_name_clone(&zone->origin, tempname);
12352 dns_db_currentversion(zonedb, &version);
12353 result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
12354 if (result != ISC_R_SUCCESS)
12355 goto soa_cleanup;
12357 dns_rdataset_init(&rdataset);
12358 result = dns_db_findrdataset(zonedb, node, version,
12359 dns_rdatatype_soa,
12360 dns_rdatatype_none, 0, &rdataset,
12361 NULL);
12362 if (result != ISC_R_SUCCESS)
12363 goto soa_cleanup;
12364 result = dns_rdataset_first(&rdataset);
12365 if (result != ISC_R_SUCCESS)
12366 goto soa_cleanup;
12367 dns_rdataset_current(&rdataset, &rdata);
12368 dns_rdata_toregion(&rdata, &r);
12369 result = isc_buffer_allocate(zone->mctx, &b, r.length);
12370 if (result != ISC_R_SUCCESS)
12371 goto soa_cleanup;
12372 isc_buffer_putmem(b, r.base, r.length);
12373 isc_buffer_usedregion(b, &r);
12374 dns_rdata_init(temprdata);
12375 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
12376 dns_message_takebuffer(message, &b);
12377 result = dns_rdataset_next(&rdataset);
12378 dns_rdataset_disassociate(&rdataset);
12379 if (result != ISC_R_NOMORE)
12380 goto soa_cleanup;
12381 temprdatalist->rdclass = rdata.rdclass;
12382 temprdatalist->type = rdata.type;
12383 temprdatalist->covers = 0;
12384 temprdatalist->ttl = rdataset.ttl;
12385 ISC_LIST_INIT(temprdatalist->rdata);
12386 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
12388 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
12389 if (result != ISC_R_SUCCESS)
12390 goto soa_cleanup;
12392 ISC_LIST_APPEND(tempname->list, temprdataset, link);
12393 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
12394 temprdatalist = NULL;
12395 temprdataset = NULL;
12396 temprdata = NULL;
12397 tempname = NULL;
12399 soa_cleanup:
12400 if (node != NULL)
12401 dns_db_detachnode(zonedb, &node);
12402 if (version != NULL)
12403 dns_db_closeversion(zonedb, &version, ISC_FALSE);
12404 if (zonedb != NULL)
12405 dns_db_detach(&zonedb);
12406 if (tempname != NULL)
12407 dns_message_puttempname(message, &tempname);
12408 if (temprdata != NULL)
12409 dns_message_puttemprdata(message, &temprdata);
12410 if (temprdataset != NULL)
12411 dns_message_puttemprdataset(message, &temprdataset);
12412 if (temprdatalist != NULL)
12413 dns_message_puttemprdatalist(message, &temprdatalist);
12415 done:
12416 *messagep = message;
12417 return (ISC_R_SUCCESS);
12419 cleanup:
12420 if (tempname != NULL)
12421 dns_message_puttempname(message, &tempname);
12422 if (temprdataset != NULL)
12423 dns_message_puttemprdataset(message, &temprdataset);
12424 dns_message_destroy(&message);
12425 return (result);
12428 isc_result_t
12429 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
12430 dns_message_t *msg)
12432 unsigned int i;
12433 dns_rdata_soa_t soa;
12434 dns_rdataset_t *rdataset = NULL;
12435 dns_rdata_t rdata = DNS_RDATA_INIT;
12436 isc_result_t result;
12437 char fromtext[ISC_SOCKADDR_FORMATSIZE];
12438 int match = 0;
12439 isc_netaddr_t netaddr;
12440 isc_sockaddr_t local, remote;
12441 isc_uint32_t serial = 0;
12442 isc_boolean_t have_serial = ISC_FALSE;
12443 dns_tsigkey_t *tsigkey;
12444 dns_name_t *tsig;
12446 REQUIRE(DNS_ZONE_VALID(zone));
12449 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
12450 * ROLLOVER.
12452 * SOA: RFC1996
12453 * Check that 'from' is a valid notify source, (zone->masters).
12454 * Return DNS_R_REFUSED if not.
12456 * If the notify message contains a serial number check it
12457 * against the zones serial and return if <= current serial
12459 * If a refresh check is progress, if so just record the
12460 * fact we received a NOTIFY and from where and return.
12461 * We will perform a new refresh check when the current one
12462 * completes. Return ISC_R_SUCCESS.
12464 * Otherwise initiate a refresh check using 'from' as the
12465 * first address to check. Return ISC_R_SUCCESS.
12468 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
12471 * Notify messages are processed by the raw zone.
12473 LOCK_ZONE(zone);
12474 INSIST(zone != zone->raw);
12475 if (inline_secure(zone)) {
12476 result = dns_zone_notifyreceive(zone->raw, from, msg);
12477 UNLOCK_ZONE(zone);
12478 return (result);
12481 * We only handle NOTIFY (SOA) at the present.
12483 if (isc_sockaddr_pf(from) == PF_INET)
12484 inc_stats(zone, dns_zonestatscounter_notifyinv4);
12485 else
12486 inc_stats(zone, dns_zonestatscounter_notifyinv6);
12487 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
12488 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
12489 dns_rdatatype_soa, dns_rdatatype_none,
12490 NULL, NULL) != ISC_R_SUCCESS) {
12491 UNLOCK_ZONE(zone);
12492 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
12493 dns_zone_log(zone, ISC_LOG_NOTICE,
12494 "NOTIFY with no "
12495 "question section from: %s", fromtext);
12496 return (DNS_R_FORMERR);
12498 dns_zone_log(zone, ISC_LOG_NOTICE,
12499 "NOTIFY zone does not match");
12500 return (DNS_R_NOTIMP);
12504 * If we are a master zone just succeed.
12506 if (zone->type == dns_zone_master) {
12507 UNLOCK_ZONE(zone);
12508 return (ISC_R_SUCCESS);
12511 isc_netaddr_fromsockaddr(&netaddr, from);
12512 for (i = 0; i < zone->masterscnt; i++) {
12513 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
12514 break;
12515 if (zone->view->aclenv.match_mapped &&
12516 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
12517 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
12518 isc_netaddr_t na1, na2;
12519 isc_netaddr_fromv4mapped(&na1, &netaddr);
12520 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
12521 if (isc_netaddr_equal(&na1, &na2))
12522 break;
12527 * Accept notify requests from non masters if they are on
12528 * 'zone->notify_acl'.
12530 tsigkey = dns_message_gettsigkey(msg);
12531 tsig = dns_tsigkey_identity(tsigkey);
12532 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
12533 dns_acl_match(&netaddr, tsig, zone->notify_acl,
12534 &zone->view->aclenv,
12535 &match, NULL) == ISC_R_SUCCESS &&
12536 match > 0)
12538 /* Accept notify. */
12539 } else if (i >= zone->masterscnt) {
12540 UNLOCK_ZONE(zone);
12541 dns_zone_log(zone, ISC_LOG_INFO,
12542 "refused notify from non-master: %s", fromtext);
12543 inc_stats(zone, dns_zonestatscounter_notifyrej);
12544 return (DNS_R_REFUSED);
12548 * If the zone is loaded and there are answers check the serial
12549 * to see if we need to do a refresh. Do not worry about this
12550 * check if we are a dialup zone as we use the notify request
12551 * to trigger a refresh check.
12553 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
12554 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
12555 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
12556 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
12557 &zone->origin,
12558 dns_rdatatype_soa,
12559 dns_rdatatype_none, NULL,
12560 &rdataset);
12561 if (result == ISC_R_SUCCESS)
12562 result = dns_rdataset_first(rdataset);
12563 if (result == ISC_R_SUCCESS) {
12564 isc_uint32_t oldserial;
12565 unsigned int soacount;
12567 dns_rdataset_current(rdataset, &rdata);
12568 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12569 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12570 serial = soa.serial;
12571 have_serial = ISC_TRUE;
12573 * The following should safely be performed without DB
12574 * lock and succeed in this context.
12576 result = zone_get_from_db(zone, zone->db, NULL,
12577 &soacount, &oldserial, NULL,
12578 NULL, NULL, NULL, NULL);
12579 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12580 RUNTIME_CHECK(soacount > 0U);
12581 if (isc_serial_le(serial, oldserial)) {
12582 dns_zone_log(zone,
12583 ISC_LOG_INFO,
12584 "notify from %s: "
12585 "zone is up to date",
12586 fromtext);
12587 UNLOCK_ZONE(zone);
12588 return (ISC_R_SUCCESS);
12594 * If we got this far and there was a refresh in progress just
12595 * let it complete. Record where we got the notify from so we
12596 * can perform a refresh check when the current one completes
12598 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
12599 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12600 zone->notifyfrom = *from;
12601 UNLOCK_ZONE(zone);
12602 if (have_serial)
12603 dns_zone_log(zone, ISC_LOG_INFO,
12604 "notify from %s: serial %u: refresh in "
12605 "progress, refresh check queued",
12606 fromtext, serial);
12607 else
12608 dns_zone_log(zone, ISC_LOG_INFO,
12609 "notify from %s: refresh in progress, "
12610 "refresh check queued", fromtext);
12611 return (ISC_R_SUCCESS);
12613 if (have_serial)
12614 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
12615 fromtext, serial);
12616 else
12617 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
12618 fromtext);
12619 zone->notifyfrom = *from;
12620 local = zone->masteraddr;
12621 remote = zone->sourceaddr;
12622 UNLOCK_ZONE(zone);
12623 dns_zonemgr_unreachabledel(zone->zmgr, &local, &remote);
12624 dns_zone_refresh(zone);
12625 return (ISC_R_SUCCESS);
12628 void
12629 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
12631 REQUIRE(DNS_ZONE_VALID(zone));
12633 LOCK_ZONE(zone);
12634 if (zone->notify_acl != NULL)
12635 dns_acl_detach(&zone->notify_acl);
12636 dns_acl_attach(acl, &zone->notify_acl);
12637 UNLOCK_ZONE(zone);
12640 void
12641 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
12643 REQUIRE(DNS_ZONE_VALID(zone));
12645 LOCK_ZONE(zone);
12646 if (zone->query_acl != NULL)
12647 dns_acl_detach(&zone->query_acl);
12648 dns_acl_attach(acl, &zone->query_acl);
12649 UNLOCK_ZONE(zone);
12652 void
12653 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
12655 REQUIRE(DNS_ZONE_VALID(zone));
12657 LOCK_ZONE(zone);
12658 if (zone->queryon_acl != NULL)
12659 dns_acl_detach(&zone->queryon_acl);
12660 dns_acl_attach(acl, &zone->queryon_acl);
12661 UNLOCK_ZONE(zone);
12664 void
12665 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
12667 REQUIRE(DNS_ZONE_VALID(zone));
12669 LOCK_ZONE(zone);
12670 if (zone->update_acl != NULL)
12671 dns_acl_detach(&zone->update_acl);
12672 dns_acl_attach(acl, &zone->update_acl);
12673 UNLOCK_ZONE(zone);
12676 void
12677 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
12679 REQUIRE(DNS_ZONE_VALID(zone));
12681 LOCK_ZONE(zone);
12682 if (zone->forward_acl != NULL)
12683 dns_acl_detach(&zone->forward_acl);
12684 dns_acl_attach(acl, &zone->forward_acl);
12685 UNLOCK_ZONE(zone);
12688 void
12689 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
12691 REQUIRE(DNS_ZONE_VALID(zone));
12693 LOCK_ZONE(zone);
12694 if (zone->xfr_acl != NULL)
12695 dns_acl_detach(&zone->xfr_acl);
12696 dns_acl_attach(acl, &zone->xfr_acl);
12697 UNLOCK_ZONE(zone);
12700 dns_acl_t *
12701 dns_zone_getnotifyacl(dns_zone_t *zone) {
12703 REQUIRE(DNS_ZONE_VALID(zone));
12705 return (zone->notify_acl);
12708 dns_acl_t *
12709 dns_zone_getqueryacl(dns_zone_t *zone) {
12711 REQUIRE(DNS_ZONE_VALID(zone));
12713 return (zone->query_acl);
12716 dns_acl_t *
12717 dns_zone_getqueryonacl(dns_zone_t *zone) {
12719 REQUIRE(DNS_ZONE_VALID(zone));
12721 return (zone->queryon_acl);
12724 dns_acl_t *
12725 dns_zone_getupdateacl(dns_zone_t *zone) {
12727 REQUIRE(DNS_ZONE_VALID(zone));
12729 return (zone->update_acl);
12732 dns_acl_t *
12733 dns_zone_getforwardacl(dns_zone_t *zone) {
12735 REQUIRE(DNS_ZONE_VALID(zone));
12737 return (zone->forward_acl);
12740 dns_acl_t *
12741 dns_zone_getxfracl(dns_zone_t *zone) {
12743 REQUIRE(DNS_ZONE_VALID(zone));
12745 return (zone->xfr_acl);
12748 void
12749 dns_zone_clearupdateacl(dns_zone_t *zone) {
12751 REQUIRE(DNS_ZONE_VALID(zone));
12753 LOCK_ZONE(zone);
12754 if (zone->update_acl != NULL)
12755 dns_acl_detach(&zone->update_acl);
12756 UNLOCK_ZONE(zone);
12759 void
12760 dns_zone_clearforwardacl(dns_zone_t *zone) {
12762 REQUIRE(DNS_ZONE_VALID(zone));
12764 LOCK_ZONE(zone);
12765 if (zone->forward_acl != NULL)
12766 dns_acl_detach(&zone->forward_acl);
12767 UNLOCK_ZONE(zone);
12770 void
12771 dns_zone_clearnotifyacl(dns_zone_t *zone) {
12773 REQUIRE(DNS_ZONE_VALID(zone));
12775 LOCK_ZONE(zone);
12776 if (zone->notify_acl != NULL)
12777 dns_acl_detach(&zone->notify_acl);
12778 UNLOCK_ZONE(zone);
12781 void
12782 dns_zone_clearqueryacl(dns_zone_t *zone) {
12784 REQUIRE(DNS_ZONE_VALID(zone));
12786 LOCK_ZONE(zone);
12787 if (zone->query_acl != NULL)
12788 dns_acl_detach(&zone->query_acl);
12789 UNLOCK_ZONE(zone);
12792 void
12793 dns_zone_clearqueryonacl(dns_zone_t *zone) {
12795 REQUIRE(DNS_ZONE_VALID(zone));
12797 LOCK_ZONE(zone);
12798 if (zone->queryon_acl != NULL)
12799 dns_acl_detach(&zone->queryon_acl);
12800 UNLOCK_ZONE(zone);
12803 void
12804 dns_zone_clearxfracl(dns_zone_t *zone) {
12806 REQUIRE(DNS_ZONE_VALID(zone));
12808 LOCK_ZONE(zone);
12809 if (zone->xfr_acl != NULL)
12810 dns_acl_detach(&zone->xfr_acl);
12811 UNLOCK_ZONE(zone);
12814 isc_boolean_t
12815 dns_zone_getupdatedisabled(dns_zone_t *zone) {
12816 REQUIRE(DNS_ZONE_VALID(zone));
12817 return (zone->update_disabled);
12821 void
12822 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
12823 REQUIRE(DNS_ZONE_VALID(zone));
12824 zone->update_disabled = state;
12827 isc_boolean_t
12828 dns_zone_getzeronosoattl(dns_zone_t *zone) {
12829 REQUIRE(DNS_ZONE_VALID(zone));
12830 return (zone->zero_no_soa_ttl);
12834 void
12835 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
12836 REQUIRE(DNS_ZONE_VALID(zone));
12837 zone->zero_no_soa_ttl = state;
12840 void
12841 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
12843 REQUIRE(DNS_ZONE_VALID(zone));
12845 zone->check_names = severity;
12848 dns_severity_t
12849 dns_zone_getchecknames(dns_zone_t *zone) {
12851 REQUIRE(DNS_ZONE_VALID(zone));
12853 return (zone->check_names);
12856 void
12857 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
12859 REQUIRE(DNS_ZONE_VALID(zone));
12861 zone->journalsize = size;
12864 isc_int32_t
12865 dns_zone_getjournalsize(dns_zone_t *zone) {
12867 REQUIRE(DNS_ZONE_VALID(zone));
12869 return (zone->journalsize);
12872 static void
12873 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
12874 isc_result_t result = ISC_R_FAILURE;
12875 isc_buffer_t buffer;
12877 REQUIRE(buf != NULL);
12878 REQUIRE(length > 1U);
12881 * Leave space for terminating '\0'.
12883 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12884 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
12885 if (dns_name_dynamic(&zone->origin))
12886 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12887 if (result != ISC_R_SUCCESS &&
12888 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12889 isc_buffer_putstr(&buffer, "<UNKNOWN>");
12891 if (isc_buffer_availablelength(&buffer) > 0)
12892 isc_buffer_putstr(&buffer, "/");
12893 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12896 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
12897 strcmp(zone->view->name, "_default") != 0 &&
12898 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
12899 isc_buffer_putstr(&buffer, "/");
12900 isc_buffer_putstr(&buffer, zone->view->name);
12902 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
12903 isc_buffer_putstr(&buffer, " (signed)");
12904 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
12905 isc_buffer_putstr(&buffer, " (unsigned)");
12907 buf[isc_buffer_usedlength(&buffer)] = '\0';
12910 static void
12911 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
12912 isc_result_t result = ISC_R_FAILURE;
12913 isc_buffer_t buffer;
12915 REQUIRE(buf != NULL);
12916 REQUIRE(length > 1U);
12919 * Leave space for terminating '\0'.
12921 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12922 if (dns_name_dynamic(&zone->origin))
12923 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
12924 if (result != ISC_R_SUCCESS &&
12925 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
12926 isc_buffer_putstr(&buffer, "<UNKNOWN>");
12928 buf[isc_buffer_usedlength(&buffer)] = '\0';
12931 static void
12932 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
12933 isc_buffer_t buffer;
12935 REQUIRE(buf != NULL);
12936 REQUIRE(length > 1U);
12939 * Leave space for terminating '\0'.
12941 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12942 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
12944 buf[isc_buffer_usedlength(&buffer)] = '\0';
12947 static void
12948 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
12949 isc_buffer_t buffer;
12951 REQUIRE(buf != NULL);
12952 REQUIRE(length > 1U);
12956 * Leave space for terminating '\0'.
12958 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
12960 if (zone->view == NULL) {
12961 isc_buffer_putstr(&buffer, "_none");
12962 } else if (strlen(zone->view->name)
12963 < isc_buffer_availablelength(&buffer)) {
12964 isc_buffer_putstr(&buffer, zone->view->name);
12965 } else {
12966 isc_buffer_putstr(&buffer, "_toolong");
12969 buf[isc_buffer_usedlength(&buffer)] = '\0';
12972 void
12973 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
12974 REQUIRE(DNS_ZONE_VALID(zone));
12975 REQUIRE(buf != NULL);
12976 zone_namerd_tostr(zone, buf, length);
12979 static void
12980 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
12981 va_list ap;
12982 char message[4096];
12984 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
12985 return;
12987 va_start(ap, fmt);
12988 vsnprintf(message, sizeof(message), fmt, ap);
12989 va_end(ap);
12990 isc_log_write(dns_lctx, DNS_LOGCATEGORY_NOTIFY, DNS_LOGMODULE_ZONE,
12991 level, "zone %s: %s", zone->strnamerd, message);
12994 void
12995 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
12996 int level, const char *fmt, ...) {
12997 va_list ap;
12998 char message[4096];
13000 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
13001 return;
13003 va_start(ap, fmt);
13004 vsnprintf(message, sizeof(message), fmt, ap);
13005 va_end(ap);
13006 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE,
13007 level, "%s%s: %s", (zone->type == dns_zone_key) ?
13008 "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
13009 "redirect-zone" : "zone ", zone->strnamerd, message);
13012 void
13013 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
13014 va_list ap;
13015 char message[4096];
13017 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
13018 return;
13020 va_start(ap, fmt);
13021 vsnprintf(message, sizeof(message), fmt, ap);
13022 va_end(ap);
13023 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13024 level, "%s%s: %s", (zone->type == dns_zone_key) ?
13025 "managed-keys-zone" : (zone->type == dns_zone_redirect) ?
13026 "redirect-zone" : "zone ", zone->strnamerd, message);
13029 static void
13030 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
13031 const char *fmt, ...)
13033 va_list ap;
13034 char message[4096];
13035 int level = ISC_LOG_DEBUG(debuglevel);
13036 const char *zstr;
13038 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
13039 return;
13041 va_start(ap, fmt);
13042 vsnprintf(message, sizeof(message), fmt, ap);
13043 va_end(ap);
13045 switch (zone->type) {
13046 case dns_zone_key:
13047 zstr = "managed-keys-zone";
13048 break;
13049 case dns_zone_redirect:
13050 zstr = "redirect-zone";
13051 break;
13052 default:
13053 zstr = "zone";
13056 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
13057 level, "%s: %s %s: %s", me, zstr, zone->strnamerd,
13058 message);
13061 static int
13062 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
13064 isc_result_t result;
13065 dns_name_t *name;
13066 dns_rdataset_t *curr;
13067 int count = 0;
13069 result = dns_message_firstname(msg, section);
13070 while (result == ISC_R_SUCCESS) {
13071 name = NULL;
13072 dns_message_currentname(msg, section, &name);
13074 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
13075 curr = ISC_LIST_PREV(curr, link)) {
13076 if (curr->type == type)
13077 count++;
13079 result = dns_message_nextname(msg, section);
13082 return (count);
13085 void
13086 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
13087 REQUIRE(DNS_ZONE_VALID(zone));
13089 zone->maxxfrin = maxxfrin;
13092 isc_uint32_t
13093 dns_zone_getmaxxfrin(dns_zone_t *zone) {
13094 REQUIRE(DNS_ZONE_VALID(zone));
13096 return (zone->maxxfrin);
13099 void
13100 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
13101 REQUIRE(DNS_ZONE_VALID(zone));
13102 zone->maxxfrout = maxxfrout;
13105 isc_uint32_t
13106 dns_zone_getmaxxfrout(dns_zone_t *zone) {
13107 REQUIRE(DNS_ZONE_VALID(zone));
13109 return (zone->maxxfrout);
13112 dns_zonetype_t
13113 dns_zone_gettype(dns_zone_t *zone) {
13114 REQUIRE(DNS_ZONE_VALID(zone));
13116 return (zone->type);
13119 dns_name_t *
13120 dns_zone_getorigin(dns_zone_t *zone) {
13121 REQUIRE(DNS_ZONE_VALID(zone));
13123 return (&zone->origin);
13126 void
13127 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
13128 REQUIRE(DNS_ZONE_VALID(zone));
13130 LOCK_ZONE(zone);
13131 if (zone->task != NULL)
13132 isc_task_detach(&zone->task);
13133 isc_task_attach(task, &zone->task);
13134 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13135 if (zone->db != NULL)
13136 dns_db_settask(zone->db, zone->task);
13137 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13138 UNLOCK_ZONE(zone);
13141 void
13142 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
13143 REQUIRE(DNS_ZONE_VALID(zone));
13144 isc_task_attach(zone->task, target);
13147 void
13148 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
13149 REQUIRE(DNS_ZONE_VALID(zone));
13151 if (idlein == 0)
13152 idlein = DNS_DEFAULT_IDLEIN;
13153 zone->idlein = idlein;
13156 isc_uint32_t
13157 dns_zone_getidlein(dns_zone_t *zone) {
13158 REQUIRE(DNS_ZONE_VALID(zone));
13160 return (zone->idlein);
13163 void
13164 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
13165 REQUIRE(DNS_ZONE_VALID(zone));
13167 zone->idleout = idleout;
13170 isc_uint32_t
13171 dns_zone_getidleout(dns_zone_t *zone) {
13172 REQUIRE(DNS_ZONE_VALID(zone));
13174 return (zone->idleout);
13177 static void
13178 notify_done(isc_task_t *task, isc_event_t *event) {
13179 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13180 dns_notify_t *notify;
13181 isc_result_t result;
13182 dns_message_t *message = NULL;
13183 isc_buffer_t buf;
13184 char rcode[128];
13185 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
13187 UNUSED(task);
13189 notify = event->ev_arg;
13190 REQUIRE(DNS_NOTIFY_VALID(notify));
13191 INSIST(task == notify->zone->task);
13193 isc_buffer_init(&buf, rcode, sizeof(rcode));
13194 isc_sockaddr_format(&notify->dst, addrbuf, sizeof(addrbuf));
13196 result = revent->result;
13197 if (result == ISC_R_SUCCESS)
13198 result = dns_message_create(notify->zone->mctx,
13199 DNS_MESSAGE_INTENTPARSE, &message);
13200 if (result == ISC_R_SUCCESS)
13201 result = dns_request_getresponse(revent->request, message,
13202 DNS_MESSAGEPARSE_PRESERVEORDER);
13203 if (result == ISC_R_SUCCESS)
13204 result = dns_rcode_totext(message->rcode, &buf);
13205 if (result == ISC_R_SUCCESS)
13206 notify_log(notify->zone, ISC_LOG_DEBUG(3),
13207 "notify response from %s: %.*s",
13208 addrbuf, (int)buf.used, rcode);
13209 else
13210 notify_log(notify->zone, ISC_LOG_DEBUG(2),
13211 "notify to %s failed: %s", addrbuf,
13212 dns_result_totext(result));
13215 * Old bind's return formerr if they see a soa record. Retry w/o
13216 * the soa if we see a formerr and had sent a SOA.
13218 isc_event_free(&event);
13219 if (message != NULL && message->rcode == dns_rcode_formerr &&
13220 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
13221 isc_boolean_t startup;
13223 notify->flags |= DNS_NOTIFY_NOSOA;
13224 dns_request_destroy(&notify->request);
13225 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
13226 result = notify_send_queue(notify, startup);
13227 if (result != ISC_R_SUCCESS)
13228 notify_destroy(notify, ISC_FALSE);
13229 } else {
13230 if (result == ISC_R_TIMEDOUT)
13231 notify_log(notify->zone, ISC_LOG_DEBUG(1),
13232 "notify to %s: retries exceeded", addrbuf);
13233 notify_destroy(notify, ISC_FALSE);
13235 if (message != NULL)
13236 dns_message_destroy(&message);
13239 struct secure_event {
13240 isc_event_t e;
13241 dns_db_t *db;
13242 isc_uint32_t serial;
13245 static void
13246 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
13247 UNUSED(arg);
13248 dns_zone_log(zone, level, "%s", message);
13251 static isc_result_t
13252 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
13253 isc_uint32_t start, isc_uint32_t end,
13254 dns_difftuple_t **soatuplep, dns_diff_t *diff)
13256 isc_result_t result;
13257 dns_difftuple_t *tuple = NULL;
13258 dns_diffop_t op = DNS_DIFFOP_ADD;
13259 int n_soa = 0;
13261 REQUIRE(soatuplep != NULL);
13263 if (start == end)
13264 return (DNS_R_UNCHANGED);
13266 CHECK(dns_journal_iter_init(journal, start, end));
13267 for (result = dns_journal_first_rr(journal);
13268 result == ISC_R_SUCCESS;
13269 result = dns_journal_next_rr(journal))
13271 dns_name_t *name = NULL;
13272 isc_uint32_t ttl;
13273 dns_rdata_t *rdata = NULL;
13274 dns_journal_current_rr(journal, &name, &ttl, &rdata);
13276 if (rdata->type == dns_rdatatype_soa) {
13277 n_soa++;
13278 if (n_soa == 2) {
13280 * Save the latest raw SOA record.
13282 if (*soatuplep != NULL)
13283 dns_difftuple_free(soatuplep);
13284 CHECK(dns_difftuple_create(diff->mctx,
13285 DNS_DIFFOP_ADD,
13286 name, ttl, rdata,
13287 soatuplep));
13289 if (n_soa == 3)
13290 n_soa = 1;
13291 continue;
13294 /* Sanity. */
13295 if (n_soa == 0) {
13296 dns_zone_log(raw, ISC_LOG_ERROR,
13297 "corrupt journal file: '%s'\n",
13298 raw->journal);
13299 return (ISC_R_FAILURE);
13302 if (zone->privatetype != 0 &&
13303 rdata->type == zone->privatetype)
13304 continue;
13306 if (rdata->type == dns_rdatatype_nsec ||
13307 rdata->type == dns_rdatatype_rrsig ||
13308 rdata->type == dns_rdatatype_nsec3 ||
13309 rdata->type == dns_rdatatype_dnskey ||
13310 rdata->type == dns_rdatatype_nsec3param)
13311 continue;
13313 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
13315 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
13316 &tuple));
13317 dns_diff_appendminimal(diff, &tuple);
13319 if (result == ISC_R_NOMORE)
13320 result = ISC_R_SUCCESS;
13322 failure:
13323 return(result);
13326 static isc_result_t
13327 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
13328 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
13329 dns_diff_t *diff)
13331 isc_result_t result;
13332 dns_db_t *rawdb = NULL;
13333 dns_dbversion_t *rawver = NULL;
13334 dns_difftuple_t *tuple = NULL, *next;
13335 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
13336 dns_rdata_soa_t oldsoa, newsoa;
13338 REQUIRE(DNS_ZONE_VALID(seczone));
13339 REQUIRE(soatuple != NULL && *soatuple == NULL);
13341 if (!seczone->sourceserialset)
13342 return (DNS_R_UNCHANGED);
13344 dns_db_attach(raw->db, &rawdb);
13345 dns_db_currentversion(rawdb, &rawver);
13346 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
13347 dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
13348 dns_db_detach(&rawdb);
13350 if (result != ISC_R_SUCCESS)
13351 return (result);
13353 for (tuple = ISC_LIST_HEAD(diff->tuples);
13354 tuple != NULL;
13355 tuple = next)
13357 next = ISC_LIST_NEXT(tuple, link);
13358 if (tuple->rdata.type == dns_rdatatype_nsec ||
13359 tuple->rdata.type == dns_rdatatype_rrsig ||
13360 tuple->rdata.type == dns_rdatatype_dnskey ||
13361 tuple->rdata.type == dns_rdatatype_nsec3 ||
13362 tuple->rdata.type == dns_rdatatype_nsec3param)
13364 ISC_LIST_UNLINK(diff->tuples, tuple, link);
13365 dns_difftuple_free(&tuple);
13366 continue;
13368 if (tuple->rdata.type == dns_rdatatype_soa) {
13369 if (tuple->op == DNS_DIFFOP_DEL) {
13370 INSIST(oldtuple == NULL);
13371 oldtuple = tuple;
13373 if (tuple->op == DNS_DIFFOP_ADD) {
13374 INSIST(newtuple == NULL);
13375 newtuple = tuple;
13380 if (oldtuple != NULL && newtuple != NULL) {
13382 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
13383 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13385 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
13386 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13389 * If the SOA records are the same except for the serial
13390 * remove them from the diff.
13392 if (oldsoa.refresh == newsoa.refresh &&
13393 oldsoa.retry == newsoa.retry &&
13394 oldsoa.minimum == newsoa.minimum &&
13395 oldsoa.expire == newsoa.expire &&
13396 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
13397 dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
13398 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
13399 dns_difftuple_free(&oldtuple);
13400 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
13401 dns_difftuple_free(&newtuple);
13405 if (ISC_LIST_EMPTY(diff->tuples))
13406 return (DNS_R_UNCHANGED);
13409 * If there are still SOA records in the diff they can now be removed
13410 * saving the new SOA record.
13412 if (oldtuple != NULL) {
13413 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
13414 dns_difftuple_free(&oldtuple);
13417 if (newtuple != NULL) {
13418 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
13419 *soatuple = newtuple;
13422 return (ISC_R_SUCCESS);
13425 static void
13426 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
13427 static char me[] = "receive_secure_serial";
13428 isc_result_t result;
13429 dns_journal_t *rjournal = NULL;
13430 isc_uint32_t start, end;
13431 dns_zone_t *zone, *raw = NULL;
13432 dns_db_t *db = NULL;
13433 dns_dbversion_t *newver = NULL, *oldver = NULL;
13434 dns_diff_t diff;
13435 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
13436 dns_update_log_t log = { update_log_cb, NULL };
13437 isc_time_t timenow;
13439 zone = event->ev_arg;
13440 end = ((struct secure_event *)event)->serial;
13441 isc_event_free(&event);
13443 ENTER;
13445 LOCK_ZONE(zone);
13447 dns_diff_init(zone->mctx, &diff);
13449 UNUSED(task);
13451 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13452 if (zone->db != NULL)
13453 dns_db_attach(zone->db, &db);
13454 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13456 if (zone->raw != NULL)
13457 dns_zone_attach(zone->raw, &raw);
13458 UNLOCK_ZONE(zone);
13461 * zone->db may be NULL if the load from disk failed.
13463 if (db == NULL || raw == NULL) {
13464 result = ISC_R_FAILURE;
13465 goto failure;
13469 * We first attempt to sync the raw zone to the secure zone
13470 * by using the raw zone's journal, applying all the deltas
13471 * from the latest source-serial of the secure zone up to
13472 * the current serial number of the raw zone.
13474 * If that fails, then we'll fall back to a direct comparison
13475 * between raw and secure zones.
13477 result = dns_journal_open(raw->mctx, raw->journal,
13478 DNS_JOURNAL_WRITE, &rjournal);
13479 if (result != ISC_R_SUCCESS)
13480 goto failure;
13481 else {
13482 dns_journal_t *sjournal = NULL;
13484 result = dns_journal_open(zone->mctx, zone->journal,
13485 DNS_JOURNAL_READ, &sjournal);
13486 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
13487 goto failure;
13489 if (!dns_journal_get_sourceserial(rjournal, &start)) {
13490 start = dns_journal_first_serial(rjournal);
13491 dns_journal_set_sourceserial(rjournal, start);
13493 if (sjournal != NULL) {
13494 isc_uint32_t serial;
13496 * We read the secure journal first, if that exists
13497 * use its value provided it is greater that from the
13498 * raw journal.
13500 if (dns_journal_get_sourceserial(sjournal, &serial)) {
13501 if (isc_serial_gt(serial, start))
13502 start = serial;
13504 dns_journal_destroy(&sjournal);
13508 dns_db_currentversion(db, &oldver);
13509 CHECK(dns_db_newversion(db, &newver));
13512 * Try to apply diffs from the raw zone's journal to the secure
13513 * zone. If that fails, we recover by syncing up the databases
13514 * directly.
13516 result = sync_secure_journal(zone, raw, rjournal, start, end,
13517 &soatuple, &diff);
13518 if (result == DNS_R_UNCHANGED)
13519 goto failure;
13520 else if (result != ISC_R_SUCCESS)
13521 CHECK(sync_secure_db(zone, raw, db, oldver, &soatuple, &diff));
13523 CHECK(dns_diff_apply(&diff, db, newver));
13525 if (soatuple != NULL) {
13526 isc_uint32_t oldserial, newserial, desired;
13528 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
13529 DNS_DIFFOP_DEL, &tuple));
13530 oldserial = dns_soa_getserial(&tuple->rdata);
13531 newserial = desired = dns_soa_getserial(&soatuple->rdata);
13532 if (!isc_serial_gt(newserial, oldserial)) {
13533 newserial = oldserial + 1;
13534 if (newserial == 0)
13535 newserial++;
13536 dns_soa_setserial(newserial, &soatuple->rdata);
13538 CHECK(do_one_tuple(&tuple, db, newver, &diff));
13539 CHECK(do_one_tuple(&soatuple, db, newver, &diff));
13540 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
13541 newserial, desired);
13542 } else
13543 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
13544 zone->updatemethod));
13546 CHECK(dns_update_signatures(&log, zone, db, oldver, newver,
13547 &diff, zone->sigvalidityinterval));
13549 CHECK(zone_journal(zone, &diff, &end, "receive_secure_serial"));
13551 dns_journal_set_sourceserial(rjournal, end);
13552 dns_journal_commit(rjournal);
13554 LOCK_ZONE(zone);
13555 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
13557 zone->sourceserial = end;
13558 zone->sourceserialset = ISC_TRUE;
13559 zone_needdump(zone, DNS_DUMP_DELAY);
13561 TIME_NOW(&timenow);
13562 zone_settimer(zone, &timenow);
13563 UNLOCK_ZONE(zone);
13565 dns_db_closeversion(db, &oldver, ISC_FALSE);
13566 dns_db_closeversion(db, &newver, ISC_TRUE);
13568 failure:
13569 if (raw != NULL)
13570 dns_zone_detach(&raw);
13571 if (result != ISC_R_SUCCESS)
13572 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
13573 dns_result_totext(result));
13574 if (tuple != NULL)
13575 dns_difftuple_free(&tuple);
13576 if (soatuple != NULL)
13577 dns_difftuple_free(&soatuple);
13578 if (db != NULL) {
13579 if (oldver != NULL)
13580 dns_db_closeversion(db, &oldver, ISC_FALSE);
13581 if (newver != NULL)
13582 dns_db_closeversion(db, &newver, ISC_FALSE);
13583 dns_db_detach(&db);
13585 if (rjournal != NULL)
13586 dns_journal_destroy(&rjournal);
13587 dns_diff_clear(&diff);
13588 dns_zone_idetach(&zone);
13590 INSIST(oldver == NULL);
13591 INSIST(newver == NULL);
13594 static isc_result_t
13595 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
13596 isc_event_t *e;
13597 dns_zone_t *dummy = NULL;
13599 e = isc_event_allocate(zone->secure->mctx, zone,
13600 DNS_EVENT_ZONESECURESERIAL,
13601 receive_secure_serial, zone->secure,
13602 sizeof(struct secure_event));
13603 if (e == NULL)
13604 return (ISC_R_NOMEMORY);
13605 ((struct secure_event *)e)->serial = serial;
13606 INSIST(LOCKED_ZONE(zone->secure));
13607 zone_iattach(zone->secure, &dummy);
13608 isc_task_send(zone->secure->task, &e);
13610 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
13611 return (ISC_R_SUCCESS);
13614 static isc_result_t
13615 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
13616 dns_rdataset_t *rdataset, isc_uint32_t oldserial)
13618 dns_rdata_soa_t soa;
13619 dns_rdata_t rdata = DNS_RDATA_INIT;
13620 dns_rdatalist_t temprdatalist;
13621 dns_rdataset_t temprdataset;
13622 isc_buffer_t b;
13623 isc_result_t result;
13624 unsigned char buf[DNS_SOA_BUFFERSIZE];
13626 result = dns_rdataset_first(rdataset);
13627 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13628 dns_rdataset_current(rdataset, &rdata);
13629 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13630 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13632 if (isc_serial_gt(soa.serial, oldserial))
13633 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
13634 NULL));
13636 * Always bump the serial.
13638 oldserial++;
13639 if (oldserial == 0)
13640 oldserial++;
13641 soa.serial = oldserial;
13644 * Construct a replacement rdataset.
13646 dns_rdata_reset(&rdata);
13647 isc_buffer_init(&b, buf, sizeof(buf));
13648 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
13649 dns_rdatatype_soa, &soa, &b);
13650 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13651 temprdatalist.rdclass = rdata.rdclass;
13652 temprdatalist.type = rdata.type;
13653 temprdatalist.covers = 0;
13654 temprdatalist.ttl = rdataset->ttl;
13655 ISC_LIST_INIT(temprdatalist.rdata);
13656 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
13658 dns_rdataset_init(&temprdataset);
13659 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
13660 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13661 return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
13662 0, NULL));
13666 * This function should populate an nsec3paramlist_t with the
13667 * nsecparam_t data from a zone.
13669 static isc_result_t
13670 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
13671 isc_result_t result;
13672 dns_dbnode_t *node = NULL;
13673 dns_rdataset_t rdataset, prdataset;
13674 dns_dbversion_t *version = NULL;
13675 nsec3param_t *nsec3param = NULL;
13676 nsec3param_t *nsec3p = NULL;
13677 nsec3param_t *next;
13678 dns_db_t *db = NULL;
13679 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
13681 REQUIRE(DNS_ZONE_VALID(zone));
13682 REQUIRE(nsec3list != NULL);
13683 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
13685 dns_rdataset_init(&rdataset);
13686 dns_rdataset_init(&prdataset);
13688 dns_db_attach(zone->db, &db);
13689 CHECK(dns_db_getoriginnode(db, &node));
13691 dns_db_currentversion(db, &version);
13692 result = dns_db_findrdataset(db, node, version,
13693 dns_rdatatype_nsec3param,
13694 dns_rdatatype_none, 0, &rdataset, NULL);
13696 if (result != ISC_R_SUCCESS)
13697 goto getprivate;
13700 * walk nsec3param rdataset making a list of parameters (note that
13701 * multiple simultaneous nsec3 chains are annoyingly legal -- this
13702 * is why we use an nsec3list, even tho we will usually only have
13703 * one)
13705 for (result = dns_rdataset_first(&rdataset);
13706 result == ISC_R_SUCCESS;
13707 result = dns_rdataset_next(&rdataset))
13709 dns_rdata_t rdata = DNS_RDATA_INIT;
13710 dns_rdata_t private = DNS_RDATA_INIT;
13712 dns_rdataset_current(&rdataset, &rdata);
13713 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13714 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13715 "looping through nsec3param data");
13716 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13717 if (nsec3param == NULL)
13718 CHECK(ISC_R_NOMEMORY);
13719 ISC_LINK_INIT(nsec3param, link);
13722 * now transfer the data from the rdata to
13723 * the nsec3param
13725 dns_nsec3param_toprivate(&rdata, &private,
13726 zone->privatetype, nsec3param->data,
13727 sizeof(nsec3param->data));
13728 nsec3param->length = private.length;
13729 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13732 getprivate:
13733 result = dns_db_findrdataset(db, node, version, zone->privatetype,
13734 dns_rdatatype_none, 0, &prdataset, NULL);
13735 if (result != ISC_R_SUCCESS)
13736 goto done;
13739 * walk private type records, converting them to nsec3 parameters
13740 * using dns_nsec3param_fromprivate(), do the right thing based on
13741 * CREATE and REMOVE flags
13743 for (result = dns_rdataset_first(&prdataset);
13744 result == ISC_R_SUCCESS;
13745 result = dns_rdataset_next(&prdataset))
13747 dns_rdata_t rdata = DNS_RDATA_INIT;
13748 dns_rdata_t private = DNS_RDATA_INIT;
13750 dns_rdataset_current(&prdataset, &private);
13751 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
13752 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
13753 "looping through nsec3param private data");
13756 * Do we have a valid private record?
13758 if (!dns_nsec3param_fromprivate(&private, &rdata,
13759 buf, sizeof(buf)))
13760 continue;
13763 * Remove any NSEC3PARAM records scheduled to be removed.
13765 if (NSEC3REMOVE(rdata.data[1])) {
13767 * Zero out the flags.
13769 rdata.data[1] = 0;
13771 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13772 nsec3p != NULL;
13773 nsec3p = next)
13775 next = ISC_LIST_NEXT(nsec3p, link);
13777 if (nsec3p->length == rdata.length + 1 &&
13778 memcmp(rdata.data, nsec3p->data + 1,
13779 nsec3p->length - 1) == 0) {
13780 ISC_LIST_UNLINK(*nsec3list,
13781 nsec3p, link);
13782 isc_mem_put(zone->mctx, nsec3p,
13783 sizeof(nsec3param_t));
13786 continue;
13789 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
13790 if (nsec3param == NULL)
13791 CHECK(ISC_R_NOMEMORY);
13792 ISC_LINK_INIT(nsec3param, link);
13795 * Copy the remaining private records so the nsec/nsec3
13796 * chain gets created.
13798 INSIST(private.length <= sizeof(nsec3param->data));
13799 memmove(nsec3param->data, private.data, private.length);
13800 nsec3param->length = private.length;
13801 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
13804 done:
13805 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
13806 result = ISC_R_SUCCESS;
13808 failure:
13809 if (node != NULL)
13810 dns_db_detachnode(db, &node);
13811 if (version != NULL)
13812 dns_db_closeversion(db, &version, ISC_FALSE);
13813 if (db != NULL)
13814 dns_db_detach(&db);
13815 if (dns_rdataset_isassociated(&rdataset))
13816 dns_rdataset_disassociate(&rdataset);
13817 if (dns_rdataset_isassociated(&prdataset))
13818 dns_rdataset_disassociate(&prdataset);
13819 return (result);
13823 * Walk the list of the nsec3 chains desired for the zone, converting
13824 * parameters to private type records using dns_nsec3param_toprivate(),
13825 * and insert them into the new zone db.
13827 static isc_result_t
13828 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
13829 nsec3paramlist_t *nsec3list)
13831 isc_result_t result;
13832 dns_diff_t diff;
13833 dns_rdata_t rdata;
13834 nsec3param_t *nsec3p = NULL;
13835 nsec3param_t *next;
13837 REQUIRE(DNS_ZONE_VALID(zone));
13838 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
13840 dns_diff_init(zone->mctx, &diff);
13843 * Loop through the list of private-type records, set the INITIAL
13844 * and CREATE flags, and the add the record to the apex of the tree
13845 * in db.
13847 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13848 nsec3p != NULL;
13849 nsec3p = next)
13851 next = ISC_LIST_NEXT(nsec3p, link);
13852 dns_rdata_init(&rdata);
13853 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
13854 rdata.length = nsec3p->length;
13855 rdata.data = nsec3p->data;
13856 rdata.type = zone->privatetype;
13857 rdata.rdclass = zone->rdclass;
13858 CHECK(update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
13859 &zone->origin, 0, &rdata));
13862 result = ISC_R_SUCCESS;
13864 failure:
13865 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
13866 nsec3p != NULL;
13867 nsec3p = next)
13869 next = ISC_LIST_NEXT(nsec3p, link);
13870 ISC_LIST_UNLINK(*nsec3list, nsec3p, link);
13871 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
13874 dns_diff_clear(&diff);
13875 return (result);
13878 static void
13879 receive_secure_db(isc_task_t *task, isc_event_t *event) {
13880 isc_result_t result;
13881 dns_zone_t *zone;
13882 dns_db_t *rawdb, *db = NULL;
13883 dns_dbnode_t *rawnode = NULL, *node = NULL;
13884 dns_fixedname_t fname;
13885 dns_name_t *name;
13886 dns_dbiterator_t *dbiterator = NULL;
13887 dns_rdatasetiter_t *rdsit = NULL;
13888 dns_rdataset_t rdataset;
13889 dns_dbversion_t *version = NULL;
13890 isc_time_t loadtime;
13891 unsigned int oldserial = 0;
13892 isc_boolean_t have_oldserial = ISC_FALSE;
13893 nsec3paramlist_t nsec3list;
13895 UNUSED(task);
13897 ISC_LIST_INIT(nsec3list);
13899 zone = event->ev_arg;
13900 rawdb = ((struct secure_event *)event)->db;
13901 isc_event_free(&event);
13903 dns_fixedname_init(&fname);
13904 name = dns_fixedname_name(&fname);
13905 dns_rdataset_init(&rdataset);
13907 LOCK_ZONE(zone);
13908 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
13909 result = ISC_R_SHUTTINGDOWN;
13910 goto failure;
13913 TIME_NOW(&loadtime);
13914 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13915 if (zone->db != NULL) {
13916 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
13917 if (result == ISC_R_SUCCESS)
13918 have_oldserial = ISC_TRUE;
13921 * assemble nsec3parameters from the old zone, and set a flag
13922 * if any are found
13924 result = save_nsec3param(zone, &nsec3list);
13925 if (result != ISC_R_SUCCESS) {
13926 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13927 goto failure;
13930 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13932 result = dns_db_create(zone->mctx, zone->db_argv[0],
13933 &zone->origin, dns_dbtype_zone, zone->rdclass,
13934 zone->db_argc - 1, zone->db_argv + 1, &db);
13935 if (result != ISC_R_SUCCESS)
13936 goto failure;
13938 result = dns_db_newversion(db, &version);
13939 if (result != ISC_R_SUCCESS)
13940 goto failure;
13942 result = dns_db_createiterator(rawdb, 0, &dbiterator);
13943 if (result != ISC_R_SUCCESS)
13944 goto failure;
13946 for (result = dns_dbiterator_first(dbiterator);
13947 result == ISC_R_SUCCESS;
13948 result = dns_dbiterator_next(dbiterator)) {
13949 result = dns_dbiterator_current(dbiterator, &rawnode, name);
13950 if (result != ISC_R_SUCCESS)
13951 continue;
13953 result = dns_db_findnode(db, name, ISC_TRUE, &node);
13954 if (result != ISC_R_SUCCESS)
13955 goto failure;
13957 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
13958 if (result != ISC_R_SUCCESS)
13959 goto failure;
13961 for (result = dns_rdatasetiter_first(rdsit);
13962 result == ISC_R_SUCCESS;
13963 result = dns_rdatasetiter_next(rdsit)) {
13964 dns_rdatasetiter_current(rdsit, &rdataset);
13965 if (rdataset.type == dns_rdatatype_nsec ||
13966 rdataset.type == dns_rdatatype_rrsig ||
13967 rdataset.type == dns_rdatatype_nsec3 ||
13968 rdataset.type == dns_rdatatype_dnskey ||
13969 rdataset.type == dns_rdatatype_nsec3param) {
13970 dns_rdataset_disassociate(&rdataset);
13971 continue;
13973 if (rdataset.type == dns_rdatatype_soa &&
13974 have_oldserial) {
13975 result = checkandaddsoa(db, node, version,
13976 &rdataset, oldserial);
13977 } else
13978 result = dns_db_addrdataset(db, node, version,
13979 0, &rdataset, 0,
13980 NULL);
13981 if (result != ISC_R_SUCCESS)
13982 goto failure;
13984 dns_rdataset_disassociate(&rdataset);
13986 dns_rdatasetiter_destroy(&rdsit);
13987 dns_db_detachnode(rawdb, &rawnode);
13988 dns_db_detachnode(db, &node);
13992 * Call restore_nsec3param() to create private-type records from
13993 * the old nsec3 parameters and insert them into db
13995 if (!ISC_LIST_EMPTY(nsec3list))
13996 restore_nsec3param(zone, db, version, &nsec3list);
13998 dns_db_closeversion(db, &version, ISC_TRUE);
14001 * Lock hierarchy: zmgr, zone, raw.
14003 INSIST(zone != zone->raw);
14004 LOCK_ZONE(zone->raw);
14005 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14006 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14007 zone_needdump(zone, 0); /* XXXMPA */
14008 UNLOCK_ZONE(zone->raw);
14010 failure:
14011 UNLOCK_ZONE(zone);
14012 if (result != ISC_R_SUCCESS)
14013 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
14014 dns_result_totext(result));
14016 while (!ISC_LIST_EMPTY(nsec3list)) {
14017 nsec3param_t *nsec3p;
14018 nsec3p = ISC_LIST_HEAD(nsec3list);
14019 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
14020 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
14022 if (dns_rdataset_isassociated(&rdataset))
14023 dns_rdataset_disassociate(&rdataset);
14024 if (db != NULL) {
14025 if (node != NULL)
14026 dns_db_detachnode(db, &node);
14027 if (version != NULL)
14028 dns_db_closeversion(db, &version, ISC_FALSE);
14029 dns_db_detach(&db);
14031 if (rawnode != NULL)
14032 dns_db_detachnode(rawdb, &rawnode);
14033 dns_db_detach(&rawdb);
14034 if (dbiterator != NULL)
14035 dns_dbiterator_destroy(&dbiterator);
14036 dns_zone_idetach(&zone);
14038 INSIST(version == NULL);
14041 static isc_result_t
14042 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
14043 isc_event_t *e;
14044 dns_db_t *dummy = NULL;
14045 dns_zone_t *secure = NULL;
14047 e = isc_event_allocate(zone->secure->mctx, zone,
14048 DNS_EVENT_ZONESECUREDB,
14049 receive_secure_db, zone->secure,
14050 sizeof(struct secure_event));
14051 if (e == NULL)
14052 return (ISC_R_NOMEMORY);
14053 dns_db_attach(db, &dummy);
14054 ((struct secure_event *)e)->db = dummy;
14055 INSIST(LOCKED_ZONE(zone->secure));
14056 zone_iattach(zone->secure, &secure);
14057 isc_task_send(zone->secure->task, &e);
14058 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
14059 return (ISC_R_SUCCESS);
14062 isc_result_t
14063 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
14064 isc_result_t result;
14065 dns_zone_t *secure = NULL;
14067 REQUIRE(DNS_ZONE_VALID(zone));
14068 again:
14069 LOCK_ZONE(zone);
14070 if (inline_raw(zone)) {
14071 secure = zone->secure;
14072 INSIST(secure != zone);
14073 TRYLOCK_ZONE(result, secure);
14074 if (result != ISC_R_SUCCESS) {
14075 UNLOCK_ZONE(zone);
14076 secure = NULL;
14077 #if ISC_PLATFORM_USETHREADS
14078 isc_thread_yield();
14079 #endif
14080 goto again;
14083 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
14084 result = zone_replacedb(zone, db, dump);
14085 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
14086 if (secure != NULL)
14087 UNLOCK_ZONE(secure);
14088 UNLOCK_ZONE(zone);
14089 return (result);
14092 static isc_result_t
14093 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
14094 dns_dbversion_t *ver;
14095 isc_result_t result;
14096 unsigned int soacount = 0;
14097 unsigned int nscount = 0;
14100 * 'zone' and 'zonedb' locked by caller.
14102 REQUIRE(DNS_ZONE_VALID(zone));
14103 REQUIRE(LOCKED_ZONE(zone));
14104 if (inline_raw(zone))
14105 REQUIRE(LOCKED_ZONE(zone->secure));
14107 result = dns_db_rpz_ready(db);
14108 if (result != ISC_R_SUCCESS)
14109 return (result);
14111 result = zone_get_from_db(zone, db, &nscount, &soacount,
14112 NULL, NULL, NULL, NULL, NULL, NULL);
14113 if (result == ISC_R_SUCCESS) {
14114 if (soacount != 1) {
14115 dns_zone_log(zone, ISC_LOG_ERROR,
14116 "has %d SOA records", soacount);
14117 result = DNS_R_BADZONE;
14119 if (nscount == 0 && zone->type != dns_zone_key) {
14120 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
14121 result = DNS_R_BADZONE;
14123 if (result != ISC_R_SUCCESS)
14124 return (result);
14125 } else {
14126 dns_zone_log(zone, ISC_LOG_ERROR,
14127 "retrieving SOA and NS records failed: %s",
14128 dns_result_totext(result));
14129 return (result);
14132 result = check_nsec3param(zone, db);
14133 if (result != ISC_R_SUCCESS)
14134 return (result);
14136 ver = NULL;
14137 dns_db_currentversion(db, &ver);
14140 * The initial version of a slave zone is always dumped;
14141 * subsequent versions may be journaled instead if this
14142 * is enabled in the configuration.
14144 if (zone->db != NULL && zone->journal != NULL &&
14145 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
14146 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
14148 isc_uint32_t serial, oldserial;
14150 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
14152 result = dns_db_getsoaserial(db, ver, &serial);
14153 if (result != ISC_R_SUCCESS) {
14154 dns_zone_log(zone, ISC_LOG_ERROR,
14155 "ixfr-from-differences: unable to get "
14156 "new serial");
14157 goto fail;
14161 * This is checked in zone_postload() for master zones.
14163 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
14164 &oldserial, NULL, NULL, NULL, NULL,
14165 NULL);
14166 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14167 RUNTIME_CHECK(soacount > 0U);
14168 if ((zone->type == dns_zone_slave ||
14169 (zone->type == dns_zone_redirect &&
14170 zone->masters != NULL))
14171 && !isc_serial_gt(serial, oldserial)) {
14172 isc_uint32_t serialmin, serialmax;
14173 serialmin = (oldserial + 1) & 0xffffffffU;
14174 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
14175 dns_zone_log(zone, ISC_LOG_ERROR,
14176 "ixfr-from-differences: failed: "
14177 "new serial (%u) out of range [%u - %u]",
14178 serial, serialmin, serialmax);
14179 result = ISC_R_RANGE;
14180 goto fail;
14183 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
14184 zone->journal);
14185 if (result != ISC_R_SUCCESS)
14186 goto fail;
14187 if (dump)
14188 zone_needdump(zone, DNS_DUMP_DELAY);
14189 else if (zone->journalsize != -1) {
14190 result = dns_journal_compact(zone->mctx, zone->journal,
14191 serial, zone->journalsize);
14192 switch (result) {
14193 case ISC_R_SUCCESS:
14194 case ISC_R_NOSPACE:
14195 case ISC_R_NOTFOUND:
14196 dns_zone_log(zone, ISC_LOG_DEBUG(3),
14197 "dns_journal_compact: %s",
14198 dns_result_totext(result));
14199 break;
14200 default:
14201 dns_zone_log(zone, ISC_LOG_ERROR,
14202 "dns_journal_compact failed: %s",
14203 dns_result_totext(result));
14204 break;
14207 if (zone->type == dns_zone_master && inline_raw(zone))
14208 zone_send_secureserial(zone, serial);
14209 } else {
14210 if (dump && zone->masterfile != NULL) {
14212 * If DNS_ZONEFLG_FORCEXFER was set we don't want
14213 * to keep the old masterfile.
14215 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
14216 remove(zone->masterfile) < 0 && errno != ENOENT) {
14217 char strbuf[ISC_STRERRORSIZE];
14218 isc__strerror(errno, strbuf, sizeof(strbuf));
14219 isc_log_write(dns_lctx,
14220 DNS_LOGCATEGORY_GENERAL,
14221 DNS_LOGMODULE_ZONE,
14222 ISC_LOG_WARNING,
14223 "unable to remove masterfile "
14224 "'%s': '%s'",
14225 zone->masterfile, strbuf);
14227 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
14228 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
14229 else
14230 zone_needdump(zone, 0);
14232 if (dump && zone->journal != NULL) {
14234 * The in-memory database just changed, and
14235 * because 'dump' is set, it didn't change by
14236 * being loaded from disk. Also, we have not
14237 * journaled diffs for this change.
14238 * Therefore, the on-disk journal is missing
14239 * the deltas for this change. Since it can
14240 * no longer be used to bring the zone
14241 * up-to-date, it is useless and should be
14242 * removed.
14244 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14245 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14246 "removing journal file");
14247 if (remove(zone->journal) < 0 && errno != ENOENT) {
14248 char strbuf[ISC_STRERRORSIZE];
14249 isc__strerror(errno, strbuf, sizeof(strbuf));
14250 isc_log_write(dns_lctx,
14251 DNS_LOGCATEGORY_GENERAL,
14252 DNS_LOGMODULE_ZONE,
14253 ISC_LOG_WARNING,
14254 "unable to remove journal "
14255 "'%s': '%s'",
14256 zone->journal, strbuf);
14260 if (inline_raw(zone))
14261 zone_send_securedb(zone, db);
14264 dns_db_closeversion(db, &ver, ISC_FALSE);
14266 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
14268 if (zone->db != NULL)
14269 zone_detachdb(zone);
14270 zone_attachdb(zone, db);
14271 dns_db_settask(zone->db, zone->task);
14272 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
14273 return (ISC_R_SUCCESS);
14275 fail:
14276 dns_db_closeversion(db, &ver, ISC_FALSE);
14277 return (result);
14280 /* The caller must hold the dblock as a writer. */
14281 static inline void
14282 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
14283 REQUIRE(zone->db == NULL && db != NULL);
14285 dns_db_attach(db, &zone->db);
14286 if (zone->acache != NULL) {
14287 isc_result_t result;
14288 result = dns_acache_setdb(zone->acache, db);
14289 if (result != ISC_R_SUCCESS && result != ISC_R_EXISTS) {
14290 UNEXPECTED_ERROR(__FILE__, __LINE__,
14291 "dns_acache_setdb() failed: %s",
14292 isc_result_totext(result));
14297 /* The caller must hold the dblock as a writer. */
14298 static inline void
14299 zone_detachdb(dns_zone_t *zone) {
14300 REQUIRE(zone->db != NULL);
14302 if (zone->acache != NULL)
14303 (void)dns_acache_putdb(zone->acache, zone->db);
14304 dns_db_detach(&zone->db);
14307 static void
14308 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
14309 isc_time_t now;
14310 isc_boolean_t again = ISC_FALSE;
14311 unsigned int soacount;
14312 unsigned int nscount;
14313 isc_uint32_t serial, refresh, retry, expire, minimum;
14314 isc_result_t xfrresult = result;
14315 isc_boolean_t free_needed;
14316 dns_zone_t *secure = NULL;
14318 REQUIRE(DNS_ZONE_VALID(zone));
14320 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14321 "zone transfer finished: %s", dns_result_totext(result));
14324 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
14325 * could result in a deadlock due to a LOR so we will spin if we
14326 * can't obtain the both locks.
14328 again:
14329 LOCK_ZONE(zone);
14330 if (inline_raw(zone)) {
14331 secure = zone->secure;
14332 INSIST(secure != zone);
14333 TRYLOCK_ZONE(result, secure);
14334 if (result != ISC_R_SUCCESS) {
14335 UNLOCK_ZONE(zone);
14336 secure = NULL;
14337 #if ISC_PLATFORM_USETHREADS
14338 isc_thread_yield();
14339 #endif
14340 goto again;
14344 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
14345 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14346 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
14348 TIME_NOW(&now);
14349 switch (result) {
14350 case ISC_R_SUCCESS:
14351 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14352 /*FALLTHROUGH*/
14353 case DNS_R_UPTODATE:
14354 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
14356 * Has the zone expired underneath us?
14358 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14359 if (zone->db == NULL) {
14360 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14361 goto same_master;
14365 * Update the zone structure's data from the actual
14366 * SOA received.
14368 nscount = 0;
14369 soacount = 0;
14370 INSIST(zone->db != NULL);
14371 result = zone_get_from_db(zone, zone->db, &nscount,
14372 &soacount, &serial, &refresh,
14373 &retry, &expire, &minimum, NULL);
14374 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14375 if (result == ISC_R_SUCCESS) {
14376 if (soacount != 1)
14377 dns_zone_log(zone, ISC_LOG_ERROR,
14378 "transferred zone "
14379 "has %d SOA record%s", soacount,
14380 (soacount != 0) ? "s" : "");
14381 if (nscount == 0) {
14382 dns_zone_log(zone, ISC_LOG_ERROR,
14383 "transferred zone "
14384 "has no NS records");
14385 if (DNS_ZONE_FLAG(zone,
14386 DNS_ZONEFLG_HAVETIMERS)) {
14387 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
14388 zone->retry = DNS_ZONE_DEFAULTRETRY;
14390 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
14391 zone_unload(zone);
14392 goto next_master;
14394 zone->refresh = RANGE(refresh, zone->minrefresh,
14395 zone->maxrefresh);
14396 zone->retry = RANGE(retry, zone->minretry,
14397 zone->maxretry);
14398 zone->expire = RANGE(expire,
14399 zone->refresh + zone->retry,
14400 DNS_MAX_EXPIRE);
14401 zone->minimum = minimum;
14402 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
14406 * Set our next update/expire times.
14408 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
14409 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
14410 zone->refreshtime = now;
14411 DNS_ZONE_TIME_ADD(&now, zone->expire,
14412 &zone->expiretime);
14413 } else {
14414 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
14415 &zone->refreshtime);
14416 DNS_ZONE_TIME_ADD(&now, zone->expire,
14417 &zone->expiretime);
14419 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
14420 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
14421 if (zone->tsigkey != NULL) {
14422 char namebuf[DNS_NAME_FORMATSIZE];
14423 dns_name_format(&zone->tsigkey->name, namebuf,
14424 sizeof(namebuf));
14425 snprintf(buf, sizeof(buf), ": TSIG '%s'",
14426 namebuf);
14427 } else
14428 buf[0] = '\0';
14429 dns_zone_log(zone, ISC_LOG_INFO,
14430 "transferred serial %u%s",
14431 serial, buf);
14432 if (inline_raw(zone))
14433 zone_send_secureserial(zone, serial);
14437 * This is not necessary if we just performed a AXFR
14438 * however it is necessary for an IXFR / UPTODATE and
14439 * won't hurt with an AXFR.
14441 if (zone->masterfile != NULL || zone->journal != NULL) {
14442 unsigned int delay = DNS_DUMP_DELAY;
14444 result = ISC_R_FAILURE;
14445 if (zone->journal != NULL)
14446 result = isc_file_settime(zone->journal, &now);
14447 if (result != ISC_R_SUCCESS &&
14448 zone->masterfile != NULL)
14449 result = isc_file_settime(zone->masterfile,
14450 &now);
14452 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
14453 result == ISC_R_FILENOTFOUND)
14454 delay = 0;
14456 if ((result == ISC_R_SUCCESS ||
14457 result == ISC_R_FILENOTFOUND) &&
14458 zone->masterfile != NULL)
14459 zone_needdump(zone, delay);
14460 else if (result != ISC_R_SUCCESS)
14461 dns_zone_log(zone, ISC_LOG_ERROR,
14462 "transfer: could not set file "
14463 "modification time of '%s': %s",
14464 zone->masterfile,
14465 dns_result_totext(result));
14467 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
14468 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
14469 break;
14471 case DNS_R_BADIXFR:
14472 /* Force retry with AXFR. */
14473 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14474 goto same_master;
14476 default:
14477 next_master:
14479 * Skip to next failed / untried master.
14481 do {
14482 zone->curmaster++;
14483 } while (zone->curmaster < zone->masterscnt &&
14484 zone->mastersok[zone->curmaster]);
14485 /* FALLTHROUGH */
14486 same_master:
14487 if (zone->curmaster >= zone->masterscnt) {
14488 zone->curmaster = 0;
14489 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
14490 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14491 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14492 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14493 while (zone->curmaster < zone->masterscnt &&
14494 zone->mastersok[zone->curmaster])
14495 zone->curmaster++;
14496 again = ISC_TRUE;
14497 } else
14498 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
14499 } else {
14500 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
14501 again = ISC_TRUE;
14503 inc_stats(zone, dns_zonestatscounter_xfrfail);
14504 break;
14506 zone_settimer(zone, &now);
14509 * If creating the transfer object failed, zone->xfr is NULL.
14510 * Otherwise, we are called as the done callback of a zone
14511 * transfer object that just entered its shutting-down
14512 * state. Since we are no longer responsible for shutting
14513 * it down, we can detach our reference.
14515 if (zone->xfr != NULL)
14516 dns_xfrin_detach(&zone->xfr);
14518 if (zone->tsigkey != NULL)
14519 dns_tsigkey_detach(&zone->tsigkey);
14522 * Handle any deferred journal compaction.
14524 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
14525 result = dns_journal_compact(zone->mctx, zone->journal,
14526 zone->compact_serial,
14527 zone->journalsize);
14528 switch (result) {
14529 case ISC_R_SUCCESS:
14530 case ISC_R_NOSPACE:
14531 case ISC_R_NOTFOUND:
14532 dns_zone_log(zone, ISC_LOG_DEBUG(3),
14533 "dns_journal_compact: %s",
14534 dns_result_totext(result));
14535 break;
14536 default:
14537 dns_zone_log(zone, ISC_LOG_ERROR,
14538 "dns_journal_compact failed: %s",
14539 dns_result_totext(result));
14540 break;
14542 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
14545 if (secure != NULL)
14546 UNLOCK_ZONE(secure);
14548 * This transfer finishing freed up a transfer quota slot.
14549 * Let any other zones waiting for quota have it.
14551 if (zone->zmgr != NULL &&
14552 zone->statelist == &zone->zmgr->xfrin_in_progress) {
14553 UNLOCK_ZONE(zone);
14554 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14555 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
14556 zone->statelist = NULL;
14557 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
14558 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14559 LOCK_ZONE(zone);
14563 * Retry with a different server if necessary.
14565 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
14566 queue_soa_query(zone);
14568 INSIST(zone->irefs > 0);
14569 zone->irefs--;
14570 free_needed = exit_check(zone);
14571 UNLOCK_ZONE(zone);
14572 if (free_needed)
14573 zone_free(zone);
14576 static void
14577 zone_loaddone(void *arg, isc_result_t result) {
14578 static char me[] = "zone_loaddone";
14579 dns_load_t *load = arg;
14580 dns_zone_t *zone;
14581 isc_result_t tresult;
14582 dns_zone_t *secure = NULL;
14584 REQUIRE(DNS_LOAD_VALID(load));
14585 zone = load->zone;
14587 ENTER;
14589 tresult = dns_db_endload(load->db, &load->callbacks);
14590 if (tresult != ISC_R_SUCCESS &&
14591 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
14592 result = tresult;
14595 * Lock hierarchy: zmgr, zone, raw.
14597 again:
14598 LOCK_ZONE(zone);
14599 INSIST(zone != zone->raw);
14600 if (inline_secure(zone))
14601 LOCK_ZONE(zone->raw);
14602 else if (inline_raw(zone)) {
14603 secure = zone->secure;
14604 TRYLOCK_ZONE(result, secure);
14605 if (result != ISC_R_SUCCESS) {
14606 UNLOCK_ZONE(zone);
14607 secure = NULL;
14608 #if ISC_PLATFORM_USETHREADS
14609 isc_thread_yield();
14610 #endif
14611 goto again;
14614 (void)zone_postload(zone, load->db, load->loadtime, result);
14615 zonemgr_putio(&zone->readio);
14616 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
14617 zone_idetach(&load->callbacks.zone);
14619 * Leave the zone frozen if the reload fails.
14621 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
14622 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
14623 zone->update_disabled = ISC_FALSE;
14624 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
14625 if (inline_secure(zone))
14626 UNLOCK_ZONE(zone->raw);
14627 else if (secure != NULL)
14628 UNLOCK_ZONE(secure);
14629 UNLOCK_ZONE(zone);
14631 load->magic = 0;
14632 dns_db_detach(&load->db);
14633 if (load->zone->lctx != NULL)
14634 dns_loadctx_detach(&load->zone->lctx);
14635 dns_zone_idetach(&load->zone);
14636 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
14639 void
14640 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
14641 REQUIRE(DNS_ZONE_VALID(zone));
14642 REQUIRE(table != NULL);
14643 REQUIRE(*table == NULL);
14645 LOCK_ZONE(zone);
14646 if (zone->ssutable != NULL)
14647 dns_ssutable_attach(zone->ssutable, table);
14648 UNLOCK_ZONE(zone);
14651 void
14652 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
14653 REQUIRE(DNS_ZONE_VALID(zone));
14655 LOCK_ZONE(zone);
14656 if (zone->ssutable != NULL)
14657 dns_ssutable_detach(&zone->ssutable);
14658 if (table != NULL)
14659 dns_ssutable_attach(table, &zone->ssutable);
14660 UNLOCK_ZONE(zone);
14663 void
14664 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
14665 REQUIRE(DNS_ZONE_VALID(zone));
14667 zone->sigvalidityinterval = interval;
14670 isc_uint32_t
14671 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
14672 REQUIRE(DNS_ZONE_VALID(zone));
14674 return (zone->sigvalidityinterval);
14677 void
14678 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
14679 isc_time_t now;
14681 REQUIRE(DNS_ZONE_VALID(zone));
14683 LOCK_ZONE(zone);
14684 zone->sigresigninginterval = interval;
14685 set_resigntime(zone);
14686 if (zone->task != NULL) {
14687 TIME_NOW(&now);
14688 zone_settimer(zone, &now);
14690 UNLOCK_ZONE(zone);
14693 isc_uint32_t
14694 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
14695 REQUIRE(DNS_ZONE_VALID(zone));
14697 return (zone->sigresigninginterval);
14700 static void
14701 queue_xfrin(dns_zone_t *zone) {
14702 const char me[] = "queue_xfrin";
14703 isc_result_t result;
14704 dns_zonemgr_t *zmgr = zone->zmgr;
14706 ENTER;
14708 INSIST(zone->statelist == NULL);
14710 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14711 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
14712 LOCK_ZONE(zone);
14713 zone->irefs++;
14714 UNLOCK_ZONE(zone);
14715 zone->statelist = &zmgr->waiting_for_xfrin;
14716 result = zmgr_start_xfrin_ifquota(zmgr, zone);
14717 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
14719 if (result == ISC_R_QUOTA) {
14720 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
14721 "zone transfer deferred due to quota");
14722 } else if (result != ISC_R_SUCCESS) {
14723 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
14724 "starting zone transfer: %s",
14725 isc_result_totext(result));
14730 * This event callback is called when a zone has received
14731 * any necessary zone transfer quota. This is the time
14732 * to go ahead and start the transfer.
14734 static void
14735 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
14736 isc_result_t result = ISC_R_SUCCESS;
14737 dns_peer_t *peer = NULL;
14738 char master[ISC_SOCKADDR_FORMATSIZE];
14739 char source[ISC_SOCKADDR_FORMATSIZE];
14740 dns_rdatatype_t xfrtype;
14741 dns_zone_t *zone = event->ev_arg;
14742 isc_netaddr_t masterip;
14743 isc_sockaddr_t sourceaddr;
14744 isc_sockaddr_t masteraddr;
14745 isc_time_t now;
14746 const char *soa_before = "";
14747 isc_dscp_t dscp = -1;
14748 isc_boolean_t loaded;
14750 UNUSED(task);
14752 INSIST(task == zone->task);
14754 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14755 result = ISC_R_CANCELED;
14756 goto cleanup;
14759 TIME_NOW(&now);
14761 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
14762 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
14763 &zone->sourceaddr, &now))
14765 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
14766 dns_zone_log(zone, ISC_LOG_INFO,
14767 "got_transfer_quota: skipping zone transfer as "
14768 "master %s (source %s) is unreachable (cached)",
14769 master, source);
14770 result = ISC_R_CANCELED;
14771 goto cleanup;
14774 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14775 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
14777 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14778 soa_before = "SOA before ";
14780 * Decide whether we should request IXFR or AXFR.
14782 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14783 loaded = ISC_TF(zone->db != NULL);
14784 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14786 if (!loaded) {
14787 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14788 "no database exists yet, requesting AXFR of "
14789 "initial version from %s", master);
14790 xfrtype = dns_rdatatype_axfr;
14791 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
14792 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14793 "forced reload, requesting AXFR of "
14794 "initial version from %s", master);
14795 xfrtype = dns_rdatatype_axfr;
14796 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
14797 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14798 "retrying with AXFR from %s due to "
14799 "previous IXFR failure", master);
14800 xfrtype = dns_rdatatype_axfr;
14801 LOCK_ZONE(zone);
14802 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
14803 UNLOCK_ZONE(zone);
14804 } else {
14805 isc_boolean_t use_ixfr = ISC_TRUE;
14806 if (peer != NULL)
14807 result = dns_peer_getrequestixfr(peer, &use_ixfr);
14808 if (peer == NULL || result != ISC_R_SUCCESS)
14809 use_ixfr = zone->requestixfr;
14810 if (use_ixfr == ISC_FALSE) {
14811 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14812 "IXFR disabled, requesting %sAXFR from %s",
14813 soa_before, master);
14814 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
14815 xfrtype = dns_rdatatype_soa;
14816 else
14817 xfrtype = dns_rdatatype_axfr;
14818 } else {
14819 dns_zone_log(zone, ISC_LOG_DEBUG(1),
14820 "requesting IXFR from %s", master);
14821 xfrtype = dns_rdatatype_ixfr;
14826 * Determine if we should attempt to sign the request with TSIG.
14828 result = ISC_R_NOTFOUND;
14831 * First, look for a tsig key in the master statement, then
14832 * try for a server key.
14834 if ((zone->masterkeynames != NULL) &&
14835 (zone->masterkeynames[zone->curmaster] != NULL)) {
14836 dns_view_t *view = dns_zone_getview(zone);
14837 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14838 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
14840 if (zone->tsigkey == NULL)
14841 result = dns_view_getpeertsig(zone->view, &masterip,
14842 &zone->tsigkey);
14844 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14845 dns_zone_log(zone, ISC_LOG_ERROR,
14846 "could not get TSIG key for zone transfer: %s",
14847 isc_result_totext(result));
14850 if (zone->masterdscps != NULL)
14851 dscp = zone->masterdscps[zone->curmaster];
14853 LOCK_ZONE(zone);
14854 masteraddr = zone->masteraddr;
14855 sourceaddr = zone->sourceaddr;
14856 switch (isc_sockaddr_pf(&masteraddr)) {
14857 case PF_INET:
14858 if (dscp == -1)
14859 dscp = zone->xfrsource4dscp;
14860 break;
14861 case PF_INET6:
14862 if (dscp == -1)
14863 dscp = zone->xfrsource6dscp;
14864 break;
14865 default:
14866 INSIST(0);
14868 UNLOCK_ZONE(zone);
14869 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
14870 result = dns_xfrin_create3(zone, xfrtype, &masteraddr, &sourceaddr,
14871 dscp, zone->tsigkey, zone->mctx,
14872 zone->zmgr->timermgr, zone->zmgr->socketmgr,
14873 zone->task, zone_xfrdone, &zone->xfr);
14874 if (result == ISC_R_SUCCESS) {
14875 LOCK_ZONE(zone);
14876 if (xfrtype == dns_rdatatype_axfr) {
14877 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14878 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
14879 else
14880 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
14881 } else if (xfrtype == dns_rdatatype_ixfr) {
14882 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
14883 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
14884 else
14885 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
14887 UNLOCK_ZONE(zone);
14889 cleanup:
14891 * Any failure in this function is handled like a failed
14892 * zone transfer. This ensures that we get removed from
14893 * zmgr->xfrin_in_progress.
14895 if (result != ISC_R_SUCCESS)
14896 zone_xfrdone(zone, result);
14898 isc_event_free(&event);
14902 * Update forwarding support.
14905 static void
14906 forward_destroy(dns_forward_t *forward) {
14908 forward->magic = 0;
14909 if (forward->request != NULL)
14910 dns_request_destroy(&forward->request);
14911 if (forward->msgbuf != NULL)
14912 isc_buffer_free(&forward->msgbuf);
14913 if (forward->zone != NULL) {
14914 LOCK(&forward->zone->lock);
14915 if (ISC_LINK_LINKED(forward, link))
14916 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
14917 UNLOCK(&forward->zone->lock);
14918 dns_zone_idetach(&forward->zone);
14920 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
14923 static isc_result_t
14924 sendtomaster(dns_forward_t *forward) {
14925 isc_result_t result;
14926 isc_sockaddr_t src;
14927 isc_dscp_t dscp = -1;
14929 LOCK_ZONE(forward->zone);
14931 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
14932 UNLOCK_ZONE(forward->zone);
14933 return (ISC_R_CANCELED);
14936 if (forward->which >= forward->zone->masterscnt) {
14937 UNLOCK_ZONE(forward->zone);
14938 return (ISC_R_NOMORE);
14941 forward->addr = forward->zone->masters[forward->which];
14943 * Always use TCP regardless of whether the original update
14944 * used TCP.
14945 * XXX The timeout may but a bit small if we are far down a
14946 * transfer graph and the master has to try several masters.
14948 switch (isc_sockaddr_pf(&forward->addr)) {
14949 case PF_INET:
14950 src = forward->zone->xfrsource4;
14951 dscp = forward->zone->xfrsource4dscp;
14952 break;
14953 case PF_INET6:
14954 src = forward->zone->xfrsource6;
14955 dscp = forward->zone->xfrsource6dscp;
14956 break;
14957 default:
14958 result = ISC_R_NOTIMPLEMENTED;
14959 goto unlock;
14961 result = dns_request_createraw4(forward->zone->view->requestmgr,
14962 forward->msgbuf,
14963 &src, &forward->addr, dscp,
14964 forward->options, 15 /* XXX */,
14965 0, 0, forward->zone->task,
14966 forward_callback, forward,
14967 &forward->request);
14968 if (result == ISC_R_SUCCESS) {
14969 if (!ISC_LINK_LINKED(forward, link))
14970 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
14973 unlock:
14974 UNLOCK_ZONE(forward->zone);
14975 return (result);
14978 static void
14979 forward_callback(isc_task_t *task, isc_event_t *event) {
14980 const char me[] = "forward_callback";
14981 dns_requestevent_t *revent = (dns_requestevent_t *)event;
14982 dns_message_t *msg = NULL;
14983 char master[ISC_SOCKADDR_FORMATSIZE];
14984 isc_result_t result;
14985 dns_forward_t *forward;
14986 dns_zone_t *zone;
14988 UNUSED(task);
14990 forward = revent->ev_arg;
14991 INSIST(DNS_FORWARD_VALID(forward));
14992 zone = forward->zone;
14993 INSIST(DNS_ZONE_VALID(zone));
14995 ENTER;
14997 isc_sockaddr_format(&forward->addr, master, sizeof(master));
14999 if (revent->result != ISC_R_SUCCESS) {
15000 dns_zone_log(zone, ISC_LOG_INFO,
15001 "could not forward dynamic update to %s: %s",
15002 master, dns_result_totext(revent->result));
15003 goto next_master;
15006 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
15007 if (result != ISC_R_SUCCESS)
15008 goto next_master;
15010 result = dns_request_getresponse(revent->request, msg,
15011 DNS_MESSAGEPARSE_PRESERVEORDER |
15012 DNS_MESSAGEPARSE_CLONEBUFFER);
15013 if (result != ISC_R_SUCCESS)
15014 goto next_master;
15016 switch (msg->rcode) {
15018 * Pass these rcodes back to client.
15020 case dns_rcode_noerror:
15021 case dns_rcode_yxdomain:
15022 case dns_rcode_yxrrset:
15023 case dns_rcode_nxrrset:
15024 case dns_rcode_refused:
15025 case dns_rcode_nxdomain: {
15026 char rcode[128];
15027 isc_buffer_t rb;
15029 isc_buffer_init(&rb, rcode, sizeof(rcode));
15030 (void)dns_rcode_totext(msg->rcode, &rb);
15031 dns_zone_log(zone, ISC_LOG_INFO,
15032 "forwarded dynamic update: "
15033 "master %s returned: %.*s",
15034 master, (int)rb.used, rcode);
15035 break;
15038 /* These should not occur if the masters/zone are valid. */
15039 case dns_rcode_notzone:
15040 case dns_rcode_notauth: {
15041 char rcode[128];
15042 isc_buffer_t rb;
15044 isc_buffer_init(&rb, rcode, sizeof(rcode));
15045 (void)dns_rcode_totext(msg->rcode, &rb);
15046 dns_zone_log(zone, ISC_LOG_WARNING,
15047 "forwarding dynamic update: "
15048 "unexpected response: master %s returned: %.*s",
15049 master, (int)rb.used, rcode);
15050 goto next_master;
15053 /* Try another server for these rcodes. */
15054 case dns_rcode_formerr:
15055 case dns_rcode_servfail:
15056 case dns_rcode_notimp:
15057 case dns_rcode_badvers:
15058 default:
15059 goto next_master;
15062 /* call callback */
15063 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
15064 msg = NULL;
15065 dns_request_destroy(&forward->request);
15066 forward_destroy(forward);
15067 isc_event_free(&event);
15068 return;
15070 next_master:
15071 if (msg != NULL)
15072 dns_message_destroy(&msg);
15073 isc_event_free(&event);
15074 forward->which++;
15075 dns_request_destroy(&forward->request);
15076 result = sendtomaster(forward);
15077 if (result != ISC_R_SUCCESS) {
15078 /* call callback */
15079 dns_zone_log(zone, ISC_LOG_DEBUG(3),
15080 "exhausted dynamic update forwarder list");
15081 (forward->callback)(forward->callback_arg, result, NULL);
15082 forward_destroy(forward);
15086 isc_result_t
15087 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
15088 dns_updatecallback_t callback, void *callback_arg)
15090 dns_forward_t *forward;
15091 isc_result_t result;
15092 isc_region_t *mr;
15094 REQUIRE(DNS_ZONE_VALID(zone));
15095 REQUIRE(msg != NULL);
15096 REQUIRE(callback != NULL);
15098 forward = isc_mem_get(zone->mctx, sizeof(*forward));
15099 if (forward == NULL)
15100 return (ISC_R_NOMEMORY);
15102 forward->request = NULL;
15103 forward->zone = NULL;
15104 forward->msgbuf = NULL;
15105 forward->which = 0;
15106 forward->mctx = 0;
15107 forward->callback = callback;
15108 forward->callback_arg = callback_arg;
15109 ISC_LINK_INIT(forward, link);
15110 forward->magic = FORWARD_MAGIC;
15111 forward->options = DNS_REQUESTOPT_TCP;
15113 * If we have a SIG(0) signed message we need to preserve the
15114 * query id as that is included in the SIG(0) computation.
15116 if (msg->sig0 != NULL)
15117 forward->options |= DNS_REQUESTOPT_FIXEDID;
15119 mr = dns_message_getrawmessage(msg);
15120 if (mr == NULL) {
15121 result = ISC_R_UNEXPECTEDEND;
15122 goto cleanup;
15125 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
15126 if (result != ISC_R_SUCCESS)
15127 goto cleanup;
15128 result = isc_buffer_copyregion(forward->msgbuf, mr);
15129 if (result != ISC_R_SUCCESS)
15130 goto cleanup;
15132 isc_mem_attach(zone->mctx, &forward->mctx);
15133 dns_zone_iattach(zone, &forward->zone);
15134 result = sendtomaster(forward);
15136 cleanup:
15137 if (result != ISC_R_SUCCESS) {
15138 forward_destroy(forward);
15140 return (result);
15143 isc_result_t
15144 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
15145 REQUIRE(DNS_ZONE_VALID(zone));
15146 REQUIRE(next != NULL && *next == NULL);
15148 *next = ISC_LIST_NEXT(zone, link);
15149 if (*next == NULL)
15150 return (ISC_R_NOMORE);
15151 else
15152 return (ISC_R_SUCCESS);
15155 isc_result_t
15156 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
15157 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15158 REQUIRE(first != NULL && *first == NULL);
15160 *first = ISC_LIST_HEAD(zmgr->zones);
15161 if (*first == NULL)
15162 return (ISC_R_NOMORE);
15163 else
15164 return (ISC_R_SUCCESS);
15167 /***
15168 *** Zone manager.
15169 ***/
15171 isc_result_t
15172 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
15173 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
15174 dns_zonemgr_t **zmgrp)
15176 dns_zonemgr_t *zmgr;
15177 isc_result_t result;
15179 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
15180 if (zmgr == NULL)
15181 return (ISC_R_NOMEMORY);
15182 zmgr->mctx = NULL;
15183 zmgr->refs = 1;
15184 isc_mem_attach(mctx, &zmgr->mctx);
15185 zmgr->taskmgr = taskmgr;
15186 zmgr->timermgr = timermgr;
15187 zmgr->socketmgr = socketmgr;
15188 zmgr->zonetasks = NULL;
15189 zmgr->loadtasks = NULL;
15190 zmgr->mctxpool = NULL;
15191 zmgr->task = NULL;
15192 zmgr->notifyrl = NULL;
15193 zmgr->refreshrl = NULL;
15194 zmgr->startupnotifyrl = NULL;
15195 zmgr->startuprefreshrl = NULL;
15196 ISC_LIST_INIT(zmgr->zones);
15197 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
15198 ISC_LIST_INIT(zmgr->xfrin_in_progress);
15199 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
15200 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
15201 if (result != ISC_R_SUCCESS)
15202 goto free_mem;
15204 zmgr->transfersin = 10;
15205 zmgr->transfersperns = 2;
15207 /* Unreachable lock. */
15208 result = isc_rwlock_init(&zmgr->urlock, 0, 0);
15209 if (result != ISC_R_SUCCESS)
15210 goto free_rwlock;
15212 /* Create a single task for queueing of SOA queries. */
15213 result = isc_task_create(taskmgr, 1, &zmgr->task);
15214 if (result != ISC_R_SUCCESS)
15215 goto free_urlock;
15217 isc_task_setname(zmgr->task, "zmgr", zmgr);
15218 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15219 &zmgr->notifyrl);
15220 if (result != ISC_R_SUCCESS)
15221 goto free_task;
15223 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15224 &zmgr->refreshrl);
15225 if (result != ISC_R_SUCCESS)
15226 goto free_notifyrl;
15228 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15229 &zmgr->startupnotifyrl);
15230 if (result != ISC_R_SUCCESS)
15231 goto free_refreshrl;
15233 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
15234 &zmgr->startuprefreshrl);
15235 if (result != ISC_R_SUCCESS)
15236 goto free_startupnotifyrl;
15238 /* default to 20 refresh queries / notifies per second. */
15239 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
15240 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
15241 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
15242 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
15244 zmgr->iolimit = 1;
15245 zmgr->ioactive = 0;
15246 ISC_LIST_INIT(zmgr->high);
15247 ISC_LIST_INIT(zmgr->low);
15249 result = isc_mutex_init(&zmgr->iolock);
15250 if (result != ISC_R_SUCCESS)
15251 goto free_startuprefreshrl;
15253 zmgr->magic = ZONEMGR_MAGIC;
15255 *zmgrp = zmgr;
15256 return (ISC_R_SUCCESS);
15258 #if 0
15259 free_iolock:
15260 DESTROYLOCK(&zmgr->iolock);
15261 #endif
15262 free_startuprefreshrl:
15263 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
15264 free_startupnotifyrl:
15265 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
15266 free_refreshrl:
15267 isc_ratelimiter_detach(&zmgr->refreshrl);
15268 free_notifyrl:
15269 isc_ratelimiter_detach(&zmgr->notifyrl);
15270 free_task:
15271 isc_task_detach(&zmgr->task);
15272 free_urlock:
15273 isc_rwlock_destroy(&zmgr->urlock);
15274 free_rwlock:
15275 isc_rwlock_destroy(&zmgr->rwlock);
15276 free_mem:
15277 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
15278 isc_mem_detach(&mctx);
15279 return (result);
15282 isc_result_t
15283 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
15284 isc_result_t result;
15285 isc_mem_t *mctx = NULL;
15286 dns_zone_t *zone = NULL;
15287 void *item;
15289 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15290 REQUIRE(zonep != NULL && *zonep == NULL);
15292 if (zmgr->mctxpool == NULL)
15293 return (ISC_R_FAILURE);
15295 item = isc_pool_get(zmgr->mctxpool);
15296 if (item == NULL)
15297 return (ISC_R_FAILURE);
15299 isc_mem_attach((isc_mem_t *) item, &mctx);
15300 result = dns_zone_create(&zone, mctx);
15301 isc_mem_detach(&mctx);
15303 if (result == ISC_R_SUCCESS)
15304 *zonep = zone;
15306 return (result);
15309 isc_result_t
15310 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15311 isc_result_t result;
15313 REQUIRE(DNS_ZONE_VALID(zone));
15314 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15316 if (zmgr->zonetasks == NULL)
15317 return (ISC_R_FAILURE);
15319 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15320 LOCK_ZONE(zone);
15321 REQUIRE(zone->task == NULL);
15322 REQUIRE(zone->timer == NULL);
15323 REQUIRE(zone->zmgr == NULL);
15325 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
15326 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
15329 * Set the task name. The tag will arbitrarily point to one
15330 * of the zones sharing the task (in practice, the one
15331 * to be managed last).
15333 isc_task_setname(zone->task, "zone", zone);
15334 isc_task_setname(zone->loadtask, "loadzone", zone);
15336 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
15337 NULL, NULL,
15338 zone->task, zone_timer, zone,
15339 &zone->timer);
15341 if (result != ISC_R_SUCCESS)
15342 goto cleanup_tasks;
15345 * The timer "holds" a iref.
15347 zone->irefs++;
15348 INSIST(zone->irefs != 0);
15350 ISC_LIST_APPEND(zmgr->zones, zone, link);
15351 zone->zmgr = zmgr;
15352 zmgr->refs++;
15354 goto unlock;
15356 cleanup_tasks:
15357 isc_task_detach(&zone->loadtask);
15358 isc_task_detach(&zone->task);
15360 unlock:
15361 UNLOCK_ZONE(zone);
15362 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15363 return (result);
15366 void
15367 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15368 isc_boolean_t free_now = ISC_FALSE;
15370 REQUIRE(DNS_ZONE_VALID(zone));
15371 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15372 REQUIRE(zone->zmgr == zmgr);
15374 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15375 LOCK_ZONE(zone);
15377 ISC_LIST_UNLINK(zmgr->zones, zone, link);
15378 zone->zmgr = NULL;
15379 zmgr->refs--;
15380 if (zmgr->refs == 0)
15381 free_now = ISC_TRUE;
15383 UNLOCK_ZONE(zone);
15384 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15386 if (free_now)
15387 zonemgr_free(zmgr);
15388 ENSURE(zone->zmgr == NULL);
15391 void
15392 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
15393 REQUIRE(DNS_ZONEMGR_VALID(source));
15394 REQUIRE(target != NULL && *target == NULL);
15396 RWLOCK(&source->rwlock, isc_rwlocktype_write);
15397 REQUIRE(source->refs > 0);
15398 source->refs++;
15399 INSIST(source->refs > 0);
15400 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
15401 *target = source;
15404 void
15405 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
15406 dns_zonemgr_t *zmgr;
15407 isc_boolean_t free_now = ISC_FALSE;
15409 REQUIRE(zmgrp != NULL);
15410 zmgr = *zmgrp;
15411 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15413 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15414 zmgr->refs--;
15415 if (zmgr->refs == 0)
15416 free_now = ISC_TRUE;
15417 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15419 if (free_now)
15420 zonemgr_free(zmgr);
15421 *zmgrp = NULL;
15424 isc_result_t
15425 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
15426 dns_zone_t *p;
15428 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15430 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15431 for (p = ISC_LIST_HEAD(zmgr->zones);
15432 p != NULL;
15433 p = ISC_LIST_NEXT(p, link))
15435 dns_zone_maintenance(p);
15437 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15440 * Recent configuration changes may have increased the
15441 * amount of available transfers quota. Make sure any
15442 * transfers currently blocked on quota get started if
15443 * possible.
15445 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15446 zmgr_resume_xfrs(zmgr, ISC_TRUE);
15447 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15448 return (ISC_R_SUCCESS);
15451 void
15452 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
15454 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15456 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15457 zmgr_resume_xfrs(zmgr, ISC_TRUE);
15458 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15461 void
15462 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
15463 dns_zone_t *zone;
15465 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15467 isc_ratelimiter_shutdown(zmgr->notifyrl);
15468 isc_ratelimiter_shutdown(zmgr->refreshrl);
15469 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
15470 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
15472 if (zmgr->task != NULL)
15473 isc_task_destroy(&zmgr->task);
15474 if (zmgr->zonetasks != NULL)
15475 isc_taskpool_destroy(&zmgr->zonetasks);
15476 if (zmgr->loadtasks != NULL)
15477 isc_taskpool_destroy(&zmgr->loadtasks);
15478 if (zmgr->mctxpool != NULL)
15479 isc_pool_destroy(&zmgr->mctxpool);
15481 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15482 for (zone = ISC_LIST_HEAD(zmgr->zones);
15483 zone != NULL;
15484 zone = ISC_LIST_NEXT(zone, link))
15486 LOCK_ZONE(zone);
15487 forward_cancel(zone);
15488 UNLOCK_ZONE(zone);
15490 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
15493 static isc_result_t
15494 mctxinit(void **target, void *arg) {
15495 isc_result_t result;
15496 isc_mem_t *mctx = NULL;
15498 UNUSED(arg);
15500 REQUIRE(target != NULL && *target == NULL);
15502 result = isc_mem_create(0, 0, &mctx);
15503 if (result != ISC_R_SUCCESS)
15504 return (result);
15505 isc_mem_setname(mctx, "zonemgr-pool", NULL);
15507 *target = mctx;
15508 return (ISC_R_SUCCESS);
15511 static void
15512 mctxfree(void **target) {
15513 isc_mem_t *mctx = *(isc_mem_t **) target;
15514 isc_mem_detach(&mctx);
15515 *target = NULL;
15518 #define ZONES_PER_TASK 100
15519 #define ZONES_PER_MCTX 1000
15521 isc_result_t
15522 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
15523 isc_result_t result;
15524 int ntasks = num_zones / ZONES_PER_TASK;
15525 int nmctx = num_zones / ZONES_PER_MCTX;
15526 isc_taskpool_t *pool = NULL;
15527 isc_pool_t *mctxpool = NULL;
15529 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15532 * For anything fewer than 1000 zones we use 10 tasks in
15533 * the task pools. More than that, and we'll scale at one
15534 * task per 100 zones. Similarly, for anything smaller than
15535 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
15537 if (ntasks < 10)
15538 ntasks = 10;
15539 if (nmctx < 2)
15540 nmctx = 2;
15542 /* Create or resize the zone task pools. */
15543 if (zmgr->zonetasks == NULL)
15544 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15545 ntasks, 2, &pool);
15546 else
15547 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
15549 if (result == ISC_R_SUCCESS)
15550 zmgr->zonetasks = pool;
15552 pool = NULL;
15553 if (zmgr->loadtasks == NULL)
15554 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
15555 ntasks, 2, &pool);
15556 else
15557 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
15559 if (result == ISC_R_SUCCESS)
15560 zmgr->loadtasks = pool;
15563 * We always set all tasks in the zone-load task pool to
15564 * privileged. This prevents other tasks in the system from
15565 * running while the server task manager is in privileged
15566 * mode.
15568 * NOTE: If we start using task privileges for any other
15569 * part of the system than zone tasks, then this will need to be
15570 * revisted. In that case we'd want to turn on privileges for
15571 * zone tasks only when we were loading, and turn them off the
15572 * rest of the time. For now, however, it's okay to just
15573 * set it and forget it.
15575 isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
15577 /* Create or resize the zone memory context pool. */
15578 if (zmgr->mctxpool == NULL)
15579 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
15580 mctxinit, NULL, &mctxpool);
15581 else
15582 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
15584 if (result == ISC_R_SUCCESS)
15585 zmgr->mctxpool = mctxpool;
15587 return (result);
15590 static void
15591 zonemgr_free(dns_zonemgr_t *zmgr) {
15592 isc_mem_t *mctx;
15594 INSIST(zmgr->refs == 0);
15595 INSIST(ISC_LIST_EMPTY(zmgr->zones));
15597 zmgr->magic = 0;
15599 DESTROYLOCK(&zmgr->iolock);
15600 isc_ratelimiter_detach(&zmgr->notifyrl);
15601 isc_ratelimiter_detach(&zmgr->refreshrl);
15602 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
15603 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
15605 isc_rwlock_destroy(&zmgr->urlock);
15606 isc_rwlock_destroy(&zmgr->rwlock);
15607 mctx = zmgr->mctx;
15608 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
15609 isc_mem_detach(&mctx);
15612 void
15613 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15614 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15616 zmgr->transfersin = value;
15619 isc_uint32_t
15620 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
15621 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15623 return (zmgr->transfersin);
15626 void
15627 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
15628 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15630 zmgr->transfersperns = value;
15633 isc_uint32_t
15634 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
15635 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15637 return (zmgr->transfersperns);
15641 * Try to start a new incoming zone transfer to fill a quota
15642 * slot that was just vacated.
15644 * Requires:
15645 * The zone manager is locked by the caller.
15647 static void
15648 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
15649 dns_zone_t *zone;
15650 dns_zone_t *next;
15652 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
15653 zone != NULL;
15654 zone = next)
15656 isc_result_t result;
15657 next = ISC_LIST_NEXT(zone, statelink);
15658 result = zmgr_start_xfrin_ifquota(zmgr, zone);
15659 if (result == ISC_R_SUCCESS) {
15660 if (multi)
15661 continue;
15663 * We successfully filled the slot. We're done.
15665 break;
15666 } else if (result == ISC_R_QUOTA) {
15668 * Not enough quota. This is probably the per-server
15669 * quota, because we usually get called when a unit of
15670 * global quota has just been freed. Try the next
15671 * zone, it may succeed if it uses another master.
15673 continue;
15674 } else {
15675 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15676 "starting zone transfer: %s",
15677 isc_result_totext(result));
15678 break;
15684 * Try to start an incoming zone transfer for 'zone', quota permitting.
15686 * Requires:
15687 * The zone manager is locked by the caller.
15689 * Returns:
15690 * ISC_R_SUCCESS There was enough quota and we attempted to
15691 * start a transfer. zone_xfrdone() has been or will
15692 * be called.
15693 * ISC_R_QUOTA Not enough quota.
15694 * Others Failure.
15696 static isc_result_t
15697 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
15698 dns_peer_t *peer = NULL;
15699 isc_netaddr_t masterip;
15700 isc_uint32_t nxfrsin, nxfrsperns;
15701 dns_zone_t *x;
15702 isc_uint32_t maxtransfersin, maxtransfersperns;
15703 isc_event_t *e;
15706 * If we are exiting just pretend we got quota so the zone will
15707 * be cleaned up in the zone's task context.
15709 LOCK_ZONE(zone);
15710 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15711 UNLOCK_ZONE(zone);
15712 goto gotquota;
15716 * Find any configured information about the server we'd
15717 * like to transfer this zone from.
15719 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15720 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15721 UNLOCK_ZONE(zone);
15724 * Determine the total maximum number of simultaneous
15725 * transfers allowed, and the maximum for this specific
15726 * master.
15728 maxtransfersin = zmgr->transfersin;
15729 maxtransfersperns = zmgr->transfersperns;
15730 if (peer != NULL)
15731 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
15734 * Count the total number of transfers that are in progress,
15735 * and the number of transfers in progress from this master.
15736 * We linearly scan a list of all transfers; if this turns
15737 * out to be too slow, we could hash on the master address.
15739 nxfrsin = nxfrsperns = 0;
15740 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
15741 x != NULL;
15742 x = ISC_LIST_NEXT(x, statelink))
15744 isc_netaddr_t xip;
15746 LOCK_ZONE(x);
15747 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
15748 UNLOCK_ZONE(x);
15750 nxfrsin++;
15751 if (isc_netaddr_equal(&xip, &masterip))
15752 nxfrsperns++;
15755 /* Enforce quota. */
15756 if (nxfrsin >= maxtransfersin)
15757 return (ISC_R_QUOTA);
15759 if (nxfrsperns >= maxtransfersperns)
15760 return (ISC_R_QUOTA);
15762 gotquota:
15764 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
15765 * list and send it an event to let it start the actual transfer in the
15766 * context of its own task.
15768 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
15769 got_transfer_quota, zone, sizeof(isc_event_t));
15770 if (e == NULL)
15771 return (ISC_R_NOMEMORY);
15773 LOCK_ZONE(zone);
15774 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
15775 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
15776 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
15777 zone->statelist = &zmgr->xfrin_in_progress;
15778 isc_task_send(zone->task, &e);
15779 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
15780 UNLOCK_ZONE(zone);
15782 return (ISC_R_SUCCESS);
15785 void
15786 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
15788 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15789 REQUIRE(iolimit > 0);
15791 zmgr->iolimit = iolimit;
15794 isc_uint32_t
15795 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
15797 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15799 return (zmgr->iolimit);
15803 * Get permission to request a file handle from the OS.
15804 * An event will be sent to action when one is available.
15805 * There are two queues available (high and low), the high
15806 * queue will be serviced before the low one.
15808 * zonemgr_putio() must be called after the event is delivered to
15809 * 'action'.
15812 static isc_result_t
15813 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
15814 isc_task_t *task, isc_taskaction_t action, void *arg,
15815 dns_io_t **iop)
15817 dns_io_t *io;
15818 isc_boolean_t queue;
15820 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
15821 REQUIRE(iop != NULL && *iop == NULL);
15823 io = isc_mem_get(zmgr->mctx, sizeof(*io));
15824 if (io == NULL)
15825 return (ISC_R_NOMEMORY);
15827 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
15828 action, arg, sizeof(*io->event));
15829 if (io->event == NULL) {
15830 isc_mem_put(zmgr->mctx, io, sizeof(*io));
15831 return (ISC_R_NOMEMORY);
15834 io->zmgr = zmgr;
15835 io->high = high;
15836 io->task = NULL;
15837 isc_task_attach(task, &io->task);
15838 ISC_LINK_INIT(io, link);
15839 io->magic = IO_MAGIC;
15841 LOCK(&zmgr->iolock);
15842 zmgr->ioactive++;
15843 queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
15844 if (queue) {
15845 if (io->high)
15846 ISC_LIST_APPEND(zmgr->high, io, link);
15847 else
15848 ISC_LIST_APPEND(zmgr->low, io, link);
15850 UNLOCK(&zmgr->iolock);
15851 *iop = io;
15853 if (!queue)
15854 isc_task_send(io->task, &io->event);
15855 return (ISC_R_SUCCESS);
15858 static void
15859 zonemgr_putio(dns_io_t **iop) {
15860 dns_io_t *io;
15861 dns_io_t *next;
15862 dns_zonemgr_t *zmgr;
15864 REQUIRE(iop != NULL);
15865 io = *iop;
15866 REQUIRE(DNS_IO_VALID(io));
15868 *iop = NULL;
15870 INSIST(!ISC_LINK_LINKED(io, link));
15871 INSIST(io->event == NULL);
15873 zmgr = io->zmgr;
15874 isc_task_detach(&io->task);
15875 io->magic = 0;
15876 isc_mem_put(zmgr->mctx, io, sizeof(*io));
15878 LOCK(&zmgr->iolock);
15879 INSIST(zmgr->ioactive > 0);
15880 zmgr->ioactive--;
15881 next = HEAD(zmgr->high);
15882 if (next == NULL)
15883 next = HEAD(zmgr->low);
15884 if (next != NULL) {
15885 if (next->high)
15886 ISC_LIST_UNLINK(zmgr->high, next, link);
15887 else
15888 ISC_LIST_UNLINK(zmgr->low, next, link);
15889 INSIST(next->event != NULL);
15891 UNLOCK(&zmgr->iolock);
15892 if (next != NULL)
15893 isc_task_send(next->task, &next->event);
15896 static void
15897 zonemgr_cancelio(dns_io_t *io) {
15898 isc_boolean_t send_event = ISC_FALSE;
15900 REQUIRE(DNS_IO_VALID(io));
15903 * If we are queued to be run then dequeue.
15905 LOCK(&io->zmgr->iolock);
15906 if (ISC_LINK_LINKED(io, link)) {
15907 if (io->high)
15908 ISC_LIST_UNLINK(io->zmgr->high, io, link);
15909 else
15910 ISC_LIST_UNLINK(io->zmgr->low, io, link);
15912 send_event = ISC_TRUE;
15913 INSIST(io->event != NULL);
15915 UNLOCK(&io->zmgr->iolock);
15916 if (send_event) {
15917 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
15918 isc_task_send(io->task, &io->event);
15922 static void
15923 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
15924 char *buf;
15925 int buflen;
15926 isc_result_t result;
15928 buflen = strlen(path) + strlen(templat) + 2;
15930 buf = isc_mem_get(zone->mctx, buflen);
15931 if (buf == NULL)
15932 return;
15934 result = isc_file_template(path, templat, buf, buflen);
15935 if (result != ISC_R_SUCCESS)
15936 goto cleanup;
15938 result = isc_file_renameunique(path, buf);
15939 if (result != ISC_R_SUCCESS)
15940 goto cleanup;
15942 dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
15943 "renaming file to '%s' for failure analysis and "
15944 "retransferring.", path, buf);
15946 cleanup:
15947 isc_mem_put(zone->mctx, buf, buflen);
15950 #if 0
15951 /* Hook for ondestroy notification from a database. */
15953 static void
15954 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
15955 dns_db_t *db = event->sender;
15956 UNUSED(task);
15958 isc_event_free(&event);
15960 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15961 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15962 "database (%p) destroyed", (void*) db);
15964 #endif
15966 static void
15967 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
15968 isc_interval_t interval;
15969 isc_uint32_t s, ns;
15970 isc_uint32_t pertic;
15971 isc_result_t result;
15973 if (value == 0)
15974 value = 1;
15976 if (value == 1) {
15977 s = 1;
15978 ns = 0;
15979 pertic = 1;
15980 } else if (value <= 10) {
15981 s = 0;
15982 ns = 1000000000 / value;
15983 pertic = 1;
15984 } else {
15985 s = 0;
15986 ns = (1000000000 / value) * 10;
15987 pertic = 10;
15990 isc_interval_set(&interval, s, ns);
15992 result = isc_ratelimiter_setinterval(rl, &interval);
15993 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15994 isc_ratelimiter_setpertic(rl, pertic);
15996 *rate = value;
15999 void
16000 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
16002 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16004 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
16006 /* Seperately controlled in BIND 9.11.x */
16007 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
16008 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
16010 /* XXXMPA seperate out once we have the code to support this. */
16011 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
16014 unsigned int
16015 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
16016 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16018 return (zmgr->serialqueryrate);
16021 isc_boolean_t
16022 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16023 isc_sockaddr_t *local, isc_time_t *now)
16025 unsigned int i;
16026 isc_rwlocktype_t locktype;
16027 isc_result_t result;
16028 isc_uint32_t seconds = isc_time_seconds(now);
16029 isc_uint32_t count = 0;
16031 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16033 locktype = isc_rwlocktype_read;
16034 RWLOCK(&zmgr->urlock, locktype);
16035 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16036 if (zmgr->unreachable[i].expire >= seconds &&
16037 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16038 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
16039 result = isc_rwlock_tryupgrade(&zmgr->urlock);
16040 if (result == ISC_R_SUCCESS) {
16041 locktype = isc_rwlocktype_write;
16042 zmgr->unreachable[i].last = seconds;
16043 count = zmgr->unreachable[i].count;
16045 break;
16048 RWUNLOCK(&zmgr->urlock, locktype);
16049 return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
16052 void
16053 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16054 isc_sockaddr_t *local)
16056 unsigned int i;
16057 isc_rwlocktype_t locktype;
16058 isc_result_t result;
16060 char master[ISC_SOCKADDR_FORMATSIZE];
16061 char source[ISC_SOCKADDR_FORMATSIZE];
16063 isc_sockaddr_format(remote, master, sizeof(master));
16064 isc_sockaddr_format(local, source, sizeof(source));
16066 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16068 locktype = isc_rwlocktype_read;
16069 RWLOCK(&zmgr->urlock, locktype);
16070 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16071 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16072 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
16073 if (zmgr->unreachable[i].expire == 0)
16074 break;
16075 result = isc_rwlock_tryupgrade(&zmgr->urlock);
16076 if (result == ISC_R_SUCCESS) {
16077 locktype = isc_rwlocktype_write;
16078 zmgr->unreachable[i].expire = 0;
16079 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16080 DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
16081 "master %s (source %s) deleted "
16082 "from unreachable cache",
16083 master, source);
16085 break;
16088 RWUNLOCK(&zmgr->urlock, locktype);
16091 void
16092 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16093 isc_sockaddr_t *local, isc_time_t *now)
16095 isc_uint32_t seconds = isc_time_seconds(now);
16096 isc_uint32_t last = seconds;
16097 unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
16099 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16101 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
16102 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16103 /* Existing entry? */
16104 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16105 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
16106 break;
16107 /* Empty slot? */
16108 if (zmgr->unreachable[i].expire < seconds)
16109 slot = i;
16110 /* Least recently used slot? */
16111 if (zmgr->unreachable[i].last < last) {
16112 last = zmgr->unreachable[i].last;
16113 oldest = i;
16116 if (i < UNREACH_CHACHE_SIZE) {
16118 * Found a existing entry. Update the expire timer and
16119 * last usage timestamps.
16121 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
16122 zmgr->unreachable[i].last = seconds;
16123 if (zmgr->unreachable[i].expire < seconds)
16124 zmgr->unreachable[i].count = 1;
16125 else
16126 zmgr->unreachable[i].count++;
16127 } else if (slot != UNREACH_CHACHE_SIZE) {
16129 * Found a empty slot. Add a new entry to the cache.
16131 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
16132 zmgr->unreachable[slot].last = seconds;
16133 zmgr->unreachable[slot].remote = *remote;
16134 zmgr->unreachable[slot].local = *local;
16135 zmgr->unreachable[slot].count = 1;
16136 } else {
16138 * Replace the least recently used entry in the cache.
16140 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
16141 zmgr->unreachable[oldest].last = seconds;
16142 zmgr->unreachable[oldest].remote = *remote;
16143 zmgr->unreachable[oldest].local = *local;
16144 zmgr->unreachable[oldest].count = 1;
16146 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
16149 void
16150 dns_zone_forcereload(dns_zone_t *zone) {
16151 REQUIRE(DNS_ZONE_VALID(zone));
16153 if (zone->type == dns_zone_master ||
16154 (zone->type == dns_zone_redirect && zone->masters == NULL))
16155 return;
16157 LOCK_ZONE(zone);
16158 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
16159 UNLOCK_ZONE(zone);
16160 dns_zone_refresh(zone);
16163 isc_boolean_t
16164 dns_zone_isforced(dns_zone_t *zone) {
16165 REQUIRE(DNS_ZONE_VALID(zone));
16167 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
16170 isc_result_t
16171 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
16173 * This function is obsoleted.
16175 UNUSED(zone);
16176 UNUSED(on);
16177 return (ISC_R_NOTIMPLEMENTED);
16180 isc_uint64_t *
16181 dns_zone_getstatscounters(dns_zone_t *zone) {
16183 * This function is obsoleted.
16185 UNUSED(zone);
16186 return (NULL);
16189 void
16190 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
16191 REQUIRE(DNS_ZONE_VALID(zone));
16192 REQUIRE(zone->stats == NULL);
16194 LOCK_ZONE(zone);
16195 zone->stats = NULL;
16196 isc_stats_attach(stats, &zone->stats);
16197 UNLOCK_ZONE(zone);
16200 void
16201 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
16203 REQUIRE(DNS_ZONE_VALID(zone));
16205 LOCK_ZONE(zone);
16206 if (zone->requeststats_on && stats == NULL)
16207 zone->requeststats_on = ISC_FALSE;
16208 else if (!zone->requeststats_on && stats != NULL) {
16209 if (zone->requeststats == NULL) {
16210 isc_stats_attach(stats, &zone->requeststats);
16211 zone->requeststats_on = ISC_TRUE;
16214 UNLOCK_ZONE(zone);
16217 void
16218 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
16220 REQUIRE(DNS_ZONE_VALID(zone));
16222 LOCK_ZONE(zone);
16223 if (zone->requeststats_on && stats != NULL) {
16224 if (zone->rcvquerystats == NULL) {
16225 dns_stats_attach(stats, &zone->rcvquerystats);
16226 zone->requeststats_on = ISC_TRUE;
16229 UNLOCK_ZONE(zone);
16232 isc_stats_t *
16233 dns_zone_getrequeststats(dns_zone_t *zone) {
16235 * We don't lock zone for efficiency reason. This is not catastrophic
16236 * because requeststats must always be valid when requeststats_on is
16237 * true.
16238 * Some counters may be incremented while requeststats_on is becoming
16239 * false, or some cannot be incremented just after the statistics are
16240 * installed, but it shouldn't matter much in practice.
16242 if (zone->requeststats_on)
16243 return (zone->requeststats);
16244 else
16245 return (NULL);
16249 * Return the received query stats bucket
16250 * see note from dns_zone_getrequeststats()
16252 dns_stats_t *
16253 dns_zone_getrcvquerystats(dns_zone_t *zone) {
16254 if (zone->requeststats_on)
16255 return (zone->rcvquerystats);
16256 else
16257 return (NULL);
16260 void
16261 dns_zone_dialup(dns_zone_t *zone) {
16263 REQUIRE(DNS_ZONE_VALID(zone));
16265 zone_debuglog(zone, "dns_zone_dialup", 3,
16266 "notify = %d, refresh = %d",
16267 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
16268 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
16270 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
16271 dns_zone_notify(zone);
16272 if (zone->type != dns_zone_master && zone->masters != NULL &&
16273 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
16274 dns_zone_refresh(zone);
16277 void
16278 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
16279 REQUIRE(DNS_ZONE_VALID(zone));
16281 LOCK_ZONE(zone);
16282 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
16283 DNS_ZONEFLG_DIALREFRESH |
16284 DNS_ZONEFLG_NOREFRESH);
16285 switch (dialup) {
16286 case dns_dialuptype_no:
16287 break;
16288 case dns_dialuptype_yes:
16289 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
16290 DNS_ZONEFLG_DIALREFRESH |
16291 DNS_ZONEFLG_NOREFRESH));
16292 break;
16293 case dns_dialuptype_notify:
16294 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
16295 break;
16296 case dns_dialuptype_notifypassive:
16297 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
16298 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
16299 break;
16300 case dns_dialuptype_refresh:
16301 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
16302 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
16303 break;
16304 case dns_dialuptype_passive:
16305 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
16306 break;
16307 default:
16308 INSIST(0);
16310 UNLOCK_ZONE(zone);
16313 isc_result_t
16314 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
16315 isc_result_t result = ISC_R_SUCCESS;
16317 REQUIRE(DNS_ZONE_VALID(zone));
16319 LOCK_ZONE(zone);
16320 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
16321 UNLOCK_ZONE(zone);
16323 return (result);
16326 const char *
16327 dns_zone_getkeydirectory(dns_zone_t *zone) {
16328 REQUIRE(DNS_ZONE_VALID(zone));
16330 return (zone->keydirectory);
16333 unsigned int
16334 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
16335 dns_zone_t *zone;
16336 unsigned int count = 0;
16338 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16340 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16341 switch (state) {
16342 case DNS_ZONESTATE_XFERRUNNING:
16343 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
16344 zone != NULL;
16345 zone = ISC_LIST_NEXT(zone, statelink))
16346 count++;
16347 break;
16348 case DNS_ZONESTATE_XFERDEFERRED:
16349 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
16350 zone != NULL;
16351 zone = ISC_LIST_NEXT(zone, statelink))
16352 count++;
16353 break;
16354 case DNS_ZONESTATE_SOAQUERY:
16355 for (zone = ISC_LIST_HEAD(zmgr->zones);
16356 zone != NULL;
16357 zone = ISC_LIST_NEXT(zone, link))
16358 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
16359 count++;
16360 break;
16361 case DNS_ZONESTATE_ANY:
16362 for (zone = ISC_LIST_HEAD(zmgr->zones);
16363 zone != NULL;
16364 zone = ISC_LIST_NEXT(zone, link)) {
16365 dns_view_t *view = zone->view;
16366 if (view != NULL && strcmp(view->name, "_bind") == 0)
16367 continue;
16368 count++;
16370 break;
16371 default:
16372 INSIST(0);
16375 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16377 return (count);
16380 isc_result_t
16381 dns_zone_checknames(dns_zone_t *zone, dns_name_t *name, dns_rdata_t *rdata) {
16382 isc_boolean_t ok = ISC_TRUE;
16383 isc_boolean_t fail = ISC_FALSE;
16384 char namebuf[DNS_NAME_FORMATSIZE];
16385 char namebuf2[DNS_NAME_FORMATSIZE];
16386 char typebuf[DNS_RDATATYPE_FORMATSIZE];
16387 int level = ISC_LOG_WARNING;
16388 dns_name_t bad;
16390 REQUIRE(DNS_ZONE_VALID(zone));
16392 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
16393 rdata->type != dns_rdatatype_nsec3)
16394 return (ISC_R_SUCCESS);
16396 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
16397 rdata->type == dns_rdatatype_nsec3) {
16398 level = ISC_LOG_ERROR;
16399 fail = ISC_TRUE;
16402 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
16403 if (!ok) {
16404 dns_name_format(name, namebuf, sizeof(namebuf));
16405 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
16406 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
16407 dns_result_totext(DNS_R_BADOWNERNAME));
16408 if (fail)
16409 return (DNS_R_BADOWNERNAME);
16412 dns_name_init(&bad, NULL);
16413 ok = dns_rdata_checknames(rdata, name, &bad);
16414 if (!ok) {
16415 dns_name_format(name, namebuf, sizeof(namebuf));
16416 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
16417 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
16418 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
16419 namebuf2, dns_result_totext(DNS_R_BADNAME));
16420 if (fail)
16421 return (DNS_R_BADNAME);
16424 return (ISC_R_SUCCESS);
16427 void
16428 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
16429 REQUIRE(DNS_ZONE_VALID(zone));
16430 zone->checkmx = checkmx;
16433 void
16434 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
16435 REQUIRE(DNS_ZONE_VALID(zone));
16436 zone->checksrv = checksrv;
16439 void
16440 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
16441 REQUIRE(DNS_ZONE_VALID(zone));
16442 zone->checkns = checkns;
16445 void
16446 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
16447 REQUIRE(DNS_ZONE_VALID(zone));
16449 LOCK_ZONE(zone);
16450 zone->isself = isself;
16451 zone->isselfarg = arg;
16452 UNLOCK_ZONE(zone);
16455 void
16456 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
16457 REQUIRE(DNS_ZONE_VALID(zone));
16459 LOCK_ZONE(zone);
16460 zone->notifydelay = delay;
16461 UNLOCK_ZONE(zone);
16464 isc_uint32_t
16465 dns_zone_getnotifydelay(dns_zone_t *zone) {
16466 REQUIRE(DNS_ZONE_VALID(zone));
16468 return (zone->notifydelay);
16471 isc_result_t
16472 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
16473 isc_uint16_t keyid, isc_boolean_t delete)
16475 isc_result_t result;
16476 REQUIRE(DNS_ZONE_VALID(zone));
16478 dns_zone_log(zone, ISC_LOG_NOTICE,
16479 "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
16480 algorithm, keyid);
16481 LOCK_ZONE(zone);
16482 result = zone_signwithkey(zone, algorithm, keyid, delete);
16483 UNLOCK_ZONE(zone);
16485 return (result);
16488 static const char *hex = "0123456789ABCDEF";
16490 isc_result_t
16491 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
16492 isc_result_t result;
16493 char salt[255*2+1];
16494 unsigned int i, j;
16496 REQUIRE(DNS_ZONE_VALID(zone));
16498 if (nsec3param->salt_length != 0) {
16499 INSIST((nsec3param->salt_length * 2U) < sizeof(salt));
16500 for (i = 0, j = 0; i < nsec3param->salt_length; i++) {
16501 salt[j++] = hex[(nsec3param->salt[i] >> 4) & 0xf];
16502 salt[j++] = hex[nsec3param->salt[i] & 0xf];
16504 salt[j] = '\0';
16505 } else
16506 strcpy(salt, "-");
16507 dns_zone_log(zone, ISC_LOG_NOTICE,
16508 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
16509 nsec3param->hash, nsec3param->iterations,
16510 salt);
16511 LOCK_ZONE(zone);
16512 result = zone_addnsec3chain(zone, nsec3param);
16513 UNLOCK_ZONE(zone);
16515 return (result);
16518 void
16519 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
16520 REQUIRE(DNS_ZONE_VALID(zone));
16522 if (nodes == 0)
16523 nodes = 1;
16524 zone->nodes = nodes;
16527 void
16528 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
16529 REQUIRE(DNS_ZONE_VALID(zone));
16532 * We treat signatures as a signed value so explicitly
16533 * limit its range here.
16535 if (signatures > ISC_INT32_MAX)
16536 signatures = ISC_INT32_MAX;
16537 else if (signatures == 0)
16538 signatures = 1;
16539 zone->signatures = signatures;
16542 void
16543 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
16544 REQUIRE(DNS_ZONE_VALID(zone));
16545 zone->privatetype = type;
16548 dns_rdatatype_t
16549 dns_zone_getprivatetype(dns_zone_t *zone) {
16550 REQUIRE(DNS_ZONE_VALID(zone));
16551 return (zone->privatetype);
16554 static isc_result_t
16555 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
16556 isc_boolean_t delete)
16558 dns_signing_t *signing;
16559 dns_signing_t *current;
16560 isc_result_t result = ISC_R_SUCCESS;
16561 isc_time_t now;
16562 dns_db_t *db = NULL;
16564 signing = isc_mem_get(zone->mctx, sizeof *signing);
16565 if (signing == NULL)
16566 return (ISC_R_NOMEMORY);
16568 signing->magic = 0;
16569 signing->db = NULL;
16570 signing->dbiterator = NULL;
16571 signing->algorithm = algorithm;
16572 signing->keyid = keyid;
16573 signing->delete = delete;
16574 signing->done = ISC_FALSE;
16576 TIME_NOW(&now);
16578 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16579 if (zone->db != NULL)
16580 dns_db_attach(zone->db, &db);
16581 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16583 if (db == NULL) {
16584 result = ISC_R_NOTFOUND;
16585 goto cleanup;
16588 dns_db_attach(db, &signing->db);
16590 for (current = ISC_LIST_HEAD(zone->signing);
16591 current != NULL;
16592 current = ISC_LIST_NEXT(current, link)) {
16593 if (current->db == signing->db &&
16594 current->algorithm == signing->algorithm &&
16595 current->keyid == signing->keyid) {
16596 if (current->delete != signing->delete)
16597 current->done = ISC_TRUE;
16598 else
16599 goto cleanup;
16603 result = dns_db_createiterator(signing->db, 0,
16604 &signing->dbiterator);
16606 if (result == ISC_R_SUCCESS)
16607 result = dns_dbiterator_first(signing->dbiterator);
16608 if (result == ISC_R_SUCCESS) {
16609 dns_dbiterator_pause(signing->dbiterator);
16610 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
16611 signing = NULL;
16612 if (isc_time_isepoch(&zone->signingtime)) {
16613 zone->signingtime = now;
16614 if (zone->task != NULL)
16615 zone_settimer(zone, &now);
16619 cleanup:
16620 if (signing != NULL) {
16621 if (signing->db != NULL)
16622 dns_db_detach(&signing->db);
16623 if (signing->dbiterator != NULL)
16624 dns_dbiterator_destroy(&signing->dbiterator);
16625 isc_mem_put(zone->mctx, signing, sizeof *signing);
16627 if (db != NULL)
16628 dns_db_detach(&db);
16629 return (result);
16632 static void
16633 logmsg(const char *format, ...) {
16634 va_list args;
16635 va_start(args, format);
16636 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
16637 ISC_LOG_DEBUG(1), format, args);
16638 va_end(args);
16641 static void
16642 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
16643 dns_dnsseckey_t *key;
16644 while (!ISC_LIST_EMPTY(*list)) {
16645 key = ISC_LIST_HEAD(*list);
16646 ISC_LIST_UNLINK(*list, key, link);
16647 dns_dnsseckey_destroy(mctx, &key);
16651 /* Called once; *timep should be set to the current time. */
16652 static isc_result_t
16653 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
16654 isc_result_t result;
16655 isc_stdtime_t now, then = 0, event;
16656 int i;
16658 now = *timep;
16660 for (i = 0; i <= DST_MAX_TIMES; i++) {
16661 result = dst_key_gettime(key, i, &event);
16662 if (result == ISC_R_SUCCESS && event > now &&
16663 (then == 0 || event < then))
16664 then = event;
16667 if (then != 0) {
16668 *timep = then;
16669 return (ISC_R_SUCCESS);
16672 return (ISC_R_NOTFOUND);
16675 static isc_result_t
16676 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
16677 const dns_rdata_t *rdata, isc_boolean_t *flag)
16679 dns_rdataset_t rdataset;
16680 dns_dbnode_t *node = NULL;
16681 isc_result_t result;
16683 dns_rdataset_init(&rdataset);
16684 if (rdata->type == dns_rdatatype_nsec3)
16685 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
16686 else
16687 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
16688 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
16689 (isc_stdtime_t) 0, &rdataset, NULL);
16690 if (result == ISC_R_NOTFOUND) {
16691 *flag = ISC_FALSE;
16692 result = ISC_R_SUCCESS;
16693 goto failure;
16696 for (result = dns_rdataset_first(&rdataset);
16697 result == ISC_R_SUCCESS;
16698 result = dns_rdataset_next(&rdataset)) {
16699 dns_rdata_t myrdata = DNS_RDATA_INIT;
16700 dns_rdataset_current(&rdataset, &myrdata);
16701 if (!dns_rdata_compare(&myrdata, rdata))
16702 break;
16704 dns_rdataset_disassociate(&rdataset);
16705 if (result == ISC_R_SUCCESS) {
16706 *flag = ISC_TRUE;
16707 } else if (result == ISC_R_NOMORE) {
16708 *flag = ISC_FALSE;
16709 result = ISC_R_SUCCESS;
16712 failure:
16713 if (node != NULL)
16714 dns_db_detachnode(db, &node);
16715 return (result);
16719 * Add records to signal the state of signing or of key removal.
16721 static isc_result_t
16722 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
16723 dns_dbversion_t *ver, dns_diff_t *diff,
16724 isc_boolean_t sign_all)
16726 dns_difftuple_t *tuple, *newtuple = NULL;
16727 dns_rdata_dnskey_t dnskey;
16728 dns_rdata_t rdata = DNS_RDATA_INIT;
16729 isc_boolean_t flag;
16730 isc_region_t r;
16731 isc_result_t result = ISC_R_SUCCESS;
16732 isc_uint16_t keyid;
16733 unsigned char buf[5];
16734 dns_name_t *name = dns_db_origin(db);
16736 for (tuple = ISC_LIST_HEAD(diff->tuples);
16737 tuple != NULL;
16738 tuple = ISC_LIST_NEXT(tuple, link)) {
16739 if (tuple->rdata.type != dns_rdatatype_dnskey)
16740 continue;
16742 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
16743 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16744 if ((dnskey.flags &
16745 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
16746 != DNS_KEYOWNER_ZONE)
16747 continue;
16749 dns_rdata_toregion(&tuple->rdata, &r);
16751 keyid = dst_region_computeid(&r, dnskey.algorithm);
16753 buf[0] = dnskey.algorithm;
16754 buf[1] = (keyid & 0xff00) >> 8;
16755 buf[2] = (keyid & 0xff);
16756 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
16757 buf[4] = 0;
16758 rdata.data = buf;
16759 rdata.length = sizeof(buf);
16760 rdata.type = privatetype;
16761 rdata.rdclass = tuple->rdata.rdclass;
16763 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
16764 CHECK(rr_exists(db, ver, name, &rdata, &flag));
16765 if (flag)
16766 continue;
16767 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
16768 name, 0, &rdata, &newtuple));
16769 CHECK(do_one_tuple(&newtuple, db, ver, diff));
16770 INSIST(newtuple == NULL);
16774 * Remove any record which says this operation has already
16775 * completed.
16777 buf[4] = 1;
16778 CHECK(rr_exists(db, ver, name, &rdata, &flag));
16779 if (flag) {
16780 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
16781 name, 0, &rdata, &newtuple));
16782 CHECK(do_one_tuple(&newtuple, db, ver, diff));
16783 INSIST(newtuple == NULL);
16786 failure:
16787 return (result);
16790 static isc_result_t
16791 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16792 dns_diff_t *diff, zonediff_t *zonediff)
16794 isc_result_t result;
16795 isc_stdtime_t now, inception, soaexpire;
16796 isc_boolean_t check_ksk, keyset_kskonly;
16797 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
16798 unsigned int nkeys = 0, i;
16799 dns_difftuple_t *tuple;
16801 result = find_zone_keys(zone, db, ver, zone->mctx, DNS_MAXZONEKEYS,
16802 zone_keys, &nkeys);
16803 if (result != ISC_R_SUCCESS) {
16804 dns_zone_log(zone, ISC_LOG_ERROR,
16805 "sign_apex:find_zone_keys -> %s",
16806 dns_result_totext(result));
16807 return (result);
16810 isc_stdtime_get(&now);
16811 inception = now - 3600; /* Allow for clock skew. */
16812 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
16814 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
16815 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
16818 * See if update_sigs will update DNSKEY signature and if not
16819 * cause them to sign so that so that newly activated keys
16820 * are used.
16822 for (tuple = ISC_LIST_HEAD(diff->tuples);
16823 tuple != NULL;
16824 tuple = ISC_LIST_NEXT(tuple, link)) {
16825 if (tuple->rdata.type == dns_rdatatype_dnskey &&
16826 dns_name_equal(&tuple->name, &zone->origin))
16827 break;
16830 if (tuple == NULL) {
16831 result = del_sigs(zone, db, ver, &zone->origin,
16832 dns_rdatatype_dnskey, zonediff,
16833 zone_keys, nkeys, now, ISC_FALSE);
16834 if (result != ISC_R_SUCCESS) {
16835 dns_zone_log(zone, ISC_LOG_ERROR,
16836 "sign_apex:del_sigs -> %s",
16837 dns_result_totext(result));
16838 goto failure;
16840 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
16841 zonediff->diff, zone_keys, nkeys, zone->mctx,
16842 inception, soaexpire, check_ksk,
16843 keyset_kskonly);
16844 if (result != ISC_R_SUCCESS) {
16845 dns_zone_log(zone, ISC_LOG_ERROR,
16846 "sign_apex:add_sigs -> %s",
16847 dns_result_totext(result));
16848 goto failure;
16852 result = update_sigs(diff, db, ver, zone_keys, nkeys, zone,
16853 inception, soaexpire, now, check_ksk,
16854 keyset_kskonly, zonediff);
16856 if (result != ISC_R_SUCCESS) {
16857 dns_zone_log(zone, ISC_LOG_ERROR,
16858 "sign_apex:update_sigs -> %s",
16859 dns_result_totext(result));
16860 goto failure;
16863 failure:
16864 for (i = 0; i < nkeys; i++)
16865 dst_key_free(&zone_keys[i]);
16866 return (result);
16870 * Prevent the zone entering a inconsistent state where
16871 * NSEC only DNSKEYs are present with NSEC3 chains.
16872 * See update.c:check_dnssec()
16874 static isc_boolean_t
16875 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16876 dns_diff_t *diff)
16878 isc_result_t result;
16879 dns_difftuple_t *tuple;
16880 isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
16881 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
16883 /* Scan the tuples for an NSEC-only DNSKEY */
16884 for (tuple = ISC_LIST_HEAD(diff->tuples);
16885 tuple != NULL;
16886 tuple = ISC_LIST_NEXT(tuple, link)) {
16887 isc_uint8_t alg;
16888 if (tuple->rdata.type != dns_rdatatype_dnskey ||
16889 tuple->op != DNS_DIFFOP_ADD)
16890 continue;
16892 alg = tuple->rdata.data[3];
16893 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
16894 alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
16895 nseconly = ISC_TRUE;
16896 break;
16900 /* Check existing DB for NSEC-only DNSKEY */
16901 if (!nseconly) {
16902 result = dns_nsec_nseconly(db, ver, &nseconly);
16903 if (result == ISC_R_NOTFOUND)
16904 result = ISC_R_SUCCESS;
16905 CHECK(result);
16908 /* Check existing DB for NSEC3 */
16909 if (!nsec3)
16910 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
16911 privatetype, &nsec3));
16913 /* Refuse to allow NSEC3 with NSEC-only keys */
16914 if (nseconly && nsec3) {
16915 dns_zone_log(zone, ISC_LOG_ERROR,
16916 "NSEC only DNSKEYs and NSEC3 chains not allowed");
16917 goto failure;
16920 return (ISC_TRUE);
16922 failure:
16923 return (ISC_FALSE);
16926 static isc_result_t
16927 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16928 dns_diff_t *diff)
16930 isc_result_t result;
16931 dns_dbnode_t *node = NULL;
16932 dns_rdataset_t rdataset;
16934 dns_rdataset_init(&rdataset);
16935 CHECK(dns_db_getoriginnode(db, &node));
16937 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
16938 dns_rdatatype_none, 0, &rdataset, NULL);
16939 if (dns_rdataset_isassociated(&rdataset))
16940 dns_rdataset_disassociate(&rdataset);
16941 if (result != ISC_R_NOTFOUND)
16942 goto failure;
16944 result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
16946 failure:
16947 if (node != NULL)
16948 dns_db_detachnode(db, &node);
16949 return (result);
16953 * Given an RRSIG rdataset and an algorithm, determine whether there
16954 * are any signatures using that algorithm.
16956 static isc_boolean_t
16957 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
16958 dns_rdata_t rdata = DNS_RDATA_INIT;
16959 dns_rdata_rrsig_t rrsig;
16960 isc_result_t result;
16962 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
16963 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
16964 return (ISC_FALSE);
16967 for (result = dns_rdataset_first(rdataset);
16968 result == ISC_R_SUCCESS;
16969 result = dns_rdataset_next(rdataset))
16971 dns_rdataset_current(rdataset, &rdata);
16972 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
16973 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16974 dns_rdata_reset(&rdata);
16975 if (rrsig.algorithm == alg)
16976 return (ISC_TRUE);
16979 return (ISC_FALSE);
16982 static isc_result_t
16983 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
16984 dns_diff_t *diff)
16986 dns_name_t *origin;
16987 isc_boolean_t build_nsec3;
16988 isc_result_t result;
16990 origin = dns_db_origin(db);
16991 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
16992 &build_nsec3));
16993 if (build_nsec3)
16994 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
16995 ISC_FALSE, zone->privatetype, diff));
16996 CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
16998 failure:
16999 return (result);
17002 static void
17003 zone_rekey(dns_zone_t *zone) {
17004 isc_result_t result;
17005 dns_db_t *db = NULL;
17006 dns_dbnode_t *node = NULL;
17007 dns_dbversion_t *ver = NULL;
17008 dns_rdataset_t soaset, soasigs, keyset, keysigs;
17009 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
17010 dns_dnsseckey_t *key;
17011 dns_diff_t diff, _sig_diff;
17012 zonediff_t zonediff;
17013 isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
17014 isc_boolean_t newalg = ISC_FALSE;
17015 isc_boolean_t fullsign;
17016 dns_ttl_t ttl = 3600;
17017 const char *dir;
17018 isc_mem_t *mctx;
17019 isc_stdtime_t now;
17020 isc_time_t timenow;
17021 isc_interval_t ival;
17022 char timebuf[80];
17024 REQUIRE(DNS_ZONE_VALID(zone));
17026 ISC_LIST_INIT(dnskeys);
17027 ISC_LIST_INIT(keys);
17028 ISC_LIST_INIT(rmkeys);
17029 dns_rdataset_init(&soaset);
17030 dns_rdataset_init(&soasigs);
17031 dns_rdataset_init(&keyset);
17032 dns_rdataset_init(&keysigs);
17033 dir = dns_zone_getkeydirectory(zone);
17034 mctx = zone->mctx;
17035 dns_diff_init(mctx, &diff);
17036 dns_diff_init(mctx, &_sig_diff);
17037 zonediff_init(&zonediff, &_sig_diff);
17039 CHECK(dns_zone_getdb(zone, &db));
17040 CHECK(dns_db_newversion(db, &ver));
17041 CHECK(dns_db_getoriginnode(db, &node));
17043 TIME_NOW(&timenow);
17044 now = isc_time_seconds(&timenow);
17046 dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
17048 /* Get the SOA record's TTL */
17049 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
17050 dns_rdatatype_none, 0, &soaset, &soasigs));
17051 ttl = soaset.ttl;
17052 dns_rdataset_disassociate(&soaset);
17054 /* Get the DNSKEY rdataset */
17055 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
17056 dns_rdatatype_none, 0, &keyset, &keysigs);
17057 if (result == ISC_R_SUCCESS) {
17058 ttl = keyset.ttl;
17059 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
17060 mctx, &keyset,
17061 &keysigs, &soasigs,
17062 ISC_FALSE, ISC_FALSE,
17063 &dnskeys));
17064 } else if (result != ISC_R_NOTFOUND)
17065 goto failure;
17068 * True when called from "rndc sign". Indicates the zone should be
17069 * fully signed now.
17071 fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
17073 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, mctx, &keys);
17074 if (result == ISC_R_SUCCESS) {
17075 isc_boolean_t check_ksk;
17076 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
17078 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
17079 &zone->origin, ttl, &diff,
17080 ISC_TF(!check_ksk),
17081 mctx, logmsg);
17083 /* Keys couldn't be updated for some reason;
17084 * try again later. */
17085 if (result != ISC_R_SUCCESS) {
17086 dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
17087 "couldn't update zone keys: %s",
17088 isc_result_totext(result));
17089 goto failure;
17093 * See if any pre-existing keys have newly become active;
17094 * also, see if any new key is for a new algorithm, as in that
17095 * event, we need to sign the zone fully. (If there's a new
17096 * key, but it's for an already-existing algorithm, then
17097 * the zone signing can be handled incrementally.)
17099 for (key = ISC_LIST_HEAD(dnskeys);
17100 key != NULL;
17101 key = ISC_LIST_NEXT(key, link)) {
17102 if (!key->first_sign)
17103 continue;
17105 newactive = ISC_TRUE;
17107 if (!dns_rdataset_isassociated(&keysigs)) {
17108 newalg = ISC_TRUE;
17109 break;
17112 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
17114 * This isn't a new algorithm; clear
17115 * first_sign so we won't sign the
17116 * whole zone with this key later
17118 key->first_sign = ISC_FALSE;
17119 } else {
17120 newalg = ISC_TRUE;
17121 break;
17125 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
17126 dnskey_sane(zone, db, ver, &diff)) {
17127 CHECK(dns_diff_apply(&diff, db, ver));
17128 CHECK(clean_nsec3param(zone, db, ver, &diff));
17129 CHECK(add_signing_records(db, zone->privatetype,
17130 ver, &diff,
17131 ISC_TF(newalg || fullsign)));
17132 CHECK(update_soa_serial(db, ver, &diff, mctx,
17133 zone->updatemethod));
17134 CHECK(add_chains(zone, db, ver, &diff));
17135 CHECK(sign_apex(zone, db, ver, &diff, &zonediff));
17136 CHECK(zone_journal(zone, zonediff.diff, NULL,
17137 "zone_rekey"));
17138 commit = ISC_TRUE;
17142 dns_db_closeversion(db, &ver, ISC_TRUE);
17144 if (commit) {
17145 dns_difftuple_t *tuple;
17147 LOCK_ZONE(zone);
17148 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17150 zone_needdump(zone, DNS_DUMP_DELAY);
17152 zone_settimer(zone, &timenow);
17154 /* Remove any signatures from removed keys. */
17155 if (!ISC_LIST_EMPTY(rmkeys)) {
17156 for (key = ISC_LIST_HEAD(rmkeys);
17157 key != NULL;
17158 key = ISC_LIST_NEXT(key, link)) {
17159 result = zone_signwithkey(zone,
17160 dst_key_alg(key->key),
17161 dst_key_id(key->key),
17162 ISC_TRUE);
17163 if (result != ISC_R_SUCCESS) {
17164 dns_zone_log(zone, ISC_LOG_ERROR,
17165 "zone_signwithkey failed: %s",
17166 dns_result_totext(result));
17171 if (fullsign) {
17173 * "rndc sign" was called, so we now sign the zone
17174 * with all active keys, whether they're new or not.
17176 for (key = ISC_LIST_HEAD(dnskeys);
17177 key != NULL;
17178 key = ISC_LIST_NEXT(key, link)) {
17179 if (!key->force_sign && !key->hint_sign)
17180 continue;
17182 result = zone_signwithkey(zone,
17183 dst_key_alg(key->key),
17184 dst_key_id(key->key),
17185 ISC_FALSE);
17186 if (result != ISC_R_SUCCESS) {
17187 dns_zone_log(zone, ISC_LOG_ERROR,
17188 "zone_signwithkey failed: %s",
17189 dns_result_totext(result));
17192 } else if (newalg) {
17194 * We haven't been told to sign fully, but a new
17195 * algorithm was added to the DNSKEY. We sign
17196 * the full zone, but only with newly active
17197 * keys.
17199 for (key = ISC_LIST_HEAD(dnskeys);
17200 key != NULL;
17201 key = ISC_LIST_NEXT(key, link)) {
17202 if (!key->first_sign)
17203 continue;
17205 result = zone_signwithkey(zone,
17206 dst_key_alg(key->key),
17207 dst_key_id(key->key),
17208 ISC_FALSE);
17209 if (result != ISC_R_SUCCESS) {
17210 dns_zone_log(zone, ISC_LOG_ERROR,
17211 "zone_signwithkey failed: %s",
17212 dns_result_totext(result));
17218 * Clear fullsign flag, if it was set, so we don't do
17219 * another full signing next time
17221 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
17224 * Cause the zone to add/delete NSEC3 chains for the
17225 * deferred NSEC3PARAM changes.
17227 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
17228 tuple != NULL;
17229 tuple = ISC_LIST_NEXT(tuple, link)) {
17230 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
17231 dns_rdata_t rdata = DNS_RDATA_INIT;
17232 dns_rdata_nsec3param_t nsec3param;
17234 if (tuple->rdata.type != zone->privatetype ||
17235 tuple->op != DNS_DIFFOP_ADD)
17236 continue;
17238 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
17239 buf, sizeof(buf)))
17240 continue;
17241 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
17242 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17243 if (nsec3param.flags == 0)
17244 continue;
17246 result = zone_addnsec3chain(zone, &nsec3param);
17247 if (result != ISC_R_SUCCESS) {
17248 dns_zone_log(zone, ISC_LOG_ERROR,
17249 "zone_addnsec3chain failed: %s",
17250 dns_result_totext(result));
17255 * Activate any NSEC3 chain updates that may have
17256 * been scheduled before this rekey.
17258 if (fullsign || newalg)
17259 resume_addnsec3chain(zone);
17262 * Schedule the next resigning event
17264 set_resigntime(zone);
17265 UNLOCK_ZONE(zone);
17268 isc_time_settoepoch(&zone->refreshkeytime);
17271 * If we're doing key maintenance, set the key refresh timer to
17272 * the next scheduled key event or to 'dnssec-loadkeys-interval'
17273 * seconds in the future, whichever is sooner.
17275 if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
17276 isc_time_t timethen;
17277 isc_stdtime_t then;
17279 LOCK_ZONE(zone);
17280 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
17281 &timethen);
17282 zone->refreshkeytime = timethen;
17283 UNLOCK_ZONE(zone);
17285 for (key = ISC_LIST_HEAD(dnskeys);
17286 key != NULL;
17287 key = ISC_LIST_NEXT(key, link)) {
17288 then = now;
17289 result = next_keyevent(key->key, &then);
17290 if (result != ISC_R_SUCCESS)
17291 continue;
17293 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
17294 LOCK_ZONE(zone);
17295 if (isc_time_compare(&timethen,
17296 &zone->refreshkeytime) < 0) {
17297 zone->refreshkeytime = timethen;
17299 UNLOCK_ZONE(zone);
17302 zone_settimer(zone, &timenow);
17304 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
17305 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
17308 done:
17309 dns_diff_clear(&diff);
17310 dns_diff_clear(&_sig_diff);
17312 clear_keylist(&dnskeys, mctx);
17313 clear_keylist(&keys, mctx);
17314 clear_keylist(&rmkeys, mctx);
17316 if (ver != NULL)
17317 dns_db_closeversion(db, &ver, ISC_FALSE);
17318 if (dns_rdataset_isassociated(&keyset))
17319 dns_rdataset_disassociate(&keyset);
17320 if (dns_rdataset_isassociated(&keysigs))
17321 dns_rdataset_disassociate(&keysigs);
17322 if (dns_rdataset_isassociated(&soasigs))
17323 dns_rdataset_disassociate(&soasigs);
17324 if (node != NULL)
17325 dns_db_detachnode(db, &node);
17326 if (db != NULL)
17327 dns_db_detach(&db);
17329 INSIST(ver == NULL);
17330 return;
17332 failure:
17334 * Something went wrong; try again in ten minutes or
17335 * after a key refresh interval, whichever is shorter.
17337 isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
17338 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
17339 goto done;
17342 void
17343 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
17344 isc_time_t now;
17346 if (zone->type == dns_zone_master && zone->task != NULL) {
17347 LOCK_ZONE(zone);
17349 if (fullsign)
17350 zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
17352 TIME_NOW(&now);
17353 zone->refreshkeytime = now;
17354 zone_settimer(zone, &now);
17356 UNLOCK_ZONE(zone);
17360 isc_result_t
17361 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
17362 unsigned int *errors)
17364 isc_result_t result;
17365 dns_dbnode_t *node = NULL;
17367 REQUIRE(DNS_ZONE_VALID(zone));
17368 REQUIRE(errors != NULL);
17370 result = dns_db_getoriginnode(db, &node);
17371 if (result != ISC_R_SUCCESS)
17372 return (result);
17373 result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
17374 ISC_FALSE);
17375 dns_db_detachnode(db, &node);
17376 return (result);
17379 void
17380 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
17381 REQUIRE(DNS_ZONE_VALID(zone));
17383 LOCK_ZONE(zone);
17384 zone->added = added;
17385 UNLOCK_ZONE(zone);
17388 isc_boolean_t
17389 dns_zone_getadded(dns_zone_t *zone) {
17390 REQUIRE(DNS_ZONE_VALID(zone));
17391 return (zone->added);
17394 isc_result_t
17395 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
17397 isc_time_t loadtime;
17398 isc_result_t result;
17399 dns_zone_t *secure = NULL;
17401 TIME_NOW(&loadtime);
17404 * Lock hierarchy: zmgr, zone, raw.
17406 again:
17407 LOCK_ZONE(zone);
17408 INSIST(zone != zone->raw);
17409 if (inline_secure(zone))
17410 LOCK_ZONE(zone->raw);
17411 else if (inline_raw(zone)) {
17412 secure = zone->secure;
17413 TRYLOCK_ZONE(result, secure);
17414 if (result != ISC_R_SUCCESS) {
17415 UNLOCK_ZONE(zone);
17416 secure = NULL;
17417 #if ISC_PLATFORM_USETHREADS
17418 isc_thread_yield();
17419 #endif
17420 goto again;
17423 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
17424 if (inline_secure(zone))
17425 UNLOCK_ZONE(zone->raw);
17426 else if (secure != NULL)
17427 UNLOCK_ZONE(secure);
17428 UNLOCK_ZONE(zone);
17429 return result;
17432 isc_result_t
17433 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
17434 REQUIRE(DNS_ZONE_VALID(zone));
17435 if (interval == 0)
17436 return (ISC_R_RANGE);
17437 /* Maximum value: 24 hours (3600 minutes) */
17438 if (interval > (24 * 60))
17439 interval = (24 * 60);
17440 /* Multiply by 60 for seconds */
17441 zone->refreshkeyinterval = interval * 60;
17442 return (ISC_R_SUCCESS);
17445 void
17446 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
17447 REQUIRE(DNS_ZONE_VALID(zone));
17448 zone->requestixfr = flag;
17451 isc_boolean_t
17452 dns_zone_getrequestixfr(dns_zone_t *zone) {
17453 REQUIRE(DNS_ZONE_VALID(zone));
17454 return (zone->requestixfr);
17457 void
17458 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
17459 REQUIRE(DNS_ZONE_VALID(zone));
17460 zone->updatemethod = method;
17463 dns_updatemethod_t
17464 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
17465 REQUIRE(DNS_ZONE_VALID(zone));
17466 return(zone->updatemethod);
17470 * Lock hierarchy: zmgr, zone, raw.
17472 isc_result_t
17473 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
17474 isc_result_t result;
17475 dns_zonemgr_t *zmgr;
17477 REQUIRE(DNS_ZONE_VALID(zone));
17478 REQUIRE(zone->zmgr != NULL);
17479 REQUIRE(zone->task != NULL);
17480 REQUIRE(zone->loadtask != NULL);
17481 REQUIRE(zone->raw == NULL);
17483 REQUIRE(DNS_ZONE_VALID(raw));
17484 REQUIRE(raw->zmgr == NULL);
17485 REQUIRE(raw->task == NULL);
17486 REQUIRE(raw->loadtask == NULL);
17487 REQUIRE(raw->secure == NULL);
17489 REQUIRE(zone != raw);
17492 * Lock hierarchy: zmgr, zone, raw.
17494 zmgr = zone->zmgr;
17495 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17496 LOCK_ZONE(zone);
17497 LOCK_ZONE(raw);
17499 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
17500 NULL, NULL, zone->task, zone_timer, raw,
17501 &raw->timer);
17502 if (result != ISC_R_SUCCESS)
17503 goto unlock;
17506 * The timer "holds" a iref.
17508 raw->irefs++;
17509 INSIST(raw->irefs != 0);
17512 /* dns_zone_attach(raw, &zone->raw); */
17513 isc_refcount_increment(&raw->erefs, NULL);
17514 zone->raw = raw;
17516 /* dns_zone_iattach(zone, &raw->secure); */
17517 zone_iattach(zone, &raw->secure);
17519 isc_task_attach(zone->task, &raw->task);
17520 isc_task_attach(zone->loadtask, &raw->loadtask);
17522 ISC_LIST_APPEND(zmgr->zones, raw, link);
17523 raw->zmgr = zmgr;
17524 zmgr->refs++;
17526 unlock:
17527 UNLOCK_ZONE(raw);
17528 UNLOCK_ZONE(zone);
17529 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17530 return (result);
17533 void
17534 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
17535 REQUIRE(DNS_ZONE_VALID(zone));
17536 REQUIRE(raw != NULL && *raw == NULL);
17538 LOCK(&zone->lock);
17539 INSIST(zone != zone->raw);
17540 if (zone->raw != NULL)
17541 dns_zone_attach(zone->raw, raw);
17542 UNLOCK(&zone->lock);
17545 struct keydone {
17546 isc_event_t event;
17547 isc_boolean_t all;
17548 unsigned char data[5];
17551 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
17553 static void
17554 keydone(isc_task_t *task, isc_event_t *event) {
17555 const char *me = "keydone";
17556 isc_boolean_t commit = ISC_FALSE;
17557 isc_result_t result;
17558 dns_rdata_t rdata = DNS_RDATA_INIT;
17559 dns_dbversion_t *oldver = NULL, *newver = NULL;
17560 dns_zone_t *zone;
17561 dns_db_t *db = NULL;
17562 dns_dbnode_t *node = NULL;
17563 dns_rdataset_t rdataset;
17564 dns_diff_t diff;
17565 struct keydone *keydone = (struct keydone *)event;
17566 dns_update_log_t log = { update_log_cb, NULL };
17567 isc_boolean_t clear_pending = ISC_FALSE;
17569 UNUSED(task);
17571 zone = event->ev_arg;
17572 INSIST(DNS_ZONE_VALID(zone));
17574 ENTER;
17576 dns_rdataset_init(&rdataset);
17577 dns_diff_init(zone->mctx, &diff);
17579 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17580 if (zone->db != NULL) {
17581 dns_db_attach(zone->db, &db);
17582 dns_db_currentversion(db, &oldver);
17583 result = dns_db_newversion(db, &newver);
17584 if (result != ISC_R_SUCCESS) {
17585 dns_zone_log(zone, ISC_LOG_ERROR,
17586 "keydone:dns_db_newversion -> %s",
17587 dns_result_totext(result));
17588 goto failure;
17591 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17592 if (db == NULL)
17593 goto failure;
17595 result = dns_db_getoriginnode(db, &node);
17596 if (result != ISC_R_SUCCESS)
17597 goto failure;
17599 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17600 dns_rdatatype_none, 0, &rdataset, NULL);
17601 if (result == ISC_R_NOTFOUND) {
17602 INSIST(!dns_rdataset_isassociated(&rdataset));
17603 goto failure;
17605 if (result != ISC_R_SUCCESS) {
17606 INSIST(!dns_rdataset_isassociated(&rdataset));
17607 goto failure;
17610 for (result = dns_rdataset_first(&rdataset);
17611 result == ISC_R_SUCCESS;
17612 result = dns_rdataset_next(&rdataset)) {
17613 isc_boolean_t found = ISC_FALSE;
17615 dns_rdataset_current(&rdataset, &rdata);
17617 if (keydone->all) {
17618 if (rdata.length == 5 && rdata.data[0] != 0 &&
17619 rdata.data[3] == 0 && rdata.data[4] == 1)
17620 found = ISC_TRUE;
17621 else if (rdata.data[0] == 0 &&
17622 (rdata.data[2] & PENDINGFLAGS) != 0) {
17623 found = ISC_TRUE;
17624 clear_pending = ISC_TRUE;
17626 } else if (rdata.length == 5 &&
17627 memcmp(rdata.data, keydone->data, 5) == 0)
17628 found = ISC_TRUE;
17630 if (found)
17631 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
17632 &zone->origin, rdataset.ttl,
17633 &rdata));
17634 dns_rdata_reset(&rdata);
17637 if (!ISC_LIST_EMPTY(diff.tuples)) {
17638 /* Write changes to journal file. */
17639 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17640 zone->updatemethod));
17642 result = dns_update_signatures(&log, zone, db,
17643 oldver, newver, &diff,
17644 zone->sigvalidityinterval);
17645 if (!clear_pending)
17646 CHECK(result);
17648 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
17649 commit = ISC_TRUE;
17651 LOCK_ZONE(zone);
17652 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17653 zone_needdump(zone, 30);
17654 UNLOCK_ZONE(zone);
17657 failure:
17658 if (dns_rdataset_isassociated(&rdataset))
17659 dns_rdataset_disassociate(&rdataset);
17660 if (db != NULL) {
17661 if (node != NULL)
17662 dns_db_detachnode(db, &node);
17663 if (oldver != NULL)
17664 dns_db_closeversion(db, &oldver, ISC_FALSE);
17665 if (newver != NULL)
17666 dns_db_closeversion(db, &newver, commit);
17667 dns_db_detach(&db);
17669 dns_diff_clear(&diff);
17670 isc_event_free(&event);
17671 dns_zone_idetach(&zone);
17673 INSIST(oldver == NULL);
17674 INSIST(newver == NULL);
17677 isc_result_t
17678 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
17679 isc_result_t result = ISC_R_SUCCESS;
17680 isc_event_t *e;
17681 isc_buffer_t b;
17682 dns_zone_t *dummy = NULL;
17683 struct keydone *kd;
17685 REQUIRE(DNS_ZONE_VALID(zone));
17687 LOCK_ZONE(zone);
17689 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
17690 zone, sizeof(struct keydone));
17691 if (e == NULL) {
17692 result = ISC_R_NOMEMORY;
17693 goto failure;
17696 kd = (struct keydone *) e;
17697 if (strcasecmp(keystr, "all") == 0)
17698 kd->all = ISC_TRUE;
17699 else {
17700 isc_textregion_t r;
17701 char *algstr;
17702 dns_keytag_t keyid;
17703 dns_secalg_t alg;
17704 size_t n;
17706 kd->all = ISC_FALSE;
17708 n = sscanf(keystr, "%hd/", &keyid);
17709 if (n == 0U)
17710 CHECK(ISC_R_FAILURE);
17712 algstr = strchr(keystr, '/');
17713 if (algstr != NULL)
17714 algstr++;
17715 else
17716 CHECK(ISC_R_FAILURE);
17718 n = sscanf(algstr, "%hhd", &alg);
17719 if (n == 0U) {
17720 DE_CONST(algstr, r.base);
17721 r.length = strlen(algstr);
17722 CHECK(dns_secalg_fromtext(&alg, &r));
17725 /* construct a private-type rdata */
17726 isc_buffer_init(&b, kd->data, sizeof(kd->data));
17727 isc_buffer_putuint8(&b, alg);
17728 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
17729 isc_buffer_putuint8(&b, (keyid & 0xff));
17730 isc_buffer_putuint8(&b, 0);
17731 isc_buffer_putuint8(&b, 1);
17734 zone_iattach(zone, &dummy);
17735 isc_task_send(zone->task, &e);
17737 failure:
17738 if (e != NULL)
17739 isc_event_free(&e);
17740 UNLOCK_ZONE(zone);
17741 return (result);
17744 static void
17745 setnsec3param(isc_task_t *task, isc_event_t *event) {
17746 const char *me = "setnsec3param";
17747 isc_boolean_t commit = ISC_FALSE;
17748 isc_result_t result;
17749 dns_dbversion_t *oldver = NULL, *newver = NULL;
17750 dns_zone_t *zone;
17751 dns_db_t *db = NULL;
17752 dns_dbnode_t *node = NULL;
17753 dns_rdataset_t prdataset, nrdataset;
17754 dns_diff_t diff;
17755 struct np3event *npe = (struct np3event *)event;
17756 nsec3param_t *np;
17757 dns_update_log_t log = { update_log_cb, NULL };
17758 dns_rdata_t rdata;
17759 isc_boolean_t nseconly;
17760 isc_boolean_t exists = ISC_FALSE;
17762 UNUSED(task);
17764 zone = event->ev_arg;
17765 INSIST(DNS_ZONE_VALID(zone));
17767 ENTER;
17769 np = &npe->params;
17771 dns_rdataset_init(&prdataset);
17772 dns_rdataset_init(&nrdataset);
17773 dns_diff_init(zone->mctx, &diff);
17775 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17776 if (zone->db != NULL) {
17777 dns_db_attach(zone->db, &db);
17778 dns_db_currentversion(db, &oldver);
17779 result = dns_db_newversion(db, &newver);
17780 if (result != ISC_R_SUCCESS) {
17781 dns_zone_log(zone, ISC_LOG_ERROR,
17782 "setnsec3param:dns_db_newversion -> %s",
17783 dns_result_totext(result));
17784 goto failure;
17787 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17788 if (db == NULL)
17789 goto failure;
17791 CHECK(dns_db_getoriginnode(db, &node));
17794 * Does a private-type record already exist for this chain?
17796 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
17797 dns_rdatatype_none, 0, &prdataset, NULL);
17798 if (result == ISC_R_SUCCESS) {
17799 for (result = dns_rdataset_first(&prdataset);
17800 result == ISC_R_SUCCESS;
17801 result = dns_rdataset_next(&prdataset)) {
17802 dns_rdata_init(&rdata);
17803 dns_rdataset_current(&prdataset, &rdata);
17805 if (np->length == rdata.length &&
17806 memcmp(rdata.data, np->data, np->length) == 0) {
17807 exists = ISC_TRUE;
17808 break;
17811 } else if (result != ISC_R_NOTFOUND) {
17812 INSIST(!dns_rdataset_isassociated(&prdataset));
17813 goto failure;
17817 * Does the chain already exist?
17819 result = dns_db_findrdataset(db, node, newver,
17820 dns_rdatatype_nsec3param,
17821 dns_rdatatype_none, 0, &nrdataset, NULL);
17822 if (result == ISC_R_SUCCESS) {
17823 for (result = dns_rdataset_first(&nrdataset);
17824 result == ISC_R_SUCCESS;
17825 result = dns_rdataset_next(&nrdataset)) {
17826 dns_rdata_init(&rdata);
17827 dns_rdataset_current(&nrdataset, &rdata);
17829 if (np->length == (rdata.length + 1) &&
17830 memcmp(rdata.data, np->data + 1,
17831 np->length - 1) == 0)
17833 exists = ISC_TRUE;
17834 break;
17837 } else if (result != ISC_R_NOTFOUND) {
17838 INSIST(!dns_rdataset_isassociated(&nrdataset));
17839 goto failure;
17844 * We need to remove any existing NSEC3 chains.
17846 if (!exists && np->replace && (np->length != 0 || np->nsec))
17847 CHECK(dns_nsec3param_deletechains(db, newver, zone,
17848 !np->nsec, &diff));
17850 if (!exists && np->length != 0) {
17852 * We're creating an NSEC3 chain.
17854 * If the zone is not currently capable of supporting
17855 * an NSEC3 chain, add the INITIAL flag, so these
17856 * parameters can be used later when NSEC3 becomes
17857 * available.
17859 dns_rdata_init(&rdata);
17861 np->data[2] |= DNS_NSEC3FLAG_CREATE;
17862 result = dns_nsec_nseconly(db, newver, &nseconly);
17863 if (result == ISC_R_NOTFOUND || nseconly)
17864 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
17866 rdata.length = np->length;
17867 rdata.data = np->data;
17868 rdata.type = zone->privatetype;
17869 rdata.rdclass = zone->rdclass;
17870 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
17871 &zone->origin, 0, &rdata));
17874 if (!ISC_LIST_EMPTY(diff.tuples)) {
17875 /* Write changes to journal file. */
17876 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
17877 zone->updatemethod));
17878 result = dns_update_signatures(&log, zone, db,
17879 oldver, newver, &diff,
17880 zone->sigvalidityinterval);
17881 if (result != ISC_R_NOTFOUND)
17882 CHECK(result);
17883 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
17884 commit = ISC_TRUE;
17886 LOCK_ZONE(zone);
17887 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
17888 zone_needdump(zone, 30);
17889 UNLOCK_ZONE(zone);
17892 failure:
17893 if (dns_rdataset_isassociated(&prdataset))
17894 dns_rdataset_disassociate(&prdataset);
17895 if (dns_rdataset_isassociated(&nrdataset))
17896 dns_rdataset_disassociate(&nrdataset);
17897 if (node != NULL)
17898 dns_db_detachnode(db, &node);
17899 if (oldver != NULL)
17900 dns_db_closeversion(db, &oldver, ISC_FALSE);
17901 if (newver != NULL)
17902 dns_db_closeversion(db, &newver, commit);
17903 if (db != NULL)
17904 dns_db_detach(&db);
17905 if (commit)
17906 resume_addnsec3chain(zone);
17907 dns_diff_clear(&diff);
17908 isc_event_free(&event);
17909 dns_zone_idetach(&zone);
17911 INSIST(oldver == NULL);
17912 INSIST(newver == NULL);
17915 isc_result_t
17916 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
17917 isc_uint16_t iter, isc_uint8_t saltlen,
17918 unsigned char *salt, isc_boolean_t replace)
17920 isc_result_t result = ISC_R_SUCCESS;
17921 dns_rdata_nsec3param_t param;
17922 dns_rdata_t nrdata = DNS_RDATA_INIT;
17923 dns_rdata_t prdata = DNS_RDATA_INIT;
17924 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
17925 struct np3event *npe;
17926 nsec3param_t *np;
17927 dns_zone_t *dummy = NULL;
17928 isc_buffer_t b;
17929 isc_event_t *e;
17931 REQUIRE(DNS_ZONE_VALID(zone));
17932 REQUIRE(salt != NULL);
17934 LOCK_ZONE(zone);
17936 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
17937 setnsec3param, zone, sizeof(struct np3event));
17938 if (e == NULL) {
17939 result = ISC_R_NOMEMORY;
17940 goto failure;
17943 npe = (struct np3event *) e;
17944 np = &npe->params;
17946 np->replace = replace;
17947 if (hash == 0) {
17948 np->length = 0;
17949 np->nsec = ISC_TRUE;
17950 } else {
17951 param.common.rdclass = zone->rdclass;
17952 param.common.rdtype = dns_rdatatype_nsec3param;
17953 ISC_LINK_INIT(&param.common, link);
17954 param.mctx = NULL;
17955 param.hash = hash;
17956 param.flags = flags;
17957 param.iterations = iter;
17958 param.salt_length = saltlen;
17959 param.salt = salt;
17960 isc_buffer_init(&b, nbuf, sizeof(nbuf));
17961 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
17962 dns_rdatatype_nsec3param,
17963 &param, &b));
17964 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
17965 np->data, sizeof(np->data));
17966 np->length = prdata.length;
17969 zone_iattach(zone, &dummy);
17970 isc_task_send(zone->task, &e);
17972 failure:
17973 if (e != NULL)
17974 isc_event_free(&e);
17975 UNLOCK_ZONE(zone);
17976 return (result);
17979 isc_result_t
17980 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
17981 REQUIRE(DNS_ZONE_VALID(zone));
17982 REQUIRE(loadtime != NULL);
17984 LOCK_ZONE(zone);
17985 *loadtime = zone->loadtime;
17986 UNLOCK_ZONE(zone);
17987 return (ISC_R_SUCCESS);
17990 isc_result_t
17991 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
17992 REQUIRE(DNS_ZONE_VALID(zone));
17993 REQUIRE(expiretime != NULL);
17995 LOCK_ZONE(zone);
17996 *expiretime = zone->expiretime;
17997 UNLOCK_ZONE(zone);
17998 return (ISC_R_SUCCESS);
18001 isc_result_t
18002 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
18003 REQUIRE(DNS_ZONE_VALID(zone));
18004 REQUIRE(refreshtime != NULL);
18006 LOCK_ZONE(zone);
18007 *refreshtime = zone->refreshtime;
18008 UNLOCK_ZONE(zone);
18009 return (ISC_R_SUCCESS);
18012 isc_result_t
18013 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
18014 REQUIRE(DNS_ZONE_VALID(zone));
18015 REQUIRE(refreshkeytime != NULL);
18017 LOCK_ZONE(zone);
18018 *refreshkeytime = zone->refreshkeytime;
18019 UNLOCK_ZONE(zone);
18020 return (ISC_R_SUCCESS);
18023 unsigned int
18024 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
18025 dns_include_t *include;
18026 char **array = NULL;
18027 unsigned int n = 0;
18029 REQUIRE(DNS_ZONE_VALID(zone));
18030 REQUIRE(includesp != NULL && *includesp == NULL);
18032 LOCK_ZONE(zone);
18033 if (zone->nincludes == 0)
18034 goto done;
18036 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
18037 if (array == NULL)
18038 goto done;
18039 for (include = ISC_LIST_HEAD(zone->includes);
18040 include != NULL;
18041 include = ISC_LIST_NEXT(include, link)) {
18042 INSIST(n < zone->nincludes);
18043 array[n++] = isc_mem_strdup(zone->mctx, include->name);
18045 INSIST(n == zone->nincludes);
18046 *includesp = array;
18048 done:
18049 UNLOCK_ZONE(zone);
18050 return (n);
18053 void
18054 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
18055 REQUIRE(DNS_ZONE_VALID(zone));
18057 zone->statlevel = level;
18060 dns_zonestat_level_t
18061 dns_zone_getstatlevel(dns_zone_t *zone) {
18062 REQUIRE(DNS_ZONE_VALID(zone));
18064 return (zone->statlevel);