zone.c revision 1.4 1 /* $NetBSD: zone.c,v 1.4 2019/02/24 20:01:30 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <config.h>
17
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <stdbool.h>
21
22 #include <isc/file.h>
23 #include <isc/hex.h>
24 #include <isc/mutex.h>
25 #include <isc/pool.h>
26 #include <isc/print.h>
27 #include <isc/random.h>
28 #include <isc/ratelimiter.h>
29 #include <isc/refcount.h>
30 #include <isc/rwlock.h>
31 #include <isc/serial.h>
32 #include <isc/stats.h>
33 #include <isc/stdtime.h>
34 #include <isc/strerr.h>
35 #include <isc/string.h>
36 #include <isc/taskpool.h>
37 #include <isc/thread.h>
38 #include <isc/timer.h>
39 #include <isc/util.h>
40
41 #include <dns/acl.h>
42 #include <dns/adb.h>
43 #include <dns/callbacks.h>
44 #include <dns/catz.h>
45 #include <dns/db.h>
46 #include <dns/dbiterator.h>
47 #include <dns/dlz.h>
48 #include <dns/dnssec.h>
49 #include <dns/events.h>
50 #include <dns/journal.h>
51 #include <dns/keydata.h>
52 #include <dns/keytable.h>
53 #include <dns/keyvalues.h>
54 #include <dns/log.h>
55 #include <dns/master.h>
56 #include <dns/masterdump.h>
57 #include <dns/message.h>
58 #include <dns/name.h>
59 #include <dns/nsec.h>
60 #include <dns/nsec3.h>
61 #include <dns/peer.h>
62 #include <dns/private.h>
63 #include <dns/rcode.h>
64 #include <dns/rdata.h>
65 #include <dns/rdataclass.h>
66 #include <dns/rdatalist.h>
67 #include <dns/rdataset.h>
68 #include <dns/rdatasetiter.h>
69 #include <dns/rdatastruct.h>
70 #include <dns/rdatatype.h>
71 #include <dns/request.h>
72 #include <dns/resolver.h>
73 #include <dns/result.h>
74 #include <dns/rriterator.h>
75 #include <dns/soa.h>
76 #include <dns/ssu.h>
77 #include <dns/stats.h>
78 #include <dns/time.h>
79 #include <dns/tsig.h>
80 #include <dns/update.h>
81 #include <dns/xfrin.h>
82 #include <dns/zone.h>
83 #include <dns/zoneverify.h>
84 #include <dns/zt.h>
85
86 #include <dst/dst.h>
87
88 #include "zone_p.h"
89
90 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
91 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
92
93 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
94 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
95
96 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
97 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
98
99 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
100 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
101
102 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
103 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
104
105 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
106 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
107
108 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
109 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
110
111 /*%
112 * Ensure 'a' is at least 'min' but not more than 'max'.
113 */
114 #define RANGE(a, min, max) \
115 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
116
117 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
118
119 /*%
120 * Key flags
121 */
122 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
123 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
124 #define ALG(x) dst_key_alg(x)
125
126 /*
127 * Default values.
128 */
129 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
130 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
131 #define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
132 #define RESIGN_DELAY 3600 /*%< 1 hour */
133
134 #ifndef DNS_MAX_EXPIRE
135 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
136 #endif
137
138 #ifndef DNS_DUMP_DELAY
139 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
140 #endif
141
142 typedef struct dns_notify dns_notify_t;
143 typedef struct dns_stub dns_stub_t;
144 typedef struct dns_load dns_load_t;
145 typedef struct dns_forward dns_forward_t;
146 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
147 typedef struct dns_io dns_io_t;
148 typedef ISC_LIST(dns_io_t) dns_iolist_t;
149 typedef struct dns_signing dns_signing_t;
150 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
151 typedef struct dns_nsec3chain dns_nsec3chain_t;
152 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
153 typedef struct dns_keyfetch dns_keyfetch_t;
154 typedef struct dns_asyncload dns_asyncload_t;
155 typedef struct dns_include dns_include_t;
156
157 #define DNS_ZONE_CHECKLOCK
158 #ifdef DNS_ZONE_CHECKLOCK
159 #define LOCK_ZONE(z) \
160 do { LOCK(&(z)->lock); \
161 INSIST((z)->locked == false); \
162 (z)->locked = true; \
163 } while (/*CONSTCOND*/0)
164 #define UNLOCK_ZONE(z) \
165 do { (z)->locked = false; UNLOCK(&(z)->lock); } while (/*CONSTCON*/0)
166 #define LOCKED_ZONE(z) ((z)->locked)
167 #define TRYLOCK_ZONE(result, z) \
168 do { \
169 result = isc_mutex_trylock(&(z)->lock); \
170 if (result == ISC_R_SUCCESS) { \
171 INSIST((z)->locked == false); \
172 (z)->locked = true; \
173 } \
174 } while (/*CONSTCOND*/0)
175 #else
176 #define LOCK_ZONE(z) LOCK(&(z)->lock)
177 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
178 #define LOCKED_ZONE(z) true
179 #define TRYLOCK_ZONE(result, z) \
180 do { result = isc_mutex_trylock(&(z)->lock); } while (/*CONSTCOND*/0)
181 #endif
182
183 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
184 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
185 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
186 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
187
188 #ifdef ENABLE_AFL
189 extern bool dns_fuzzing_resolver;
190 #endif
191
192 struct dns_zone {
193 /* Unlocked */
194 unsigned int magic;
195 isc_mutex_t lock;
196 #ifdef DNS_ZONE_CHECKLOCK
197 bool locked;
198 #endif
199 isc_mem_t *mctx;
200 isc_refcount_t erefs;
201
202 isc_rwlock_t dblock;
203 dns_db_t *db; /* Locked by dblock */
204
205 /* Locked */
206 dns_zonemgr_t *zmgr;
207 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
208 isc_timer_t *timer;
209 unsigned int irefs;
210 dns_name_t origin;
211 char *masterfile;
212 ISC_LIST(dns_include_t) includes; /* Include files */
213 ISC_LIST(dns_include_t) newincludes; /* Loading */
214 unsigned int nincludes;
215 dns_masterformat_t masterformat;
216 const dns_master_style_t *masterstyle;
217 char *journal;
218 int32_t journalsize;
219 dns_rdataclass_t rdclass;
220 dns_zonetype_t type;
221 unsigned int flags;
222 dns_zoneopt_t options;
223 unsigned int db_argc;
224 char **db_argv;
225 isc_time_t expiretime;
226 isc_time_t refreshtime;
227 isc_time_t dumptime;
228 isc_time_t loadtime;
229 isc_time_t notifytime;
230 isc_time_t resigntime;
231 isc_time_t keywarntime;
232 isc_time_t signingtime;
233 isc_time_t nsec3chaintime;
234 isc_time_t refreshkeytime;
235 uint32_t refreshkeyinterval;
236 uint32_t refreshkeycount;
237 uint32_t refresh;
238 uint32_t retry;
239 uint32_t expire;
240 uint32_t minimum;
241 isc_stdtime_t key_expiry;
242 isc_stdtime_t log_key_expired_timer;
243 char *keydirectory;
244
245 uint32_t maxrefresh;
246 uint32_t minrefresh;
247 uint32_t maxretry;
248 uint32_t minretry;
249
250 uint32_t maxrecords;
251
252 isc_sockaddr_t *masters;
253 isc_dscp_t *masterdscps;
254 dns_name_t **masterkeynames;
255 bool *mastersok;
256 unsigned int masterscnt;
257 unsigned int curmaster;
258 isc_sockaddr_t masteraddr;
259 dns_notifytype_t notifytype;
260 isc_sockaddr_t *notify;
261 dns_name_t **notifykeynames;
262 isc_dscp_t *notifydscp;
263 unsigned int notifycnt;
264 isc_sockaddr_t notifyfrom;
265 isc_task_t *task;
266 isc_task_t *loadtask;
267 isc_sockaddr_t notifysrc4;
268 isc_sockaddr_t notifysrc6;
269 isc_sockaddr_t xfrsource4;
270 isc_sockaddr_t xfrsource6;
271 isc_sockaddr_t altxfrsource4;
272 isc_sockaddr_t altxfrsource6;
273 isc_sockaddr_t sourceaddr;
274 isc_dscp_t notifysrc4dscp;
275 isc_dscp_t notifysrc6dscp;
276 isc_dscp_t xfrsource4dscp;
277 isc_dscp_t xfrsource6dscp;
278 isc_dscp_t altxfrsource4dscp;
279 isc_dscp_t altxfrsource6dscp;
280 dns_xfrin_ctx_t *xfr; /* task locked */
281 dns_tsigkey_t *tsigkey; /* key used for xfr */
282 /* Access Control Lists */
283 dns_acl_t *update_acl;
284 dns_acl_t *forward_acl;
285 dns_acl_t *notify_acl;
286 dns_acl_t *query_acl;
287 dns_acl_t *queryon_acl;
288 dns_acl_t *xfr_acl;
289 bool update_disabled;
290 bool zero_no_soa_ttl;
291 dns_severity_t check_names;
292 ISC_LIST(dns_notify_t) notifies;
293 dns_request_t *request;
294 dns_loadctx_t *lctx;
295 dns_io_t *readio;
296 dns_dumpctx_t *dctx;
297 dns_io_t *writeio;
298 uint32_t maxxfrin;
299 uint32_t maxxfrout;
300 uint32_t idlein;
301 uint32_t idleout;
302 isc_event_t ctlevent;
303 dns_ssutable_t *ssutable;
304 uint32_t sigvalidityinterval;
305 uint32_t keyvalidityinterval;
306 uint32_t sigresigninginterval;
307 dns_view_t *view;
308 dns_view_t *prev_view;
309 dns_checkmxfunc_t checkmx;
310 dns_checksrvfunc_t checksrv;
311 dns_checknsfunc_t checkns;
312 /*%
313 * Zones in certain states such as "waiting for zone transfer"
314 * or "zone transfer in progress" are kept on per-state linked lists
315 * in the zone manager using the 'statelink' field. The 'statelist'
316 * field points at the list the zone is currently on. It the zone
317 * is not on any such list, statelist is NULL.
318 */
319 ISC_LINK(dns_zone_t) statelink;
320 dns_zonelist_t *statelist;
321 /*%
322 * Statistics counters about zone management.
323 */
324 isc_stats_t *stats;
325 /*%
326 * Optional per-zone statistics counters. Counted outside of this
327 * module.
328 */
329 dns_zonestat_level_t statlevel;
330 bool requeststats_on;
331 isc_stats_t *requeststats;
332 dns_stats_t *rcvquerystats;
333 uint32_t notifydelay;
334 dns_isselffunc_t isself;
335 void *isselfarg;
336
337 char * strnamerd;
338 char * strname;
339 char * strrdclass;
340 char * strviewname;
341
342 /*%
343 * Serial number for deferred journal compaction.
344 */
345 uint32_t compact_serial;
346 /*%
347 * Keys that are signing the zone for the first time.
348 */
349 dns_signinglist_t signing;
350 dns_nsec3chainlist_t nsec3chain;
351 /*%
352 * List of outstanding NSEC3PARAM change requests.
353 */
354 isc_eventlist_t setnsec3param_queue;
355 /*%
356 * Signing / re-signing quantum stopping parameters.
357 */
358 uint32_t signatures;
359 uint32_t nodes;
360 dns_rdatatype_t privatetype;
361
362 /*%
363 * Autosigning/key-maintenance options
364 */
365 uint32_t keyopts;
366
367 /*%
368 * True if added by "rndc addzone"
369 */
370 bool added;
371
372 /*%
373 * True if added by automatically by named.
374 */
375 bool automatic;
376
377 /*%
378 * response policy data to be relayed to the database
379 */
380 dns_rpz_zones_t *rpzs;
381 dns_rpz_num_t rpz_num;
382
383 /*%
384 * catalog zone data
385 */
386 dns_catz_zones_t *catzs;
387
388 /*%
389 * parent catalog zone
390 */
391 dns_catz_zone_t *parentcatz;
392
393 /*%
394 * Serial number update method.
395 */
396 dns_updatemethod_t updatemethod;
397
398 /*%
399 * whether ixfr is requested
400 */
401 bool requestixfr;
402
403 /*%
404 * whether EDNS EXPIRE is requested
405 */
406 bool requestexpire;
407
408 /*%
409 * Outstanding forwarded UPDATE requests.
410 */
411 dns_forwardlist_t forwards;
412
413 dns_zone_t *raw;
414 dns_zone_t *secure;
415
416 bool sourceserialset;
417 uint32_t sourceserial;
418
419 /*%
420 * maximum zone ttl
421 */
422 dns_ttl_t maxttl;
423
424 /*
425 * Inline zone signing state.
426 */
427 dns_diff_t rss_diff;
428 isc_eventlist_t rss_events;
429 dns_dbversion_t *rss_newver;
430 dns_dbversion_t *rss_oldver;
431 dns_db_t *rss_db;
432 dns_zone_t *rss_raw;
433 isc_event_t *rss_event;
434 dns_update_state_t *rss_state;
435
436 isc_stats_t *gluecachestats;
437 };
438
439 #define zonediff_init(z, d) \
440 do { \
441 dns__zonediff_t *_z = (z); \
442 (_z)->diff = (d); \
443 (_z)->offline = false; \
444 } while (/*CONSTCOND*/0)
445
446 #define DNS_ZONE_FLAG(z,f) ((z)->flags & (f))
447 #define DNS_ZONE_SETFLAG(z,f) do { \
448 INSIST(LOCKED_ZONE(z)); \
449 (z)->flags |= (f); \
450 } while (/*CONSTCOND*/0)
451 #define DNS_ZONE_CLRFLAG(z,f) do { \
452 INSIST(LOCKED_ZONE(z)); \
453 (z)->flags &= ~(f); \
454 } while (/*CONSTCOND*/0)
455 /* XXX MPA these may need to go back into zone.h */
456 #define DNS_ZONEFLG_REFRESH 0x00000001U /*%< refresh check in progress */
457 #define DNS_ZONEFLG_NEEDDUMP 0x00000002U /*%< zone need consolidation */
458 #define DNS_ZONEFLG_USEVC 0x00000004U /*%< use tcp for refresh query */
459 #define DNS_ZONEFLG_DUMPING 0x00000008U /*%< a dump is in progress */
460 #define DNS_ZONEFLG_HASINCLUDE 0x00000010U /*%< $INCLUDE in zone file */
461 #define DNS_ZONEFLG_LOADED 0x00000020U /*%< database has loaded */
462 #define DNS_ZONEFLG_EXITING 0x00000040U /*%< zone is being destroyed */
463 #define DNS_ZONEFLG_EXPIRED 0x00000080U /*%< zone has expired */
464 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /*%< refresh check needed */
465 #define DNS_ZONEFLG_UPTODATE 0x00000200U /*%< zone contents are
466 * uptodate */
467 #define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /*%< need to send out notify
468 * messages */
469 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /*%< generate a journal diff on
470 * reload */
471 #define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
472 * zone with no masters
473 * occurred */
474 #define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
475 #define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
476 * from SOA (if not set, we
477 * are still using
478 * default timer values) */
479 #define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
480 #define DNS_ZONEFLG_NOREFRESH 0x00010000U
481 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
482 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
483 #define DNS_ZONEFLG_SHUTDOWN 0x00080000U
484 #define DNS_ZONEFLAG_NOIXFR 0x00100000U /*%< IXFR failed, force AXFR */
485 #define DNS_ZONEFLG_FLUSH 0x00200000U
486 #define DNS_ZONEFLG_NOEDNS 0x00400000U
487 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
488 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
489 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
490 #define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */
491 #define DNS_ZONEFLG_THAW 0x08000000U
492 #define DNS_ZONEFLG_LOADPENDING 0x10000000U /*%< Loading scheduled */
493 #define DNS_ZONEFLG_NODELAY 0x20000000U
494 #define DNS_ZONEFLG_SENDSECURE 0x40000000U
495 #define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
496 * due to the zone just
497 * being loaded for the
498 * first time. */
499
500 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
501 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
502
503 /* Flags for zone_load() */
504 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
505 #define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
506 load. */
507
508 #define UNREACH_CHACHE_SIZE 10U
509 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
510
511 #define CHECK(op) \
512 do { result = (op); \
513 if (result != ISC_R_SUCCESS) goto failure; \
514 } while (/*CONSTCOND*/0)
515
516 struct dns_unreachable {
517 isc_sockaddr_t remote;
518 isc_sockaddr_t local;
519 uint32_t expire;
520 uint32_t last;
521 uint32_t count;
522 };
523
524 struct dns_zonemgr {
525 unsigned int magic;
526 isc_mem_t * mctx;
527 int refs; /* Locked by rwlock */
528 isc_taskmgr_t * taskmgr;
529 isc_timermgr_t * timermgr;
530 isc_socketmgr_t * socketmgr;
531 isc_taskpool_t * zonetasks;
532 isc_taskpool_t * loadtasks;
533 isc_task_t * task;
534 isc_pool_t * mctxpool;
535 isc_ratelimiter_t * notifyrl;
536 isc_ratelimiter_t * refreshrl;
537 isc_ratelimiter_t * startupnotifyrl;
538 isc_ratelimiter_t * startuprefreshrl;
539 isc_rwlock_t rwlock;
540 isc_mutex_t iolock;
541 isc_rwlock_t urlock;
542
543 /* Locked by rwlock. */
544 dns_zonelist_t zones;
545 dns_zonelist_t waiting_for_xfrin;
546 dns_zonelist_t xfrin_in_progress;
547
548 /* Configuration data. */
549 uint32_t transfersin;
550 uint32_t transfersperns;
551 unsigned int notifyrate;
552 unsigned int startupnotifyrate;
553 unsigned int serialqueryrate;
554 unsigned int startupserialqueryrate;
555
556 /* Locked by iolock */
557 uint32_t iolimit;
558 uint32_t ioactive;
559 dns_iolist_t high;
560 dns_iolist_t low;
561
562 /* Locked by urlock. */
563 /* LRU cache */
564 struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
565 };
566
567 /*%
568 * Hold notify state.
569 */
570 struct dns_notify {
571 unsigned int magic;
572 unsigned int flags;
573 isc_mem_t *mctx;
574 dns_zone_t *zone;
575 dns_adbfind_t *find;
576 dns_request_t *request;
577 dns_name_t ns;
578 isc_sockaddr_t dst;
579 dns_tsigkey_t *key;
580 isc_dscp_t dscp;
581 ISC_LINK(dns_notify_t) link;
582 isc_event_t *event;
583 };
584
585 #define DNS_NOTIFY_NOSOA 0x0001U
586 #define DNS_NOTIFY_STARTUP 0x0002U
587
588 /*%
589 * dns_stub holds state while performing a 'stub' transfer.
590 * 'db' is the zone's 'db' or a new one if this is the initial
591 * transfer.
592 */
593
594 struct dns_stub {
595 unsigned int magic;
596 isc_mem_t *mctx;
597 dns_zone_t *zone;
598 dns_db_t *db;
599 dns_dbversion_t *version;
600 };
601
602 /*%
603 * Hold load state.
604 */
605 struct dns_load {
606 unsigned int magic;
607 isc_mem_t *mctx;
608 dns_zone_t *zone;
609 dns_db_t *db;
610 isc_time_t loadtime;
611 dns_rdatacallbacks_t callbacks;
612 };
613
614 /*%
615 * Hold forward state.
616 */
617 struct dns_forward {
618 unsigned int magic;
619 isc_mem_t *mctx;
620 dns_zone_t *zone;
621 isc_buffer_t *msgbuf;
622 dns_request_t *request;
623 uint32_t which;
624 isc_sockaddr_t addr;
625 dns_updatecallback_t callback;
626 void *callback_arg;
627 unsigned int options;
628 ISC_LINK(dns_forward_t) link;
629 };
630
631 /*%
632 * Hold IO request state.
633 */
634 struct dns_io {
635 unsigned int magic;
636 dns_zonemgr_t *zmgr;
637 bool high;
638 isc_task_t *task;
639 ISC_LINK(dns_io_t) link;
640 isc_event_t *event;
641 };
642
643 /*%
644 * Hold state for when we are signing a zone with a new
645 * DNSKEY as result of an update.
646 */
647 struct dns_signing {
648 unsigned int magic;
649 dns_db_t *db;
650 dns_dbiterator_t *dbiterator;
651 dns_secalg_t algorithm;
652 uint16_t keyid;
653 bool deleteit;
654 bool done;
655 ISC_LINK(dns_signing_t) link;
656 };
657
658 struct dns_nsec3chain {
659 unsigned int magic;
660 dns_db_t *db;
661 dns_dbiterator_t *dbiterator;
662 dns_rdata_nsec3param_t nsec3param;
663 unsigned char salt[255];
664 bool done;
665 bool seen_nsec;
666 bool delete_nsec;
667 bool save_delete_nsec;
668 ISC_LINK(dns_nsec3chain_t) link;
669 };
670 /*%<
671 * 'dbiterator' contains a iterator for the database. If we are creating
672 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
673 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
674 * iterated.
675 *
676 * 'nsec3param' contains the parameters of the NSEC3 chain being created
677 * or removed.
678 *
679 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
680 *
681 * 'seen_nsec' will be set to true if, while iterating the zone to create a
682 * NSEC3 chain, a NSEC record is seen.
683 *
684 * 'delete_nsec' will be set to true if, at the completion of the creation
685 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
686 * are in the process of deleting the NSEC chain.
687 *
688 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
689 * so it can be recovered in the event of a error.
690 */
691
692 struct dns_keyfetch {
693 dns_fixedname_t name;
694 dns_rdataset_t keydataset;
695 dns_rdataset_t dnskeyset;
696 dns_rdataset_t dnskeysigset;
697 dns_zone_t *zone;
698 dns_db_t *db;
699 dns_fetch_t *fetch;
700 };
701
702 /*%
703 * Hold state for an asynchronous load
704 */
705 struct dns_asyncload {
706 dns_zone_t *zone;
707 unsigned int flags;
708 dns_zt_zoneloaded_t loaded;
709 void *loaded_arg;
710 };
711
712 /*%
713 * Reference to an include file encountered during loading
714 */
715 struct dns_include {
716 char *name;
717 isc_time_t filetime;
718 ISC_LINK(dns_include_t) link;
719 };
720
721 /*
722 * These can be overridden by the -T mkeytimers option on the command
723 * line, so that we can test with shorter periods than specified in
724 * RFC 5011.
725 */
726 #define HOUR 3600
727 #define DAY (24*HOUR)
728 #define MONTH (30*DAY)
729 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
730 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
731 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
732
733 #define SEND_BUFFER_SIZE 2048
734
735 static void zone_settimer(dns_zone_t *, isc_time_t *);
736 static void cancel_refresh(dns_zone_t *);
737 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
738 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
739 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
740 ISC_FORMAT_PRINTF(3, 4);
741 static void dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
742 ISC_FORMAT_PRINTF(3, 4);
743 static void queue_xfrin(dns_zone_t *zone);
744 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
745 dns_diff_t *diff, dns_diffop_t op,
746 dns_name_t *name, dns_ttl_t ttl,
747 dns_rdata_t *rdata);
748 static void zone_unload(dns_zone_t *zone);
749 static void zone_expire(dns_zone_t *zone);
750 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
751 static void zone_idetach(dns_zone_t **zonep);
752 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
753 bool dump);
754 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
755 static inline void zone_detachdb(dns_zone_t *zone);
756 static isc_result_t default_journal(dns_zone_t *zone);
757 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
758 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
759 isc_time_t loadtime, isc_result_t result);
760 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
761 static void zone_shutdown(isc_task_t *, isc_event_t *);
762 static void zone_loaddone(void *arg, isc_result_t result);
763 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
764 isc_time_t loadtime);
765 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
766 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
767 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
768 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
769 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
770 uint32_t serial);
771 static void refresh_callback(isc_task_t *, isc_event_t *);
772 static void stub_callback(isc_task_t *, isc_event_t *);
773 static void queue_soa_query(dns_zone_t *zone);
774 static void soa_query(isc_task_t *, isc_event_t *);
775 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
776 dns_stub_t *stub);
777 static int message_count(dns_message_t *msg, dns_section_t section,
778 dns_rdatatype_t type);
779 static void notify_cancel(dns_zone_t *zone);
780 static void notify_find_address(dns_notify_t *notify);
781 static void notify_send(dns_notify_t *notify);
782 static isc_result_t notify_createmessage(dns_zone_t *zone,
783 unsigned int flags,
784 dns_message_t **messagep);
785 static void notify_done(isc_task_t *task, isc_event_t *event);
786 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
787 static isc_result_t zone_dump(dns_zone_t *, bool);
788 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
789 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
790 dns_zone_t *zone);
791 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
792 static void zonemgr_free(dns_zonemgr_t *zmgr);
793 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
794 isc_task_t *task, isc_taskaction_t action,
795 void *arg, dns_io_t **iop);
796 static void zonemgr_putio(dns_io_t **iop);
797 static void zonemgr_cancelio(dns_io_t *io);
798
799 static isc_result_t
800 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
801 unsigned int *soacount, uint32_t *serial,
802 uint32_t *refresh, uint32_t *retry,
803 uint32_t *expire, uint32_t *minimum,
804 unsigned int *errors);
805
806 static void zone_freedbargs(dns_zone_t *zone);
807 static void forward_callback(isc_task_t *task, isc_event_t *event);
808 static void zone_saveunique(dns_zone_t *zone, const char *path,
809 const char *templat);
810 static void zone_maintenance(dns_zone_t *zone);
811 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
812 static void dump_done(void *arg, isc_result_t result);
813 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
814 uint16_t keyid,
815 bool deleteit);
816 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
817 dns_dbnode_t *node, dns_name_t *name,
818 dns_diff_t *diff);
819 static void zone_rekey(dns_zone_t *zone);
820 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
821 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
822 unsigned int value);
823
824 #define ENTER zone_debuglog(zone, me, 1, "enter")
825
826 static const unsigned int dbargc_default = 1;
827 static const char *dbargv_default[] = { "rbt" };
828
829 #define DNS_ZONE_JITTER_ADD(a, b, c) \
830 do { \
831 isc_interval_t _i; \
832 uint32_t _j; \
833 _j = (b) - isc_random_uniform((b)/4); \
834 isc_interval_set(&_i, _j, 0); \
835 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
836 dns_zone_log(zone, ISC_LOG_WARNING, \
837 "epoch approaching: upgrade required: " \
838 "now + %s failed", #b); \
839 isc_interval_set(&_i, _j/2, 0); \
840 (void)isc_time_add((a), &_i, (c)); \
841 } \
842 } while (/*CONSTCOND*/0)
843
844 #define DNS_ZONE_TIME_ADD(a, b, c) \
845 do { \
846 isc_interval_t _i; \
847 isc_interval_set(&_i, (b), 0); \
848 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
849 dns_zone_log(zone, ISC_LOG_WARNING, \
850 "epoch approaching: upgrade required: " \
851 "now + %s failed", #b); \
852 isc_interval_set(&_i, (b)/2, 0); \
853 (void)isc_time_add((a), &_i, (c)); \
854 } \
855 } while (/*CONSTCOND*/0)
856
857 typedef struct nsec3param nsec3param_t;
858 struct nsec3param {
859 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
860 unsigned int length;
861 bool nsec;
862 bool replace;
863 ISC_LINK(nsec3param_t) link;
864 };
865 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
866 struct np3event {
867 isc_event_t event;
868 nsec3param_t params;
869 };
870
871 struct ssevent {
872 isc_event_t event;
873 uint32_t serial;
874 };
875
876 /*%
877 * Increment resolver-related statistics counters. Zone must be locked.
878 */
879 static inline void
880 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
881 if (zone->stats != NULL)
882 isc_stats_increment(zone->stats, counter);
883 }
884
885 /***
886 *** Public functions.
887 ***/
888
889 isc_result_t
890 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
891 isc_result_t result;
892 dns_zone_t *zone;
893 isc_time_t now;
894
895 REQUIRE(zonep != NULL && *zonep == NULL);
896 REQUIRE(mctx != NULL);
897
898 TIME_NOW(&now);
899 zone = isc_mem_get(mctx, sizeof(*zone));
900 if (zone == NULL) {
901 return (ISC_R_NOMEMORY);
902 }
903
904 zone->mctx = NULL;
905 isc_mem_attach(mctx, &zone->mctx);
906
907 isc_mutex_init(&zone->lock);
908
909 result = ZONEDB_INITLOCK(&zone->dblock);
910 if (result != ISC_R_SUCCESS) {
911 goto free_mutex;
912 }
913
914 /* XXX MPA check that all elements are initialised */
915 #ifdef DNS_ZONE_CHECKLOCK
916 zone->locked = false;
917 #endif
918 zone->db = NULL;
919 zone->zmgr = NULL;
920 ISC_LINK_INIT(zone, link);
921 isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
922 zone->irefs = 0;
923 dns_name_init(&zone->origin, NULL);
924 zone->strnamerd = NULL;
925 zone->strname = NULL;
926 zone->strrdclass = NULL;
927 zone->strviewname = NULL;
928 zone->masterfile = NULL;
929 ISC_LIST_INIT(zone->includes);
930 ISC_LIST_INIT(zone->newincludes);
931 zone->nincludes = 0;
932 zone->masterformat = dns_masterformat_none;
933 zone->masterstyle = NULL;
934 zone->keydirectory = NULL;
935 zone->journalsize = -1;
936 zone->journal = NULL;
937 zone->rdclass = dns_rdataclass_none;
938 zone->type = dns_zone_none;
939 zone->flags = 0;
940 zone->options = 0;
941 zone->keyopts = 0;
942 zone->db_argc = 0;
943 zone->db_argv = NULL;
944 isc_time_settoepoch(&zone->expiretime);
945 isc_time_settoepoch(&zone->refreshtime);
946 isc_time_settoepoch(&zone->dumptime);
947 isc_time_settoepoch(&zone->loadtime);
948 zone->notifytime = now;
949 isc_time_settoepoch(&zone->resigntime);
950 isc_time_settoepoch(&zone->keywarntime);
951 isc_time_settoepoch(&zone->signingtime);
952 isc_time_settoepoch(&zone->nsec3chaintime);
953 isc_time_settoepoch(&zone->refreshkeytime);
954 zone->refreshkeyinterval = 0;
955 zone->refreshkeycount = 0;
956 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
957 zone->retry = DNS_ZONE_DEFAULTRETRY;
958 zone->expire = 0;
959 zone->minimum = 0;
960 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
961 zone->minrefresh = DNS_ZONE_MINREFRESH;
962 zone->maxretry = DNS_ZONE_MAXRETRY;
963 zone->minretry = DNS_ZONE_MINRETRY;
964 zone->masters = NULL;
965 zone->masterdscps = NULL;
966 zone->masterkeynames = NULL;
967 zone->mastersok = NULL;
968 zone->masterscnt = 0;
969 zone->curmaster = 0;
970 zone->maxttl = 0;
971 zone->notify = NULL;
972 zone->notifykeynames = NULL;
973 zone->notifydscp = NULL;
974 zone->notifytype = dns_notifytype_yes;
975 zone->notifycnt = 0;
976 zone->task = NULL;
977 zone->loadtask = NULL;
978 zone->update_acl = NULL;
979 zone->forward_acl = NULL;
980 zone->notify_acl = NULL;
981 zone->query_acl = NULL;
982 zone->queryon_acl = NULL;
983 zone->xfr_acl = NULL;
984 zone->update_disabled = false;
985 zone->zero_no_soa_ttl = true;
986 zone->check_names = dns_severity_ignore;
987 zone->request = NULL;
988 zone->lctx = NULL;
989 zone->readio = NULL;
990 zone->dctx = NULL;
991 zone->writeio = NULL;
992 zone->timer = NULL;
993 zone->idlein = DNS_DEFAULT_IDLEIN;
994 zone->idleout = DNS_DEFAULT_IDLEOUT;
995 zone->log_key_expired_timer = 0;
996 ISC_LIST_INIT(zone->notifies);
997 isc_sockaddr_any(&zone->notifysrc4);
998 isc_sockaddr_any6(&zone->notifysrc6);
999 isc_sockaddr_any(&zone->xfrsource4);
1000 isc_sockaddr_any6(&zone->xfrsource6);
1001 isc_sockaddr_any(&zone->altxfrsource4);
1002 isc_sockaddr_any6(&zone->altxfrsource6);
1003 zone->notifysrc4dscp = -1;
1004 zone->notifysrc6dscp = -1;
1005 zone->xfrsource4dscp = -1;
1006 zone->xfrsource6dscp = -1;
1007 zone->altxfrsource4dscp = -1;
1008 zone->altxfrsource6dscp = -1;
1009 zone->xfr = NULL;
1010 zone->tsigkey = NULL;
1011 zone->maxxfrin = MAX_XFER_TIME;
1012 zone->maxxfrout = MAX_XFER_TIME;
1013 zone->ssutable = NULL;
1014 zone->sigvalidityinterval = 30 * 24 * 3600;
1015 zone->keyvalidityinterval = 0;
1016 zone->sigresigninginterval = 7 * 24 * 3600;
1017 zone->view = NULL;
1018 zone->prev_view = NULL;
1019 zone->checkmx = NULL;
1020 zone->checksrv = NULL;
1021 zone->checkns = NULL;
1022 ISC_LINK_INIT(zone, statelink);
1023 zone->statelist = NULL;
1024 zone->stats = NULL;
1025 zone->requeststats_on = false;
1026 zone->statlevel = dns_zonestat_none;
1027 zone->requeststats = NULL;
1028 zone->rcvquerystats = NULL;
1029 zone->notifydelay = 5;
1030 zone->isself = NULL;
1031 zone->isselfarg = NULL;
1032 ISC_LIST_INIT(zone->signing);
1033 ISC_LIST_INIT(zone->nsec3chain);
1034 ISC_LIST_INIT(zone->setnsec3param_queue);
1035 zone->signatures = 10;
1036 zone->nodes = 100;
1037 zone->privatetype = (dns_rdatatype_t)0xffffU;
1038 zone->added = false;
1039 zone->automatic = false;
1040 zone->rpzs = NULL;
1041 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1042
1043 zone->catzs = NULL;
1044 zone->parentcatz = NULL;
1045
1046 ISC_LIST_INIT(zone->forwards);
1047 zone->raw = NULL;
1048 zone->secure = NULL;
1049 zone->sourceserial = 0;
1050 zone->sourceserialset = false;
1051 zone->requestixfr = true;
1052 zone->requestexpire = true;
1053 ISC_LIST_INIT(zone->rss_events);
1054 zone->rss_db = NULL;
1055 zone->rss_raw = NULL;
1056 zone->rss_newver = NULL;
1057 zone->rss_oldver = NULL;
1058 zone->rss_event = NULL;
1059 zone->rss_state = NULL;
1060 zone->updatemethod = dns_updatemethod_increment;
1061 zone->maxrecords = 0U;
1062
1063 zone->magic = ZONE_MAGIC;
1064
1065 zone->gluecachestats = NULL;
1066 result = isc_stats_create(mctx, &zone->gluecachestats,
1067 dns_gluecachestatscounter_max);
1068 if (result != ISC_R_SUCCESS) {
1069 goto free_erefs;
1070 }
1071
1072 /* Must be after magic is set. */
1073 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1074 if (result != ISC_R_SUCCESS) {
1075 goto free_stats;
1076 }
1077
1078 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1079 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
1080 NULL, NULL);
1081 *zonep = zone;
1082 return (ISC_R_SUCCESS);
1083
1084 free_stats:
1085 if (zone->gluecachestats != NULL)
1086 isc_stats_detach(&zone->gluecachestats);
1087
1088 free_erefs:
1089 INSIST(isc_refcount_decrement(&zone->erefs) > 0);
1090 isc_refcount_destroy(&zone->erefs);
1091
1092 ZONEDB_DESTROYLOCK(&zone->dblock);
1093
1094 free_mutex:
1095 isc_mutex_destroy(&zone->lock);
1096
1097 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1098 return (result);
1099 }
1100
1101 /*
1102 * Free a zone. Because we require that there be no more
1103 * outstanding events or references, no locking is necessary.
1104 */
1105 static void
1106 zone_free(dns_zone_t *zone) {
1107 isc_mem_t *mctx = NULL;
1108 dns_signing_t *signing;
1109 dns_nsec3chain_t *nsec3chain;
1110 isc_event_t *setnsec3param_event;
1111 dns_include_t *include;
1112
1113 REQUIRE(DNS_ZONE_VALID(zone));
1114 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
1115 REQUIRE(zone->irefs == 0);
1116 REQUIRE(!LOCKED_ZONE(zone));
1117 REQUIRE(zone->timer == NULL);
1118 REQUIRE(zone->zmgr == NULL);
1119
1120 /*
1121 * Managed objects. Order is important.
1122 */
1123 if (zone->request != NULL) {
1124 dns_request_destroy(&zone->request); /* XXXMPA */
1125 }
1126 INSIST(zone->readio == NULL);
1127 INSIST(zone->statelist == NULL);
1128 INSIST(zone->writeio == NULL);
1129
1130 if (zone->task != NULL) {
1131 isc_task_detach(&zone->task);
1132 }
1133 if (zone->loadtask != NULL) {
1134 isc_task_detach(&zone->loadtask);
1135 }
1136 if (zone->view != NULL) {
1137 dns_view_weakdetach(&zone->view);
1138 }
1139 if (zone->prev_view != NULL) {
1140 dns_view_weakdetach(&zone->prev_view);
1141 }
1142
1143 /* Unmanaged objects */
1144 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1145 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1146 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
1147 ev_link);
1148 isc_event_free(&setnsec3param_event);
1149 }
1150 for (signing = ISC_LIST_HEAD(zone->signing);
1151 signing != NULL;
1152 signing = ISC_LIST_HEAD(zone->signing)) {
1153 ISC_LIST_UNLINK(zone->signing, signing, link);
1154 dns_db_detach(&signing->db);
1155 dns_dbiterator_destroy(&signing->dbiterator);
1156 isc_mem_put(zone->mctx, signing, sizeof *signing);
1157 }
1158 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1159 nsec3chain != NULL;
1160 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1161 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1162 dns_db_detach(&nsec3chain->db);
1163 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1164 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1165 }
1166 for (include = ISC_LIST_HEAD(zone->includes);
1167 include != NULL;
1168 include = ISC_LIST_HEAD(zone->includes)) {
1169 ISC_LIST_UNLINK(zone->includes, include, link);
1170 isc_mem_free(zone->mctx, include->name);
1171 isc_mem_put(zone->mctx, include, sizeof *include);
1172 }
1173 for (include = ISC_LIST_HEAD(zone->newincludes);
1174 include != NULL;
1175 include = ISC_LIST_HEAD(zone->newincludes)) {
1176 ISC_LIST_UNLINK(zone->newincludes, include, link);
1177 isc_mem_free(zone->mctx, include->name);
1178 isc_mem_put(zone->mctx, include, sizeof *include);
1179 }
1180 if (zone->masterfile != NULL) {
1181 isc_mem_free(zone->mctx, zone->masterfile);
1182 }
1183 zone->masterfile = NULL;
1184 if (zone->keydirectory != NULL) {
1185 isc_mem_free(zone->mctx, zone->keydirectory);
1186 }
1187 zone->keydirectory = NULL;
1188 zone->journalsize = -1;
1189 if (zone->journal != NULL) {
1190 isc_mem_free(zone->mctx, zone->journal);
1191 }
1192 zone->journal = NULL;
1193 if (zone->stats != NULL) {
1194 isc_stats_detach(&zone->stats);
1195 }
1196 if (zone->requeststats != NULL) {
1197 isc_stats_detach(&zone->requeststats);
1198 }
1199 if (zone->rcvquerystats != NULL){
1200 dns_stats_detach(&zone->rcvquerystats);
1201 }
1202 if (zone->db != NULL) {
1203 zone_detachdb(zone);
1204 }
1205 if (zone->rpzs != NULL) {
1206 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1207 dns_rpz_detach_rpzs(&zone->rpzs);
1208 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1209 }
1210 if (zone->catzs != NULL) {
1211 dns_catz_catzs_detach(&zone->catzs);
1212 }
1213 zone_freedbargs(zone);
1214 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL,
1215 NULL, 0) == ISC_R_SUCCESS);
1216 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1217 zone->check_names = dns_severity_ignore;
1218 if (zone->update_acl != NULL) {
1219 dns_acl_detach(&zone->update_acl);
1220 }
1221 if (zone->forward_acl != NULL) {
1222 dns_acl_detach(&zone->forward_acl);
1223 }
1224 if (zone->notify_acl != NULL) {
1225 dns_acl_detach(&zone->notify_acl);
1226 }
1227 if (zone->query_acl != NULL) {
1228 dns_acl_detach(&zone->query_acl);
1229 }
1230 if (zone->queryon_acl != NULL) {
1231 dns_acl_detach(&zone->queryon_acl);
1232 }
1233 if (zone->xfr_acl != NULL) {
1234 dns_acl_detach(&zone->xfr_acl);
1235 }
1236 if (dns_name_dynamic(&zone->origin)) {
1237 dns_name_free(&zone->origin, zone->mctx);
1238 }
1239 if (zone->strnamerd != NULL) {
1240 isc_mem_free(zone->mctx, zone->strnamerd);
1241 }
1242 if (zone->strname != NULL) {
1243 isc_mem_free(zone->mctx, zone->strname);
1244 }
1245 if (zone->strrdclass != NULL) {
1246 isc_mem_free(zone->mctx, zone->strrdclass);
1247 }
1248 if (zone->strviewname != NULL) {
1249 isc_mem_free(zone->mctx, zone->strviewname);
1250 }
1251 if (zone->ssutable != NULL) {
1252 dns_ssutable_detach(&zone->ssutable);
1253 }
1254 if (zone->gluecachestats != NULL) {
1255 isc_stats_detach(&zone->gluecachestats);
1256 }
1257
1258 /* last stuff */
1259 ZONEDB_DESTROYLOCK(&zone->dblock);
1260 isc_mutex_destroy(&zone->lock);
1261 zone->magic = 0;
1262 mctx = zone->mctx;
1263 isc_mem_put(mctx, zone, sizeof(*zone));
1264 isc_mem_detach(&mctx);
1265 }
1266
1267 /*
1268 * Returns true iff this the signed side of an inline-signing zone.
1269 * Caller should hold zone lock.
1270 */
1271 static inline bool
1272 inline_secure(dns_zone_t *zone) {
1273 REQUIRE(DNS_ZONE_VALID(zone));
1274 if (zone->raw != NULL)
1275 return (true);
1276 return (false);
1277 }
1278
1279 /*
1280 * Returns true iff this the unsigned side of an inline-signing zone
1281 * Caller should hold zone lock.
1282 */
1283 static inline bool
1284 inline_raw(dns_zone_t *zone) {
1285 REQUIRE(DNS_ZONE_VALID(zone));
1286 if (zone->secure != NULL)
1287 return (true);
1288 return (false);
1289 }
1290
1291 /*
1292 * Single shot.
1293 */
1294 void
1295 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1296 char namebuf[1024];
1297
1298 REQUIRE(DNS_ZONE_VALID(zone));
1299 REQUIRE(rdclass != dns_rdataclass_none);
1300
1301 /*
1302 * Test and set.
1303 */
1304 LOCK_ZONE(zone);
1305 INSIST(zone != zone->raw);
1306 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1307 zone->rdclass == rdclass);
1308 zone->rdclass = rdclass;
1309
1310 if (zone->strnamerd != NULL)
1311 isc_mem_free(zone->mctx, zone->strnamerd);
1312 if (zone->strrdclass != NULL)
1313 isc_mem_free(zone->mctx, zone->strrdclass);
1314
1315 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1316 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1317 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1318 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1319
1320 if (inline_secure(zone))
1321 dns_zone_setclass(zone->raw, rdclass);
1322 UNLOCK_ZONE(zone);
1323 }
1324
1325 dns_rdataclass_t
1326 dns_zone_getclass(dns_zone_t *zone) {
1327 REQUIRE(DNS_ZONE_VALID(zone));
1328
1329 return (zone->rdclass);
1330 }
1331
1332 void
1333 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1334 REQUIRE(DNS_ZONE_VALID(zone));
1335
1336 LOCK_ZONE(zone);
1337 zone->notifytype = notifytype;
1338 UNLOCK_ZONE(zone);
1339 }
1340
1341 isc_result_t
1342 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1343 isc_result_t result;
1344 unsigned int soacount;
1345
1346 REQUIRE(DNS_ZONE_VALID(zone));
1347 REQUIRE(serialp != NULL);
1348
1349 LOCK_ZONE(zone);
1350 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1351 if (zone->db != NULL) {
1352 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1353 serialp, NULL, NULL, NULL, NULL,
1354 NULL);
1355 if (result == ISC_R_SUCCESS && soacount == 0)
1356 result = ISC_R_FAILURE;
1357 } else
1358 result = DNS_R_NOTLOADED;
1359 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1360 UNLOCK_ZONE(zone);
1361
1362 return (result);
1363 }
1364
1365 /*
1366 * Single shot.
1367 */
1368 void
1369 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1370 char namebuf[1024];
1371
1372 REQUIRE(DNS_ZONE_VALID(zone));
1373 REQUIRE(type != dns_zone_none);
1374
1375 /*
1376 * Test and set.
1377 */
1378 LOCK_ZONE(zone);
1379 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1380 zone->type = type;
1381
1382 if (zone->strnamerd != NULL)
1383 isc_mem_free(zone->mctx, zone->strnamerd);
1384
1385 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1386 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1387 UNLOCK_ZONE(zone);
1388 }
1389
1390 static void
1391 zone_freedbargs(dns_zone_t *zone) {
1392 unsigned int i;
1393
1394 /* Free the old database argument list. */
1395 if (zone->db_argv != NULL) {
1396 for (i = 0; i < zone->db_argc; i++)
1397 isc_mem_free(zone->mctx, zone->db_argv[i]);
1398 isc_mem_put(zone->mctx, zone->db_argv,
1399 zone->db_argc * sizeof(*zone->db_argv));
1400 }
1401 zone->db_argc = 0;
1402 zone->db_argv = NULL;
1403 }
1404
1405 isc_result_t
1406 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1407 size_t size = 0;
1408 unsigned int i;
1409 isc_result_t result = ISC_R_SUCCESS;
1410 void *mem;
1411 char **tmp, *tmp2, *base;
1412
1413 REQUIRE(DNS_ZONE_VALID(zone));
1414 REQUIRE(argv != NULL && *argv == NULL);
1415
1416 LOCK_ZONE(zone);
1417 size = (zone->db_argc + 1) * sizeof(char *);
1418 for (i = 0; i < zone->db_argc; i++)
1419 size += strlen(zone->db_argv[i]) + 1;
1420 mem = isc_mem_allocate(mctx, size);
1421 if (mem != NULL) {
1422 tmp = mem;
1423 tmp2 = mem;
1424 base = mem;
1425 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1426 for (i = 0; i < zone->db_argc; i++) {
1427 *tmp++ = tmp2;
1428 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1429 tmp2 += strlen(tmp2) + 1;
1430 }
1431 *tmp = NULL;
1432 } else
1433 result = ISC_R_NOMEMORY;
1434 UNLOCK_ZONE(zone);
1435 *argv = mem;
1436 return (result);
1437 }
1438
1439 isc_result_t
1440 dns_zone_setdbtype(dns_zone_t *zone,
1441 unsigned int dbargc, const char * const *dbargv)
1442 {
1443 isc_result_t result = ISC_R_SUCCESS;
1444 char **argv = NULL;
1445 unsigned int i;
1446
1447 REQUIRE(DNS_ZONE_VALID(zone));
1448 REQUIRE(dbargc >= 1);
1449 REQUIRE(dbargv != NULL);
1450
1451 LOCK_ZONE(zone);
1452
1453 /* Set up a new database argument list. */
1454 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1455 if (argv == NULL) {
1456 goto nomem;
1457 }
1458 for (i = 0; i < dbargc; i++) {
1459 argv[i] = NULL;
1460 }
1461 for (i = 0; i < dbargc; i++) {
1462 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1463 if (argv[i] == NULL)
1464 goto nomem;
1465 }
1466
1467 /* Free the old list. */
1468 zone_freedbargs(zone);
1469
1470 zone->db_argc = dbargc;
1471 zone->db_argv = argv;
1472 result = ISC_R_SUCCESS;
1473 goto unlock;
1474
1475 nomem:
1476 if (argv != NULL) {
1477 for (i = 0; i < dbargc; i++) {
1478 if (argv[i] != NULL) {
1479 isc_mem_free(zone->mctx, argv[i]);
1480 }
1481 }
1482 isc_mem_put(zone->mctx, argv, dbargc * sizeof(*argv));
1483 }
1484 result = ISC_R_NOMEMORY;
1485
1486 unlock:
1487 UNLOCK_ZONE(zone);
1488 return (result);
1489 }
1490
1491 static void
1492 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1493 char namebuf[1024];
1494
1495 if (zone->prev_view == NULL && zone->view != NULL) {
1496 dns_view_weakattach(zone->view, &zone->prev_view);
1497 }
1498
1499 INSIST(zone != zone->raw);
1500 if (zone->view != NULL) {
1501 dns_view_weakdetach(&zone->view);
1502 }
1503 dns_view_weakattach(view, &zone->view);
1504
1505 if (zone->strviewname != NULL) {
1506 isc_mem_free(zone->mctx, zone->strviewname);
1507 }
1508 if (zone->strnamerd != NULL) {
1509 isc_mem_free(zone->mctx, zone->strnamerd);
1510 }
1511
1512 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1513 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1514 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1515 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1516
1517 if (inline_secure(zone)) {
1518 dns_zone_setview(zone->raw, view);
1519 }
1520 }
1521
1522 void
1523 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1524 REQUIRE(DNS_ZONE_VALID(zone));
1525
1526 LOCK_ZONE(zone);
1527 dns_zone_setview_helper(zone, view);
1528 UNLOCK_ZONE(zone);
1529 }
1530
1531 dns_view_t *
1532 dns_zone_getview(dns_zone_t *zone) {
1533 REQUIRE(DNS_ZONE_VALID(zone));
1534
1535 return (zone->view);
1536 }
1537
1538 void
1539 dns_zone_setviewcommit(dns_zone_t *zone) {
1540 REQUIRE(DNS_ZONE_VALID(zone));
1541
1542 LOCK_ZONE(zone);
1543 if (zone->prev_view != NULL)
1544 dns_view_weakdetach(&zone->prev_view);
1545 UNLOCK_ZONE(zone);
1546 }
1547
1548 void
1549 dns_zone_setviewrevert(dns_zone_t *zone) {
1550 REQUIRE(DNS_ZONE_VALID(zone));
1551
1552 LOCK_ZONE(zone);
1553 if (zone->prev_view != NULL) {
1554 dns_zone_setview_helper(zone, zone->prev_view);
1555 dns_view_weakdetach(&zone->prev_view);
1556 }
1557 UNLOCK_ZONE(zone);
1558 }
1559
1560 isc_result_t
1561 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1562 isc_result_t result;
1563 char namebuf[1024];
1564
1565 REQUIRE(DNS_ZONE_VALID(zone));
1566 REQUIRE(origin != NULL);
1567
1568 LOCK_ZONE(zone);
1569 INSIST(zone != zone->raw);
1570 if (dns_name_dynamic(&zone->origin)) {
1571 dns_name_free(&zone->origin, zone->mctx);
1572 dns_name_init(&zone->origin, NULL);
1573 }
1574 result = dns_name_dup(origin, zone->mctx, &zone->origin);
1575
1576 if (zone->strnamerd != NULL)
1577 isc_mem_free(zone->mctx, zone->strnamerd);
1578 if (zone->strname != NULL)
1579 isc_mem_free(zone->mctx, zone->strname);
1580
1581 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1582 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1583 zone_name_tostr(zone, namebuf, sizeof namebuf);
1584 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1585
1586 if (result == ISC_R_SUCCESS && inline_secure(zone))
1587 result = dns_zone_setorigin(zone->raw, origin);
1588 UNLOCK_ZONE(zone);
1589 return (result);
1590 }
1591
1592 static isc_result_t
1593 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1594 char *copy;
1595
1596 if (value != NULL) {
1597 copy = isc_mem_strdup(zone->mctx, value);
1598 if (copy == NULL)
1599 return (ISC_R_NOMEMORY);
1600 } else {
1601 copy = NULL;
1602 }
1603
1604 if (*field != NULL)
1605 isc_mem_free(zone->mctx, *field);
1606
1607 *field = copy;
1608 return (ISC_R_SUCCESS);
1609 }
1610
1611 isc_result_t
1612 dns_zone_setfile(dns_zone_t *zone, const char *file,
1613 dns_masterformat_t format,
1614 const dns_master_style_t *style)
1615 {
1616 isc_result_t result = ISC_R_SUCCESS;
1617
1618 REQUIRE(DNS_ZONE_VALID(zone));
1619
1620 LOCK_ZONE(zone);
1621 result = dns_zone_setstring(zone, &zone->masterfile, file);
1622 if (result == ISC_R_SUCCESS) {
1623 zone->masterformat = format;
1624 if (format == dns_masterformat_text)
1625 zone->masterstyle = style;
1626 result = default_journal(zone);
1627 }
1628 UNLOCK_ZONE(zone);
1629
1630 return (result);
1631 }
1632
1633 const char *
1634 dns_zone_getfile(dns_zone_t *zone) {
1635 REQUIRE(DNS_ZONE_VALID(zone));
1636
1637 return (zone->masterfile);
1638 }
1639
1640 dns_ttl_t
1641 dns_zone_getmaxttl(dns_zone_t *zone) {
1642 REQUIRE(DNS_ZONE_VALID(zone));
1643
1644 return (zone->maxttl);
1645 }
1646
1647 void
1648 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1649 REQUIRE(DNS_ZONE_VALID(zone));
1650
1651 LOCK_ZONE(zone);
1652 if (maxttl != 0)
1653 zone->options |= DNS_ZONEOPT_CHECKTTL;
1654 else
1655 zone->options &= ~DNS_ZONEOPT_CHECKTTL;
1656 zone->maxttl = maxttl;
1657 UNLOCK_ZONE(zone);
1658
1659 return;
1660 }
1661
1662 static isc_result_t
1663 default_journal(dns_zone_t *zone) {
1664 isc_result_t result;
1665 char *journal;
1666
1667 REQUIRE(DNS_ZONE_VALID(zone));
1668 REQUIRE(LOCKED_ZONE(zone));
1669
1670 if (zone->masterfile != NULL) {
1671 /* Calculate string length including '\0'. */
1672 int len = strlen(zone->masterfile) + sizeof(".jnl");
1673 journal = isc_mem_allocate(zone->mctx, len);
1674 if (journal == NULL)
1675 return (ISC_R_NOMEMORY);
1676 strlcpy(journal, zone->masterfile, len);
1677 strlcat(journal, ".jnl", len);
1678 } else {
1679 journal = NULL;
1680 }
1681 result = dns_zone_setstring(zone, &zone->journal, journal);
1682 if (journal != NULL)
1683 isc_mem_free(zone->mctx, journal);
1684 return (result);
1685 }
1686
1687 isc_result_t
1688 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1689 isc_result_t result = ISC_R_SUCCESS;
1690
1691 REQUIRE(DNS_ZONE_VALID(zone));
1692
1693 LOCK_ZONE(zone);
1694 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1695 UNLOCK_ZONE(zone);
1696
1697 return (result);
1698 }
1699
1700 char *
1701 dns_zone_getjournal(dns_zone_t *zone) {
1702 REQUIRE(DNS_ZONE_VALID(zone));
1703
1704 return (zone->journal);
1705 }
1706
1707 /*
1708 * Return true iff the zone is "dynamic", in the sense that the zone's
1709 * master file (if any) is written by the server, rather than being
1710 * updated manually and read by the server.
1711 *
1712 * This is true for slave zones, mirror zones, stub zones, key zones,
1713 * and zones that allow dynamic updates either by having an update
1714 * policy ("ssutable") or an "allow-update" ACL with a value other than
1715 * exactly "{ none; }".
1716 */
1717 bool
1718 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1719 REQUIRE(DNS_ZONE_VALID(zone));
1720
1721 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
1722 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1723 (zone->type == dns_zone_redirect && zone->masters != NULL))
1724 return (true);
1725
1726 /* Inline zones are always dynamic. */
1727 if (zone->type == dns_zone_master && zone->raw != NULL)
1728 return (true);
1729
1730 /* If !ignore_freeze, we need check whether updates are disabled. */
1731 if (zone->type == dns_zone_master &&
1732 (!zone->update_disabled || ignore_freeze) &&
1733 ((zone->ssutable != NULL) ||
1734 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1735 return (true);
1736
1737 return (false);
1738
1739 }
1740
1741 /*
1742 * Set the response policy index and information for a zone.
1743 */
1744 isc_result_t
1745 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1746 dns_rpz_num_t rpz_num)
1747 {
1748 /*
1749 * Only RBTDB zones can be used for response policy zones,
1750 * because only they have the code to load the create the summary data.
1751 * Only zones that are loaded instead of mmap()ed create the
1752 * summary data and so can be policy zones.
1753 */
1754 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1755 strcmp(zone->db_argv[0], "rbt64") != 0)
1756 return (ISC_R_NOTIMPLEMENTED);
1757 if (zone->masterformat == dns_masterformat_map)
1758 return (ISC_R_NOTIMPLEMENTED);
1759
1760 /*
1761 * This must happen only once or be redundant.
1762 */
1763 LOCK_ZONE(zone);
1764 if (zone->rpzs != NULL) {
1765 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1766 } else {
1767 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1768 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1769 zone->rpz_num = rpz_num;
1770 }
1771 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1772 UNLOCK_ZONE(zone);
1773
1774 return (ISC_R_SUCCESS);
1775 }
1776
1777 dns_rpz_num_t
1778 dns_zone_get_rpz_num(dns_zone_t *zone) {
1779 return (zone->rpz_num);
1780 }
1781
1782 /*
1783 * If a zone is a response policy zone, mark its new database.
1784 */
1785 void
1786 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1787 isc_result_t result;
1788 if (zone->rpz_num == DNS_RPZ_INVALID_NUM)
1789 return;
1790 REQUIRE(zone->rpzs != NULL);
1791 zone->rpzs->zones[zone->rpz_num]->db_registered = true;
1792 result = dns_db_updatenotify_register(db,
1793 dns_rpz_dbupdate_callback,
1794 zone->rpzs->zones[zone->rpz_num]);
1795 REQUIRE(result == ISC_R_SUCCESS);
1796 }
1797
1798 void
1799 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1800 REQUIRE(DNS_ZONE_VALID(zone));
1801 REQUIRE(catzs != NULL);
1802
1803 LOCK_ZONE(zone);
1804 INSIST(zone->catzs == NULL || zone->catzs == catzs);
1805 dns_catz_catzs_set_view(catzs, zone->view);
1806 if (zone->catzs == NULL)
1807 dns_catz_catzs_attach(catzs, &zone->catzs);
1808 UNLOCK_ZONE(zone);
1809 }
1810
1811 /*
1812 * If a zone is a catalog zone, attach it to update notification in database.
1813 */
1814 void
1815 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1816 REQUIRE(DNS_ZONE_VALID(zone));
1817 REQUIRE(db != NULL);
1818
1819 if (zone->catzs != NULL) {
1820 dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1821 zone->catzs);
1822 }
1823 }
1824
1825 /*
1826 * Set catalog zone ownership of the zone
1827 */
1828 void
1829 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
1830 REQUIRE(DNS_ZONE_VALID(zone));
1831 REQUIRE(catz != NULL);
1832 LOCK_ZONE(zone);
1833 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
1834 zone->parentcatz = catz;
1835 UNLOCK_ZONE(zone);
1836 }
1837
1838 dns_catz_zone_t *
1839 dns_zone_get_parentcatz(const dns_zone_t *zone) {
1840 REQUIRE(DNS_ZONE_VALID(zone));
1841 return (zone->parentcatz);
1842 }
1843
1844
1845 static bool
1846 zone_touched(dns_zone_t *zone) {
1847 isc_result_t result;
1848 isc_time_t modtime;
1849 dns_include_t *include;
1850
1851 REQUIRE(DNS_ZONE_VALID(zone));
1852
1853 result = isc_file_getmodtime(zone->masterfile, &modtime);
1854 if (result != ISC_R_SUCCESS ||
1855 isc_time_compare(&modtime, &zone->loadtime) > 0)
1856 return (true);
1857
1858 for (include = ISC_LIST_HEAD(zone->includes);
1859 include != NULL;
1860 include = ISC_LIST_NEXT(include, link))
1861 {
1862 result = isc_file_getmodtime(include->name, &modtime);
1863 if (result != ISC_R_SUCCESS ||
1864 isc_time_compare(&modtime, &include->filetime) > 0)
1865 return (true);
1866 }
1867
1868 return (false);
1869 }
1870
1871 /*
1872 * Note: when dealing with inline-signed zones, external callers will always
1873 * call zone_load() for the secure zone; zone_load() calls itself recursively
1874 * in order to load the raw zone.
1875 */
1876 static isc_result_t
1877 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
1878 isc_result_t result;
1879 isc_time_t now;
1880 isc_time_t loadtime;
1881 dns_db_t *db = NULL;
1882 bool rbt, hasraw;
1883
1884 REQUIRE(DNS_ZONE_VALID(zone));
1885
1886 if (!locked)
1887 LOCK_ZONE(zone);
1888
1889 INSIST(zone != zone->raw);
1890 hasraw = inline_secure(zone);
1891 if (hasraw) {
1892 /*
1893 * We are trying to load an inline-signed zone. First call
1894 * self recursively to try loading the raw version of the zone.
1895 * Assuming the raw zone file is readable, there are two
1896 * possibilities:
1897 *
1898 * a) the raw zone was not yet loaded and thus it will be
1899 * loaded now, synchronously; if this succeeds, a
1900 * subsequent attempt to load the signed zone file will
1901 * take place and thus zone_postload() will be called
1902 * twice: first for the raw zone and then for the secure
1903 * zone; the latter call will take care of syncing the raw
1904 * version with the secure version,
1905 *
1906 * b) the raw zone was already loaded and we are trying to
1907 * reload it, which will happen asynchronously; this means
1908 * zone_postload() will only be called for the raw zone
1909 * because "result" returned by the zone_load() call below
1910 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
1911 * zone_postload() called for the raw zone will take care
1912 * of syncing the raw version with the secure version.
1913 */
1914 result = zone_load(zone->raw, flags, false);
1915 if (result != ISC_R_SUCCESS) {
1916 if (!locked)
1917 UNLOCK_ZONE(zone);
1918 return(result);
1919 }
1920 LOCK_ZONE(zone->raw);
1921 }
1922
1923 TIME_NOW(&now);
1924
1925 INSIST(zone->type != dns_zone_none);
1926
1927 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1928 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1929 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1930 result = DNS_R_CONTINUE;
1931 goto cleanup;
1932 }
1933
1934 INSIST(zone->db_argc >= 1);
1935
1936 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1937 strcmp(zone->db_argv[0], "rbt64") == 0;
1938
1939 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1940 /*
1941 * The zone has no master file configured.
1942 */
1943 result = ISC_R_SUCCESS;
1944 goto cleanup;
1945 }
1946
1947 if (zone->db != NULL && dns_zone_isdynamic(zone, false)) {
1948 /*
1949 * This is a slave, stub, or dynamically updated
1950 * zone being reloaded. Do nothing - the database
1951 * we already have is guaranteed to be up-to-date.
1952 */
1953 if (zone->type == dns_zone_master && !hasraw)
1954 result = DNS_R_DYNAMIC;
1955 else
1956 result = ISC_R_SUCCESS;
1957 goto cleanup;
1958 }
1959
1960 /*
1961 * Store the current time before the zone is loaded, so that if the
1962 * file changes between the time of the load and the time that
1963 * zone->loadtime is set, then the file will still be reloaded
1964 * the next time dns_zone_load is called.
1965 */
1966 TIME_NOW(&loadtime);
1967
1968 /*
1969 * Don't do the load if the file that stores the zone is older
1970 * than the last time the zone was loaded. If the zone has not
1971 * been loaded yet, zone->loadtime will be the epoch.
1972 */
1973 if (zone->masterfile != NULL) {
1974 isc_time_t filetime;
1975
1976 /*
1977 * The file is already loaded. If we are just doing a
1978 * "rndc reconfig", we are done.
1979 */
1980 if (!isc_time_isepoch(&zone->loadtime) &&
1981 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1982 result = ISC_R_SUCCESS;
1983 goto cleanup;
1984 }
1985
1986 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1987 !zone_touched(zone))
1988 {
1989 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
1990 ISC_LOG_DEBUG(1),
1991 "skipping load: master file "
1992 "older than last load");
1993 result = DNS_R_UPTODATE;
1994 goto cleanup;
1995 }
1996
1997 /*
1998 * If the file modification time is in the past
1999 * set loadtime to that value.
2000 */
2001 result = isc_file_getmodtime(zone->masterfile, &filetime);
2002 if (result == ISC_R_SUCCESS &&
2003 isc_time_compare(&loadtime, &filetime) > 0)
2004 loadtime = filetime;
2005 }
2006
2007 /*
2008 * Built in zones (with the exception of empty zones) don't need
2009 * to be reloaded.
2010 */
2011 if (zone->type == dns_zone_master &&
2012 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2013 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2014 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2015 result = ISC_R_SUCCESS;
2016 goto cleanup;
2017 }
2018
2019 /*
2020 * Zones associated with a DLZ don't need to be loaded either,
2021 * but we need to associate the database with the zone object.
2022 */
2023 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2024 dns_dlzdb_t *dlzdb;
2025 dns_dlzfindzone_t findzone;
2026
2027 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2028 dlzdb != NULL;
2029 dlzdb = ISC_LIST_NEXT(dlzdb, link))
2030 {
2031 INSIST(DNS_DLZ_VALID(dlzdb));
2032 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
2033 break;
2034 }
2035
2036 if (dlzdb == NULL) {
2037 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2038 ISC_LOG_ERROR,
2039 "DLZ %s does not exist or is set "
2040 "to 'search yes;'", zone->db_argv[1]);
2041 result = ISC_R_NOTFOUND;
2042 goto cleanup;
2043 }
2044
2045 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2046 /* ask SDLZ driver if the zone is supported */
2047 findzone = dlzdb->implementation->methods->findzone;
2048 result = (*findzone)(dlzdb->implementation->driverarg,
2049 dlzdb->dbdata, dlzdb->mctx,
2050 zone->view->rdclass, &zone->origin,
2051 NULL, NULL, &db);
2052 if (result != ISC_R_NOTFOUND) {
2053 if (zone->db != NULL)
2054 zone_detachdb(zone);
2055 zone_attachdb(zone, db);
2056 dns_db_detach(&db);
2057 result = ISC_R_SUCCESS;
2058 }
2059 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2060
2061 if (result == ISC_R_SUCCESS) {
2062 if (dlzdb->configure_callback == NULL)
2063 goto cleanup;
2064
2065 result = (*dlzdb->configure_callback)(zone->view,
2066 dlzdb, zone);
2067 if (result != ISC_R_SUCCESS)
2068 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2069 ISC_LOG_ERROR,
2070 "DLZ configuration callback: %s",
2071 isc_result_totext(result));
2072 }
2073 goto cleanup;
2074 }
2075
2076 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2077 zone->type == dns_zone_stub ||
2078 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2079 rbt) {
2080 if (zone->masterfile == NULL ||
2081 !isc_file_exists(zone->masterfile)) {
2082 if (zone->masterfile != NULL) {
2083 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2084 ISC_LOG_DEBUG(1),
2085 "no master file");
2086 }
2087 zone->refreshtime = now;
2088 if (zone->task != NULL)
2089 zone_settimer(zone, &now);
2090 result = ISC_R_SUCCESS;
2091 goto cleanup;
2092 }
2093 }
2094
2095 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2096 ISC_LOG_DEBUG(1), "starting load");
2097
2098 result = dns_db_create(zone->mctx, zone->db_argv[0],
2099 &zone->origin, (zone->type == dns_zone_stub) ?
2100 dns_dbtype_stub : dns_dbtype_zone,
2101 zone->rdclass,
2102 zone->db_argc - 1, zone->db_argv + 1,
2103 &db);
2104
2105 if (result != ISC_R_SUCCESS) {
2106 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2107 "loading zone: creating database: %s",
2108 isc_result_totext(result));
2109 goto cleanup;
2110 }
2111 dns_db_settask(db, zone->task);
2112
2113 if (zone->type == dns_zone_master || zone->type == dns_zone_slave ||
2114 zone->type == dns_zone_mirror)
2115 {
2116 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2117 if (result == ISC_R_NOTIMPLEMENTED) {
2118 result = ISC_R_SUCCESS;
2119 }
2120 if (result != ISC_R_SUCCESS) {
2121 goto cleanup;
2122 }
2123 }
2124
2125 if (! dns_db_ispersistent(db)) {
2126 if (zone->masterfile != NULL) {
2127 result = zone_startload(db, zone, loadtime);
2128 } else {
2129 result = DNS_R_NOMASTERFILE;
2130 if (zone->type == dns_zone_master ||
2131 (zone->type == dns_zone_redirect &&
2132 zone->masters == NULL)) {
2133 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2134 ISC_LOG_ERROR,
2135 "loading zone: "
2136 "no master file configured");
2137 goto cleanup;
2138 }
2139 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2140 ISC_LOG_INFO, "loading zone: "
2141 "no master file configured: continuing");
2142 }
2143 }
2144
2145 if (result == DNS_R_CONTINUE) {
2146 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2147 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
2148 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2149 goto cleanup;
2150 }
2151
2152 result = zone_postload(zone, db, loadtime, result);
2153
2154 cleanup:
2155 if (hasraw)
2156 UNLOCK_ZONE(zone->raw);
2157 if (!locked)
2158 UNLOCK_ZONE(zone);
2159 if (db != NULL)
2160 dns_db_detach(&db);
2161 return (result);
2162 }
2163
2164 isc_result_t
2165 dns_zone_load(dns_zone_t *zone, bool newonly) {
2166 return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2167 }
2168
2169 static void
2170 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2171 dns_asyncload_t *asl = event->ev_arg;
2172 dns_zone_t *zone = asl->zone;
2173 isc_result_t result;
2174
2175 UNUSED(task);
2176
2177 REQUIRE(DNS_ZONE_VALID(zone));
2178
2179 isc_event_free(&event);
2180
2181 LOCK_ZONE(zone);
2182 result = zone_load(zone, asl->flags, true);
2183 if (result != DNS_R_CONTINUE) {
2184 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2185 }
2186 UNLOCK_ZONE(zone);
2187
2188 /* Inform the zone table we've finished loading */
2189 if (asl->loaded != NULL)
2190 (asl->loaded)(asl->loaded_arg, zone, task);
2191
2192 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2193 dns_zone_idetach(&zone);
2194 }
2195
2196 isc_result_t
2197 dns_zone_asyncload(dns_zone_t *zone, bool newonly,
2198 dns_zt_zoneloaded_t done, void *arg)
2199 {
2200 isc_event_t *e;
2201 dns_asyncload_t *asl = NULL;
2202 isc_result_t result = ISC_R_SUCCESS;
2203
2204 REQUIRE(DNS_ZONE_VALID(zone));
2205
2206 if (zone->zmgr == NULL)
2207 return (ISC_R_FAILURE);
2208
2209 /* If we already have a load pending, stop now */
2210 LOCK_ZONE(zone);
2211 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2212 UNLOCK_ZONE(zone);
2213 return (ISC_R_ALREADYRUNNING);
2214 }
2215
2216 asl = isc_mem_get(zone->mctx, sizeof (*asl));
2217 if (asl == NULL)
2218 CHECK(ISC_R_NOMEMORY);
2219
2220 asl->zone = NULL;
2221 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2222 asl->loaded = done;
2223 asl->loaded_arg = arg;
2224
2225 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
2226 DNS_EVENT_ZONELOAD,
2227 zone_asyncload, asl,
2228 sizeof(isc_event_t));
2229 if (e == NULL)
2230 CHECK(ISC_R_NOMEMORY);
2231
2232 zone_iattach(zone, &asl->zone);
2233 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2234 isc_task_send(zone->loadtask, &e);
2235 UNLOCK_ZONE(zone);
2236
2237 return (ISC_R_SUCCESS);
2238
2239 failure:
2240 if (asl != NULL)
2241 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2242 UNLOCK_ZONE(zone);
2243 return (result);
2244 }
2245
2246 bool
2247 dns__zone_loadpending(dns_zone_t *zone) {
2248 REQUIRE(DNS_ZONE_VALID(zone));
2249
2250 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2251 }
2252
2253 isc_result_t
2254 dns_zone_loadandthaw(dns_zone_t *zone) {
2255 isc_result_t result;
2256
2257 if (inline_raw(zone))
2258 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
2259 false);
2260 else
2261 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2262
2263 switch (result) {
2264 case DNS_R_CONTINUE:
2265 /* Deferred thaw. */
2266 break;
2267 case DNS_R_UPTODATE:
2268 case ISC_R_SUCCESS:
2269 case DNS_R_SEENINCLUDE:
2270 zone->update_disabled = false;
2271 break;
2272 case DNS_R_NOMASTERFILE:
2273 zone->update_disabled = false;
2274 break;
2275 default:
2276 /* Error, remain in disabled state. */
2277 break;
2278 }
2279 return (result);
2280 }
2281
2282 static unsigned int
2283 get_master_options(dns_zone_t *zone) {
2284 unsigned int options;
2285
2286 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2287 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2288 (zone->type == dns_zone_redirect && zone->masters == NULL))
2289 {
2290 options |= DNS_MASTER_SLAVE;
2291 }
2292 if (zone->type == dns_zone_key) {
2293 options |= DNS_MASTER_KEY;
2294 }
2295 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2296 options |= DNS_MASTER_CHECKNS;
2297 }
2298 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2299 options |= DNS_MASTER_FATALNS;
2300 }
2301 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2302 options |= DNS_MASTER_CHECKNAMES;
2303 }
2304 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2305 options |= DNS_MASTER_CHECKNAMESFAIL;
2306 }
2307 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2308 options |= DNS_MASTER_CHECKMX;
2309 }
2310 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2311 options |= DNS_MASTER_CHECKMXFAIL;
2312 }
2313 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2314 options |= DNS_MASTER_CHECKWILDCARD;
2315 }
2316 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2317 options |= DNS_MASTER_CHECKTTL;
2318 }
2319
2320 return (options);
2321 }
2322
2323 static void
2324 zone_registerinclude(const char *filename, void *arg) {
2325 isc_result_t result;
2326 dns_zone_t *zone = (dns_zone_t *) arg;
2327 dns_include_t *inc = NULL;
2328
2329 REQUIRE(DNS_ZONE_VALID(zone));
2330
2331 if (filename == NULL)
2332 return;
2333
2334 /*
2335 * Suppress duplicates.
2336 */
2337 for (inc = ISC_LIST_HEAD(zone->newincludes);
2338 inc != NULL;
2339 inc = ISC_LIST_NEXT(inc, link))
2340 if (strcmp(filename, inc->name) == 0)
2341 return;
2342
2343 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2344 if (inc == NULL)
2345 return;
2346 inc->name = isc_mem_strdup(zone->mctx, filename);
2347 if (inc->name == NULL) {
2348 isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
2349 return;
2350 }
2351 ISC_LINK_INIT(inc, link);
2352
2353 result = isc_file_getmodtime(filename, &inc->filetime);
2354 if (result != ISC_R_SUCCESS)
2355 isc_time_settoepoch(&inc->filetime);
2356
2357 ISC_LIST_APPEND(zone->newincludes, inc, link);
2358 }
2359
2360 static void
2361 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2362 dns_load_t *load = event->ev_arg;
2363 isc_result_t result = ISC_R_SUCCESS;
2364 unsigned int options;
2365
2366 REQUIRE(DNS_LOAD_VALID(load));
2367
2368 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2369 result = ISC_R_CANCELED;
2370 isc_event_free(&event);
2371 if (result == ISC_R_CANCELED)
2372 goto fail;
2373
2374 options = get_master_options(load->zone);
2375
2376 result = dns_master_loadfileinc(load->zone->masterfile,
2377 dns_db_origin(load->db),
2378 dns_db_origin(load->db),
2379 load->zone->rdclass, options, 0,
2380 &load->callbacks, task,
2381 zone_loaddone, load,
2382 &load->zone->lctx,
2383 zone_registerinclude,
2384 load->zone, load->zone->mctx,
2385 load->zone->masterformat,
2386 load->zone->maxttl);
2387 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2388 result != DNS_R_SEENINCLUDE)
2389 goto fail;
2390 return;
2391
2392 fail:
2393 zone_loaddone(load, result);
2394 }
2395
2396 static void
2397 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2398 isc_result_t result;
2399 unsigned int soacount;
2400
2401 LOCK(&raw->lock);
2402 if (raw->db != NULL) {
2403 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2404 &rawdata->sourceserial,
2405 NULL, NULL, NULL, NULL,
2406 NULL);
2407 if (result == ISC_R_SUCCESS && soacount > 0U)
2408 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2409 }
2410 UNLOCK(&raw->lock);
2411 }
2412
2413 static void
2414 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2415 const char me[] = "zone_gotwritehandle";
2416 dns_zone_t *zone = event->ev_arg;
2417 isc_result_t result = ISC_R_SUCCESS;
2418 dns_dbversion_t *version = NULL;
2419 dns_masterrawheader_t rawdata;
2420
2421 REQUIRE(DNS_ZONE_VALID(zone));
2422 INSIST(task == zone->task);
2423 ENTER;
2424
2425 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2426 result = ISC_R_CANCELED;
2427 isc_event_free(&event);
2428 if (result == ISC_R_CANCELED)
2429 goto fail;
2430
2431 LOCK_ZONE(zone);
2432 INSIST(zone != zone->raw);
2433 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2434 if (zone->db != NULL) {
2435 const dns_master_style_t *output_style;
2436
2437 dns_db_currentversion(zone->db, &version);
2438 dns_master_initrawheader(&rawdata);
2439 if (inline_secure(zone))
2440 get_raw_serial(zone->raw, &rawdata);
2441 if (zone->type == dns_zone_key)
2442 output_style = &dns_master_style_keyzone;
2443 else if (zone->masterstyle != NULL)
2444 output_style = zone->masterstyle;
2445 else
2446 output_style = &dns_master_style_default;
2447 result = dns_master_dumpinc(zone->mctx, zone->db, version,
2448 output_style, zone->masterfile,
2449 zone->task, dump_done, zone,
2450 &zone->dctx, zone->masterformat,
2451 &rawdata);
2452 dns_db_closeversion(zone->db, &version, false);
2453 } else
2454 result = ISC_R_CANCELED;
2455 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2456 UNLOCK_ZONE(zone);
2457 if (result != DNS_R_CONTINUE)
2458 goto fail;
2459 return;
2460
2461 fail:
2462 dump_done(zone, result);
2463 }
2464
2465 /*
2466 * Save the raw serial number for inline-signing zones.
2467 * (XXX: Other information from the header will be used
2468 * for other purposes in the future, but for now this is
2469 * all we're interested in.)
2470 */
2471 static void
2472 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2473 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2474 return;
2475
2476 zone->sourceserial = header->sourceserial;
2477 zone->sourceserialset = true;
2478 }
2479
2480 void
2481 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2482 if (zone == NULL)
2483 return;
2484
2485 LOCK_ZONE(zone);
2486 zone_setrawdata(zone, header);
2487 UNLOCK_ZONE(zone);
2488 }
2489
2490 static isc_result_t
2491 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2492 dns_load_t *load;
2493 isc_result_t result;
2494 isc_result_t tresult;
2495 unsigned int options;
2496
2497 dns_zone_rpz_enable_db(zone, db);
2498 dns_zone_catz_enable_db(zone, db);
2499 options = get_master_options(zone);
2500 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2501 options |= DNS_MASTER_MANYERRORS;
2502
2503 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2504 load = isc_mem_get(zone->mctx, sizeof(*load));
2505 if (load == NULL)
2506 return (ISC_R_NOMEMORY);
2507
2508 load->mctx = NULL;
2509 load->zone = NULL;
2510 load->db = NULL;
2511 load->loadtime = loadtime;
2512 load->magic = LOAD_MAGIC;
2513
2514 isc_mem_attach(zone->mctx, &load->mctx);
2515 zone_iattach(zone, &load->zone);
2516 dns_db_attach(db, &load->db);
2517 dns_rdatacallbacks_init(&load->callbacks);
2518 load->callbacks.rawdata = zone_setrawdata;
2519 zone_iattach(zone, &load->callbacks.zone);
2520 result = dns_db_beginload(db, &load->callbacks);
2521 if (result != ISC_R_SUCCESS)
2522 goto cleanup;
2523 result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2524 zone_gotreadhandle, load,
2525 &zone->readio);
2526 if (result != ISC_R_SUCCESS) {
2527 /*
2528 * We can't report multiple errors so ignore
2529 * the result of dns_db_endload().
2530 */
2531 (void)dns_db_endload(load->db, &load->callbacks);
2532 goto cleanup;
2533 } else
2534 result = DNS_R_CONTINUE;
2535 } else {
2536 dns_rdatacallbacks_t callbacks;
2537
2538 dns_rdatacallbacks_init(&callbacks);
2539 callbacks.rawdata = zone_setrawdata;
2540 zone_iattach(zone, &callbacks.zone);
2541 result = dns_db_beginload(db, &callbacks);
2542 if (result != ISC_R_SUCCESS) {
2543 zone_idetach(&callbacks.zone);
2544 return (result);
2545 }
2546 result = dns_master_loadfile(zone->masterfile,
2547 &zone->origin, &zone->origin,
2548 zone->rdclass, options, 0,
2549 &callbacks,
2550 zone_registerinclude,
2551 zone, zone->mctx,
2552 zone->masterformat,
2553 zone->maxttl);
2554 tresult = dns_db_endload(db, &callbacks);
2555 if (result == ISC_R_SUCCESS)
2556 result = tresult;
2557 zone_idetach(&callbacks.zone);
2558 }
2559
2560 return (result);
2561
2562 cleanup:
2563 load->magic = 0;
2564 dns_db_detach(&load->db);
2565 zone_idetach(&load->zone);
2566 zone_idetach(&load->callbacks.zone);
2567 isc_mem_detach(&load->mctx);
2568 isc_mem_put(zone->mctx, load, sizeof(*load));
2569 return (result);
2570 }
2571
2572 static bool
2573 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2574 dns_name_t *owner)
2575 {
2576 isc_result_t result;
2577 char ownerbuf[DNS_NAME_FORMATSIZE];
2578 char namebuf[DNS_NAME_FORMATSIZE];
2579 char altbuf[DNS_NAME_FORMATSIZE];
2580 dns_fixedname_t fixed;
2581 dns_name_t *foundname;
2582 int level;
2583
2584 /*
2585 * "." means the services does not exist.
2586 */
2587 if (dns_name_equal(name, dns_rootname))
2588 return (true);
2589
2590 /*
2591 * Outside of zone.
2592 */
2593 if (!dns_name_issubdomain(name, &zone->origin)) {
2594 if (zone->checkmx != NULL)
2595 return ((zone->checkmx)(zone, name, owner));
2596 return (true);
2597 }
2598
2599 if (zone->type == dns_zone_master)
2600 level = ISC_LOG_ERROR;
2601 else
2602 level = ISC_LOG_WARNING;
2603
2604 foundname = dns_fixedname_initname(&fixed);
2605
2606 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2607 0, 0, NULL, foundname, NULL, NULL);
2608 if (result == ISC_R_SUCCESS)
2609 return (true);
2610
2611 if (result == DNS_R_NXRRSET) {
2612 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2613 0, 0, NULL, foundname, NULL, NULL);
2614 if (result == ISC_R_SUCCESS)
2615 return (true);
2616 }
2617
2618 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2619 dns_name_format(name, namebuf, sizeof namebuf);
2620 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2621 result == DNS_R_EMPTYNAME) {
2622 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2623 level = ISC_LOG_WARNING;
2624 dns_zone_log(zone, level,
2625 "%s/MX '%s' has no address records (A or AAAA)",
2626 ownerbuf, namebuf);
2627 return ((level == ISC_LOG_WARNING) ? true : false);
2628 }
2629
2630 if (result == DNS_R_CNAME) {
2631 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2632 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2633 level = ISC_LOG_WARNING;
2634 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2635 dns_zone_log(zone, level,
2636 "%s/MX '%s' is a CNAME (illegal)",
2637 ownerbuf, namebuf);
2638 return ((level == ISC_LOG_WARNING) ? true : false);
2639 }
2640
2641 if (result == DNS_R_DNAME) {
2642 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2643 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2644 level = ISC_LOG_WARNING;
2645 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2646 dns_name_format(foundname, altbuf, sizeof altbuf);
2647 dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2648 " '%s' (illegal)", ownerbuf, namebuf,
2649 altbuf);
2650 }
2651 return ((level == ISC_LOG_WARNING) ? true : false);
2652 }
2653
2654 if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2655 return ((zone->checkmx)(zone, name, owner));
2656
2657 return (true);
2658 }
2659
2660 static bool
2661 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2662 dns_name_t *owner)
2663 {
2664 isc_result_t result;
2665 char ownerbuf[DNS_NAME_FORMATSIZE];
2666 char namebuf[DNS_NAME_FORMATSIZE];
2667 char altbuf[DNS_NAME_FORMATSIZE];
2668 dns_fixedname_t fixed;
2669 dns_name_t *foundname;
2670 int level;
2671
2672 /*
2673 * "." means the services does not exist.
2674 */
2675 if (dns_name_equal(name, dns_rootname))
2676 return (true);
2677
2678 /*
2679 * Outside of zone.
2680 */
2681 if (!dns_name_issubdomain(name, &zone->origin)) {
2682 if (zone->checksrv != NULL)
2683 return ((zone->checksrv)(zone, name, owner));
2684 return (true);
2685 }
2686
2687 if (zone->type == dns_zone_master)
2688 level = ISC_LOG_ERROR;
2689 else
2690 level = ISC_LOG_WARNING;
2691
2692 foundname = dns_fixedname_initname(&fixed);
2693
2694 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2695 0, 0, NULL, foundname, NULL, NULL);
2696 if (result == ISC_R_SUCCESS)
2697 return (true);
2698
2699 if (result == DNS_R_NXRRSET) {
2700 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2701 0, 0, NULL, foundname, NULL, NULL);
2702 if (result == ISC_R_SUCCESS)
2703 return (true);
2704 }
2705
2706 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2707 dns_name_format(name, namebuf, sizeof namebuf);
2708 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2709 result == DNS_R_EMPTYNAME) {
2710 dns_zone_log(zone, level,
2711 "%s/SRV '%s' has no address records (A or AAAA)",
2712 ownerbuf, namebuf);
2713 /* XXX950 make fatal for 9.5.0. */
2714 return (true);
2715 }
2716
2717 if (result == DNS_R_CNAME) {
2718 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2719 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2720 level = ISC_LOG_WARNING;
2721 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2722 dns_zone_log(zone, level,
2723 "%s/SRV '%s' is a CNAME (illegal)",
2724 ownerbuf, namebuf);
2725 return ((level == ISC_LOG_WARNING) ? true : false);
2726 }
2727
2728 if (result == DNS_R_DNAME) {
2729 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2730 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2731 level = ISC_LOG_WARNING;
2732 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2733 dns_name_format(foundname, altbuf, sizeof altbuf);
2734 dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2735 "DNAME '%s' (illegal)", ownerbuf, namebuf,
2736 altbuf);
2737 }
2738 return ((level == ISC_LOG_WARNING) ? true : false);
2739 }
2740
2741 if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2742 return ((zone->checksrv)(zone, name, owner));
2743
2744 return (true);
2745 }
2746
2747 static bool
2748 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2749 dns_name_t *owner)
2750 {
2751 bool answer = true;
2752 isc_result_t result, tresult;
2753 char ownerbuf[DNS_NAME_FORMATSIZE];
2754 char namebuf[DNS_NAME_FORMATSIZE];
2755 char altbuf[DNS_NAME_FORMATSIZE];
2756 dns_fixedname_t fixed;
2757 dns_name_t *foundname;
2758 dns_rdataset_t a;
2759 dns_rdataset_t aaaa;
2760 int level;
2761
2762 /*
2763 * Outside of zone.
2764 */
2765 if (!dns_name_issubdomain(name, &zone->origin)) {
2766 if (zone->checkns != NULL)
2767 return ((zone->checkns)(zone, name, owner, NULL, NULL));
2768 return (true);
2769 }
2770
2771 if (zone->type == dns_zone_master)
2772 level = ISC_LOG_ERROR;
2773 else
2774 level = ISC_LOG_WARNING;
2775
2776 foundname = dns_fixedname_initname(&fixed);
2777 dns_rdataset_init(&a);
2778 dns_rdataset_init(&aaaa);
2779
2780 /*
2781 * Perform a regular lookup to catch DNAME records then look
2782 * for glue.
2783 */
2784 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2785 0, 0, NULL, foundname, &a, NULL);
2786 switch (result) {
2787 case ISC_R_SUCCESS:
2788 case DNS_R_DNAME:
2789 case DNS_R_CNAME:
2790 break;
2791 default:
2792 if (dns_rdataset_isassociated(&a))
2793 dns_rdataset_disassociate(&a);
2794 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2795 DNS_DBFIND_GLUEOK, 0, NULL,
2796 foundname, &a, NULL);
2797 }
2798 if (result == ISC_R_SUCCESS) {
2799 dns_rdataset_disassociate(&a);
2800 return (true);
2801 } else if (result == DNS_R_DELEGATION)
2802 dns_rdataset_disassociate(&a);
2803
2804 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2805 result == DNS_R_GLUE) {
2806 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2807 DNS_DBFIND_GLUEOK, 0, NULL,
2808 foundname, &aaaa, NULL);
2809 if (tresult == ISC_R_SUCCESS) {
2810 if (dns_rdataset_isassociated(&a))
2811 dns_rdataset_disassociate(&a);
2812 dns_rdataset_disassociate(&aaaa);
2813 return (true);
2814 }
2815 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME)
2816 dns_rdataset_disassociate(&aaaa);
2817 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2818 /*
2819 * Check glue against child zone.
2820 */
2821 if (zone->checkns != NULL)
2822 answer = (zone->checkns)(zone, name, owner,
2823 &a, &aaaa);
2824 if (dns_rdataset_isassociated(&a))
2825 dns_rdataset_disassociate(&a);
2826 if (dns_rdataset_isassociated(&aaaa))
2827 dns_rdataset_disassociate(&aaaa);
2828 return (answer);
2829 }
2830 }
2831
2832 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2833 dns_name_format(name, namebuf, sizeof namebuf);
2834 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2835 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2836 const char *what;
2837 bool required = false;
2838 if (dns_name_issubdomain(name, owner)) {
2839 what = "REQUIRED GLUE ";
2840 required = true;
2841 } else if (result == DNS_R_DELEGATION)
2842 what = "SIBLING GLUE ";
2843 else
2844 what = "";
2845
2846 if (result != DNS_R_DELEGATION || required ||
2847 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2848 dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2849 "address records (A or AAAA)",
2850 ownerbuf, namebuf, what);
2851 /*
2852 * Log missing address record.
2853 */
2854 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2855 (void)(zone->checkns)(zone, name, owner,
2856 &a, &aaaa);
2857 /* XXX950 make fatal for 9.5.0. */
2858 /* answer = false; */
2859 }
2860 } else if (result == DNS_R_CNAME) {
2861 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2862 ownerbuf, namebuf);
2863 /* XXX950 make fatal for 9.5.0. */
2864 /* answer = false; */
2865 } else if (result == DNS_R_DNAME) {
2866 dns_name_format(foundname, altbuf, sizeof altbuf);
2867 dns_zone_log(zone, level,
2868 "%s/NS '%s' is below a DNAME '%s' (illegal)",
2869 ownerbuf, namebuf, altbuf);
2870 /* XXX950 make fatal for 9.5.0. */
2871 /* answer = false; */
2872 }
2873
2874 if (dns_rdataset_isassociated(&a))
2875 dns_rdataset_disassociate(&a);
2876 if (dns_rdataset_isassociated(&aaaa))
2877 dns_rdataset_disassociate(&aaaa);
2878 return (answer);
2879 }
2880
2881 static bool
2882 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2883 dns_rdataset_t *rdataset)
2884 {
2885 dns_rdataset_t tmprdataset;
2886 isc_result_t result;
2887 bool answer = true;
2888 bool format = true;
2889 int level = ISC_LOG_WARNING;
2890 char ownerbuf[DNS_NAME_FORMATSIZE];
2891 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2892 unsigned int count1 = 0;
2893
2894 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2895 level = ISC_LOG_ERROR;
2896
2897 dns_rdataset_init(&tmprdataset);
2898 for (result = dns_rdataset_first(rdataset);
2899 result == ISC_R_SUCCESS;
2900 result = dns_rdataset_next(rdataset)) {
2901 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2902 unsigned int count2 = 0;
2903
2904 count1++;
2905 dns_rdataset_current(rdataset, &rdata1);
2906 dns_rdataset_clone(rdataset, &tmprdataset);
2907 for (result = dns_rdataset_first(&tmprdataset);
2908 result == ISC_R_SUCCESS;
2909 result = dns_rdataset_next(&tmprdataset)) {
2910 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2911 count2++;
2912 if (count1 >= count2)
2913 continue;
2914 dns_rdataset_current(&tmprdataset, &rdata2);
2915 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2916 if (format) {
2917 dns_name_format(owner, ownerbuf,
2918 sizeof ownerbuf);
2919 dns_rdatatype_format(rdata1.type,
2920 typebuf,
2921 sizeof(typebuf));
2922 format = false;
2923 }
2924 dns_zone_log(zone, level, "%s/%s has "
2925 "semantically identical records",
2926 ownerbuf, typebuf);
2927 if (level == ISC_LOG_ERROR)
2928 answer = false;
2929 break;
2930 }
2931 }
2932 dns_rdataset_disassociate(&tmprdataset);
2933 if (!format)
2934 break;
2935 }
2936 return (answer);
2937 }
2938
2939 static bool
2940 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2941 dns_dbiterator_t *dbiterator = NULL;
2942 dns_dbnode_t *node = NULL;
2943 dns_fixedname_t fixed;
2944 dns_name_t *name;
2945 dns_rdataset_t rdataset;
2946 dns_rdatasetiter_t *rdsit = NULL;
2947 bool ok = true;
2948 isc_result_t result;
2949
2950 name = dns_fixedname_initname(&fixed);
2951 dns_rdataset_init(&rdataset);
2952
2953 result = dns_db_createiterator(db, 0, &dbiterator);
2954 if (result != ISC_R_SUCCESS)
2955 return (true);
2956
2957 for (result = dns_dbiterator_first(dbiterator);
2958 result == ISC_R_SUCCESS;
2959 result = dns_dbiterator_next(dbiterator)) {
2960 result = dns_dbiterator_current(dbiterator, &node, name);
2961 if (result != ISC_R_SUCCESS)
2962 continue;
2963
2964 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2965 if (result != ISC_R_SUCCESS)
2966 continue;
2967
2968 for (result = dns_rdatasetiter_first(rdsit);
2969 result == ISC_R_SUCCESS;
2970 result = dns_rdatasetiter_next(rdsit)) {
2971 dns_rdatasetiter_current(rdsit, &rdataset);
2972 if (!zone_rrset_check_dup(zone, name, &rdataset))
2973 ok = false;
2974 dns_rdataset_disassociate(&rdataset);
2975 }
2976 dns_rdatasetiter_destroy(&rdsit);
2977 dns_db_detachnode(db, &node);
2978 }
2979
2980 if (node != NULL)
2981 dns_db_detachnode(db, &node);
2982 dns_dbiterator_destroy(&dbiterator);
2983
2984 return (ok);
2985 }
2986
2987 static bool
2988 isspf(const dns_rdata_t *rdata) {
2989 char buf[1024];
2990 const unsigned char *data = rdata->data;
2991 unsigned int rdl = rdata->length, i = 0, tl, len;
2992
2993 while (rdl > 0U) {
2994 len = tl = *data;
2995 ++data;
2996 --rdl;
2997 INSIST(tl <= rdl);
2998 if (len > sizeof(buf) - i - 1)
2999 len = sizeof(buf) - i - 1;
3000 memmove(buf + i, data, len);
3001 i += len;
3002 data += tl;
3003 rdl -= tl;
3004 }
3005
3006 if (i < 6U)
3007 return(false);
3008
3009 buf[i] = 0;
3010 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
3011 return (true);
3012 return (false);
3013 }
3014
3015 static bool
3016 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3017 dns_dbiterator_t *dbiterator = NULL;
3018 dns_dbnode_t *node = NULL;
3019 dns_rdataset_t rdataset;
3020 dns_fixedname_t fixed;
3021 dns_fixedname_t fixedbottom;
3022 dns_rdata_mx_t mx;
3023 dns_rdata_ns_t ns;
3024 dns_rdata_in_srv_t srv;
3025 dns_rdata_t rdata;
3026 dns_name_t *name;
3027 dns_name_t *bottom;
3028 isc_result_t result;
3029 bool ok = true, have_spf, have_txt;
3030
3031 name = dns_fixedname_initname(&fixed);
3032 bottom = dns_fixedname_initname(&fixedbottom);
3033 dns_rdataset_init(&rdataset);
3034 dns_rdata_init(&rdata);
3035
3036 result = dns_db_createiterator(db, 0, &dbiterator);
3037 if (result != ISC_R_SUCCESS)
3038 return (true);
3039
3040 result = dns_dbiterator_first(dbiterator);
3041 while (result == ISC_R_SUCCESS) {
3042 result = dns_dbiterator_current(dbiterator, &node, name);
3043 if (result != ISC_R_SUCCESS)
3044 goto cleanup;
3045
3046 /*
3047 * Is this name visible in the zone?
3048 */
3049 if (!dns_name_issubdomain(name, &zone->origin) ||
3050 (dns_name_countlabels(bottom) > 0 &&
3051 dns_name_issubdomain(name, bottom)))
3052 goto next;
3053
3054 /*
3055 * Don't check the NS records at the origin.
3056 */
3057 if (dns_name_equal(name, &zone->origin))
3058 goto checkfordname;
3059
3060 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3061 0, 0, &rdataset, NULL);
3062 if (result != ISC_R_SUCCESS)
3063 goto checkfordname;
3064 /*
3065 * Remember bottom of zone due to NS.
3066 */
3067 dns_name_copy(name, bottom, NULL);
3068
3069 result = dns_rdataset_first(&rdataset);
3070 while (result == ISC_R_SUCCESS) {
3071 dns_rdataset_current(&rdataset, &rdata);
3072 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3073 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3074 if (!zone_check_glue(zone, db, &ns.name, name))
3075 ok = false;
3076 dns_rdata_reset(&rdata);
3077 result = dns_rdataset_next(&rdataset);
3078 }
3079 dns_rdataset_disassociate(&rdataset);
3080 goto next;
3081
3082 checkfordname:
3083 result = dns_db_findrdataset(db, node, NULL,
3084 dns_rdatatype_dname, 0, 0,
3085 &rdataset, NULL);
3086 if (result == ISC_R_SUCCESS) {
3087 /*
3088 * Remember bottom of zone due to DNAME.
3089 */
3090 dns_name_copy(name, bottom, NULL);
3091 dns_rdataset_disassociate(&rdataset);
3092 }
3093
3094 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3095 0, 0, &rdataset, NULL);
3096 if (result != ISC_R_SUCCESS)
3097 goto checksrv;
3098 result = dns_rdataset_first(&rdataset);
3099 while (result == ISC_R_SUCCESS) {
3100 dns_rdataset_current(&rdataset, &rdata);
3101 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3102 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3103 if (!zone_check_mx(zone, db, &mx.mx, name))
3104 ok = false;
3105 dns_rdata_reset(&rdata);
3106 result = dns_rdataset_next(&rdataset);
3107 }
3108 dns_rdataset_disassociate(&rdataset);
3109
3110 checksrv:
3111 if (zone->rdclass != dns_rdataclass_in)
3112 goto next;
3113 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3114 0, 0, &rdataset, NULL);
3115 if (result != ISC_R_SUCCESS)
3116 goto checkspf;
3117 result = dns_rdataset_first(&rdataset);
3118 while (result == ISC_R_SUCCESS) {
3119 dns_rdataset_current(&rdataset, &rdata);
3120 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3121 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3122 if (!zone_check_srv(zone, db, &srv.target, name))
3123 ok = false;
3124 dns_rdata_reset(&rdata);
3125 result = dns_rdataset_next(&rdataset);
3126 }
3127 dns_rdataset_disassociate(&rdataset);
3128
3129 checkspf:
3130 /*
3131 * Check if there is a type SPF record without an
3132 * SPF-formatted type TXT record also being present.
3133 */
3134 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
3135 goto next;
3136 if (zone->rdclass != dns_rdataclass_in)
3137 goto next;
3138 have_spf = have_txt = false;
3139 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3140 0, 0, &rdataset, NULL);
3141 if (result == ISC_R_SUCCESS) {
3142 dns_rdataset_disassociate(&rdataset);
3143 have_spf = true;
3144 }
3145 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3146 0, 0, &rdataset, NULL);
3147 if (result != ISC_R_SUCCESS)
3148 goto notxt;
3149 result = dns_rdataset_first(&rdataset);
3150 while (result == ISC_R_SUCCESS) {
3151 dns_rdataset_current(&rdataset, &rdata);
3152 have_txt = isspf(&rdata);
3153 dns_rdata_reset(&rdata);
3154 if (have_txt)
3155 break;
3156 result = dns_rdataset_next(&rdataset);
3157 }
3158 dns_rdataset_disassociate(&rdataset);
3159
3160 notxt:
3161 if (have_spf && !have_txt) {
3162 char namebuf[DNS_NAME_FORMATSIZE];
3163
3164 dns_name_format(name, namebuf, sizeof(namebuf));
3165 dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
3166 "SPF record but no SPF TXT record found, "
3167 "add matching type TXT record", namebuf);
3168 }
3169
3170 next:
3171 dns_db_detachnode(db, &node);
3172 result = dns_dbiterator_next(dbiterator);
3173 }
3174
3175 cleanup:
3176 if (node != NULL)
3177 dns_db_detachnode(db, &node);
3178 dns_dbiterator_destroy(&dbiterator);
3179
3180 return (ok);
3181 }
3182
3183 /*
3184 * OpenSSL verification of RSA keys with exponent 3 is known to be
3185 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3186 * if they are in use.
3187 */
3188 static void
3189 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3190 dns_dbnode_t *node = NULL;
3191 dns_dbversion_t *version = NULL;
3192 dns_rdata_dnskey_t dnskey;
3193 dns_rdata_t rdata = DNS_RDATA_INIT;
3194 dns_rdataset_t rdataset;
3195 isc_result_t result;
3196 bool logit, foundrsa = false;
3197 const char *algorithm;
3198
3199 result = dns_db_findnode(db, &zone->origin, false, &node);
3200 if (result != ISC_R_SUCCESS) {
3201 goto cleanup;
3202 }
3203
3204 dns_db_currentversion(db, &version);
3205 dns_rdataset_init(&rdataset);
3206 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3207 dns_rdatatype_none, 0, &rdataset, NULL);
3208 if (result != ISC_R_SUCCESS) {
3209 goto cleanup;
3210 }
3211
3212 for (result = dns_rdataset_first(&rdataset);
3213 result == ISC_R_SUCCESS;
3214 result = dns_rdataset_next(&rdataset))
3215 {
3216 dns_rdataset_current(&rdataset, &rdata);
3217 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3218 INSIST(result == ISC_R_SUCCESS);
3219
3220 /* RFC 3110, section 4: Performance Considerations:
3221 *
3222 * A public exponent of 3 minimizes the effort needed to verify
3223 * a signature. Use of 3 as the public exponent is weak for
3224 * confidentiality uses since, if the same data can be collected
3225 * encrypted under three different keys with an exponent of 3
3226 * then, using the Chinese Remainder Theorem [NETSEC], the
3227 * original plain text can be easily recovered. If a key is
3228 * known to be used only for authentication, as is the case with
3229 * DNSSEC, then an exponent of 3 is acceptable. However other
3230 * applications in the future may wish to leverage DNS
3231 * distributed keys for applications that do require
3232 * confidentiality. For keys which might have such other uses,
3233 * a more conservative choice would be 65537 (F4, the fourth
3234 * fermat number).
3235 */
3236 if (dnskey.algorithm == DST_ALG_RSASHA1 &&
3237 dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3238 dnskey.data[1] == 3)
3239 {
3240 if (dnskey.algorithm == DST_ALG_RSASHA1) {
3241 logit = !foundrsa;
3242 foundrsa = true;
3243 algorithm = "RSASHA1";
3244 }
3245 if (logit) {
3246 dnssec_log(zone, ISC_LOG_WARNING,
3247 "weak %s (%u) key found "
3248 "(exponent=3)", algorithm,
3249 dnskey.algorithm);
3250 }
3251 }
3252 dns_rdata_reset(&rdata);
3253 }
3254 dns_rdataset_disassociate(&rdataset);
3255
3256 cleanup:
3257 if (node != NULL) {
3258 dns_db_detachnode(db, &node);
3259 }
3260 if (version != NULL) {
3261 dns_db_closeversion(db, &version, false);
3262 }
3263 }
3264
3265 static void
3266 resume_signingwithkey(dns_zone_t *zone) {
3267 dns_dbnode_t *node = NULL;
3268 dns_dbversion_t *version = NULL;
3269 dns_rdata_t rdata = DNS_RDATA_INIT;
3270 dns_rdataset_t rdataset;
3271 isc_result_t result;
3272 dns_db_t *db = NULL;
3273
3274 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3275 if (zone->db != NULL) {
3276 dns_db_attach(zone->db, &db);
3277 }
3278 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3279 if (db == NULL) {
3280 goto cleanup;
3281 }
3282
3283 result = dns_db_findnode(db, &zone->origin, false, &node);
3284 if (result != ISC_R_SUCCESS) {
3285 goto cleanup;
3286 }
3287
3288 dns_db_currentversion(db, &version);
3289 dns_rdataset_init(&rdataset);
3290 result = dns_db_findrdataset(db, node, version,
3291 zone->privatetype,
3292 dns_rdatatype_none, 0,
3293 &rdataset, NULL);
3294 if (result != ISC_R_SUCCESS) {
3295 INSIST(!dns_rdataset_isassociated(&rdataset));
3296 goto cleanup;
3297 }
3298
3299 for (result = dns_rdataset_first(&rdataset);
3300 result == ISC_R_SUCCESS;
3301 result = dns_rdataset_next(&rdataset))
3302 {
3303 dns_rdataset_current(&rdataset, &rdata);
3304 if (rdata.length != 5 ||
3305 rdata.data[0] == 0 || rdata.data[4] != 0)
3306 {
3307 dns_rdata_reset(&rdata);
3308 continue;
3309 }
3310
3311 result = zone_signwithkey(zone, rdata.data[0],
3312 (rdata.data[1] << 8) | rdata.data[2],
3313 rdata.data[3]);
3314 if (result != ISC_R_SUCCESS) {
3315 dnssec_log(zone, ISC_LOG_ERROR,
3316 "zone_signwithkey failed: %s",
3317 dns_result_totext(result));
3318 }
3319 dns_rdata_reset(&rdata);
3320 }
3321 dns_rdataset_disassociate(&rdataset);
3322
3323 cleanup:
3324 if (db != NULL) {
3325 if (node != NULL) {
3326 dns_db_detachnode(db, &node);
3327 }
3328 if (version != NULL) {
3329 dns_db_closeversion(db, &version, false);
3330 }
3331 dns_db_detach(&db);
3332 }
3333 }
3334
3335 /*
3336 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3337 * supplied NSEC3PARAM RDATA.
3338 *
3339 * Zone must be locked by caller.
3340 */
3341 static isc_result_t
3342 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3343 dns_nsec3chain_t *nsec3chain, *current;
3344 dns_dbversion_t *version = NULL;
3345 bool nseconly = false, nsec3ok = false;
3346 isc_result_t result;
3347 isc_time_t now;
3348 unsigned int options = 0;
3349 char saltbuf[255*2+1];
3350 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3351 dns_db_t *db = NULL;
3352
3353 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3354 if (zone->db != NULL) {
3355 dns_db_attach(zone->db, &db);
3356 }
3357 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3358
3359 if (db == NULL) {
3360 result = ISC_R_SUCCESS;
3361 goto cleanup;
3362 }
3363
3364 /*
3365 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3366 * chain from it is pointless as it would not be possible for the
3367 * latter to exist in the first place.
3368 */
3369 dns_db_currentversion(db, &version);
3370 result = dns_nsec_nseconly(db, version, &nseconly);
3371 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3372 dns_db_closeversion(db, &version, false);
3373 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3374 result = ISC_R_SUCCESS;
3375 goto cleanup;
3376 }
3377
3378 /*
3379 * Allocate and initialize structure preserving state of
3380 * adding/removing records belonging to this NSEC3 chain between
3381 * separate zone_nsec3chain() calls.
3382 */
3383 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3384 if (nsec3chain == NULL) {
3385 result = ISC_R_NOMEMORY;
3386 goto cleanup;
3387 }
3388
3389 nsec3chain->magic = 0;
3390 nsec3chain->done = false;
3391 nsec3chain->db = NULL;
3392 nsec3chain->dbiterator = NULL;
3393 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3394 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3395 nsec3chain->nsec3param.hash = nsec3param->hash;
3396 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3397 nsec3chain->nsec3param.flags = nsec3param->flags;
3398 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3399 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3400 nsec3chain->nsec3param.salt = nsec3chain->salt;
3401 nsec3chain->seen_nsec = false;
3402 nsec3chain->delete_nsec = false;
3403 nsec3chain->save_delete_nsec = false;
3404
3405 /*
3406 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3407 */
3408 if (nsec3param->flags == 0) {
3409 strlcpy(flags, "NONE", sizeof(flags));
3410 } else {
3411 flags[0] = '\0';
3412 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3413 strlcat(flags, "REMOVE", sizeof(flags));
3414 }
3415 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3416 if (flags[0] == '\0') {
3417 strlcpy(flags, "INITIAL", sizeof(flags));
3418 } else {
3419 strlcat(flags, "|INITIAL", sizeof(flags));
3420 }
3421 }
3422 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3423 if (flags[0] == '\0') {
3424 strlcpy(flags, "CREATE", sizeof(flags));
3425 } else {
3426 strlcat(flags, "|CREATE", sizeof(flags));
3427 }
3428 }
3429 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3430 if (flags[0] == '\0') {
3431 strlcpy(flags, "NONSEC", sizeof(flags));
3432 } else {
3433 strlcat(flags, "|NONSEC", sizeof(flags));
3434 }
3435 }
3436 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3437 if (flags[0] == '\0') {
3438 strlcpy(flags, "OPTOUT", sizeof(flags));
3439 } else {
3440 strlcat(flags, "|OPTOUT", sizeof(flags));
3441 }
3442 }
3443 }
3444 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3445 sizeof(saltbuf));
3446 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3447 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3448 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3449
3450 /*
3451 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3452 * currently being processed, interrupt its processing to avoid
3453 * simultaneously adding and removing records for the same NSEC3 chain.
3454 */
3455 for (current = ISC_LIST_HEAD(zone->nsec3chain);
3456 current != NULL;
3457 current = ISC_LIST_NEXT(current, link))
3458 {
3459 if ((current->db == db) &&
3460 (current->nsec3param.hash == nsec3param->hash) &&
3461 (current->nsec3param.iterations ==
3462 nsec3param->iterations) &&
3463 (current->nsec3param.salt_length ==
3464 nsec3param->salt_length) &&
3465 memcmp(current->nsec3param.salt, nsec3param->salt,
3466 nsec3param->salt_length) == 0)
3467 {
3468 current->done = true;
3469 }
3470 }
3471
3472 /*
3473 * Attach zone database to the structure initialized above and create
3474 * an iterator for it with appropriate options in order to avoid
3475 * creating NSEC3 records for NSEC3 records.
3476 */
3477 dns_db_attach(db, &nsec3chain->db);
3478 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3479 options = DNS_DB_NONSEC3;
3480 }
3481 result = dns_db_createiterator(nsec3chain->db, options,
3482 &nsec3chain->dbiterator);
3483 if (result == ISC_R_SUCCESS) {
3484 result = dns_dbiterator_first(nsec3chain->dbiterator);
3485 }
3486 if (result == ISC_R_SUCCESS) {
3487 /*
3488 * Database iterator initialization succeeded. We are now
3489 * ready to kick off adding/removing records belonging to this
3490 * NSEC3 chain. Append the structure initialized above to the
3491 * "nsec3chain" list for the zone and set the appropriate zone
3492 * timer so that zone_nsec3chain() is called as soon as
3493 * possible.
3494 */
3495 dns_dbiterator_pause(nsec3chain->dbiterator);
3496 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
3497 nsec3chain, link);
3498 nsec3chain = NULL;
3499 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3500 TIME_NOW(&now);
3501 zone->nsec3chaintime = now;
3502 if (zone->task != NULL) {
3503 zone_settimer(zone, &now);
3504 }
3505 }
3506 }
3507
3508 if (nsec3chain != NULL) {
3509 if (nsec3chain->db != NULL) {
3510 dns_db_detach(&nsec3chain->db);
3511 }
3512 if (nsec3chain->dbiterator != NULL) {
3513 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3514 }
3515 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3516 }
3517
3518 cleanup:
3519 if (db != NULL) {
3520 dns_db_detach(&db);
3521 }
3522 return (result);
3523 }
3524
3525 /*
3526 * Find private-type records at the zone apex which signal that an NSEC3 chain
3527 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3528 * and pass it to zone_addnsec3chain().
3529 *
3530 * Zone must be locked by caller.
3531 */
3532 static void
3533 resume_addnsec3chain(dns_zone_t *zone) {
3534 dns_dbnode_t *node = NULL;
3535 dns_dbversion_t *version = NULL;
3536 dns_rdataset_t rdataset;
3537 isc_result_t result;
3538 dns_rdata_nsec3param_t nsec3param;
3539 bool nseconly = false, nsec3ok = false;
3540 dns_db_t *db = NULL;
3541
3542 INSIST(LOCKED_ZONE(zone));
3543
3544 if (zone->privatetype == 0)
3545 return;
3546
3547 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3548 if (zone->db != NULL) {
3549 dns_db_attach(zone->db, &db);
3550 }
3551 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3552 if (db == NULL) {
3553 goto cleanup;
3554 }
3555
3556 result = dns_db_findnode(db, &zone->origin, false, &node);
3557 if (result != ISC_R_SUCCESS) {
3558 goto cleanup;
3559 }
3560
3561 dns_db_currentversion(db, &version);
3562
3563 /*
3564 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3565 * apex to exist and contain no keys using NSEC-only algorithms.
3566 */
3567 result = dns_nsec_nseconly(db, version, &nseconly);
3568 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3569
3570 /*
3571 * Get the RRset containing all private-type records at the zone apex.
3572 */
3573 dns_rdataset_init(&rdataset);
3574 result = dns_db_findrdataset(db, node, version,
3575 zone->privatetype, dns_rdatatype_none,
3576 0, &rdataset, NULL);
3577 if (result != ISC_R_SUCCESS) {
3578 INSIST(!dns_rdataset_isassociated(&rdataset));
3579 goto cleanup;
3580 }
3581
3582 for (result = dns_rdataset_first(&rdataset);
3583 result == ISC_R_SUCCESS;
3584 result = dns_rdataset_next(&rdataset))
3585 {
3586 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3587 dns_rdata_t rdata = DNS_RDATA_INIT;
3588 dns_rdata_t private = DNS_RDATA_INIT;
3589
3590 dns_rdataset_current(&rdataset, &private);
3591 /*
3592 * Try extracting NSEC3PARAM RDATA from this private-type
3593 * record. Failure means this private-type record does not
3594 * represent an NSEC3PARAM record, so skip it.
3595 */
3596 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3597 sizeof(buf)))
3598 {
3599 continue;
3600 }
3601 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3602 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3603 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3604 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3605 {
3606 /*
3607 * Pass the NSEC3PARAM RDATA contained in this
3608 * private-type record to zone_addnsec3chain() so that
3609 * it can kick off adding or removing NSEC3 records.
3610 */
3611 result = zone_addnsec3chain(zone, &nsec3param);
3612 if (result != ISC_R_SUCCESS) {
3613 dnssec_log(zone, ISC_LOG_ERROR,
3614 "zone_addnsec3chain failed: %s",
3615 dns_result_totext(result));
3616 }
3617 }
3618 }
3619 dns_rdataset_disassociate(&rdataset);
3620
3621 cleanup:
3622 if (db != NULL) {
3623 if (node != NULL) {
3624 dns_db_detachnode(db, &node);
3625 }
3626 if (version != NULL) {
3627 dns_db_closeversion(db, &version, false);
3628 }
3629 dns_db_detach(&db);
3630 }
3631 }
3632
3633 static void
3634 set_resigntime(dns_zone_t *zone) {
3635 dns_rdataset_t rdataset;
3636 dns_fixedname_t fixed;
3637 unsigned int resign;
3638 isc_result_t result;
3639 uint32_t nanosecs;
3640 dns_db_t *db = NULL;
3641
3642 /* We only re-sign zones that can be dynamically updated */
3643 if (zone->update_disabled)
3644 return;
3645
3646 if (!inline_secure(zone) && (zone->type != dns_zone_master ||
3647 (zone->ssutable == NULL &&
3648 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3649 return;
3650
3651 dns_rdataset_init(&rdataset);
3652 dns_fixedname_init(&fixed);
3653
3654 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3655 if (zone->db != NULL)
3656 dns_db_attach(zone->db, &db);
3657 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3658 if (db == NULL) {
3659 isc_time_settoepoch(&zone->resigntime);
3660 return;
3661 }
3662
3663 result = dns_db_getsigningtime(db, &rdataset,
3664 dns_fixedname_name(&fixed));
3665 if (result != ISC_R_SUCCESS) {
3666 isc_time_settoepoch(&zone->resigntime);
3667 goto cleanup;
3668 }
3669
3670 resign = rdataset.resign - zone->sigresigninginterval;
3671 dns_rdataset_disassociate(&rdataset);
3672 nanosecs = isc_random_uniform(1000000000);
3673 isc_time_set(&zone->resigntime, resign, nanosecs);
3674 cleanup:
3675 dns_db_detach(&db);
3676 return;
3677 }
3678
3679 static isc_result_t
3680 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3681 dns_dbnode_t *node = NULL;
3682 dns_rdataset_t rdataset;
3683 dns_dbversion_t *version = NULL;
3684 dns_rdata_nsec3param_t nsec3param;
3685 bool ok = false;
3686 isc_result_t result;
3687 dns_rdata_t rdata = DNS_RDATA_INIT;
3688 bool dynamic = (zone->type == dns_zone_master)
3689 ? dns_zone_isdynamic(zone, false) : false;
3690
3691 dns_rdataset_init(&rdataset);
3692 result = dns_db_findnode(db, &zone->origin, false, &node);
3693 if (result != ISC_R_SUCCESS) {
3694 dns_zone_log(zone, ISC_LOG_ERROR,
3695 "nsec3param lookup failure: %s",
3696 dns_result_totext(result));
3697 return (result);
3698 }
3699 dns_db_currentversion(db, &version);
3700
3701 result = dns_db_findrdataset(db, node, version,
3702 dns_rdatatype_nsec3param,
3703 dns_rdatatype_none, 0, &rdataset, NULL);
3704 if (result == ISC_R_NOTFOUND) {
3705 INSIST(!dns_rdataset_isassociated(&rdataset));
3706 result = ISC_R_SUCCESS;
3707 goto cleanup;
3708 }
3709 if (result != ISC_R_SUCCESS) {
3710 INSIST(!dns_rdataset_isassociated(&rdataset));
3711 dns_zone_log(zone, ISC_LOG_ERROR,
3712 "nsec3param lookup failure: %s",
3713 dns_result_totext(result));
3714 goto cleanup;
3715 }
3716
3717 /*
3718 * For dynamic zones we must support every algorithm so we can
3719 * regenerate all the NSEC3 chains.
3720 * For non-dynamic zones we only need to find a supported algorithm.
3721 */
3722 for (result = dns_rdataset_first(&rdataset);
3723 result == ISC_R_SUCCESS;
3724 result = dns_rdataset_next(&rdataset))
3725 {
3726 dns_rdataset_current(&rdataset, &rdata);
3727 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3728 dns_rdata_reset(&rdata);
3729 INSIST(result == ISC_R_SUCCESS);
3730 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3731 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3732 {
3733 dns_zone_log(zone, ISC_LOG_WARNING,
3734 "nsec3 test \"unknown\" hash algorithm found: %u",
3735 nsec3param.hash);
3736 ok = true;
3737 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3738 if (dynamic) {
3739 dns_zone_log(zone, ISC_LOG_ERROR,
3740 "unsupported nsec3 hash algorithm"
3741 " in dynamic zone: %u",
3742 nsec3param.hash);
3743 result = DNS_R_BADZONE;
3744 /* Stop second error message. */
3745 ok = true;
3746 break;
3747 } else
3748 dns_zone_log(zone, ISC_LOG_WARNING,
3749 "unsupported nsec3 hash algorithm: %u",
3750 nsec3param.hash);
3751 } else {
3752 ok = true;
3753 }
3754 }
3755 if (result == ISC_R_NOMORE) {
3756 result = ISC_R_SUCCESS;
3757 }
3758
3759 if (!ok) {
3760 result = DNS_R_BADZONE;
3761 dns_zone_log(zone, ISC_LOG_ERROR,
3762 "no supported nsec3 hash algorithm");
3763 }
3764
3765 cleanup:
3766 if (dns_rdataset_isassociated(&rdataset)) {
3767 dns_rdataset_disassociate(&rdataset);
3768 }
3769 dns_db_closeversion(db, &version, false);
3770 dns_db_detachnode(db, &node);
3771 return (result);
3772 }
3773
3774 /*
3775 * Set the timer for refreshing the key zone to the soonest future time
3776 * of the set (current timer, keydata->refresh, keydata->addhd,
3777 * keydata->removehd).
3778 */
3779 static void
3780 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3781 isc_stdtime_t now, bool force)
3782 {
3783 const char me[] = "set_refreshkeytimer";
3784 isc_stdtime_t then;
3785 isc_time_t timenow, timethen;
3786 char timebuf[80];
3787
3788 ENTER;
3789 then = key->refresh;
3790 if (force)
3791 then = now;
3792 if (key->addhd > now && key->addhd < then)
3793 then = key->addhd;
3794 if (key->removehd > now && key->removehd < then)
3795 then = key->removehd;
3796
3797 TIME_NOW(&timenow);
3798 if (then > now)
3799 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3800 else
3801 timethen = timenow;
3802 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3803 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3804 zone->refreshkeytime = timethen;
3805
3806 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3807 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3808 zone_settimer(zone, &timenow);
3809 }
3810
3811 /*
3812 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3813 * If the key zone is changed, set '*changed' to true.
3814 */
3815 static isc_result_t
3816 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3817 dns_diff_t *diff, dns_keytable_t *keytable,
3818 dns_keynode_t **keynodep, bool *changed)
3819 {
3820 const char me[] = "create_keydata";
3821 isc_result_t result = ISC_R_SUCCESS;
3822 isc_buffer_t keyb, dstb;
3823 unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3824 dns_rdata_keydata_t keydata;
3825 dns_rdata_dnskey_t dnskey;
3826 dns_rdata_t rdata = DNS_RDATA_INIT;
3827 dns_keynode_t *keynode;
3828 isc_stdtime_t now;
3829 isc_region_t r;
3830 dst_key_t *key;
3831
3832 REQUIRE(keynodep != NULL);
3833 keynode = *keynodep;
3834
3835 ENTER;
3836 isc_stdtime_get(&now);
3837
3838 /* Loop in case there's more than one key. */
3839 while (result == ISC_R_SUCCESS) {
3840 dns_keynode_t *nextnode = NULL;
3841
3842 key = dns_keynode_key(keynode);
3843 if (key == NULL)
3844 goto skip;
3845
3846 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3847 CHECK(dst_key_todns(key, &dstb));
3848
3849 /* Convert DST key to DNSKEY. */
3850 dns_rdata_reset(&rdata);
3851 isc_buffer_usedregion(&dstb, &r);
3852 dns_rdata_fromregion(&rdata, dst_key_class(key),
3853 dns_rdatatype_dnskey, &r);
3854
3855 /* DSTKEY to KEYDATA. */
3856 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3857 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3858 NULL));
3859
3860 /* KEYDATA to rdata. */
3861 dns_rdata_reset(&rdata);
3862 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3863 CHECK(dns_rdata_fromstruct(&rdata,
3864 zone->rdclass, dns_rdatatype_keydata,
3865 &keydata, &keyb));
3866
3867 /* Add rdata to zone. */
3868 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3869 dst_key_name(key), 0, &rdata));
3870 *changed = true;
3871
3872 /* Refresh new keys from the zone apex as soon as possible. */
3873 set_refreshkeytimer(zone, &keydata, now, true);
3874
3875 skip:
3876 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3877 if (result != ISC_R_NOTFOUND) {
3878 dns_keytable_detachkeynode(keytable, &keynode);
3879 keynode = nextnode;
3880 }
3881 }
3882
3883 if (keynode != NULL)
3884 dns_keytable_detachkeynode(keytable, &keynode);
3885 *keynodep = NULL;
3886
3887 return (ISC_R_SUCCESS);
3888
3889 failure:
3890 return (result);
3891 }
3892
3893 /*
3894 * Remove from the key zone all the KEYDATA records found in rdataset.
3895 */
3896 static isc_result_t
3897 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3898 dns_name_t *name, dns_rdataset_t *rdataset)
3899 {
3900 dns_rdata_t rdata = DNS_RDATA_INIT;
3901 isc_result_t result, uresult;
3902
3903 for (result = dns_rdataset_first(rdataset);
3904 result == ISC_R_SUCCESS;
3905 result = dns_rdataset_next(rdataset)) {
3906 dns_rdata_reset(&rdata);
3907 dns_rdataset_current(rdataset, &rdata);
3908 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3909 name, 0, &rdata);
3910 if (uresult != ISC_R_SUCCESS)
3911 return (uresult);
3912 }
3913 if (result == ISC_R_NOMORE)
3914 result = ISC_R_SUCCESS;
3915 return (result);
3916 }
3917
3918 /*
3919 * Compute the DNSSEC key ID for a DNSKEY record.
3920 */
3921 static isc_result_t
3922 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3923 dns_keytag_t *tag)
3924 {
3925 isc_result_t result;
3926 dns_rdata_t rdata = DNS_RDATA_INIT;
3927 unsigned char data[4096];
3928 isc_buffer_t buffer;
3929 dst_key_t *dstkey = NULL;
3930
3931 isc_buffer_init(&buffer, data, sizeof(data));
3932 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3933 dns_rdatatype_dnskey, dnskey, &buffer);
3934
3935 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3936 if (result == ISC_R_SUCCESS) {
3937 *tag = dst_key_id(dstkey);
3938 dst_key_free(&dstkey);
3939 }
3940
3941 return (result);
3942 }
3943
3944 /*
3945 * Add key to the security roots.
3946 */
3947 static void
3948 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3949 dns_rdata_dnskey_t *dnskey, bool initial,
3950 isc_mem_t *mctx)
3951 {
3952 isc_result_t result;
3953 dns_rdata_t rdata = DNS_RDATA_INIT;
3954 unsigned char data[4096];
3955 isc_buffer_t buffer;
3956 dns_keytable_t *sr = NULL;
3957 dst_key_t *dstkey = NULL;
3958
3959 /* Convert dnskey to DST key. */
3960 isc_buffer_init(&buffer, data, sizeof(data));
3961 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3962 dns_rdatatype_dnskey, dnskey, &buffer);
3963
3964 result = dns_view_getsecroots(zone->view, &sr);
3965 if (result != ISC_R_SUCCESS)
3966 goto failure;
3967
3968 CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3969 CHECK(dns_keytable_add(sr, true, initial, &dstkey));
3970 dns_keytable_detach(&sr);
3971
3972 failure:
3973 if (dstkey != NULL)
3974 dst_key_free(&dstkey);
3975 if (sr != NULL)
3976 dns_keytable_detach(&sr);
3977 return;
3978 }
3979
3980 /*
3981 * Add a null key to the security roots for so that all queries
3982 * to the zone will fail.
3983 */
3984 static void
3985 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3986 isc_result_t result;
3987 dns_keytable_t *sr = NULL;
3988
3989 result = dns_view_getsecroots(zone->view, &sr);
3990 if (result == ISC_R_SUCCESS) {
3991 dns_keytable_marksecure(sr, keyname);
3992 dns_keytable_detach(&sr);
3993 }
3994 }
3995
3996 /*
3997 * Scan a set of KEYDATA records from the key zone. The ones that are
3998 * valid (i.e., the add holddown timer has expired) become trusted keys.
3999 */
4000 static void
4001 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4002 isc_result_t result;
4003 dns_rdata_t rdata = DNS_RDATA_INIT;
4004 dns_rdata_keydata_t keydata;
4005 dns_rdata_dnskey_t dnskey;
4006 isc_mem_t *mctx = zone->mctx;
4007 int trusted = 0, revoked = 0, pending = 0;
4008 isc_stdtime_t now;
4009 dns_keytable_t *sr = NULL;
4010
4011 isc_stdtime_get(&now);
4012
4013 result = dns_view_getsecroots(zone->view, &sr);
4014 if (result == ISC_R_SUCCESS) {
4015 dns_keytable_delete(sr, name);
4016 dns_keytable_detach(&sr);
4017 }
4018
4019 /* Now insert all the accepted trust anchors from this keydata set. */
4020 for (result = dns_rdataset_first(rdataset);
4021 result == ISC_R_SUCCESS;
4022 result = dns_rdataset_next(rdataset))
4023 {
4024 dns_rdata_reset(&rdata);
4025 dns_rdataset_current(rdataset, &rdata);
4026
4027 /* Convert rdata to keydata. */
4028 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4029 if (result == ISC_R_UNEXPECTEDEND) {
4030 continue;
4031 }
4032 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4033
4034 /* Set the key refresh timer to force a fast refresh. */
4035 set_refreshkeytimer(zone, &keydata, now, true);
4036
4037 /* If the removal timer is nonzero, this key was revoked. */
4038 if (keydata.removehd != 0) {
4039 revoked++;
4040 continue;
4041 }
4042
4043 /*
4044 * If the add timer is still pending, this key is not
4045 * trusted yet.
4046 */
4047 if (now < keydata.addhd) {
4048 pending++;
4049 continue;
4050 }
4051
4052 /* Convert keydata to dnskey. */
4053 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4054
4055 /* Add to keytables. */
4056 trusted++;
4057 trust_key(zone, name, &dnskey, (keydata.addhd == 0), mctx);
4058 }
4059
4060 if (trusted == 0 && pending != 0) {
4061 char namebuf[DNS_NAME_FORMATSIZE];
4062 dns_name_format(name, namebuf, sizeof namebuf);
4063 dnssec_log(zone, ISC_LOG_ERROR,
4064 "No valid trust anchors for '%s'!", namebuf);
4065 dnssec_log(zone, ISC_LOG_ERROR,
4066 "%d key(s) revoked, %d still pending",
4067 revoked, pending);
4068 dnssec_log(zone, ISC_LOG_ERROR,
4069 "All queries to '%s' will fail", namebuf);
4070 fail_secure(zone, name);
4071 }
4072 }
4073
4074 static isc_result_t
4075 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4076 dns_diff_t *diff)
4077 {
4078 dns_diff_t temp_diff;
4079 isc_result_t result;
4080
4081 /*
4082 * Create a singleton diff.
4083 */
4084 dns_diff_init(diff->mctx, &temp_diff);
4085 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4086
4087 /*
4088 * Apply it to the database.
4089 */
4090 result = dns_diff_apply(&temp_diff, db, ver);
4091 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4092 if (result != ISC_R_SUCCESS) {
4093 dns_difftuple_free(tuple);
4094 return (result);
4095 }
4096
4097 /*
4098 * Merge it into the current pending journal entry.
4099 */
4100 dns_diff_appendminimal(diff, tuple);
4101
4102 /*
4103 * Do not clear temp_diff.
4104 */
4105 return (ISC_R_SUCCESS);
4106 }
4107
4108 static isc_result_t
4109 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4110 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4111 dns_rdata_t *rdata)
4112 {
4113 dns_difftuple_t *tuple = NULL;
4114 isc_result_t result;
4115 result = dns_difftuple_create(diff->mctx, op,
4116 name, ttl, rdata, &tuple);
4117 if (result != ISC_R_SUCCESS)
4118 return (result);
4119 return (do_one_tuple(&tuple, db, ver, diff));
4120 }
4121
4122 static isc_result_t
4123 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4124 isc_mem_t *mctx, dns_updatemethod_t method) {
4125 dns_difftuple_t *deltuple = NULL;
4126 dns_difftuple_t *addtuple = NULL;
4127 uint32_t serial;
4128 isc_result_t result;
4129
4130 INSIST(method != dns_updatemethod_none);
4131
4132 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4133 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4134 addtuple->op = DNS_DIFFOP_ADD;
4135
4136 serial = dns_soa_getserial(&addtuple->rdata);
4137 serial = dns_update_soaserial(serial, method);
4138 dns_soa_setserial(serial, &addtuple->rdata);
4139 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4140 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4141 result = ISC_R_SUCCESS;
4142
4143 failure:
4144 if (addtuple != NULL)
4145 dns_difftuple_free(&addtuple);
4146 if (deltuple != NULL)
4147 dns_difftuple_free(&deltuple);
4148 return (result);
4149 }
4150
4151 /*
4152 * Write all transactions in 'diff' to the zone journal file.
4153 */
4154 static isc_result_t
4155 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4156 const char *caller)
4157 {
4158 const char me[] = "zone_journal";
4159 const char *journalfile;
4160 isc_result_t result = ISC_R_SUCCESS;
4161 dns_journal_t *journal = NULL;
4162 unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
4163
4164 ENTER;
4165 journalfile = dns_zone_getjournal(zone);
4166 if (journalfile != NULL) {
4167 result = dns_journal_open(zone->mctx, journalfile, mode,
4168 &journal);
4169 if (result != ISC_R_SUCCESS) {
4170 dns_zone_log(zone, ISC_LOG_ERROR,
4171 "%s:dns_journal_open -> %s",
4172 caller, dns_result_totext(result));
4173 return (result);
4174 }
4175
4176 if (sourceserial != NULL)
4177 dns_journal_set_sourceserial(journal, *sourceserial);
4178
4179 result = dns_journal_write_transaction(journal, diff);
4180 if (result != ISC_R_SUCCESS) {
4181 dns_zone_log(zone, ISC_LOG_ERROR,
4182 "%s:dns_journal_write_transaction -> %s",
4183 caller, dns_result_totext(result));
4184 }
4185 dns_journal_destroy(&journal);
4186 }
4187
4188 return (result);
4189 }
4190
4191 /*
4192 * Create an SOA record for a newly-created zone
4193 */
4194 static isc_result_t
4195 add_soa(dns_zone_t *zone, dns_db_t *db) {
4196 isc_result_t result;
4197 dns_rdata_t rdata = DNS_RDATA_INIT;
4198 unsigned char buf[DNS_SOA_BUFFERSIZE];
4199 dns_dbversion_t *ver = NULL;
4200 dns_diff_t diff;
4201
4202 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4203
4204 dns_diff_init(zone->mctx, &diff);
4205 result = dns_db_newversion(db, &ver);
4206 if (result != ISC_R_SUCCESS) {
4207 dns_zone_log(zone, ISC_LOG_ERROR,
4208 "add_soa:dns_db_newversion -> %s",
4209 dns_result_totext(result));
4210 goto failure;
4211 }
4212
4213 /* Build SOA record */
4214 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4215 0, 0, 0, 0, 0, buf, &rdata);
4216 if (result != ISC_R_SUCCESS) {
4217 dns_zone_log(zone, ISC_LOG_ERROR,
4218 "add_soa:dns_soa_buildrdata -> %s",
4219 dns_result_totext(result));
4220 goto failure;
4221 }
4222
4223 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
4224 &zone->origin, 0, &rdata);
4225
4226 failure:
4227 dns_diff_clear(&diff);
4228 if (ver != NULL)
4229 dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4230
4231 INSIST(ver == NULL);
4232
4233 return (result);
4234 }
4235
4236 struct addifmissing_arg {
4237 dns_db_t *db;
4238 dns_dbversion_t *ver;
4239 dns_diff_t *diff;
4240 dns_zone_t *zone;
4241 bool *changed;
4242 isc_result_t result;
4243 };
4244
4245 static void
4246 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
4247 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4248 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4249 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4250 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4251 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4252 isc_result_t result;
4253 dns_keynode_t *dummy = NULL;
4254
4255 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS)
4256 return;
4257
4258 if (dns_keynode_managed(keynode)) {
4259 dns_fixedname_t fname;
4260 dns_name_t *keyname;
4261 dst_key_t *key;
4262
4263 key = dns_keynode_key(keynode);
4264 if (key == NULL)
4265 return;
4266 dns_fixedname_init(&fname);
4267
4268 keyname = dst_key_name(key);
4269 result = dns_db_find(db, keyname, ver,
4270 dns_rdatatype_keydata,
4271 DNS_DBFIND_NOWILD, 0, NULL,
4272 dns_fixedname_name(&fname),
4273 NULL, NULL);
4274 if (result == ISC_R_SUCCESS)
4275 return;
4276 dns_keytable_attachkeynode(keytable, keynode, &dummy);
4277 result = create_keydata(zone, db, ver, diff, keytable,
4278 &dummy, changed);
4279 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
4280 ((struct addifmissing_arg *)arg)->result = result;
4281 }
4282 };
4283
4284 /*
4285 * Synchronize the set of initializing keys found in managed-keys {}
4286 * statements with the set of trust anchors found in the managed-keys.bind
4287 * zone. If a domain is no longer named in managed-keys, delete all keys
4288 * from that domain from the key zone. If a domain is mentioned in in
4289 * managed-keys but there are no references to it in the key zone, load
4290 * the key zone with the initializing key(s) for that domain.
4291 */
4292 static isc_result_t
4293 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4294 isc_result_t result = ISC_R_SUCCESS;
4295 bool changed = false;
4296 bool commit = false;
4297 dns_keynode_t *keynode = NULL;
4298 dns_view_t *view = zone->view;
4299 dns_keytable_t *sr = NULL;
4300 dns_dbversion_t *ver = NULL;
4301 dns_diff_t diff;
4302 dns_rriterator_t rrit;
4303 struct addifmissing_arg arg;
4304
4305 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4306
4307 dns_diff_init(zone->mctx, &diff);
4308
4309 CHECK(dns_view_getsecroots(view, &sr));
4310
4311 result = dns_db_newversion(db, &ver);
4312 if (result != ISC_R_SUCCESS) {
4313 dnssec_log(zone, ISC_LOG_ERROR,
4314 "sync_keyzone:dns_db_newversion -> %s",
4315 dns_result_totext(result));
4316 goto failure;
4317 }
4318
4319 /*
4320 * Walk the zone DB. If we find any keys whose names are no longer
4321 * in managed-keys (or *are* in trusted-keys, meaning they are
4322 * permanent and not RFC5011-maintained), delete them from the
4323 * zone. Otherwise call load_secroots(), which loads keys into
4324 * secroots as appropriate.
4325 */
4326 dns_rriterator_init(&rrit, db, ver, 0);
4327 for (result = dns_rriterator_first(&rrit);
4328 result == ISC_R_SUCCESS;
4329 result = dns_rriterator_nextrrset(&rrit))
4330 {
4331 dns_rdataset_t *rdataset = NULL;
4332 dns_name_t *rrname = NULL;
4333 uint32_t ttl;
4334
4335 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4336 if (!dns_rdataset_isassociated(rdataset)) {
4337 dns_rriterator_destroy(&rrit);
4338 goto failure;
4339 }
4340
4341 if (rdataset->type != dns_rdatatype_keydata) {
4342 continue;
4343 }
4344
4345 result = dns_keytable_find(sr, rrname, &keynode);
4346 if ((result != ISC_R_SUCCESS &&
4347 result != DNS_R_PARTIALMATCH) ||
4348 dns_keynode_managed(keynode) == false)
4349 {
4350 CHECK(delete_keydata(db, ver, &diff,
4351 rrname, rdataset));
4352 changed = true;
4353 } else {
4354 load_secroots(zone, rrname, rdataset);
4355 }
4356
4357 if (keynode != NULL) {
4358 dns_keytable_detachkeynode(sr, &keynode);
4359 }
4360 }
4361 dns_rriterator_destroy(&rrit);
4362
4363 /*
4364 * Now walk secroots to find any managed keys that aren't
4365 * in the zone. If we find any, we add them to the zone.
4366 */
4367 arg.db = db;
4368 arg.ver = ver;
4369 arg.result = ISC_R_SUCCESS;
4370 arg.diff = &diff;
4371 arg.zone = zone;
4372 arg.changed = &changed;
4373 dns_keytable_forall(sr, addifmissing, &arg);
4374 result = arg.result;
4375 if (changed) {
4376 /* Write changes to journal file. */
4377 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
4378 zone->updatemethod));
4379 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4380
4381 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4382 zone_needdump(zone, 30);
4383 commit = true;
4384 }
4385
4386 failure:
4387 if (result != ISC_R_SUCCESS &&
4388 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4389 {
4390 dnssec_log(zone, ISC_LOG_ERROR,
4391 "unable to synchronize managed keys: %s",
4392 dns_result_totext(result));
4393 isc_time_settoepoch(&zone->refreshkeytime);
4394 }
4395 if (keynode != NULL) {
4396 dns_keytable_detachkeynode(sr, &keynode);
4397 }
4398 if (sr != NULL) {
4399 dns_keytable_detach(&sr);
4400 }
4401 if (ver != NULL) {
4402 dns_db_closeversion(db, &ver, commit);
4403 }
4404 dns_diff_clear(&diff);
4405
4406 INSIST(ver == NULL);
4407
4408 return (result);
4409 }
4410
4411 isc_result_t
4412 dns_zone_synckeyzone(dns_zone_t *zone) {
4413 isc_result_t result;
4414 dns_db_t *db = NULL;
4415
4416 if (zone->type != dns_zone_key) {
4417 return (DNS_R_BADZONE);
4418 }
4419
4420 CHECK(dns_zone_getdb(zone, &db));
4421
4422 LOCK_ZONE(zone);
4423 result = sync_keyzone(zone, db);
4424 UNLOCK_ZONE(zone);
4425
4426 failure:
4427 if (db != NULL) {
4428 dns_db_detach(&db);
4429 }
4430 return (result);
4431 }
4432
4433 static void
4434 maybe_send_secure(dns_zone_t *zone) {
4435 isc_result_t result;
4436
4437 /*
4438 * We've finished loading, or else failed to load, an inline-signing
4439 * 'secure' zone. We now need information about the status of the
4440 * 'raw' zone. If we failed to load, then we need it to send a
4441 * copy of its database; if we succeeded, we need it to send its
4442 * serial number so that we can sync with it. If it has not yet
4443 * loaded, we set a flag so that it will send the necessary
4444 * information when it has finished loading.
4445 */
4446 if (zone->raw->db != NULL) {
4447 if (zone->db != NULL) {
4448 uint32_t serial;
4449 unsigned int soacount;
4450
4451 result = zone_get_from_db(zone->raw, zone->raw->db,
4452 NULL, &soacount, &serial,
4453 NULL, NULL, NULL, NULL, NULL);
4454 if (result == ISC_R_SUCCESS && soacount > 0U)
4455 zone_send_secureserial(zone->raw, serial);
4456 } else
4457 zone_send_securedb(zone->raw, zone->raw->db);
4458
4459 } else
4460 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4461 }
4462
4463 static bool
4464 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4465 isc_result_t result;
4466 bool answer = false;
4467 dns_diff_t diff;
4468
4469 dns_diff_init(mctx, &diff);
4470 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4471 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
4472 answer = true;
4473 dns_diff_clear(&diff);
4474 return (answer);
4475 }
4476
4477 /*
4478 * The zone is presumed to be locked.
4479 * If this is a inline_raw zone the secure version is also locked.
4480 */
4481 static isc_result_t
4482 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4483 isc_result_t result)
4484 {
4485 unsigned int soacount = 0;
4486 unsigned int nscount = 0;
4487 unsigned int errors = 0;
4488 uint32_t serial, oldserial, refresh, retry, expire, minimum;
4489 isc_time_t now;
4490 bool needdump = false;
4491 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4492 bool nomaster = false;
4493 bool had_db = false;
4494 unsigned int options;
4495 dns_include_t *inc;
4496
4497 INSIST(LOCKED_ZONE(zone));
4498 if (inline_raw(zone)) {
4499 INSIST(LOCKED_ZONE(zone->secure));
4500 }
4501
4502 TIME_NOW(&now);
4503
4504 /*
4505 * Initiate zone transfer? We may need a error code that
4506 * indicates that the "permanent" form does not exist.
4507 * XXX better error feedback to log.
4508 */
4509 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4510 if (zone->type == dns_zone_slave ||
4511 zone->type == dns_zone_mirror ||
4512 zone->type == dns_zone_stub ||
4513 (zone->type == dns_zone_redirect &&
4514 zone->masters == NULL))
4515 {
4516 if (result == ISC_R_FILENOTFOUND) {
4517 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4518 ISC_LOG_DEBUG(1),
4519 "no master file");
4520 } else if (result != DNS_R_NOMASTERFILE) {
4521 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4522 ISC_LOG_ERROR,
4523 "loading from master file %s "
4524 "failed: %s",
4525 zone->masterfile,
4526 dns_result_totext(result));
4527 }
4528 } else if (zone->type == dns_zone_master &&
4529 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4530 {
4531 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4532 ISC_LOG_DEBUG(1),
4533 "no master file, requesting db");
4534 maybe_send_secure(zone);
4535 } else {
4536 int level = ISC_LOG_ERROR;
4537 if (zone->type == dns_zone_key &&
4538 result == ISC_R_FILENOTFOUND)
4539 level = ISC_LOG_DEBUG(1);
4540 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4541 "loading from master file %s failed: %s",
4542 zone->masterfile,
4543 dns_result_totext(result));
4544 nomaster = true;
4545 }
4546
4547 if (zone->type != dns_zone_key) {
4548 goto cleanup;
4549 }
4550 }
4551
4552 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4553 "number of nodes in database: %u",
4554 dns_db_nodecount(db));
4555
4556 if (result == DNS_R_SEENINCLUDE) {
4557 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4558 } else {
4559 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4560 }
4561
4562 /*
4563 * If there's no master file for a key zone, then the zone is new:
4564 * create an SOA record. (We do this now, instead of later, so that
4565 * if there happens to be a journal file, we can roll forward from
4566 * a sane starting point.)
4567 */
4568 if (nomaster && zone->type == dns_zone_key) {
4569 result = add_soa(zone, db);
4570 if (result != ISC_R_SUCCESS) {
4571 goto cleanup;
4572 }
4573 }
4574
4575 /*
4576 * Apply update log, if any, on initial load.
4577 */
4578 if (zone->journal != NULL &&
4579 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4580 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4581 {
4582 if (zone->type == dns_zone_master && (inline_secure(zone) ||
4583 (zone->update_acl != NULL || zone->ssutable != NULL)))
4584 {
4585 options = DNS_JOURNALOPT_RESIGN;
4586 } else {
4587 options = 0;
4588 }
4589 result = dns_journal_rollforward(zone->mctx, db, options,
4590 zone->journal);
4591 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4592 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4593 result != ISC_R_RANGE)
4594 {
4595 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4596 ISC_LOG_ERROR,
4597 "journal rollforward failed: %s",
4598 dns_result_totext(result));
4599 goto cleanup;
4600
4601
4602 }
4603 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4604 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4605 ISC_LOG_ERROR,
4606 "journal rollforward failed: "
4607 "journal out of sync with zone");
4608 goto cleanup;
4609 }
4610 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4611 "journal rollforward completed "
4612 "successfully: %s",
4613 dns_result_totext(result));
4614 if (result == ISC_R_SUCCESS) {
4615 needdump = true;
4616 }
4617 }
4618
4619 /*
4620 * Obtain ns, soa and cname counts for top of zone.
4621 */
4622 INSIST(db != NULL);
4623 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4624 &refresh, &retry, &expire, &minimum,
4625 &errors);
4626 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4627 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4628 "could not find NS and/or SOA records");
4629 }
4630
4631 /*
4632 * Check to make sure the journal is up to date, and remove the
4633 * journal file if it isn't, as we wouldn't be able to apply
4634 * updates otherwise.
4635 */
4636 if (zone->journal != NULL && dns_zone_isdynamic(zone, true) &&
4637 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4638 {
4639 uint32_t jserial;
4640 dns_journal_t *journal = NULL;
4641 bool empty = false;
4642
4643 result = dns_journal_open(zone->mctx, zone->journal,
4644 DNS_JOURNAL_READ, &journal);
4645 if (result == ISC_R_SUCCESS) {
4646 jserial = dns_journal_last_serial(journal);
4647 empty = dns_journal_empty(journal);
4648 dns_journal_destroy(&journal);
4649 } else {
4650 jserial = serial;
4651 result = ISC_R_SUCCESS;
4652 }
4653
4654 if (jserial != serial) {
4655 if (!empty) {
4656 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4657 ISC_LOG_INFO,
4658 "journal file is out of date: "
4659 "removing journal file");
4660 }
4661 if (remove(zone->journal) < 0 && errno != ENOENT) {
4662 char strbuf[ISC_STRERRORSIZE];
4663 strerror_r(errno, strbuf, sizeof(strbuf));
4664 isc_log_write(dns_lctx,
4665 DNS_LOGCATEGORY_GENERAL,
4666 DNS_LOGMODULE_ZONE,
4667 ISC_LOG_WARNING,
4668 "unable to remove journal "
4669 "'%s': '%s'",
4670 zone->journal, strbuf);
4671 }
4672 }
4673 }
4674
4675 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4676 "loaded; checking validity");
4677
4678 /*
4679 * Master / Slave / Mirror / Stub zones require both NS and SOA records
4680 * at the top of the zone.
4681 */
4682
4683 switch (zone->type) {
4684 case dns_zone_dlz:
4685 case dns_zone_master:
4686 case dns_zone_slave:
4687 case dns_zone_mirror:
4688 case dns_zone_stub:
4689 case dns_zone_redirect:
4690 if (soacount != 1) {
4691 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4692 ISC_LOG_ERROR,
4693 "has %d SOA records", soacount);
4694 result = DNS_R_BADZONE;
4695 }
4696 if (nscount == 0) {
4697 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4698 ISC_LOG_ERROR,
4699 "has no NS records");
4700 result = DNS_R_BADZONE;
4701 }
4702 if (result != ISC_R_SUCCESS) {
4703 goto cleanup;
4704 }
4705 if (zone->type == dns_zone_master && errors != 0) {
4706 result = DNS_R_BADZONE;
4707 goto cleanup;
4708 }
4709 if (zone->type != dns_zone_stub &&
4710 zone->type != dns_zone_redirect)
4711 {
4712 result = check_nsec3param(zone, db);
4713 if (result != ISC_R_SUCCESS)
4714 goto cleanup;
4715 }
4716 if (zone->type == dns_zone_master &&
4717 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4718 !integrity_checks(zone, db))
4719 {
4720 result = DNS_R_BADZONE;
4721 goto cleanup;
4722 }
4723 if (zone->type == dns_zone_master &&
4724 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4725 !zone_check_dup(zone, db))
4726 {
4727 result = DNS_R_BADZONE;
4728 goto cleanup;
4729 }
4730
4731 result = dns_zone_verifydb(zone, db, NULL);
4732 if (result != ISC_R_SUCCESS) {
4733 goto cleanup;
4734 }
4735
4736 if (zone->db != NULL) {
4737 unsigned int oldsoacount;
4738
4739 /*
4740 * This is checked in zone_replacedb() for slave zones
4741 * as they don't reload from disk.
4742 */
4743 result = zone_get_from_db(zone, zone->db, NULL,
4744 &oldsoacount, &oldserial,
4745 NULL, NULL, NULL, NULL,
4746 NULL);
4747 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4748 RUNTIME_CHECK(soacount > 0U);
4749 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4750 !isc_serial_gt(serial, oldserial)) {
4751 uint32_t serialmin, serialmax;
4752
4753 INSIST(zone->type == dns_zone_master);
4754 INSIST(zone->raw == NULL);
4755
4756 if (serial == oldserial &&
4757 zone_unchanged(zone->db, db, zone->mctx)) {
4758 dns_zone_logc(zone,
4759 DNS_LOGCATEGORY_ZONELOAD,
4760 ISC_LOG_INFO,
4761 "ixfr-from-differences: "
4762 "unchanged");
4763 goto done;
4764 }
4765
4766 serialmin = (oldserial + 1) & 0xffffffffU;
4767 serialmax = (oldserial + 0x7fffffffU) &
4768 0xffffffffU;
4769 dns_zone_logc(zone,
4770 DNS_LOGCATEGORY_ZONELOAD,
4771 ISC_LOG_ERROR,
4772 "ixfr-from-differences: "
4773 "new serial (%u) out of range "
4774 "[%u - %u]", serial, serialmin,
4775 serialmax);
4776 result = DNS_R_BADZONE;
4777 goto cleanup;
4778 } else if (!isc_serial_ge(serial, oldserial)) {
4779 dns_zone_logc(zone,
4780 DNS_LOGCATEGORY_ZONELOAD,
4781 ISC_LOG_ERROR,
4782 "zone serial (%u/%u) has gone "
4783 "backwards", serial, oldserial);
4784 } else if (serial == oldserial && !hasinclude &&
4785 strcmp(zone->db_argv[0], "_builtin") != 0)
4786 {
4787 dns_zone_logc(zone,
4788 DNS_LOGCATEGORY_ZONELOAD,
4789 ISC_LOG_ERROR,
4790 "zone serial (%u) unchanged. "
4791 "zone may fail to transfer "
4792 "to slaves.", serial);
4793 }
4794 }
4795
4796 if (zone->type == dns_zone_master &&
4797 (zone->update_acl != NULL || zone->ssutable != NULL) &&
4798 zone->sigresigninginterval < (3 * refresh) &&
4799 dns_db_issecure(db))
4800 {
4801 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4802 ISC_LOG_WARNING,
4803 "sig-re-signing-interval less than "
4804 "3 * refresh.");
4805 }
4806
4807 zone->refresh = RANGE(refresh,
4808 zone->minrefresh, zone->maxrefresh);
4809 zone->retry = RANGE(retry,
4810 zone->minretry, zone->maxretry);
4811 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4812 DNS_MAX_EXPIRE);
4813 zone->minimum = minimum;
4814 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4815
4816 if (zone->type == dns_zone_slave ||
4817 zone->type == dns_zone_mirror ||
4818 zone->type == dns_zone_stub ||
4819 (zone->type == dns_zone_redirect &&
4820 zone->masters != NULL))
4821 {
4822 isc_time_t t;
4823 uint32_t delay;
4824
4825 result = isc_file_getmodtime(zone->journal, &t);
4826 if (result != ISC_R_SUCCESS) {
4827 result = isc_file_getmodtime(zone->masterfile,
4828 &t);
4829 }
4830 if (result == ISC_R_SUCCESS) {
4831 DNS_ZONE_TIME_ADD(&t, zone->expire,
4832 &zone->expiretime);
4833 } else {
4834 DNS_ZONE_TIME_ADD(&now, zone->retry,
4835 &zone->expiretime);
4836 }
4837
4838 delay = (zone->retry -
4839 isc_random_uniform((zone->retry * 3) / 4));
4840 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4841 if (isc_time_compare(&zone->refreshtime,
4842 &zone->expiretime) >= 0)
4843 {
4844 zone->refreshtime = now;
4845 }
4846 }
4847
4848 break;
4849
4850 case dns_zone_key:
4851 result = sync_keyzone(zone, db);
4852 if (result != ISC_R_SUCCESS) {
4853 goto cleanup;
4854 }
4855 break;
4856
4857 default:
4858 UNEXPECTED_ERROR(__FILE__, __LINE__,
4859 "unexpected zone type %d", zone->type);
4860 result = ISC_R_UNEXPECTED;
4861 goto cleanup;
4862 }
4863
4864 /*
4865 * Check for weak DNSKEY's.
4866 */
4867 if (zone->type == dns_zone_master) {
4868 zone_check_dnskeys(zone, db);
4869 }
4870
4871 /*
4872 * Schedule DNSSEC key refresh.
4873 */
4874 if (zone->type == dns_zone_master &&
4875 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4876 {
4877 zone->refreshkeytime = now;
4878 }
4879
4880 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4881 if (zone->db != NULL) {
4882 had_db = true;
4883 result = zone_replacedb(zone, db, false);
4884 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4885 if (result != ISC_R_SUCCESS) {
4886 goto cleanup;
4887 }
4888 } else {
4889 zone_attachdb(zone, db);
4890 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4891 DNS_ZONE_SETFLAG(zone,
4892 DNS_ZONEFLG_LOADED|
4893 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
4894 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4895 inline_raw(zone))
4896 {
4897 if (zone->secure->db == NULL) {
4898 zone_send_securedb(zone, db);
4899 } else {
4900 zone_send_secureserial(zone, serial);
4901 }
4902 }
4903 }
4904
4905 /*
4906 * Finished loading inline-signing zone; need to get status
4907 * from the raw side now.
4908 */
4909 if (zone->type == dns_zone_master && inline_secure(zone)) {
4910 maybe_send_secure(zone);
4911 }
4912
4913 result = ISC_R_SUCCESS;
4914
4915 if (needdump) {
4916 if (zone->type == dns_zone_key) {
4917 zone_needdump(zone, 30);
4918 } else {
4919 zone_needdump(zone, DNS_DUMP_DELAY);
4920 }
4921 }
4922
4923 if (zone->task != NULL) {
4924 if (zone->type == dns_zone_master) {
4925 set_resigntime(zone);
4926 resume_signingwithkey(zone);
4927 resume_addnsec3chain(zone);
4928 }
4929
4930 if (zone->type == dns_zone_master &&
4931 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4932 dns_zone_isdynamic(zone, false) &&
4933 dns_db_issecure(db))
4934 {
4935 dns_name_t *name;
4936 dns_fixedname_t fixed;
4937 dns_rdataset_t next;
4938
4939 dns_rdataset_init(&next);
4940 name = dns_fixedname_initname(&fixed);
4941
4942 result = dns_db_getsigningtime(db, &next, name);
4943 if (result == ISC_R_SUCCESS) {
4944 isc_stdtime_t timenow;
4945 char namebuf[DNS_NAME_FORMATSIZE];
4946 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4947
4948 isc_stdtime_get(&timenow);
4949 dns_name_format(name, namebuf, sizeof(namebuf));
4950 dns_rdatatype_format(next.covers,
4951 typebuf, sizeof(typebuf));
4952 dnssec_log(zone, ISC_LOG_DEBUG(3),
4953 "next resign: %s/%s "
4954 "in %d seconds", namebuf, typebuf,
4955 next.resign - timenow -
4956 zone->sigresigninginterval);
4957 dns_rdataset_disassociate(&next);
4958 } else {
4959 dnssec_log(zone, ISC_LOG_WARNING,
4960 "signed dynamic zone has no "
4961 "resign event scheduled");
4962 }
4963 }
4964
4965 zone_settimer(zone, &now);
4966 }
4967
4968 /*
4969 * Clear old include list.
4970 */
4971 for (inc = ISC_LIST_HEAD(zone->includes);
4972 inc != NULL;
4973 inc = ISC_LIST_HEAD(zone->includes))
4974 {
4975 ISC_LIST_UNLINK(zone->includes, inc, link);
4976 isc_mem_free(zone->mctx, inc->name);
4977 isc_mem_put(zone->mctx, inc, sizeof(*inc));
4978 }
4979 zone->nincludes = 0;
4980
4981 /*
4982 * Transfer new include list.
4983 */
4984 for (inc = ISC_LIST_HEAD(zone->newincludes);
4985 inc != NULL;
4986 inc = ISC_LIST_HEAD(zone->newincludes))
4987 {
4988 ISC_LIST_UNLINK(zone->newincludes, inc, link);
4989 ISC_LIST_APPEND(zone->includes, inc, link);
4990 zone->nincludes++;
4991 }
4992
4993 if (! dns_db_ispersistent(db)) {
4994 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4995 ISC_LOG_INFO, "loaded serial %u%s", serial,
4996 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4997 }
4998
4999 if (!had_db && zone->type == dns_zone_mirror) {
5000 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5001 "mirror zone is now in use");
5002 }
5003
5004 zone->loadtime = loadtime;
5005 goto done;
5006
5007 cleanup:
5008 if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
5009 dnssec_log(zone, ISC_LOG_ERROR,
5010 "failed to initialize managed-keys (%s): "
5011 "DNSSEC validation is at risk",
5012 isc_result_totext(result));
5013 }
5014
5015 for (inc = ISC_LIST_HEAD(zone->newincludes);
5016 inc != NULL;
5017 inc = ISC_LIST_HEAD(zone->newincludes))
5018 {
5019 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5020 isc_mem_free(zone->mctx, inc->name);
5021 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5022 }
5023 if (zone->type == dns_zone_slave ||
5024 zone->type == dns_zone_mirror ||
5025 zone->type == dns_zone_stub ||
5026 zone->type == dns_zone_key ||
5027 (zone->type == dns_zone_redirect && zone->masters != NULL))
5028 {
5029 if (result != ISC_R_NOMEMORY) {
5030 if (zone->journal != NULL) {
5031 zone_saveunique(zone, zone->journal,
5032 "jn-XXXXXXXX");
5033 }
5034 if (zone->masterfile != NULL) {
5035 zone_saveunique(zone, zone->masterfile,
5036 "db-XXXXXXXX");
5037 }
5038 }
5039
5040 /* Mark the zone for immediate refresh. */
5041 zone->refreshtime = now;
5042 if (zone->task != NULL) {
5043 zone_settimer(zone, &now);
5044 }
5045 result = ISC_R_SUCCESS;
5046 } else if (zone->type == dns_zone_master ||
5047 zone->type == dns_zone_redirect)
5048 {
5049 if (! (inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5050 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5051 ISC_LOG_ERROR,
5052 "not loaded due to errors.");
5053 } else if (zone->type == dns_zone_master) {
5054 result = ISC_R_SUCCESS;
5055 }
5056 }
5057
5058 done:
5059 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5060 /*
5061 * If this is an inline-signed zone and we were called for the raw
5062 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5063 * as well, but only if this is a reload, not an initial zone load: in
5064 * the former case, zone_postload() will not be run for the secure
5065 * zone; in the latter case, it will be. Check which case we are
5066 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5067 * secure zone: if it is set, this must be a reload.
5068 */
5069 if (inline_raw(zone) &&
5070 DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5071 {
5072 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5073 }
5074
5075 zone_debuglog(zone, "zone_postload", 99, "done");
5076
5077 return (result);
5078 }
5079
5080 static bool
5081 exit_check(dns_zone_t *zone) {
5082 REQUIRE(LOCKED_ZONE(zone));
5083
5084 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
5085 /*
5086 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5087 */
5088 INSIST(isc_refcount_current(&zone->erefs) == 0);
5089 return (true);
5090 }
5091 return (false);
5092 }
5093
5094 static bool
5095 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5096 dns_name_t *name, bool logit)
5097 {
5098 isc_result_t result;
5099 char namebuf[DNS_NAME_FORMATSIZE];
5100 char altbuf[DNS_NAME_FORMATSIZE];
5101 dns_fixedname_t fixed;
5102 dns_name_t *foundname;
5103 int level;
5104
5105 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
5106 return (true);
5107
5108 if (zone->type == dns_zone_master)
5109 level = ISC_LOG_ERROR;
5110 else
5111 level = ISC_LOG_WARNING;
5112
5113 foundname = dns_fixedname_initname(&fixed);
5114
5115 result = dns_db_find(db, name, version, dns_rdatatype_a,
5116 0, 0, NULL, foundname, NULL, NULL);
5117 if (result == ISC_R_SUCCESS)
5118 return (true);
5119
5120 if (result == DNS_R_NXRRSET) {
5121 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
5122 0, 0, NULL, foundname, NULL, NULL);
5123 if (result == ISC_R_SUCCESS)
5124 return (true);
5125 }
5126
5127 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5128 result == DNS_R_EMPTYNAME) {
5129 if (logit) {
5130 dns_name_format(name, namebuf, sizeof namebuf);
5131 dns_zone_log(zone, level, "NS '%s' has no address "
5132 "records (A or AAAA)", namebuf);
5133 }
5134 return (false);
5135 }
5136
5137 if (result == DNS_R_CNAME) {
5138 if (logit) {
5139 dns_name_format(name, namebuf, sizeof namebuf);
5140 dns_zone_log(zone, level, "NS '%s' is a CNAME "
5141 "(illegal)", namebuf);
5142 }
5143 return (false);
5144 }
5145
5146 if (result == DNS_R_DNAME) {
5147 if (logit) {
5148 dns_name_format(name, namebuf, sizeof namebuf);
5149 dns_name_format(foundname, altbuf, sizeof altbuf);
5150 dns_zone_log(zone, level, "NS '%s' is below a DNAME "
5151 "'%s' (illegal)", namebuf, altbuf);
5152 }
5153 return (false);
5154 }
5155
5156 return (true);
5157 }
5158
5159 static isc_result_t
5160 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5161 dns_dbversion_t *version, unsigned int *nscount,
5162 unsigned int *errors, bool logit)
5163 {
5164 isc_result_t result;
5165 unsigned int count = 0;
5166 unsigned int ecount = 0;
5167 dns_rdataset_t rdataset;
5168 dns_rdata_t rdata;
5169 dns_rdata_ns_t ns;
5170
5171 dns_rdataset_init(&rdataset);
5172 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5173 dns_rdatatype_none, 0, &rdataset, NULL);
5174 if (result == ISC_R_NOTFOUND) {
5175 INSIST(!dns_rdataset_isassociated(&rdataset));
5176 goto success;
5177 }
5178 if (result != ISC_R_SUCCESS) {
5179 INSIST(!dns_rdataset_isassociated(&rdataset));
5180 goto invalidate_rdataset;
5181 }
5182
5183 result = dns_rdataset_first(&rdataset);
5184 while (result == ISC_R_SUCCESS) {
5185 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5186 (zone->type == dns_zone_master ||
5187 zone->type == dns_zone_slave ||
5188 zone->type == dns_zone_mirror))
5189 {
5190 dns_rdata_init(&rdata);
5191 dns_rdataset_current(&rdataset, &rdata);
5192 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5193 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5194 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5195 !zone_check_ns(zone, db, version, &ns.name, logit))
5196 ecount++;
5197 }
5198 count++;
5199 result = dns_rdataset_next(&rdataset);
5200 }
5201 dns_rdataset_disassociate(&rdataset);
5202
5203 success:
5204 if (nscount != NULL)
5205 *nscount = count;
5206 if (errors != NULL)
5207 *errors = ecount;
5208
5209 result = ISC_R_SUCCESS;
5210
5211 invalidate_rdataset:
5212 dns_rdataset_invalidate(&rdataset);
5213
5214 return (result);
5215 }
5216
5217 static isc_result_t
5218 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5219 unsigned int *soacount,
5220 uint32_t *serial, uint32_t *refresh,
5221 uint32_t *retry, uint32_t *expire,
5222 uint32_t *minimum)
5223 {
5224 isc_result_t result;
5225 unsigned int count;
5226 dns_rdataset_t rdataset;
5227 dns_rdata_t rdata = DNS_RDATA_INIT;
5228 dns_rdata_soa_t soa;
5229
5230 dns_rdataset_init(&rdataset);
5231 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5232 dns_rdatatype_none, 0, &rdataset, NULL);
5233 if (result == ISC_R_NOTFOUND) {
5234 INSIST(!dns_rdataset_isassociated(&rdataset));
5235 if (soacount != NULL)
5236 *soacount = 0;
5237 if (serial != NULL)
5238 *serial = 0;
5239 if (refresh != NULL)
5240 *refresh = 0;
5241 if (retry != NULL)
5242 *retry = 0;
5243 if (expire != NULL)
5244 *expire = 0;
5245 if (minimum != NULL)
5246 *minimum = 0;
5247 result = ISC_R_SUCCESS;
5248 goto invalidate_rdataset;
5249 }
5250 if (result != ISC_R_SUCCESS) {
5251 INSIST(!dns_rdataset_isassociated(&rdataset));
5252 goto invalidate_rdataset;
5253 }
5254
5255 count = 0;
5256 result = dns_rdataset_first(&rdataset);
5257 while (result == ISC_R_SUCCESS) {
5258 dns_rdata_init(&rdata);
5259 dns_rdataset_current(&rdataset, &rdata);
5260 count++;
5261 if (count == 1) {
5262 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5263 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5264 }
5265
5266 result = dns_rdataset_next(&rdataset);
5267 dns_rdata_reset(&rdata);
5268 }
5269 dns_rdataset_disassociate(&rdataset);
5270
5271 if (soacount != NULL)
5272 *soacount = count;
5273
5274 if (count > 0) {
5275 if (serial != NULL)
5276 *serial = soa.serial;
5277 if (refresh != NULL)
5278 *refresh = soa.refresh;
5279 if (retry != NULL)
5280 *retry = soa.retry;
5281 if (expire != NULL)
5282 *expire = soa.expire;
5283 if (minimum != NULL)
5284 *minimum = soa.minimum;
5285 } else {
5286 if (soacount != NULL)
5287 *soacount = 0;
5288 if (serial != NULL)
5289 *serial = 0;
5290 if (refresh != NULL)
5291 *refresh = 0;
5292 if (retry != NULL)
5293 *retry = 0;
5294 if (expire != NULL)
5295 *expire = 0;
5296 if (minimum != NULL)
5297 *minimum = 0;
5298 }
5299
5300 result = ISC_R_SUCCESS;
5301
5302 invalidate_rdataset:
5303 dns_rdataset_invalidate(&rdataset);
5304
5305 return (result);
5306 }
5307
5308 /*
5309 * zone must be locked.
5310 */
5311 static isc_result_t
5312 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5313 unsigned int *soacount, uint32_t *serial,
5314 uint32_t *refresh, uint32_t *retry,
5315 uint32_t *expire, uint32_t *minimum,
5316 unsigned int *errors)
5317 {
5318 isc_result_t result;
5319 isc_result_t answer = ISC_R_SUCCESS;
5320 dns_dbversion_t *version = NULL;
5321 dns_dbnode_t *node;
5322
5323 REQUIRE(db != NULL);
5324 REQUIRE(zone != NULL);
5325
5326 dns_db_currentversion(db, &version);
5327
5328 if (nscount != NULL)
5329 *nscount = 0;
5330 if (soacount != NULL)
5331 *soacount = 0;
5332 if (serial != NULL)
5333 *serial = 0;
5334 if (refresh != NULL)
5335 *refresh = 0;
5336 if (retry != NULL)
5337 *retry = 0;
5338 if (expire != NULL)
5339 *expire = 0;
5340 if (errors != NULL)
5341 *errors = 0;
5342
5343 node = NULL;
5344 result = dns_db_findnode(db, &zone->origin, false, &node);
5345 if (result != ISC_R_SUCCESS) {
5346 answer = result;
5347 goto closeversion;
5348 }
5349
5350 if (nscount != NULL || errors != NULL) {
5351 result = zone_count_ns_rr(zone, db, node, version,
5352 nscount, errors, true);
5353 if (result != ISC_R_SUCCESS)
5354 answer = result;
5355 }
5356
5357 if (soacount != NULL || serial != NULL || refresh != NULL
5358 || retry != NULL || expire != NULL || minimum != NULL) {
5359 result = zone_load_soa_rr(db, node, version, soacount,
5360 serial, refresh, retry, expire,
5361 minimum);
5362 if (result != ISC_R_SUCCESS)
5363 answer = result;
5364 }
5365
5366 dns_db_detachnode(db, &node);
5367 closeversion:
5368 dns_db_closeversion(db, &version, false);
5369
5370 return (answer);
5371 }
5372
5373 void
5374 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5375 REQUIRE(DNS_ZONE_VALID(source));
5376 REQUIRE(target != NULL && *target == NULL);
5377 isc_refcount_increment(&source->erefs);
5378 *target = source;
5379 }
5380
5381 void
5382 dns_zone_detach(dns_zone_t **zonep) {
5383 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5384 dns_zone_t *zone = *zonep;
5385 *zonep = NULL;
5386
5387 bool free_now = false;
5388 dns_zone_t *raw = NULL;
5389 dns_zone_t *secure = NULL;
5390 if (isc_refcount_decrement(&zone->erefs) == 1) {
5391 isc_refcount_destroy(&zone->erefs);
5392
5393 LOCK_ZONE(zone);
5394 INSIST(zone != zone->raw);
5395 /*
5396 * We just detached the last external reference.
5397 */
5398 if (zone->task != NULL) {
5399 /*
5400 * This zone is being managed. Post
5401 * its control event and let it clean
5402 * up synchronously in the context of
5403 * its task.
5404 */
5405 isc_event_t *ev = &zone->ctlevent;
5406 isc_task_send(zone->task, &ev);
5407 } else {
5408 /*
5409 * This zone is not being managed; it has
5410 * no task and can have no outstanding
5411 * events. Free it immediately.
5412 */
5413 /*
5414 * Unmanaged zones should not have non-null views;
5415 * we have no way of detaching from the view here
5416 * without causing deadlock because this code is called
5417 * with the view already locked.
5418 */
5419 INSIST(zone->view == NULL);
5420 free_now = true;
5421 raw = zone->raw;
5422 zone->raw = NULL;
5423 secure = zone->secure;
5424 zone->secure = NULL;
5425 }
5426 UNLOCK_ZONE(zone);
5427 }
5428 if (free_now) {
5429 if (raw != NULL) {
5430 dns_zone_detach(&raw);
5431 }
5432 if (secure != NULL) {
5433 dns_zone_idetach(&secure);
5434 }
5435 zone_free(zone);
5436 }
5437 }
5438
5439 void
5440 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5441 REQUIRE(DNS_ZONE_VALID(source));
5442 REQUIRE(target != NULL && *target == NULL);
5443 LOCK_ZONE(source);
5444 zone_iattach(source, target);
5445 UNLOCK_ZONE(source);
5446 }
5447
5448 static void
5449 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5450
5451 /*
5452 * 'source' locked by caller.
5453 */
5454 REQUIRE(LOCKED_ZONE(source));
5455 REQUIRE(DNS_ZONE_VALID(source));
5456 REQUIRE(target != NULL && *target == NULL);
5457 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
5458 source->irefs++;
5459 INSIST(source->irefs != 0);
5460 *target = source;
5461 }
5462
5463 static void
5464 zone_idetach(dns_zone_t **zonep) {
5465 dns_zone_t *zone;
5466
5467 /*
5468 * 'zone' locked by caller.
5469 */
5470 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5471 zone = *zonep;
5472 REQUIRE(LOCKED_ZONE(*zonep));
5473 *zonep = NULL;
5474
5475 INSIST(zone->irefs > 0);
5476 zone->irefs--;
5477 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
5478 }
5479
5480 void
5481 dns_zone_idetach(dns_zone_t **zonep) {
5482 dns_zone_t *zone;
5483 bool free_needed;
5484
5485 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5486 zone = *zonep;
5487 *zonep = NULL;
5488
5489 LOCK_ZONE(zone);
5490 INSIST(zone->irefs > 0);
5491 zone->irefs--;
5492 free_needed = exit_check(zone);
5493 UNLOCK_ZONE(zone);
5494 if (free_needed)
5495 zone_free(zone);
5496 }
5497
5498 isc_mem_t *
5499 dns_zone_getmctx(dns_zone_t *zone) {
5500 REQUIRE(DNS_ZONE_VALID(zone));
5501
5502 return (zone->mctx);
5503 }
5504
5505 dns_zonemgr_t *
5506 dns_zone_getmgr(dns_zone_t *zone) {
5507 REQUIRE(DNS_ZONE_VALID(zone));
5508
5509 return (zone->zmgr);
5510 }
5511
5512 void
5513 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value) {
5514 REQUIRE(DNS_ZONE_VALID(zone));
5515
5516 LOCK_ZONE(zone);
5517 if (value)
5518 DNS_ZONE_SETFLAG(zone, flags);
5519 else
5520 DNS_ZONE_CLRFLAG(zone, flags);
5521 UNLOCK_ZONE(zone);
5522 }
5523
5524 void
5525 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option,
5526 bool value)
5527 {
5528 REQUIRE(DNS_ZONE_VALID(zone));
5529
5530 LOCK_ZONE(zone);
5531 if (value)
5532 zone->options |= option;
5533 else
5534 zone->options &= ~option;
5535 UNLOCK_ZONE(zone);
5536 }
5537
5538 dns_zoneopt_t
5539 dns_zone_getoptions(dns_zone_t *zone) {
5540 REQUIRE(DNS_ZONE_VALID(zone));
5541
5542 return (zone->options);
5543 }
5544
5545 void
5546 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value)
5547 {
5548 REQUIRE(DNS_ZONE_VALID(zone));
5549
5550 LOCK_ZONE(zone);
5551 if (value)
5552 zone->keyopts |= keyopt;
5553 else
5554 zone->keyopts &= ~keyopt;
5555 UNLOCK_ZONE(zone);
5556 }
5557
5558 unsigned int
5559 dns_zone_getkeyopts(dns_zone_t *zone) {
5560
5561 REQUIRE(DNS_ZONE_VALID(zone));
5562
5563 return (zone->keyopts);
5564 }
5565
5566 isc_result_t
5567 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5568 REQUIRE(DNS_ZONE_VALID(zone));
5569
5570 LOCK_ZONE(zone);
5571 zone->xfrsource4 = *xfrsource;
5572 UNLOCK_ZONE(zone);
5573
5574 return (ISC_R_SUCCESS);
5575 }
5576
5577 isc_sockaddr_t *
5578 dns_zone_getxfrsource4(dns_zone_t *zone) {
5579 REQUIRE(DNS_ZONE_VALID(zone));
5580 return (&zone->xfrsource4);
5581 }
5582
5583 isc_result_t
5584 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5585 REQUIRE(DNS_ZONE_VALID(zone));
5586
5587 LOCK_ZONE(zone);
5588 zone->xfrsource4dscp = dscp;
5589 UNLOCK_ZONE(zone);
5590
5591 return (ISC_R_SUCCESS);
5592 }
5593
5594 isc_dscp_t
5595 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5596 REQUIRE(DNS_ZONE_VALID(zone));
5597 return (zone->xfrsource4dscp);
5598 }
5599
5600 isc_result_t
5601 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5602 REQUIRE(DNS_ZONE_VALID(zone));
5603
5604 LOCK_ZONE(zone);
5605 zone->xfrsource6 = *xfrsource;
5606 UNLOCK_ZONE(zone);
5607
5608 return (ISC_R_SUCCESS);
5609 }
5610
5611 isc_sockaddr_t *
5612 dns_zone_getxfrsource6(dns_zone_t *zone) {
5613 REQUIRE(DNS_ZONE_VALID(zone));
5614 return (&zone->xfrsource6);
5615 }
5616
5617 isc_dscp_t
5618 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5619 REQUIRE(DNS_ZONE_VALID(zone));
5620 return (zone->xfrsource6dscp);
5621 }
5622
5623 isc_result_t
5624 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5625 REQUIRE(DNS_ZONE_VALID(zone));
5626
5627 LOCK_ZONE(zone);
5628 zone->xfrsource6dscp = dscp;
5629 UNLOCK_ZONE(zone);
5630
5631 return (ISC_R_SUCCESS);
5632 }
5633
5634 isc_result_t
5635 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5636 const isc_sockaddr_t *altxfrsource)
5637 {
5638 REQUIRE(DNS_ZONE_VALID(zone));
5639
5640 LOCK_ZONE(zone);
5641 zone->altxfrsource4 = *altxfrsource;
5642 UNLOCK_ZONE(zone);
5643
5644 return (ISC_R_SUCCESS);
5645 }
5646
5647 isc_sockaddr_t *
5648 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
5649 REQUIRE(DNS_ZONE_VALID(zone));
5650 return (&zone->altxfrsource4);
5651 }
5652
5653 isc_result_t
5654 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5655 REQUIRE(DNS_ZONE_VALID(zone));
5656
5657 LOCK_ZONE(zone);
5658 zone->altxfrsource4dscp = dscp;
5659 UNLOCK_ZONE(zone);
5660
5661 return (ISC_R_SUCCESS);
5662 }
5663
5664 isc_dscp_t
5665 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
5666 REQUIRE(DNS_ZONE_VALID(zone));
5667 return (zone->altxfrsource4dscp);
5668 }
5669
5670 isc_result_t
5671 dns_zone_setaltxfrsource6(dns_zone_t *zone,
5672 const isc_sockaddr_t *altxfrsource)
5673 {
5674 REQUIRE(DNS_ZONE_VALID(zone));
5675
5676 LOCK_ZONE(zone);
5677 zone->altxfrsource6 = *altxfrsource;
5678 UNLOCK_ZONE(zone);
5679
5680 return (ISC_R_SUCCESS);
5681 }
5682
5683 isc_sockaddr_t *
5684 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
5685 REQUIRE(DNS_ZONE_VALID(zone));
5686 return (&zone->altxfrsource6);
5687 }
5688
5689 isc_result_t
5690 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5691 REQUIRE(DNS_ZONE_VALID(zone));
5692
5693 LOCK_ZONE(zone);
5694 zone->altxfrsource6dscp = dscp;
5695 UNLOCK_ZONE(zone);
5696
5697 return (ISC_R_SUCCESS);
5698 }
5699
5700 isc_dscp_t
5701 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
5702 REQUIRE(DNS_ZONE_VALID(zone));
5703 return (zone->altxfrsource6dscp);
5704 }
5705
5706 isc_result_t
5707 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5708 REQUIRE(DNS_ZONE_VALID(zone));
5709
5710 LOCK_ZONE(zone);
5711 zone->notifysrc4 = *notifysrc;
5712 UNLOCK_ZONE(zone);
5713
5714 return (ISC_R_SUCCESS);
5715 }
5716
5717 isc_sockaddr_t *
5718 dns_zone_getnotifysrc4(dns_zone_t *zone) {
5719 REQUIRE(DNS_ZONE_VALID(zone));
5720 return (&zone->notifysrc4);
5721 }
5722
5723 isc_result_t
5724 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5725 REQUIRE(DNS_ZONE_VALID(zone));
5726
5727 LOCK_ZONE(zone);
5728 zone->notifysrc4dscp = dscp;
5729 UNLOCK_ZONE(zone);
5730
5731 return (ISC_R_SUCCESS);
5732 }
5733
5734 isc_dscp_t
5735 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
5736 REQUIRE(DNS_ZONE_VALID(zone));
5737 return (zone->notifysrc4dscp);
5738 }
5739
5740 isc_result_t
5741 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5742 REQUIRE(DNS_ZONE_VALID(zone));
5743
5744 LOCK_ZONE(zone);
5745 zone->notifysrc6 = *notifysrc;
5746 UNLOCK_ZONE(zone);
5747
5748 return (ISC_R_SUCCESS);
5749 }
5750
5751 isc_sockaddr_t *
5752 dns_zone_getnotifysrc6(dns_zone_t *zone) {
5753 REQUIRE(DNS_ZONE_VALID(zone));
5754 return (&zone->notifysrc6);
5755 }
5756
5757 static bool
5758 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
5759 uint32_t count)
5760 {
5761 unsigned int i;
5762
5763 for (i = 0; i < count; i++)
5764 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i]))
5765 return (false);
5766 return (true);
5767 }
5768
5769 static bool
5770 same_keynames(dns_name_t * const *oldlist, dns_name_t * const *newlist,
5771 uint32_t count)
5772 {
5773 unsigned int i;
5774
5775 if (oldlist == NULL && newlist == NULL)
5776 return (true);
5777 if (oldlist == NULL || newlist == NULL)
5778 return (false);
5779
5780 for (i = 0; i < count; i++) {
5781 if (oldlist[i] == NULL && newlist[i] == NULL)
5782 continue;
5783 if (oldlist[i] == NULL || newlist[i] == NULL ||
5784 !dns_name_equal(oldlist[i], newlist[i]))
5785 return (false);
5786 }
5787 return (true);
5788 }
5789
5790 static void
5791 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
5792 dns_name_t ***keynamesp, unsigned int *countp,
5793 isc_mem_t *mctx)
5794 {
5795 unsigned int count;
5796 isc_sockaddr_t *addrs;
5797 isc_dscp_t *dscps;
5798 dns_name_t **keynames;
5799
5800 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
5801 keynamesp != NULL);
5802
5803 count = *countp;
5804 *countp = 0;
5805 addrs = *addrsp;
5806 *addrsp = NULL;
5807 dscps = *dscpsp;
5808 *dscpsp = NULL;
5809 keynames = *keynamesp;
5810 *keynamesp = NULL;
5811
5812 if (addrs != NULL)
5813 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
5814
5815 if (dscps != NULL)
5816 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
5817
5818 if (keynames != NULL) {
5819 unsigned int i;
5820 for (i = 0; i < count; i++) {
5821 if (keynames[i] != NULL) {
5822 dns_name_free(keynames[i], mctx);
5823 isc_mem_put(mctx, keynames[i],
5824 sizeof(dns_name_t));
5825 keynames[i] = NULL;
5826 }
5827 }
5828 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
5829 }
5830 }
5831
5832 static isc_result_t
5833 set_addrkeylist(unsigned int count,
5834 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
5835 const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
5836 dns_name_t **names, dns_name_t ***newnamesp,
5837 isc_mem_t *mctx)
5838 {
5839 isc_result_t result;
5840 isc_sockaddr_t *newaddrs = NULL;
5841 isc_dscp_t *newdscp = NULL;
5842 dns_name_t **newnames = NULL;
5843 unsigned int i;
5844
5845 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
5846 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
5847 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
5848
5849 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
5850 if (newaddrs == NULL)
5851 return (ISC_R_NOMEMORY);
5852 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
5853
5854 if (dscp != NULL) {
5855 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
5856 if (newdscp == NULL) {
5857 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5858 return (ISC_R_NOMEMORY);
5859 }
5860 memmove(newdscp, dscp, count * sizeof(*newdscp));
5861 } else
5862 newdscp = NULL;
5863
5864 if (names != NULL) {
5865 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
5866 if (newnames == NULL) {
5867 if (newdscp != NULL)
5868 isc_mem_put(mctx, newdscp,
5869 count * sizeof(*newdscp));
5870 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5871 return (ISC_R_NOMEMORY);
5872 }
5873 for (i = 0; i < count; i++)
5874 newnames[i] = NULL;
5875 for (i = 0; i < count; i++) {
5876 if (names[i] != NULL) {
5877 newnames[i] = isc_mem_get(mctx,
5878 sizeof(dns_name_t));
5879 if (newnames[i] == NULL)
5880 goto allocfail;
5881 dns_name_init(newnames[i], NULL);
5882 result = dns_name_dup(names[i], mctx,
5883 newnames[i]);
5884 if (result != ISC_R_SUCCESS) {
5885 allocfail:
5886 for (i = 0; i < count; i++)
5887 if (newnames[i] != NULL)
5888 dns_name_free(
5889 newnames[i],
5890 mctx);
5891 isc_mem_put(mctx, newaddrs,
5892 count * sizeof(*newaddrs));
5893 isc_mem_put(mctx, newdscp,
5894 count * sizeof(*newdscp));
5895 isc_mem_put(mctx, newnames,
5896 count * sizeof(*newnames));
5897 return (ISC_R_NOMEMORY);
5898 }
5899 }
5900 }
5901 } else
5902 newnames = NULL;
5903
5904 *newdscpp = newdscp;
5905 *newaddrsp = newaddrs;
5906 *newnamesp = newnames;
5907 return (ISC_R_SUCCESS);
5908 }
5909
5910 isc_result_t
5911 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5912 REQUIRE(DNS_ZONE_VALID(zone));
5913
5914 LOCK_ZONE(zone);
5915 zone->notifysrc6dscp = dscp;
5916 UNLOCK_ZONE(zone);
5917
5918 return (ISC_R_SUCCESS);
5919 }
5920
5921 isc_dscp_t
5922 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
5923 REQUIRE(DNS_ZONE_VALID(zone));
5924 return (zone->notifysrc6dscp);
5925 }
5926
5927 isc_result_t
5928 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5929 uint32_t count)
5930 {
5931 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
5932 count));
5933 }
5934
5935 isc_result_t
5936 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5937 dns_name_t **keynames, uint32_t count)
5938 {
5939 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
5940 count));
5941 }
5942
5943 isc_result_t
5944 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5945 const isc_dscp_t *dscps, dns_name_t **keynames,
5946 uint32_t count)
5947 {
5948 isc_result_t result;
5949 isc_sockaddr_t *newaddrs = NULL;
5950 isc_dscp_t *newdscps = NULL;
5951 dns_name_t **newnames = NULL;
5952
5953 REQUIRE(DNS_ZONE_VALID(zone));
5954 REQUIRE(count == 0 || notify != NULL);
5955 if (keynames != NULL)
5956 REQUIRE(count != 0);
5957
5958 LOCK_ZONE(zone);
5959
5960 if (count == zone->notifycnt &&
5961 same_addrs(zone->notify, notify, count) &&
5962 same_keynames(zone->notifykeynames, keynames, count))
5963 goto unlock;
5964
5965 clear_addresskeylist(&zone->notify, &zone->notifydscp,
5966 &zone->notifykeynames, &zone->notifycnt,
5967 zone->mctx);
5968
5969 if (count == 0)
5970 goto unlock;
5971
5972 /*
5973 * Set up the notify and notifykey lists
5974 */
5975 result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
5976 keynames, &newnames, zone->mctx);
5977 if (result != ISC_R_SUCCESS)
5978 goto unlock;
5979
5980 /*
5981 * Everything is ok so attach to the zone.
5982 */
5983 zone->notify = newaddrs;
5984 zone->notifydscp = newdscps;
5985 zone->notifykeynames = newnames;
5986 zone->notifycnt = count;
5987 unlock:
5988 UNLOCK_ZONE(zone);
5989 return (ISC_R_SUCCESS);
5990 }
5991
5992 isc_result_t
5993 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
5994 uint32_t count)
5995 {
5996 isc_result_t result;
5997
5998 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
5999 return (result);
6000 }
6001
6002 isc_result_t
6003 dns_zone_setmasterswithkeys(dns_zone_t *zone,
6004 const isc_sockaddr_t *masters,
6005 dns_name_t **keynames,
6006 uint32_t count)
6007 {
6008 isc_result_t result = ISC_R_SUCCESS;
6009 isc_sockaddr_t *newaddrs = NULL;
6010 isc_dscp_t *newdscps = NULL;
6011 dns_name_t **newnames = NULL;
6012 bool *newok;
6013 unsigned int i;
6014
6015 REQUIRE(DNS_ZONE_VALID(zone));
6016 REQUIRE(count == 0 || masters != NULL);
6017 if (keynames != NULL) {
6018 REQUIRE(count != 0);
6019 }
6020
6021 LOCK_ZONE(zone);
6022 /*
6023 * The refresh code assumes that 'masters' wouldn't change under it.
6024 * If it will change then kill off any current refresh in progress
6025 * and update the masters info. If it won't change then we can just
6026 * unlock and exit.
6027 */
6028 if (count != zone->masterscnt ||
6029 !same_addrs(zone->masters, masters, count) ||
6030 !same_keynames(zone->masterkeynames, keynames, count)) {
6031 if (zone->request != NULL)
6032 dns_request_cancel(zone->request);
6033 } else
6034 goto unlock;
6035
6036 /*
6037 * This needs to happen before clear_addresskeylist() sets
6038 * zone->masterscnt to 0:
6039 */
6040 if (zone->mastersok != NULL) {
6041 isc_mem_put(zone->mctx, zone->mastersok,
6042 zone->masterscnt * sizeof(bool));
6043 zone->mastersok = NULL;
6044 }
6045 clear_addresskeylist(&zone->masters, &zone->masterdscps,
6046 &zone->masterkeynames, &zone->masterscnt,
6047 zone->mctx);
6048 /*
6049 * If count == 0, don't allocate any space for masters, mastersok or
6050 * keynames so internally, those pointers are NULL if count == 0
6051 */
6052 if (count == 0)
6053 goto unlock;
6054
6055 /*
6056 * mastersok must contain count elements
6057 */
6058 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6059 if (newok == NULL) {
6060 result = ISC_R_NOMEMORY;
6061 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
6062 goto unlock;
6063 };
6064 for (i = 0; i < count; i++)
6065 newok[i] = false;
6066
6067 /*
6068 * Now set up the masters and masterkey lists
6069 */
6070 result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
6071 keynames, &newnames, zone->mctx);
6072 INSIST(newdscps == NULL);
6073 if (result != ISC_R_SUCCESS) {
6074 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6075 goto unlock;
6076 }
6077
6078 /*
6079 * Everything is ok so attach to the zone.
6080 */
6081 zone->curmaster = 0;
6082 zone->mastersok = newok;
6083 zone->masters = newaddrs;
6084 zone->masterdscps = newdscps;
6085 zone->masterkeynames = newnames;
6086 zone->masterscnt = count;
6087 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6088
6089 unlock:
6090 UNLOCK_ZONE(zone);
6091 return (result);
6092 }
6093
6094 isc_result_t
6095 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6096 isc_result_t result = ISC_R_SUCCESS;
6097
6098 REQUIRE(DNS_ZONE_VALID(zone));
6099
6100 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6101 if (zone->db == NULL)
6102 result = DNS_R_NOTLOADED;
6103 else
6104 dns_db_attach(zone->db, dpb);
6105 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6106
6107 return (result);
6108 }
6109
6110 void
6111 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6112 REQUIRE(DNS_ZONE_VALID(zone));
6113 REQUIRE(zone->type == dns_zone_staticstub);
6114
6115 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6116 REQUIRE(zone->db == NULL);
6117 dns_db_attach(db, &zone->db);
6118 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6119 }
6120
6121 /*
6122 * Co-ordinates the starting of routine jobs.
6123 */
6124 void
6125 dns_zone_maintenance(dns_zone_t *zone) {
6126 const char me[] = "dns_zone_maintenance";
6127 isc_time_t now;
6128
6129 REQUIRE(DNS_ZONE_VALID(zone));
6130 ENTER;
6131
6132 LOCK_ZONE(zone);
6133 TIME_NOW(&now);
6134 zone_settimer(zone, &now);
6135 UNLOCK_ZONE(zone);
6136 }
6137
6138 static inline bool
6139 was_dumping(dns_zone_t *zone) {
6140 bool dumping;
6141
6142 REQUIRE(LOCKED_ZONE(zone));
6143
6144 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
6145 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6146 if (!dumping) {
6147 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6148 isc_time_settoepoch(&zone->dumptime);
6149 }
6150 return (dumping);
6151 }
6152
6153 /*%
6154 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6155 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6156 * Only load the public part of a given key if it is not active at timestamp
6157 * 'now'. Store the number of keys found in 'nkeys'.
6158 */
6159 isc_result_t
6160 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6161 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6162 dst_key_t **keys, unsigned int *nkeys)
6163 {
6164 isc_result_t result;
6165 dns_dbnode_t *node = NULL;
6166 const char *directory = dns_zone_getkeydirectory(zone);
6167
6168 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6169 memset(keys, 0, sizeof(*keys) * maxkeys);
6170 result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6171 directory, now, mctx, maxkeys, keys,
6172 nkeys);
6173 if (result == ISC_R_NOTFOUND)
6174 result = ISC_R_SUCCESS;
6175 failure:
6176 if (node != NULL)
6177 dns_db_detachnode(db, &node);
6178 return (result);
6179 }
6180
6181 static isc_result_t
6182 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6183 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
6184 {
6185 isc_result_t result;
6186
6187 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
6188 return (ISC_R_SUCCESS);
6189 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6190 name, ttl, rdata);
6191 if (result != ISC_R_SUCCESS)
6192 return (result);
6193 rdata->flags |= DNS_RDATA_OFFLINE;
6194 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6195 name, ttl, rdata);
6196 zonediff->offline = true;
6197 return (result);
6198 }
6199
6200 static void
6201 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
6202 {
6203 unsigned int delta;
6204 char timebuf[80];
6205
6206 zone->key_expiry = when;
6207 if (when <= now) {
6208 dns_zone_log(zone, ISC_LOG_ERROR,
6209 "DNSKEY RRSIG(s) have expired");
6210 isc_time_settoepoch(&zone->keywarntime);
6211 } else if (when < now + 7 * 24 * 3600) {
6212 isc_time_t t;
6213 isc_time_set(&t, when, 0);
6214 isc_time_formattimestamp(&t, timebuf, 80);
6215 dns_zone_log(zone, ISC_LOG_WARNING,
6216 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6217 timebuf);
6218 delta = when - now;
6219 delta--; /* loop prevention */
6220 delta /= 24 * 3600; /* to whole days */
6221 delta *= 24 * 3600; /* to seconds */
6222 isc_time_set(&zone->keywarntime, when - delta, 0);
6223 } else {
6224 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6225 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6226 dns_zone_log(zone, ISC_LOG_NOTICE,
6227 "setting keywarntime to %s", timebuf);
6228 }
6229 }
6230
6231 /*
6232 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6233 * have no new key.
6234 */
6235 static bool
6236 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6237 bool *warn)
6238 {
6239 unsigned int i = 0;
6240 bool have_ksk = false, have_zsk = false;
6241 bool have_pksk = false, have_pzsk = false;
6242
6243 for (i = 0; i < nkeys; i++) {
6244 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
6245 continue;
6246 if (dst_key_isprivate(keys[i])) {
6247 if (KSK(keys[i]))
6248 have_ksk = have_pksk = true;
6249 else
6250 have_zsk = have_pzsk = true;
6251 } else {
6252 if (KSK(keys[i]))
6253 have_ksk = true;
6254 else
6255 have_zsk = true;
6256 }
6257 }
6258
6259 if (have_zsk && have_ksk && !have_pzsk)
6260 *warn = true;
6261
6262 /*
6263 * It's okay to delete a signature if there is an active key
6264 * with the same algorithm to replace it.
6265 */
6266 if (have_pksk || have_pzsk)
6267 return (true);
6268
6269 /*
6270 * Failing that, it is *not* okay to delete a signature
6271 * if the associated public key is still in the DNSKEY RRset
6272 */
6273 for (i = 0; i < nkeys; i++) {
6274 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6275 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6276 return (false);
6277 }
6278
6279 /*
6280 * But if the key is gone, then go ahead.
6281 */
6282 return (true);
6283 }
6284
6285 /*
6286 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6287 * See also update.c:del_keysigs().
6288 */
6289 static isc_result_t
6290 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6291 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6292 unsigned int nkeys, isc_stdtime_t now, bool incremental)
6293 {
6294 isc_result_t result;
6295 dns_dbnode_t *node = NULL;
6296 dns_rdataset_t rdataset;
6297 unsigned int i;
6298 dns_rdata_rrsig_t rrsig;
6299 bool found;
6300 int64_t timewarn = 0, timemaybe = 0;
6301
6302 dns_rdataset_init(&rdataset);
6303
6304 if (type == dns_rdatatype_nsec3)
6305 result = dns_db_findnsec3node(db, name, false, &node);
6306 else
6307 result = dns_db_findnode(db, name, false, &node);
6308 if (result == ISC_R_NOTFOUND)
6309 return (ISC_R_SUCCESS);
6310 if (result != ISC_R_SUCCESS)
6311 goto failure;
6312 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6313 (isc_stdtime_t) 0, &rdataset, NULL);
6314 dns_db_detachnode(db, &node);
6315
6316 if (result == ISC_R_NOTFOUND) {
6317 INSIST(!dns_rdataset_isassociated(&rdataset));
6318 return (ISC_R_SUCCESS);
6319 }
6320 if (result != ISC_R_SUCCESS) {
6321 INSIST(!dns_rdataset_isassociated(&rdataset));
6322 goto failure;
6323 }
6324
6325 for (result = dns_rdataset_first(&rdataset);
6326 result == ISC_R_SUCCESS;
6327 result = dns_rdataset_next(&rdataset)) {
6328 dns_rdata_t rdata = DNS_RDATA_INIT;
6329
6330 dns_rdataset_current(&rdataset, &rdata);
6331 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6332 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6333
6334 if (type != dns_rdatatype_dnskey) {
6335 bool warn = false, deleted = false;
6336 if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
6337 result = update_one_rr(db, ver, zonediff->diff,
6338 DNS_DIFFOP_DELRESIGN, name,
6339 rdataset.ttl, &rdata);
6340 if (result != ISC_R_SUCCESS)
6341 break;
6342 deleted = true;
6343 }
6344 if (warn) {
6345 /*
6346 * At this point, we've got an RRSIG,
6347 * which is signed by an inactive key.
6348 * An administrator needs to provide a new
6349 * key/alg, but until that time, we want to
6350 * keep the old RRSIG. Marking the key as
6351 * offline will prevent us spinning waiting
6352 * for the private part.
6353 */
6354 if (incremental && !deleted) {
6355 result = offline(db, ver, zonediff,
6356 name, rdataset.ttl,
6357 &rdata);
6358 if (result != ISC_R_SUCCESS)
6359 break;
6360 }
6361
6362 /*
6363 * Log the key id and algorithm of
6364 * the inactive key with no replacement
6365 */
6366 if (zone->log_key_expired_timer <= now) {
6367 char origin[DNS_NAME_FORMATSIZE];
6368 char algbuf[DNS_NAME_FORMATSIZE];
6369 dns_name_format(&zone->origin, origin,
6370 sizeof(origin));
6371 dns_secalg_format(rrsig.algorithm,
6372 algbuf,
6373 sizeof(algbuf));
6374 dns_zone_log(zone, ISC_LOG_WARNING,
6375 "Key %s/%s/%d "
6376 "missing or inactive "
6377 "and has no replacement: "
6378 "retaining signatures.",
6379 origin, algbuf,
6380 rrsig.keyid);
6381 zone->log_key_expired_timer = now +
6382 3600;
6383 }
6384 }
6385 continue;
6386 }
6387
6388 /*
6389 * RRSIG(DNSKEY) requires special processing.
6390 */
6391 found = false;
6392 for (i = 0; i < nkeys; i++) {
6393 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6394 rrsig.keyid == dst_key_id(keys[i])) {
6395 found = true;
6396 /*
6397 * Mark offline RRSIG(DNSKEY).
6398 * We want the earliest offline expire time
6399 * iff there is a new offline signature.
6400 */
6401 if (!dst_key_inactive(keys[i]) &&
6402 !dst_key_isprivate(keys[i]))
6403 {
6404 int64_t timeexpire =
6405 dns_time64_from32(rrsig.timeexpire);
6406 if (timewarn != 0 &&
6407 timewarn > timeexpire)
6408 timewarn = timeexpire;
6409 if (rdata.flags & DNS_RDATA_OFFLINE) {
6410 if (timemaybe == 0 ||
6411 timemaybe > timeexpire)
6412 timemaybe = timeexpire;
6413 break;
6414 }
6415 if (timewarn == 0)
6416 timewarn = timemaybe;
6417 if (timewarn == 0 ||
6418 timewarn > timeexpire)
6419 timewarn = timeexpire;
6420 result = offline(db, ver, zonediff,
6421 name, rdataset.ttl,
6422 &rdata);
6423 break;
6424 }
6425 result = update_one_rr(db, ver, zonediff->diff,
6426 DNS_DIFFOP_DELRESIGN,
6427 name, rdataset.ttl,
6428 &rdata);
6429 break;
6430 }
6431 }
6432
6433 /*
6434 * If there is not a matching DNSKEY then
6435 * delete the RRSIG.
6436 */
6437 if (!found)
6438 result = update_one_rr(db, ver, zonediff->diff,
6439 DNS_DIFFOP_DELRESIGN, name,
6440 rdataset.ttl, &rdata);
6441 if (result != ISC_R_SUCCESS)
6442 break;
6443 }
6444
6445 dns_rdataset_disassociate(&rdataset);
6446 if (result == ISC_R_NOMORE)
6447 result = ISC_R_SUCCESS;
6448 if (timewarn > 0) {
6449 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6450 if (timewarn == stdwarn) {
6451 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6452 now);
6453 } else {
6454 dns_zone_log(zone, ISC_LOG_ERROR,
6455 "key expiry warning time out of range");
6456 }
6457 }
6458 failure:
6459 if (node != NULL)
6460 dns_db_detachnode(db, &node);
6461 return (result);
6462 }
6463
6464 static isc_result_t
6465 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6466 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6467 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
6468 isc_stdtime_t expire, bool check_ksk,
6469 bool keyset_kskonly)
6470 {
6471 isc_result_t result;
6472 dns_dbnode_t *node = NULL;
6473 dns_rdataset_t rdataset;
6474 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6475 unsigned char data[1024]; /* XXX */
6476 isc_buffer_t buffer;
6477 unsigned int i, j;
6478
6479 dns_rdataset_init(&rdataset);
6480 isc_buffer_init(&buffer, data, sizeof(data));
6481
6482 if (type == dns_rdatatype_nsec3)
6483 result = dns_db_findnsec3node(db, name, false, &node);
6484 else
6485 result = dns_db_findnode(db, name, false, &node);
6486 if (result == ISC_R_NOTFOUND)
6487 return (ISC_R_SUCCESS);
6488 if (result != ISC_R_SUCCESS)
6489 goto failure;
6490 result = dns_db_findrdataset(db, node, ver, type, 0,
6491 (isc_stdtime_t) 0, &rdataset, NULL);
6492 dns_db_detachnode(db, &node);
6493 if (result == ISC_R_NOTFOUND) {
6494 INSIST(!dns_rdataset_isassociated(&rdataset));
6495 return (ISC_R_SUCCESS);
6496 }
6497 if (result != ISC_R_SUCCESS) {
6498 INSIST(!dns_rdataset_isassociated(&rdataset));
6499 goto failure;
6500 }
6501
6502 for (i = 0; i < nkeys; i++) {
6503 bool both = false;
6504
6505 if (!dst_key_isprivate(keys[i]))
6506 continue;
6507 if (dst_key_inactive(keys[i])) /* Should be redundant. */
6508 continue;
6509
6510 if (check_ksk && !REVOKE(keys[i])) {
6511 bool have_ksk, have_nonksk;
6512 if (KSK(keys[i])) {
6513 have_ksk = true;
6514 have_nonksk = false;
6515 } else {
6516 have_ksk = false;
6517 have_nonksk = true;
6518 }
6519 for (j = 0; j < nkeys; j++) {
6520 if (j == i || ALG(keys[i]) != ALG(keys[j]))
6521 continue;
6522 if (!dst_key_isprivate(keys[j]))
6523 continue;
6524 if (dst_key_inactive(keys[j])) /* SBR */
6525 continue;
6526 if (REVOKE(keys[j]))
6527 continue;
6528 if (KSK(keys[j]))
6529 have_ksk = true;
6530 else
6531 have_nonksk = true;
6532 both = have_ksk && have_nonksk;
6533 if (both)
6534 break;
6535 }
6536 }
6537 if (both) {
6538 /*
6539 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6540 */
6541 if (type == dns_rdatatype_dnskey ||
6542 type == dns_rdatatype_cdnskey ||
6543 type == dns_rdatatype_cds)
6544 {
6545 if (!KSK(keys[i]) && keyset_kskonly)
6546 continue;
6547 } else if (KSK(keys[i])) {
6548 continue;
6549 }
6550 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
6551 continue;
6552 }
6553
6554 /* Calculate the signature, creating a RRSIG RDATA. */
6555 isc_buffer_clear(&buffer);
6556 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
6557 &inception, &expire,
6558 mctx, &buffer, &sig_rdata));
6559 /* Update the database and journal with the RRSIG. */
6560 /* XXX inefficient - will cause dataset merging */
6561 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
6562 name, rdataset.ttl, &sig_rdata));
6563 dns_rdata_reset(&sig_rdata);
6564 isc_buffer_init(&buffer, data, sizeof(data));
6565 }
6566
6567 failure:
6568 if (dns_rdataset_isassociated(&rdataset))
6569 dns_rdataset_disassociate(&rdataset);
6570 if (node != NULL)
6571 dns_db_detachnode(db, &node);
6572 return (result);
6573 }
6574
6575 static void
6576 zone_resigninc(dns_zone_t *zone) {
6577 const char *me = "zone_resigninc";
6578 dns_db_t *db = NULL;
6579 dns_dbversion_t *version = NULL;
6580 dns_diff_t _sig_diff;
6581 dns__zonediff_t zonediff;
6582 dns_fixedname_t fixed;
6583 dns_name_t *name;
6584 dns_rdataset_t rdataset;
6585 dns_rdatatype_t covers;
6586 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6587 bool check_ksk, keyset_kskonly = false;
6588 isc_result_t result;
6589 isc_stdtime_t now, inception, soaexpire, expire, stop;
6590 uint32_t jitter, sigvalidityinterval;
6591 unsigned int i;
6592 unsigned int nkeys = 0;
6593 unsigned int resign;
6594
6595 ENTER;
6596
6597 dns_rdataset_init(&rdataset);
6598 dns_diff_init(zone->mctx, &_sig_diff);
6599 zonediff_init(&zonediff, &_sig_diff);
6600
6601 /*
6602 * Zone is frozen or automatic resigning is disabled.
6603 * Pause for 5 minutes.
6604 */
6605 if (zone->update_disabled ||
6606 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
6607 {
6608 result = ISC_R_FAILURE;
6609 goto failure;
6610 }
6611
6612 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6613 dns_db_attach(zone->db, &db);
6614 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6615
6616 result = dns_db_newversion(db, &version);
6617 if (result != ISC_R_SUCCESS) {
6618 dns_zone_log(zone, ISC_LOG_ERROR,
6619 "zone_resigninc:dns_db_newversion -> %s",
6620 dns_result_totext(result));
6621 goto failure;
6622 }
6623
6624 isc_stdtime_get(&now);
6625
6626 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
6627 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6628 if (result != ISC_R_SUCCESS) {
6629 dns_zone_log(zone, ISC_LOG_ERROR,
6630 "zone_resigninc:dns__zone_findkeys -> %s",
6631 dns_result_totext(result));
6632 goto failure;
6633 }
6634
6635 sigvalidityinterval = zone->sigvalidityinterval;
6636 inception = now - 3600; /* Allow for clock skew. */
6637 soaexpire = now + sigvalidityinterval;
6638 /*
6639 * Spread out signatures over time if they happen to be
6640 * clumped. We don't do this for each add_sigs() call as
6641 * we still want some clustering to occur.
6642 */
6643 if (sigvalidityinterval >= 3600U) {
6644 if (sigvalidityinterval > 7200U) {
6645 jitter = isc_random_uniform(3600);
6646 } else {
6647 jitter = isc_random_uniform(1200);
6648 }
6649 expire = soaexpire - jitter - 1;
6650 } else {
6651 expire = soaexpire - 1;
6652 }
6653 stop = now + 5;
6654
6655 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6656 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6657
6658 name = dns_fixedname_initname(&fixed);
6659 result = dns_db_getsigningtime(db, &rdataset, name);
6660 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6661 dns_zone_log(zone, ISC_LOG_ERROR,
6662 "zone_resigninc:dns_db_getsigningtime -> %s",
6663 dns_result_totext(result));
6664 }
6665
6666 i = 0;
6667 while (result == ISC_R_SUCCESS) {
6668 resign = rdataset.resign - zone->sigresigninginterval;
6669 covers = rdataset.covers;
6670 dns_rdataset_disassociate(&rdataset);
6671
6672 /*
6673 * Stop if we hit the SOA as that means we have walked the
6674 * entire zone. The SOA record should always be the most
6675 * recent signature.
6676 */
6677 /* XXXMPA increase number of RRsets signed pre call */
6678 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
6679 resign > stop)
6680 break;
6681
6682 result = del_sigs(zone, db, version, name, covers, &zonediff,
6683 zone_keys, nkeys, now, true);
6684 if (result != ISC_R_SUCCESS) {
6685 dns_zone_log(zone, ISC_LOG_ERROR,
6686 "zone_resigninc:del_sigs -> %s",
6687 dns_result_totext(result));
6688 break;
6689 }
6690
6691 result = add_sigs(db, version, name, covers, zonediff.diff,
6692 zone_keys, nkeys, zone->mctx, inception,
6693 expire, check_ksk, keyset_kskonly);
6694 if (result != ISC_R_SUCCESS) {
6695 dns_zone_log(zone, ISC_LOG_ERROR,
6696 "zone_resigninc:add_sigs -> %s",
6697 dns_result_totext(result));
6698 break;
6699 }
6700 result = dns_db_getsigningtime(db, &rdataset, name);
6701 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
6702 result = ISC_R_SUCCESS;
6703 break;
6704 }
6705 if (result != ISC_R_SUCCESS)
6706 dns_zone_log(zone, ISC_LOG_ERROR,
6707 "zone_resigninc:dns_db_getsigningtime -> %s",
6708 dns_result_totext(result));
6709 }
6710
6711 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
6712 goto failure;
6713
6714 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6715 &zonediff, zone_keys, nkeys, now, true);
6716 if (result != ISC_R_SUCCESS) {
6717 dns_zone_log(zone, ISC_LOG_ERROR,
6718 "zone_resigninc:del_sigs -> %s",
6719 dns_result_totext(result));
6720 goto failure;
6721 }
6722
6723 /*
6724 * Did we change anything in the zone?
6725 */
6726 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
6727 /*
6728 * Commit the changes if any key has been marked as offline.
6729 */
6730 if (zonediff.offline)
6731 dns_db_closeversion(db, &version, true);
6732 goto failure;
6733 }
6734
6735 /* Increment SOA serial if we have made changes */
6736 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
6737 zone->updatemethod);
6738 if (result != ISC_R_SUCCESS) {
6739 dns_zone_log(zone, ISC_LOG_ERROR,
6740 "zone_resigninc:update_soa_serial -> %s",
6741 dns_result_totext(result));
6742 goto failure;
6743 }
6744
6745 /*
6746 * Generate maximum life time signatures so that the above loop
6747 * termination is sensible.
6748 */
6749 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6750 zonediff.diff, zone_keys, nkeys, zone->mctx,
6751 inception, soaexpire, check_ksk, keyset_kskonly);
6752 if (result != ISC_R_SUCCESS) {
6753 dns_zone_log(zone, ISC_LOG_ERROR,
6754 "zone_resigninc:add_sigs -> %s",
6755 dns_result_totext(result));
6756 goto failure;
6757 }
6758
6759 /* Write changes to journal file. */
6760 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
6761
6762 /* Everything has succeeded. Commit the changes. */
6763 dns_db_closeversion(db, &version, true);
6764
6765 failure:
6766 dns_diff_clear(&_sig_diff);
6767 for (i = 0; i < nkeys; i++)
6768 dst_key_free(&zone_keys[i]);
6769 if (version != NULL) {
6770 dns_db_closeversion(db, &version, false);
6771 dns_db_detach(&db);
6772 } else if (db != NULL)
6773 dns_db_detach(&db);
6774 if (result == ISC_R_SUCCESS) {
6775 set_resigntime(zone);
6776 LOCK_ZONE(zone);
6777 zone_needdump(zone, DNS_DUMP_DELAY);
6778 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6779 UNLOCK_ZONE(zone);
6780 } else {
6781 /*
6782 * Something failed. Retry in 5 minutes.
6783 */
6784 isc_interval_t ival;
6785 isc_interval_set(&ival, 300, 0);
6786 isc_time_nowplusinterval(&zone->resigntime, &ival);
6787 }
6788
6789 INSIST(version == NULL);
6790 }
6791
6792 static isc_result_t
6793 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
6794 dns_name_t *newname, bool bottom)
6795 {
6796 isc_result_t result;
6797 dns_dbiterator_t *dbit = NULL;
6798 dns_rdatasetiter_t *rdsit = NULL;
6799 dns_dbnode_t *node = NULL;
6800
6801 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
6802 CHECK(dns_dbiterator_seek(dbit, oldname));
6803 do {
6804 result = dns_dbiterator_next(dbit);
6805 if (result == ISC_R_NOMORE)
6806 CHECK(dns_dbiterator_first(dbit));
6807 CHECK(dns_dbiterator_current(dbit, &node, newname));
6808 if (bottom && dns_name_issubdomain(newname, oldname) &&
6809 !dns_name_equal(newname, oldname)) {
6810 dns_db_detachnode(db, &node);
6811 continue;
6812 }
6813 /*
6814 * Is this node empty?
6815 */
6816 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
6817 result = dns_rdatasetiter_first(rdsit);
6818 dns_db_detachnode(db, &node);
6819 dns_rdatasetiter_destroy(&rdsit);
6820 if (result != ISC_R_NOMORE)
6821 break;
6822 } while (1);
6823 failure:
6824 if (node != NULL)
6825 dns_db_detachnode(db, &node);
6826 if (dbit != NULL)
6827 dns_dbiterator_destroy(&dbit);
6828 return (result);
6829 }
6830
6831 static bool
6832 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
6833 dns_rdatatype_t type, dst_key_t *key)
6834 {
6835 isc_result_t result;
6836 dns_rdataset_t rdataset;
6837 dns_rdata_t rdata = DNS_RDATA_INIT;
6838 dns_rdata_rrsig_t rrsig;
6839
6840 dns_rdataset_init(&rdataset);
6841 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
6842 type, 0, &rdataset, NULL);
6843 if (result != ISC_R_SUCCESS) {
6844 INSIST(!dns_rdataset_isassociated(&rdataset));
6845 return (false);
6846 }
6847 for (result = dns_rdataset_first(&rdataset);
6848 result == ISC_R_SUCCESS;
6849 result = dns_rdataset_next(&rdataset)) {
6850 dns_rdataset_current(&rdataset, &rdata);
6851 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6852 INSIST(result == ISC_R_SUCCESS);
6853 if (rrsig.algorithm == dst_key_alg(key) &&
6854 rrsig.keyid == dst_key_id(key)) {
6855 dns_rdataset_disassociate(&rdataset);
6856 return (true);
6857 }
6858 dns_rdata_reset(&rdata);
6859 }
6860 dns_rdataset_disassociate(&rdataset);
6861 return (false);
6862 }
6863
6864 static isc_result_t
6865 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6866 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom,
6867 dns_diff_t *diff)
6868 {
6869 dns_fixedname_t fixed;
6870 dns_name_t *next;
6871 dns_rdata_t rdata = DNS_RDATA_INIT;
6872 isc_result_t result;
6873 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
6874
6875 next = dns_fixedname_initname(&fixed);
6876
6877 CHECK(next_active(db, version, name, next, bottom));
6878 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
6879 &rdata));
6880 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
6881 &rdata));
6882 failure:
6883 return (result);
6884 }
6885
6886 static isc_result_t
6887 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
6888 dns_dbversion_t *version, bool *is_bottom_of_zone)
6889 {
6890 isc_result_t result;
6891 dns_rdatasetiter_t *iterator = NULL;
6892 dns_rdataset_t rdataset;
6893 bool seen_soa = false, seen_ns = false, seen_dname = false;
6894
6895 REQUIRE(is_bottom_of_zone != NULL);
6896
6897 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6898 if (result != ISC_R_SUCCESS) {
6899 if (result == ISC_R_NOTFOUND) {
6900 result = ISC_R_SUCCESS;
6901 }
6902 return (result);
6903 }
6904
6905 dns_rdataset_init(&rdataset);
6906 for (result = dns_rdatasetiter_first(iterator);
6907 result == ISC_R_SUCCESS;
6908 result = dns_rdatasetiter_next(iterator)) {
6909 dns_rdatasetiter_current(iterator, &rdataset);
6910 switch (rdataset.type) {
6911 case dns_rdatatype_soa:
6912 seen_soa = true;
6913 break;
6914 case dns_rdatatype_ns:
6915 seen_ns = true;
6916 break;
6917 case dns_rdatatype_dname:
6918 seen_dname = true;
6919 break;
6920 }
6921 dns_rdataset_disassociate(&rdataset);
6922 }
6923 if (result != ISC_R_NOMORE) {
6924 goto failure;
6925 }
6926 if ((seen_ns && !seen_soa) || seen_dname) {
6927 *is_bottom_of_zone = true;
6928 }
6929 result = ISC_R_SUCCESS;
6930
6931 failure:
6932 dns_rdatasetiter_destroy(&iterator);
6933
6934 return (result);
6935 }
6936
6937 static isc_result_t
6938 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
6939 dns_dbversion_t *version, bool build_nsec3,
6940 bool build_nsec, dst_key_t *key,
6941 isc_stdtime_t inception, isc_stdtime_t expire,
6942 unsigned int minimum, bool is_ksk,
6943 bool keyset_kskonly, bool is_bottom_of_zone,
6944 dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx)
6945 {
6946 isc_result_t result;
6947 dns_rdatasetiter_t *iterator = NULL;
6948 dns_rdataset_t rdataset;
6949 dns_rdata_t rdata = DNS_RDATA_INIT;
6950 isc_buffer_t buffer;
6951 unsigned char data[1024];
6952 bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
6953
6954 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6955 if (result != ISC_R_SUCCESS) {
6956 if (result == ISC_R_NOTFOUND)
6957 result = ISC_R_SUCCESS;
6958 return (result);
6959 }
6960
6961 dns_rdataset_init(&rdataset);
6962 isc_buffer_init(&buffer, data, sizeof(data));
6963 seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
6964 for (result = dns_rdatasetiter_first(iterator);
6965 result == ISC_R_SUCCESS;
6966 result = dns_rdatasetiter_next(iterator)) {
6967 dns_rdatasetiter_current(iterator, &rdataset);
6968 if (rdataset.type == dns_rdatatype_soa)
6969 seen_soa = true;
6970 else if (rdataset.type == dns_rdatatype_ns)
6971 seen_ns = true;
6972 else if (rdataset.type == dns_rdatatype_ds)
6973 seen_ds = true;
6974 else if (rdataset.type == dns_rdatatype_nsec)
6975 seen_nsec = true;
6976 else if (rdataset.type == dns_rdatatype_nsec3)
6977 seen_nsec3 = true;
6978 if (rdataset.type != dns_rdatatype_rrsig)
6979 seen_rr = true;
6980 dns_rdataset_disassociate(&rdataset);
6981 }
6982 if (result != ISC_R_NOMORE)
6983 goto failure;
6984 /*
6985 * Going from insecure to NSEC3.
6986 * Don't generate NSEC3 records for NSEC3 records.
6987 */
6988 if (build_nsec3 && !seen_nsec3 && seen_rr) {
6989 bool unsecure = !seen_ds && seen_ns && !seen_soa;
6990 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
6991 unsecure, diff));
6992 (*signatures)--;
6993 }
6994 /*
6995 * Going from insecure to NSEC.
6996 * Don't generate NSEC records for NSEC3 records.
6997 */
6998 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
6999 /*
7000 * Build a NSEC record except at the origin.
7001 */
7002 if (!dns_name_equal(name, dns_db_origin(db))) {
7003 CHECK(add_nsec(db, version, name, node, minimum,
7004 is_bottom_of_zone, diff));
7005 /* Count a NSEC generation as a signature generation. */
7006 (*signatures)--;
7007 }
7008 }
7009 result = dns_rdatasetiter_first(iterator);
7010 while (result == ISC_R_SUCCESS) {
7011 dns_rdatasetiter_current(iterator, &rdataset);
7012 if (rdataset.type == dns_rdatatype_soa ||
7013 rdataset.type == dns_rdatatype_rrsig)
7014 {
7015 goto next_rdataset;
7016 }
7017 if (rdataset.type == dns_rdatatype_dnskey ||
7018 rdataset.type == dns_rdatatype_cdnskey ||
7019 rdataset.type == dns_rdatatype_cds)
7020 {
7021 /*
7022 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7023 * (RFC 7344, section 4.1 specifies that they must
7024 * be signed with a key in the current DS RRset,
7025 * which would only include KSK's.)
7026 */
7027 if (!is_ksk && keyset_kskonly) {
7028 goto next_rdataset;
7029 }
7030 } else if (is_ksk) {
7031 goto next_rdataset;
7032 }
7033 if (seen_ns && !seen_soa &&
7034 rdataset.type != dns_rdatatype_ds &&
7035 rdataset.type != dns_rdatatype_nsec)
7036 {
7037 goto next_rdataset;
7038 }
7039 if (signed_with_key(db, node, version, rdataset.type, key)) {
7040 goto next_rdataset;
7041 }
7042 /* Calculate the signature, creating a RRSIG RDATA. */
7043 isc_buffer_clear(&buffer);
7044 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
7045 &expire, mctx, &buffer, &rdata));
7046 /* Update the database and journal with the RRSIG. */
7047 /* XXX inefficient - will cause dataset merging */
7048 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7049 name, rdataset.ttl, &rdata));
7050 dns_rdata_reset(&rdata);
7051 (*signatures)--;
7052 next_rdataset:
7053 dns_rdataset_disassociate(&rdataset);
7054 result = dns_rdatasetiter_next(iterator);
7055 }
7056 if (result == ISC_R_NOMORE)
7057 result = ISC_R_SUCCESS;
7058 failure:
7059 if (dns_rdataset_isassociated(&rdataset))
7060 dns_rdataset_disassociate(&rdataset);
7061 if (iterator != NULL)
7062 dns_rdatasetiter_destroy(&iterator);
7063 return (result);
7064 }
7065
7066 /*
7067 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7068 */
7069 static isc_result_t
7070 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7071 dns_ttl_t minimum, bool update_only, dns_diff_t *diff)
7072 {
7073 isc_result_t result;
7074 dns_rdataset_t rdataset;
7075 dns_dbnode_t *node = NULL;
7076
7077 CHECK(dns_db_getoriginnode(db, &node));
7078 if (update_only) {
7079 dns_rdataset_init(&rdataset);
7080 result = dns_db_findrdataset(db, node, version,
7081 dns_rdatatype_nsec,
7082 dns_rdatatype_none,
7083 0, &rdataset, NULL);
7084 if (dns_rdataset_isassociated(&rdataset))
7085 dns_rdataset_disassociate(&rdataset);
7086 if (result == ISC_R_NOTFOUND)
7087 goto success;
7088 if (result != ISC_R_SUCCESS)
7089 goto failure;
7090 }
7091 CHECK(delete_nsec(db, version, node, name, diff));
7092 CHECK(add_nsec(db, version, name, node, minimum, false, diff));
7093 success:
7094 result = ISC_R_SUCCESS;
7095 failure:
7096 if (node != NULL)
7097 dns_db_detachnode(db, &node);
7098 return (result);
7099 }
7100
7101 static isc_result_t
7102 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7103 dns_dbversion_t *version, bool build_nsec3,
7104 dns_ttl_t minimum, dns_diff_t *diff)
7105 {
7106 isc_result_t result;
7107 dns_dbnode_t *node = NULL;
7108 dns_rdataset_t rdataset;
7109 dns_rdata_t rdata = DNS_RDATA_INIT;
7110 unsigned char data[5];
7111 bool seen_done = false;
7112 bool have_rr = false;
7113
7114 dns_rdataset_init(&rdataset);
7115 result = dns_db_getoriginnode(signing->db, &node);
7116 if (result != ISC_R_SUCCESS)
7117 goto failure;
7118
7119 result = dns_db_findrdataset(signing->db, node, version,
7120 zone->privatetype, dns_rdatatype_none,
7121 0, &rdataset, NULL);
7122 if (result == ISC_R_NOTFOUND) {
7123 INSIST(!dns_rdataset_isassociated(&rdataset));
7124 result = ISC_R_SUCCESS;
7125 goto failure;
7126 }
7127 if (result != ISC_R_SUCCESS) {
7128 INSIST(!dns_rdataset_isassociated(&rdataset));
7129 goto failure;
7130 }
7131 for (result = dns_rdataset_first(&rdataset);
7132 result == ISC_R_SUCCESS;
7133 result = dns_rdataset_next(&rdataset)) {
7134 dns_rdataset_current(&rdataset, &rdata);
7135 /*
7136 * If we don't match the algorithm or keyid skip the record.
7137 */
7138 if (rdata.length != 5 ||
7139 rdata.data[0] != signing->algorithm ||
7140 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7141 rdata.data[2] != (signing->keyid & 0xff)) {
7142 have_rr = true;
7143 dns_rdata_reset(&rdata);
7144 continue;
7145 }
7146 /*
7147 * We have a match. If we were signing (!signing->deleteit)
7148 * and we already have a record indicating that we have
7149 * finished signing (rdata.data[4] != 0) then keep it.
7150 * Otherwise it needs to be deleted as we have removed all
7151 * the signatures (signing->deleteit), so any record indicating
7152 * completion is now out of date, or we have finished signing
7153 * with the new record so we no longer need to remember that
7154 * we need to sign the zone with the matching key across a
7155 * nameserver re-start.
7156 */
7157 if (!signing->deleteit && rdata.data[4] != 0) {
7158 seen_done = true;
7159 have_rr = true;
7160 } else
7161 CHECK(update_one_rr(signing->db, version, diff,
7162 DNS_DIFFOP_DEL, &zone->origin,
7163 rdataset.ttl, &rdata));
7164 dns_rdata_reset(&rdata);
7165 }
7166 if (result == ISC_R_NOMORE)
7167 result = ISC_R_SUCCESS;
7168 if (!signing->deleteit && !seen_done) {
7169 /*
7170 * If we were signing then we need to indicate that we have
7171 * finished signing the zone with this key. If it is already
7172 * there we don't need to add it a second time.
7173 */
7174 data[0] = signing->algorithm;
7175 data[1] = (signing->keyid >> 8) & 0xff;
7176 data[2] = signing->keyid & 0xff;
7177 data[3] = 0;
7178 data[4] = 1;
7179 rdata.length = sizeof(data);
7180 rdata.data = data;
7181 rdata.type = zone->privatetype;
7182 rdata.rdclass = dns_db_class(signing->db);
7183 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7184 &zone->origin, rdataset.ttl, &rdata));
7185 } else if (!have_rr) {
7186 dns_name_t *origin = dns_db_origin(signing->db);
7187 /*
7188 * Rebuild the NSEC/NSEC3 record for the origin as we no
7189 * longer have any private records.
7190 */
7191 if (build_nsec3)
7192 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7193 minimum, false, diff));
7194 CHECK(updatesecure(signing->db, version, origin, minimum,
7195 true, diff));
7196 }
7197
7198 failure:
7199 if (dns_rdataset_isassociated(&rdataset))
7200 dns_rdataset_disassociate(&rdataset);
7201 if (node != NULL)
7202 dns_db_detachnode(signing->db, &node);
7203 return (result);
7204 }
7205
7206 /*
7207 * Called from zone_nsec3chain() in order to update zone records indicating
7208 * processing status of given NSEC3 chain:
7209 *
7210 * - If the supplied dns_nsec3chain_t structure has been fully processed
7211 * (which is indicated by "active" being set to false):
7212 *
7213 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7214 *
7215 * - remove all private-type records containing NSEC3PARAM RDATA matching
7216 * the relevant NSEC3 chain.
7217 *
7218 * - If the supplied dns_nsec3chain_t structure has not been fully processed
7219 * (which is indicated by "active" being set to true), only remove the
7220 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7221 * "flags" field set to 0.
7222 *
7223 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7224 * in the relevant private-type record, but with the "flags" field set to
7225 * 0, indicating that this NSEC3 chain is now complete for this zone.
7226 *
7227 * Note that this function is called at different processing stages for NSEC3
7228 * chain additions vs. removals and needs to handle all cases properly.
7229 */
7230 static isc_result_t
7231 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7232 bool active, dns_rdatatype_t privatetype,
7233 dns_diff_t *diff)
7234 {
7235 dns_dbnode_t *node = NULL;
7236 dns_name_t *name = dns_db_origin(db);
7237 dns_rdata_t rdata = DNS_RDATA_INIT;
7238 dns_rdataset_t rdataset;
7239 dns_rdata_nsec3param_t nsec3param;
7240 isc_result_t result;
7241 isc_buffer_t buffer;
7242 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7243 dns_ttl_t ttl = 0;
7244 bool nseconly = false, nsec3ok = false;
7245
7246 dns_rdataset_init(&rdataset);
7247
7248 result = dns_db_getoriginnode(db, &node);
7249 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7250 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7251 0, 0, &rdataset, NULL);
7252 if (result == ISC_R_NOTFOUND)
7253 goto try_private;
7254 if (result != ISC_R_SUCCESS)
7255 goto failure;
7256
7257 /*
7258 * Preserve the existing ttl.
7259 */
7260 ttl = rdataset.ttl;
7261
7262 /*
7263 * Delete all NSEC3PARAM records which match that in nsec3chain.
7264 */
7265 for (result = dns_rdataset_first(&rdataset);
7266 result == ISC_R_SUCCESS;
7267 result = dns_rdataset_next(&rdataset)) {
7268
7269 dns_rdataset_current(&rdataset, &rdata);
7270 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7271
7272 if (nsec3param.hash != chain->nsec3param.hash ||
7273 (active && nsec3param.flags != 0) ||
7274 nsec3param.iterations != chain->nsec3param.iterations ||
7275 nsec3param.salt_length != chain->nsec3param.salt_length ||
7276 memcmp(nsec3param.salt, chain->nsec3param.salt,
7277 nsec3param.salt_length)) {
7278 dns_rdata_reset(&rdata);
7279 continue;
7280 }
7281
7282 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7283 name, rdataset.ttl, &rdata));
7284 dns_rdata_reset(&rdata);
7285 }
7286 if (result != ISC_R_NOMORE)
7287 goto failure;
7288
7289 dns_rdataset_disassociate(&rdataset);
7290
7291 try_private:
7292
7293 if (active)
7294 goto add;
7295
7296 result = dns_nsec_nseconly(db, ver, &nseconly);
7297 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
7298
7299 /*
7300 * Delete all private records which match that in nsec3chain.
7301 */
7302 result = dns_db_findrdataset(db, node, ver, privatetype,
7303 0, 0, &rdataset, NULL);
7304 if (result == ISC_R_NOTFOUND)
7305 goto add;
7306 if (result != ISC_R_SUCCESS)
7307 goto failure;
7308
7309 for (result = dns_rdataset_first(&rdataset);
7310 result == ISC_R_SUCCESS;
7311 result = dns_rdataset_next(&rdataset)) {
7312 dns_rdata_t private = DNS_RDATA_INIT;
7313 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
7314
7315 dns_rdataset_current(&rdataset, &private);
7316 if (!dns_nsec3param_fromprivate(&private, &rdata,
7317 buf, sizeof(buf)))
7318 continue;
7319 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7320
7321 if ((!nsec3ok &&
7322 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
7323 nsec3param.hash != chain->nsec3param.hash ||
7324 nsec3param.iterations != chain->nsec3param.iterations ||
7325 nsec3param.salt_length != chain->nsec3param.salt_length ||
7326 memcmp(nsec3param.salt, chain->nsec3param.salt,
7327 nsec3param.salt_length)) {
7328 dns_rdata_reset(&rdata);
7329 continue;
7330 }
7331
7332 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7333 name, rdataset.ttl, &private));
7334 dns_rdata_reset(&rdata);
7335 }
7336 if (result != ISC_R_NOMORE)
7337 goto failure;
7338
7339 add:
7340 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
7341 result = ISC_R_SUCCESS;
7342 goto failure;
7343 }
7344
7345 /*
7346 * Add a NSEC3PARAM record which matches that in nsec3chain but
7347 * with all flags bits cleared.
7348 *
7349 * Note: we do not clear chain->nsec3param.flags as this change
7350 * may be reversed.
7351 */
7352 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
7353 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
7354 dns_rdatatype_nsec3param,
7355 &chain->nsec3param, &buffer));
7356 rdata.data[1] = 0; /* Clear flag bits. */
7357 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
7358
7359 failure:
7360 dns_db_detachnode(db, &node);
7361 if (dns_rdataset_isassociated(&rdataset))
7362 dns_rdataset_disassociate(&rdataset);
7363 return (result);
7364 }
7365
7366 static isc_result_t
7367 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7368 dns_name_t *name, dns_diff_t *diff)
7369 {
7370 dns_rdataset_t rdataset;
7371 isc_result_t result;
7372
7373 dns_rdataset_init(&rdataset);
7374
7375 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7376 0, 0, &rdataset, NULL);
7377 if (result == ISC_R_NOTFOUND)
7378 return (ISC_R_SUCCESS);
7379 if (result != ISC_R_SUCCESS)
7380 return (result);
7381 for (result = dns_rdataset_first(&rdataset);
7382 result == ISC_R_SUCCESS;
7383 result = dns_rdataset_next(&rdataset)) {
7384 dns_rdata_t rdata = DNS_RDATA_INIT;
7385
7386 dns_rdataset_current(&rdataset, &rdata);
7387 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7388 rdataset.ttl, &rdata));
7389 }
7390 if (result == ISC_R_NOMORE)
7391 result = ISC_R_SUCCESS;
7392 failure:
7393 dns_rdataset_disassociate(&rdataset);
7394 return (result);
7395 }
7396
7397 static isc_result_t
7398 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7399 dns_name_t *name, const dns_rdata_nsec3param_t *param,
7400 dns_diff_t *diff)
7401 {
7402 dns_rdataset_t rdataset;
7403 dns_rdata_nsec3_t nsec3;
7404 isc_result_t result;
7405
7406 dns_rdataset_init(&rdataset);
7407 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
7408 0, 0, &rdataset, NULL);
7409 if (result == ISC_R_NOTFOUND)
7410 return (ISC_R_SUCCESS);
7411 if (result != ISC_R_SUCCESS)
7412 return (result);
7413
7414 for (result = dns_rdataset_first(&rdataset);
7415 result == ISC_R_SUCCESS;
7416 result = dns_rdataset_next(&rdataset)) {
7417 dns_rdata_t rdata = DNS_RDATA_INIT;
7418
7419 dns_rdataset_current(&rdataset, &rdata);
7420 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
7421 if (nsec3.hash != param->hash ||
7422 nsec3.iterations != param->iterations ||
7423 nsec3.salt_length != param->salt_length ||
7424 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
7425 continue;
7426 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7427 rdataset.ttl, &rdata));
7428 }
7429 if (result == ISC_R_NOMORE)
7430 result = ISC_R_SUCCESS;
7431 failure:
7432 dns_rdataset_disassociate(&rdataset);
7433 return (result);
7434 }
7435
7436 static isc_result_t
7437 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
7438 const dns_rdata_nsec3param_t *param,
7439 bool *answer)
7440 {
7441 dns_dbnode_t *node = NULL;
7442 dns_rdata_t rdata = DNS_RDATA_INIT;
7443 dns_rdata_nsec3param_t myparam;
7444 dns_rdataset_t rdataset;
7445 isc_result_t result;
7446
7447 *answer = false;
7448
7449 result = dns_db_getoriginnode(db, &node);
7450 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7451
7452 dns_rdataset_init(&rdataset);
7453
7454 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7455 0, 0, &rdataset, NULL);
7456 if (result == ISC_R_SUCCESS) {
7457 dns_rdataset_disassociate(&rdataset);
7458 dns_db_detachnode(db, &node);
7459 return (result);
7460 }
7461 if (result != ISC_R_NOTFOUND) {
7462 dns_db_detachnode(db, &node);
7463 return (result);
7464 }
7465
7466 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7467 0, 0, &rdataset, NULL);
7468 if (result == ISC_R_NOTFOUND) {
7469 *answer = true;
7470 dns_db_detachnode(db, &node);
7471 return (ISC_R_SUCCESS);
7472 }
7473 if (result != ISC_R_SUCCESS) {
7474 dns_db_detachnode(db, &node);
7475 return (result);
7476 }
7477
7478 for (result = dns_rdataset_first(&rdataset);
7479 result == ISC_R_SUCCESS;
7480 result = dns_rdataset_next(&rdataset)) {
7481 dns_rdataset_current(&rdataset, &rdata);
7482 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
7483 dns_rdata_reset(&rdata);
7484 /*
7485 * Ignore any NSEC3PARAM removals.
7486 */
7487 if (NSEC3REMOVE(myparam.flags))
7488 continue;
7489 /*
7490 * Ignore the chain that we are in the process of deleting.
7491 */
7492 if (myparam.hash == param->hash &&
7493 myparam.iterations == param->iterations &&
7494 myparam.salt_length == param->salt_length &&
7495 !memcmp(myparam.salt, param->salt, myparam.salt_length))
7496 continue;
7497 /*
7498 * Found an active NSEC3 chain.
7499 */
7500 break;
7501 }
7502 if (result == ISC_R_NOMORE) {
7503 *answer = true;
7504 result = ISC_R_SUCCESS;
7505 }
7506
7507 failure:
7508 if (dns_rdataset_isassociated(&rdataset))
7509 dns_rdataset_disassociate(&rdataset);
7510 dns_db_detachnode(db, &node);
7511 return (result);
7512 }
7513
7514 /*%
7515 * Given a tuple which is part of a diff, return a pointer to the next tuple in
7516 * that diff which has the same name and type (or NULL if no such tuple is
7517 * found).
7518 */
7519 static dns_difftuple_t *
7520 find_next_matching_tuple(dns_difftuple_t *cur) {
7521 dns_difftuple_t *next = cur;
7522
7523 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
7524 if (cur->rdata.type == next->rdata.type &&
7525 dns_name_equal(&cur->name, &next->name))
7526 {
7527 return (next);
7528 }
7529 }
7530
7531 return (NULL);
7532 }
7533
7534 /*%
7535 * Remove all tuples with the same name and type as 'cur' from 'src' and append
7536 * them to 'dst'.
7537 */
7538 static void
7539 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
7540 do {
7541 dns_difftuple_t *next = find_next_matching_tuple(cur);
7542 ISC_LIST_UNLINK(src->tuples, cur, link);
7543 dns_diff_appendminimal(dst, &cur);
7544 cur = next;
7545 } while (cur != NULL);
7546 }
7547
7548 /*%
7549 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
7550 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
7551 * along with tuples representing relevant signature changes.
7552 */
7553 isc_result_t
7554 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
7555 dst_key_t *zone_keys[], unsigned int nkeys,
7556 dns_zone_t *zone, isc_stdtime_t inception,
7557 isc_stdtime_t expire, isc_stdtime_t keyexpire,
7558 isc_stdtime_t now, bool check_ksk,
7559 bool keyset_kskonly, dns__zonediff_t *zonediff)
7560 {
7561 dns_difftuple_t *tuple;
7562 isc_result_t result;
7563
7564 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
7565 isc_stdtime_t exp = expire;
7566
7567 if (keyexpire != 0 &&
7568 (tuple->rdata.type == dns_rdatatype_dnskey ||
7569 tuple->rdata.type == dns_rdatatype_cdnskey ||
7570 tuple->rdata.type == dns_rdatatype_cds))
7571 {
7572 exp = keyexpire;
7573 }
7574
7575 result = del_sigs(zone, db, version, &tuple->name,
7576 tuple->rdata.type, zonediff,
7577 zone_keys, nkeys, now, false);
7578 if (result != ISC_R_SUCCESS) {
7579 dns_zone_log(zone, ISC_LOG_ERROR,
7580 "dns__zone_updatesigs:del_sigs -> %s",
7581 dns_result_totext(result));
7582 return (result);
7583 }
7584 result = add_sigs(db, version, &tuple->name,
7585 tuple->rdata.type, zonediff->diff,
7586 zone_keys, nkeys, zone->mctx, inception,
7587 exp, check_ksk, keyset_kskonly);
7588 if (result != ISC_R_SUCCESS) {
7589 dns_zone_log(zone, ISC_LOG_ERROR,
7590 "dns__zone_updatesigs:add_sigs -> %s",
7591 dns_result_totext(result));
7592 return (result);
7593 }
7594
7595 /*
7596 * Signature changes for all RRs with name tuple->name and type
7597 * tuple->rdata.type were appended to zonediff->diff. Now we
7598 * remove all the "raw" changes with the same name and type
7599 * from diff (so that they are not processed by this loop
7600 * again) and append them to zonediff so that they get applied.
7601 */
7602 move_matching_tuples(tuple, diff, zonediff->diff);
7603 }
7604 return (ISC_R_SUCCESS);
7605 }
7606
7607 /*
7608 * Incrementally build and sign a new NSEC3 chain using the parameters
7609 * requested.
7610 */
7611 static void
7612 zone_nsec3chain(dns_zone_t *zone) {
7613 const char *me = "zone_nsec3chain";
7614 dns_db_t *db = NULL;
7615 dns_dbnode_t *node = NULL;
7616 dns_dbversion_t *version = NULL;
7617 dns_diff_t _sig_diff;
7618 dns_diff_t nsec_diff;
7619 dns_diff_t nsec3_diff;
7620 dns_diff_t param_diff;
7621 dns__zonediff_t zonediff;
7622 dns_fixedname_t fixed;
7623 dns_fixedname_t nextfixed;
7624 dns_name_t *name, *nextname;
7625 dns_rdataset_t rdataset;
7626 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
7627 dns_nsec3chainlist_t cleanup;
7628 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7629 int32_t signatures;
7630 bool check_ksk, keyset_kskonly;
7631 bool delegation;
7632 bool first;
7633 isc_result_t result;
7634 isc_stdtime_t now, inception, soaexpire, expire;
7635 uint32_t jitter, sigvalidityinterval;
7636 unsigned int i;
7637 unsigned int nkeys = 0;
7638 uint32_t nodes;
7639 bool unsecure = false;
7640 bool seen_soa, seen_ns, seen_dname, seen_ds;
7641 bool seen_nsec, seen_nsec3, seen_rr;
7642 dns_rdatasetiter_t *iterator = NULL;
7643 bool buildnsecchain;
7644 bool updatensec = false;
7645 dns_rdatatype_t privatetype = zone->privatetype;
7646
7647 ENTER;
7648
7649 dns_rdataset_init(&rdataset);
7650 name = dns_fixedname_initname(&fixed);
7651 nextname = dns_fixedname_initname(&nextfixed);
7652 dns_diff_init(zone->mctx, ¶m_diff);
7653 dns_diff_init(zone->mctx, &nsec3_diff);
7654 dns_diff_init(zone->mctx, &nsec_diff);
7655 dns_diff_init(zone->mctx, &_sig_diff);
7656 zonediff_init(&zonediff, &_sig_diff);
7657 ISC_LIST_INIT(cleanup);
7658
7659 /*
7660 * Updates are disabled. Pause for 5 minutes.
7661 */
7662 if (zone->update_disabled) {
7663 result = ISC_R_FAILURE;
7664 goto failure;
7665 }
7666
7667 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7668 /*
7669 * This function is called when zone timer fires, after the latter gets
7670 * set by zone_addnsec3chain(). If the action triggering the call to
7671 * zone_addnsec3chain() is closely followed by a zone deletion request,
7672 * it might turn out that the timer thread will not be woken up until
7673 * after the zone is deleted by rmzone(), which calls dns_db_detach()
7674 * for zone->db, causing the latter to become NULL. Return immediately
7675 * if that happens.
7676 */
7677 if (zone->db != NULL) {
7678 dns_db_attach(zone->db, &db);
7679 }
7680 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7681 if (db == NULL) {
7682 return;
7683 }
7684
7685 result = dns_db_newversion(db, &version);
7686 if (result != ISC_R_SUCCESS) {
7687 dnssec_log(zone, ISC_LOG_ERROR,
7688 "zone_nsec3chain:dns_db_newversion -> %s",
7689 dns_result_totext(result));
7690 goto failure;
7691 }
7692
7693 isc_stdtime_get(&now);
7694
7695 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7696 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7697 if (result != ISC_R_SUCCESS) {
7698 dnssec_log(zone, ISC_LOG_ERROR,
7699 "zone_nsec3chain:dns__zone_findkeys -> %s",
7700 dns_result_totext(result));
7701 goto failure;
7702 }
7703
7704 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7705 inception = now - 3600; /* Allow for clock skew. */
7706 soaexpire = now + sigvalidityinterval;
7707
7708 /*
7709 * Spread out signatures over time if they happen to be
7710 * clumped. We don't do this for each add_sigs() call as
7711 * we still want some clustering to occur.
7712 */
7713 if (sigvalidityinterval >= 3600U) {
7714 if (sigvalidityinterval > 7200U) {
7715 jitter = isc_random_uniform(3600);
7716 } else {
7717 jitter = isc_random_uniform(1200);
7718 }
7719 expire = soaexpire - jitter - 1;
7720 } else {
7721 expire = soaexpire - 1;
7722 }
7723
7724 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7725 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7726
7727 /*
7728 * We keep pulling nodes off each iterator in turn until
7729 * we have no more nodes to pull off or we reach the limits
7730 * for this quantum.
7731 */
7732 nodes = zone->nodes;
7733 signatures = zone->signatures;
7734 LOCK_ZONE(zone);
7735 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7736 UNLOCK_ZONE(zone);
7737 first = true;
7738
7739 if (nsec3chain != NULL) {
7740 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7741 }
7742 /*
7743 * Generate new NSEC3 chains first.
7744 *
7745 * The following while loop iterates over nodes in the zone database,
7746 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
7747 * them. Once all nodes are processed, the "delete_nsec" field is
7748 * consulted to check whether we are supposed to remove NSEC records
7749 * from the zone database; if so, the database iterator is reset to
7750 * point to the first node and the loop traverses all of them again,
7751 * this time removing NSEC records. If we hit a node which is obscured
7752 * by a delegation or a DNAME, nodes are skipped over until we find one
7753 * that is not obscured by the same obscuring name and then normal
7754 * processing is resumed.
7755 *
7756 * The above is repeated until all requested NSEC3 chain changes are
7757 * applied or when we reach the limits for this quantum, whichever
7758 * happens first.
7759 *
7760 * Note that the "signatures" variable is only used here to limit the
7761 * amount of work performed. Actual DNSSEC signatures are only
7762 * generated by dns__zone_updatesigs() calls later in this function.
7763 */
7764 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7765 LOCK_ZONE(zone);
7766 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7767
7768 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7769 if (nsec3chain->done || nsec3chain->db != zone->db) {
7770 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
7771 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7772 }
7773 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7774 UNLOCK_ZONE(zone);
7775 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
7776 goto next_addchain;
7777
7778 /*
7779 * Possible future db.
7780 */
7781 if (nsec3chain->db != db) {
7782 goto next_addchain;
7783 }
7784
7785 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
7786 goto next_addchain;
7787
7788 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
7789
7790 if (nsec3chain->delete_nsec) {
7791 delegation = false;
7792 dns_dbiterator_pause(nsec3chain->dbiterator);
7793 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
7794 goto next_addnode;
7795 }
7796 /*
7797 * On the first pass we need to check if the current node
7798 * has not been obscured.
7799 */
7800 delegation = false;
7801 unsecure = false;
7802 if (first) {
7803 dns_fixedname_t ffound;
7804 dns_name_t *found;
7805 found = dns_fixedname_initname(&ffound);
7806 result = dns_db_find(db, name, version,
7807 dns_rdatatype_soa,
7808 DNS_DBFIND_NOWILD, 0, NULL, found,
7809 NULL, NULL);
7810 if ((result == DNS_R_DELEGATION ||
7811 result == DNS_R_DNAME) &&
7812 !dns_name_equal(name, found)) {
7813 /*
7814 * Remember the obscuring name so that
7815 * we skip all obscured names.
7816 */
7817 dns_name_copy(found, name, NULL);
7818 delegation = true;
7819 goto next_addnode;
7820 }
7821 }
7822
7823 /*
7824 * Check to see if this is a bottom of zone node.
7825 */
7826 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7827 if (result == ISC_R_NOTFOUND) {
7828 /* Empty node? */
7829 goto next_addnode;
7830 }
7831 if (result != ISC_R_SUCCESS) {
7832 goto failure;
7833 }
7834
7835 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
7836 for (result = dns_rdatasetiter_first(iterator);
7837 result == ISC_R_SUCCESS;
7838 result = dns_rdatasetiter_next(iterator))
7839 {
7840 dns_rdatasetiter_current(iterator, &rdataset);
7841 INSIST(rdataset.type != dns_rdatatype_nsec3);
7842 if (rdataset.type == dns_rdatatype_soa) {
7843 seen_soa = true;
7844 } else if (rdataset.type == dns_rdatatype_ns) {
7845 seen_ns = true;
7846 } else if (rdataset.type == dns_rdatatype_dname) {
7847 seen_dname = true;
7848 } else if (rdataset.type == dns_rdatatype_ds) {
7849 seen_ds = true;
7850 } else if (rdataset.type == dns_rdatatype_nsec) {
7851 seen_nsec = true;
7852 }
7853 dns_rdataset_disassociate(&rdataset);
7854 }
7855 dns_rdatasetiter_destroy(&iterator);
7856 /*
7857 * Is there a NSEC chain than needs to be cleaned up?
7858 */
7859 if (seen_nsec) {
7860 nsec3chain->seen_nsec = true;
7861 }
7862 if (seen_ns && !seen_soa && !seen_ds) {
7863 unsecure = true;
7864 }
7865 if ((seen_ns && !seen_soa) || seen_dname) {
7866 delegation = true;
7867 }
7868
7869 /*
7870 * Process one node.
7871 */
7872 dns_dbiterator_pause(nsec3chain->dbiterator);
7873 result = dns_nsec3_addnsec3(db, version, name,
7874 &nsec3chain->nsec3param,
7875 zone->minimum, unsecure,
7876 &nsec3_diff);
7877 if (result != ISC_R_SUCCESS) {
7878 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7879 "dns_nsec3_addnsec3 -> %s",
7880 dns_result_totext(result));
7881 goto failure;
7882 }
7883
7884 /*
7885 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
7886 * two signatures. Additionally there will, in general, be
7887 * two signature generated below.
7888 *
7889 * If we are only changing the optout flag the cost is half
7890 * that of the cost of generating a completely new chain.
7891 */
7892 signatures -= 4;
7893
7894 /*
7895 * Go onto next node.
7896 */
7897 next_addnode:
7898 first = false;
7899 dns_db_detachnode(db, &node);
7900 do {
7901 result = dns_dbiterator_next(nsec3chain->dbiterator);
7902
7903 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
7904 dns_dbiterator_pause(nsec3chain->dbiterator);
7905 CHECK(fixup_nsec3param(db, version, nsec3chain,
7906 false, privatetype,
7907 ¶m_diff));
7908 LOCK_ZONE(zone);
7909 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7910 link);
7911 UNLOCK_ZONE(zone);
7912 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7913 goto next_addchain;
7914 }
7915 if (result == ISC_R_NOMORE) {
7916 dns_dbiterator_pause(nsec3chain->dbiterator);
7917 if (nsec3chain->seen_nsec) {
7918 CHECK(fixup_nsec3param(db, version,
7919 nsec3chain,
7920 true,
7921 privatetype,
7922 ¶m_diff));
7923 nsec3chain->delete_nsec = true;
7924 goto same_addchain;
7925 }
7926 CHECK(fixup_nsec3param(db, version, nsec3chain,
7927 false, privatetype,
7928 ¶m_diff));
7929 LOCK_ZONE(zone);
7930 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7931 link);
7932 UNLOCK_ZONE(zone);
7933 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7934 goto next_addchain;
7935 } else if (result != ISC_R_SUCCESS) {
7936 dnssec_log(zone, ISC_LOG_ERROR,
7937 "zone_nsec3chain:"
7938 "dns_dbiterator_next -> %s",
7939 dns_result_totext(result));
7940 goto failure;
7941 } else if (delegation) {
7942 dns_dbiterator_current(nsec3chain->dbiterator,
7943 &node, nextname);
7944 dns_db_detachnode(db, &node);
7945 if (!dns_name_issubdomain(nextname, name))
7946 break;
7947 } else {
7948 break;
7949 }
7950 } while (1);
7951 continue;
7952
7953 same_addchain:
7954 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7955 first = true;
7956 continue;
7957
7958 next_addchain:
7959 dns_dbiterator_pause(nsec3chain->dbiterator);
7960 nsec3chain = nextnsec3chain;
7961 first = true;
7962 if (nsec3chain != NULL) {
7963 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7964 }
7965 }
7966
7967 if (nsec3chain != NULL) {
7968 goto skip_removals;
7969 }
7970
7971 /*
7972 * Process removals.
7973 *
7974 * This is a counterpart of the above while loop which takes care of
7975 * removing an NSEC3 chain. It starts with determining whether the
7976 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
7977 * NSEC chain by iterating over all nodes in the zone database and only
7978 * then goes on to remove NSEC3 records be iterating over all nodes
7979 * again and calling deletematchingnsec3() for each of them; otherwise,
7980 * it starts removing NSEC3 records immediately. Rules for processing
7981 * obscured nodes and interrupting work are the same as for the while
7982 * loop above.
7983 */
7984 LOCK_ZONE(zone);
7985 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7986 UNLOCK_ZONE(zone);
7987 first = true;
7988 buildnsecchain = false;
7989 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7990 LOCK_ZONE(zone);
7991 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7992 UNLOCK_ZONE(zone);
7993
7994 if (nsec3chain->db != db) {
7995 goto next_removechain;
7996 }
7997
7998 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
7999 goto next_removechain;
8000 }
8001
8002 /*
8003 * Work out if we need to build a NSEC chain as a consequence
8004 * of removing this NSEC3 chain.
8005 */
8006 if (first && !updatensec &&
8007 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8008 {
8009 result = need_nsec_chain(db, version,
8010 &nsec3chain->nsec3param,
8011 &buildnsecchain);
8012 if (result != ISC_R_SUCCESS) {
8013 dnssec_log(zone, ISC_LOG_ERROR,
8014 "zone_nsec3chain:"
8015 "need_nsec_chain -> %s",
8016 dns_result_totext(result));
8017 goto failure;
8018 }
8019 }
8020
8021 if (first) {
8022 dnssec_log(zone, ISC_LOG_DEBUG(3),
8023 "zone_nsec3chain:buildnsecchain = %u\n",
8024 buildnsecchain);
8025 }
8026
8027 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8028 delegation = false;
8029
8030 if (!buildnsecchain) {
8031 /*
8032 * Delete the NSEC3PARAM record matching this chain.
8033 */
8034 if (first) {
8035 result = fixup_nsec3param(db, version,
8036 nsec3chain,
8037 true, privatetype,
8038 ¶m_diff);
8039 if (result != ISC_R_SUCCESS) {
8040 dnssec_log(zone, ISC_LOG_ERROR,
8041 "zone_nsec3chain:"
8042 "fixup_nsec3param -> %s",
8043 dns_result_totext(result));
8044 goto failure;
8045 }
8046 }
8047
8048 /*
8049 * Delete the NSEC3 records.
8050 */
8051 result = deletematchingnsec3(db, version, node, name,
8052 &nsec3chain->nsec3param,
8053 &nsec3_diff);
8054 if (result != ISC_R_SUCCESS) {
8055 dnssec_log(zone, ISC_LOG_ERROR,
8056 "zone_nsec3chain:"
8057 "deletematchingnsec3 -> %s",
8058 dns_result_totext(result));
8059 goto failure;
8060 }
8061 goto next_removenode;
8062 }
8063
8064 if (first) {
8065 dns_fixedname_t ffound;
8066 dns_name_t *found;
8067 found = dns_fixedname_initname(&ffound);
8068 result = dns_db_find(db, name, version,
8069 dns_rdatatype_soa,
8070 DNS_DBFIND_NOWILD, 0, NULL, found,
8071 NULL, NULL);
8072 if ((result == DNS_R_DELEGATION ||
8073 result == DNS_R_DNAME) &&
8074 !dns_name_equal(name, found))
8075 {
8076 /*
8077 * Remember the obscuring name so that
8078 * we skip all obscured names.
8079 */
8080 dns_name_copy(found, name, NULL);
8081 delegation = true;
8082 goto next_removenode;
8083 }
8084 }
8085
8086 /*
8087 * Check to see if this is a bottom of zone node.
8088 */
8089 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8090 if (result == ISC_R_NOTFOUND) {
8091 /* Empty node? */
8092 goto next_removenode;
8093 }
8094 if (result != ISC_R_SUCCESS) {
8095 goto failure;
8096 }
8097
8098 seen_soa = seen_ns = seen_dname = seen_nsec3 =
8099 seen_nsec = seen_rr = false;
8100 for (result = dns_rdatasetiter_first(iterator);
8101 result == ISC_R_SUCCESS;
8102 result = dns_rdatasetiter_next(iterator))
8103 {
8104 dns_rdatasetiter_current(iterator, &rdataset);
8105 if (rdataset.type == dns_rdatatype_soa) {
8106 seen_soa = true;
8107 } else if (rdataset.type == dns_rdatatype_ns) {
8108 seen_ns = true;
8109 } else if (rdataset.type == dns_rdatatype_dname) {
8110 seen_dname = true;
8111 } else if (rdataset.type == dns_rdatatype_nsec) {
8112 seen_nsec = true;
8113 } else if (rdataset.type == dns_rdatatype_nsec3) {
8114 seen_nsec3 = true;
8115 } else if (rdataset.type != dns_rdatatype_rrsig) {
8116 seen_rr = true;
8117 }
8118 dns_rdataset_disassociate(&rdataset);
8119 }
8120 dns_rdatasetiter_destroy(&iterator);
8121
8122 if (!seen_rr || seen_nsec3 || seen_nsec) {
8123 goto next_removenode;
8124 }
8125 if ((seen_ns && !seen_soa) || seen_dname) {
8126 delegation = true;
8127 }
8128
8129 /*
8130 * Add a NSEC record except at the origin.
8131 */
8132 if (!dns_name_equal(name, dns_db_origin(db))) {
8133 dns_dbiterator_pause(nsec3chain->dbiterator);
8134 CHECK(add_nsec(db, version, name, node, zone->minimum,
8135 delegation, &nsec_diff));
8136 signatures--;
8137 }
8138
8139 next_removenode:
8140 first = false;
8141 dns_db_detachnode(db, &node);
8142 do {
8143 result = dns_dbiterator_next(nsec3chain->dbiterator);
8144 if (result == ISC_R_NOMORE && buildnsecchain) {
8145 /*
8146 * The NSEC chain should now be built.
8147 * We can now remove the NSEC3 chain.
8148 */
8149 updatensec = true;
8150 goto same_removechain;
8151 }
8152 if (result == ISC_R_NOMORE) {
8153 LOCK_ZONE(zone);
8154 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8155 link);
8156 UNLOCK_ZONE(zone);
8157 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8158 dns_dbiterator_pause(nsec3chain->dbiterator);
8159 result = fixup_nsec3param(db, version,
8160 nsec3chain, false,
8161 privatetype,
8162 ¶m_diff);
8163 if (result != ISC_R_SUCCESS) {
8164 dnssec_log(zone, ISC_LOG_ERROR,
8165 "zone_nsec3chain:"
8166 "fixup_nsec3param -> %s",
8167 dns_result_totext(result));
8168 goto failure;
8169 }
8170 goto next_removechain;
8171 } else if (result != ISC_R_SUCCESS) {
8172 dnssec_log(zone, ISC_LOG_ERROR,
8173 "zone_nsec3chain:"
8174 "dns_dbiterator_next -> %s",
8175 dns_result_totext(result));
8176 goto failure;
8177 } else if (delegation) {
8178 dns_dbiterator_current(nsec3chain->dbiterator,
8179 &node, nextname);
8180 dns_db_detachnode(db, &node);
8181 if (!dns_name_issubdomain(nextname, name)) {
8182 break;
8183 }
8184 } else {
8185 break;
8186 }
8187 } while (1);
8188 continue;
8189
8190 same_removechain:
8191 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8192 buildnsecchain = false;
8193 first = true;
8194 continue;
8195
8196 next_removechain:
8197 dns_dbiterator_pause(nsec3chain->dbiterator);
8198 nsec3chain = nextnsec3chain;
8199 first = true;
8200 }
8201
8202 skip_removals:
8203 /*
8204 * We may need to update the NSEC/NSEC3 records for the zone apex.
8205 */
8206 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8207 bool rebuild_nsec = false,
8208 rebuild_nsec3 = false;
8209 result = dns_db_getoriginnode(db, &node);
8210 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8211 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8212 if (result != ISC_R_SUCCESS) {
8213 dnssec_log(zone, ISC_LOG_ERROR,
8214 "zone_nsec3chain:dns_db_allrdatasets -> %s",
8215 dns_result_totext(result));
8216 goto failure;
8217 }
8218 for (result = dns_rdatasetiter_first(iterator);
8219 result == ISC_R_SUCCESS;
8220 result = dns_rdatasetiter_next(iterator))
8221 {
8222 dns_rdatasetiter_current(iterator, &rdataset);
8223 if (rdataset.type == dns_rdatatype_nsec) {
8224 rebuild_nsec = true;
8225 } else if (rdataset.type == dns_rdatatype_nsec3param) {
8226 rebuild_nsec3 = true;
8227 }
8228 dns_rdataset_disassociate(&rdataset);
8229 }
8230 dns_rdatasetiter_destroy(&iterator);
8231 dns_db_detachnode(db, &node);
8232
8233 if (rebuild_nsec) {
8234 if (nsec3chain != NULL) {
8235 dns_dbiterator_pause(nsec3chain->dbiterator);
8236 }
8237
8238 result = updatesecure(db, version, &zone->origin,
8239 zone->minimum, true,
8240 &nsec_diff);
8241 if (result != ISC_R_SUCCESS) {
8242 dnssec_log(zone, ISC_LOG_ERROR,
8243 "zone_nsec3chain:updatesecure -> %s",
8244 dns_result_totext(result));
8245 goto failure;
8246 }
8247 }
8248
8249 if (rebuild_nsec3) {
8250 if (nsec3chain != NULL) {
8251 dns_dbiterator_pause(nsec3chain->dbiterator);
8252 }
8253
8254 result = dns_nsec3_addnsec3s(db, version,
8255 dns_db_origin(db),
8256 zone->minimum, false,
8257 &nsec3_diff);
8258 if (result != ISC_R_SUCCESS) {
8259 dnssec_log(zone, ISC_LOG_ERROR,
8260 "zone_nsec3chain:"
8261 "dns_nsec3_addnsec3s -> %s",
8262 dns_result_totext(result));
8263 goto failure;
8264 }
8265 }
8266 }
8267
8268 /*
8269 * Add / update signatures for the NSEC3 records.
8270 */
8271 if (nsec3chain != NULL) {
8272 dns_dbiterator_pause(nsec3chain->dbiterator);
8273 }
8274 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
8275 nkeys, zone, inception, expire, 0, now,
8276 check_ksk, keyset_kskonly, &zonediff);
8277 if (result != ISC_R_SUCCESS) {
8278 dnssec_log(zone, ISC_LOG_ERROR,
8279 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8280 dns_result_totext(result));
8281 goto failure;
8282 }
8283
8284 /*
8285 * We have changed the NSEC3PARAM or private RRsets
8286 * above so we need to update the signatures.
8287 */
8288 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
8289 nkeys, zone, inception, expire, 0, now,
8290 check_ksk, keyset_kskonly, &zonediff);
8291 if (result != ISC_R_SUCCESS) {
8292 dnssec_log(zone, ISC_LOG_ERROR,
8293 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8294 dns_result_totext(result));
8295 goto failure;
8296 }
8297
8298 if (updatensec) {
8299 result = updatesecure(db, version, &zone->origin,
8300 zone->minimum, false, &nsec_diff);
8301 if (result != ISC_R_SUCCESS) {
8302 dnssec_log(zone, ISC_LOG_ERROR,
8303 "zone_nsec3chain:updatesecure -> %s",
8304 dns_result_totext(result));
8305 goto failure;
8306 }
8307 }
8308
8309 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys,
8310 nkeys, zone, inception, expire, 0, now,
8311 check_ksk, keyset_kskonly, &zonediff);
8312 if (result != ISC_R_SUCCESS) {
8313 dnssec_log(zone, ISC_LOG_ERROR,
8314 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8315 dns_result_totext(result));
8316 goto failure;
8317 }
8318
8319 /*
8320 * If we made no effective changes to the zone then we can just
8321 * cleanup otherwise we need to increment the serial.
8322 */
8323 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8324 /*
8325 * No need to call dns_db_closeversion() here as it is
8326 * called with commit = true below.
8327 */
8328 goto done;
8329 }
8330
8331 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8332 &zonediff, zone_keys, nkeys, now, false);
8333 if (result != ISC_R_SUCCESS) {
8334 dnssec_log(zone, ISC_LOG_ERROR,
8335 "zone_nsec3chain:del_sigs -> %s",
8336 dns_result_totext(result));
8337 goto failure;
8338 }
8339
8340 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
8341 zone->updatemethod);
8342 if (result != ISC_R_SUCCESS) {
8343 dnssec_log(zone, ISC_LOG_ERROR,
8344 "zone_nsec3chain:update_soa_serial -> %s",
8345 dns_result_totext(result));
8346 goto failure;
8347 }
8348
8349 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
8350 zonediff.diff, zone_keys, nkeys, zone->mctx,
8351 inception, soaexpire, check_ksk, keyset_kskonly);
8352 if (result != ISC_R_SUCCESS) {
8353 dnssec_log(zone, ISC_LOG_ERROR,
8354 "zone_nsec3chain:add_sigs -> %s",
8355 dns_result_totext(result));
8356 goto failure;
8357 }
8358
8359 /* Write changes to journal file. */
8360 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
8361
8362 LOCK_ZONE(zone);
8363 zone_needdump(zone, DNS_DUMP_DELAY);
8364 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8365 UNLOCK_ZONE(zone);
8366
8367 done:
8368 /*
8369 * Pause all iterators so that dns_db_closeversion() can succeed.
8370 */
8371 LOCK_ZONE(zone);
8372 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8373 nsec3chain != NULL;
8374 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8375 {
8376 dns_dbiterator_pause(nsec3chain->dbiterator);
8377 }
8378 UNLOCK_ZONE(zone);
8379
8380 /*
8381 * Everything has succeeded. Commit the changes.
8382 * Unconditionally commit as zonediff.offline not checked above.
8383 */
8384 dns_db_closeversion(db, &version, true);
8385
8386 /*
8387 * Everything succeeded so we can clean these up now.
8388 */
8389 nsec3chain = ISC_LIST_HEAD(cleanup);
8390 while (nsec3chain != NULL) {
8391 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8392 dns_db_detach(&nsec3chain->db);
8393 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8394 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8395 nsec3chain = ISC_LIST_HEAD(cleanup);
8396 }
8397
8398 set_resigntime(zone);
8399
8400 failure:
8401 if (result != ISC_R_SUCCESS) {
8402 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
8403 dns_result_totext(result));
8404 }
8405
8406 /*
8407 * On error roll back the current nsec3chain.
8408 */
8409 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
8410 if (nsec3chain->done) {
8411 dns_db_detach(&nsec3chain->db);
8412 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8413 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8414 } else {
8415 result = dns_dbiterator_first(nsec3chain->dbiterator);
8416 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8417 dns_dbiterator_pause(nsec3chain->dbiterator);
8418 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8419 }
8420 }
8421
8422 /*
8423 * Rollback the cleanup list.
8424 */
8425 nsec3chain = ISC_LIST_TAIL(cleanup);
8426 while (nsec3chain != NULL) {
8427 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8428 if (nsec3chain->done) {
8429 dns_db_detach(&nsec3chain->db);
8430 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8431 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8432 } else {
8433 LOCK_ZONE(zone);
8434 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
8435 UNLOCK_ZONE(zone);
8436 result = dns_dbiterator_first(nsec3chain->dbiterator);
8437 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8438 dns_dbiterator_pause(nsec3chain->dbiterator);
8439 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8440 }
8441 nsec3chain = ISC_LIST_TAIL(cleanup);
8442 }
8443
8444 LOCK_ZONE(zone);
8445 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8446 nsec3chain != NULL;
8447 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8448 {
8449 dns_dbiterator_pause(nsec3chain->dbiterator);
8450 }
8451 UNLOCK_ZONE(zone);
8452
8453 dns_diff_clear(¶m_diff);
8454 dns_diff_clear(&nsec3_diff);
8455 dns_diff_clear(&nsec_diff);
8456 dns_diff_clear(&_sig_diff);
8457
8458 if (iterator != NULL) {
8459 dns_rdatasetiter_destroy(&iterator);
8460 }
8461
8462 for (i = 0; i < nkeys; i++) {
8463 dst_key_free(&zone_keys[i]);
8464 }
8465
8466 if (node != NULL) {
8467 dns_db_detachnode(db, &node);
8468 }
8469 if (version != NULL) {
8470 dns_db_closeversion(db, &version, false);
8471 dns_db_detach(&db);
8472 } else if (db != NULL) {
8473 dns_db_detach(&db);
8474 }
8475
8476 LOCK_ZONE(zone);
8477 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
8478 isc_interval_t interval;
8479 if (zone->update_disabled || result != ISC_R_SUCCESS) {
8480 isc_interval_set(&interval, 60, 0); /* 1 minute */
8481 } else {
8482 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
8483 }
8484 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
8485 } else {
8486 isc_time_settoepoch(&zone->nsec3chaintime);
8487 }
8488 UNLOCK_ZONE(zone);
8489
8490 INSIST(version == NULL);
8491 }
8492
8493 /*%
8494 * Delete all RRSIG records with the given algorithm and keyid.
8495 * Remove the NSEC record and RRSIGs if nkeys is zero.
8496 * If all remaining RRsets are signed with the given algorithm
8497 * set *has_algp to true.
8498 */
8499 static isc_result_t
8500 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
8501 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
8502 uint16_t keyid, bool *has_algp, dns_diff_t *diff)
8503 {
8504 dns_rdata_rrsig_t rrsig;
8505 dns_rdataset_t rdataset;
8506 dns_rdatasetiter_t *iterator = NULL;
8507 isc_result_t result;
8508 bool alg_missed = false;
8509 bool alg_found = false;
8510
8511 char namebuf[DNS_NAME_FORMATSIZE];
8512 dns_name_format(name, namebuf, sizeof(namebuf));
8513
8514 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8515 if (result != ISC_R_SUCCESS) {
8516 if (result == ISC_R_NOTFOUND)
8517 result = ISC_R_SUCCESS;
8518 return (result);
8519 }
8520
8521 dns_rdataset_init(&rdataset);
8522 for (result = dns_rdatasetiter_first(iterator);
8523 result == ISC_R_SUCCESS;
8524 result = dns_rdatasetiter_next(iterator)) {
8525 bool has_alg = false;
8526 dns_rdatasetiter_current(iterator, &rdataset);
8527 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
8528 for (result = dns_rdataset_first(&rdataset);
8529 result == ISC_R_SUCCESS;
8530 result = dns_rdataset_next(&rdataset)) {
8531 dns_rdata_t rdata = DNS_RDATA_INIT;
8532 dns_rdataset_current(&rdataset, &rdata);
8533 CHECK(update_one_rr(db, version, diff,
8534 DNS_DIFFOP_DEL, name,
8535 rdataset.ttl, &rdata));
8536 }
8537 if (result != ISC_R_NOMORE)
8538 goto failure;
8539 dns_rdataset_disassociate(&rdataset);
8540 continue;
8541 }
8542 if (rdataset.type != dns_rdatatype_rrsig) {
8543 dns_rdataset_disassociate(&rdataset);
8544 continue;
8545 }
8546 for (result = dns_rdataset_first(&rdataset);
8547 result == ISC_R_SUCCESS;
8548 result = dns_rdataset_next(&rdataset))
8549 {
8550 dns_rdata_t rdata = DNS_RDATA_INIT;
8551 dns_rdataset_current(&rdataset, &rdata);
8552 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
8553 if (nkeys != 0 &&
8554 (rrsig.algorithm != algorithm ||
8555 rrsig.keyid != keyid))
8556 {
8557 if (rrsig.algorithm == algorithm) {
8558 has_alg = true;
8559 }
8560 continue;
8561 }
8562 CHECK(update_one_rr(db, version, diff,
8563 DNS_DIFFOP_DELRESIGN, name,
8564 rdataset.ttl, &rdata));
8565 }
8566 dns_rdataset_disassociate(&rdataset);
8567 if (result != ISC_R_NOMORE)
8568 break;
8569
8570 /*
8571 * After deleting, if there's still a signature for
8572 * 'algorithm', set alg_found; if not, set alg_missed.
8573 */
8574 if (has_alg) {
8575 alg_found = true;
8576 } else {
8577 alg_missed = true;
8578 }
8579 }
8580 if (result == ISC_R_NOMORE)
8581 result = ISC_R_SUCCESS;
8582
8583 /*
8584 * Set `has_algp` if the algorithm was found in every RRset:
8585 * i.e., found in at least one, and not missing from any.
8586 */
8587 *has_algp = (alg_found && !alg_missed);
8588 failure:
8589 if (dns_rdataset_isassociated(&rdataset))
8590 dns_rdataset_disassociate(&rdataset);
8591 dns_rdatasetiter_destroy(&iterator);
8592 return (result);
8593 }
8594
8595 /*
8596 * Incrementally sign the zone using the keys requested.
8597 * Builds the NSEC chain if required.
8598 */
8599 static void
8600 zone_sign(dns_zone_t *zone) {
8601 const char *me = "zone_sign";
8602 dns_db_t *db = NULL;
8603 dns_dbnode_t *node = NULL;
8604 dns_dbversion_t *version = NULL;
8605 dns_diff_t _sig_diff;
8606 dns_diff_t post_diff;
8607 dns__zonediff_t zonediff;
8608 dns_fixedname_t fixed;
8609 dns_fixedname_t nextfixed;
8610 dns_name_t *name, *nextname;
8611 dns_rdataset_t rdataset;
8612 dns_signing_t *signing, *nextsigning;
8613 dns_signinglist_t cleanup;
8614 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8615 int32_t signatures;
8616 bool check_ksk, keyset_kskonly, is_ksk;
8617 bool with_ksk, with_zsk;
8618 bool commit = false;
8619 bool is_bottom_of_zone;
8620 bool build_nsec = false;
8621 bool build_nsec3 = false;
8622 bool first;
8623 isc_result_t result;
8624 isc_stdtime_t now, inception, soaexpire, expire;
8625 uint32_t jitter, sigvalidityinterval, expiryinterval;
8626 unsigned int i, j;
8627 unsigned int nkeys = 0;
8628 uint32_t nodes;
8629
8630 ENTER;
8631
8632 dns_rdataset_init(&rdataset);
8633 name = dns_fixedname_initname(&fixed);
8634 nextname = dns_fixedname_initname(&nextfixed);
8635 dns_diff_init(zone->mctx, &_sig_diff);
8636 dns_diff_init(zone->mctx, &post_diff);
8637 zonediff_init(&zonediff, &_sig_diff);
8638 ISC_LIST_INIT(cleanup);
8639
8640 /*
8641 * Updates are disabled. Pause for 1 minute.
8642 */
8643 if (zone->update_disabled) {
8644 result = ISC_R_FAILURE;
8645 goto cleanup;
8646 }
8647
8648 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8649 if (zone->db != NULL) {
8650 dns_db_attach(zone->db, &db);
8651 }
8652 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8653 if (db == NULL) {
8654 result = ISC_R_FAILURE;
8655 goto cleanup;
8656 }
8657
8658 result = dns_db_newversion(db, &version);
8659 if (result != ISC_R_SUCCESS) {
8660 dnssec_log(zone, ISC_LOG_ERROR,
8661 "zone_sign:dns_db_newversion -> %s",
8662 dns_result_totext(result));
8663 goto cleanup;
8664 }
8665
8666 isc_stdtime_get(&now);
8667
8668 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8669 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8670 if (result != ISC_R_SUCCESS) {
8671 dnssec_log(zone, ISC_LOG_ERROR,
8672 "zone_sign:dns__zone_findkeys -> %s",
8673 dns_result_totext(result));
8674 goto cleanup;
8675 }
8676
8677 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8678 inception = now - 3600; /* Allow for clock skew. */
8679 soaexpire = now + sigvalidityinterval;
8680 expiryinterval = dns_zone_getsigresigninginterval(zone);
8681 if (expiryinterval > sigvalidityinterval) {
8682 expiryinterval = sigvalidityinterval;
8683 } else {
8684 expiryinterval = sigvalidityinterval - expiryinterval;
8685 }
8686
8687 /*
8688 * Spread out signatures over time if they happen to be
8689 * clumped. We don't do this for each add_sigs() call as
8690 * we still want some clustering to occur.
8691 */
8692 if (sigvalidityinterval >= 3600U) {
8693 if (sigvalidityinterval > 7200U) {
8694 jitter = isc_random_uniform(expiryinterval);
8695 } else {
8696 jitter = isc_random_uniform(1200);
8697 }
8698 expire = soaexpire - jitter - 1;
8699 } else {
8700 expire = soaexpire - 1;
8701 }
8702
8703 /*
8704 * We keep pulling nodes off each iterator in turn until
8705 * we have no more nodes to pull off or we reach the limits
8706 * for this quantum.
8707 */
8708 nodes = zone->nodes;
8709 signatures = zone->signatures;
8710 signing = ISC_LIST_HEAD(zone->signing);
8711 first = true;
8712
8713 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8714 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8715
8716 /* Determine which type of chain to build */
8717 CHECK(dns_private_chains(db, version, zone->privatetype,
8718 &build_nsec, &build_nsec3));
8719
8720 /* If neither chain is found, default to NSEC */
8721 if (!build_nsec && !build_nsec3) {
8722 build_nsec = true;
8723 }
8724
8725 while (signing != NULL && nodes-- > 0 && signatures > 0) {
8726 bool has_alg = false;
8727 nextsigning = ISC_LIST_NEXT(signing, link);
8728
8729 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8730 if (signing->done || signing->db != zone->db) {
8731 /*
8732 * The zone has been reloaded. We will have
8733 * created new signings as part of the reload
8734 * process so we can destroy this one.
8735 */
8736 ISC_LIST_UNLINK(zone->signing, signing, link);
8737 ISC_LIST_APPEND(cleanup, signing, link);
8738 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8739 goto next_signing;
8740 }
8741 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8742
8743 if (signing->db != db) {
8744 goto next_signing;
8745 }
8746
8747 is_bottom_of_zone = false;
8748
8749 if (first && signing->deleteit) {
8750 /*
8751 * Remove the key we are deleting from consideration.
8752 */
8753 for (i = 0, j = 0; i < nkeys; i++) {
8754 /*
8755 * Find the key we want to remove.
8756 */
8757 if (ALG(zone_keys[i]) == signing->algorithm &&
8758 dst_key_id(zone_keys[i]) == signing->keyid)
8759 {
8760 if (KSK(zone_keys[i]))
8761 dst_key_free(&zone_keys[i]);
8762 continue;
8763 }
8764 zone_keys[j] = zone_keys[i];
8765 j++;
8766 }
8767 for (i = j; i < nkeys; i++) {
8768 zone_keys[i] = NULL;
8769 }
8770 nkeys = j;
8771 }
8772
8773 dns_dbiterator_current(signing->dbiterator, &node, name);
8774
8775 if (signing->deleteit) {
8776 dns_dbiterator_pause(signing->dbiterator);
8777 CHECK(del_sig(db, version, name, node, nkeys,
8778 signing->algorithm, signing->keyid,
8779 &has_alg, zonediff.diff));
8780 }
8781
8782 /*
8783 * On the first pass we need to check if the current node
8784 * has not been obscured.
8785 */
8786 if (first) {
8787 dns_fixedname_t ffound;
8788 dns_name_t *found;
8789 found = dns_fixedname_initname(&ffound);
8790 result = dns_db_find(db, name, version,
8791 dns_rdatatype_soa,
8792 DNS_DBFIND_NOWILD, 0, NULL, found,
8793 NULL, NULL);
8794 if ((result == DNS_R_DELEGATION ||
8795 result == DNS_R_DNAME) &&
8796 !dns_name_equal(name, found))
8797 {
8798 /*
8799 * Remember the obscuring name so that
8800 * we skip all obscured names.
8801 */
8802 dns_name_copy(found, name, NULL);
8803 is_bottom_of_zone = true;
8804 goto next_node;
8805 }
8806 }
8807
8808 /*
8809 * Process one node.
8810 */
8811 with_ksk = false;
8812 with_zsk = false;
8813 dns_dbiterator_pause(signing->dbiterator);
8814
8815 CHECK(check_if_bottom_of_zone(db, node, version,
8816 &is_bottom_of_zone));
8817
8818 for (i = 0; !has_alg && i < nkeys; i++) {
8819 bool both = false;
8820
8821 /*
8822 * Find the keys we want to sign with.
8823 */
8824 if (!dst_key_isprivate(zone_keys[i])) {
8825 continue;
8826 }
8827 /*
8828 * Should be redundant.
8829 */
8830 if (dst_key_inactive(zone_keys[i])) {
8831 continue;
8832 }
8833
8834 /*
8835 * When adding look for the specific key.
8836 */
8837 if (!signing->deleteit &&
8838 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
8839 dst_key_id(zone_keys[i]) != signing->keyid))
8840 {
8841 continue;
8842 }
8843
8844 /*
8845 * When deleting make sure we are properly signed
8846 * with the algorithm that was being removed.
8847 */
8848 if (signing->deleteit &&
8849 ALG(zone_keys[i]) != signing->algorithm)
8850 {
8851 continue;
8852 }
8853
8854 /*
8855 * Do we do KSK processing?
8856 */
8857 if (check_ksk && !REVOKE(zone_keys[i])) {
8858 bool have_ksk, have_nonksk;
8859 if (KSK(zone_keys[i])) {
8860 have_ksk = true;
8861 have_nonksk = false;
8862 } else {
8863 have_ksk = false;
8864 have_nonksk = true;
8865 }
8866 for (j = 0; j < nkeys; j++) {
8867 if (j == i ||
8868 (ALG(zone_keys[i]) !=
8869 ALG(zone_keys[j])))
8870 {
8871 continue;
8872 }
8873 if (!dst_key_isprivate(zone_keys[j])) {
8874 continue;
8875 }
8876 /*
8877 * Should be redundant.
8878 */
8879 if (dst_key_inactive(zone_keys[j])) {
8880 continue;
8881 }
8882 if (REVOKE(zone_keys[j])) {
8883 continue;
8884 }
8885 if (KSK(zone_keys[j])) {
8886 have_ksk = true;
8887 } else {
8888 have_nonksk = true;
8889 }
8890 both = have_ksk && have_nonksk;
8891 if (both) {
8892 break;
8893 }
8894 }
8895 }
8896 if (both || REVOKE(zone_keys[i])) {
8897 is_ksk = KSK(zone_keys[i]);
8898 } else {
8899 is_ksk = false;
8900 }
8901
8902 /*
8903 * If deleting signatures, we need to ensure that
8904 * the RRset is still signed at least once by a
8905 * KSK and a ZSK.
8906 */
8907 if (signing->deleteit && !is_ksk && with_zsk) {
8908 continue;
8909 }
8910
8911 if (signing->deleteit && is_ksk && with_ksk) {
8912 continue;
8913 }
8914
8915 CHECK(sign_a_node(db, name, node, version, build_nsec3,
8916 build_nsec, zone_keys[i], inception,
8917 expire, zone->minimum, is_ksk,
8918 (both && keyset_kskonly),
8919 is_bottom_of_zone, zonediff.diff,
8920 &signatures, zone->mctx));
8921 /*
8922 * If we are adding we are done. Look for other keys
8923 * of the same algorithm if deleting.
8924 */
8925 if (!signing->deleteit) {
8926 break;
8927 }
8928 if (!is_ksk) {
8929 with_zsk = true;
8930 }
8931 if (KSK(zone_keys[i])) {
8932 with_ksk = true;
8933 }
8934 }
8935
8936 /*
8937 * Go onto next node.
8938 */
8939 next_node:
8940 first = false;
8941 dns_db_detachnode(db, &node);
8942 do {
8943 result = dns_dbiterator_next(signing->dbiterator);
8944 if (result == ISC_R_NOMORE) {
8945 ISC_LIST_UNLINK(zone->signing, signing, link);
8946 ISC_LIST_APPEND(cleanup, signing, link);
8947 dns_dbiterator_pause(signing->dbiterator);
8948 if (nkeys != 0 && build_nsec) {
8949 /*
8950 * We have finished regenerating the
8951 * zone with a zone signing key.
8952 * The NSEC chain is now complete and
8953 * there is a full set of signatures
8954 * for the zone. We can now clear the
8955 * OPT bit from the NSEC record.
8956 */
8957 result = updatesecure(db, version,
8958 &zone->origin,
8959 zone->minimum,
8960 false,
8961 &post_diff);
8962 if (result != ISC_R_SUCCESS) {
8963 dnssec_log(zone, ISC_LOG_ERROR,
8964 "updatesecure -> %s",
8965 dns_result_totext(result));
8966 goto cleanup;
8967 }
8968 }
8969 result = updatesignwithkey(zone, signing,
8970 version,
8971 build_nsec3,
8972 zone->minimum,
8973 &post_diff);
8974 if (result != ISC_R_SUCCESS) {
8975 dnssec_log(zone, ISC_LOG_ERROR,
8976 "updatesignwithkey -> %s",
8977 dns_result_totext(result));
8978 goto cleanup;
8979 }
8980 build_nsec = false;
8981 goto next_signing;
8982 } else if (result != ISC_R_SUCCESS) {
8983 dnssec_log(zone, ISC_LOG_ERROR,
8984 "zone_sign:"
8985 "dns_dbiterator_next -> %s",
8986 dns_result_totext(result));
8987 goto cleanup;
8988 } else if (is_bottom_of_zone) {
8989 dns_dbiterator_current(signing->dbiterator,
8990 &node, nextname);
8991 dns_db_detachnode(db, &node);
8992 if (!dns_name_issubdomain(nextname, name)) {
8993 break;
8994 }
8995 } else {
8996 break;
8997 }
8998 } while (1);
8999 continue;
9000
9001 next_signing:
9002 dns_dbiterator_pause(signing->dbiterator);
9003 signing = nextsigning;
9004 first = true;
9005 }
9006
9007 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9008 result = dns__zone_updatesigs(&post_diff, db, version,
9009 zone_keys, nkeys, zone,
9010 inception, expire, 0, now,
9011 check_ksk, keyset_kskonly,
9012 &zonediff);
9013 if (result != ISC_R_SUCCESS) {
9014 dnssec_log(zone, ISC_LOG_ERROR,
9015 "zone_sign:dns__zone_updatesigs -> %s",
9016 dns_result_totext(result));
9017 goto cleanup;
9018 }
9019 }
9020
9021 /*
9022 * Have we changed anything?
9023 */
9024 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9025 if (zonediff.offline) {
9026 commit = true;
9027 }
9028 result = ISC_R_SUCCESS;
9029 goto pauseall;
9030 }
9031
9032 commit = true;
9033
9034 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9035 &zonediff, zone_keys, nkeys, now, false);
9036 if (result != ISC_R_SUCCESS) {
9037 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9038 dns_result_totext(result));
9039 goto cleanup;
9040 }
9041
9042 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
9043 zone->updatemethod);
9044 if (result != ISC_R_SUCCESS) {
9045 dnssec_log(zone, ISC_LOG_ERROR,
9046 "zone_sign:update_soa_serial -> %s",
9047 dns_result_totext(result));
9048 goto cleanup;
9049 }
9050
9051 /*
9052 * Generate maximum life time signatures so that the above loop
9053 * termination is sensible.
9054 */
9055 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
9056 zonediff.diff, zone_keys, nkeys, zone->mctx,
9057 inception, soaexpire, check_ksk, keyset_kskonly);
9058 if (result != ISC_R_SUCCESS) {
9059 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9060 dns_result_totext(result));
9061 goto cleanup;
9062 }
9063
9064 /*
9065 * Write changes to journal file.
9066 */
9067 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
9068
9069 pauseall:
9070 /*
9071 * Pause all iterators so that dns_db_closeversion() can succeed.
9072 */
9073 for (signing = ISC_LIST_HEAD(zone->signing);
9074 signing != NULL;
9075 signing = ISC_LIST_NEXT(signing, link))
9076 {
9077 dns_dbiterator_pause(signing->dbiterator);
9078 }
9079
9080 for (signing = ISC_LIST_HEAD(cleanup);
9081 signing != NULL;
9082 signing = ISC_LIST_NEXT(signing, link))
9083 {
9084 dns_dbiterator_pause(signing->dbiterator);
9085 }
9086
9087 /*
9088 * Everything has succeeded. Commit the changes.
9089 */
9090 dns_db_closeversion(db, &version, commit);
9091
9092 /*
9093 * Everything succeeded so we can clean these up now.
9094 */
9095 signing = ISC_LIST_HEAD(cleanup);
9096 while (signing != NULL) {
9097 ISC_LIST_UNLINK(cleanup, signing, link);
9098 dns_db_detach(&signing->db);
9099 dns_dbiterator_destroy(&signing->dbiterator);
9100 isc_mem_put(zone->mctx, signing, sizeof *signing);
9101 signing = ISC_LIST_HEAD(cleanup);
9102 }
9103
9104 set_resigntime(zone);
9105
9106 if (commit) {
9107 LOCK_ZONE(zone);
9108 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9109 zone_needdump(zone, DNS_DUMP_DELAY);
9110 UNLOCK_ZONE(zone);
9111 }
9112
9113 failure:
9114 if (result != ISC_R_SUCCESS) {
9115 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
9116 dns_result_totext(result));
9117 }
9118
9119 cleanup:
9120 /*
9121 * Pause all dbiterators.
9122 */
9123 for (signing = ISC_LIST_HEAD(zone->signing);
9124 signing != NULL;
9125 signing = ISC_LIST_NEXT(signing, link))
9126 {
9127 dns_dbiterator_pause(signing->dbiterator);
9128 }
9129
9130 /*
9131 * Rollback the cleanup list.
9132 */
9133 signing = ISC_LIST_HEAD(cleanup);
9134 while (signing != NULL) {
9135 ISC_LIST_UNLINK(cleanup, signing, link);
9136 ISC_LIST_PREPEND(zone->signing, signing, link);
9137 dns_dbiterator_first(signing->dbiterator);
9138 dns_dbiterator_pause(signing->dbiterator);
9139 signing = ISC_LIST_HEAD(cleanup);
9140 }
9141
9142 dns_diff_clear(&_sig_diff);
9143
9144 for (i = 0; i < nkeys; i++) {
9145 dst_key_free(&zone_keys[i]);
9146 }
9147
9148 if (node != NULL) {
9149 dns_db_detachnode(db, &node);
9150 }
9151
9152 if (version != NULL) {
9153 dns_db_closeversion(db, &version, false);
9154 dns_db_detach(&db);
9155 } else if (db != NULL) {
9156 dns_db_detach(&db);
9157 }
9158
9159 if (ISC_LIST_HEAD(zone->signing) != NULL) {
9160 isc_interval_t interval;
9161 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9162 isc_interval_set(&interval, 60, 0); /* 1 minute */
9163 } else {
9164 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9165 }
9166 isc_time_nowplusinterval(&zone->signingtime, &interval);
9167 } else {
9168 isc_time_settoepoch(&zone->signingtime);
9169 }
9170
9171 INSIST(version == NULL);
9172 }
9173
9174 static isc_result_t
9175 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
9176 unsigned char *data, int size)
9177 {
9178 dns_rdata_dnskey_t dnskey;
9179 dns_rdata_keydata_t keydata;
9180 isc_buffer_t buf;
9181 isc_result_t result;
9182
9183 dns_rdata_reset(target);
9184 isc_buffer_init(&buf, data, size);
9185
9186 switch (rr->type) {
9187 case dns_rdatatype_dnskey:
9188 result = dns_rdata_tostruct(rr, &dnskey, NULL);
9189 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9190 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
9191 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9192 &dnskey, &buf);
9193 break;
9194 case dns_rdatatype_keydata:
9195 result = dns_rdata_tostruct(rr, &keydata, NULL);
9196 if (result == ISC_R_UNEXPECTEDEND)
9197 return (result);
9198 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9199 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9200 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9201 &dnskey, &buf);
9202 break;
9203 default:
9204 INSIST(0);
9205 ISC_UNREACHABLE();
9206 }
9207 return (ISC_R_SUCCESS);
9208 }
9209
9210 /*
9211 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
9212 * a KEYDATA rdataset from the key zone.
9213 *
9214 * 'rr' contains either a DNSKEY record, or a KEYDATA record
9215 *
9216 * After normalizing keys to the same format (DNSKEY, with revoke bit
9217 * cleared), return true if a key that matches 'rr' is found in
9218 * 'rdset', or false if not.
9219 */
9220
9221 static bool
9222 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
9223 unsigned char data1[4096], data2[4096];
9224 dns_rdata_t rdata, rdata1, rdata2;
9225 isc_result_t result;
9226
9227 dns_rdata_init(&rdata);
9228 dns_rdata_init(&rdata1);
9229 dns_rdata_init(&rdata2);
9230
9231 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
9232 if (result != ISC_R_SUCCESS)
9233 return (false);
9234
9235 for (result = dns_rdataset_first(rdset);
9236 result == ISC_R_SUCCESS;
9237 result = dns_rdataset_next(rdset)) {
9238 dns_rdata_reset(&rdata);
9239 dns_rdataset_current(rdset, &rdata);
9240 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
9241 if (result != ISC_R_SUCCESS)
9242 continue;
9243 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
9244 return (true);
9245 }
9246
9247 return (false);
9248 }
9249
9250 /*
9251 * Calculate the refresh interval for a keydata zone, per
9252 * RFC5011: MAX(1 hr,
9253 * MIN(15 days,
9254 * 1/2 * OrigTTL,
9255 * 1/2 * RRSigExpirationInterval))
9256 * or for retries: MAX(1 hr,
9257 * MIN(1 day,
9258 * 1/10 * OrigTTL,
9259 * 1/10 * RRSigExpirationInterval))
9260 */
9261 static inline isc_stdtime_t
9262 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
9263 isc_result_t result;
9264 uint32_t t;
9265 dns_rdataset_t *rdset;
9266 dns_rdata_t sigrr = DNS_RDATA_INIT;
9267 dns_rdata_sig_t sig;
9268 isc_stdtime_t now;
9269
9270 isc_stdtime_get(&now);
9271
9272 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
9273 rdset = &kfetch->dnskeysigset;
9274 else
9275 return (now + dns_zone_mkey_hour);
9276
9277 result = dns_rdataset_first(rdset);
9278 if (result != ISC_R_SUCCESS)
9279 return (now + dns_zone_mkey_hour);
9280
9281 dns_rdataset_current(rdset, &sigrr);
9282 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9283 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9284
9285 if (!retry) {
9286 t = sig.originalttl / 2;
9287
9288 if (isc_serial_gt(sig.timeexpire, now)) {
9289 uint32_t exp = (sig.timeexpire - now) / 2;
9290 if (t > exp)
9291 t = exp;
9292 }
9293
9294 if (t > (15 * dns_zone_mkey_day))
9295 t = (15 * dns_zone_mkey_day);
9296
9297 if (t < dns_zone_mkey_hour)
9298 t = dns_zone_mkey_hour;
9299 } else {
9300 t = sig.originalttl / 10;
9301
9302 if (isc_serial_gt(sig.timeexpire, now)) {
9303 uint32_t exp = (sig.timeexpire - now) / 10;
9304 if (t > exp)
9305 t = exp;
9306 }
9307
9308 if (t > dns_zone_mkey_day)
9309 t = dns_zone_mkey_day;
9310
9311 if (t < dns_zone_mkey_hour)
9312 t = dns_zone_mkey_hour;
9313 }
9314
9315 return (now + t);
9316 }
9317
9318 /*
9319 * This routine is called when no changes are needed in a KEYDATA
9320 * record except to simply update the refresh timer. Caller should
9321 * hold zone lock.
9322 */
9323 static isc_result_t
9324 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
9325 {
9326 isc_result_t result;
9327 isc_buffer_t keyb;
9328 unsigned char key_buf[4096];
9329 dns_rdata_t rdata = DNS_RDATA_INIT;
9330 dns_rdata_keydata_t keydata;
9331 dns_name_t *name;
9332 dns_zone_t *zone = kfetch->zone;
9333 isc_stdtime_t now;
9334
9335 name = dns_fixedname_name(&kfetch->name);
9336 isc_stdtime_get(&now);
9337
9338 for (result = dns_rdataset_first(&kfetch->keydataset);
9339 result == ISC_R_SUCCESS;
9340 result = dns_rdataset_next(&kfetch->keydataset)) {
9341 dns_rdata_reset(&rdata);
9342 dns_rdataset_current(&kfetch->keydataset, &rdata);
9343
9344 /* Delete old version */
9345 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
9346 name, 0, &rdata));
9347
9348 /* Update refresh timer */
9349 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
9350 if (result == ISC_R_UNEXPECTEDEND)
9351 continue;
9352 if (result != ISC_R_SUCCESS)
9353 goto failure;
9354 keydata.refresh = refresh_time(kfetch, true);
9355 set_refreshkeytimer(zone, &keydata, now, false);
9356
9357 dns_rdata_reset(&rdata);
9358 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9359 CHECK(dns_rdata_fromstruct(&rdata,
9360 zone->rdclass, dns_rdatatype_keydata,
9361 &keydata, &keyb));
9362
9363 /* Insert updated version */
9364 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
9365 name, 0, &rdata));
9366 }
9367 result = ISC_R_SUCCESS;
9368 failure:
9369 return (result);
9370 }
9371
9372 /*
9373 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
9374 */
9375 static bool
9376 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
9377 isc_result_t result;
9378 dns_name_t *keyname;
9379 isc_mem_t *mctx;
9380 dns_rdata_t sigrr = DNS_RDATA_INIT;
9381 dns_rdata_t rr = DNS_RDATA_INIT;
9382 dns_rdata_rrsig_t sig;
9383 dns_rdata_dnskey_t dnskey;
9384 dst_key_t *dstkey = NULL;
9385 unsigned char key_buf[4096];
9386 isc_buffer_t keyb;
9387 bool answer = false;
9388
9389 REQUIRE(kfetch != NULL && keydata != NULL);
9390 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
9391
9392 keyname = dns_fixedname_name(&kfetch->name);
9393 mctx = kfetch->zone->view->mctx;
9394
9395 /* Generate a key from keydata */
9396 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9397 dns_keydata_todnskey(keydata, &dnskey, NULL);
9398 dns_rdata_fromstruct(&rr, keydata->common.rdclass,
9399 dns_rdatatype_dnskey, &dnskey, &keyb);
9400 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
9401 if (result != ISC_R_SUCCESS) {
9402 return (false);
9403 }
9404
9405 /* See if that key generated any of the signatures */
9406 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9407 result == ISC_R_SUCCESS;
9408 result = dns_rdataset_next(&kfetch->dnskeysigset))
9409 {
9410 dns_fixedname_t fixed;
9411 dns_fixedname_init(&fixed);
9412
9413 dns_rdata_reset(&sigrr);
9414 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9415 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9416 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9417
9418 if (dst_key_alg(dstkey) == sig.algorithm &&
9419 dst_key_rid(dstkey) == sig.keyid)
9420 {
9421 result = dns_dnssec_verify(keyname,
9422 &kfetch->dnskeyset,
9423 dstkey, false, 0, mctx,
9424 &sigrr,
9425 dns_fixedname_name(&fixed));
9426
9427 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
9428 "Confirm revoked DNSKEY is self-signed: %s",
9429 dns_result_totext(result));
9430
9431 if (result == ISC_R_SUCCESS) {
9432 answer = true;
9433 break;
9434 }
9435 }
9436 }
9437
9438 dst_key_free(&dstkey);
9439 return (answer);
9440 }
9441
9442 /*
9443 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
9444 * anchors are being managed; scan the keyset, and update the key zone and the
9445 * local trust anchors according to RFC5011.
9446 */
9447 static void
9448 keyfetch_done(isc_task_t *task, isc_event_t *event) {
9449 isc_result_t result, eresult;
9450 dns_fetchevent_t *devent;
9451 dns_keyfetch_t *kfetch;
9452 dns_zone_t *zone;
9453 isc_mem_t *mctx = NULL;
9454 dns_keytable_t *secroots = NULL;
9455 dns_dbversion_t *ver = NULL;
9456 dns_diff_t diff;
9457 bool alldone = false;
9458 bool commit = false;
9459 dns_name_t *keyname;
9460 dns_rdata_t sigrr = DNS_RDATA_INIT;
9461 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
9462 dns_rdata_t keydatarr = DNS_RDATA_INIT;
9463 dns_rdata_rrsig_t sig;
9464 dns_rdata_dnskey_t dnskey;
9465 dns_rdata_keydata_t keydata;
9466 bool initializing;
9467 char namebuf[DNS_NAME_FORMATSIZE];
9468 unsigned char key_buf[4096];
9469 isc_buffer_t keyb;
9470 dst_key_t *dstkey;
9471 isc_stdtime_t now;
9472 int pending = 0;
9473 bool secure = false, initial = false;
9474 bool free_needed;
9475
9476 UNUSED(task);
9477 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
9478 INSIST(event->ev_arg != NULL);
9479
9480 kfetch = event->ev_arg;
9481 zone = kfetch->zone;
9482 isc_mem_attach(zone->mctx, &mctx);
9483 keyname = dns_fixedname_name(&kfetch->name);
9484
9485 devent = (dns_fetchevent_t *) event;
9486 eresult = devent->result;
9487
9488 /* Free resources which are not of interest */
9489 if (devent->node != NULL) {
9490 dns_db_detachnode(devent->db, &devent->node);
9491 }
9492 if (devent->db != NULL) {
9493 dns_db_detach(&devent->db);
9494 }
9495 isc_event_free(&event);
9496 dns_resolver_destroyfetch(&kfetch->fetch);
9497
9498 LOCK_ZONE(zone);
9499 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
9500 goto cleanup;
9501 }
9502
9503 isc_stdtime_get(&now);
9504 dns_name_format(keyname, namebuf, sizeof(namebuf));
9505
9506 result = dns_view_getsecroots(zone->view, &secroots);
9507 INSIST(result == ISC_R_SUCCESS);
9508
9509 dns_diff_init(mctx, &diff);
9510
9511 CHECK(dns_db_newversion(kfetch->db, &ver));
9512
9513 zone->refreshkeycount--;
9514 alldone = (zone->refreshkeycount == 0);
9515
9516 if (alldone) {
9517 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
9518 }
9519
9520 dnssec_log(zone, ISC_LOG_DEBUG(3),
9521 "Returned from key fetch in keyfetch_done() for '%s': %s",
9522 namebuf, dns_result_totext(eresult));
9523
9524 /* Fetch failed */
9525 if (eresult != ISC_R_SUCCESS ||
9526 !dns_rdataset_isassociated(&kfetch->dnskeyset))
9527 {
9528 dnssec_log(zone, ISC_LOG_WARNING,
9529 "Unable to fetch DNSKEY set '%s': %s",
9530 namebuf, dns_result_totext(eresult));
9531 CHECK(minimal_update(kfetch, ver, &diff));
9532 goto done;
9533 }
9534
9535 /* No RRSIGs found */
9536 if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
9537 dnssec_log(zone, ISC_LOG_WARNING,
9538 "No DNSKEY RRSIGs found for '%s': %s",
9539 namebuf, dns_result_totext(eresult));
9540 CHECK(minimal_update(kfetch, ver, &diff));
9541 goto done;
9542 }
9543
9544 /*
9545 * Clear any cached trust level, as we need to run validation
9546 * over again; trusted keys might have changed.
9547 */
9548 kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
9549
9550 /*
9551 * Validate the dnskeyset against the current trusted keys.
9552 */
9553 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9554 result == ISC_R_SUCCESS;
9555 result = dns_rdataset_next(&kfetch->dnskeysigset))
9556 {
9557 dns_keynode_t *keynode = NULL;
9558
9559 dns_rdata_reset(&sigrr);
9560 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9561 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9562 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9563
9564 result = dns_keytable_find(secroots, keyname, &keynode);
9565 while (result == ISC_R_SUCCESS) {
9566 dns_keynode_t *nextnode = NULL;
9567 dns_fixedname_t fixed;
9568 dns_fixedname_init(&fixed);
9569
9570 dstkey = dns_keynode_key(keynode);
9571 if (dstkey == NULL) {
9572 /* fail_secure() was called */
9573 break;
9574 }
9575
9576 if (dst_key_alg(dstkey) == sig.algorithm &&
9577 dst_key_id(dstkey) == sig.keyid)
9578 {
9579 result = dns_dnssec_verify(keyname,
9580 &kfetch->dnskeyset,
9581 dstkey, false,
9582 0,
9583 zone->view->mctx,
9584 &sigrr,
9585 dns_fixedname_name(
9586 &fixed));
9587
9588 dnssec_log(zone, ISC_LOG_DEBUG(3),
9589 "Verifying DNSKEY set for zone "
9590 "'%s' using key %d/%d: %s",
9591 namebuf, sig.keyid, sig.algorithm,
9592 dns_result_totext(result));
9593
9594 if (result == ISC_R_SUCCESS) {
9595 kfetch->dnskeyset.trust =
9596 dns_trust_secure;
9597 kfetch->dnskeysigset.trust =
9598 dns_trust_secure;
9599 secure = true;
9600 initial = dns_keynode_initial(keynode);
9601 dns_keynode_trust(keynode);
9602 break;
9603 }
9604 }
9605
9606 result = dns_keytable_nextkeynode(secroots,
9607 keynode, &nextnode);
9608 dns_keytable_detachkeynode(secroots, &keynode);
9609 keynode = nextnode;
9610 }
9611
9612 if (keynode != NULL) {
9613 dns_keytable_detachkeynode(secroots, &keynode);
9614 }
9615
9616 if (secure) {
9617 break;
9618 }
9619 }
9620
9621 /*
9622 * If we were not able to verify the answer using the current
9623 * trusted keys then all we can do is look at any revoked keys.
9624 */
9625 if (!secure) {
9626 dnssec_log(zone, ISC_LOG_INFO,
9627 "DNSKEY set for zone '%s' could not be verified "
9628 "with current keys", namebuf);
9629 }
9630
9631 /*
9632 * First scan keydataset to find keys that are not in dnskeyset
9633 * - Missing keys which are not scheduled for removal,
9634 * log a warning
9635 * - Missing keys which are scheduled for removal and
9636 * the remove hold-down timer has completed should
9637 * be removed from the key zone
9638 * - Missing keys whose acceptance timers have not yet
9639 * completed, log a warning and reset the acceptance
9640 * timer to 30 days in the future
9641 * - All keys not being removed have their refresh timers
9642 * updated
9643 */
9644 initializing = true;
9645 for (result = dns_rdataset_first(&kfetch->keydataset);
9646 result == ISC_R_SUCCESS;
9647 result = dns_rdataset_next(&kfetch->keydataset))
9648 {
9649 dns_keytag_t keytag;
9650
9651 dns_rdata_reset(&keydatarr);
9652 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9653 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9654 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9655
9656 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9657 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9658 if (result != ISC_R_SUCCESS) {
9659 /*
9660 * Skip if we cannot compute the key tag.
9661 * This may happen if the algorithm is unsupported
9662 */
9663 dns_zone_log(zone, ISC_LOG_ERROR,
9664 "Cannot compute tag for key in zone %s: %s "
9665 "(skipping)",
9666 namebuf, dns_result_totext(result));
9667 continue;
9668 }
9669 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9670
9671 /*
9672 * If any keydata record has a nonzero add holddown, then
9673 * there was a pre-existing trust anchor for this domain;
9674 * that means we are *not* initializing it and shouldn't
9675 * automatically trust all the keys we find at the zone apex.
9676 */
9677 initializing = initializing && (keydata.addhd == 0);
9678
9679 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
9680 bool deletekey = false;
9681
9682 if (!secure) {
9683 if (keydata.removehd != 0 &&
9684 keydata.removehd <= now)
9685 {
9686 deletekey = true;
9687 }
9688 } else if (keydata.addhd == 0) {
9689 deletekey = true;
9690 } else if (keydata.addhd > now) {
9691 dnssec_log(zone, ISC_LOG_INFO,
9692 "Pending key %d for zone %s "
9693 "unexpectedly missing "
9694 "restarting 30-day acceptance "
9695 "timer", keytag, namebuf);
9696 if (keydata.addhd < now + dns_zone_mkey_month) {
9697 keydata.addhd =
9698 now + dns_zone_mkey_month;
9699 }
9700 keydata.refresh = refresh_time(kfetch, false);
9701 } else if (keydata.removehd == 0) {
9702 dnssec_log(zone, ISC_LOG_INFO,
9703 "Active key %d for zone %s "
9704 "unexpectedly missing",
9705 keytag, namebuf);
9706 keydata.refresh = now + dns_zone_mkey_hour;
9707 } else if (keydata.removehd <= now) {
9708 deletekey = true;
9709 dnssec_log(zone, ISC_LOG_INFO,
9710 "Revoked key %d for zone %s "
9711 "missing: deleting from "
9712 "managed keys database",
9713 keytag, namebuf);
9714 } else {
9715 keydata.refresh = refresh_time(kfetch, false);
9716 }
9717
9718 if (secure || deletekey) {
9719 /* Delete old version */
9720 CHECK(update_one_rr(kfetch->db, ver, &diff,
9721 DNS_DIFFOP_DEL, keyname, 0,
9722 &keydatarr));
9723 }
9724
9725 if (!secure || deletekey) {
9726 continue;
9727 }
9728
9729 dns_rdata_reset(&keydatarr);
9730 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9731 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9732 dns_rdatatype_keydata,
9733 &keydata, &keyb);
9734
9735 /* Insert updated version */
9736 CHECK(update_one_rr(kfetch->db, ver, &diff,
9737 DNS_DIFFOP_ADD, keyname, 0,
9738 &keydatarr));
9739
9740 set_refreshkeytimer(zone, &keydata, now, false);
9741 }
9742 }
9743
9744 /*
9745 * Next scan dnskeyset:
9746 * - If new keys are found (i.e., lacking a match in keydataset)
9747 * add them to the key zone and set the acceptance timer
9748 * to 30 days in the future (or to immediately if we've
9749 * determined that we're initializing the zone for the
9750 * first time)
9751 * - Previously-known keys that have been revoked
9752 * must be scheduled for removal from the key zone (or,
9753 * if they hadn't been accepted as trust anchors yet
9754 * anyway, removed at once)
9755 * - Previously-known unrevoked keys whose acceptance timers
9756 * have completed are promoted to trust anchors
9757 * - All keys not being removed have their refresh
9758 * timers updated
9759 */
9760 for (result = dns_rdataset_first(&kfetch->dnskeyset);
9761 result == ISC_R_SUCCESS;
9762 result = dns_rdataset_next(&kfetch->dnskeyset))
9763 {
9764 bool revoked = false;
9765 bool newkey = false;
9766 bool updatekey = false;
9767 bool deletekey = false;
9768 bool trustkey = false;
9769 dns_keytag_t keytag;
9770
9771 dns_rdata_reset(&dnskeyrr);
9772 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
9773 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9774 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9775
9776 /* Skip ZSK's */
9777 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
9778 continue;
9779 }
9780
9781 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9782 if (result != ISC_R_SUCCESS) {
9783 /*
9784 * Skip if we cannot compute the key tag.
9785 * This may happen if the algorithm is unsupported
9786 */
9787 dns_zone_log(zone, ISC_LOG_ERROR,
9788 "Cannot compute tag for key in zone %s: %s "
9789 "(skipping)",
9790 namebuf, dns_result_totext(result));
9791 continue;
9792 }
9793 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9794
9795 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
9796
9797 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
9798 dns_rdata_reset(&keydatarr);
9799 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9800 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9801 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9802
9803 if (revoked && revocable(kfetch, &keydata)) {
9804 if (keydata.addhd > now) {
9805 /*
9806 * Key wasn't trusted yet, and now
9807 * it's been revoked? Just remove it
9808 */
9809 deletekey = true;
9810 dnssec_log(zone, ISC_LOG_INFO,
9811 "Pending key %d for "
9812 "zone %s is now revoked: "
9813 "deleting from the "
9814 "managed keys database",
9815 keytag, namebuf);
9816 } else if (keydata.removehd == 0) {
9817 /*
9818 * Remove key from secroots.
9819 */
9820 dns_view_untrust(zone->view, keyname,
9821 &dnskey, mctx);
9822
9823 /* If initializing, delete now */
9824 if (keydata.addhd == 0) {
9825 deletekey = true;
9826 } else {
9827 keydata.removehd = now +
9828 dns_zone_mkey_month;
9829 keydata.flags |=
9830 DNS_KEYFLAG_REVOKE;
9831 }
9832
9833 dnssec_log(zone, ISC_LOG_INFO,
9834 "Trusted key %d for "
9835 "zone %s is now revoked",
9836 keytag, namebuf);
9837 } else if (keydata.removehd < now) {
9838 /* Scheduled for removal */
9839 deletekey = true;
9840
9841 dnssec_log(zone, ISC_LOG_INFO,
9842 "Revoked key %d for "
9843 "zone %s removal timer "
9844 "complete: deleting from "
9845 "the managed keys database",
9846 keytag, namebuf);
9847 }
9848 } else if (revoked && keydata.removehd == 0) {
9849 dnssec_log(zone, ISC_LOG_WARNING,
9850 "Active key %d for zone "
9851 "%s is revoked but "
9852 "did not self-sign; "
9853 "ignoring", keytag, namebuf);
9854 continue;
9855 } else if (secure) {
9856 if (keydata.removehd != 0) {
9857 /*
9858 * Key isn't revoked--but it
9859 * seems it used to be.
9860 * Remove it now and add it
9861 * back as if it were a fresh key,
9862 * with a 30-day acceptance timer.
9863 */
9864 deletekey = true;
9865 newkey = true;
9866 keydata.removehd = 0;
9867 keydata.addhd =
9868 now + dns_zone_mkey_month;
9869
9870 dnssec_log(zone, ISC_LOG_INFO,
9871 "Revoked key %d for "
9872 "zone %s has returned: "
9873 "starting 30-day "
9874 "acceptance timer",
9875 keytag, namebuf);
9876 } else if (keydata.addhd > now) {
9877 pending++;
9878 } else if (keydata.addhd == 0) {
9879 keydata.addhd = now;
9880 }
9881
9882 if (keydata.addhd <= now) {
9883 trustkey = true;
9884 dnssec_log(zone, ISC_LOG_INFO,
9885 "Key %d for zone %s "
9886 "is now trusted (%s)",
9887 keytag, namebuf,
9888 initial
9889 ? "initializing key "
9890 "verified"
9891 : "acceptance timer "
9892 "complete");
9893 }
9894 } else if (keydata.addhd > now) {
9895 /*
9896 * Not secure, and key is pending:
9897 * reset the acceptance timer
9898 */
9899 pending++;
9900 keydata.addhd = now + dns_zone_mkey_month;
9901 dnssec_log(zone, ISC_LOG_INFO,
9902 "Pending key %d "
9903 "for zone %s was "
9904 "not validated: restarting "
9905 "30-day acceptance timer",
9906 keytag, namebuf);
9907 }
9908
9909 if (!deletekey && !newkey) {
9910 updatekey = true;
9911 }
9912 } else if (secure) {
9913 /*
9914 * Key wasn't in the key zone but it's
9915 * revoked now anyway, so just skip it
9916 */
9917 if (revoked) {
9918 continue;
9919 }
9920
9921 /* Key wasn't in the key zone: add it */
9922 newkey = true;
9923
9924 if (initializing) {
9925 dnssec_log(zone, ISC_LOG_WARNING,
9926 "Initializing automatic trust "
9927 "anchor management for zone '%s'; "
9928 "DNSKEY ID %d is now trusted, "
9929 "waiving the normal 30-day "
9930 "waiting period.",
9931 namebuf, keytag);
9932 trustkey = true;
9933 } else {
9934 dnssec_log(zone, ISC_LOG_INFO,
9935 "New key %d observed "
9936 "for zone '%s': "
9937 "starting 30-day "
9938 "acceptance timer",
9939 keytag, namebuf);
9940 }
9941 } else {
9942 /*
9943 * No previously known key, and the key is not
9944 * secure, so skip it.
9945 */
9946 continue;
9947 }
9948
9949 /* Delete old version */
9950 if (deletekey || !newkey) {
9951 CHECK(update_one_rr(kfetch->db, ver, &diff,
9952 DNS_DIFFOP_DEL, keyname, 0,
9953 &keydatarr));
9954 }
9955
9956 if (updatekey) {
9957 /* Set refresh timer */
9958 keydata.refresh = refresh_time(kfetch, false);
9959 dns_rdata_reset(&keydatarr);
9960 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9961 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9962 dns_rdatatype_keydata,
9963 &keydata, &keyb);
9964
9965 /* Insert updated version */
9966 CHECK(update_one_rr(kfetch->db, ver, &diff,
9967 DNS_DIFFOP_ADD, keyname, 0,
9968 &keydatarr));
9969 } else if (newkey) {
9970 /* Convert DNSKEY to KEYDATA */
9971 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9972 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9973 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
9974 NULL);
9975 keydata.addhd = initializing
9976 ? now : now + dns_zone_mkey_month;
9977 keydata.refresh = refresh_time(kfetch, false);
9978 dns_rdata_reset(&keydatarr);
9979 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9980 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9981 dns_rdatatype_keydata,
9982 &keydata, &keyb);
9983
9984 /* Insert into key zone */
9985 CHECK(update_one_rr(kfetch->db, ver, &diff,
9986 DNS_DIFFOP_ADD, keyname, 0,
9987 &keydatarr));
9988 }
9989
9990 if (trustkey) {
9991 /* Trust this key. */
9992 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9993 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9994 trust_key(zone, keyname, &dnskey, false, mctx);
9995 }
9996
9997 if (secure && !deletekey) {
9998 INSIST(newkey || updatekey);
9999 set_refreshkeytimer(zone, &keydata, now, false);
10000 }
10001 }
10002
10003 /*
10004 * RFC5011 says, "A trust point that has all of its trust anchors
10005 * revoked is considered deleted and is treated as if the trust
10006 * point was never configured." But if someone revoked their
10007 * active key before the standby was trusted, that would mean the
10008 * zone would suddenly be nonsecured. We avoid this by checking to
10009 * see if there's pending keydata. If so, we put a null key in
10010 * the security roots; then all queries to the zone will fail.
10011 */
10012 if (pending != 0) {
10013 fail_secure(zone, keyname);
10014 }
10015
10016 done:
10017 if (!ISC_LIST_EMPTY(diff.tuples)) {
10018 /* Write changes to journal file. */
10019 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
10020 zone->updatemethod));
10021 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10022 commit = true;
10023
10024 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10025 zone_needdump(zone, 30);
10026 } else if (result == ISC_R_NOMORE) {
10027 /*
10028 * If "updatekey" was true for all keys found in the DNSKEY
10029 * response and the previous update of those keys happened
10030 * during the same second (only possible if a key refresh was
10031 * externally triggered), it may happen that all relevant
10032 * update_one_rr() calls will return ISC_R_SUCCESS, but
10033 * diff.tuples will remain empty. Reset result to
10034 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
10035 */
10036 result = ISC_R_SUCCESS;
10037 }
10038
10039 failure:
10040 if (result != ISC_R_SUCCESS) {
10041 dnssec_log(zone, ISC_LOG_ERROR,
10042 "error during managed-keys processing (%s): "
10043 "DNSSEC validation may be at risk",
10044 isc_result_totext(result));
10045 }
10046 dns_diff_clear(&diff);
10047 if (ver != NULL) {
10048 dns_db_closeversion(kfetch->db, &ver, commit);
10049 }
10050
10051 cleanup:
10052 dns_db_detach(&kfetch->db);
10053
10054 INSIST(zone->irefs > 0);
10055 zone->irefs--;
10056 kfetch->zone = NULL;
10057
10058 if (dns_rdataset_isassociated(&kfetch->keydataset)) {
10059 dns_rdataset_disassociate(&kfetch->keydataset);
10060 }
10061 if (dns_rdataset_isassociated(&kfetch->dnskeyset)) {
10062 dns_rdataset_disassociate(&kfetch->dnskeyset);
10063 }
10064 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10065 dns_rdataset_disassociate(&kfetch->dnskeysigset);
10066 }
10067
10068 dns_name_free(keyname, mctx);
10069 isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
10070 isc_mem_detach(&mctx);
10071
10072 if (secroots != NULL) {
10073 dns_keytable_detach(&secroots);
10074 }
10075
10076 free_needed = exit_check(zone);
10077 UNLOCK_ZONE(zone);
10078 if (free_needed) {
10079 zone_free(zone);
10080 }
10081
10082 INSIST(ver == NULL);
10083 }
10084
10085 /*
10086 * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
10087 * records from the zone apex.
10088 */
10089 static void
10090 zone_refreshkeys(dns_zone_t *zone) {
10091 const char me[] = "zone_refreshkeys";
10092 isc_result_t result;
10093 dns_rriterator_t rrit;
10094 dns_db_t *db = NULL;
10095 dns_dbversion_t *ver = NULL;
10096 dns_diff_t diff;
10097 dns_rdata_t rdata = DNS_RDATA_INIT;
10098 dns_rdata_keydata_t kd;
10099 isc_stdtime_t now;
10100 bool commit = false;
10101 bool fetching = false, fetch_err = false;
10102 bool timerset = false;
10103
10104 ENTER;
10105 REQUIRE(zone->db != NULL);
10106
10107 isc_stdtime_get(&now);
10108
10109 LOCK_ZONE(zone);
10110 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10111 isc_time_settoepoch(&zone->refreshkeytime);
10112 UNLOCK_ZONE(zone);
10113 return;
10114 }
10115
10116 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10117 dns_db_attach(zone->db, &db);
10118 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10119
10120 dns_diff_init(zone->mctx, &diff);
10121
10122 CHECK(dns_db_newversion(db, &ver));
10123
10124 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
10125
10126 dns_rriterator_init(&rrit, db, ver, 0);
10127 for (result = dns_rriterator_first(&rrit);
10128 result == ISC_R_SUCCESS;
10129 result = dns_rriterator_nextrrset(&rrit))
10130 {
10131 isc_stdtime_t timer = 0xffffffff;
10132 dns_name_t *name = NULL, *kname = NULL;
10133 dns_rdataset_t *kdset = NULL;
10134 dns_keyfetch_t *kfetch;
10135 uint32_t ttl;
10136
10137 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
10138 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
10139 !dns_rdataset_isassociated(kdset))
10140 {
10141 continue;
10142 }
10143
10144 /*
10145 * Scan the stored keys looking for ones that need
10146 * removal or refreshing
10147 */
10148 for (result = dns_rdataset_first(kdset);
10149 result == ISC_R_SUCCESS;
10150 result = dns_rdataset_next(kdset))
10151 {
10152 dns_rdata_reset(&rdata);
10153 dns_rdataset_current(kdset, &rdata);
10154 result = dns_rdata_tostruct(&rdata, &kd, NULL);
10155 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10156
10157 /* Removal timer expired? */
10158 if (kd.removehd != 0 && kd.removehd < now) {
10159 CHECK(update_one_rr(db, ver, &diff,
10160 DNS_DIFFOP_DEL, name, ttl,
10161 &rdata));
10162 continue;
10163 }
10164
10165 /* Acceptance timer expired? */
10166 if (kd.addhd <= now) {
10167 timer = kd.addhd;
10168 }
10169
10170 /* Or do we just need to refresh the keyset? */
10171 if (timer > kd.refresh) {
10172 timer = kd.refresh;
10173 }
10174
10175 set_refreshkeytimer(zone, &kd, now, false);
10176 timerset = true;
10177 }
10178
10179 if (timer > now) {
10180 continue;
10181 }
10182
10183 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
10184 if (kfetch == NULL) {
10185 fetch_err = true;
10186 goto failure;
10187 }
10188
10189 zone->refreshkeycount++;
10190 kfetch->zone = zone;
10191 zone->irefs++;
10192 INSIST(zone->irefs != 0);
10193 kname = dns_fixedname_initname(&kfetch->name);
10194 dns_name_dup(name, zone->mctx, kname);
10195 dns_rdataset_init(&kfetch->dnskeyset);
10196 dns_rdataset_init(&kfetch->dnskeysigset);
10197 dns_rdataset_init(&kfetch->keydataset);
10198 dns_rdataset_clone(kdset, &kfetch->keydataset);
10199 kfetch->db = NULL;
10200 dns_db_attach(db, &kfetch->db);
10201 kfetch->fetch = NULL;
10202
10203 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
10204 char namebuf[DNS_NAME_FORMATSIZE];
10205 dns_name_format(kname, namebuf,
10206 sizeof(namebuf));
10207 dnssec_log(zone, ISC_LOG_DEBUG(3),
10208 "Creating key fetch in "
10209 "zone_refreshkeys() for '%s'",
10210 namebuf);
10211 }
10212
10213 /*
10214 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is
10215 * not set and the cache still holds a non-expired, validated
10216 * version of the RRset being queried for by the time the
10217 * response is received, the cached RRset will be passed to
10218 * keyfetch_done() instead of the one received in the response
10219 * as the latter will have a lower trust level due to not being
10220 * validated until keyfetch_done() is called.
10221 */
10222
10223 #ifdef ENABLE_AFL
10224 if (dns_fuzzing_resolver == false) {
10225 #endif
10226 result = dns_resolver_createfetch(zone->view->resolver,
10227 kname, dns_rdatatype_dnskey,
10228 NULL, NULL, NULL, NULL, 0,
10229 DNS_FETCHOPT_NOVALIDATE |
10230 DNS_FETCHOPT_UNSHARED |
10231 DNS_FETCHOPT_NOCACHED,
10232 0, NULL, zone->task,
10233 keyfetch_done, kfetch,
10234 &kfetch->dnskeyset,
10235 &kfetch->dnskeysigset,
10236 &kfetch->fetch);
10237 #ifdef ENABLE_AFL
10238 } else {
10239 result = ISC_R_FAILURE;
10240 }
10241 #endif
10242 if (result == ISC_R_SUCCESS) {
10243 fetching = true;
10244 } else {
10245 zone->refreshkeycount--;
10246 zone->irefs--;
10247 dns_db_detach(&kfetch->db);
10248 dns_rdataset_disassociate(&kfetch->keydataset);
10249 dns_name_free(kname, zone->mctx);
10250 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
10251 dnssec_log(zone, ISC_LOG_WARNING,
10252 "Failed to create fetch for DNSKEY update");
10253 fetch_err = true;
10254 }
10255 }
10256 if (!ISC_LIST_EMPTY(diff.tuples)) {
10257 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
10258 zone->updatemethod));
10259 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
10260 commit = true;
10261 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10262 zone_needdump(zone, 30);
10263 }
10264
10265 failure:
10266 if (fetch_err) {
10267 /*
10268 * Error during a key fetch; retry in an hour.
10269 */
10270 isc_time_t timenow, timethen;
10271 char timebuf[80];
10272
10273 TIME_NOW(&timenow);
10274 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
10275 zone->refreshkeytime = timethen;
10276 zone_settimer(zone, &timenow);
10277
10278 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
10279 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
10280 timebuf);
10281 } else if (!timerset) {
10282 isc_time_settoepoch(&zone->refreshkeytime);
10283 }
10284
10285 if (!fetching) {
10286 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10287 }
10288
10289 dns_diff_clear(&diff);
10290 if (ver != NULL) {
10291 dns_rriterator_destroy(&rrit);
10292 dns_db_closeversion(db, &ver, commit);
10293 }
10294 dns_db_detach(&db);
10295
10296 UNLOCK_ZONE(zone);
10297
10298 INSIST(ver == NULL);
10299 }
10300
10301 static void
10302 zone_maintenance(dns_zone_t *zone) {
10303 const char me[] = "zone_maintenance";
10304 isc_time_t now;
10305 isc_result_t result;
10306 bool dumping, load_pending;
10307
10308 REQUIRE(DNS_ZONE_VALID(zone));
10309 ENTER;
10310
10311 /*
10312 * Are we pending load/reload?
10313 */
10314 LOCK_ZONE(zone);
10315 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
10316 UNLOCK_ZONE(zone);
10317
10318 if (load_pending) {
10319 return;
10320 }
10321
10322 /*
10323 * Configuring the view of this zone may have
10324 * failed, for example because the config file
10325 * had a syntax error. In that case, the view
10326 * adb or resolver will be NULL, and we had better not try
10327 * to do further maintenance on it.
10328 */
10329 if (zone->view == NULL || zone->view->adb == NULL)
10330 return;
10331
10332 TIME_NOW(&now);
10333
10334 /*
10335 * Expire check.
10336 */
10337 switch (zone->type) {
10338 case dns_zone_redirect:
10339 if (zone->masters == NULL)
10340 break;
10341 /* FALLTHROUGH */
10342 case dns_zone_slave:
10343 case dns_zone_mirror:
10344 case dns_zone_stub:
10345 LOCK_ZONE(zone);
10346 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
10347 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10348 zone_expire(zone);
10349 zone->refreshtime = now;
10350 }
10351 UNLOCK_ZONE(zone);
10352 break;
10353 default:
10354 break;
10355 }
10356
10357 /*
10358 * Up to date check.
10359 */
10360 switch (zone->type) {
10361 case dns_zone_redirect:
10362 if (zone->masters == NULL)
10363 break;
10364 /* FALLTHROUGH */
10365 case dns_zone_slave:
10366 case dns_zone_mirror:
10367 case dns_zone_stub:
10368 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
10369 isc_time_compare(&now, &zone->refreshtime) >= 0)
10370 dns_zone_refresh(zone);
10371 break;
10372 default:
10373 break;
10374 }
10375
10376 /*
10377 * Slaves send notifies before backing up to disk, masters after.
10378 */
10379 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror) &&
10380 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10381 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
10382 isc_time_compare(&now, &zone->notifytime) >= 0)
10383 zone_notify(zone, &now);
10384
10385 /*
10386 * Do we need to consolidate the backing store?
10387 */
10388 switch (zone->type) {
10389 case dns_zone_master:
10390 case dns_zone_slave:
10391 case dns_zone_mirror:
10392 case dns_zone_key:
10393 case dns_zone_redirect:
10394 case dns_zone_stub:
10395 LOCK_ZONE(zone);
10396 if (zone->masterfile != NULL &&
10397 isc_time_compare(&now, &zone->dumptime) >= 0 &&
10398 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10399 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
10400 dumping = was_dumping(zone);
10401 } else
10402 dumping = true;
10403 UNLOCK_ZONE(zone);
10404 if (!dumping) {
10405 result = zone_dump(zone, true); /* task locked */
10406 if (result != ISC_R_SUCCESS)
10407 dns_zone_log(zone, ISC_LOG_WARNING,
10408 "dump failed: %s",
10409 dns_result_totext(result));
10410 }
10411 break;
10412 default:
10413 break;
10414 }
10415
10416 /*
10417 * Master/redirect zones send notifies now, if needed
10418 */
10419 switch (zone->type) {
10420 case dns_zone_master:
10421 case dns_zone_redirect:
10422 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10423 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
10424 isc_time_compare(&now, &zone->notifytime) >= 0)
10425 zone_notify(zone, &now);
10426 default:
10427 break;
10428 }
10429
10430 /*
10431 * Do we need to refresh keys?
10432 */
10433 switch (zone->type) {
10434 case dns_zone_key:
10435 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
10436 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10437 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10438 zone_refreshkeys(zone);
10439 }
10440 }
10441 break;
10442 case dns_zone_master:
10443 if (!isc_time_isepoch(&zone->refreshkeytime) &&
10444 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
10445 zone->rss_event == NULL)
10446 zone_rekey(zone);
10447 default:
10448 break;
10449 }
10450
10451 switch (zone->type) {
10452 case dns_zone_master:
10453 case dns_zone_redirect:
10454 case dns_zone_slave:
10455 /*
10456 * Do we need to sign/resign some RRsets?
10457 */
10458 if (zone->rss_event != NULL)
10459 break;
10460 if (!isc_time_isepoch(&zone->signingtime) &&
10461 isc_time_compare(&now, &zone->signingtime) >= 0)
10462 zone_sign(zone);
10463 else if (!isc_time_isepoch(&zone->resigntime) &&
10464 isc_time_compare(&now, &zone->resigntime) >= 0)
10465 zone_resigninc(zone);
10466 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
10467 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
10468 zone_nsec3chain(zone);
10469 /*
10470 * Do we need to issue a key expiry warning?
10471 */
10472 if (!isc_time_isepoch(&zone->keywarntime) &&
10473 isc_time_compare(&now, &zone->keywarntime) >= 0)
10474 set_key_expiry_warning(zone, zone->key_expiry,
10475 isc_time_seconds(&now));
10476 break;
10477
10478 default:
10479 break;
10480 }
10481 zone_settimer(zone, &now);
10482 }
10483
10484 void
10485 dns_zone_markdirty(dns_zone_t *zone) {
10486 uint32_t serial;
10487 isc_result_t result = ISC_R_SUCCESS;
10488 dns_zone_t *secure = NULL;
10489
10490 /*
10491 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
10492 * could result in a deadlock due to a LOR so we will spin if we
10493 * can't obtain the both locks.
10494 */
10495 again:
10496 LOCK_ZONE(zone);
10497 if (zone->type == dns_zone_master) {
10498 if (inline_raw(zone)) {
10499 unsigned int soacount;
10500 secure = zone->secure;
10501 INSIST(secure != zone);
10502 TRYLOCK_ZONE(result, secure);
10503 if (result != ISC_R_SUCCESS) {
10504 UNLOCK_ZONE(zone);
10505 secure = NULL;
10506 isc_thread_yield();
10507 goto again;
10508 }
10509
10510 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10511 if (zone->db != NULL) {
10512 result = zone_get_from_db(zone, zone->db, NULL,
10513 &soacount, &serial,
10514 NULL, NULL, NULL,
10515 NULL, NULL);
10516 } else
10517 result = DNS_R_NOTLOADED;
10518 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10519 if (result == ISC_R_SUCCESS && soacount > 0U)
10520 zone_send_secureserial(zone, serial);
10521 }
10522
10523 /* XXXMPA make separate call back */
10524 if (result == ISC_R_SUCCESS)
10525 set_resigntime(zone);
10526 }
10527 if (secure != NULL)
10528 UNLOCK_ZONE(secure);
10529 zone_needdump(zone, DNS_DUMP_DELAY);
10530 UNLOCK_ZONE(zone);
10531 }
10532
10533 void
10534 dns_zone_expire(dns_zone_t *zone) {
10535 REQUIRE(DNS_ZONE_VALID(zone));
10536
10537 LOCK_ZONE(zone);
10538 zone_expire(zone);
10539 UNLOCK_ZONE(zone);
10540 }
10541
10542 static void
10543 zone_expire(dns_zone_t *zone) {
10544 /*
10545 * 'zone' locked by caller.
10546 */
10547
10548 REQUIRE(LOCKED_ZONE(zone));
10549
10550 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
10551
10552 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
10553 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
10554 zone->retry = DNS_ZONE_DEFAULTRETRY;
10555 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10556 zone_unload(zone);
10557 }
10558
10559 void
10560 dns_zone_refresh(dns_zone_t *zone) {
10561 isc_interval_t i;
10562 uint32_t oldflags;
10563 unsigned int j;
10564 isc_result_t result;
10565
10566 REQUIRE(DNS_ZONE_VALID(zone));
10567
10568 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10569 return;
10570
10571 /*
10572 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
10573 * in progress at a time.
10574 */
10575
10576 LOCK_ZONE(zone);
10577 oldflags = zone->flags;
10578 if (zone->masterscnt == 0) {
10579 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
10580 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
10581 dns_zone_log(zone, ISC_LOG_ERROR,
10582 "cannot refresh: no masters");
10583 goto unlock;
10584 }
10585 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
10586 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10587 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10588 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
10589 goto unlock;
10590
10591 /*
10592 * Set the next refresh time as if refresh check has failed.
10593 * Setting this to the retry time will do that. XXXMLG
10594 * If we are successful it will be reset using zone->refresh.
10595 */
10596 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
10597 0);
10598 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
10599 if (result != ISC_R_SUCCESS)
10600 dns_zone_log(zone, ISC_LOG_WARNING,
10601 "isc_time_nowplusinterval() failed: %s",
10602 dns_result_totext(result));
10603
10604 /*
10605 * When lacking user-specified timer values from the SOA,
10606 * do exponential backoff of the retry time up to a
10607 * maximum of six hours.
10608 */
10609 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
10610 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
10611
10612 zone->curmaster = 0;
10613 for (j = 0; j < zone->masterscnt; j++)
10614 zone->mastersok[j] = false;
10615 /* initiate soa query */
10616 queue_soa_query(zone);
10617 unlock:
10618 UNLOCK_ZONE(zone);
10619 }
10620
10621 static void
10622 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
10623 isc_result_t result;
10624 int32_t journalsize;
10625 dns_dbversion_t *ver = NULL;
10626 uint64_t dbsize;
10627
10628 INSIST(LOCKED_ZONE(zone));
10629 if (inline_raw(zone))
10630 INSIST(LOCKED_ZONE(zone->secure));
10631
10632 journalsize = zone->journalsize;
10633 if (journalsize == -1) {
10634 journalsize = DNS_JOURNAL_SIZE_MAX;
10635 dns_db_currentversion(db, &ver);
10636 result = dns_db_getsize(db, ver, NULL, &dbsize);
10637 dns_db_closeversion(db, &ver, false);
10638 if (result != ISC_R_SUCCESS) {
10639 dns_zone_log(zone, ISC_LOG_ERROR,
10640 "zone_journal_compact: "
10641 "could not get zone size: %s",
10642 isc_result_totext(result));
10643 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
10644 journalsize = (int32_t)dbsize * 2;
10645 }
10646 }
10647 zone_debuglog(zone, "zone_journal_compact", 1,
10648 "target journal size %d", journalsize);
10649 result = dns_journal_compact(zone->mctx, zone->journal,
10650 serial, journalsize);
10651 switch (result) {
10652 case ISC_R_SUCCESS:
10653 case ISC_R_NOSPACE:
10654 case ISC_R_NOTFOUND:
10655 dns_zone_log(zone, ISC_LOG_DEBUG(3),
10656 "dns_journal_compact: %s",
10657 dns_result_totext(result));
10658 break;
10659 default:
10660 dns_zone_log(zone, ISC_LOG_ERROR,
10661 "dns_journal_compact failed: %s",
10662 dns_result_totext(result));
10663 break;
10664 }
10665 }
10666
10667 isc_result_t
10668 dns_zone_flush(dns_zone_t *zone) {
10669 isc_result_t result = ISC_R_SUCCESS;
10670 bool dumping;
10671
10672 REQUIRE(DNS_ZONE_VALID(zone));
10673
10674 LOCK_ZONE(zone);
10675 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
10676 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10677 zone->masterfile != NULL) {
10678 result = ISC_R_ALREADYRUNNING;
10679 dumping = was_dumping(zone);
10680 } else
10681 dumping = true;
10682 UNLOCK_ZONE(zone);
10683 if (!dumping)
10684 result = zone_dump(zone, true); /* Unknown task. */
10685 return (result);
10686 }
10687
10688 isc_result_t
10689 dns_zone_dump(dns_zone_t *zone) {
10690 isc_result_t result = ISC_R_ALREADYRUNNING;
10691 bool dumping;
10692
10693 REQUIRE(DNS_ZONE_VALID(zone));
10694
10695 LOCK_ZONE(zone);
10696 dumping = was_dumping(zone);
10697 UNLOCK_ZONE(zone);
10698 if (!dumping)
10699 result = zone_dump(zone, false); /* Unknown task. */
10700 return (result);
10701 }
10702
10703 static void
10704 zone_needdump(dns_zone_t *zone, unsigned int delay) {
10705 const char me[] = "zone_needdump";
10706 isc_time_t dumptime;
10707 isc_time_t now;
10708
10709 /*
10710 * 'zone' locked by caller
10711 */
10712
10713 REQUIRE(DNS_ZONE_VALID(zone));
10714 REQUIRE(LOCKED_ZONE(zone));
10715 ENTER;
10716
10717 /*
10718 * Do we have a place to dump to and are we loaded?
10719 */
10720 if (zone->masterfile == NULL ||
10721 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
10722 return;
10723
10724 TIME_NOW(&now);
10725 /* add some noise */
10726 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
10727
10728 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10729 if (isc_time_isepoch(&zone->dumptime) ||
10730 isc_time_compare(&zone->dumptime, &dumptime) > 0)
10731 zone->dumptime = dumptime;
10732 if (zone->task != NULL)
10733 zone_settimer(zone, &now);
10734 }
10735
10736 static void
10737 dump_done(void *arg, isc_result_t result) {
10738 const char me[] = "dump_done";
10739 dns_zone_t *zone = arg;
10740 dns_zone_t *secure = NULL;
10741 dns_db_t *db;
10742 dns_dbversion_t *version;
10743 bool again = false;
10744 bool compact = false;
10745 uint32_t serial;
10746 isc_result_t tresult;
10747
10748 REQUIRE(DNS_ZONE_VALID(zone));
10749
10750 ENTER;
10751
10752 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
10753 /*
10754 * We don't own these, zone->dctx must stay valid.
10755 */
10756 db = dns_dumpctx_db(zone->dctx);
10757 version = dns_dumpctx_version(zone->dctx);
10758 tresult = dns_db_getsoaserial(db, version, &serial);
10759
10760 /*
10761 * Handle lock order inversion.
10762 */
10763 again:
10764 LOCK_ZONE(zone);
10765 if (inline_raw(zone)) {
10766 secure = zone->secure;
10767 INSIST(secure != zone);
10768 TRYLOCK_ZONE(result, secure);
10769 if (result != ISC_R_SUCCESS) {
10770 UNLOCK_ZONE(zone);
10771 secure = NULL;
10772 isc_thread_yield();
10773 goto again;
10774 }
10775 }
10776
10777 /*
10778 * If there is a secure version of this zone
10779 * use its serial if it is less than ours.
10780 */
10781 if (tresult == ISC_R_SUCCESS && secure != NULL) {
10782 uint32_t sserial;
10783 isc_result_t mresult;
10784
10785 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
10786 if (secure->db != NULL) {
10787 mresult = dns_db_getsoaserial(zone->secure->db,
10788 NULL, &sserial);
10789 if (mresult == ISC_R_SUCCESS &&
10790 isc_serial_lt(sserial, serial))
10791 serial = sserial;
10792 }
10793 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
10794 }
10795 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
10796 dns_db_t *zdb = NULL;
10797 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
10798 zone_journal_compact(zone, zdb, serial);
10799 dns_db_detach(&zdb);
10800 }
10801 } else if (tresult == ISC_R_SUCCESS) {
10802 compact = true;
10803 zone->compact_serial = serial;
10804 }
10805 if (secure != NULL)
10806 UNLOCK_ZONE(secure);
10807 UNLOCK_ZONE(zone);
10808 }
10809
10810 LOCK_ZONE(zone);
10811 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
10812 if (compact)
10813 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
10814 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
10815 /*
10816 * Try again in a short while.
10817 */
10818 zone_needdump(zone, DNS_DUMP_DELAY);
10819 } else if (result == ISC_R_SUCCESS &&
10820 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
10821 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10822 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10823 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10824 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
10825 isc_time_settoepoch(&zone->dumptime);
10826 again = true;
10827 } else if (result == ISC_R_SUCCESS)
10828 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
10829
10830 if (zone->dctx != NULL)
10831 dns_dumpctx_detach(&zone->dctx);
10832 zonemgr_putio(&zone->writeio);
10833 UNLOCK_ZONE(zone);
10834 if (again)
10835 (void)zone_dump(zone, false);
10836 dns_zone_idetach(&zone);
10837 }
10838
10839 static isc_result_t
10840 zone_dump(dns_zone_t *zone, bool compact) {
10841 const char me[] = "zone_dump";
10842 isc_result_t result;
10843 dns_dbversion_t *version = NULL;
10844 bool again;
10845 dns_db_t *db = NULL;
10846 char *masterfile = NULL;
10847 dns_masterformat_t masterformat = dns_masterformat_none;
10848
10849 /*
10850 * 'compact' MUST only be set if we are task locked.
10851 */
10852
10853 REQUIRE(DNS_ZONE_VALID(zone));
10854 ENTER;
10855
10856 redo:
10857 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10858 if (zone->db != NULL)
10859 dns_db_attach(zone->db, &db);
10860 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10861 LOCK_ZONE(zone);
10862 if (zone->masterfile != NULL) {
10863 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
10864 masterformat = zone->masterformat;
10865 }
10866 UNLOCK_ZONE(zone);
10867 if (db == NULL) {
10868 result = DNS_R_NOTLOADED;
10869 goto fail;
10870 }
10871 if (masterfile == NULL) {
10872 result = DNS_R_NOMASTERFILE;
10873 goto fail;
10874 }
10875
10876 if (compact && zone->type != dns_zone_stub) {
10877 dns_zone_t *dummy = NULL;
10878 LOCK_ZONE(zone);
10879 zone_iattach(zone, &dummy);
10880 result = zonemgr_getio(zone->zmgr, false, zone->task,
10881 zone_gotwritehandle, zone,
10882 &zone->writeio);
10883 if (result != ISC_R_SUCCESS)
10884 zone_idetach(&dummy);
10885 else
10886 result = DNS_R_CONTINUE;
10887 UNLOCK_ZONE(zone);
10888 } else {
10889 const dns_master_style_t *output_style;
10890
10891 dns_masterrawheader_t rawdata;
10892 dns_db_currentversion(db, &version);
10893 dns_master_initrawheader(&rawdata);
10894 if (inline_secure(zone))
10895 get_raw_serial(zone->raw, &rawdata);
10896 if (zone->type == dns_zone_key)
10897 output_style = &dns_master_style_keyzone;
10898 else
10899 output_style = &dns_master_style_default;
10900 result = dns_master_dump(zone->mctx, db, version,
10901 output_style, masterfile,
10902 masterformat, &rawdata);
10903 dns_db_closeversion(db, &version, false);
10904 }
10905 fail:
10906 if (db != NULL)
10907 dns_db_detach(&db);
10908 if (masterfile != NULL)
10909 isc_mem_free(zone->mctx, masterfile);
10910 masterfile = NULL;
10911
10912 if (result == DNS_R_CONTINUE)
10913 return (ISC_R_SUCCESS); /* XXXMPA */
10914
10915 again = false;
10916 LOCK_ZONE(zone);
10917 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
10918 if (result != ISC_R_SUCCESS) {
10919 /*
10920 * Try again in a short while.
10921 */
10922 zone_needdump(zone, DNS_DUMP_DELAY);
10923 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
10924 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10925 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10926 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10927 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
10928 isc_time_settoepoch(&zone->dumptime);
10929 again = true;
10930 } else
10931 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
10932 UNLOCK_ZONE(zone);
10933 if (again)
10934 goto redo;
10935
10936 return (result);
10937 }
10938
10939 static isc_result_t
10940 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
10941 dns_masterformat_t format, const uint32_t rawversion)
10942 {
10943 isc_result_t result;
10944 dns_dbversion_t *version = NULL;
10945 dns_db_t *db = NULL;
10946 dns_masterrawheader_t rawdata;
10947
10948 REQUIRE(DNS_ZONE_VALID(zone));
10949
10950 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10951 if (zone->db != NULL)
10952 dns_db_attach(zone->db, &db);
10953 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10954 if (db == NULL)
10955 return (DNS_R_NOTLOADED);
10956
10957 dns_db_currentversion(db, &version);
10958 dns_master_initrawheader(&rawdata);
10959 if (rawversion == 0)
10960 rawdata.flags |= DNS_MASTERRAW_COMPAT;
10961 else if (inline_secure(zone))
10962 get_raw_serial(zone->raw, &rawdata);
10963 else if (zone->sourceserialset) {
10964 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
10965 rawdata.sourceserial = zone->sourceserial;
10966 }
10967 result = dns_master_dumptostream(zone->mctx, db, version, style,
10968 format, &rawdata, fd);
10969 dns_db_closeversion(db, &version, false);
10970 dns_db_detach(&db);
10971 return (result);
10972 }
10973
10974 isc_result_t
10975 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
10976 const dns_master_style_t *style,
10977 const uint32_t rawversion)
10978 {
10979 return (dumptostream(zone, fd, style, format, rawversion));
10980 }
10981
10982 void
10983 dns_zone_unload(dns_zone_t *zone) {
10984 REQUIRE(DNS_ZONE_VALID(zone));
10985
10986 LOCK_ZONE(zone);
10987 zone_unload(zone);
10988 UNLOCK_ZONE(zone);
10989 }
10990
10991 static void
10992 notify_cancel(dns_zone_t *zone) {
10993 dns_notify_t *notify;
10994
10995 /*
10996 * 'zone' locked by caller.
10997 */
10998
10999 REQUIRE(LOCKED_ZONE(zone));
11000
11001 for (notify = ISC_LIST_HEAD(zone->notifies);
11002 notify != NULL;
11003 notify = ISC_LIST_NEXT(notify, link)) {
11004 if (notify->find != NULL)
11005 dns_adb_cancelfind(notify->find);
11006 if (notify->request != NULL)
11007 dns_request_cancel(notify->request);
11008 }
11009 }
11010
11011 static void
11012 forward_cancel(dns_zone_t *zone) {
11013 dns_forward_t *forward;
11014
11015 /*
11016 * 'zone' locked by caller.
11017 */
11018
11019 REQUIRE(LOCKED_ZONE(zone));
11020
11021 for (forward = ISC_LIST_HEAD(zone->forwards);
11022 forward != NULL;
11023 forward = ISC_LIST_NEXT(forward, link)) {
11024 if (forward->request != NULL)
11025 dns_request_cancel(forward->request);
11026 }
11027 }
11028
11029 static void
11030 zone_unload(dns_zone_t *zone) {
11031 /*
11032 * 'zone' locked by caller.
11033 */
11034
11035 REQUIRE(LOCKED_ZONE(zone));
11036
11037 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11038 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11039 if (zone->writeio != NULL)
11040 zonemgr_cancelio(zone->writeio);
11041
11042 if (zone->dctx != NULL)
11043 dns_dumpctx_cancel(zone->dctx);
11044 }
11045 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11046 zone_detachdb(zone);
11047 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11048 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
11049 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11050
11051 if (zone->type == dns_zone_mirror) {
11052 dns_zone_log(zone, ISC_LOG_INFO,
11053 "mirror zone is no longer in use; "
11054 "reverting to normal recursion");
11055 }
11056 }
11057
11058 void
11059 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
11060 REQUIRE(DNS_ZONE_VALID(zone));
11061 REQUIRE(val > 0);
11062
11063 zone->minrefresh = val;
11064 }
11065
11066 void
11067 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
11068 REQUIRE(DNS_ZONE_VALID(zone));
11069 REQUIRE(val > 0);
11070
11071 zone->maxrefresh = val;
11072 }
11073
11074 void
11075 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
11076 REQUIRE(DNS_ZONE_VALID(zone));
11077 REQUIRE(val > 0);
11078
11079 zone->minretry = val;
11080 }
11081
11082 void
11083 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
11084 REQUIRE(DNS_ZONE_VALID(zone));
11085 REQUIRE(val > 0);
11086
11087 zone->maxretry = val;
11088 }
11089
11090 uint32_t
11091 dns_zone_getmaxrecords(dns_zone_t *zone) {
11092 REQUIRE(DNS_ZONE_VALID(zone));
11093
11094 return (zone->maxrecords);
11095 }
11096
11097 void
11098 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
11099 REQUIRE(DNS_ZONE_VALID(zone));
11100
11101 zone->maxrecords = val;
11102 }
11103
11104 static bool
11105 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
11106 isc_sockaddr_t *addr, dns_tsigkey_t *key)
11107 {
11108 dns_notify_t *notify;
11109 dns_zonemgr_t *zmgr;
11110 isc_result_t result;
11111
11112 for (notify = ISC_LIST_HEAD(zone->notifies);
11113 notify != NULL;
11114 notify = ISC_LIST_NEXT(notify, link)) {
11115 if (notify->request != NULL)
11116 continue;
11117 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
11118 dns_name_equal(name, ¬ify->ns))
11119 goto requeue;
11120 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
11121 notify->key == key)
11122 goto requeue;
11123 }
11124 return (false);
11125
11126 requeue:
11127 /*
11128 * If we are enqueued on the startup ratelimiter and this is
11129 * not a startup notify, re-enqueue on the normal notify
11130 * ratelimiter.
11131 */
11132 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
11133 (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
11134 zmgr = notify->zone->zmgr;
11135 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
11136 notify->event);
11137 if (result != ISC_R_SUCCESS)
11138 return (true);
11139
11140 notify->flags &= ~DNS_NOTIFY_STARTUP;
11141 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
11142 notify->zone->task,
11143 ¬ify->event);
11144 if (result != ISC_R_SUCCESS) {
11145 isc_event_free(¬ify->event);
11146 return (false);
11147 }
11148 }
11149
11150 return (true);
11151 }
11152
11153 static bool
11154 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
11155 dns_tsigkey_t *key = NULL;
11156 isc_sockaddr_t src;
11157 isc_sockaddr_t any;
11158 bool isself;
11159 isc_netaddr_t dstaddr;
11160 isc_result_t result;
11161
11162 if (zone->view == NULL || zone->isself == NULL)
11163 return (false);
11164
11165 switch (isc_sockaddr_pf(dst)) {
11166 case PF_INET:
11167 src = zone->notifysrc4;
11168 isc_sockaddr_any(&any);
11169 break;
11170 case PF_INET6:
11171 src = zone->notifysrc6;
11172 isc_sockaddr_any6(&any);
11173 break;
11174 default:
11175 return (false);
11176 }
11177
11178 /*
11179 * When sending from any the kernel will assign a source address
11180 * that matches the destination address.
11181 */
11182 if (isc_sockaddr_eqaddr(&any, &src))
11183 src = *dst;
11184
11185 isc_netaddr_fromsockaddr(&dstaddr, dst);
11186 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
11187 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
11188 return (false);
11189 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
11190 zone->isselfarg);
11191 if (key != NULL)
11192 dns_tsigkey_detach(&key);
11193 return (isself);
11194 }
11195
11196 static void
11197 notify_destroy(dns_notify_t *notify, bool locked) {
11198 isc_mem_t *mctx;
11199
11200 REQUIRE(DNS_NOTIFY_VALID(notify));
11201
11202 if (notify->zone != NULL) {
11203 if (!locked)
11204 LOCK_ZONE(notify->zone);
11205 REQUIRE(LOCKED_ZONE(notify->zone));
11206 if (ISC_LINK_LINKED(notify, link))
11207 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
11208 if (!locked)
11209 UNLOCK_ZONE(notify->zone);
11210 if (locked)
11211 zone_idetach(¬ify->zone);
11212 else
11213 dns_zone_idetach(¬ify->zone);
11214 }
11215 if (notify->find != NULL)
11216 dns_adb_destroyfind(¬ify->find);
11217 if (notify->request != NULL)
11218 dns_request_destroy(¬ify->request);
11219 if (dns_name_dynamic(¬ify->ns))
11220 dns_name_free(¬ify->ns, notify->mctx);
11221 if (notify->key != NULL)
11222 dns_tsigkey_detach(¬ify->key);
11223 mctx = notify->mctx;
11224 isc_mem_put(notify->mctx, notify, sizeof(*notify));
11225 isc_mem_detach(&mctx);
11226 }
11227
11228 static isc_result_t
11229 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
11230 dns_notify_t *notify;
11231
11232 REQUIRE(notifyp != NULL && *notifyp == NULL);
11233
11234 notify = isc_mem_get(mctx, sizeof(*notify));
11235 if (notify == NULL)
11236 return (ISC_R_NOMEMORY);
11237
11238 notify->mctx = NULL;
11239 isc_mem_attach(mctx, ¬ify->mctx);
11240 notify->flags = flags;
11241 notify->zone = NULL;
11242 notify->find = NULL;
11243 notify->request = NULL;
11244 notify->key = NULL;
11245 notify->event = NULL;
11246 isc_sockaddr_any(¬ify->dst);
11247 dns_name_init(¬ify->ns, NULL);
11248 ISC_LINK_INIT(notify, link);
11249 notify->magic = NOTIFY_MAGIC;
11250 *notifyp = notify;
11251 return (ISC_R_SUCCESS);
11252 }
11253
11254 /*
11255 * XXXAG should check for DNS_ZONEFLG_EXITING
11256 */
11257 static void
11258 process_adb_event(isc_task_t *task, isc_event_t *ev) {
11259 dns_notify_t *notify;
11260 isc_eventtype_t result;
11261
11262 UNUSED(task);
11263
11264 notify = ev->ev_arg;
11265 REQUIRE(DNS_NOTIFY_VALID(notify));
11266 INSIST(task == notify->zone->task);
11267 result = ev->ev_type;
11268 isc_event_free(&ev);
11269 if (result == DNS_EVENT_ADBMOREADDRESSES) {
11270 dns_adb_destroyfind(¬ify->find);
11271 notify_find_address(notify);
11272 return;
11273 }
11274 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
11275 LOCK_ZONE(notify->zone);
11276 notify_send(notify);
11277 UNLOCK_ZONE(notify->zone);
11278 }
11279 notify_destroy(notify, false);
11280 }
11281
11282 static void
11283 notify_find_address(dns_notify_t *notify) {
11284 isc_result_t result;
11285 unsigned int options;
11286
11287 REQUIRE(DNS_NOTIFY_VALID(notify));
11288 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
11289 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
11290
11291 if (notify->zone->view->adb == NULL)
11292 goto destroy;
11293
11294 result = dns_adb_createfind(notify->zone->view->adb,
11295 notify->zone->task,
11296 process_adb_event, notify,
11297 ¬ify->ns, dns_rootname, 0,
11298 options, 0, NULL,
11299 notify->zone->view->dstport,
11300 0, NULL, ¬ify->find);
11301
11302 /* Something failed? */
11303 if (result != ISC_R_SUCCESS)
11304 goto destroy;
11305
11306 /* More addresses pending? */
11307 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
11308 return;
11309
11310 /* We have as many addresses as we can get. */
11311 LOCK_ZONE(notify->zone);
11312 notify_send(notify);
11313 UNLOCK_ZONE(notify->zone);
11314
11315 destroy:
11316 notify_destroy(notify, false);
11317 }
11318
11319
11320 static isc_result_t
11321 notify_send_queue(dns_notify_t *notify, bool startup) {
11322 isc_event_t *e;
11323 isc_result_t result;
11324
11325 INSIST(notify->event == NULL);
11326 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
11327 notify_send_toaddr, notify, sizeof(isc_event_t));
11328 if (e == NULL)
11329 return (ISC_R_NOMEMORY);
11330 if (startup)
11331 notify->event = e;
11332 e->ev_arg = notify;
11333 e->ev_sender = NULL;
11334 result = isc_ratelimiter_enqueue(startup
11335 ? notify->zone->zmgr->startupnotifyrl
11336 : notify->zone->zmgr->notifyrl,
11337 notify->zone->task, &e);
11338 if (result != ISC_R_SUCCESS) {
11339 isc_event_free(&e);
11340 notify->event = NULL;
11341 }
11342 return (result);
11343 }
11344
11345 static void
11346 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
11347 dns_notify_t *notify;
11348 isc_result_t result;
11349 dns_message_t *message = NULL;
11350 isc_netaddr_t dstip;
11351 dns_tsigkey_t *key = NULL;
11352 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11353 isc_sockaddr_t src;
11354 unsigned int options, timeout;
11355 bool have_notifysource = false;
11356 bool have_notifydscp = false;
11357 isc_dscp_t dscp = -1;
11358
11359 notify = event->ev_arg;
11360 REQUIRE(DNS_NOTIFY_VALID(notify));
11361
11362 UNUSED(task);
11363
11364 LOCK_ZONE(notify->zone);
11365
11366 notify->event = NULL;
11367
11368 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
11369 result = ISC_R_CANCELED;
11370 goto cleanup;
11371 }
11372
11373 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
11374 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
11375 notify->zone->view->requestmgr == NULL ||
11376 notify->zone->db == NULL) {
11377 result = ISC_R_CANCELED;
11378 goto cleanup;
11379 }
11380
11381 /*
11382 * The raw IPv4 address should also exist. Don't send to the
11383 * mapped form.
11384 */
11385 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
11386 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr)) {
11387 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
11388 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11389 "notify: ignoring IPv6 mapped IPV4 address: %s",
11390 addrbuf);
11391 result = ISC_R_CANCELED;
11392 goto cleanup;
11393 }
11394
11395 result = notify_createmessage(notify->zone, notify->flags, &message);
11396 if (result != ISC_R_SUCCESS)
11397 goto cleanup;
11398
11399 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
11400 if (notify->key != NULL) {
11401 /* Transfer ownership of key */
11402 key = notify->key;
11403 notify->key = NULL;
11404 } else {
11405 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
11406 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
11407 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11408 notify_log(notify->zone, ISC_LOG_ERROR,
11409 "NOTIFY to %s not sent. "
11410 "Peer TSIG key lookup failure.", addrbuf);
11411 goto cleanup_message;
11412 }
11413 }
11414
11415 /* XXX: should we log the tsig key too? */
11416 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
11417 addrbuf);
11418 options = 0;
11419 if (notify->zone->view->peers != NULL) {
11420 dns_peer_t *peer = NULL;
11421 bool usetcp = false;
11422 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
11423 &dstip, &peer);
11424 if (result == ISC_R_SUCCESS) {
11425 result = dns_peer_getnotifysource(peer, &src);
11426 if (result == ISC_R_SUCCESS)
11427 have_notifysource = true;
11428 dns_peer_getnotifydscp(peer, &dscp);
11429 if (dscp != -1)
11430 have_notifydscp = true;
11431 result = dns_peer_getforcetcp(peer, &usetcp);
11432 if (result == ISC_R_SUCCESS && usetcp)
11433 options |= DNS_FETCHOPT_TCP;
11434 }
11435 }
11436 switch (isc_sockaddr_pf(¬ify->dst)) {
11437 case PF_INET:
11438 if (!have_notifysource)
11439 src = notify->zone->notifysrc4;
11440 if (!have_notifydscp)
11441 dscp = notify->zone->notifysrc4dscp;
11442 break;
11443 case PF_INET6:
11444 if (!have_notifysource)
11445 src = notify->zone->notifysrc6;
11446 if (!have_notifydscp)
11447 dscp = notify->zone->notifysrc6dscp;
11448 break;
11449 default:
11450 result = ISC_R_NOTIMPLEMENTED;
11451 goto cleanup_key;
11452 }
11453 timeout = 15;
11454 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
11455 timeout = 30;
11456 result = dns_request_createvia(notify->zone->view->requestmgr,
11457 message, &src, ¬ify->dst, dscp,
11458 options, key, timeout * 3, timeout,
11459 0, notify->zone->task, notify_done,
11460 notify, ¬ify->request);
11461 if (result == ISC_R_SUCCESS) {
11462 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
11463 inc_stats(notify->zone,
11464 dns_zonestatscounter_notifyoutv4);
11465 } else {
11466 inc_stats(notify->zone,
11467 dns_zonestatscounter_notifyoutv6);
11468 }
11469 }
11470
11471 cleanup_key:
11472 if (key != NULL)
11473 dns_tsigkey_detach(&key);
11474 cleanup_message:
11475 dns_message_destroy(&message);
11476 cleanup:
11477 UNLOCK_ZONE(notify->zone);
11478 isc_event_free(&event);
11479 if (result != ISC_R_SUCCESS)
11480 notify_destroy(notify, false);
11481 }
11482
11483 static void
11484 notify_send(dns_notify_t *notify) {
11485 dns_adbaddrinfo_t *ai;
11486 isc_sockaddr_t dst;
11487 isc_result_t result;
11488 dns_notify_t *newnotify = NULL;
11489 unsigned int flags;
11490 bool startup;
11491
11492 /*
11493 * Zone lock held by caller.
11494 */
11495 REQUIRE(DNS_NOTIFY_VALID(notify));
11496 REQUIRE(LOCKED_ZONE(notify->zone));
11497
11498 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING))
11499 return;
11500
11501 for (ai = ISC_LIST_HEAD(notify->find->list);
11502 ai != NULL;
11503 ai = ISC_LIST_NEXT(ai, publink)) {
11504 dst = ai->sockaddr;
11505 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
11506 NULL))
11507 continue;
11508 if (notify_isself(notify->zone, &dst))
11509 continue;
11510 newnotify = NULL;
11511 flags = notify->flags & DNS_NOTIFY_NOSOA;
11512 result = notify_create(notify->mctx, flags, &newnotify);
11513 if (result != ISC_R_SUCCESS)
11514 goto cleanup;
11515 zone_iattach(notify->zone, &newnotify->zone);
11516 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
11517 newnotify->dst = dst;
11518 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
11519 result = notify_send_queue(newnotify, startup);
11520 if (result != ISC_R_SUCCESS)
11521 goto cleanup;
11522 newnotify = NULL;
11523 }
11524
11525 cleanup:
11526 if (newnotify != NULL)
11527 notify_destroy(newnotify, true);
11528 }
11529
11530 void
11531 dns_zone_notify(dns_zone_t *zone) {
11532 isc_time_t now;
11533
11534 REQUIRE(DNS_ZONE_VALID(zone));
11535
11536 LOCK_ZONE(zone);
11537 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11538
11539 TIME_NOW(&now);
11540 zone_settimer(zone, &now);
11541 UNLOCK_ZONE(zone);
11542 }
11543
11544 static void
11545 zone_notify(dns_zone_t *zone, isc_time_t *now) {
11546 dns_dbnode_t *node = NULL;
11547 dns_db_t *zonedb = NULL;
11548 dns_dbversion_t *version = NULL;
11549 dns_name_t *origin = NULL;
11550 dns_name_t master;
11551 dns_rdata_ns_t ns;
11552 dns_rdata_soa_t soa;
11553 uint32_t serial;
11554 dns_rdata_t rdata = DNS_RDATA_INIT;
11555 dns_rdataset_t nsrdset;
11556 dns_rdataset_t soardset;
11557 isc_result_t result;
11558 unsigned int i;
11559 isc_sockaddr_t dst;
11560 bool isqueued;
11561 dns_notifytype_t notifytype;
11562 unsigned int flags = 0;
11563 bool loggednotify = false;
11564 bool startup;
11565
11566 REQUIRE(DNS_ZONE_VALID(zone));
11567
11568 LOCK_ZONE(zone);
11569 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11570 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11571 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
11572 notifytype = zone->notifytype;
11573 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
11574 UNLOCK_ZONE(zone);
11575
11576 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11577 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11578 return;
11579
11580 if (notifytype == dns_notifytype_no)
11581 return;
11582
11583 if (notifytype == dns_notifytype_masteronly &&
11584 zone->type != dns_zone_master)
11585 return;
11586
11587 origin = &zone->origin;
11588
11589 /*
11590 * If the zone is dialup we are done as we don't want to send
11591 * the current soa so as to force a refresh query.
11592 */
11593 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
11594 flags |= DNS_NOTIFY_NOSOA;
11595
11596 /*
11597 * Record that this was a notify due to starting up.
11598 */
11599 if (startup)
11600 flags |= DNS_NOTIFY_STARTUP;
11601
11602 /*
11603 * Get SOA RRset.
11604 */
11605 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11606 if (zone->db != NULL)
11607 dns_db_attach(zone->db, &zonedb);
11608 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11609 if (zonedb == NULL)
11610 return;
11611 dns_db_currentversion(zonedb, &version);
11612 result = dns_db_findnode(zonedb, origin, false, &node);
11613 if (result != ISC_R_SUCCESS)
11614 goto cleanup1;
11615
11616 dns_rdataset_init(&soardset);
11617 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
11618 dns_rdatatype_none, 0, &soardset, NULL);
11619 if (result != ISC_R_SUCCESS)
11620 goto cleanup2;
11621
11622 /*
11623 * Find serial and master server's name.
11624 */
11625 dns_name_init(&master, NULL);
11626 result = dns_rdataset_first(&soardset);
11627 if (result != ISC_R_SUCCESS)
11628 goto cleanup3;
11629 dns_rdataset_current(&soardset, &rdata);
11630 result = dns_rdata_tostruct(&rdata, &soa, NULL);
11631 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11632 dns_rdata_reset(&rdata);
11633 result = dns_name_dup(&soa.origin, zone->mctx, &master);
11634 serial = soa.serial;
11635 dns_rdataset_disassociate(&soardset);
11636 if (result != ISC_R_SUCCESS)
11637 goto cleanup3;
11638
11639 /*
11640 * Enqueue notify requests for 'also-notify' servers.
11641 */
11642 LOCK_ZONE(zone);
11643 for (i = 0; i < zone->notifycnt; i++) {
11644 dns_tsigkey_t *key = NULL;
11645 dns_notify_t *notify = NULL;
11646
11647 if ((zone->notifykeynames != NULL) &&
11648 (zone->notifykeynames[i] != NULL)) {
11649 dns_view_t *view = dns_zone_getview(zone);
11650 dns_name_t *keyname = zone->notifykeynames[i];
11651 (void)dns_view_gettsig(view, keyname, &key);
11652 }
11653
11654 dst = zone->notify[i];
11655 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
11656 if (key != NULL)
11657 dns_tsigkey_detach(&key);
11658 continue;
11659 }
11660
11661 result = notify_create(zone->mctx, flags, ¬ify);
11662 if (result != ISC_R_SUCCESS) {
11663 if (key != NULL)
11664 dns_tsigkey_detach(&key);
11665 continue;
11666 }
11667
11668 zone_iattach(zone, ¬ify->zone);
11669 notify->dst = dst;
11670
11671 INSIST(notify->key == NULL);
11672
11673 if (key != NULL) {
11674 notify->key = key;
11675 key = NULL;
11676 }
11677
11678 ISC_LIST_APPEND(zone->notifies, notify, link);
11679 result = notify_send_queue(notify, startup);
11680 if (result != ISC_R_SUCCESS)
11681 notify_destroy(notify, true);
11682 if (!loggednotify) {
11683 notify_log(zone, ISC_LOG_INFO,
11684 "sending notifies (serial %u)",
11685 serial);
11686 loggednotify = true;
11687 }
11688 }
11689 UNLOCK_ZONE(zone);
11690
11691 if (notifytype == dns_notifytype_explicit)
11692 goto cleanup3;
11693
11694 /*
11695 * Process NS RRset to generate notifies.
11696 */
11697
11698 dns_rdataset_init(&nsrdset);
11699 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
11700 dns_rdatatype_none, 0, &nsrdset, NULL);
11701 if (result != ISC_R_SUCCESS)
11702 goto cleanup3;
11703
11704 result = dns_rdataset_first(&nsrdset);
11705 while (result == ISC_R_SUCCESS) {
11706 dns_notify_t *notify = NULL;
11707
11708 dns_rdataset_current(&nsrdset, &rdata);
11709 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11710 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11711 dns_rdata_reset(&rdata);
11712 /*
11713 * Don't notify the master server unless explicitly
11714 * configured to do so.
11715 */
11716 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
11717 dns_name_compare(&master, &ns.name) == 0) {
11718 result = dns_rdataset_next(&nsrdset);
11719 continue;
11720 }
11721
11722 if (!loggednotify) {
11723 notify_log(zone, ISC_LOG_INFO,
11724 "sending notifies (serial %u)",
11725 serial);
11726 loggednotify = true;
11727 }
11728
11729 LOCK_ZONE(zone);
11730 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
11731 UNLOCK_ZONE(zone);
11732 if (isqueued) {
11733 result = dns_rdataset_next(&nsrdset);
11734 continue;
11735 }
11736 result = notify_create(zone->mctx, flags, ¬ify);
11737 if (result != ISC_R_SUCCESS)
11738 continue;
11739 dns_zone_iattach(zone, ¬ify->zone);
11740 result = dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
11741 if (result != ISC_R_SUCCESS) {
11742 LOCK_ZONE(zone);
11743 notify_destroy(notify, true);
11744 UNLOCK_ZONE(zone);
11745 continue;
11746 }
11747 LOCK_ZONE(zone);
11748 ISC_LIST_APPEND(zone->notifies, notify, link);
11749 UNLOCK_ZONE(zone);
11750 notify_find_address(notify);
11751 result = dns_rdataset_next(&nsrdset);
11752 }
11753 dns_rdataset_disassociate(&nsrdset);
11754
11755 cleanup3:
11756 if (dns_name_dynamic(&master))
11757 dns_name_free(&master, zone->mctx);
11758 cleanup2:
11759 dns_db_detachnode(zonedb, &node);
11760 cleanup1:
11761 dns_db_closeversion(zonedb, &version, false);
11762 dns_db_detach(&zonedb);
11763 }
11764
11765 /***
11766 *** Private
11767 ***/
11768
11769 static inline isc_result_t
11770 save_nsrrset(dns_message_t *message, dns_name_t *name,
11771 dns_db_t *db, dns_dbversion_t *version)
11772 {
11773 dns_rdataset_t *nsrdataset = NULL;
11774 dns_rdataset_t *rdataset = NULL;
11775 dns_dbnode_t *node = NULL;
11776 dns_rdata_ns_t ns;
11777 isc_result_t result;
11778 dns_rdata_t rdata = DNS_RDATA_INIT;
11779
11780 /*
11781 * Extract NS RRset from message.
11782 */
11783 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
11784 dns_rdatatype_ns, dns_rdatatype_none,
11785 NULL, &nsrdataset);
11786 if (result != ISC_R_SUCCESS)
11787 goto fail;
11788
11789 /*
11790 * Add NS rdataset.
11791 */
11792 result = dns_db_findnode(db, name, true, &node);
11793 if (result != ISC_R_SUCCESS)
11794 goto fail;
11795 result = dns_db_addrdataset(db, node, version, 0,
11796 nsrdataset, 0, NULL);
11797 dns_db_detachnode(db, &node);
11798 if (result != ISC_R_SUCCESS)
11799 goto fail;
11800 /*
11801 * Add glue rdatasets.
11802 */
11803 for (result = dns_rdataset_first(nsrdataset);
11804 result == ISC_R_SUCCESS;
11805 result = dns_rdataset_next(nsrdataset)) {
11806 dns_rdataset_current(nsrdataset, &rdata);
11807 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11808 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11809 dns_rdata_reset(&rdata);
11810 if (!dns_name_issubdomain(&ns.name, name))
11811 continue;
11812 rdataset = NULL;
11813 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11814 &ns.name, dns_rdatatype_aaaa,
11815 dns_rdatatype_none, NULL,
11816 &rdataset);
11817 if (result == ISC_R_SUCCESS) {
11818 result = dns_db_findnode(db, &ns.name,
11819 true, &node);
11820 if (result != ISC_R_SUCCESS)
11821 goto fail;
11822 result = dns_db_addrdataset(db, node, version, 0,
11823 rdataset, 0, NULL);
11824 dns_db_detachnode(db, &node);
11825 if (result != ISC_R_SUCCESS)
11826 goto fail;
11827 }
11828 rdataset = NULL;
11829 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11830 &ns.name, dns_rdatatype_a,
11831 dns_rdatatype_none, NULL,
11832 &rdataset);
11833 if (result == ISC_R_SUCCESS) {
11834 result = dns_db_findnode(db, &ns.name,
11835 true, &node);
11836 if (result != ISC_R_SUCCESS)
11837 goto fail;
11838 result = dns_db_addrdataset(db, node, version, 0,
11839 rdataset, 0, NULL);
11840 dns_db_detachnode(db, &node);
11841 if (result != ISC_R_SUCCESS)
11842 goto fail;
11843 }
11844 }
11845 if (result != ISC_R_NOMORE)
11846 goto fail;
11847
11848 return (ISC_R_SUCCESS);
11849
11850 fail:
11851 return (result);
11852 }
11853
11854 static void
11855 stub_callback(isc_task_t *task, isc_event_t *event) {
11856 const char me[] = "stub_callback";
11857 dns_requestevent_t *revent = (dns_requestevent_t *)event;
11858 dns_stub_t *stub = NULL;
11859 dns_message_t *msg = NULL;
11860 dns_zone_t *zone = NULL;
11861 char master[ISC_SOCKADDR_FORMATSIZE];
11862 char source[ISC_SOCKADDR_FORMATSIZE];
11863 uint32_t nscnt, cnamecnt, refresh, retry, expire;
11864 isc_result_t result;
11865 isc_time_t now;
11866 bool exiting = false;
11867 isc_interval_t i;
11868 unsigned int j, soacount;
11869
11870 stub = revent->ev_arg;
11871 INSIST(DNS_STUB_VALID(stub));
11872
11873 UNUSED(task);
11874
11875 zone = stub->zone;
11876
11877 ENTER;
11878
11879 TIME_NOW(&now);
11880
11881 LOCK_ZONE(zone);
11882
11883 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11884 zone_debuglog(zone, me, 1, "exiting");
11885 exiting = true;
11886 goto next_master;
11887 }
11888
11889 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
11890 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
11891
11892 if (revent->result != ISC_R_SUCCESS) {
11893 if (revent->result == ISC_R_TIMEDOUT &&
11894 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11895 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11896 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11897 "refreshing stub: timeout retrying "
11898 " without EDNS master %s (source %s)",
11899 master, source);
11900 goto same_master;
11901 }
11902 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
11903 &zone->sourceaddr, &now);
11904 dns_zone_log(zone, ISC_LOG_INFO,
11905 "could not refresh stub from master %s"
11906 " (source %s): %s", master, source,
11907 dns_result_totext(revent->result));
11908 goto next_master;
11909 }
11910
11911 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
11912 if (result != ISC_R_SUCCESS)
11913 goto next_master;
11914
11915 result = dns_request_getresponse(revent->request, msg, 0);
11916 if (result != ISC_R_SUCCESS)
11917 goto next_master;
11918
11919 /*
11920 * Unexpected rcode.
11921 */
11922 if (msg->rcode != dns_rcode_noerror) {
11923 char rcode[128];
11924 isc_buffer_t rb;
11925
11926 isc_buffer_init(&rb, rcode, sizeof(rcode));
11927 (void)dns_rcode_totext(msg->rcode, &rb);
11928
11929 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
11930 (msg->rcode == dns_rcode_servfail ||
11931 msg->rcode == dns_rcode_notimp ||
11932 msg->rcode == dns_rcode_formerr)) {
11933 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11934 "refreshing stub: rcode (%.*s) retrying "
11935 "without EDNS master %s (source %s)",
11936 (int)rb.used, rcode, master, source);
11937 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11938 goto same_master;
11939 }
11940
11941 dns_zone_log(zone, ISC_LOG_INFO,
11942 "refreshing stub: "
11943 "unexpected rcode (%.*s) from %s (source %s)",
11944 (int)rb.used, rcode, master, source);
11945 goto next_master;
11946 }
11947
11948 /*
11949 * We need complete messages.
11950 */
11951 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
11952 if (dns_request_usedtcp(revent->request)) {
11953 dns_zone_log(zone, ISC_LOG_INFO,
11954 "refreshing stub: truncated TCP "
11955 "response from master %s (source %s)",
11956 master, source);
11957 goto next_master;
11958 }
11959 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
11960 goto same_master;
11961 }
11962
11963 /*
11964 * If non-auth log and next master.
11965 */
11966 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
11967 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11968 "non-authoritative answer from "
11969 "master %s (source %s)", master, source);
11970 goto next_master;
11971 }
11972
11973 /*
11974 * Sanity checks.
11975 */
11976 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
11977 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
11978
11979 if (cnamecnt != 0) {
11980 dns_zone_log(zone, ISC_LOG_INFO,
11981 "refreshing stub: unexpected CNAME response "
11982 "from master %s (source %s)", master, source);
11983 goto next_master;
11984 }
11985
11986 if (nscnt == 0) {
11987 dns_zone_log(zone, ISC_LOG_INFO,
11988 "refreshing stub: no NS records in response "
11989 "from master %s (source %s)", master, source);
11990 goto next_master;
11991 }
11992
11993 /*
11994 * Save answer.
11995 */
11996 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
11997 if (result != ISC_R_SUCCESS) {
11998 dns_zone_log(zone, ISC_LOG_INFO,
11999 "refreshing stub: unable to save NS records "
12000 "from master %s (source %s)", master, source);
12001 goto next_master;
12002 }
12003
12004 /*
12005 * Tidy up.
12006 */
12007 dns_db_closeversion(stub->db, &stub->version, true);
12008 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12009 if (zone->db == NULL)
12010 zone_attachdb(zone, stub->db);
12011 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
12012 &refresh, &retry, &expire, NULL, NULL);
12013 if (result == ISC_R_SUCCESS && soacount > 0U) {
12014 zone->refresh = RANGE(refresh, zone->minrefresh,
12015 zone->maxrefresh);
12016 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
12017 zone->expire = RANGE(expire, zone->refresh + zone->retry,
12018 DNS_MAX_EXPIRE);
12019 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12020 }
12021 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12022 dns_db_detach(&stub->db);
12023
12024 dns_message_destroy(&msg);
12025 isc_event_free(&event);
12026 dns_request_destroy(&zone->request);
12027
12028 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12029 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
12030 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12031 isc_interval_set(&i, zone->expire, 0);
12032 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
12033
12034 if (zone->masterfile != NULL)
12035 zone_needdump(zone, 0);
12036
12037 zone_settimer(zone, &now);
12038 goto free_stub;
12039
12040 next_master:
12041 if (stub->version != NULL)
12042 dns_db_closeversion(stub->db, &stub->version, false);
12043 if (stub->db != NULL)
12044 dns_db_detach(&stub->db);
12045 if (msg != NULL)
12046 dns_message_destroy(&msg);
12047 isc_event_free(&event);
12048 dns_request_destroy(&zone->request);
12049 /*
12050 * Skip to next failed / untried master.
12051 */
12052 do {
12053 zone->curmaster++;
12054 } while (zone->curmaster < zone->masterscnt &&
12055 zone->mastersok[zone->curmaster]);
12056 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
12057 if (exiting || zone->curmaster >= zone->masterscnt) {
12058 bool done = true;
12059 if (!exiting &&
12060 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12061 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12062 /*
12063 * Did we get a good answer from all the masters?
12064 */
12065 for (j = 0; j < zone->masterscnt; j++)
12066 if (zone->mastersok[j] == false) {
12067 done = false;
12068 break;
12069 }
12070 } else
12071 done = true;
12072 if (!done) {
12073 zone->curmaster = 0;
12074 /*
12075 * Find the next failed master.
12076 */
12077 while (zone->curmaster < zone->masterscnt &&
12078 zone->mastersok[zone->curmaster])
12079 zone->curmaster++;
12080 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12081 } else {
12082 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12083
12084 zone_settimer(zone, &now);
12085 goto free_stub;
12086 }
12087 }
12088 queue_soa_query(zone);
12089 goto free_stub;
12090
12091 same_master:
12092 if (msg != NULL)
12093 dns_message_destroy(&msg);
12094 isc_event_free(&event);
12095 dns_request_destroy(&zone->request);
12096 ns_query(zone, NULL, stub);
12097 UNLOCK_ZONE(zone);
12098 goto done;
12099
12100 free_stub:
12101 UNLOCK_ZONE(zone);
12102 stub->magic = 0;
12103 dns_zone_idetach(&stub->zone);
12104 INSIST(stub->db == NULL);
12105 INSIST(stub->version == NULL);
12106 isc_mem_put(stub->mctx, stub, sizeof(*stub));
12107
12108 done:
12109 INSIST(event == NULL);
12110 return;
12111 }
12112
12113 /*
12114 * Get the EDNS EXPIRE option from the response and if it exists trim
12115 * expire to be not more than it.
12116 */
12117 static void
12118 get_edns_expire(dns_zone_t * zone, dns_message_t *message,
12119 uint32_t *expirep)
12120 {
12121 isc_result_t result;
12122 uint32_t expire;
12123 dns_rdata_t rdata = DNS_RDATA_INIT;
12124 isc_buffer_t optbuf;
12125 uint16_t optcode;
12126 uint16_t optlen;
12127
12128 REQUIRE(expirep != NULL);
12129 REQUIRE(message != NULL);
12130
12131 if (message->opt == NULL)
12132 return;
12133
12134 result = dns_rdataset_first(message->opt);
12135 if (result == ISC_R_SUCCESS) {
12136 dns_rdataset_current(message->opt, &rdata);
12137 isc_buffer_init(&optbuf, rdata.data, rdata.length);
12138 isc_buffer_add(&optbuf, rdata.length);
12139 while (isc_buffer_remaininglength(&optbuf) >= 4) {
12140 optcode = isc_buffer_getuint16(&optbuf);
12141 optlen = isc_buffer_getuint16(&optbuf);
12142 /*
12143 * A EDNS EXPIRE response has a length of 4.
12144 */
12145 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
12146 isc_buffer_forward(&optbuf, optlen);
12147 continue;
12148 }
12149 expire = isc_buffer_getuint32(&optbuf);
12150 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12151 "got EDNS EXPIRE of %u", expire);
12152 /*
12153 * Trim *expirep?
12154 */
12155 if (expire < *expirep)
12156 *expirep = expire;
12157 break;
12158 }
12159 }
12160 }
12161
12162 /*
12163 * Set the file modification time zone->expire seconds before expiretime.
12164 */
12165 static void
12166 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
12167 isc_result_t result;
12168 isc_time_t when;
12169 isc_interval_t i;
12170
12171 isc_interval_set(&i, zone->expire, 0);
12172 result = isc_time_subtract(expiretime, &i, &when);
12173 if (result != ISC_R_SUCCESS)
12174 return;
12175
12176 result = ISC_R_FAILURE;
12177 if (zone->journal != NULL)
12178 result = isc_file_settime(zone->journal, &when);
12179 if (result == ISC_R_SUCCESS &&
12180 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12181 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
12182 result = isc_file_settime(zone->masterfile, &when);
12183 else if (result != ISC_R_SUCCESS)
12184 result = isc_file_settime(zone->masterfile, &when);
12185
12186 /*
12187 * Someone removed the file from underneath us!
12188 */
12189 if (result == ISC_R_FILENOTFOUND) {
12190 zone_needdump(zone, DNS_DUMP_DELAY);
12191 } else if (result != ISC_R_SUCCESS)
12192 dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
12193 "file modification time of '%s': %s",
12194 zone->masterfile, dns_result_totext(result));
12195 }
12196
12197 /*
12198 * An SOA query has finished (successfully or not).
12199 */
12200 static void
12201 refresh_callback(isc_task_t *task, isc_event_t *event) {
12202 const char me[] = "refresh_callback";
12203 dns_requestevent_t *revent = (dns_requestevent_t *)event;
12204 dns_zone_t *zone;
12205 dns_message_t *msg = NULL;
12206 uint32_t soacnt, cnamecnt, soacount, nscount;
12207 isc_time_t now;
12208 char master[ISC_SOCKADDR_FORMATSIZE];
12209 char source[ISC_SOCKADDR_FORMATSIZE];
12210 dns_rdataset_t *rdataset = NULL;
12211 dns_rdata_t rdata = DNS_RDATA_INIT;
12212 dns_rdata_soa_t soa;
12213 isc_result_t result;
12214 uint32_t serial, oldserial = 0;
12215 unsigned int j;
12216 bool do_queue_xfrin = false;
12217
12218 zone = revent->ev_arg;
12219 INSIST(DNS_ZONE_VALID(zone));
12220
12221 UNUSED(task);
12222
12223 ENTER;
12224
12225 TIME_NOW(&now);
12226
12227 LOCK_ZONE(zone);
12228
12229 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12230 isc_event_free(&event);
12231 dns_request_destroy(&zone->request);
12232 goto detach;
12233 }
12234
12235 /*
12236 * if timeout log and next master;
12237 */
12238
12239 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12240 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12241
12242 if (revent->result != ISC_R_SUCCESS) {
12243 if (revent->result == ISC_R_TIMEDOUT &&
12244 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12245 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12246 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12247 "refresh: timeout retrying without EDNS "
12248 "master %s (source %s)", master, source);
12249 goto same_master;
12250 }
12251 if (revent->result == ISC_R_TIMEDOUT &&
12252 !dns_request_usedtcp(revent->request)) {
12253 dns_zone_log(zone, ISC_LOG_INFO,
12254 "refresh: retry limit for "
12255 "master %s exceeded (source %s)",
12256 master, source);
12257 /* Try with slave with TCP. */
12258 if ((zone->type == dns_zone_slave ||
12259 zone->type == dns_zone_mirror ||
12260 zone->type == dns_zone_redirect) &&
12261 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
12262 {
12263 if (!dns_zonemgr_unreachable(zone->zmgr,
12264 &zone->masteraddr,
12265 &zone->sourceaddr,
12266 &now))
12267 {
12268 DNS_ZONE_SETFLAG(zone,
12269 DNS_ZONEFLG_SOABEFOREAXFR);
12270 goto tcp_transfer;
12271 }
12272 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12273 "refresh: skipped tcp fallback "
12274 "as master %s (source %s) is "
12275 "unreachable (cached)",
12276 master, source);
12277 }
12278 } else
12279 dns_zone_log(zone, ISC_LOG_INFO,
12280 "refresh: failure trying master "
12281 "%s (source %s): %s", master, source,
12282 dns_result_totext(revent->result));
12283 goto next_master;
12284 }
12285
12286 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12287 if (result != ISC_R_SUCCESS)
12288 goto next_master;
12289 result = dns_request_getresponse(revent->request, msg, 0);
12290 if (result != ISC_R_SUCCESS) {
12291 dns_zone_log(zone, ISC_LOG_INFO,
12292 "refresh: failure trying master "
12293 "%s (source %s): %s", master, source,
12294 dns_result_totext(result));
12295 goto next_master;
12296 }
12297
12298 /*
12299 * Unexpected rcode.
12300 */
12301 if (msg->rcode != dns_rcode_noerror) {
12302 char rcode[128];
12303 isc_buffer_t rb;
12304
12305 isc_buffer_init(&rb, rcode, sizeof(rcode));
12306 (void)dns_rcode_totext(msg->rcode, &rb);
12307
12308 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12309 (msg->rcode == dns_rcode_servfail ||
12310 msg->rcode == dns_rcode_notimp ||
12311 msg->rcode == dns_rcode_formerr)) {
12312 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12313 "refresh: rcode (%.*s) retrying without "
12314 "EDNS master %s (source %s)",
12315 (int)rb.used, rcode, master, source);
12316 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12317 goto same_master;
12318 }
12319 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12320 msg->rcode == dns_rcode_badvers) {
12321 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12322 "refresh: rcode (%.*s) retrying without "
12323 "EDNS EXPIRE OPTION master %s (source %s)",
12324 (int)rb.used, rcode, master, source);
12325 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12326 goto same_master;
12327 }
12328 dns_zone_log(zone, ISC_LOG_INFO,
12329 "refresh: unexpected rcode (%.*s) from "
12330 "master %s (source %s)", (int)rb.used, rcode,
12331 master, source);
12332 /*
12333 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
12334 */
12335 if (msg->rcode == dns_rcode_refused &&
12336 (zone->type == dns_zone_slave ||
12337 zone->type == dns_zone_mirror ||
12338 zone->type == dns_zone_redirect))
12339 {
12340 goto tcp_transfer;
12341 }
12342 goto next_master;
12343 }
12344
12345 /*
12346 * If truncated punt to zone transfer which will query again.
12347 */
12348 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
12349 if (zone->type == dns_zone_slave ||
12350 zone->type == dns_zone_mirror ||
12351 zone->type == dns_zone_redirect)
12352 {
12353 dns_zone_log(zone, ISC_LOG_INFO,
12354 "refresh: truncated UDP answer, "
12355 "initiating TCP zone xfer "
12356 "for master %s (source %s)",
12357 master, source);
12358 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
12359 goto tcp_transfer;
12360 } else {
12361 INSIST(zone->type == dns_zone_stub);
12362 if (dns_request_usedtcp(revent->request)) {
12363 dns_zone_log(zone, ISC_LOG_INFO,
12364 "refresh: truncated TCP response "
12365 "from master %s (source %s)",
12366 master, source);
12367 goto next_master;
12368 }
12369 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
12370 goto same_master;
12371 }
12372 }
12373
12374 /*
12375 * if non-auth log and next master;
12376 */
12377 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
12378 dns_zone_log(zone, ISC_LOG_INFO,
12379 "refresh: non-authoritative answer from "
12380 "master %s (source %s)", master, source);
12381 goto next_master;
12382 }
12383
12384 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12385 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
12386 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
12387 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
12388 dns_rdatatype_soa);
12389
12390 /*
12391 * There should not be a CNAME record at top of zone.
12392 */
12393 if (cnamecnt != 0) {
12394 dns_zone_log(zone, ISC_LOG_INFO,
12395 "refresh: CNAME at top of zone "
12396 "in master %s (source %s)", master, source);
12397 goto next_master;
12398 }
12399
12400 /*
12401 * if referral log and next master;
12402 */
12403 if (soacnt == 0 && soacount == 0 && nscount != 0) {
12404 dns_zone_log(zone, ISC_LOG_INFO,
12405 "refresh: referral response "
12406 "from master %s (source %s)", master, source);
12407 goto next_master;
12408 }
12409
12410 /*
12411 * if nodata log and next master;
12412 */
12413 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
12414 dns_zone_log(zone, ISC_LOG_INFO,
12415 "refresh: NODATA response "
12416 "from master %s (source %s)", master, source);
12417 goto next_master;
12418 }
12419
12420 /*
12421 * Only one soa at top of zone.
12422 */
12423 if (soacnt != 1) {
12424 dns_zone_log(zone, ISC_LOG_INFO,
12425 "refresh: answer SOA count (%d) != 1 "
12426 "from master %s (source %s)",
12427 soacnt, master, source);
12428 goto next_master;
12429 }
12430
12431 /*
12432 * Extract serial
12433 */
12434 rdataset = NULL;
12435 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
12436 dns_rdatatype_soa, dns_rdatatype_none,
12437 NULL, &rdataset);
12438 if (result != ISC_R_SUCCESS) {
12439 dns_zone_log(zone, ISC_LOG_INFO,
12440 "refresh: unable to get SOA record "
12441 "from master %s (source %s)", master, source);
12442 goto next_master;
12443 }
12444
12445 result = dns_rdataset_first(rdataset);
12446 if (result != ISC_R_SUCCESS) {
12447 dns_zone_log(zone, ISC_LOG_INFO,
12448 "refresh: dns_rdataset_first() failed");
12449 goto next_master;
12450 }
12451
12452 dns_rdataset_current(rdataset, &rdata);
12453 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12454 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12455
12456 serial = soa.serial;
12457 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
12458 unsigned int dbsoacount;
12459 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
12460 &oldserial, NULL, NULL, NULL, NULL,
12461 NULL);
12462 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12463 RUNTIME_CHECK(dbsoacount > 0U);
12464 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
12465 serial, oldserial);
12466 } else
12467 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
12468 serial);
12469
12470 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
12471 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
12472 isc_serial_gt(serial, oldserial)) {
12473 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12474 &zone->sourceaddr, &now))
12475 {
12476 dns_zone_log(zone, ISC_LOG_INFO,
12477 "refresh: skipping %s as master %s "
12478 "(source %s) is unreachable (cached)",
12479 (zone->type == dns_zone_slave ||
12480 zone->type == dns_zone_mirror ||
12481 zone->type == dns_zone_redirect) ?
12482 "zone transfer" : "NS query",
12483 master, source);
12484 goto next_master;
12485 }
12486 tcp_transfer:
12487 isc_event_free(&event);
12488 dns_request_destroy(&zone->request);
12489 if (zone->type == dns_zone_slave ||
12490 zone->type == dns_zone_mirror ||
12491 zone->type == dns_zone_redirect)
12492 {
12493 do_queue_xfrin = true;
12494 } else {
12495 INSIST(zone->type == dns_zone_stub);
12496 ns_query(zone, rdataset, NULL);
12497 }
12498 if (msg != NULL)
12499 dns_message_destroy(&msg);
12500 } else if (isc_serial_eq(soa.serial, oldserial)) {
12501 isc_time_t expiretime;
12502 uint32_t expire;
12503
12504 /*
12505 * Compute the new expire time based on this response.
12506 */
12507 expire = zone->expire;
12508 get_edns_expire(zone, msg, &expire);
12509 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
12510
12511 /*
12512 * Has the expire time improved?
12513 */
12514 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
12515 zone->expiretime = expiretime;
12516 if (zone->masterfile != NULL)
12517 setmodtime(zone, &expiretime);
12518 }
12519
12520 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12521 zone->mastersok[zone->curmaster] = true;
12522 goto next_master;
12523 } else {
12524 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
12525 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
12526 "received from master %s < ours (%u)",
12527 soa.serial, master, oldserial);
12528 else
12529 zone_debuglog(zone, me, 1, "ahead");
12530 zone->mastersok[zone->curmaster] = true;
12531 goto next_master;
12532 }
12533 if (msg != NULL)
12534 dns_message_destroy(&msg);
12535 goto detach;
12536
12537 next_master:
12538 if (msg != NULL)
12539 dns_message_destroy(&msg);
12540 isc_event_free(&event);
12541 dns_request_destroy(&zone->request);
12542 /*
12543 * Skip to next failed / untried master.
12544 */
12545 do {
12546 zone->curmaster++;
12547 } while (zone->curmaster < zone->masterscnt &&
12548 zone->mastersok[zone->curmaster]);
12549 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
12550 if (zone->curmaster >= zone->masterscnt) {
12551 bool done = true;
12552 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12553 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12554 /*
12555 * Did we get a good answer from all the masters?
12556 */
12557 for (j = 0; j < zone->masterscnt; j++)
12558 if (zone->mastersok[j] == false) {
12559 done = false;
12560 break;
12561 }
12562 } else
12563 done = true;
12564 if (!done) {
12565 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12566 zone->curmaster = 0;
12567 /*
12568 * Find the next failed master.
12569 */
12570 while (zone->curmaster < zone->masterscnt &&
12571 zone->mastersok[zone->curmaster])
12572 zone->curmaster++;
12573 goto requeue;
12574 }
12575 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12576 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
12577 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12578 zone->refreshtime = now;
12579 }
12580 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12581 zone_settimer(zone, &now);
12582 goto detach;
12583 }
12584
12585 requeue:
12586 queue_soa_query(zone);
12587 goto detach;
12588
12589 same_master:
12590 if (msg != NULL)
12591 dns_message_destroy(&msg);
12592 isc_event_free(&event);
12593 dns_request_destroy(&zone->request);
12594 queue_soa_query(zone);
12595
12596 detach:
12597 UNLOCK_ZONE(zone);
12598 if (do_queue_xfrin)
12599 queue_xfrin(zone);
12600 dns_zone_idetach(&zone);
12601 return;
12602 }
12603
12604 static void
12605 queue_soa_query(dns_zone_t *zone) {
12606 const char me[] = "queue_soa_query";
12607 isc_event_t *e;
12608 dns_zone_t *dummy = NULL;
12609 isc_result_t result;
12610
12611 ENTER;
12612 /*
12613 * Locked by caller
12614 */
12615 REQUIRE(LOCKED_ZONE(zone));
12616
12617 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12618 cancel_refresh(zone);
12619 return;
12620 }
12621
12622 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
12623 soa_query, zone, sizeof(isc_event_t));
12624 if (e == NULL) {
12625 cancel_refresh(zone);
12626 return;
12627 }
12628
12629 /*
12630 * Attach so that we won't clean up
12631 * until the event is delivered.
12632 */
12633 zone_iattach(zone, &dummy);
12634
12635 e->ev_arg = zone;
12636 e->ev_sender = NULL;
12637 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
12638 if (result != ISC_R_SUCCESS) {
12639 zone_idetach(&dummy);
12640 isc_event_free(&e);
12641 cancel_refresh(zone);
12642 }
12643 }
12644
12645 static inline isc_result_t
12646 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
12647 dns_message_t **messagep)
12648 {
12649 dns_message_t *message = NULL;
12650 dns_name_t *qname = NULL;
12651 dns_rdataset_t *qrdataset = NULL;
12652 isc_result_t result;
12653
12654 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
12655 &message);
12656 if (result != ISC_R_SUCCESS)
12657 goto cleanup;
12658
12659 message->opcode = dns_opcode_query;
12660 message->rdclass = zone->rdclass;
12661
12662 result = dns_message_gettempname(message, &qname);
12663 if (result != ISC_R_SUCCESS)
12664 goto cleanup;
12665
12666 result = dns_message_gettemprdataset(message, &qrdataset);
12667 if (result != ISC_R_SUCCESS)
12668 goto cleanup;
12669
12670 /*
12671 * Make question.
12672 */
12673 dns_name_init(qname, NULL);
12674 dns_name_clone(&zone->origin, qname);
12675 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
12676 ISC_LIST_APPEND(qname->list, qrdataset, link);
12677 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
12678
12679 *messagep = message;
12680 return (ISC_R_SUCCESS);
12681
12682 cleanup:
12683 if (qname != NULL)
12684 dns_message_puttempname(message, &qname);
12685 if (qrdataset != NULL)
12686 dns_message_puttemprdataset(message, &qrdataset);
12687 if (message != NULL)
12688 dns_message_destroy(&message);
12689 return (result);
12690 }
12691
12692 static isc_result_t
12693 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
12694 bool reqexpire)
12695 {
12696 isc_result_t result;
12697 dns_rdataset_t *rdataset = NULL;
12698 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
12699 int count = 0;
12700
12701 /* Set EDNS options if applicable */
12702 if (reqnsid) {
12703 INSIST(count < DNS_EDNSOPTIONS);
12704 ednsopts[count].code = DNS_OPT_NSID;
12705 ednsopts[count].length = 0;
12706 ednsopts[count].value = NULL;
12707 count++;
12708 }
12709 if (reqexpire) {
12710 INSIST(count < DNS_EDNSOPTIONS);
12711 ednsopts[count].code = DNS_OPT_EXPIRE;
12712 ednsopts[count].length = 0;
12713 ednsopts[count].value = NULL;
12714 count++;
12715 }
12716 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
12717 ednsopts, count);
12718 if (result != ISC_R_SUCCESS)
12719 return (result);
12720
12721 return (dns_message_setopt(message, rdataset));
12722 }
12723
12724 static void
12725 soa_query(isc_task_t *task, isc_event_t *event) {
12726 const char me[] = "soa_query";
12727 isc_result_t result = ISC_R_FAILURE;
12728 dns_message_t *message = NULL;
12729 dns_zone_t *zone = event->ev_arg;
12730 dns_zone_t *dummy = NULL;
12731 isc_netaddr_t masterip;
12732 dns_tsigkey_t *key = NULL;
12733 uint32_t options;
12734 bool cancel = true;
12735 int timeout;
12736 bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
12737 uint16_t udpsize = SEND_BUFFER_SIZE;
12738 isc_dscp_t dscp = -1;
12739
12740 REQUIRE(DNS_ZONE_VALID(zone));
12741
12742 UNUSED(task);
12743
12744 ENTER;
12745
12746 LOCK_ZONE(zone);
12747 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
12748 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12749 zone->view->requestmgr == NULL) {
12750 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12751 cancel = false;
12752 goto cleanup;
12753 }
12754
12755 again:
12756 result = create_query(zone, dns_rdatatype_soa, &message);
12757 if (result != ISC_R_SUCCESS)
12758 goto cleanup;
12759
12760 INSIST(zone->masterscnt > 0);
12761 INSIST(zone->curmaster < zone->masterscnt);
12762
12763 zone->masteraddr = zone->masters[zone->curmaster];
12764
12765 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12766 /*
12767 * First, look for a tsig key in the master statement, then
12768 * try for a server key.
12769 */
12770 if ((zone->masterkeynames != NULL) &&
12771 (zone->masterkeynames[zone->curmaster] != NULL)) {
12772 dns_view_t *view = dns_zone_getview(zone);
12773 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12774 result = dns_view_gettsig(view, keyname, &key);
12775 if (result != ISC_R_SUCCESS) {
12776 char namebuf[DNS_NAME_FORMATSIZE];
12777 dns_name_format(keyname, namebuf, sizeof(namebuf));
12778 dns_zone_log(zone, ISC_LOG_ERROR,
12779 "unable to find key: %s", namebuf);
12780 goto skip_master;
12781 }
12782 }
12783 if (key == NULL) {
12784 result = dns_view_getpeertsig(zone->view, &masterip, &key);
12785 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12786 char addrbuf[ISC_NETADDR_FORMATSIZE];
12787 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
12788 dns_zone_log(zone, ISC_LOG_ERROR,
12789 "unable to find TSIG key for %s", addrbuf);
12790 goto skip_master;
12791 }
12792 }
12793
12794 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
12795 DNS_REQUESTOPT_TCP : 0;
12796 have_xfrsource = have_xfrdscp = false;
12797 reqnsid = zone->view->requestnsid;
12798 reqexpire = zone->requestexpire;
12799 if (zone->view->peers != NULL) {
12800 dns_peer_t *peer = NULL;
12801 bool edns, usetcp;
12802 result = dns_peerlist_peerbyaddr(zone->view->peers,
12803 &masterip, &peer);
12804 if (result == ISC_R_SUCCESS) {
12805 result = dns_peer_getsupportedns(peer, &edns);
12806 if (result == ISC_R_SUCCESS && !edns)
12807 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12808 result = dns_peer_gettransfersource(peer,
12809 &zone->sourceaddr);
12810 if (result == ISC_R_SUCCESS)
12811 have_xfrsource = true;
12812 (void)dns_peer_gettransferdscp(peer, &dscp);
12813 if (dscp != -1)
12814 have_xfrdscp = true;
12815 if (zone->view->resolver != NULL)
12816 udpsize =
12817 dns_resolver_getudpsize(zone->view->resolver);
12818 (void)dns_peer_getudpsize(peer, &udpsize);
12819 (void)dns_peer_getrequestnsid(peer, &reqnsid);
12820 (void)dns_peer_getrequestexpire(peer, &reqexpire);
12821 result = dns_peer_getforcetcp(peer, &usetcp);
12822 if (result == ISC_R_SUCCESS && usetcp)
12823 options |= DNS_REQUESTOPT_TCP;
12824 }
12825 }
12826
12827 switch (isc_sockaddr_pf(&zone->masteraddr)) {
12828 case PF_INET:
12829 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12830 if (isc_sockaddr_equal(&zone->altxfrsource4,
12831 &zone->xfrsource4))
12832 goto skip_master;
12833 zone->sourceaddr = zone->altxfrsource4;
12834 if (!have_xfrdscp)
12835 dscp = zone->altxfrsource4dscp;
12836 } else if (!have_xfrsource) {
12837 zone->sourceaddr = zone->xfrsource4;
12838 if (!have_xfrdscp)
12839 dscp = zone->xfrsource4dscp;
12840 }
12841 break;
12842 case PF_INET6:
12843 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12844 if (isc_sockaddr_equal(&zone->altxfrsource6,
12845 &zone->xfrsource6))
12846 goto skip_master;
12847 zone->sourceaddr = zone->altxfrsource6;
12848 if (!have_xfrdscp)
12849 dscp = zone->altxfrsource6dscp;
12850 } else if (!have_xfrsource) {
12851 zone->sourceaddr = zone->xfrsource6;
12852 if (!have_xfrdscp)
12853 dscp = zone->xfrsource6dscp;
12854 }
12855 break;
12856 default:
12857 result = ISC_R_NOTIMPLEMENTED;
12858 goto cleanup;
12859 }
12860
12861 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12862 result = add_opt(message, udpsize, reqnsid, reqexpire);
12863 if (result != ISC_R_SUCCESS)
12864 zone_debuglog(zone, me, 1,
12865 "unable to add opt record: %s",
12866 dns_result_totext(result));
12867 }
12868
12869 zone_iattach(zone, &dummy);
12870 timeout = 15;
12871 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
12872 timeout = 30;
12873 result = dns_request_createvia(zone->view->requestmgr, message,
12874 &zone->sourceaddr, &zone->masteraddr,
12875 dscp, options, key, timeout * 3,
12876 timeout, 0, zone->task,
12877 refresh_callback, zone, &zone->request);
12878 if (result != ISC_R_SUCCESS) {
12879 zone_idetach(&dummy);
12880 zone_debuglog(zone, me, 1,
12881 "dns_request_createvia4() failed: %s",
12882 dns_result_totext(result));
12883 goto skip_master;
12884 } else {
12885 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
12886 inc_stats(zone, dns_zonestatscounter_soaoutv4);
12887 else
12888 inc_stats(zone, dns_zonestatscounter_soaoutv6);
12889 }
12890 cancel = false;
12891
12892 cleanup:
12893 if (key != NULL)
12894 dns_tsigkey_detach(&key);
12895 if (result != ISC_R_SUCCESS)
12896 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12897 if (message != NULL)
12898 dns_message_destroy(&message);
12899 if (cancel)
12900 cancel_refresh(zone);
12901 isc_event_free(&event);
12902 UNLOCK_ZONE(zone);
12903 dns_zone_idetach(&zone);
12904 return;
12905
12906 skip_master:
12907 if (key != NULL)
12908 dns_tsigkey_detach(&key);
12909 dns_message_destroy(&message);
12910 /*
12911 * Skip to next failed / untried master.
12912 */
12913 do {
12914 zone->curmaster++;
12915 } while (zone->curmaster < zone->masterscnt &&
12916 zone->mastersok[zone->curmaster]);
12917 if (zone->curmaster < zone->masterscnt)
12918 goto again;
12919 zone->curmaster = 0;
12920 goto cleanup;
12921 }
12922
12923 static void
12924 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
12925 const char me[] = "ns_query";
12926 isc_result_t result;
12927 dns_message_t *message = NULL;
12928 isc_netaddr_t masterip;
12929 dns_tsigkey_t *key = NULL;
12930 dns_dbnode_t *node = NULL;
12931 int timeout;
12932 bool have_xfrsource = false, have_xfrdscp = false;
12933 bool reqnsid;
12934 uint16_t udpsize = SEND_BUFFER_SIZE;
12935 isc_dscp_t dscp = -1;
12936
12937 REQUIRE(DNS_ZONE_VALID(zone));
12938 REQUIRE(LOCKED_ZONE(zone));
12939 REQUIRE((soardataset != NULL && stub == NULL) ||
12940 (soardataset == NULL && stub != NULL));
12941 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
12942
12943 ENTER;
12944
12945 if (stub == NULL) {
12946 stub = isc_mem_get(zone->mctx, sizeof(*stub));
12947 if (stub == NULL)
12948 goto cleanup;
12949 stub->magic = STUB_MAGIC;
12950 stub->mctx = zone->mctx;
12951 stub->zone = NULL;
12952 stub->db = NULL;
12953 stub->version = NULL;
12954
12955 /*
12956 * Attach so that the zone won't disappear from under us.
12957 */
12958 zone_iattach(zone, &stub->zone);
12959
12960 /*
12961 * If a db exists we will update it, otherwise we create a
12962 * new one and attach it to the zone once we have the NS
12963 * RRset and glue.
12964 */
12965 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12966 if (zone->db != NULL) {
12967 dns_db_attach(zone->db, &stub->db);
12968 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12969 } else {
12970 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12971
12972 INSIST(zone->db_argc >= 1);
12973 result = dns_db_create(zone->mctx, zone->db_argv[0],
12974 &zone->origin, dns_dbtype_stub,
12975 zone->rdclass,
12976 zone->db_argc - 1,
12977 zone->db_argv + 1,
12978 &stub->db);
12979 if (result != ISC_R_SUCCESS) {
12980 dns_zone_log(zone, ISC_LOG_ERROR,
12981 "refreshing stub: "
12982 "could not create "
12983 "database: %s",
12984 dns_result_totext(result));
12985 goto cleanup;
12986 }
12987 dns_db_settask(stub->db, zone->task);
12988 }
12989
12990 result = dns_db_newversion(stub->db, &stub->version);
12991 if (result != ISC_R_SUCCESS) {
12992 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
12993 "dns_db_newversion() failed: %s",
12994 dns_result_totext(result));
12995 goto cleanup;
12996 }
12997
12998 /*
12999 * Update SOA record.
13000 */
13001 result = dns_db_findnode(stub->db, &zone->origin, true,
13002 &node);
13003 if (result != ISC_R_SUCCESS) {
13004 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
13005 "dns_db_findnode() failed: %s",
13006 dns_result_totext(result));
13007 goto cleanup;
13008 }
13009
13010 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13011 soardataset, 0, NULL);
13012 dns_db_detachnode(stub->db, &node);
13013 if (result != ISC_R_SUCCESS) {
13014 dns_zone_log(zone, ISC_LOG_INFO,
13015 "refreshing stub: "
13016 "dns_db_addrdataset() failed: %s",
13017 dns_result_totext(result));
13018 goto cleanup;
13019 }
13020 }
13021
13022 /*
13023 * XXX Optimisation: Create message when zone is setup and reuse.
13024 */
13025 result = create_query(zone, dns_rdatatype_ns, &message);
13026 INSIST(result == ISC_R_SUCCESS);
13027
13028 INSIST(zone->masterscnt > 0);
13029 INSIST(zone->curmaster < zone->masterscnt);
13030 zone->masteraddr = zone->masters[zone->curmaster];
13031
13032 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13033 /*
13034 * First, look for a tsig key in the master statement, then
13035 * try for a server key.
13036 */
13037 if ((zone->masterkeynames != NULL) &&
13038 (zone->masterkeynames[zone->curmaster] != NULL)) {
13039 dns_view_t *view = dns_zone_getview(zone);
13040 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
13041 result = dns_view_gettsig(view, keyname, &key);
13042 if (result != ISC_R_SUCCESS) {
13043 char namebuf[DNS_NAME_FORMATSIZE];
13044 dns_name_format(keyname, namebuf, sizeof(namebuf));
13045 dns_zone_log(zone, ISC_LOG_ERROR,
13046 "unable to find key: %s", namebuf);
13047 }
13048 }
13049 if (key == NULL)
13050 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
13051
13052 reqnsid = zone->view->requestnsid;
13053 if (zone->view->peers != NULL) {
13054 dns_peer_t *peer = NULL;
13055 bool edns;
13056 result = dns_peerlist_peerbyaddr(zone->view->peers,
13057 &masterip, &peer);
13058 if (result == ISC_R_SUCCESS) {
13059 result = dns_peer_getsupportedns(peer, &edns);
13060 if (result == ISC_R_SUCCESS && !edns)
13061 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13062 result = dns_peer_gettransfersource(peer,
13063 &zone->sourceaddr);
13064 if (result == ISC_R_SUCCESS)
13065 have_xfrsource = true;
13066 result = dns_peer_gettransferdscp(peer, &dscp);
13067 if (result == ISC_R_SUCCESS && dscp != -1)
13068 have_xfrdscp = true;
13069 if (zone->view->resolver != NULL)
13070 udpsize =
13071 dns_resolver_getudpsize(zone->view->resolver);
13072 (void)dns_peer_getudpsize(peer, &udpsize);
13073 (void)dns_peer_getrequestnsid(peer, &reqnsid);
13074 }
13075
13076 }
13077 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13078 result = add_opt(message, udpsize, reqnsid, false);
13079 if (result != ISC_R_SUCCESS)
13080 zone_debuglog(zone, me, 1,
13081 "unable to add opt record: %s",
13082 dns_result_totext(result));
13083 }
13084
13085 /*
13086 * Always use TCP so that we shouldn't truncate in additional section.
13087 */
13088 switch (isc_sockaddr_pf(&zone->masteraddr)) {
13089 case PF_INET:
13090 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13091 zone->sourceaddr = zone->altxfrsource4;
13092 if (!have_xfrdscp)
13093 dscp = zone->altxfrsource4dscp;
13094 } else if (!have_xfrsource) {
13095 zone->sourceaddr = zone->xfrsource4;
13096 if (!have_xfrdscp)
13097 dscp = zone->xfrsource4dscp;
13098 }
13099 break;
13100 case PF_INET6:
13101 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13102 zone->sourceaddr = zone->altxfrsource6;
13103 if (!have_xfrdscp)
13104 dscp = zone->altxfrsource6dscp;
13105 } else if (!have_xfrsource) {
13106 zone->sourceaddr = zone->xfrsource6;
13107 if (!have_xfrdscp)
13108 dscp = zone->xfrsource6dscp;
13109 }
13110 break;
13111 default:
13112 result = ISC_R_NOTIMPLEMENTED;
13113 POST(result);
13114 goto cleanup;
13115 }
13116 timeout = 15;
13117 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13118 timeout = 30;
13119 result = dns_request_createvia(zone->view->requestmgr, message,
13120 &zone->sourceaddr, &zone->masteraddr,
13121 dscp, DNS_REQUESTOPT_TCP, key,
13122 timeout * 3, timeout, 0, zone->task,
13123 stub_callback, stub, &zone->request);
13124 if (result != ISC_R_SUCCESS) {
13125 zone_debuglog(zone, me, 1,
13126 "dns_request_createvia() failed: %s",
13127 dns_result_totext(result));
13128 goto cleanup;
13129 }
13130 dns_message_destroy(&message);
13131 goto unlock;
13132
13133 cleanup:
13134 cancel_refresh(zone);
13135 if (stub != NULL) {
13136 stub->magic = 0;
13137 if (stub->version != NULL)
13138 dns_db_closeversion(stub->db, &stub->version,
13139 false);
13140 if (stub->db != NULL)
13141 dns_db_detach(&stub->db);
13142 if (stub->zone != NULL)
13143 zone_idetach(&stub->zone);
13144 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13145 }
13146 if (message != NULL)
13147 dns_message_destroy(&message);
13148 unlock:
13149 if (key != NULL)
13150 dns_tsigkey_detach(&key);
13151 return;
13152 }
13153
13154 /*
13155 * Handle the control event. Note that although this event causes the zone
13156 * to shut down, it is not a shutdown event in the sense of the task library.
13157 */
13158 static void
13159 zone_shutdown(isc_task_t *task, isc_event_t *event) {
13160 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
13161 bool free_needed, linked = false;
13162 dns_zone_t *raw = NULL, *secure = NULL;
13163
13164 UNUSED(task);
13165 REQUIRE(DNS_ZONE_VALID(zone));
13166 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
13167 INSIST(isc_refcount_current(&zone->erefs) == 0);
13168
13169 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
13170
13171 /*
13172 * Stop things being restarted after we cancel them below.
13173 */
13174 LOCK_ZONE(zone);
13175 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
13176 UNLOCK_ZONE(zone);
13177
13178 /*
13179 * If we were waiting for xfrin quota, step out of
13180 * the queue.
13181 * If there's no zone manager, we can't be waiting for the
13182 * xfrin quota
13183 */
13184 if (zone->zmgr != NULL) {
13185 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13186 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
13187 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
13188 statelink);
13189 linked = true;
13190 zone->statelist = NULL;
13191 }
13192 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
13193 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
13194 statelink);
13195 zone->statelist = NULL;
13196 zmgr_resume_xfrs(zone->zmgr, false);
13197 }
13198 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13199 }
13200
13201 /*
13202 * In task context, no locking required. See zone_xfrdone().
13203 */
13204 if (zone->xfr != NULL)
13205 dns_xfrin_shutdown(zone->xfr);
13206
13207 /* Safe to release the zone now */
13208 if (zone->zmgr != NULL)
13209 dns_zonemgr_releasezone(zone->zmgr, zone);
13210
13211 LOCK_ZONE(zone);
13212 INSIST(zone != zone->raw);
13213 if (linked) {
13214 INSIST(zone->irefs > 0);
13215 zone->irefs--;
13216 }
13217 if (zone->request != NULL) {
13218 dns_request_cancel(zone->request);
13219 }
13220
13221 if (zone->readio != NULL)
13222 zonemgr_cancelio(zone->readio);
13223
13224 if (zone->lctx != NULL)
13225 dns_loadctx_cancel(zone->lctx);
13226
13227 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
13228 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13229 if (zone->writeio != NULL)
13230 zonemgr_cancelio(zone->writeio);
13231
13232 if (zone->dctx != NULL)
13233 dns_dumpctx_cancel(zone->dctx);
13234 }
13235
13236 notify_cancel(zone);
13237
13238 forward_cancel(zone);
13239
13240 if (zone->timer != NULL) {
13241 isc_timer_detach(&zone->timer);
13242 INSIST(zone->irefs > 0);
13243 zone->irefs--;
13244 }
13245
13246 /*
13247 * We have now canceled everything set the flag to allow exit_check()
13248 * to succeed. We must not unlock between setting this flag and
13249 * calling exit_check().
13250 */
13251 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
13252 free_needed = exit_check(zone);
13253 if (inline_secure(zone)) {
13254 raw = zone->raw;
13255 zone->raw = NULL;
13256 }
13257 if (inline_raw(zone)) {
13258 secure = zone->secure;
13259 zone->secure = NULL;
13260 }
13261 UNLOCK_ZONE(zone);
13262 if (raw != NULL)
13263 dns_zone_detach(&raw);
13264 if (secure != NULL)
13265 dns_zone_idetach(&secure);
13266 if (free_needed)
13267 zone_free(zone);
13268 }
13269
13270 static void
13271 zone_timer(isc_task_t *task, isc_event_t *event) {
13272 const char me[] = "zone_timer";
13273 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
13274
13275 UNUSED(task);
13276 REQUIRE(DNS_ZONE_VALID(zone));
13277
13278 ENTER;
13279
13280 zone_maintenance(zone);
13281
13282 isc_event_free(&event);
13283 }
13284
13285 static void
13286 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
13287 const char me[] = "zone_settimer";
13288 isc_time_t next;
13289 isc_result_t result;
13290
13291 REQUIRE(DNS_ZONE_VALID(zone));
13292 ENTER;
13293
13294 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13295 return;
13296
13297 isc_time_settoepoch(&next);
13298
13299 switch (zone->type) {
13300 case dns_zone_redirect:
13301 if (zone->masters != NULL)
13302 goto treat_as_slave;
13303 /* FALLTHROUGH */
13304
13305 case dns_zone_master:
13306 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
13307 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
13308 next = zone->notifytime;
13309 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13310 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13311 INSIST(!isc_time_isepoch(&zone->dumptime));
13312 if (isc_time_isepoch(&next) ||
13313 isc_time_compare(&zone->dumptime, &next) < 0)
13314 next = zone->dumptime;
13315 }
13316 if (zone->type == dns_zone_redirect)
13317 break;
13318 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
13319 !isc_time_isepoch(&zone->refreshkeytime)) {
13320 if (isc_time_isepoch(&next) ||
13321 isc_time_compare(&zone->refreshkeytime, &next) < 0)
13322 next = zone->refreshkeytime;
13323 }
13324 if (!isc_time_isepoch(&zone->resigntime)) {
13325 if (isc_time_isepoch(&next) ||
13326 isc_time_compare(&zone->resigntime, &next) < 0)
13327 next = zone->resigntime;
13328 }
13329 if (!isc_time_isepoch(&zone->keywarntime)) {
13330 if (isc_time_isepoch(&next) ||
13331 isc_time_compare(&zone->keywarntime, &next) < 0)
13332 next = zone->keywarntime;
13333 }
13334 if (!isc_time_isepoch(&zone->signingtime)) {
13335 if (isc_time_isepoch(&next) ||
13336 isc_time_compare(&zone->signingtime, &next) < 0)
13337 next = zone->signingtime;
13338 }
13339 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
13340 if (isc_time_isepoch(&next) ||
13341 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
13342 next = zone->nsec3chaintime;
13343 }
13344 break;
13345
13346 case dns_zone_slave:
13347 case dns_zone_mirror:
13348 treat_as_slave:
13349 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
13350 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
13351 next = zone->notifytime;
13352 /* FALLTHROUGH */
13353
13354 case dns_zone_stub:
13355 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
13356 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
13357 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
13358 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
13359 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
13360 !isc_time_isepoch(&zone->refreshtime) &&
13361 (isc_time_isepoch(&next) ||
13362 isc_time_compare(&zone->refreshtime, &next) < 0))
13363 next = zone->refreshtime;
13364 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13365 !isc_time_isepoch(&zone->expiretime)) {
13366 if (isc_time_isepoch(&next) ||
13367 isc_time_compare(&zone->expiretime, &next) < 0)
13368 next = zone->expiretime;
13369 }
13370 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13371 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13372 INSIST(!isc_time_isepoch(&zone->dumptime));
13373 if (isc_time_isepoch(&next) ||
13374 isc_time_compare(&zone->dumptime, &next) < 0)
13375 next = zone->dumptime;
13376 }
13377 break;
13378
13379 case dns_zone_key:
13380 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13381 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13382 INSIST(!isc_time_isepoch(&zone->dumptime));
13383 if (isc_time_isepoch(&next) ||
13384 isc_time_compare(&zone->dumptime, &next) < 0)
13385 next = zone->dumptime;
13386 }
13387 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
13388 if (isc_time_isepoch(&next) ||
13389 (!isc_time_isepoch(&zone->refreshkeytime) &&
13390 isc_time_compare(&zone->refreshkeytime, &next) < 0))
13391 next = zone->refreshkeytime;
13392 }
13393 break;
13394
13395 default:
13396 break;
13397 }
13398
13399 if (isc_time_isepoch(&next)) {
13400 zone_debuglog(zone, me, 10, "settimer inactive");
13401 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
13402 NULL, NULL, true);
13403 if (result != ISC_R_SUCCESS)
13404 dns_zone_log(zone, ISC_LOG_ERROR,
13405 "could not deactivate zone timer: %s",
13406 isc_result_totext(result));
13407 } else {
13408 if (isc_time_compare(&next, now) <= 0)
13409 next = *now;
13410 result = isc_timer_reset(zone->timer, isc_timertype_once,
13411 &next, NULL, true);
13412 if (result != ISC_R_SUCCESS)
13413 dns_zone_log(zone, ISC_LOG_ERROR,
13414 "could not reset zone timer: %s",
13415 isc_result_totext(result));
13416 }
13417 }
13418
13419 static void
13420 cancel_refresh(dns_zone_t *zone) {
13421 const char me[] = "cancel_refresh";
13422 isc_time_t now;
13423
13424 /*
13425 * 'zone' locked by caller.
13426 */
13427
13428 REQUIRE(DNS_ZONE_VALID(zone));
13429 REQUIRE(LOCKED_ZONE(zone));
13430
13431 ENTER;
13432
13433 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13434 TIME_NOW(&now);
13435 zone_settimer(zone, &now);
13436 }
13437
13438 static isc_result_t
13439 notify_createmessage(dns_zone_t *zone, unsigned int flags,
13440 dns_message_t **messagep)
13441 {
13442 dns_db_t *zonedb = NULL;
13443 dns_dbnode_t *node = NULL;
13444 dns_dbversion_t *version = NULL;
13445 dns_message_t *message = NULL;
13446 dns_rdataset_t rdataset;
13447 dns_rdata_t rdata = DNS_RDATA_INIT;
13448
13449 dns_name_t *tempname = NULL;
13450 dns_rdata_t *temprdata = NULL;
13451 dns_rdatalist_t *temprdatalist = NULL;
13452 dns_rdataset_t *temprdataset = NULL;
13453
13454 isc_result_t result;
13455 isc_region_t r;
13456 isc_buffer_t *b = NULL;
13457
13458 REQUIRE(DNS_ZONE_VALID(zone));
13459 REQUIRE(messagep != NULL && *messagep == NULL);
13460
13461 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
13462 &message);
13463 if (result != ISC_R_SUCCESS)
13464 return (result);
13465
13466 message->opcode = dns_opcode_notify;
13467 message->flags |= DNS_MESSAGEFLAG_AA;
13468 message->rdclass = zone->rdclass;
13469
13470 result = dns_message_gettempname(message, &tempname);
13471 if (result != ISC_R_SUCCESS)
13472 goto cleanup;
13473
13474 result = dns_message_gettemprdataset(message, &temprdataset);
13475 if (result != ISC_R_SUCCESS)
13476 goto cleanup;
13477
13478 /*
13479 * Make question.
13480 */
13481 dns_name_init(tempname, NULL);
13482 dns_name_clone(&zone->origin, tempname);
13483 dns_rdataset_makequestion(temprdataset, zone->rdclass,
13484 dns_rdatatype_soa);
13485 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13486 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
13487 tempname = NULL;
13488 temprdataset = NULL;
13489
13490 if ((flags & DNS_NOTIFY_NOSOA) != 0)
13491 goto done;
13492
13493 result = dns_message_gettempname(message, &tempname);
13494 if (result != ISC_R_SUCCESS)
13495 goto soa_cleanup;
13496 result = dns_message_gettemprdata(message, &temprdata);
13497 if (result != ISC_R_SUCCESS)
13498 goto soa_cleanup;
13499 result = dns_message_gettemprdataset(message, &temprdataset);
13500 if (result != ISC_R_SUCCESS)
13501 goto soa_cleanup;
13502 result = dns_message_gettemprdatalist(message, &temprdatalist);
13503 if (result != ISC_R_SUCCESS)
13504 goto soa_cleanup;
13505
13506 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13507 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
13508 dns_db_attach(zone->db, &zonedb);
13509 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13510
13511 dns_name_init(tempname, NULL);
13512 dns_name_clone(&zone->origin, tempname);
13513 dns_db_currentversion(zonedb, &version);
13514 result = dns_db_findnode(zonedb, tempname, false, &node);
13515 if (result != ISC_R_SUCCESS)
13516 goto soa_cleanup;
13517
13518 dns_rdataset_init(&rdataset);
13519 result = dns_db_findrdataset(zonedb, node, version,
13520 dns_rdatatype_soa,
13521 dns_rdatatype_none, 0, &rdataset,
13522 NULL);
13523 if (result != ISC_R_SUCCESS)
13524 goto soa_cleanup;
13525 result = dns_rdataset_first(&rdataset);
13526 if (result != ISC_R_SUCCESS)
13527 goto soa_cleanup;
13528 dns_rdataset_current(&rdataset, &rdata);
13529 dns_rdata_toregion(&rdata, &r);
13530 result = isc_buffer_allocate(zone->mctx, &b, r.length);
13531 if (result != ISC_R_SUCCESS)
13532 goto soa_cleanup;
13533 isc_buffer_putmem(b, r.base, r.length);
13534 isc_buffer_usedregion(b, &r);
13535 dns_rdata_init(temprdata);
13536 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
13537 dns_message_takebuffer(message, &b);
13538 result = dns_rdataset_next(&rdataset);
13539 dns_rdataset_disassociate(&rdataset);
13540 if (result != ISC_R_NOMORE)
13541 goto soa_cleanup;
13542 temprdatalist->rdclass = rdata.rdclass;
13543 temprdatalist->type = rdata.type;
13544 temprdatalist->ttl = rdataset.ttl;
13545 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
13546
13547 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
13548 if (result != ISC_R_SUCCESS)
13549 goto soa_cleanup;
13550
13551 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13552 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
13553 temprdatalist = NULL;
13554 temprdataset = NULL;
13555 temprdata = NULL;
13556 tempname = NULL;
13557
13558 soa_cleanup:
13559 if (node != NULL)
13560 dns_db_detachnode(zonedb, &node);
13561 if (version != NULL)
13562 dns_db_closeversion(zonedb, &version, false);
13563 if (zonedb != NULL)
13564 dns_db_detach(&zonedb);
13565 if (tempname != NULL)
13566 dns_message_puttempname(message, &tempname);
13567 if (temprdata != NULL)
13568 dns_message_puttemprdata(message, &temprdata);
13569 if (temprdataset != NULL)
13570 dns_message_puttemprdataset(message, &temprdataset);
13571 if (temprdatalist != NULL)
13572 dns_message_puttemprdatalist(message, &temprdatalist);
13573
13574 done:
13575 *messagep = message;
13576 return (ISC_R_SUCCESS);
13577
13578 cleanup:
13579 if (tempname != NULL)
13580 dns_message_puttempname(message, &tempname);
13581 if (temprdataset != NULL)
13582 dns_message_puttemprdataset(message, &temprdataset);
13583 dns_message_destroy(&message);
13584 return (result);
13585 }
13586
13587 isc_result_t
13588 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
13589 isc_sockaddr_t *to, dns_message_t *msg)
13590 {
13591 unsigned int i;
13592 dns_rdata_soa_t soa;
13593 dns_rdataset_t *rdataset = NULL;
13594 dns_rdata_t rdata = DNS_RDATA_INIT;
13595 isc_result_t result;
13596 char fromtext[ISC_SOCKADDR_FORMATSIZE];
13597 int match = 0;
13598 isc_netaddr_t netaddr;
13599 uint32_t serial = 0;
13600 bool have_serial = false;
13601 dns_tsigkey_t *tsigkey;
13602 dns_name_t *tsig;
13603
13604 REQUIRE(DNS_ZONE_VALID(zone));
13605
13606 /*
13607 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
13608 * ROLLOVER.
13609 *
13610 * SOA: RFC1996
13611 * Check that 'from' is a valid notify source, (zone->masters).
13612 * Return DNS_R_REFUSED if not.
13613 *
13614 * If the notify message contains a serial number check it
13615 * against the zones serial and return if <= current serial
13616 *
13617 * If a refresh check is progress, if so just record the
13618 * fact we received a NOTIFY and from where and return.
13619 * We will perform a new refresh check when the current one
13620 * completes. Return ISC_R_SUCCESS.
13621 *
13622 * Otherwise initiate a refresh check using 'from' as the
13623 * first address to check. Return ISC_R_SUCCESS.
13624 */
13625
13626 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
13627
13628 /*
13629 * Notify messages are processed by the raw zone.
13630 */
13631 LOCK_ZONE(zone);
13632 INSIST(zone != zone->raw);
13633 if (inline_secure(zone)) {
13634 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
13635 UNLOCK_ZONE(zone);
13636 return (result);
13637 }
13638 /*
13639 * We only handle NOTIFY (SOA) at the present.
13640 */
13641 if (isc_sockaddr_pf(from) == PF_INET)
13642 inc_stats(zone, dns_zonestatscounter_notifyinv4);
13643 else
13644 inc_stats(zone, dns_zonestatscounter_notifyinv6);
13645 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
13646 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
13647 dns_rdatatype_soa, dns_rdatatype_none,
13648 NULL, NULL) != ISC_R_SUCCESS) {
13649 UNLOCK_ZONE(zone);
13650 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
13651 dns_zone_log(zone, ISC_LOG_NOTICE,
13652 "NOTIFY with no "
13653 "question section from: %s", fromtext);
13654 return (DNS_R_FORMERR);
13655 }
13656 dns_zone_log(zone, ISC_LOG_NOTICE,
13657 "NOTIFY zone does not match");
13658 return (DNS_R_NOTIMP);
13659 }
13660
13661 /*
13662 * If we are a master zone just succeed.
13663 */
13664 if (zone->type == dns_zone_master) {
13665 UNLOCK_ZONE(zone);
13666 return (ISC_R_SUCCESS);
13667 }
13668
13669 isc_netaddr_fromsockaddr(&netaddr, from);
13670 for (i = 0; i < zone->masterscnt; i++) {
13671 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
13672 break;
13673 if (zone->view->aclenv.match_mapped &&
13674 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
13675 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
13676 isc_netaddr_t na1, na2;
13677 isc_netaddr_fromv4mapped(&na1, &netaddr);
13678 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
13679 if (isc_netaddr_equal(&na1, &na2))
13680 break;
13681 }
13682 }
13683
13684 /*
13685 * Accept notify requests from non masters if they are on
13686 * 'zone->notify_acl'.
13687 */
13688 tsigkey = dns_message_gettsigkey(msg);
13689 tsig = dns_tsigkey_identity(tsigkey);
13690 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
13691 (dns_acl_match(&netaddr, tsig, zone->notify_acl,
13692 &zone->view->aclenv, &match,
13693 NULL) == ISC_R_SUCCESS) &&
13694 match > 0)
13695 {
13696 /* Accept notify. */
13697 } else if (i >= zone->masterscnt) {
13698 UNLOCK_ZONE(zone);
13699 dns_zone_log(zone, ISC_LOG_INFO,
13700 "refused notify from non-master: %s", fromtext);
13701 inc_stats(zone, dns_zonestatscounter_notifyrej);
13702 return (DNS_R_REFUSED);
13703 }
13704
13705 /*
13706 * If the zone is loaded and there are answers check the serial
13707 * to see if we need to do a refresh. Do not worry about this
13708 * check if we are a dialup zone as we use the notify request
13709 * to trigger a refresh check.
13710 */
13711 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
13712 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13713 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
13714 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
13715 &zone->origin,
13716 dns_rdatatype_soa,
13717 dns_rdatatype_none, NULL,
13718 &rdataset);
13719 if (result == ISC_R_SUCCESS)
13720 result = dns_rdataset_first(rdataset);
13721 if (result == ISC_R_SUCCESS) {
13722 uint32_t oldserial;
13723 unsigned int soacount;
13724
13725 dns_rdataset_current(rdataset, &rdata);
13726 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13727 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13728 serial = soa.serial;
13729 have_serial = true;
13730 /*
13731 * The following should safely be performed without DB
13732 * lock and succeed in this context.
13733 */
13734 result = zone_get_from_db(zone, zone->db, NULL,
13735 &soacount, &oldserial, NULL,
13736 NULL, NULL, NULL, NULL);
13737 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13738 RUNTIME_CHECK(soacount > 0U);
13739 if (isc_serial_le(serial, oldserial)) {
13740 dns_zone_log(zone,
13741 ISC_LOG_INFO,
13742 "notify from %s: "
13743 "zone is up to date",
13744 fromtext);
13745 UNLOCK_ZONE(zone);
13746 return (ISC_R_SUCCESS);
13747 }
13748 }
13749 }
13750
13751 /*
13752 * If we got this far and there was a refresh in progress just
13753 * let it complete. Record where we got the notify from so we
13754 * can perform a refresh check when the current one completes
13755 */
13756 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
13757 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13758 zone->notifyfrom = *from;
13759 UNLOCK_ZONE(zone);
13760 if (have_serial)
13761 dns_zone_log(zone, ISC_LOG_INFO,
13762 "notify from %s: serial %u: refresh in "
13763 "progress, refresh check queued",
13764 fromtext, serial);
13765 else
13766 dns_zone_log(zone, ISC_LOG_INFO,
13767 "notify from %s: refresh in progress, "
13768 "refresh check queued", fromtext);
13769 return (ISC_R_SUCCESS);
13770 }
13771 if (have_serial)
13772 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
13773 fromtext, serial);
13774 else
13775 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
13776 fromtext);
13777 zone->notifyfrom = *from;
13778 UNLOCK_ZONE(zone);
13779
13780 if (to != NULL) {
13781 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
13782 }
13783 dns_zone_refresh(zone);
13784 return (ISC_R_SUCCESS);
13785 }
13786
13787 void
13788 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
13789
13790 REQUIRE(DNS_ZONE_VALID(zone));
13791
13792 LOCK_ZONE(zone);
13793 if (zone->notify_acl != NULL)
13794 dns_acl_detach(&zone->notify_acl);
13795 dns_acl_attach(acl, &zone->notify_acl);
13796 UNLOCK_ZONE(zone);
13797 }
13798
13799 void
13800 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
13801
13802 REQUIRE(DNS_ZONE_VALID(zone));
13803
13804 LOCK_ZONE(zone);
13805 if (zone->query_acl != NULL)
13806 dns_acl_detach(&zone->query_acl);
13807 dns_acl_attach(acl, &zone->query_acl);
13808 UNLOCK_ZONE(zone);
13809 }
13810
13811 void
13812 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
13813
13814 REQUIRE(DNS_ZONE_VALID(zone));
13815
13816 LOCK_ZONE(zone);
13817 if (zone->queryon_acl != NULL)
13818 dns_acl_detach(&zone->queryon_acl);
13819 dns_acl_attach(acl, &zone->queryon_acl);
13820 UNLOCK_ZONE(zone);
13821 }
13822
13823 void
13824 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
13825
13826 REQUIRE(DNS_ZONE_VALID(zone));
13827
13828 LOCK_ZONE(zone);
13829 if (zone->update_acl != NULL)
13830 dns_acl_detach(&zone->update_acl);
13831 dns_acl_attach(acl, &zone->update_acl);
13832 UNLOCK_ZONE(zone);
13833 }
13834
13835 void
13836 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
13837
13838 REQUIRE(DNS_ZONE_VALID(zone));
13839
13840 LOCK_ZONE(zone);
13841 if (zone->forward_acl != NULL)
13842 dns_acl_detach(&zone->forward_acl);
13843 dns_acl_attach(acl, &zone->forward_acl);
13844 UNLOCK_ZONE(zone);
13845 }
13846
13847 void
13848 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
13849
13850 REQUIRE(DNS_ZONE_VALID(zone));
13851
13852 LOCK_ZONE(zone);
13853 if (zone->xfr_acl != NULL)
13854 dns_acl_detach(&zone->xfr_acl);
13855 dns_acl_attach(acl, &zone->xfr_acl);
13856 UNLOCK_ZONE(zone);
13857 }
13858
13859 dns_acl_t *
13860 dns_zone_getnotifyacl(dns_zone_t *zone) {
13861
13862 REQUIRE(DNS_ZONE_VALID(zone));
13863
13864 return (zone->notify_acl);
13865 }
13866
13867 dns_acl_t *
13868 dns_zone_getqueryacl(dns_zone_t *zone) {
13869
13870 REQUIRE(DNS_ZONE_VALID(zone));
13871
13872 return (zone->query_acl);
13873 }
13874
13875 dns_acl_t *
13876 dns_zone_getqueryonacl(dns_zone_t *zone) {
13877
13878 REQUIRE(DNS_ZONE_VALID(zone));
13879
13880 return (zone->queryon_acl);
13881 }
13882
13883 dns_acl_t *
13884 dns_zone_getupdateacl(dns_zone_t *zone) {
13885
13886 REQUIRE(DNS_ZONE_VALID(zone));
13887
13888 return (zone->update_acl);
13889 }
13890
13891 dns_acl_t *
13892 dns_zone_getforwardacl(dns_zone_t *zone) {
13893
13894 REQUIRE(DNS_ZONE_VALID(zone));
13895
13896 return (zone->forward_acl);
13897 }
13898
13899 dns_acl_t *
13900 dns_zone_getxfracl(dns_zone_t *zone) {
13901
13902 REQUIRE(DNS_ZONE_VALID(zone));
13903
13904 return (zone->xfr_acl);
13905 }
13906
13907 void
13908 dns_zone_clearupdateacl(dns_zone_t *zone) {
13909
13910 REQUIRE(DNS_ZONE_VALID(zone));
13911
13912 LOCK_ZONE(zone);
13913 if (zone->update_acl != NULL)
13914 dns_acl_detach(&zone->update_acl);
13915 UNLOCK_ZONE(zone);
13916 }
13917
13918 void
13919 dns_zone_clearforwardacl(dns_zone_t *zone) {
13920
13921 REQUIRE(DNS_ZONE_VALID(zone));
13922
13923 LOCK_ZONE(zone);
13924 if (zone->forward_acl != NULL)
13925 dns_acl_detach(&zone->forward_acl);
13926 UNLOCK_ZONE(zone);
13927 }
13928
13929 void
13930 dns_zone_clearnotifyacl(dns_zone_t *zone) {
13931
13932 REQUIRE(DNS_ZONE_VALID(zone));
13933
13934 LOCK_ZONE(zone);
13935 if (zone->notify_acl != NULL)
13936 dns_acl_detach(&zone->notify_acl);
13937 UNLOCK_ZONE(zone);
13938 }
13939
13940 void
13941 dns_zone_clearqueryacl(dns_zone_t *zone) {
13942
13943 REQUIRE(DNS_ZONE_VALID(zone));
13944
13945 LOCK_ZONE(zone);
13946 if (zone->query_acl != NULL)
13947 dns_acl_detach(&zone->query_acl);
13948 UNLOCK_ZONE(zone);
13949 }
13950
13951 void
13952 dns_zone_clearqueryonacl(dns_zone_t *zone) {
13953
13954 REQUIRE(DNS_ZONE_VALID(zone));
13955
13956 LOCK_ZONE(zone);
13957 if (zone->queryon_acl != NULL)
13958 dns_acl_detach(&zone->queryon_acl);
13959 UNLOCK_ZONE(zone);
13960 }
13961
13962 void
13963 dns_zone_clearxfracl(dns_zone_t *zone) {
13964
13965 REQUIRE(DNS_ZONE_VALID(zone));
13966
13967 LOCK_ZONE(zone);
13968 if (zone->xfr_acl != NULL)
13969 dns_acl_detach(&zone->xfr_acl);
13970 UNLOCK_ZONE(zone);
13971 }
13972
13973 bool
13974 dns_zone_getupdatedisabled(dns_zone_t *zone) {
13975 REQUIRE(DNS_ZONE_VALID(zone));
13976 return (zone->update_disabled);
13977
13978 }
13979
13980 void
13981 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
13982 REQUIRE(DNS_ZONE_VALID(zone));
13983 zone->update_disabled = state;
13984 }
13985
13986 bool
13987 dns_zone_getzeronosoattl(dns_zone_t *zone) {
13988 REQUIRE(DNS_ZONE_VALID(zone));
13989 return (zone->zero_no_soa_ttl);
13990
13991 }
13992
13993 void
13994 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
13995 REQUIRE(DNS_ZONE_VALID(zone));
13996 zone->zero_no_soa_ttl = state;
13997 }
13998
13999 void
14000 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
14001 REQUIRE(DNS_ZONE_VALID(zone));
14002
14003 zone->check_names = severity;
14004 }
14005
14006 dns_severity_t
14007 dns_zone_getchecknames(dns_zone_t *zone) {
14008 REQUIRE(DNS_ZONE_VALID(zone));
14009
14010 return (zone->check_names);
14011 }
14012
14013 void
14014 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
14015 REQUIRE(DNS_ZONE_VALID(zone));
14016
14017 zone->journalsize = size;
14018 }
14019
14020 int32_t
14021 dns_zone_getjournalsize(dns_zone_t *zone) {
14022 REQUIRE(DNS_ZONE_VALID(zone));
14023
14024 return (zone->journalsize);
14025 }
14026
14027 static void
14028 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
14029 isc_result_t result = ISC_R_FAILURE;
14030 isc_buffer_t buffer;
14031
14032 REQUIRE(buf != NULL);
14033 REQUIRE(length > 1U);
14034
14035 /*
14036 * Leave space for terminating '\0'.
14037 */
14038 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14039 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
14040 if (dns_name_dynamic(&zone->origin))
14041 result = dns_name_totext(&zone->origin, true, &buffer);
14042 if (result != ISC_R_SUCCESS &&
14043 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
14044 isc_buffer_putstr(&buffer, "<UNKNOWN>");
14045
14046 if (isc_buffer_availablelength(&buffer) > 0)
14047 isc_buffer_putstr(&buffer, "/");
14048 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
14049 }
14050
14051 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
14052 strcmp(zone->view->name, "_default") != 0 &&
14053 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
14054 isc_buffer_putstr(&buffer, "/");
14055 isc_buffer_putstr(&buffer, zone->view->name);
14056 }
14057 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
14058 isc_buffer_putstr(&buffer, " (signed)");
14059 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
14060 isc_buffer_putstr(&buffer, " (unsigned)");
14061
14062 buf[isc_buffer_usedlength(&buffer)] = '\0';
14063 }
14064
14065 static void
14066 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
14067 isc_result_t result = ISC_R_FAILURE;
14068 isc_buffer_t buffer;
14069
14070 REQUIRE(buf != NULL);
14071 REQUIRE(length > 1U);
14072
14073 /*
14074 * Leave space for terminating '\0'.
14075 */
14076 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14077 if (dns_name_dynamic(&zone->origin))
14078 result = dns_name_totext(&zone->origin, true, &buffer);
14079 if (result != ISC_R_SUCCESS &&
14080 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
14081 isc_buffer_putstr(&buffer, "<UNKNOWN>");
14082
14083 buf[isc_buffer_usedlength(&buffer)] = '\0';
14084 }
14085
14086 static void
14087 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
14088 isc_buffer_t buffer;
14089
14090 REQUIRE(buf != NULL);
14091 REQUIRE(length > 1U);
14092
14093 /*
14094 * Leave space for terminating '\0'.
14095 */
14096 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14097 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
14098
14099 buf[isc_buffer_usedlength(&buffer)] = '\0';
14100 }
14101
14102 static void
14103 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
14104 isc_buffer_t buffer;
14105
14106 REQUIRE(buf != NULL);
14107 REQUIRE(length > 1U);
14108
14109
14110 /*
14111 * Leave space for terminating '\0'.
14112 */
14113 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14114
14115 if (zone->view == NULL) {
14116 isc_buffer_putstr(&buffer, "_none");
14117 } else if (strlen(zone->view->name)
14118 < isc_buffer_availablelength(&buffer)) {
14119 isc_buffer_putstr(&buffer, zone->view->name);
14120 } else {
14121 isc_buffer_putstr(&buffer, "_toolong");
14122 }
14123
14124 buf[isc_buffer_usedlength(&buffer)] = '\0';
14125 }
14126
14127 void
14128 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
14129 REQUIRE(DNS_ZONE_VALID(zone));
14130 REQUIRE(buf != NULL);
14131 zone_namerd_tostr(zone, buf, length);
14132 }
14133
14134 void
14135 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
14136 REQUIRE(DNS_ZONE_VALID(zone));
14137 REQUIRE(buf != NULL);
14138 zone_name_tostr(zone, buf, length);
14139 }
14140
14141 void
14142 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
14143 const char *prefix, const char *fmt, va_list ap)
14144 {
14145 char message[4096];
14146 const char *zstr;
14147
14148 if (!isc_log_wouldlog(dns_lctx, level)) {
14149 return;
14150 }
14151
14152 vsnprintf(message, sizeof(message), fmt, ap);
14153
14154 switch (zone->type) {
14155 case dns_zone_key:
14156 zstr = "managed-keys-zone";
14157 break;
14158 case dns_zone_redirect:
14159 zstr = "redirect-zone";
14160 break;
14161 default:
14162 zstr = "zone ";
14163 }
14164
14165 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
14166 "%s%s%s%s: %s",
14167 (prefix != NULL ? prefix : ""),
14168 (prefix != NULL ? ": " : ""),
14169 zstr, zone->strnamerd, message);
14170 }
14171
14172 static void
14173 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14174 va_list ap;
14175
14176 va_start(ap, fmt);
14177 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
14178 va_end(ap);
14179 }
14180
14181 void
14182 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
14183 int level, const char *fmt, ...)
14184 {
14185 va_list ap;
14186
14187 va_start(ap, fmt);
14188 dns_zone_logv(zone, category, level, NULL, fmt, ap);
14189 va_end(ap);
14190 }
14191
14192 void
14193 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14194 va_list ap;
14195
14196 va_start(ap, fmt);
14197 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
14198 va_end(ap);
14199 }
14200
14201 static void
14202 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
14203 const char *fmt, ...)
14204 {
14205 int level = ISC_LOG_DEBUG(debuglevel);
14206 va_list ap;
14207
14208 va_start(ap, fmt);
14209 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
14210 va_end(ap);
14211 }
14212
14213 static void
14214 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14215 va_list ap;
14216
14217 va_start(ap, fmt);
14218 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
14219 va_end(ap);
14220 }
14221
14222 static int
14223 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
14224 {
14225 isc_result_t result;
14226 dns_name_t *name;
14227 dns_rdataset_t *curr;
14228 int count = 0;
14229
14230 result = dns_message_firstname(msg, section);
14231 while (result == ISC_R_SUCCESS) {
14232 name = NULL;
14233 dns_message_currentname(msg, section, &name);
14234
14235 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
14236 curr = ISC_LIST_PREV(curr, link)) {
14237 if (curr->type == type)
14238 count++;
14239 }
14240 result = dns_message_nextname(msg, section);
14241 }
14242
14243 return (count);
14244 }
14245
14246 void
14247 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
14248 REQUIRE(DNS_ZONE_VALID(zone));
14249
14250 zone->maxxfrin = maxxfrin;
14251 }
14252
14253 uint32_t
14254 dns_zone_getmaxxfrin(dns_zone_t *zone) {
14255 REQUIRE(DNS_ZONE_VALID(zone));
14256
14257 return (zone->maxxfrin);
14258 }
14259
14260 void
14261 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
14262 REQUIRE(DNS_ZONE_VALID(zone));
14263 zone->maxxfrout = maxxfrout;
14264 }
14265
14266 uint32_t
14267 dns_zone_getmaxxfrout(dns_zone_t *zone) {
14268 REQUIRE(DNS_ZONE_VALID(zone));
14269
14270 return (zone->maxxfrout);
14271 }
14272
14273 dns_zonetype_t
14274 dns_zone_gettype(dns_zone_t *zone) {
14275 REQUIRE(DNS_ZONE_VALID(zone));
14276
14277 return (zone->type);
14278 }
14279
14280 dns_zonetype_t
14281 dns_zone_getredirecttype(dns_zone_t *zone) {
14282 REQUIRE(DNS_ZONE_VALID(zone));
14283 REQUIRE(zone->type == dns_zone_redirect);
14284
14285 return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
14286 }
14287
14288 dns_name_t *
14289 dns_zone_getorigin(dns_zone_t *zone) {
14290 REQUIRE(DNS_ZONE_VALID(zone));
14291
14292 return (&zone->origin);
14293 }
14294
14295 void
14296 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
14297 REQUIRE(DNS_ZONE_VALID(zone));
14298
14299 LOCK_ZONE(zone);
14300 if (zone->task != NULL)
14301 isc_task_detach(&zone->task);
14302 isc_task_attach(task, &zone->task);
14303 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14304 if (zone->db != NULL)
14305 dns_db_settask(zone->db, zone->task);
14306 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14307 UNLOCK_ZONE(zone);
14308 }
14309
14310 void
14311 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
14312 REQUIRE(DNS_ZONE_VALID(zone));
14313 isc_task_attach(zone->task, target);
14314 }
14315
14316 void
14317 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
14318 REQUIRE(DNS_ZONE_VALID(zone));
14319
14320 if (idlein == 0)
14321 idlein = DNS_DEFAULT_IDLEIN;
14322 zone->idlein = idlein;
14323 }
14324
14325 uint32_t
14326 dns_zone_getidlein(dns_zone_t *zone) {
14327 REQUIRE(DNS_ZONE_VALID(zone));
14328
14329 return (zone->idlein);
14330 }
14331
14332 void
14333 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
14334 REQUIRE(DNS_ZONE_VALID(zone));
14335
14336 zone->idleout = idleout;
14337 }
14338
14339 uint32_t
14340 dns_zone_getidleout(dns_zone_t *zone) {
14341 REQUIRE(DNS_ZONE_VALID(zone));
14342
14343 return (zone->idleout);
14344 }
14345
14346 static void
14347 notify_done(isc_task_t *task, isc_event_t *event) {
14348 dns_requestevent_t *revent = (dns_requestevent_t *)event;
14349 dns_notify_t *notify;
14350 isc_result_t result;
14351 dns_message_t *message = NULL;
14352 isc_buffer_t buf;
14353 char rcode[128];
14354 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
14355
14356 UNUSED(task);
14357
14358 notify = event->ev_arg;
14359 REQUIRE(DNS_NOTIFY_VALID(notify));
14360 INSIST(task == notify->zone->task);
14361
14362 isc_buffer_init(&buf, rcode, sizeof(rcode));
14363 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
14364
14365 result = revent->result;
14366 if (result == ISC_R_SUCCESS)
14367 result = dns_message_create(notify->zone->mctx,
14368 DNS_MESSAGE_INTENTPARSE, &message);
14369 if (result == ISC_R_SUCCESS)
14370 result = dns_request_getresponse(revent->request, message,
14371 DNS_MESSAGEPARSE_PRESERVEORDER);
14372 if (result == ISC_R_SUCCESS)
14373 result = dns_rcode_totext(message->rcode, &buf);
14374 if (result == ISC_R_SUCCESS)
14375 notify_log(notify->zone, ISC_LOG_DEBUG(3),
14376 "notify response from %s: %.*s",
14377 addrbuf, (int)buf.used, rcode);
14378 else
14379 notify_log(notify->zone, ISC_LOG_DEBUG(2),
14380 "notify to %s failed: %s", addrbuf,
14381 dns_result_totext(result));
14382
14383 /*
14384 * Old bind's return formerr if they see a soa record. Retry w/o
14385 * the soa if we see a formerr and had sent a SOA.
14386 */
14387 isc_event_free(&event);
14388 if (message != NULL && message->rcode == dns_rcode_formerr &&
14389 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
14390 bool startup;
14391
14392 notify->flags |= DNS_NOTIFY_NOSOA;
14393 dns_request_destroy(¬ify->request);
14394 startup = (notify->flags & DNS_NOTIFY_STARTUP);
14395 result = notify_send_queue(notify, startup);
14396 if (result != ISC_R_SUCCESS)
14397 notify_destroy(notify, false);
14398 } else {
14399 if (result == ISC_R_TIMEDOUT)
14400 notify_log(notify->zone, ISC_LOG_DEBUG(1),
14401 "notify to %s: retries exceeded", addrbuf);
14402 notify_destroy(notify, false);
14403 }
14404 if (message != NULL)
14405 dns_message_destroy(&message);
14406 }
14407
14408 struct secure_event {
14409 isc_event_t e;
14410 dns_db_t *db;
14411 uint32_t serial;
14412 };
14413
14414 static void
14415 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
14416 UNUSED(arg);
14417 dns_zone_log(zone, level, "%s", message);
14418 }
14419
14420 static isc_result_t
14421 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
14422 uint32_t start, uint32_t end,
14423 dns_difftuple_t **soatuplep, dns_diff_t *diff)
14424 {
14425 isc_result_t result;
14426 dns_difftuple_t *tuple = NULL;
14427 dns_diffop_t op = DNS_DIFFOP_ADD;
14428 int n_soa = 0;
14429
14430 REQUIRE(soatuplep != NULL);
14431
14432 if (start == end)
14433 return (DNS_R_UNCHANGED);
14434
14435 CHECK(dns_journal_iter_init(journal, start, end));
14436 for (result = dns_journal_first_rr(journal);
14437 result == ISC_R_SUCCESS;
14438 result = dns_journal_next_rr(journal))
14439 {
14440 dns_name_t *name = NULL;
14441 uint32_t ttl;
14442 dns_rdata_t *rdata = NULL;
14443 dns_journal_current_rr(journal, &name, &ttl, &rdata);
14444
14445 if (rdata->type == dns_rdatatype_soa) {
14446 n_soa++;
14447 if (n_soa == 2) {
14448 /*
14449 * Save the latest raw SOA record.
14450 */
14451 if (*soatuplep != NULL)
14452 dns_difftuple_free(soatuplep);
14453 CHECK(dns_difftuple_create(diff->mctx,
14454 DNS_DIFFOP_ADD,
14455 name, ttl, rdata,
14456 soatuplep));
14457 }
14458 if (n_soa == 3)
14459 n_soa = 1;
14460 continue;
14461 }
14462
14463 /* Sanity. */
14464 if (n_soa == 0) {
14465 dns_zone_log(raw, ISC_LOG_ERROR,
14466 "corrupt journal file: '%s'\n",
14467 raw->journal);
14468 return (ISC_R_FAILURE);
14469 }
14470
14471 if (zone->privatetype != 0 &&
14472 rdata->type == zone->privatetype)
14473 continue;
14474
14475 if (rdata->type == dns_rdatatype_nsec ||
14476 rdata->type == dns_rdatatype_rrsig ||
14477 rdata->type == dns_rdatatype_nsec3 ||
14478 rdata->type == dns_rdatatype_dnskey ||
14479 rdata->type == dns_rdatatype_nsec3param)
14480 continue;
14481
14482 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
14483
14484 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
14485 &tuple));
14486 dns_diff_appendminimal(diff, &tuple);
14487 }
14488 if (result == ISC_R_NOMORE)
14489 result = ISC_R_SUCCESS;
14490
14491 failure:
14492 return(result);
14493 }
14494
14495 static isc_result_t
14496 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
14497 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
14498 dns_diff_t *diff)
14499 {
14500 isc_result_t result;
14501 dns_db_t *rawdb = NULL;
14502 dns_dbversion_t *rawver = NULL;
14503 dns_difftuple_t *tuple = NULL, *next;
14504 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
14505 dns_rdata_soa_t oldsoa, newsoa;
14506
14507 REQUIRE(DNS_ZONE_VALID(seczone));
14508 REQUIRE(soatuple != NULL && *soatuple == NULL);
14509
14510 if (!seczone->sourceserialset)
14511 return (DNS_R_UNCHANGED);
14512
14513 dns_db_attach(raw->db, &rawdb);
14514 dns_db_currentversion(rawdb, &rawver);
14515 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
14516 dns_db_closeversion(rawdb, &rawver, false);
14517 dns_db_detach(&rawdb);
14518
14519 if (result != ISC_R_SUCCESS)
14520 return (result);
14521
14522 for (tuple = ISC_LIST_HEAD(diff->tuples);
14523 tuple != NULL;
14524 tuple = next)
14525 {
14526 next = ISC_LIST_NEXT(tuple, link);
14527 if (tuple->rdata.type == dns_rdatatype_nsec ||
14528 tuple->rdata.type == dns_rdatatype_rrsig ||
14529 tuple->rdata.type == dns_rdatatype_dnskey ||
14530 tuple->rdata.type == dns_rdatatype_nsec3 ||
14531 tuple->rdata.type == dns_rdatatype_nsec3param)
14532 {
14533 ISC_LIST_UNLINK(diff->tuples, tuple, link);
14534 dns_difftuple_free(&tuple);
14535 continue;
14536 }
14537 if (tuple->rdata.type == dns_rdatatype_soa) {
14538 if (tuple->op == DNS_DIFFOP_DEL) {
14539 INSIST(oldtuple == NULL);
14540 oldtuple = tuple;
14541 }
14542 if (tuple->op == DNS_DIFFOP_ADD) {
14543 INSIST(newtuple == NULL);
14544 newtuple = tuple;
14545 }
14546 }
14547 }
14548
14549 if (oldtuple != NULL && newtuple != NULL) {
14550
14551 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
14552 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14553
14554 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
14555 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14556
14557 /*
14558 * If the SOA records are the same except for the serial
14559 * remove them from the diff.
14560 */
14561 if (oldsoa.refresh == newsoa.refresh &&
14562 oldsoa.retry == newsoa.retry &&
14563 oldsoa.minimum == newsoa.minimum &&
14564 oldsoa.expire == newsoa.expire &&
14565 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
14566 dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
14567 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14568 dns_difftuple_free(&oldtuple);
14569 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14570 dns_difftuple_free(&newtuple);
14571 }
14572 }
14573
14574 if (ISC_LIST_EMPTY(diff->tuples))
14575 return (DNS_R_UNCHANGED);
14576
14577 /*
14578 * If there are still SOA records in the diff they can now be removed
14579 * saving the new SOA record.
14580 */
14581 if (oldtuple != NULL) {
14582 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14583 dns_difftuple_free(&oldtuple);
14584 }
14585
14586 if (newtuple != NULL) {
14587 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14588 *soatuple = newtuple;
14589 }
14590
14591 return (ISC_R_SUCCESS);
14592 }
14593
14594 static void
14595 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
14596 static char me[] = "receive_secure_serial";
14597 isc_result_t result = ISC_R_SUCCESS;
14598 dns_journal_t *rjournal = NULL;
14599 dns_journal_t *sjournal = NULL;
14600 uint32_t start, end;
14601 dns_zone_t *zone;
14602 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
14603 dns_update_log_t log = { update_log_cb, NULL };
14604 uint32_t newserial = 0, desired = 0;
14605 isc_time_t timenow;
14606
14607 UNUSED(task);
14608
14609 zone = event->ev_arg;
14610 end = ((struct secure_event *)event)->serial;
14611
14612 ENTER;
14613
14614 LOCK_ZONE(zone);
14615
14616 /*
14617 * If we are already processing a receive secure serial event
14618 * for the zone, just queue the new one and exit.
14619 */
14620 if (zone->rss_event != NULL && zone->rss_event != event) {
14621 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
14622 UNLOCK_ZONE(zone);
14623 return;
14624 }
14625
14626 nextevent:
14627 if (zone->rss_event != NULL) {
14628 INSIST(zone->rss_event == event);
14629 UNLOCK_ZONE(zone);
14630 } else {
14631 zone->rss_event = event;
14632 dns_diff_init(zone->mctx, &zone->rss_diff);
14633
14634 /*
14635 * zone->db may be NULL, if the load from disk failed.
14636 */
14637 result = ISC_R_SUCCESS;
14638 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14639 if (zone->db != NULL)
14640 dns_db_attach(zone->db, &zone->rss_db);
14641 else
14642 result = ISC_R_FAILURE;
14643 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14644
14645 if (result == ISC_R_SUCCESS && zone->raw != NULL)
14646 dns_zone_attach(zone->raw, &zone->rss_raw);
14647 else
14648 result = ISC_R_FAILURE;
14649
14650 UNLOCK_ZONE(zone);
14651
14652 CHECK(result);
14653
14654 /*
14655 * We first attempt to sync the raw zone to the secure zone
14656 * by using the raw zone's journal, applying all the deltas
14657 * from the latest source-serial of the secure zone up to
14658 * the current serial number of the raw zone.
14659 *
14660 * If that fails, then we'll fall back to a direct comparison
14661 * between raw and secure zones.
14662 */
14663 CHECK(dns_journal_open(zone->rss_raw->mctx,
14664 zone->rss_raw->journal,
14665 DNS_JOURNAL_WRITE, &rjournal));
14666
14667 result = dns_journal_open(zone->mctx, zone->journal,
14668 DNS_JOURNAL_READ, &sjournal);
14669 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
14670 goto failure;
14671
14672 if (!dns_journal_get_sourceserial(rjournal, &start)) {
14673 start = dns_journal_first_serial(rjournal);
14674 dns_journal_set_sourceserial(rjournal, start);
14675 }
14676 if (sjournal != NULL) {
14677 uint32_t serial;
14678 /*
14679 * We read the secure journal first, if that
14680 * exists use its value provided it is greater
14681 * that from the raw journal.
14682 */
14683 if (dns_journal_get_sourceserial(sjournal, &serial)) {
14684 if (isc_serial_gt(serial, start))
14685 start = serial;
14686 }
14687 dns_journal_destroy(&sjournal);
14688 }
14689
14690 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
14691 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
14692
14693 /*
14694 * Try to apply diffs from the raw zone's journal to the secure
14695 * zone. If that fails, we recover by syncing up the databases
14696 * directly.
14697 */
14698 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
14699 start, end, &soatuple,
14700 &zone->rss_diff);
14701 if (result == DNS_R_UNCHANGED)
14702 goto failure;
14703 else if (result != ISC_R_SUCCESS)
14704 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
14705 zone->rss_oldver, &soatuple,
14706 &zone->rss_diff));
14707
14708 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
14709 zone->rss_newver));
14710
14711 if (soatuple != NULL) {
14712 uint32_t oldserial;
14713
14714 CHECK(dns_db_createsoatuple(zone->rss_db,
14715 zone->rss_oldver,
14716 zone->rss_diff.mctx,
14717 DNS_DIFFOP_DEL, &tuple));
14718 oldserial = dns_soa_getserial(&tuple->rdata);
14719 newserial = desired =
14720 dns_soa_getserial(&soatuple->rdata);
14721 if (!isc_serial_gt(newserial, oldserial)) {
14722 newserial = oldserial + 1;
14723 if (newserial == 0)
14724 newserial++;
14725 dns_soa_setserial(newserial, &soatuple->rdata);
14726 }
14727 CHECK(do_one_tuple(&tuple, zone->rss_db,
14728 zone->rss_newver, &zone->rss_diff));
14729 CHECK(do_one_tuple(&soatuple, zone->rss_db,
14730 zone->rss_newver, &zone->rss_diff));
14731 } else
14732 CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
14733 &zone->rss_diff, zone->mctx,
14734 zone->updatemethod));
14735
14736 }
14737 result = dns_update_signaturesinc(&log, zone, zone->rss_db,
14738 zone->rss_oldver, zone->rss_newver,
14739 &zone->rss_diff,
14740 zone->sigvalidityinterval,
14741 &zone->rss_state);
14742 if (result == DNS_R_CONTINUE) {
14743 if (rjournal != NULL)
14744 dns_journal_destroy(&rjournal);
14745 isc_task_send(task, &event);
14746 return;
14747 }
14748 /*
14749 * If something went wrong while trying to update the secure zone and
14750 * the latter was already signed before, do not apply raw zone deltas
14751 * to it as that would break existing DNSSEC signatures. However, if
14752 * the secure zone was not yet signed (e.g. because no signing keys
14753 * were created for it), commence applying raw zone deltas to it so
14754 * that contents of the raw zone and the secure zone are kept in sync.
14755 */
14756 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
14757 goto failure;
14758 }
14759
14760 if (rjournal == NULL)
14761 CHECK(dns_journal_open(zone->rss_raw->mctx,
14762 zone->rss_raw->journal,
14763 DNS_JOURNAL_WRITE, &rjournal));
14764 CHECK(zone_journal(zone, &zone->rss_diff, &end,
14765 "receive_secure_serial"));
14766
14767 dns_journal_set_sourceserial(rjournal, end);
14768 dns_journal_commit(rjournal);
14769
14770 LOCK_ZONE(zone);
14771 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14772
14773 zone->sourceserial = end;
14774 zone->sourceserialset = true;
14775 zone_needdump(zone, DNS_DUMP_DELAY);
14776
14777 TIME_NOW(&timenow);
14778 zone_settimer(zone, &timenow);
14779 UNLOCK_ZONE(zone);
14780
14781 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
14782 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
14783
14784 if (newserial != 0) {
14785 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
14786 newserial, desired);
14787 }
14788
14789 failure:
14790 isc_event_free(&zone->rss_event);
14791 event = ISC_LIST_HEAD(zone->rss_events);
14792
14793 if (zone->rss_raw != NULL)
14794 dns_zone_detach(&zone->rss_raw);
14795 if (result != ISC_R_SUCCESS)
14796 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
14797 dns_result_totext(result));
14798 if (tuple != NULL)
14799 dns_difftuple_free(&tuple);
14800 if (soatuple != NULL)
14801 dns_difftuple_free(&soatuple);
14802 if (zone->rss_db != NULL) {
14803 if (zone->rss_oldver != NULL)
14804 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
14805 false);
14806 if (zone->rss_newver != NULL)
14807 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
14808 false);
14809 dns_db_detach(&zone->rss_db);
14810 }
14811 INSIST(zone->rss_oldver == NULL);
14812 INSIST(zone->rss_newver == NULL);
14813 if (rjournal != NULL)
14814 dns_journal_destroy(&rjournal);
14815 dns_diff_clear(&zone->rss_diff);
14816
14817 if (event != NULL) {
14818 LOCK_ZONE(zone);
14819 INSIST(zone->irefs > 1);
14820 zone->irefs--;
14821 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
14822 goto nextevent;
14823 }
14824 dns_zone_idetach(&zone);
14825 }
14826
14827 static isc_result_t
14828 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
14829 isc_event_t *e;
14830 dns_zone_t *dummy = NULL;
14831
14832 e = isc_event_allocate(zone->secure->mctx, zone,
14833 DNS_EVENT_ZONESECURESERIAL,
14834 receive_secure_serial, zone->secure,
14835 sizeof(struct secure_event));
14836 if (e == NULL)
14837 return (ISC_R_NOMEMORY);
14838 ((struct secure_event *)e)->serial = serial;
14839 INSIST(LOCKED_ZONE(zone->secure));
14840 zone_iattach(zone->secure, &dummy);
14841 isc_task_send(zone->secure->task, &e);
14842
14843 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
14844 return (ISC_R_SUCCESS);
14845 }
14846
14847 static isc_result_t
14848 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
14849 dns_rdataset_t *rdataset, uint32_t oldserial)
14850 {
14851 dns_rdata_soa_t soa;
14852 dns_rdata_t rdata = DNS_RDATA_INIT;
14853 dns_rdatalist_t temprdatalist;
14854 dns_rdataset_t temprdataset;
14855 isc_buffer_t b;
14856 isc_result_t result;
14857 unsigned char buf[DNS_SOA_BUFFERSIZE];
14858 dns_fixedname_t fixed;
14859 dns_name_t *name;
14860
14861 result = dns_rdataset_first(rdataset);
14862 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14863 dns_rdataset_current(rdataset, &rdata);
14864 result = dns_rdata_tostruct(&rdata, &soa, NULL);
14865 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14866
14867 if (isc_serial_gt(soa.serial, oldserial))
14868 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
14869 NULL));
14870 /*
14871 * Always bump the serial.
14872 */
14873 oldserial++;
14874 if (oldserial == 0)
14875 oldserial++;
14876 soa.serial = oldserial;
14877
14878 /*
14879 * Construct a replacement rdataset.
14880 */
14881 dns_rdata_reset(&rdata);
14882 isc_buffer_init(&b, buf, sizeof(buf));
14883 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
14884 dns_rdatatype_soa, &soa, &b);
14885 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14886 dns_rdatalist_init(&temprdatalist);
14887 temprdatalist.rdclass = rdata.rdclass;
14888 temprdatalist.type = rdata.type;
14889 temprdatalist.ttl = rdataset->ttl;
14890 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
14891
14892 dns_rdataset_init(&temprdataset);
14893 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
14894 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14895
14896 name = dns_fixedname_initname(&fixed);
14897 result = dns_db_nodefullname(db, node, name);
14898 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14899 dns_rdataset_getownercase(rdataset, name);
14900 dns_rdataset_setownercase(&temprdataset, name);
14901 return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
14902 0, NULL));
14903 }
14904
14905 /*
14906 * This function should populate an nsec3paramlist_t with the
14907 * nsecparam_t data from a zone.
14908 */
14909 static isc_result_t
14910 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
14911 isc_result_t result;
14912 dns_dbnode_t *node = NULL;
14913 dns_rdataset_t rdataset, prdataset;
14914 dns_dbversion_t *version = NULL;
14915 nsec3param_t *nsec3param = NULL;
14916 nsec3param_t *nsec3p = NULL;
14917 nsec3param_t *next;
14918 dns_db_t *db = NULL;
14919 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14920
14921 REQUIRE(DNS_ZONE_VALID(zone));
14922 REQUIRE(nsec3list != NULL);
14923 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
14924
14925 dns_rdataset_init(&rdataset);
14926 dns_rdataset_init(&prdataset);
14927
14928 dns_db_attach(zone->db, &db);
14929 CHECK(dns_db_getoriginnode(db, &node));
14930
14931 dns_db_currentversion(db, &version);
14932 result = dns_db_findrdataset(db, node, version,
14933 dns_rdatatype_nsec3param,
14934 dns_rdatatype_none, 0, &rdataset, NULL);
14935
14936 if (result != ISC_R_SUCCESS)
14937 goto getprivate;
14938
14939 /*
14940 * walk nsec3param rdataset making a list of parameters (note that
14941 * multiple simultaneous nsec3 chains are annoyingly legal -- this
14942 * is why we use an nsec3list, even tho we will usually only have
14943 * one)
14944 */
14945 for (result = dns_rdataset_first(&rdataset);
14946 result == ISC_R_SUCCESS;
14947 result = dns_rdataset_next(&rdataset))
14948 {
14949 dns_rdata_t rdata = DNS_RDATA_INIT;
14950 dns_rdata_t private = DNS_RDATA_INIT;
14951
14952 dns_rdataset_current(&rdataset, &rdata);
14953 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14954 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14955 "looping through nsec3param data");
14956 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
14957 if (nsec3param == NULL)
14958 CHECK(ISC_R_NOMEMORY);
14959 ISC_LINK_INIT(nsec3param, link);
14960
14961 /*
14962 * now transfer the data from the rdata to
14963 * the nsec3param
14964 */
14965 dns_nsec3param_toprivate(&rdata, &private,
14966 zone->privatetype, nsec3param->data,
14967 sizeof(nsec3param->data));
14968 nsec3param->length = private.length;
14969 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
14970 }
14971
14972 getprivate:
14973 result = dns_db_findrdataset(db, node, version, zone->privatetype,
14974 dns_rdatatype_none, 0, &prdataset, NULL);
14975 if (result != ISC_R_SUCCESS)
14976 goto done;
14977
14978 /*
14979 * walk private type records, converting them to nsec3 parameters
14980 * using dns_nsec3param_fromprivate(), do the right thing based on
14981 * CREATE and REMOVE flags
14982 */
14983 for (result = dns_rdataset_first(&prdataset);
14984 result == ISC_R_SUCCESS;
14985 result = dns_rdataset_next(&prdataset))
14986 {
14987 dns_rdata_t rdata = DNS_RDATA_INIT;
14988 dns_rdata_t private = DNS_RDATA_INIT;
14989
14990 dns_rdataset_current(&prdataset, &private);
14991 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14992 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14993 "looping through nsec3param private data");
14994
14995 /*
14996 * Do we have a valid private record?
14997 */
14998 if (!dns_nsec3param_fromprivate(&private, &rdata,
14999 buf, sizeof(buf)))
15000 continue;
15001
15002 /*
15003 * Remove any NSEC3PARAM records scheduled to be removed.
15004 */
15005 if (NSEC3REMOVE(rdata.data[1])) {
15006 /*
15007 * Zero out the flags.
15008 */
15009 rdata.data[1] = 0;
15010
15011 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
15012 nsec3p != NULL;
15013 nsec3p = next)
15014 {
15015 next = ISC_LIST_NEXT(nsec3p, link);
15016
15017 if (nsec3p->length == rdata.length + 1 &&
15018 memcmp(rdata.data, nsec3p->data + 1,
15019 nsec3p->length - 1) == 0) {
15020 ISC_LIST_UNLINK(*nsec3list,
15021 nsec3p, link);
15022 isc_mem_put(zone->mctx, nsec3p,
15023 sizeof(nsec3param_t));
15024 }
15025 }
15026 continue;
15027 }
15028
15029 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
15030 if (nsec3param == NULL)
15031 CHECK(ISC_R_NOMEMORY);
15032 ISC_LINK_INIT(nsec3param, link);
15033
15034 /*
15035 * Copy the remaining private records so the nsec/nsec3
15036 * chain gets created.
15037 */
15038 INSIST(private.length <= sizeof(nsec3param->data));
15039 memmove(nsec3param->data, private.data, private.length);
15040 nsec3param->length = private.length;
15041 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
15042 }
15043
15044 done:
15045 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
15046 result = ISC_R_SUCCESS;
15047
15048 failure:
15049 if (node != NULL)
15050 dns_db_detachnode(db, &node);
15051 if (version != NULL)
15052 dns_db_closeversion(db, &version, false);
15053 if (db != NULL)
15054 dns_db_detach(&db);
15055 if (dns_rdataset_isassociated(&rdataset))
15056 dns_rdataset_disassociate(&rdataset);
15057 if (dns_rdataset_isassociated(&prdataset))
15058 dns_rdataset_disassociate(&prdataset);
15059 return (result);
15060 }
15061
15062 /*
15063 * Populate new zone db with private type records found by save_nsec3param().
15064 */
15065 static isc_result_t
15066 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
15067 nsec3paramlist_t *nsec3list)
15068 {
15069 isc_result_t result;
15070 dns_diff_t diff;
15071 dns_rdata_t rdata;
15072 nsec3param_t *nsec3p = NULL;
15073 nsec3param_t *next;
15074
15075 REQUIRE(DNS_ZONE_VALID(zone));
15076 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
15077
15078 dns_diff_init(zone->mctx, &diff);
15079
15080 /*
15081 * Loop through the list of private-type records, set the INITIAL
15082 * and CREATE flags, and the add the record to the apex of the tree
15083 * in db.
15084 */
15085 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
15086 nsec3p != NULL;
15087 nsec3p = next)
15088 {
15089 next = ISC_LIST_NEXT(nsec3p, link);
15090 dns_rdata_init(&rdata);
15091 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
15092 rdata.length = nsec3p->length;
15093 rdata.data = nsec3p->data;
15094 rdata.type = zone->privatetype;
15095 rdata.rdclass = zone->rdclass;
15096 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
15097 &zone->origin, 0, &rdata);
15098 if (result != ISC_R_SUCCESS) {
15099 break;
15100 }
15101 }
15102
15103 dns_diff_clear(&diff);
15104 return (result);
15105 }
15106
15107 static void
15108 receive_secure_db(isc_task_t *task, isc_event_t *event) {
15109 isc_result_t result;
15110 dns_zone_t *zone;
15111 dns_db_t *rawdb, *db = NULL;
15112 dns_dbnode_t *rawnode = NULL, *node = NULL;
15113 dns_fixedname_t fname;
15114 dns_name_t *name;
15115 dns_dbiterator_t *dbiterator = NULL;
15116 dns_rdatasetiter_t *rdsit = NULL;
15117 dns_rdataset_t rdataset;
15118 dns_dbversion_t *version = NULL;
15119 isc_time_t loadtime;
15120 unsigned int oldserial = 0;
15121 bool have_oldserial = false;
15122 nsec3paramlist_t nsec3list;
15123 isc_event_t *setnsec3param_event;
15124 dns_zone_t *dummy;
15125
15126 UNUSED(task);
15127
15128 ISC_LIST_INIT(nsec3list);
15129
15130 zone = event->ev_arg;
15131 rawdb = ((struct secure_event *)event)->db;
15132 isc_event_free(&event);
15133
15134 name = dns_fixedname_initname(&fname);
15135 dns_rdataset_init(&rdataset);
15136
15137 LOCK_ZONE(zone);
15138 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
15139 result = ISC_R_SHUTTINGDOWN;
15140 goto failure;
15141 }
15142
15143 TIME_NOW(&loadtime);
15144 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15145 if (zone->db != NULL) {
15146 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
15147 if (result == ISC_R_SUCCESS)
15148 have_oldserial = true;
15149
15150 /*
15151 * assemble nsec3parameters from the old zone, and set a flag
15152 * if any are found
15153 */
15154 result = save_nsec3param(zone, &nsec3list);
15155 if (result != ISC_R_SUCCESS) {
15156 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15157 goto failure;
15158 }
15159 }
15160 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15161
15162 result = dns_db_create(zone->mctx, zone->db_argv[0],
15163 &zone->origin, dns_dbtype_zone, zone->rdclass,
15164 zone->db_argc - 1, zone->db_argv + 1, &db);
15165 if (result != ISC_R_SUCCESS)
15166 goto failure;
15167
15168 result = dns_db_setgluecachestats(db, zone->gluecachestats);
15169 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
15170 goto failure;
15171 }
15172
15173 result = dns_db_newversion(db, &version);
15174 if (result != ISC_R_SUCCESS)
15175 goto failure;
15176
15177 result = dns_db_createiterator(rawdb, 0, &dbiterator);
15178 if (result != ISC_R_SUCCESS)
15179 goto failure;
15180
15181 for (result = dns_dbiterator_first(dbiterator);
15182 result == ISC_R_SUCCESS;
15183 result = dns_dbiterator_next(dbiterator)) {
15184 result = dns_dbiterator_current(dbiterator, &rawnode, name);
15185 if (result != ISC_R_SUCCESS)
15186 continue;
15187
15188 result = dns_db_findnode(db, name, true, &node);
15189 if (result != ISC_R_SUCCESS)
15190 goto failure;
15191
15192 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
15193 if (result != ISC_R_SUCCESS)
15194 goto failure;
15195
15196 for (result = dns_rdatasetiter_first(rdsit);
15197 result == ISC_R_SUCCESS;
15198 result = dns_rdatasetiter_next(rdsit)) {
15199 dns_rdatasetiter_current(rdsit, &rdataset);
15200 if (rdataset.type == dns_rdatatype_nsec ||
15201 rdataset.type == dns_rdatatype_rrsig ||
15202 rdataset.type == dns_rdatatype_nsec3 ||
15203 rdataset.type == dns_rdatatype_dnskey ||
15204 rdataset.type == dns_rdatatype_nsec3param) {
15205 dns_rdataset_disassociate(&rdataset);
15206 continue;
15207 }
15208 if (rdataset.type == dns_rdatatype_soa &&
15209 have_oldserial) {
15210 result = checkandaddsoa(db, node, version,
15211 &rdataset, oldserial);
15212 } else
15213 result = dns_db_addrdataset(db, node, version,
15214 0, &rdataset, 0,
15215 NULL);
15216 if (result != ISC_R_SUCCESS)
15217 goto failure;
15218
15219 dns_rdataset_disassociate(&rdataset);
15220 }
15221 dns_rdatasetiter_destroy(&rdsit);
15222 dns_db_detachnode(rawdb, &rawnode);
15223 dns_db_detachnode(db, &node);
15224 }
15225
15226 /*
15227 * Call restore_nsec3param() to create private-type records from
15228 * the old nsec3 parameters and insert them into db
15229 */
15230 if (!ISC_LIST_EMPTY(nsec3list)) {
15231 result = restore_nsec3param(zone, db, version, &nsec3list);
15232 if (result != ISC_R_SUCCESS) {
15233 goto failure;
15234 }
15235 }
15236
15237 dns_db_closeversion(db, &version, true);
15238
15239 /*
15240 * Lock hierarchy: zmgr, zone, raw.
15241 */
15242 INSIST(zone != zone->raw);
15243 LOCK_ZONE(zone->raw);
15244 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15245 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
15246 zone_needdump(zone, 0); /* XXXMPA */
15247 UNLOCK_ZONE(zone->raw);
15248
15249 /*
15250 * Process any queued NSEC3PARAM change requests.
15251 */
15252 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
15253 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
15254 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
15255 ev_link);
15256 dummy = NULL;
15257 zone_iattach(zone, &dummy);
15258 isc_task_send(zone->task, &setnsec3param_event);
15259 }
15260
15261 failure:
15262 UNLOCK_ZONE(zone);
15263 if (result != ISC_R_SUCCESS)
15264 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
15265 dns_result_totext(result));
15266
15267 while (!ISC_LIST_EMPTY(nsec3list)) {
15268 nsec3param_t *nsec3p;
15269 nsec3p = ISC_LIST_HEAD(nsec3list);
15270 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
15271 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
15272 }
15273 if (dns_rdataset_isassociated(&rdataset))
15274 dns_rdataset_disassociate(&rdataset);
15275 if (db != NULL) {
15276 if (node != NULL)
15277 dns_db_detachnode(db, &node);
15278 if (version != NULL)
15279 dns_db_closeversion(db, &version, false);
15280 dns_db_detach(&db);
15281 }
15282 if (rawnode != NULL)
15283 dns_db_detachnode(rawdb, &rawnode);
15284 dns_db_detach(&rawdb);
15285 if (dbiterator != NULL)
15286 dns_dbiterator_destroy(&dbiterator);
15287 dns_zone_idetach(&zone);
15288
15289 INSIST(version == NULL);
15290 }
15291
15292 static isc_result_t
15293 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
15294 isc_event_t *e;
15295 dns_db_t *dummy = NULL;
15296 dns_zone_t *secure = NULL;
15297
15298 e = isc_event_allocate(zone->secure->mctx, zone,
15299 DNS_EVENT_ZONESECUREDB,
15300 receive_secure_db, zone->secure,
15301 sizeof(struct secure_event));
15302 if (e == NULL)
15303 return (ISC_R_NOMEMORY);
15304 dns_db_attach(db, &dummy);
15305 ((struct secure_event *)e)->db = dummy;
15306 INSIST(LOCKED_ZONE(zone->secure));
15307 zone_iattach(zone->secure, &secure);
15308 isc_task_send(zone->secure->task, &e);
15309 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
15310 return (ISC_R_SUCCESS);
15311 }
15312
15313 isc_result_t
15314 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
15315 isc_result_t result;
15316 dns_zone_t *secure = NULL;
15317
15318 REQUIRE(DNS_ZONE_VALID(zone));
15319 again:
15320 LOCK_ZONE(zone);
15321 if (inline_raw(zone)) {
15322 secure = zone->secure;
15323 INSIST(secure != zone);
15324 TRYLOCK_ZONE(result, secure);
15325 if (result != ISC_R_SUCCESS) {
15326 UNLOCK_ZONE(zone);
15327 secure = NULL;
15328 isc_thread_yield();
15329 goto again;
15330 }
15331 }
15332 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
15333 result = zone_replacedb(zone, db, dump);
15334 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
15335 if (secure != NULL)
15336 UNLOCK_ZONE(secure);
15337 UNLOCK_ZONE(zone);
15338 return (result);
15339 }
15340
15341 static isc_result_t
15342 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
15343 dns_dbversion_t *ver;
15344 isc_result_t result;
15345 unsigned int soacount = 0;
15346 unsigned int nscount = 0;
15347
15348 /*
15349 * 'zone' and 'zone->db' locked by caller.
15350 */
15351 REQUIRE(DNS_ZONE_VALID(zone));
15352 REQUIRE(LOCKED_ZONE(zone));
15353 if (inline_raw(zone))
15354 REQUIRE(LOCKED_ZONE(zone->secure));
15355
15356 result = zone_get_from_db(zone, db, &nscount, &soacount,
15357 NULL, NULL, NULL, NULL, NULL, NULL);
15358 if (result == ISC_R_SUCCESS) {
15359 if (soacount != 1) {
15360 dns_zone_log(zone, ISC_LOG_ERROR,
15361 "has %d SOA records", soacount);
15362 result = DNS_R_BADZONE;
15363 }
15364 if (nscount == 0 && zone->type != dns_zone_key) {
15365 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
15366 result = DNS_R_BADZONE;
15367 }
15368 if (result != ISC_R_SUCCESS)
15369 return (result);
15370 } else {
15371 dns_zone_log(zone, ISC_LOG_ERROR,
15372 "retrieving SOA and NS records failed: %s",
15373 dns_result_totext(result));
15374 return (result);
15375 }
15376
15377 result = check_nsec3param(zone, db);
15378 if (result != ISC_R_SUCCESS)
15379 return (result);
15380
15381 ver = NULL;
15382 dns_db_currentversion(db, &ver);
15383
15384 /*
15385 * The initial version of a slave zone is always dumped;
15386 * subsequent versions may be journaled instead if this
15387 * is enabled in the configuration.
15388 */
15389 if (zone->db != NULL && zone->journal != NULL &&
15390 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
15391 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
15392 {
15393 uint32_t serial, oldserial;
15394
15395 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
15396
15397 result = dns_db_getsoaserial(db, ver, &serial);
15398 if (result != ISC_R_SUCCESS) {
15399 dns_zone_log(zone, ISC_LOG_ERROR,
15400 "ixfr-from-differences: unable to get "
15401 "new serial");
15402 goto fail;
15403 }
15404
15405 /*
15406 * This is checked in zone_postload() for master zones.
15407 */
15408 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
15409 &oldserial, NULL, NULL, NULL, NULL,
15410 NULL);
15411 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15412 RUNTIME_CHECK(soacount > 0U);
15413 if ((zone->type == dns_zone_slave ||
15414 (zone->type == dns_zone_redirect &&
15415 zone->masters != NULL))
15416 && !isc_serial_gt(serial, oldserial)) {
15417 uint32_t serialmin, serialmax;
15418 serialmin = (oldserial + 1) & 0xffffffffU;
15419 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
15420 dns_zone_log(zone, ISC_LOG_ERROR,
15421 "ixfr-from-differences: failed: "
15422 "new serial (%u) out of range [%u - %u]",
15423 serial, serialmin, serialmax);
15424 result = ISC_R_RANGE;
15425 goto fail;
15426 }
15427
15428 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
15429 zone->journal);
15430 if (result != ISC_R_SUCCESS) {
15431 char strbuf[ISC_STRERRORSIZE];
15432 strerror_r(errno, strbuf, sizeof(strbuf));
15433 dns_zone_log(zone, ISC_LOG_ERROR,
15434 "ixfr-from-differences: failed: "
15435 "%s", strbuf);
15436 goto fallback;
15437 }
15438 if (dump)
15439 zone_needdump(zone, DNS_DUMP_DELAY);
15440 else
15441 zone_journal_compact(zone, zone->db, serial);
15442 if (zone->type == dns_zone_master && inline_raw(zone))
15443 zone_send_secureserial(zone, serial);
15444 } else {
15445 fallback:
15446 if (dump && zone->masterfile != NULL) {
15447 /*
15448 * If DNS_ZONEFLG_FORCEXFER was set we don't want
15449 * to keep the old masterfile.
15450 */
15451 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
15452 remove(zone->masterfile) < 0 && errno != ENOENT) {
15453 char strbuf[ISC_STRERRORSIZE];
15454 strerror_r(errno, strbuf, sizeof(strbuf));
15455 isc_log_write(dns_lctx,
15456 DNS_LOGCATEGORY_GENERAL,
15457 DNS_LOGMODULE_ZONE,
15458 ISC_LOG_WARNING,
15459 "unable to remove masterfile "
15460 "'%s': '%s'",
15461 zone->masterfile, strbuf);
15462 }
15463 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
15464 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
15465 else
15466 zone_needdump(zone, 0);
15467 }
15468 if (dump && zone->journal != NULL) {
15469 /*
15470 * The in-memory database just changed, and
15471 * because 'dump' is set, it didn't change by
15472 * being loaded from disk. Also, we have not
15473 * journaled diffs for this change.
15474 * Therefore, the on-disk journal is missing
15475 * the deltas for this change. Since it can
15476 * no longer be used to bring the zone
15477 * up-to-date, it is useless and should be
15478 * removed.
15479 */
15480 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15481 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15482 "removing journal file");
15483 if (remove(zone->journal) < 0 && errno != ENOENT) {
15484 char strbuf[ISC_STRERRORSIZE];
15485 strerror_r(errno, strbuf, sizeof(strbuf));
15486 isc_log_write(dns_lctx,
15487 DNS_LOGCATEGORY_GENERAL,
15488 DNS_LOGMODULE_ZONE,
15489 ISC_LOG_WARNING,
15490 "unable to remove journal "
15491 "'%s': '%s'",
15492 zone->journal, strbuf);
15493 }
15494 }
15495
15496 if (inline_raw(zone))
15497 zone_send_securedb(zone, db);
15498 }
15499
15500 dns_db_closeversion(db, &ver, false);
15501
15502 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
15503
15504 if (zone->db != NULL)
15505 zone_detachdb(zone);
15506 zone_attachdb(zone, db);
15507 dns_db_settask(zone->db, zone->task);
15508 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
15509 return (ISC_R_SUCCESS);
15510
15511 fail:
15512 dns_db_closeversion(db, &ver, false);
15513 return (result);
15514 }
15515
15516 /* The caller must hold the dblock as a writer. */
15517 static inline void
15518 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
15519 REQUIRE(zone->db == NULL && db != NULL);
15520
15521 dns_db_attach(db, &zone->db);
15522 }
15523
15524 /* The caller must hold the dblock as a writer. */
15525 static inline void
15526 zone_detachdb(dns_zone_t *zone) {
15527 REQUIRE(zone->db != NULL);
15528
15529 dns_db_detach(&zone->db);
15530 }
15531
15532 static void
15533 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
15534 isc_time_t now;
15535 bool again = false;
15536 unsigned int soacount;
15537 unsigned int nscount;
15538 uint32_t serial, refresh, retry, expire, minimum;
15539 isc_result_t xfrresult = result;
15540 bool free_needed;
15541 dns_zone_t *secure = NULL;
15542
15543 REQUIRE(DNS_ZONE_VALID(zone));
15544
15545 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15546 "zone transfer finished: %s", dns_result_totext(result));
15547
15548 /*
15549 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
15550 * could result in a deadlock due to a LOR so we will spin if we
15551 * can't obtain the both locks.
15552 */
15553 again:
15554 LOCK_ZONE(zone);
15555 if (inline_raw(zone)) {
15556 secure = zone->secure;
15557 INSIST(secure != zone);
15558 TRYLOCK_ZONE(result, secure);
15559 if (result != ISC_R_SUCCESS) {
15560 UNLOCK_ZONE(zone);
15561 secure = NULL;
15562 isc_thread_yield();
15563 goto again;
15564 }
15565 }
15566
15567 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
15568 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15569 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
15570
15571 TIME_NOW(&now);
15572 switch (xfrresult) {
15573 case ISC_R_SUCCESS:
15574 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15575 /* FALLTHROUGH */
15576 case DNS_R_UPTODATE:
15577 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15578 /*
15579 * Has the zone expired underneath us?
15580 */
15581 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15582 if (zone->db == NULL) {
15583 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15584 goto same_master;
15585 }
15586
15587 /*
15588 * Update the zone structure's data from the actual
15589 * SOA received.
15590 */
15591 nscount = 0;
15592 soacount = 0;
15593 INSIST(zone->db != NULL);
15594 result = zone_get_from_db(zone, zone->db, &nscount,
15595 &soacount, &serial, &refresh,
15596 &retry, &expire, &minimum, NULL);
15597 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15598 if (result == ISC_R_SUCCESS) {
15599 if (soacount != 1)
15600 dns_zone_log(zone, ISC_LOG_ERROR,
15601 "transferred zone "
15602 "has %d SOA record%s", soacount,
15603 (soacount != 0) ? "s" : "");
15604 if (nscount == 0) {
15605 dns_zone_log(zone, ISC_LOG_ERROR,
15606 "transferred zone "
15607 "has no NS records");
15608 if (DNS_ZONE_FLAG(zone,
15609 DNS_ZONEFLG_HAVETIMERS)) {
15610 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
15611 zone->retry = DNS_ZONE_DEFAULTRETRY;
15612 }
15613 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15614 zone_unload(zone);
15615 goto next_master;
15616 }
15617 zone->refresh = RANGE(refresh, zone->minrefresh,
15618 zone->maxrefresh);
15619 zone->retry = RANGE(retry, zone->minretry,
15620 zone->maxretry);
15621 zone->expire = RANGE(expire,
15622 zone->refresh + zone->retry,
15623 DNS_MAX_EXPIRE);
15624 zone->minimum = minimum;
15625 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15626 }
15627
15628 /*
15629 * Set our next update/expire times.
15630 */
15631 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
15632 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15633 zone->refreshtime = now;
15634 DNS_ZONE_TIME_ADD(&now, zone->expire,
15635 &zone->expiretime);
15636 } else {
15637 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
15638 &zone->refreshtime);
15639 DNS_ZONE_TIME_ADD(&now, zone->expire,
15640 &zone->expiretime);
15641 }
15642 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
15643 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
15644 if (zone->tsigkey != NULL) {
15645 char namebuf[DNS_NAME_FORMATSIZE];
15646 dns_name_format(&zone->tsigkey->name, namebuf,
15647 sizeof(namebuf));
15648 snprintf(buf, sizeof(buf), ": TSIG '%s'",
15649 namebuf);
15650 } else
15651 buf[0] = '\0';
15652 dns_zone_log(zone, ISC_LOG_INFO,
15653 "transferred serial %u%s",
15654 serial, buf);
15655 if (inline_raw(zone))
15656 zone_send_secureserial(zone, serial);
15657 }
15658
15659 /*
15660 * This is not necessary if we just performed a AXFR
15661 * however it is necessary for an IXFR / UPTODATE and
15662 * won't hurt with an AXFR.
15663 */
15664 if (zone->masterfile != NULL || zone->journal != NULL) {
15665 unsigned int delay = DNS_DUMP_DELAY;
15666
15667 result = ISC_R_FAILURE;
15668 if (zone->journal != NULL)
15669 result = isc_file_settime(zone->journal, &now);
15670 if (result != ISC_R_SUCCESS &&
15671 zone->masterfile != NULL)
15672 result = isc_file_settime(zone->masterfile,
15673 &now);
15674
15675 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
15676 result == ISC_R_FILENOTFOUND)
15677 delay = 0;
15678
15679 if ((result == ISC_R_SUCCESS ||
15680 result == ISC_R_FILENOTFOUND) &&
15681 zone->masterfile != NULL)
15682 zone_needdump(zone, delay);
15683 else if (result != ISC_R_SUCCESS)
15684 dns_zone_log(zone, ISC_LOG_ERROR,
15685 "transfer: could not set file "
15686 "modification time of '%s': %s",
15687 zone->masterfile,
15688 dns_result_totext(result));
15689 }
15690 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
15691 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
15692 break;
15693
15694 case DNS_R_BADIXFR:
15695 /* Force retry with AXFR. */
15696 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
15697 goto same_master;
15698
15699 case DNS_R_TOOMANYRECORDS:
15700 case DNS_R_VERIFYFAILURE:
15701 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
15702 inc_stats(zone, dns_zonestatscounter_xfrfail);
15703 break;
15704
15705 default:
15706 next_master:
15707 /*
15708 * Skip to next failed / untried master.
15709 */
15710 do {
15711 zone->curmaster++;
15712 } while (zone->curmaster < zone->masterscnt &&
15713 zone->mastersok[zone->curmaster]);
15714 /* FALLTHROUGH */
15715 same_master:
15716 if (zone->curmaster >= zone->masterscnt) {
15717 zone->curmaster = 0;
15718 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
15719 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
15720 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15721 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15722 while (zone->curmaster < zone->masterscnt &&
15723 zone->mastersok[zone->curmaster])
15724 zone->curmaster++;
15725 again = true;
15726 } else
15727 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15728 } else {
15729 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15730 again = true;
15731 }
15732 inc_stats(zone, dns_zonestatscounter_xfrfail);
15733 break;
15734 }
15735 zone_settimer(zone, &now);
15736
15737 /*
15738 * If creating the transfer object failed, zone->xfr is NULL.
15739 * Otherwise, we are called as the done callback of a zone
15740 * transfer object that just entered its shutting-down
15741 * state. Since we are no longer responsible for shutting
15742 * it down, we can detach our reference.
15743 */
15744 if (zone->xfr != NULL)
15745 dns_xfrin_detach(&zone->xfr);
15746
15747 if (zone->tsigkey != NULL)
15748 dns_tsigkey_detach(&zone->tsigkey);
15749
15750 /*
15751 * Handle any deferred journal compaction.
15752 */
15753 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
15754 dns_db_t *db = NULL;
15755 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
15756 zone_journal_compact(zone, db, zone->compact_serial);
15757 dns_db_detach(&db);
15758 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
15759 }
15760 }
15761
15762 if (secure != NULL)
15763 UNLOCK_ZONE(secure);
15764 /*
15765 * This transfer finishing freed up a transfer quota slot.
15766 * Let any other zones waiting for quota have it.
15767 */
15768 if (zone->zmgr != NULL &&
15769 zone->statelist == &zone->zmgr->xfrin_in_progress) {
15770 UNLOCK_ZONE(zone);
15771 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15772 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
15773 zone->statelist = NULL;
15774 zmgr_resume_xfrs(zone->zmgr, false);
15775 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15776 LOCK_ZONE(zone);
15777 }
15778
15779 /*
15780 * Retry with a different server if necessary.
15781 */
15782 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
15783 queue_soa_query(zone);
15784
15785 INSIST(zone->irefs > 0);
15786 zone->irefs--;
15787 free_needed = exit_check(zone);
15788 UNLOCK_ZONE(zone);
15789 if (free_needed)
15790 zone_free(zone);
15791 }
15792
15793 static void
15794 zone_loaddone(void *arg, isc_result_t result) {
15795 static char me[] = "zone_loaddone";
15796 dns_load_t *load = arg;
15797 dns_zone_t *zone;
15798 isc_result_t tresult;
15799 dns_zone_t *secure = NULL;
15800
15801 REQUIRE(DNS_LOAD_VALID(load));
15802 zone = load->zone;
15803
15804 ENTER;
15805
15806 tresult = dns_db_endload(load->db, &load->callbacks);
15807 if (tresult != ISC_R_SUCCESS &&
15808 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
15809 result = tresult;
15810
15811 /*
15812 * Lock hierarchy: zmgr, zone, raw.
15813 */
15814 again:
15815 LOCK_ZONE(zone);
15816 INSIST(zone != zone->raw);
15817 if (inline_secure(zone))
15818 LOCK_ZONE(zone->raw);
15819 else if (inline_raw(zone)) {
15820 secure = zone->secure;
15821 TRYLOCK_ZONE(result, secure);
15822 if (result != ISC_R_SUCCESS) {
15823 UNLOCK_ZONE(zone);
15824 secure = NULL;
15825 isc_thread_yield();
15826 goto again;
15827 }
15828 }
15829 (void)zone_postload(zone, load->db, load->loadtime, result);
15830 zonemgr_putio(&zone->readio);
15831 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
15832 zone_idetach(&load->callbacks.zone);
15833 /*
15834 * Leave the zone frozen if the reload fails.
15835 */
15836 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
15837 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
15838 zone->update_disabled = false;
15839 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
15840 if (inline_secure(zone))
15841 UNLOCK_ZONE(zone->raw);
15842 else if (secure != NULL)
15843 UNLOCK_ZONE(secure);
15844 UNLOCK_ZONE(zone);
15845
15846 load->magic = 0;
15847 dns_db_detach(&load->db);
15848 if (load->zone->lctx != NULL)
15849 dns_loadctx_detach(&load->zone->lctx);
15850 dns_zone_idetach(&load->zone);
15851 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
15852 }
15853
15854 void
15855 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
15856 REQUIRE(DNS_ZONE_VALID(zone));
15857 REQUIRE(table != NULL);
15858 REQUIRE(*table == NULL);
15859
15860 LOCK_ZONE(zone);
15861 if (zone->ssutable != NULL)
15862 dns_ssutable_attach(zone->ssutable, table);
15863 UNLOCK_ZONE(zone);
15864 }
15865
15866 void
15867 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
15868 REQUIRE(DNS_ZONE_VALID(zone));
15869
15870 LOCK_ZONE(zone);
15871 if (zone->ssutable != NULL)
15872 dns_ssutable_detach(&zone->ssutable);
15873 if (table != NULL)
15874 dns_ssutable_attach(table, &zone->ssutable);
15875 UNLOCK_ZONE(zone);
15876 }
15877
15878 void
15879 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
15880 REQUIRE(DNS_ZONE_VALID(zone));
15881
15882 zone->sigvalidityinterval = interval;
15883 }
15884
15885 uint32_t
15886 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
15887 REQUIRE(DNS_ZONE_VALID(zone));
15888
15889 return (zone->sigvalidityinterval);
15890 }
15891
15892 void
15893 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
15894 REQUIRE(DNS_ZONE_VALID(zone));
15895
15896 zone->keyvalidityinterval = interval;
15897 }
15898
15899 uint32_t
15900 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
15901 REQUIRE(DNS_ZONE_VALID(zone));
15902
15903 return (zone->keyvalidityinterval);
15904 }
15905
15906 void
15907 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
15908 isc_time_t now;
15909
15910 REQUIRE(DNS_ZONE_VALID(zone));
15911
15912 LOCK_ZONE(zone);
15913 zone->sigresigninginterval = interval;
15914 set_resigntime(zone);
15915 if (zone->task != NULL) {
15916 TIME_NOW(&now);
15917 zone_settimer(zone, &now);
15918 }
15919 UNLOCK_ZONE(zone);
15920 }
15921
15922 uint32_t
15923 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
15924 REQUIRE(DNS_ZONE_VALID(zone));
15925
15926 return (zone->sigresigninginterval);
15927 }
15928
15929 static void
15930 queue_xfrin(dns_zone_t *zone) {
15931 const char me[] = "queue_xfrin";
15932 isc_result_t result;
15933 dns_zonemgr_t *zmgr = zone->zmgr;
15934
15935 ENTER;
15936
15937 INSIST(zone->statelist == NULL);
15938
15939 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15940 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
15941 LOCK_ZONE(zone);
15942 zone->irefs++;
15943 UNLOCK_ZONE(zone);
15944 zone->statelist = &zmgr->waiting_for_xfrin;
15945 result = zmgr_start_xfrin_ifquota(zmgr, zone);
15946 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15947
15948 if (result == ISC_R_QUOTA) {
15949 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
15950 "zone transfer deferred due to quota");
15951 } else if (result != ISC_R_SUCCESS) {
15952 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
15953 "starting zone transfer: %s",
15954 isc_result_totext(result));
15955 }
15956 }
15957
15958 /*
15959 * This event callback is called when a zone has received
15960 * any necessary zone transfer quota. This is the time
15961 * to go ahead and start the transfer.
15962 */
15963 static void
15964 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
15965 isc_result_t result = ISC_R_SUCCESS;
15966 dns_peer_t *peer = NULL;
15967 char master[ISC_SOCKADDR_FORMATSIZE];
15968 char source[ISC_SOCKADDR_FORMATSIZE];
15969 dns_rdatatype_t xfrtype;
15970 dns_zone_t *zone = event->ev_arg;
15971 isc_netaddr_t masterip;
15972 isc_sockaddr_t sourceaddr;
15973 isc_sockaddr_t masteraddr;
15974 isc_time_t now;
15975 const char *soa_before = "";
15976 isc_dscp_t dscp = -1;
15977 bool loaded;
15978
15979 UNUSED(task);
15980
15981 INSIST(task == zone->task);
15982
15983 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15984 result = ISC_R_CANCELED;
15985 goto cleanup;
15986 }
15987
15988 TIME_NOW(&now);
15989
15990 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
15991 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
15992 &zone->sourceaddr, &now))
15993 {
15994 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
15995 dns_zone_log(zone, ISC_LOG_INFO,
15996 "got_transfer_quota: skipping zone transfer as "
15997 "master %s (source %s) is unreachable (cached)",
15998 master, source);
15999 result = ISC_R_CANCELED;
16000 goto cleanup;
16001 }
16002
16003 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
16004 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
16005
16006 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
16007 soa_before = "SOA before ";
16008 /*
16009 * Decide whether we should request IXFR or AXFR.
16010 */
16011 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16012 loaded = (zone->db != NULL);
16013 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16014
16015 if (!loaded) {
16016 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16017 "no database exists yet, requesting AXFR of "
16018 "initial version from %s", master);
16019 xfrtype = dns_rdatatype_axfr;
16020 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
16021 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16022 "forced reload, requesting AXFR of "
16023 "initial version from %s", master);
16024 xfrtype = dns_rdatatype_axfr;
16025 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
16026 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16027 "retrying with AXFR from %s due to "
16028 "previous IXFR failure", master);
16029 xfrtype = dns_rdatatype_axfr;
16030 LOCK_ZONE(zone);
16031 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
16032 UNLOCK_ZONE(zone);
16033 } else {
16034 bool use_ixfr = true;
16035 if (peer != NULL)
16036 result = dns_peer_getrequestixfr(peer, &use_ixfr);
16037 if (peer == NULL || result != ISC_R_SUCCESS)
16038 use_ixfr = zone->requestixfr;
16039 if (use_ixfr == false) {
16040 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16041 "IXFR disabled, requesting %sAXFR from %s",
16042 soa_before, master);
16043 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
16044 xfrtype = dns_rdatatype_soa;
16045 else
16046 xfrtype = dns_rdatatype_axfr;
16047 } else {
16048 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16049 "requesting IXFR from %s", master);
16050 xfrtype = dns_rdatatype_ixfr;
16051 }
16052 }
16053
16054 /*
16055 * Determine if we should attempt to sign the request with TSIG.
16056 */
16057 result = ISC_R_NOTFOUND;
16058
16059 /*
16060 * First, look for a tsig key in the master statement, then
16061 * try for a server key.
16062 */
16063 if ((zone->masterkeynames != NULL) &&
16064 (zone->masterkeynames[zone->curmaster] != NULL)) {
16065 dns_view_t *view = dns_zone_getview(zone);
16066 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
16067 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
16068 }
16069 if (zone->tsigkey == NULL)
16070 result = dns_view_getpeertsig(zone->view, &masterip,
16071 &zone->tsigkey);
16072
16073 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16074 dns_zone_log(zone, ISC_LOG_ERROR,
16075 "could not get TSIG key for zone transfer: %s",
16076 isc_result_totext(result));
16077 }
16078
16079 if (zone->masterdscps != NULL)
16080 dscp = zone->masterdscps[zone->curmaster];
16081
16082 LOCK_ZONE(zone);
16083 masteraddr = zone->masteraddr;
16084 sourceaddr = zone->sourceaddr;
16085 switch (isc_sockaddr_pf(&masteraddr)) {
16086 case PF_INET:
16087 if (dscp == -1)
16088 dscp = zone->xfrsource4dscp;
16089 break;
16090 case PF_INET6:
16091 if (dscp == -1)
16092 dscp = zone->xfrsource6dscp;
16093 break;
16094 default:
16095 INSIST(0);
16096 ISC_UNREACHABLE();
16097 }
16098 UNLOCK_ZONE(zone);
16099 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
16100 result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr,
16101 dscp, zone->tsigkey, zone->mctx,
16102 zone->zmgr->timermgr, zone->zmgr->socketmgr,
16103 zone->task, zone_xfrdone, &zone->xfr);
16104 if (result == ISC_R_SUCCESS) {
16105 LOCK_ZONE(zone);
16106 if (xfrtype == dns_rdatatype_axfr) {
16107 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
16108 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
16109 else
16110 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
16111 } else if (xfrtype == dns_rdatatype_ixfr) {
16112 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
16113 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
16114 else
16115 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
16116 }
16117 UNLOCK_ZONE(zone);
16118 }
16119 cleanup:
16120 /*
16121 * Any failure in this function is handled like a failed
16122 * zone transfer. This ensures that we get removed from
16123 * zmgr->xfrin_in_progress.
16124 */
16125 if (result != ISC_R_SUCCESS)
16126 zone_xfrdone(zone, result);
16127
16128 isc_event_free(&event);
16129 }
16130
16131 /*
16132 * Update forwarding support.
16133 */
16134
16135 static void
16136 forward_destroy(dns_forward_t *forward) {
16137
16138 forward->magic = 0;
16139 if (forward->request != NULL)
16140 dns_request_destroy(&forward->request);
16141 if (forward->msgbuf != NULL)
16142 isc_buffer_free(&forward->msgbuf);
16143 if (forward->zone != NULL) {
16144 LOCK(&forward->zone->lock);
16145 if (ISC_LINK_LINKED(forward, link))
16146 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
16147 UNLOCK(&forward->zone->lock);
16148 dns_zone_idetach(&forward->zone);
16149 }
16150 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
16151 }
16152
16153 static isc_result_t
16154 sendtomaster(dns_forward_t *forward) {
16155 isc_result_t result;
16156 isc_sockaddr_t src;
16157 isc_dscp_t dscp = -1;
16158
16159 LOCK_ZONE(forward->zone);
16160
16161 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
16162 UNLOCK_ZONE(forward->zone);
16163 return (ISC_R_CANCELED);
16164 }
16165
16166 if (forward->which >= forward->zone->masterscnt) {
16167 UNLOCK_ZONE(forward->zone);
16168 return (ISC_R_NOMORE);
16169 }
16170
16171 forward->addr = forward->zone->masters[forward->which];
16172 /*
16173 * Always use TCP regardless of whether the original update
16174 * used TCP.
16175 * XXX The timeout may but a bit small if we are far down a
16176 * transfer graph and the master has to try several masters.
16177 */
16178 switch (isc_sockaddr_pf(&forward->addr)) {
16179 case PF_INET:
16180 src = forward->zone->xfrsource4;
16181 dscp = forward->zone->xfrsource4dscp;
16182 break;
16183 case PF_INET6:
16184 src = forward->zone->xfrsource6;
16185 dscp = forward->zone->xfrsource6dscp;
16186 break;
16187 default:
16188 result = ISC_R_NOTIMPLEMENTED;
16189 goto unlock;
16190 }
16191 result = dns_request_createraw(forward->zone->view->requestmgr,
16192 forward->msgbuf,
16193 &src, &forward->addr, dscp,
16194 forward->options, 15 /* XXX */,
16195 0, 0, forward->zone->task,
16196 forward_callback, forward,
16197 &forward->request);
16198 if (result == ISC_R_SUCCESS) {
16199 if (!ISC_LINK_LINKED(forward, link))
16200 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
16201 }
16202
16203 unlock:
16204 UNLOCK_ZONE(forward->zone);
16205 return (result);
16206 }
16207
16208 static void
16209 forward_callback(isc_task_t *task, isc_event_t *event) {
16210 const char me[] = "forward_callback";
16211 dns_requestevent_t *revent = (dns_requestevent_t *)event;
16212 dns_message_t *msg = NULL;
16213 char master[ISC_SOCKADDR_FORMATSIZE];
16214 isc_result_t result;
16215 dns_forward_t *forward;
16216 dns_zone_t *zone;
16217
16218 UNUSED(task);
16219
16220 forward = revent->ev_arg;
16221 INSIST(DNS_FORWARD_VALID(forward));
16222 zone = forward->zone;
16223 INSIST(DNS_ZONE_VALID(zone));
16224
16225 ENTER;
16226
16227 isc_sockaddr_format(&forward->addr, master, sizeof(master));
16228
16229 if (revent->result != ISC_R_SUCCESS) {
16230 dns_zone_log(zone, ISC_LOG_INFO,
16231 "could not forward dynamic update to %s: %s",
16232 master, dns_result_totext(revent->result));
16233 goto next_master;
16234 }
16235
16236 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
16237 if (result != ISC_R_SUCCESS)
16238 goto next_master;
16239
16240 result = dns_request_getresponse(revent->request, msg,
16241 DNS_MESSAGEPARSE_PRESERVEORDER |
16242 DNS_MESSAGEPARSE_CLONEBUFFER);
16243 if (result != ISC_R_SUCCESS)
16244 goto next_master;
16245
16246 switch (msg->rcode) {
16247 /*
16248 * Pass these rcodes back to client.
16249 */
16250 case dns_rcode_noerror:
16251 case dns_rcode_yxdomain:
16252 case dns_rcode_yxrrset:
16253 case dns_rcode_nxrrset:
16254 case dns_rcode_refused:
16255 case dns_rcode_nxdomain: {
16256 char rcode[128];
16257 isc_buffer_t rb;
16258
16259 isc_buffer_init(&rb, rcode, sizeof(rcode));
16260 (void)dns_rcode_totext(msg->rcode, &rb);
16261 dns_zone_log(zone, ISC_LOG_INFO,
16262 "forwarded dynamic update: "
16263 "master %s returned: %.*s",
16264 master, (int)rb.used, rcode);
16265 break;
16266 }
16267
16268 /* These should not occur if the masters/zone are valid. */
16269 case dns_rcode_notzone:
16270 case dns_rcode_notauth: {
16271 char rcode[128];
16272 isc_buffer_t rb;
16273
16274 isc_buffer_init(&rb, rcode, sizeof(rcode));
16275 (void)dns_rcode_totext(msg->rcode, &rb);
16276 dns_zone_log(zone, ISC_LOG_WARNING,
16277 "forwarding dynamic update: "
16278 "unexpected response: master %s returned: %.*s",
16279 master, (int)rb.used, rcode);
16280 goto next_master;
16281 }
16282
16283 /* Try another server for these rcodes. */
16284 case dns_rcode_formerr:
16285 case dns_rcode_servfail:
16286 case dns_rcode_notimp:
16287 case dns_rcode_badvers:
16288 default:
16289 goto next_master;
16290 }
16291
16292 /* call callback */
16293 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
16294 msg = NULL;
16295 dns_request_destroy(&forward->request);
16296 forward_destroy(forward);
16297 isc_event_free(&event);
16298 return;
16299
16300 next_master:
16301 if (msg != NULL)
16302 dns_message_destroy(&msg);
16303 isc_event_free(&event);
16304 forward->which++;
16305 dns_request_destroy(&forward->request);
16306 result = sendtomaster(forward);
16307 if (result != ISC_R_SUCCESS) {
16308 /* call callback */
16309 dns_zone_log(zone, ISC_LOG_DEBUG(3),
16310 "exhausted dynamic update forwarder list");
16311 (forward->callback)(forward->callback_arg, result, NULL);
16312 forward_destroy(forward);
16313 }
16314 }
16315
16316 isc_result_t
16317 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
16318 dns_updatecallback_t callback, void *callback_arg)
16319 {
16320 dns_forward_t *forward;
16321 isc_result_t result;
16322 isc_region_t *mr;
16323
16324 REQUIRE(DNS_ZONE_VALID(zone));
16325 REQUIRE(msg != NULL);
16326 REQUIRE(callback != NULL);
16327
16328 forward = isc_mem_get(zone->mctx, sizeof(*forward));
16329 if (forward == NULL)
16330 return (ISC_R_NOMEMORY);
16331
16332 forward->request = NULL;
16333 forward->zone = NULL;
16334 forward->msgbuf = NULL;
16335 forward->which = 0;
16336 forward->mctx = 0;
16337 forward->callback = callback;
16338 forward->callback_arg = callback_arg;
16339 ISC_LINK_INIT(forward, link);
16340 forward->magic = FORWARD_MAGIC;
16341 forward->options = DNS_REQUESTOPT_TCP;
16342 /*
16343 * If we have a SIG(0) signed message we need to preserve the
16344 * query id as that is included in the SIG(0) computation.
16345 */
16346 if (msg->sig0 != NULL)
16347 forward->options |= DNS_REQUESTOPT_FIXEDID;
16348
16349 mr = dns_message_getrawmessage(msg);
16350 if (mr == NULL) {
16351 result = ISC_R_UNEXPECTEDEND;
16352 goto cleanup;
16353 }
16354
16355 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
16356 if (result != ISC_R_SUCCESS)
16357 goto cleanup;
16358 result = isc_buffer_copyregion(forward->msgbuf, mr);
16359 if (result != ISC_R_SUCCESS)
16360 goto cleanup;
16361
16362 isc_mem_attach(zone->mctx, &forward->mctx);
16363 dns_zone_iattach(zone, &forward->zone);
16364 result = sendtomaster(forward);
16365
16366 cleanup:
16367 if (result != ISC_R_SUCCESS) {
16368 forward_destroy(forward);
16369 }
16370 return (result);
16371 }
16372
16373 isc_result_t
16374 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
16375 REQUIRE(DNS_ZONE_VALID(zone));
16376 REQUIRE(next != NULL && *next == NULL);
16377
16378 *next = ISC_LIST_NEXT(zone, link);
16379 if (*next == NULL)
16380 return (ISC_R_NOMORE);
16381 else
16382 return (ISC_R_SUCCESS);
16383 }
16384
16385 isc_result_t
16386 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
16387 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16388 REQUIRE(first != NULL && *first == NULL);
16389
16390 *first = ISC_LIST_HEAD(zmgr->zones);
16391 if (*first == NULL)
16392 return (ISC_R_NOMORE);
16393 else
16394 return (ISC_R_SUCCESS);
16395 }
16396
16397 /***
16398 *** Zone manager.
16399 ***/
16400
16401 isc_result_t
16402 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
16403 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
16404 dns_zonemgr_t **zmgrp)
16405 {
16406 dns_zonemgr_t *zmgr;
16407 isc_result_t result;
16408
16409 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
16410 if (zmgr == NULL)
16411 return (ISC_R_NOMEMORY);
16412 zmgr->mctx = NULL;
16413 zmgr->refs = 1;
16414 isc_mem_attach(mctx, &zmgr->mctx);
16415 zmgr->taskmgr = taskmgr;
16416 zmgr->timermgr = timermgr;
16417 zmgr->socketmgr = socketmgr;
16418 zmgr->zonetasks = NULL;
16419 zmgr->loadtasks = NULL;
16420 zmgr->mctxpool = NULL;
16421 zmgr->task = NULL;
16422 zmgr->notifyrl = NULL;
16423 zmgr->refreshrl = NULL;
16424 zmgr->startupnotifyrl = NULL;
16425 zmgr->startuprefreshrl = NULL;
16426 ISC_LIST_INIT(zmgr->zones);
16427 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
16428 ISC_LIST_INIT(zmgr->xfrin_in_progress);
16429 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
16430 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
16431 if (result != ISC_R_SUCCESS)
16432 goto free_mem;
16433
16434 zmgr->transfersin = 10;
16435 zmgr->transfersperns = 2;
16436
16437 /* Unreachable lock. */
16438 result = isc_rwlock_init(&zmgr->urlock, 0, 0);
16439 if (result != ISC_R_SUCCESS)
16440 goto free_rwlock;
16441
16442 /* Create a single task for queueing of SOA queries. */
16443 result = isc_task_create(taskmgr, 1, &zmgr->task);
16444 if (result != ISC_R_SUCCESS)
16445 goto free_urlock;
16446
16447 isc_task_setname(zmgr->task, "zmgr", zmgr);
16448 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16449 &zmgr->notifyrl);
16450 if (result != ISC_R_SUCCESS)
16451 goto free_task;
16452
16453 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16454 &zmgr->refreshrl);
16455 if (result != ISC_R_SUCCESS)
16456 goto free_notifyrl;
16457
16458 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16459 &zmgr->startupnotifyrl);
16460 if (result != ISC_R_SUCCESS)
16461 goto free_refreshrl;
16462
16463 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16464 &zmgr->startuprefreshrl);
16465 if (result != ISC_R_SUCCESS)
16466 goto free_startupnotifyrl;
16467
16468 /* default to 20 refresh queries / notifies per second. */
16469 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
16470 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
16471 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
16472 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
16473 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
16474 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
16475
16476 zmgr->iolimit = 1;
16477 zmgr->ioactive = 0;
16478 ISC_LIST_INIT(zmgr->high);
16479 ISC_LIST_INIT(zmgr->low);
16480
16481 isc_mutex_init(&zmgr->iolock);
16482
16483 zmgr->magic = ZONEMGR_MAGIC;
16484
16485 *zmgrp = zmgr;
16486 return (ISC_R_SUCCESS);
16487
16488 #if 0
16489 free_iolock:
16490 isc_mutex_destroy(&zmgr->iolock);
16491 #endif
16492 free_startupnotifyrl:
16493 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
16494 free_refreshrl:
16495 isc_ratelimiter_detach(&zmgr->refreshrl);
16496 free_notifyrl:
16497 isc_ratelimiter_detach(&zmgr->notifyrl);
16498 free_task:
16499 isc_task_detach(&zmgr->task);
16500 free_urlock:
16501 isc_rwlock_destroy(&zmgr->urlock);
16502 free_rwlock:
16503 isc_rwlock_destroy(&zmgr->rwlock);
16504 free_mem:
16505 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
16506 isc_mem_detach(&mctx);
16507 return (result);
16508 }
16509
16510 isc_result_t
16511 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
16512 isc_result_t result;
16513 isc_mem_t *mctx = NULL;
16514 dns_zone_t *zone = NULL;
16515 void *item;
16516
16517 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16518 REQUIRE(zonep != NULL && *zonep == NULL);
16519
16520 if (zmgr->mctxpool == NULL)
16521 return (ISC_R_FAILURE);
16522
16523 item = isc_pool_get(zmgr->mctxpool);
16524 if (item == NULL)
16525 return (ISC_R_FAILURE);
16526
16527 isc_mem_attach((isc_mem_t *) item, &mctx);
16528 result = dns_zone_create(&zone, mctx);
16529 isc_mem_detach(&mctx);
16530
16531 if (result == ISC_R_SUCCESS)
16532 *zonep = zone;
16533
16534 return (result);
16535 }
16536
16537 isc_result_t
16538 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16539 isc_result_t result;
16540
16541 REQUIRE(DNS_ZONE_VALID(zone));
16542 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16543
16544 if (zmgr->zonetasks == NULL)
16545 return (ISC_R_FAILURE);
16546
16547 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16548 LOCK_ZONE(zone);
16549 REQUIRE(zone->task == NULL);
16550 REQUIRE(zone->timer == NULL);
16551 REQUIRE(zone->zmgr == NULL);
16552
16553 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
16554 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
16555
16556 /*
16557 * Set the task name. The tag will arbitrarily point to one
16558 * of the zones sharing the task (in practice, the one
16559 * to be managed last).
16560 */
16561 isc_task_setname(zone->task, "zone", zone);
16562 isc_task_setname(zone->loadtask, "loadzone", zone);
16563
16564 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16565 NULL, NULL,
16566 zone->task, zone_timer, zone,
16567 &zone->timer);
16568
16569 if (result != ISC_R_SUCCESS)
16570 goto cleanup_tasks;
16571
16572 /*
16573 * The timer "holds" a iref.
16574 */
16575 zone->irefs++;
16576 INSIST(zone->irefs != 0);
16577
16578 ISC_LIST_APPEND(zmgr->zones, zone, link);
16579 zone->zmgr = zmgr;
16580 zmgr->refs++;
16581
16582 goto unlock;
16583
16584 cleanup_tasks:
16585 isc_task_detach(&zone->loadtask);
16586 isc_task_detach(&zone->task);
16587
16588 unlock:
16589 UNLOCK_ZONE(zone);
16590 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16591 return (result);
16592 }
16593
16594 void
16595 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16596 bool free_now = false;
16597
16598 REQUIRE(DNS_ZONE_VALID(zone));
16599 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16600 REQUIRE(zone->zmgr == zmgr);
16601
16602 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16603 LOCK_ZONE(zone);
16604
16605 ISC_LIST_UNLINK(zmgr->zones, zone, link);
16606 zone->zmgr = NULL;
16607 zmgr->refs--;
16608 if (zmgr->refs == 0)
16609 free_now = true;
16610
16611 UNLOCK_ZONE(zone);
16612 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16613
16614 if (free_now)
16615 zonemgr_free(zmgr);
16616 ENSURE(zone->zmgr == NULL);
16617 }
16618
16619 void
16620 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
16621 REQUIRE(DNS_ZONEMGR_VALID(source));
16622 REQUIRE(target != NULL && *target == NULL);
16623
16624 RWLOCK(&source->rwlock, isc_rwlocktype_write);
16625 REQUIRE(source->refs > 0);
16626 source->refs++;
16627 INSIST(source->refs > 0);
16628 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
16629 *target = source;
16630 }
16631
16632 void
16633 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
16634 dns_zonemgr_t *zmgr;
16635 bool free_now = false;
16636
16637 REQUIRE(zmgrp != NULL);
16638 zmgr = *zmgrp;
16639 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16640
16641 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16642 zmgr->refs--;
16643 if (zmgr->refs == 0)
16644 free_now = true;
16645 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16646
16647 if (free_now)
16648 zonemgr_free(zmgr);
16649 *zmgrp = NULL;
16650 }
16651
16652 isc_result_t
16653 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
16654 dns_zone_t *p;
16655
16656 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16657
16658 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16659 for (p = ISC_LIST_HEAD(zmgr->zones);
16660 p != NULL;
16661 p = ISC_LIST_NEXT(p, link))
16662 {
16663 dns_zone_maintenance(p);
16664 }
16665 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16666
16667 /*
16668 * Recent configuration changes may have increased the
16669 * amount of available transfers quota. Make sure any
16670 * transfers currently blocked on quota get started if
16671 * possible.
16672 */
16673 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16674 zmgr_resume_xfrs(zmgr, true);
16675 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16676 return (ISC_R_SUCCESS);
16677 }
16678
16679 void
16680 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
16681
16682 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16683
16684 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16685 zmgr_resume_xfrs(zmgr, true);
16686 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16687 }
16688
16689 void
16690 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
16691 dns_zone_t *zone;
16692
16693 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16694
16695 isc_ratelimiter_shutdown(zmgr->notifyrl);
16696 isc_ratelimiter_shutdown(zmgr->refreshrl);
16697 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
16698 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
16699
16700 if (zmgr->task != NULL)
16701 isc_task_destroy(&zmgr->task);
16702 if (zmgr->zonetasks != NULL)
16703 isc_taskpool_destroy(&zmgr->zonetasks);
16704 if (zmgr->loadtasks != NULL)
16705 isc_taskpool_destroy(&zmgr->loadtasks);
16706 if (zmgr->mctxpool != NULL)
16707 isc_pool_destroy(&zmgr->mctxpool);
16708
16709 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16710 for (zone = ISC_LIST_HEAD(zmgr->zones);
16711 zone != NULL;
16712 zone = ISC_LIST_NEXT(zone, link))
16713 {
16714 LOCK_ZONE(zone);
16715 forward_cancel(zone);
16716 UNLOCK_ZONE(zone);
16717 }
16718 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16719 }
16720
16721 static isc_result_t
16722 mctxinit(void **target, void *arg) {
16723 isc_result_t result;
16724 isc_mem_t *mctx = NULL;
16725
16726 UNUSED(arg);
16727
16728 REQUIRE(target != NULL && *target == NULL);
16729
16730 result = isc_mem_create(0, 0, &mctx);
16731 if (result != ISC_R_SUCCESS)
16732 return (result);
16733 isc_mem_setname(mctx, "zonemgr-pool", NULL);
16734
16735 *target = mctx;
16736 return (ISC_R_SUCCESS);
16737 }
16738
16739 static void
16740 mctxfree(void **target) {
16741 isc_mem_t *mctx = *(isc_mem_t **) target;
16742 isc_mem_detach(&mctx);
16743 *target = NULL;
16744 }
16745
16746 #define ZONES_PER_TASK 100
16747 #define ZONES_PER_MCTX 1000
16748
16749 isc_result_t
16750 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
16751 isc_result_t result;
16752 int ntasks = num_zones / ZONES_PER_TASK;
16753 int nmctx = num_zones / ZONES_PER_MCTX;
16754 isc_taskpool_t *pool = NULL;
16755 isc_pool_t *mctxpool = NULL;
16756
16757 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16758
16759 /*
16760 * For anything fewer than 1000 zones we use 10 tasks in
16761 * the task pools. More than that, and we'll scale at one
16762 * task per 100 zones. Similarly, for anything smaller than
16763 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
16764 */
16765 if (ntasks < 10)
16766 ntasks = 10;
16767 if (nmctx < 2)
16768 nmctx = 2;
16769
16770 /* Create or resize the zone task pools. */
16771 if (zmgr->zonetasks == NULL)
16772 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16773 ntasks, 2, &pool);
16774 else
16775 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
16776
16777 if (result == ISC_R_SUCCESS)
16778 zmgr->zonetasks = pool;
16779
16780 pool = NULL;
16781 if (zmgr->loadtasks == NULL)
16782 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16783 ntasks, 2, &pool);
16784 else
16785 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
16786
16787 if (result == ISC_R_SUCCESS)
16788 zmgr->loadtasks = pool;
16789
16790 /*
16791 * We always set all tasks in the zone-load task pool to
16792 * privileged. This prevents other tasks in the system from
16793 * running while the server task manager is in privileged
16794 * mode.
16795 *
16796 * NOTE: If we start using task privileges for any other
16797 * part of the system than zone tasks, then this will need to be
16798 * revisted. In that case we'd want to turn on privileges for
16799 * zone tasks only when we were loading, and turn them off the
16800 * rest of the time. For now, however, it's okay to just
16801 * set it and forget it.
16802 */
16803 isc_taskpool_setprivilege(zmgr->loadtasks, true);
16804
16805 /* Create or resize the zone memory context pool. */
16806 if (zmgr->mctxpool == NULL)
16807 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
16808 mctxinit, NULL, &mctxpool);
16809 else
16810 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
16811
16812 if (result == ISC_R_SUCCESS)
16813 zmgr->mctxpool = mctxpool;
16814
16815 return (result);
16816 }
16817
16818 static void
16819 zonemgr_free(dns_zonemgr_t *zmgr) {
16820 isc_mem_t *mctx;
16821
16822 INSIST(zmgr->refs == 0);
16823 INSIST(ISC_LIST_EMPTY(zmgr->zones));
16824
16825 zmgr->magic = 0;
16826
16827 isc_mutex_destroy(&zmgr->iolock);
16828 isc_ratelimiter_detach(&zmgr->notifyrl);
16829 isc_ratelimiter_detach(&zmgr->refreshrl);
16830 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
16831 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
16832
16833 isc_rwlock_destroy(&zmgr->urlock);
16834 isc_rwlock_destroy(&zmgr->rwlock);
16835 mctx = zmgr->mctx;
16836 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
16837 isc_mem_detach(&mctx);
16838 }
16839
16840 void
16841 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
16842 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16843
16844 zmgr->transfersin = value;
16845 }
16846
16847 uint32_t
16848 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
16849 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16850
16851 return (zmgr->transfersin);
16852 }
16853
16854 void
16855 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
16856 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16857
16858 zmgr->transfersperns = value;
16859 }
16860
16861 uint32_t
16862 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
16863 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16864
16865 return (zmgr->transfersperns);
16866 }
16867
16868 /*
16869 * Try to start a new incoming zone transfer to fill a quota
16870 * slot that was just vacated.
16871 *
16872 * Requires:
16873 * The zone manager is locked by the caller.
16874 */
16875 static void
16876 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
16877 dns_zone_t *zone;
16878 dns_zone_t *next;
16879
16880 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
16881 zone != NULL;
16882 zone = next)
16883 {
16884 isc_result_t result;
16885 next = ISC_LIST_NEXT(zone, statelink);
16886 result = zmgr_start_xfrin_ifquota(zmgr, zone);
16887 if (result == ISC_R_SUCCESS) {
16888 if (multi)
16889 continue;
16890 /*
16891 * We successfully filled the slot. We're done.
16892 */
16893 break;
16894 } else if (result == ISC_R_QUOTA) {
16895 /*
16896 * Not enough quota. This is probably the per-server
16897 * quota, because we usually get called when a unit of
16898 * global quota has just been freed. Try the next
16899 * zone, it may succeed if it uses another master.
16900 */
16901 continue;
16902 } else {
16903 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16904 "starting zone transfer: %s",
16905 isc_result_totext(result));
16906 break;
16907 }
16908 }
16909 }
16910
16911 /*
16912 * Try to start an incoming zone transfer for 'zone', quota permitting.
16913 *
16914 * Requires:
16915 * The zone manager is locked by the caller.
16916 *
16917 * Returns:
16918 * ISC_R_SUCCESS There was enough quota and we attempted to
16919 * start a transfer. zone_xfrdone() has been or will
16920 * be called.
16921 * ISC_R_QUOTA Not enough quota.
16922 * Others Failure.
16923 */
16924 static isc_result_t
16925 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16926 dns_peer_t *peer = NULL;
16927 isc_netaddr_t masterip;
16928 uint32_t nxfrsin, nxfrsperns;
16929 dns_zone_t *x;
16930 uint32_t maxtransfersin, maxtransfersperns;
16931 isc_event_t *e;
16932
16933 /*
16934 * If we are exiting just pretend we got quota so the zone will
16935 * be cleaned up in the zone's task context.
16936 */
16937 LOCK_ZONE(zone);
16938 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
16939 UNLOCK_ZONE(zone);
16940 goto gotquota;
16941 }
16942
16943 /*
16944 * Find any configured information about the server we'd
16945 * like to transfer this zone from.
16946 */
16947 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
16948 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
16949 UNLOCK_ZONE(zone);
16950
16951 /*
16952 * Determine the total maximum number of simultaneous
16953 * transfers allowed, and the maximum for this specific
16954 * master.
16955 */
16956 maxtransfersin = zmgr->transfersin;
16957 maxtransfersperns = zmgr->transfersperns;
16958 if (peer != NULL)
16959 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
16960
16961 /*
16962 * Count the total number of transfers that are in progress,
16963 * and the number of transfers in progress from this master.
16964 * We linearly scan a list of all transfers; if this turns
16965 * out to be too slow, we could hash on the master address.
16966 */
16967 nxfrsin = nxfrsperns = 0;
16968 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
16969 x != NULL;
16970 x = ISC_LIST_NEXT(x, statelink))
16971 {
16972 isc_netaddr_t xip;
16973
16974 LOCK_ZONE(x);
16975 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
16976 UNLOCK_ZONE(x);
16977
16978 nxfrsin++;
16979 if (isc_netaddr_equal(&xip, &masterip))
16980 nxfrsperns++;
16981 }
16982
16983 /* Enforce quota. */
16984 if (nxfrsin >= maxtransfersin)
16985 return (ISC_R_QUOTA);
16986
16987 if (nxfrsperns >= maxtransfersperns)
16988 return (ISC_R_QUOTA);
16989
16990 gotquota:
16991 /*
16992 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
16993 * list and send it an event to let it start the actual transfer in the
16994 * context of its own task.
16995 */
16996 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
16997 got_transfer_quota, zone, sizeof(isc_event_t));
16998 if (e == NULL)
16999 return (ISC_R_NOMEMORY);
17000
17001 LOCK_ZONE(zone);
17002 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
17003 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
17004 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
17005 zone->statelist = &zmgr->xfrin_in_progress;
17006 isc_task_send(zone->task, &e);
17007 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
17008 UNLOCK_ZONE(zone);
17009
17010 return (ISC_R_SUCCESS);
17011 }
17012
17013 void
17014 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
17015
17016 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17017 REQUIRE(iolimit > 0);
17018
17019 zmgr->iolimit = iolimit;
17020 }
17021
17022 uint32_t
17023 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
17024
17025 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17026
17027 return (zmgr->iolimit);
17028 }
17029
17030 /*
17031 * Get permission to request a file handle from the OS.
17032 * An event will be sent to action when one is available.
17033 * There are two queues available (high and low), the high
17034 * queue will be serviced before the low one.
17035 *
17036 * zonemgr_putio() must be called after the event is delivered to
17037 * 'action'.
17038 */
17039
17040 static isc_result_t
17041 zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
17042 isc_task_t *task, isc_taskaction_t action, void *arg,
17043 dns_io_t **iop)
17044 {
17045 dns_io_t *io;
17046 bool queue;
17047
17048 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17049 REQUIRE(iop != NULL && *iop == NULL);
17050
17051 io = isc_mem_get(zmgr->mctx, sizeof(*io));
17052 if (io == NULL)
17053 return (ISC_R_NOMEMORY);
17054
17055 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
17056 action, arg, sizeof(*io->event));
17057 if (io->event == NULL) {
17058 isc_mem_put(zmgr->mctx, io, sizeof(*io));
17059 return (ISC_R_NOMEMORY);
17060 }
17061
17062 io->zmgr = zmgr;
17063 io->high = high;
17064 io->task = NULL;
17065 isc_task_attach(task, &io->task);
17066 ISC_LINK_INIT(io, link);
17067 io->magic = IO_MAGIC;
17068
17069 LOCK(&zmgr->iolock);
17070 zmgr->ioactive++;
17071 queue = (zmgr->ioactive > zmgr->iolimit);
17072 if (queue) {
17073 if (io->high)
17074 ISC_LIST_APPEND(zmgr->high, io, link);
17075 else
17076 ISC_LIST_APPEND(zmgr->low, io, link);
17077 }
17078 UNLOCK(&zmgr->iolock);
17079 *iop = io;
17080
17081 if (!queue)
17082 isc_task_send(io->task, &io->event);
17083 return (ISC_R_SUCCESS);
17084 }
17085
17086 static void
17087 zonemgr_putio(dns_io_t **iop) {
17088 dns_io_t *io;
17089 dns_io_t *next;
17090 dns_zonemgr_t *zmgr;
17091
17092 REQUIRE(iop != NULL);
17093 io = *iop;
17094 REQUIRE(DNS_IO_VALID(io));
17095
17096 *iop = NULL;
17097
17098 INSIST(!ISC_LINK_LINKED(io, link));
17099 INSIST(io->event == NULL);
17100
17101 zmgr = io->zmgr;
17102 isc_task_detach(&io->task);
17103 io->magic = 0;
17104 isc_mem_put(zmgr->mctx, io, sizeof(*io));
17105
17106 LOCK(&zmgr->iolock);
17107 INSIST(zmgr->ioactive > 0);
17108 zmgr->ioactive--;
17109 next = HEAD(zmgr->high);
17110 if (next == NULL)
17111 next = HEAD(zmgr->low);
17112 if (next != NULL) {
17113 if (next->high)
17114 ISC_LIST_UNLINK(zmgr->high, next, link);
17115 else
17116 ISC_LIST_UNLINK(zmgr->low, next, link);
17117 INSIST(next->event != NULL);
17118 }
17119 UNLOCK(&zmgr->iolock);
17120 if (next != NULL)
17121 isc_task_send(next->task, &next->event);
17122 }
17123
17124 static void
17125 zonemgr_cancelio(dns_io_t *io) {
17126 bool send_event = false;
17127
17128 REQUIRE(DNS_IO_VALID(io));
17129
17130 /*
17131 * If we are queued to be run then dequeue.
17132 */
17133 LOCK(&io->zmgr->iolock);
17134 if (ISC_LINK_LINKED(io, link)) {
17135 if (io->high)
17136 ISC_LIST_UNLINK(io->zmgr->high, io, link);
17137 else
17138 ISC_LIST_UNLINK(io->zmgr->low, io, link);
17139
17140 send_event = true;
17141 INSIST(io->event != NULL);
17142 }
17143 UNLOCK(&io->zmgr->iolock);
17144 if (send_event) {
17145 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
17146 isc_task_send(io->task, &io->event);
17147 }
17148 }
17149
17150 static void
17151 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
17152 char *buf;
17153 int buflen;
17154 isc_result_t result;
17155
17156 buflen = strlen(path) + strlen(templat) + 2;
17157
17158 buf = isc_mem_get(zone->mctx, buflen);
17159 if (buf == NULL)
17160 return;
17161
17162 result = isc_file_template(path, templat, buf, buflen);
17163 if (result != ISC_R_SUCCESS)
17164 goto cleanup;
17165
17166 result = isc_file_renameunique(path, buf);
17167 if (result != ISC_R_SUCCESS)
17168 goto cleanup;
17169
17170 dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
17171 "renaming file to '%s' for failure analysis and "
17172 "retransferring.", path, buf);
17173
17174 cleanup:
17175 isc_mem_put(zone->mctx, buf, buflen);
17176 }
17177
17178 static void
17179 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
17180 isc_interval_t interval;
17181 uint32_t s, ns;
17182 uint32_t pertic;
17183 isc_result_t result;
17184
17185 if (value == 0)
17186 value = 1;
17187
17188 if (value == 1) {
17189 s = 1;
17190 ns = 0;
17191 pertic = 1;
17192 } else if (value <= 10) {
17193 s = 0;
17194 ns = 1000000000 / value;
17195 pertic = 1;
17196 } else {
17197 s = 0;
17198 ns = (1000000000 / value) * 10;
17199 pertic = 10;
17200 }
17201
17202 isc_interval_set(&interval, s, ns);
17203
17204 result = isc_ratelimiter_setinterval(rl, &interval);
17205 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17206 isc_ratelimiter_setpertic(rl, pertic);
17207
17208 *rate = value;
17209 }
17210
17211 void
17212 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
17213
17214 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17215
17216 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
17217 }
17218
17219 void
17220 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
17221
17222 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17223
17224 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
17225 }
17226
17227 void
17228 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
17229
17230 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17231
17232 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
17233 /* XXXMPA seperate out once we have the code to support this. */
17234 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
17235 }
17236
17237 unsigned int
17238 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
17239 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17240
17241 return (zmgr->notifyrate);
17242 }
17243
17244 unsigned int
17245 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
17246 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17247
17248 return (zmgr->startupnotifyrate);
17249 }
17250
17251 unsigned int
17252 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
17253 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17254
17255 return (zmgr->serialqueryrate);
17256 }
17257
17258 bool
17259 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17260 isc_sockaddr_t *local, isc_time_t *now)
17261 {
17262 unsigned int i;
17263 isc_rwlocktype_t locktype;
17264 isc_result_t result;
17265 uint32_t seconds = isc_time_seconds(now);
17266 uint32_t count = 0;
17267
17268 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17269
17270 locktype = isc_rwlocktype_read;
17271 RWLOCK(&zmgr->urlock, locktype);
17272 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17273 if (zmgr->unreachable[i].expire >= seconds &&
17274 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17275 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
17276 result = isc_rwlock_tryupgrade(&zmgr->urlock);
17277 if (result == ISC_R_SUCCESS) {
17278 locktype = isc_rwlocktype_write;
17279 zmgr->unreachable[i].last = seconds;
17280 count = zmgr->unreachable[i].count;
17281 }
17282 break;
17283 }
17284 }
17285 RWUNLOCK(&zmgr->urlock, locktype);
17286 return (i < UNREACH_CHACHE_SIZE && count > 1U);
17287 }
17288
17289 void
17290 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17291 isc_sockaddr_t *local)
17292 {
17293 unsigned int i;
17294 isc_rwlocktype_t locktype;
17295 isc_result_t result;
17296
17297 char master[ISC_SOCKADDR_FORMATSIZE];
17298 char source[ISC_SOCKADDR_FORMATSIZE];
17299
17300 isc_sockaddr_format(remote, master, sizeof(master));
17301 isc_sockaddr_format(local, source, sizeof(source));
17302
17303 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17304
17305 locktype = isc_rwlocktype_read;
17306 RWLOCK(&zmgr->urlock, locktype);
17307 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17308 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17309 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
17310 if (zmgr->unreachable[i].expire == 0)
17311 break;
17312 result = isc_rwlock_tryupgrade(&zmgr->urlock);
17313 if (result == ISC_R_SUCCESS) {
17314 locktype = isc_rwlocktype_write;
17315 zmgr->unreachable[i].expire = 0;
17316 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17317 DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
17318 "master %s (source %s) deleted "
17319 "from unreachable cache",
17320 master, source);
17321 }
17322 break;
17323 }
17324 }
17325 RWUNLOCK(&zmgr->urlock, locktype);
17326 }
17327
17328 void
17329 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17330 isc_sockaddr_t *local, isc_time_t *now)
17331 {
17332 uint32_t seconds = isc_time_seconds(now);
17333 uint32_t last = seconds;
17334 unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
17335
17336 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17337
17338 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
17339 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17340 /* Existing entry? */
17341 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17342 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
17343 break;
17344 /* Empty slot? */
17345 if (zmgr->unreachable[i].expire < seconds)
17346 slot = i;
17347 /* Least recently used slot? */
17348 if (zmgr->unreachable[i].last < last) {
17349 last = zmgr->unreachable[i].last;
17350 oldest = i;
17351 }
17352 }
17353 if (i < UNREACH_CHACHE_SIZE) {
17354 /*
17355 * Found a existing entry. Update the expire timer and
17356 * last usage timestamps.
17357 */
17358 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
17359 zmgr->unreachable[i].last = seconds;
17360 if (zmgr->unreachable[i].expire < seconds)
17361 zmgr->unreachable[i].count = 1;
17362 else
17363 zmgr->unreachable[i].count++;
17364 } else if (slot != UNREACH_CHACHE_SIZE) {
17365 /*
17366 * Found a empty slot. Add a new entry to the cache.
17367 */
17368 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
17369 zmgr->unreachable[slot].last = seconds;
17370 zmgr->unreachable[slot].remote = *remote;
17371 zmgr->unreachable[slot].local = *local;
17372 zmgr->unreachable[slot].count = 1;
17373 } else {
17374 /*
17375 * Replace the least recently used entry in the cache.
17376 */
17377 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
17378 zmgr->unreachable[oldest].last = seconds;
17379 zmgr->unreachable[oldest].remote = *remote;
17380 zmgr->unreachable[oldest].local = *local;
17381 zmgr->unreachable[oldest].count = 1;
17382 }
17383 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
17384 }
17385
17386 void
17387 dns_zone_forcereload(dns_zone_t *zone) {
17388 REQUIRE(DNS_ZONE_VALID(zone));
17389
17390 if (zone->type == dns_zone_master ||
17391 (zone->type == dns_zone_redirect && zone->masters == NULL))
17392 return;
17393
17394 LOCK_ZONE(zone);
17395 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17396 UNLOCK_ZONE(zone);
17397 dns_zone_refresh(zone);
17398 }
17399
17400 bool
17401 dns_zone_isforced(dns_zone_t *zone) {
17402 REQUIRE(DNS_ZONE_VALID(zone));
17403
17404 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
17405 }
17406
17407 isc_result_t
17408 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
17409 /*
17410 * This function is obsoleted.
17411 */
17412 UNUSED(zone);
17413 UNUSED(on);
17414 return (ISC_R_NOTIMPLEMENTED);
17415 }
17416
17417 uint64_t *
17418 dns_zone_getstatscounters(dns_zone_t *zone) {
17419 /*
17420 * This function is obsoleted.
17421 */
17422 UNUSED(zone);
17423 return (NULL);
17424 }
17425
17426 void
17427 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
17428 REQUIRE(DNS_ZONE_VALID(zone));
17429 REQUIRE(zone->stats == NULL);
17430
17431 LOCK_ZONE(zone);
17432 zone->stats = NULL;
17433 isc_stats_attach(stats, &zone->stats);
17434 UNLOCK_ZONE(zone);
17435 }
17436
17437 void
17438 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
17439
17440 REQUIRE(DNS_ZONE_VALID(zone));
17441
17442 LOCK_ZONE(zone);
17443 if (zone->requeststats_on && stats == NULL)
17444 zone->requeststats_on = false;
17445 else if (!zone->requeststats_on && stats != NULL) {
17446 if (zone->requeststats == NULL) {
17447 isc_stats_attach(stats, &zone->requeststats);
17448 zone->requeststats_on = true;
17449 }
17450 }
17451 UNLOCK_ZONE(zone);
17452 }
17453
17454 void
17455 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
17456
17457 REQUIRE(DNS_ZONE_VALID(zone));
17458
17459 LOCK_ZONE(zone);
17460 if (zone->requeststats_on && stats != NULL) {
17461 if (zone->rcvquerystats == NULL) {
17462 dns_stats_attach(stats, &zone->rcvquerystats);
17463 zone->requeststats_on = true;
17464 }
17465 }
17466 UNLOCK_ZONE(zone);
17467 }
17468
17469 isc_stats_t *
17470 dns_zone_getrequeststats(dns_zone_t *zone) {
17471 /*
17472 * We don't lock zone for efficiency reason. This is not catastrophic
17473 * because requeststats must always be valid when requeststats_on is
17474 * true.
17475 * Some counters may be incremented while requeststats_on is becoming
17476 * false, or some cannot be incremented just after the statistics are
17477 * installed, but it shouldn't matter much in practice.
17478 */
17479 if (zone->requeststats_on)
17480 return (zone->requeststats);
17481 else
17482 return (NULL);
17483 }
17484
17485 /*
17486 * Return the received query stats bucket
17487 * see note from dns_zone_getrequeststats()
17488 */
17489 dns_stats_t *
17490 dns_zone_getrcvquerystats(dns_zone_t *zone) {
17491 if (zone->requeststats_on)
17492 return (zone->rcvquerystats);
17493 else
17494 return (NULL);
17495 }
17496
17497 void
17498 dns_zone_dialup(dns_zone_t *zone) {
17499
17500 REQUIRE(DNS_ZONE_VALID(zone));
17501
17502 zone_debuglog(zone, "dns_zone_dialup", 3,
17503 "notify = %d, refresh = %d",
17504 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
17505 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
17506
17507 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
17508 dns_zone_notify(zone);
17509 if (zone->type != dns_zone_master && zone->masters != NULL &&
17510 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
17511 dns_zone_refresh(zone);
17512 }
17513
17514 void
17515 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
17516 REQUIRE(DNS_ZONE_VALID(zone));
17517
17518 LOCK_ZONE(zone);
17519 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
17520 DNS_ZONEFLG_DIALREFRESH |
17521 DNS_ZONEFLG_NOREFRESH);
17522 switch (dialup) {
17523 case dns_dialuptype_no:
17524 break;
17525 case dns_dialuptype_yes:
17526 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
17527 DNS_ZONEFLG_DIALREFRESH |
17528 DNS_ZONEFLG_NOREFRESH));
17529 break;
17530 case dns_dialuptype_notify:
17531 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17532 break;
17533 case dns_dialuptype_notifypassive:
17534 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17535 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17536 break;
17537 case dns_dialuptype_refresh:
17538 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
17539 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17540 break;
17541 case dns_dialuptype_passive:
17542 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17543 break;
17544 default:
17545 INSIST(0);
17546 ISC_UNREACHABLE();
17547 }
17548 UNLOCK_ZONE(zone);
17549 }
17550
17551 isc_result_t
17552 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
17553 isc_result_t result = ISC_R_SUCCESS;
17554
17555 REQUIRE(DNS_ZONE_VALID(zone));
17556
17557 LOCK_ZONE(zone);
17558 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
17559 UNLOCK_ZONE(zone);
17560
17561 return (result);
17562 }
17563
17564 const char *
17565 dns_zone_getkeydirectory(dns_zone_t *zone) {
17566 REQUIRE(DNS_ZONE_VALID(zone));
17567
17568 return (zone->keydirectory);
17569 }
17570
17571 unsigned int
17572 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
17573 dns_zone_t *zone;
17574 unsigned int count = 0;
17575
17576 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17577
17578 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17579 switch (state) {
17580 case DNS_ZONESTATE_XFERRUNNING:
17581 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
17582 zone != NULL;
17583 zone = ISC_LIST_NEXT(zone, statelink))
17584 count++;
17585 break;
17586 case DNS_ZONESTATE_XFERDEFERRED:
17587 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
17588 zone != NULL;
17589 zone = ISC_LIST_NEXT(zone, statelink))
17590 count++;
17591 break;
17592 case DNS_ZONESTATE_SOAQUERY:
17593 for (zone = ISC_LIST_HEAD(zmgr->zones);
17594 zone != NULL;
17595 zone = ISC_LIST_NEXT(zone, link))
17596 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
17597 count++;
17598 break;
17599 case DNS_ZONESTATE_ANY:
17600 for (zone = ISC_LIST_HEAD(zmgr->zones);
17601 zone != NULL;
17602 zone = ISC_LIST_NEXT(zone, link)) {
17603 dns_view_t *view = zone->view;
17604 if (view != NULL && strcmp(view->name, "_bind") == 0)
17605 continue;
17606 count++;
17607 }
17608 break;
17609 case DNS_ZONESTATE_AUTOMATIC:
17610 for (zone = ISC_LIST_HEAD(zmgr->zones);
17611 zone != NULL;
17612 zone = ISC_LIST_NEXT(zone, link)) {
17613 dns_view_t *view = zone->view;
17614 if (view != NULL && strcmp(view->name, "_bind") == 0)
17615 continue;
17616 if (zone->automatic)
17617 count++;
17618 }
17619 break;
17620 default:
17621 INSIST(0);
17622 ISC_UNREACHABLE();
17623 }
17624
17625 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17626
17627 return (count);
17628 }
17629
17630 isc_result_t
17631 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
17632 dns_rdata_t *rdata)
17633 {
17634 bool ok = true;
17635 bool fail = false;
17636 char namebuf[DNS_NAME_FORMATSIZE];
17637 char namebuf2[DNS_NAME_FORMATSIZE];
17638 char typebuf[DNS_RDATATYPE_FORMATSIZE];
17639 int level = ISC_LOG_WARNING;
17640 dns_name_t bad;
17641
17642 REQUIRE(DNS_ZONE_VALID(zone));
17643
17644 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
17645 rdata->type != dns_rdatatype_nsec3)
17646 return (ISC_R_SUCCESS);
17647
17648 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
17649 rdata->type == dns_rdatatype_nsec3) {
17650 level = ISC_LOG_ERROR;
17651 fail = true;
17652 }
17653
17654 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
17655 if (!ok) {
17656 dns_name_format(name, namebuf, sizeof(namebuf));
17657 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17658 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
17659 dns_result_totext(DNS_R_BADOWNERNAME));
17660 if (fail)
17661 return (DNS_R_BADOWNERNAME);
17662 }
17663
17664 dns_name_init(&bad, NULL);
17665 ok = dns_rdata_checknames(rdata, name, &bad);
17666 if (!ok) {
17667 dns_name_format(name, namebuf, sizeof(namebuf));
17668 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
17669 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17670 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
17671 namebuf2, dns_result_totext(DNS_R_BADNAME));
17672 if (fail)
17673 return (DNS_R_BADNAME);
17674 }
17675
17676 return (ISC_R_SUCCESS);
17677 }
17678
17679 void
17680 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
17681 REQUIRE(DNS_ZONE_VALID(zone));
17682 zone->checkmx = checkmx;
17683 }
17684
17685 void
17686 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
17687 REQUIRE(DNS_ZONE_VALID(zone));
17688 zone->checksrv = checksrv;
17689 }
17690
17691 void
17692 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
17693 REQUIRE(DNS_ZONE_VALID(zone));
17694 zone->checkns = checkns;
17695 }
17696
17697 void
17698 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
17699 REQUIRE(DNS_ZONE_VALID(zone));
17700
17701 LOCK_ZONE(zone);
17702 zone->isself = isself;
17703 zone->isselfarg = arg;
17704 UNLOCK_ZONE(zone);
17705 }
17706
17707 void
17708 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
17709 REQUIRE(DNS_ZONE_VALID(zone));
17710
17711 LOCK_ZONE(zone);
17712 zone->notifydelay = delay;
17713 UNLOCK_ZONE(zone);
17714 }
17715
17716 uint32_t
17717 dns_zone_getnotifydelay(dns_zone_t *zone) {
17718 REQUIRE(DNS_ZONE_VALID(zone));
17719
17720 return (zone->notifydelay);
17721 }
17722
17723 isc_result_t
17724 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
17725 uint16_t keyid, bool deleteit)
17726 {
17727 isc_result_t result;
17728 REQUIRE(DNS_ZONE_VALID(zone));
17729
17730 dnssec_log(zone, ISC_LOG_NOTICE,
17731 "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
17732 algorithm, keyid);
17733 LOCK_ZONE(zone);
17734 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
17735 UNLOCK_ZONE(zone);
17736
17737 return (result);
17738 }
17739
17740 /*
17741 * Called when a dynamic update for an NSEC3PARAM record is received.
17742 *
17743 * If set, transform the NSEC3 salt into human-readable form so that it can be
17744 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
17745 */
17746 isc_result_t
17747 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
17748 isc_result_t result;
17749 char salt[255*2+1];
17750
17751 REQUIRE(DNS_ZONE_VALID(zone));
17752
17753 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
17754 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17755 dnssec_log(zone, ISC_LOG_NOTICE,
17756 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
17757 nsec3param->hash, nsec3param->iterations, salt);
17758 LOCK_ZONE(zone);
17759 result = zone_addnsec3chain(zone, nsec3param);
17760 UNLOCK_ZONE(zone);
17761
17762 return (result);
17763 }
17764
17765 void
17766 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
17767 REQUIRE(DNS_ZONE_VALID(zone));
17768
17769 if (nodes == 0)
17770 nodes = 1;
17771 zone->nodes = nodes;
17772 }
17773
17774 void
17775 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
17776 REQUIRE(DNS_ZONE_VALID(zone));
17777
17778 /*
17779 * We treat signatures as a signed value so explicitly
17780 * limit its range here.
17781 */
17782 if (signatures > INT32_MAX)
17783 signatures = INT32_MAX;
17784 else if (signatures == 0)
17785 signatures = 1;
17786 zone->signatures = signatures;
17787 }
17788
17789 uint32_t
17790 dns_zone_getsignatures(dns_zone_t *zone) {
17791 REQUIRE(DNS_ZONE_VALID(zone));
17792 return (zone->signatures);
17793 }
17794
17795 void
17796 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
17797 REQUIRE(DNS_ZONE_VALID(zone));
17798 zone->privatetype = type;
17799 }
17800
17801 dns_rdatatype_t
17802 dns_zone_getprivatetype(dns_zone_t *zone) {
17803 REQUIRE(DNS_ZONE_VALID(zone));
17804 return (zone->privatetype);
17805 }
17806
17807 static isc_result_t
17808 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
17809 bool deleteit)
17810 {
17811 dns_signing_t *signing;
17812 dns_signing_t *current;
17813 isc_result_t result = ISC_R_SUCCESS;
17814 isc_time_t now;
17815 dns_db_t *db = NULL;
17816
17817 signing = isc_mem_get(zone->mctx, sizeof *signing);
17818 if (signing == NULL)
17819 return (ISC_R_NOMEMORY);
17820
17821 signing->magic = 0;
17822 signing->db = NULL;
17823 signing->dbiterator = NULL;
17824 signing->algorithm = algorithm;
17825 signing->keyid = keyid;
17826 signing->deleteit = deleteit;
17827 signing->done = false;
17828
17829 TIME_NOW(&now);
17830
17831 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17832 if (zone->db != NULL)
17833 dns_db_attach(zone->db, &db);
17834 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17835
17836 if (db == NULL) {
17837 result = ISC_R_NOTFOUND;
17838 goto cleanup;
17839 }
17840
17841 dns_db_attach(db, &signing->db);
17842
17843 for (current = ISC_LIST_HEAD(zone->signing);
17844 current != NULL;
17845 current = ISC_LIST_NEXT(current, link)) {
17846 if (current->db == signing->db &&
17847 current->algorithm == signing->algorithm &&
17848 current->keyid == signing->keyid) {
17849 if (current->deleteit != signing->deleteit)
17850 current->done = true;
17851 else
17852 goto cleanup;
17853 }
17854 }
17855
17856 result = dns_db_createiterator(signing->db, 0,
17857 &signing->dbiterator);
17858
17859 if (result == ISC_R_SUCCESS)
17860 result = dns_dbiterator_first(signing->dbiterator);
17861 if (result == ISC_R_SUCCESS) {
17862 dns_dbiterator_pause(signing->dbiterator);
17863 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
17864 signing = NULL;
17865 if (isc_time_isepoch(&zone->signingtime)) {
17866 zone->signingtime = now;
17867 if (zone->task != NULL)
17868 zone_settimer(zone, &now);
17869 }
17870 }
17871
17872 cleanup:
17873 if (signing != NULL) {
17874 if (signing->db != NULL)
17875 dns_db_detach(&signing->db);
17876 if (signing->dbiterator != NULL)
17877 dns_dbiterator_destroy(&signing->dbiterator);
17878 isc_mem_put(zone->mctx, signing, sizeof *signing);
17879 }
17880 if (db != NULL)
17881 dns_db_detach(&db);
17882 return (result);
17883 }
17884
17885 static void
17886 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
17887 dns_dnsseckey_t *key;
17888 while (!ISC_LIST_EMPTY(*list)) {
17889 key = ISC_LIST_HEAD(*list);
17890 ISC_LIST_UNLINK(*list, key, link);
17891 dns_dnsseckey_destroy(mctx, &key);
17892 }
17893 }
17894
17895 /* Called once; *timep should be set to the current time. */
17896 static isc_result_t
17897 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
17898 isc_result_t result;
17899 isc_stdtime_t now, then = 0, event;
17900 int i;
17901
17902 now = *timep;
17903
17904 for (i = 0; i <= DST_MAX_TIMES; i++) {
17905 result = dst_key_gettime(key, i, &event);
17906 if (result == ISC_R_SUCCESS && event > now &&
17907 (then == 0 || event < then))
17908 then = event;
17909 }
17910
17911 if (then != 0) {
17912 *timep = then;
17913 return (ISC_R_SUCCESS);
17914 }
17915
17916 return (ISC_R_NOTFOUND);
17917 }
17918
17919 static isc_result_t
17920 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
17921 const dns_rdata_t *rdata, bool *flag)
17922 {
17923 dns_rdataset_t rdataset;
17924 dns_dbnode_t *node = NULL;
17925 isc_result_t result;
17926
17927 dns_rdataset_init(&rdataset);
17928 if (rdata->type == dns_rdatatype_nsec3)
17929 CHECK(dns_db_findnsec3node(db, name, false, &node));
17930 else
17931 CHECK(dns_db_findnode(db, name, false, &node));
17932 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
17933 (isc_stdtime_t) 0, &rdataset, NULL);
17934 if (result == ISC_R_NOTFOUND) {
17935 *flag = false;
17936 result = ISC_R_SUCCESS;
17937 goto failure;
17938 }
17939
17940 for (result = dns_rdataset_first(&rdataset);
17941 result == ISC_R_SUCCESS;
17942 result = dns_rdataset_next(&rdataset)) {
17943 dns_rdata_t myrdata = DNS_RDATA_INIT;
17944 dns_rdataset_current(&rdataset, &myrdata);
17945 if (!dns_rdata_compare(&myrdata, rdata))
17946 break;
17947 }
17948 dns_rdataset_disassociate(&rdataset);
17949 if (result == ISC_R_SUCCESS) {
17950 *flag = true;
17951 } else if (result == ISC_R_NOMORE) {
17952 *flag = false;
17953 result = ISC_R_SUCCESS;
17954 }
17955
17956 failure:
17957 if (node != NULL)
17958 dns_db_detachnode(db, &node);
17959 return (result);
17960 }
17961
17962 /*
17963 * Add records to signal the state of signing or of key removal.
17964 */
17965 static isc_result_t
17966 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
17967 dns_dbversion_t *ver, dns_diff_t *diff,
17968 bool sign_all)
17969 {
17970 dns_difftuple_t *tuple, *newtuple = NULL;
17971 dns_rdata_dnskey_t dnskey;
17972 dns_rdata_t rdata = DNS_RDATA_INIT;
17973 bool flag;
17974 isc_region_t r;
17975 isc_result_t result = ISC_R_SUCCESS;
17976 uint16_t keyid;
17977 unsigned char buf[5];
17978 dns_name_t *name = dns_db_origin(db);
17979
17980 for (tuple = ISC_LIST_HEAD(diff->tuples);
17981 tuple != NULL;
17982 tuple = ISC_LIST_NEXT(tuple, link)) {
17983 if (tuple->rdata.type != dns_rdatatype_dnskey)
17984 continue;
17985
17986 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
17987 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17988 if ((dnskey.flags &
17989 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
17990 != DNS_KEYOWNER_ZONE)
17991 continue;
17992
17993 dns_rdata_toregion(&tuple->rdata, &r);
17994
17995 keyid = dst_region_computeid(&r);
17996
17997 buf[0] = dnskey.algorithm;
17998 buf[1] = (keyid & 0xff00) >> 8;
17999 buf[2] = (keyid & 0xff);
18000 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
18001 buf[4] = 0;
18002 rdata.data = buf;
18003 rdata.length = sizeof(buf);
18004 rdata.type = privatetype;
18005 rdata.rdclass = tuple->rdata.rdclass;
18006
18007 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
18008 CHECK(rr_exists(db, ver, name, &rdata, &flag));
18009 if (flag)
18010 continue;
18011 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
18012 name, 0, &rdata, &newtuple));
18013 CHECK(do_one_tuple(&newtuple, db, ver, diff));
18014 INSIST(newtuple == NULL);
18015 }
18016
18017 /*
18018 * Remove any record which says this operation has already
18019 * completed.
18020 */
18021 buf[4] = 1;
18022 CHECK(rr_exists(db, ver, name, &rdata, &flag));
18023 if (flag) {
18024 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
18025 name, 0, &rdata, &newtuple));
18026 CHECK(do_one_tuple(&newtuple, db, ver, diff));
18027 INSIST(newtuple == NULL);
18028 }
18029 }
18030 failure:
18031 return (result);
18032 }
18033
18034 static isc_result_t
18035 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18036 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff)
18037 {
18038 isc_result_t result;
18039 isc_stdtime_t inception, soaexpire, keyexpire;
18040 bool check_ksk, keyset_kskonly;
18041 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
18042 unsigned int nkeys = 0, i;
18043 dns_difftuple_t *tuple;
18044
18045 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
18046 DNS_MAXZONEKEYS, zone_keys, &nkeys);
18047 if (result != ISC_R_SUCCESS) {
18048 dnssec_log(zone, ISC_LOG_ERROR,
18049 "sign_apex:dns__zone_findkeys -> %s",
18050 dns_result_totext(result));
18051 return (result);
18052 }
18053
18054 inception = now - 3600; /* Allow for clock skew. */
18055 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
18056
18057 keyexpire = dns_zone_getkeyvalidityinterval(zone);
18058 if (keyexpire == 0) {
18059 keyexpire = soaexpire - 1;
18060 } else {
18061 keyexpire += now;
18062 }
18063
18064 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
18065 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
18066
18067 /*
18068 * See if dns__zone_updatesigs() will update DNSKEY signature and if
18069 * not cause them to sign so that newly activated keys are used.
18070 */
18071 for (tuple = ISC_LIST_HEAD(diff->tuples);
18072 tuple != NULL;
18073 tuple = ISC_LIST_NEXT(tuple, link))
18074 {
18075 if (tuple->rdata.type == dns_rdatatype_dnskey &&
18076 dns_name_equal(&tuple->name, &zone->origin))
18077 {
18078 break;
18079 }
18080 }
18081
18082 if (tuple == NULL) {
18083 result = del_sigs(zone, db, ver, &zone->origin,
18084 dns_rdatatype_dnskey, zonediff,
18085 zone_keys, nkeys, now, false);
18086 if (result != ISC_R_SUCCESS) {
18087 dnssec_log(zone, ISC_LOG_ERROR,
18088 "sign_apex:del_sigs -> %s",
18089 dns_result_totext(result));
18090 goto failure;
18091 }
18092 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
18093 zonediff->diff, zone_keys, nkeys, zone->mctx,
18094 inception, keyexpire, check_ksk,
18095 keyset_kskonly);
18096 if (result != ISC_R_SUCCESS) {
18097 dnssec_log(zone, ISC_LOG_ERROR,
18098 "sign_apex:add_sigs -> %s",
18099 dns_result_totext(result));
18100 goto failure;
18101 }
18102 }
18103
18104 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
18105 inception, soaexpire, keyexpire, now,
18106 check_ksk, keyset_kskonly, zonediff);
18107
18108 if (result != ISC_R_SUCCESS) {
18109 dnssec_log(zone, ISC_LOG_ERROR,
18110 "sign_apex:dns__zone_updatesigs -> %s",
18111 dns_result_totext(result));
18112 goto failure;
18113 }
18114
18115 failure:
18116 for (i = 0; i < nkeys; i++) {
18117 dst_key_free(&zone_keys[i]);
18118 }
18119 return (result);
18120 }
18121
18122 /*
18123 * Prevent the zone entering a inconsistent state where
18124 * NSEC only DNSKEYs are present with NSEC3 chains.
18125 * See update.c:check_dnssec()
18126 */
18127 static bool
18128 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18129 dns_diff_t *diff)
18130 {
18131 isc_result_t result;
18132 dns_difftuple_t *tuple;
18133 bool nseconly = false, nsec3 = false;
18134 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
18135
18136 /* Scan the tuples for an NSEC-only DNSKEY */
18137 for (tuple = ISC_LIST_HEAD(diff->tuples);
18138 tuple != NULL;
18139 tuple = ISC_LIST_NEXT(tuple, link))
18140 {
18141 uint8_t alg;
18142 if (tuple->rdata.type != dns_rdatatype_dnskey ||
18143 tuple->op != DNS_DIFFOP_ADD)
18144 {
18145 continue;
18146 }
18147
18148 alg = tuple->rdata.data[3];
18149 if (alg == DST_ALG_RSASHA1) {
18150 nseconly = true;
18151 break;
18152 }
18153 }
18154
18155 /* Check existing DB for NSEC-only DNSKEY */
18156 if (!nseconly) {
18157 result = dns_nsec_nseconly(db, ver, &nseconly);
18158 if (result == ISC_R_NOTFOUND) {
18159 result = ISC_R_SUCCESS;
18160 }
18161 CHECK(result);
18162 }
18163
18164 /* Check existing DB for NSEC3 */
18165 if (!nsec3) {
18166 CHECK(dns_nsec3_activex(db, ver, false,
18167 privatetype, &nsec3));
18168 }
18169
18170 /* Refuse to allow NSEC3 with NSEC-only keys */
18171 if (nseconly && nsec3) {
18172 dnssec_log(zone, ISC_LOG_ERROR,
18173 "NSEC only DNSKEYs and NSEC3 chains not allowed");
18174 goto failure;
18175 }
18176
18177 return (true);
18178
18179 failure:
18180 return (false);
18181 }
18182
18183 static isc_result_t
18184 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18185 dns_diff_t *diff)
18186 {
18187 isc_result_t result;
18188 dns_dbnode_t *node = NULL;
18189 dns_rdataset_t rdataset;
18190
18191 dns_rdataset_init(&rdataset);
18192 CHECK(dns_db_getoriginnode(db, &node));
18193
18194 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
18195 dns_rdatatype_none, 0, &rdataset, NULL);
18196 if (dns_rdataset_isassociated(&rdataset))
18197 dns_rdataset_disassociate(&rdataset);
18198 if (result != ISC_R_NOTFOUND)
18199 goto failure;
18200
18201 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
18202
18203 failure:
18204 if (node != NULL)
18205 dns_db_detachnode(db, &node);
18206 return (result);
18207 }
18208
18209 /*
18210 * Given an RRSIG rdataset and an algorithm, determine whether there
18211 * are any signatures using that algorithm.
18212 */
18213 static bool
18214 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
18215 dns_rdata_t rdata = DNS_RDATA_INIT;
18216 dns_rdata_rrsig_t rrsig;
18217 isc_result_t result;
18218
18219 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
18220 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
18221 return (false);
18222 }
18223
18224 for (result = dns_rdataset_first(rdataset);
18225 result == ISC_R_SUCCESS;
18226 result = dns_rdataset_next(rdataset))
18227 {
18228 dns_rdataset_current(rdataset, &rdata);
18229 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
18230 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18231 dns_rdata_reset(&rdata);
18232 if (rrsig.algorithm == alg)
18233 return (true);
18234 }
18235
18236 return (false);
18237 }
18238
18239 static isc_result_t
18240 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18241 dns_diff_t *diff)
18242 {
18243 dns_name_t *origin;
18244 bool build_nsec3;
18245 isc_result_t result;
18246
18247 origin = dns_db_origin(db);
18248 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
18249 &build_nsec3));
18250 if (build_nsec3)
18251 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
18252 false, zone->privatetype, diff));
18253 CHECK(updatesecure(db, ver, origin, zone->minimum, true, diff));
18254
18255 failure:
18256 return (result);
18257 }
18258
18259 static void
18260 dnssec_report(const char *format, ...) {
18261 va_list args;
18262 va_start(args, format);
18263 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
18264 ISC_LOG_INFO, format, args);
18265 va_end(args);
18266 }
18267
18268 static void
18269 zone_rekey(dns_zone_t *zone) {
18270 isc_result_t result;
18271 dns_db_t *db = NULL;
18272 dns_dbnode_t *node = NULL;
18273 dns_dbversion_t *ver = NULL;
18274 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
18275 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
18276 dns_dnsseckey_t *key = NULL;
18277 dns_diff_t diff, _sig_diff;
18278 dns__zonediff_t zonediff;
18279 bool commit = false, newactive = false;
18280 bool newalg = false;
18281 bool fullsign;
18282 dns_ttl_t ttl = 3600;
18283 const char *dir = NULL;
18284 isc_mem_t *mctx = NULL;
18285 isc_stdtime_t now;
18286 isc_time_t timenow;
18287 isc_interval_t ival;
18288 char timebuf[80];
18289
18290 REQUIRE(DNS_ZONE_VALID(zone));
18291
18292 ISC_LIST_INIT(dnskeys);
18293 ISC_LIST_INIT(keys);
18294 ISC_LIST_INIT(rmkeys);
18295 dns_rdataset_init(&soaset);
18296 dns_rdataset_init(&soasigs);
18297 dns_rdataset_init(&keyset);
18298 dns_rdataset_init(&keysigs);
18299 dns_rdataset_init(&cdsset);
18300 dns_rdataset_init(&cdnskeyset);
18301 dir = dns_zone_getkeydirectory(zone);
18302 mctx = zone->mctx;
18303 dns_diff_init(mctx, &diff);
18304 dns_diff_init(mctx, &_sig_diff);
18305 zonediff_init(&zonediff, &_sig_diff);
18306
18307 CHECK(dns_zone_getdb(zone, &db));
18308 CHECK(dns_db_newversion(db, &ver));
18309 CHECK(dns_db_getoriginnode(db, &node));
18310
18311 TIME_NOW(&timenow);
18312 now = isc_time_seconds(&timenow);
18313
18314 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
18315
18316 /* Get the SOA record's TTL */
18317 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
18318 dns_rdatatype_none, 0, &soaset, &soasigs));
18319 ttl = soaset.ttl;
18320 dns_rdataset_disassociate(&soaset);
18321
18322 /* Get the DNSKEY rdataset */
18323 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
18324 dns_rdatatype_none, 0, &keyset, &keysigs);
18325 if (result == ISC_R_SUCCESS) {
18326 ttl = keyset.ttl;
18327 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
18328 mctx, &keyset,
18329 &keysigs, &soasigs,
18330 false, false,
18331 &dnskeys));
18332 } else if (result != ISC_R_NOTFOUND) {
18333 goto failure;
18334 }
18335
18336
18337 /* Get the CDS rdataset */
18338 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
18339 dns_rdatatype_none, 0, &cdsset, NULL);
18340 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset))
18341 dns_rdataset_disassociate(&cdsset);
18342
18343 /* Get the CDNSKEY rdataset */
18344 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
18345 dns_rdatatype_none, 0, &cdnskeyset, NULL);
18346 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset))
18347 {
18348 dns_rdataset_disassociate(&cdnskeyset);
18349 }
18350
18351 /*
18352 * True when called from "rndc sign". Indicates the zone should be
18353 * fully signed now.
18354 */
18355 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
18356
18357 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
18358 &keys);
18359 if (result == ISC_R_SUCCESS) {
18360 bool check_ksk;
18361 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
18362
18363 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
18364 &zone->origin, ttl, &diff,
18365 !check_ksk, mctx,
18366 dnssec_report);
18367 /*
18368 * Keys couldn't be updated for some reason;
18369 * try again later.
18370 */
18371 if (result != ISC_R_SUCCESS) {
18372 dnssec_log(zone, ISC_LOG_ERROR,
18373 "zone_rekey:couldn't update zone keys: %s",
18374 isc_result_totext(result));
18375 goto failure;
18376 }
18377
18378 /*
18379 * Update CDS / CDNSKEY records.
18380 */
18381 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
18382 &cdnskeyset, now, ttl,
18383 &diff, mctx);
18384 if (result != ISC_R_SUCCESS) {
18385 dnssec_log(zone, ISC_LOG_ERROR,
18386 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
18387 isc_result_totext(result));
18388 goto failure;
18389 }
18390
18391 /*
18392 * See if any pre-existing keys have newly become active;
18393 * also, see if any new key is for a new algorithm, as in that
18394 * event, we need to sign the zone fully. (If there's a new
18395 * key, but it's for an already-existing algorithm, then
18396 * the zone signing can be handled incrementally.)
18397 */
18398 for (key = ISC_LIST_HEAD(dnskeys);
18399 key != NULL;
18400 key = ISC_LIST_NEXT(key, link))
18401 {
18402 if (!key->first_sign) {
18403 continue;
18404 }
18405
18406 newactive = true;
18407
18408 if (!dns_rdataset_isassociated(&keysigs)) {
18409 newalg = true;
18410 break;
18411 }
18412
18413 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
18414 /*
18415 * This isn't a new algorithm; clear
18416 * first_sign so we won't sign the
18417 * whole zone with this key later
18418 */
18419 key->first_sign = false;
18420 } else {
18421 newalg = true;
18422 break;
18423 }
18424 }
18425
18426 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
18427 dnskey_sane(zone, db, ver, &diff))
18428 {
18429 CHECK(dns_diff_apply(&diff, db, ver));
18430 CHECK(clean_nsec3param(zone, db, ver, &diff));
18431 CHECK(add_signing_records(db, zone->privatetype,
18432 ver, &diff,
18433 (newalg || fullsign)));
18434 CHECK(update_soa_serial(db, ver, &diff, mctx,
18435 zone->updatemethod));
18436 CHECK(add_chains(zone, db, ver, &diff));
18437 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
18438 CHECK(zone_journal(zone, zonediff.diff, NULL,
18439 "zone_rekey"));
18440 commit = true;
18441 }
18442 }
18443
18444 dns_db_closeversion(db, &ver, true);
18445
18446 if (commit) {
18447 dns_difftuple_t *tuple;
18448
18449 LOCK_ZONE(zone);
18450 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
18451
18452 zone_needdump(zone, DNS_DUMP_DELAY);
18453
18454 zone_settimer(zone, &timenow);
18455
18456 /* Remove any signatures from removed keys. */
18457 if (!ISC_LIST_EMPTY(rmkeys)) {
18458 for (key = ISC_LIST_HEAD(rmkeys);
18459 key != NULL;
18460 key = ISC_LIST_NEXT(key, link))
18461 {
18462 result = zone_signwithkey(zone,
18463 dst_key_alg(key->key),
18464 dst_key_id(key->key),
18465 true);
18466 if (result != ISC_R_SUCCESS) {
18467 dnssec_log(zone, ISC_LOG_ERROR,
18468 "zone_signwithkey failed: %s",
18469 dns_result_totext(result));
18470 }
18471 }
18472 }
18473
18474 if (fullsign) {
18475 /*
18476 * "rndc sign" was called, so we now sign the zone
18477 * with all active keys, whether they're new or not.
18478 */
18479 for (key = ISC_LIST_HEAD(dnskeys);
18480 key != NULL;
18481 key = ISC_LIST_NEXT(key, link))
18482 {
18483 if (!key->force_sign && !key->hint_sign) {
18484 continue;
18485 }
18486
18487 result = zone_signwithkey(zone,
18488 dst_key_alg(key->key),
18489 dst_key_id(key->key),
18490 false);
18491 if (result != ISC_R_SUCCESS) {
18492 dnssec_log(zone, ISC_LOG_ERROR,
18493 "zone_signwithkey failed: %s",
18494 dns_result_totext(result));
18495 }
18496 }
18497 } else if (newalg) {
18498 /*
18499 * We haven't been told to sign fully, but a new
18500 * algorithm was added to the DNSKEY. We sign
18501 * the full zone, but only with newly active
18502 * keys.
18503 */
18504 for (key = ISC_LIST_HEAD(dnskeys);
18505 key != NULL;
18506 key = ISC_LIST_NEXT(key, link))
18507 {
18508 if (!key->first_sign) {
18509 continue;
18510 }
18511
18512 result = zone_signwithkey(zone,
18513 dst_key_alg(key->key),
18514 dst_key_id(key->key),
18515 false);
18516 if (result != ISC_R_SUCCESS) {
18517 dnssec_log(zone, ISC_LOG_ERROR,
18518 "zone_signwithkey failed: %s",
18519 dns_result_totext(result));
18520 }
18521 }
18522 }
18523
18524 /*
18525 * Clear fullsign flag, if it was set, so we don't do
18526 * another full signing next time
18527 */
18528 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
18529
18530 /*
18531 * Cause the zone to add/delete NSEC3 chains for the
18532 * deferred NSEC3PARAM changes.
18533 */
18534 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
18535 tuple != NULL;
18536 tuple = ISC_LIST_NEXT(tuple, link))
18537 {
18538 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
18539 dns_rdata_t rdata = DNS_RDATA_INIT;
18540 dns_rdata_nsec3param_t nsec3param;
18541
18542 if (tuple->rdata.type != zone->privatetype ||
18543 tuple->op != DNS_DIFFOP_ADD)
18544 {
18545 continue;
18546 }
18547
18548 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
18549 buf, sizeof(buf)))
18550 {
18551 continue;
18552 }
18553
18554 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
18555 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18556 if (nsec3param.flags == 0) {
18557 continue;
18558 }
18559
18560 result = zone_addnsec3chain(zone, &nsec3param);
18561 if (result != ISC_R_SUCCESS) {
18562 dnssec_log(zone, ISC_LOG_ERROR,
18563 "zone_addnsec3chain failed: %s",
18564 dns_result_totext(result));
18565 }
18566 }
18567
18568 /*
18569 * Activate any NSEC3 chain updates that may have
18570 * been scheduled before this rekey.
18571 */
18572 if (fullsign || newalg) {
18573 resume_addnsec3chain(zone);
18574 }
18575
18576 /*
18577 * Schedule the next resigning event
18578 */
18579 set_resigntime(zone);
18580 UNLOCK_ZONE(zone);
18581 }
18582
18583 isc_time_settoepoch(&zone->refreshkeytime);
18584
18585 /*
18586 * If we're doing key maintenance, set the key refresh timer to
18587 * the next scheduled key event or to 'dnssec-loadkeys-interval'
18588 * seconds in the future, whichever is sooner.
18589 */
18590 if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
18591 isc_time_t timethen;
18592 isc_stdtime_t then;
18593
18594 LOCK_ZONE(zone);
18595 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
18596 &timethen);
18597 zone->refreshkeytime = timethen;
18598 UNLOCK_ZONE(zone);
18599
18600 for (key = ISC_LIST_HEAD(dnskeys);
18601 key != NULL;
18602 key = ISC_LIST_NEXT(key, link))
18603 {
18604 then = now;
18605 result = next_keyevent(key->key, &then);
18606 if (result != ISC_R_SUCCESS) {
18607 continue;
18608 }
18609
18610 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
18611 LOCK_ZONE(zone);
18612 if (isc_time_compare(&timethen,
18613 &zone->refreshkeytime) < 0)
18614 {
18615 zone->refreshkeytime = timethen;
18616 }
18617 UNLOCK_ZONE(zone);
18618 }
18619
18620 zone_settimer(zone, &timenow);
18621
18622 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
18623 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
18624 }
18625
18626 result = ISC_R_SUCCESS;
18627
18628 failure:
18629 if (result != ISC_R_SUCCESS) {
18630 /*
18631 * Something went wrong; try again in ten minutes or
18632 * after a key refresh interval, whichever is shorter.
18633 */
18634 isc_interval_set(&ival,
18635 ISC_MIN(zone->refreshkeyinterval, 600), 0);
18636 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
18637 }
18638
18639 dns_diff_clear(&diff);
18640 dns_diff_clear(&_sig_diff);
18641
18642 clear_keylist(&dnskeys, mctx);
18643 clear_keylist(&keys, mctx);
18644 clear_keylist(&rmkeys, mctx);
18645
18646 if (ver != NULL) {
18647 dns_db_closeversion(db, &ver, false);
18648 }
18649 if (dns_rdataset_isassociated(&cdsset)) {
18650 dns_rdataset_disassociate(&cdsset);
18651 }
18652 if (dns_rdataset_isassociated(&keyset)) {
18653 dns_rdataset_disassociate(&keyset);
18654 }
18655 if (dns_rdataset_isassociated(&keysigs)) {
18656 dns_rdataset_disassociate(&keysigs);
18657 }
18658 if (dns_rdataset_isassociated(&soasigs)) {
18659 dns_rdataset_disassociate(&soasigs);
18660 }
18661 if (dns_rdataset_isassociated(&cdnskeyset)) {
18662 dns_rdataset_disassociate(&cdnskeyset);
18663 }
18664 if (node != NULL) {
18665 dns_db_detachnode(db, &node);
18666 }
18667 if (db != NULL) {
18668 dns_db_detach(&db);
18669 }
18670
18671 INSIST(ver == NULL);
18672 }
18673
18674 void
18675 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
18676 isc_time_t now;
18677
18678 if (zone->type == dns_zone_master && zone->task != NULL) {
18679 LOCK_ZONE(zone);
18680
18681 if (fullsign)
18682 zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
18683
18684 TIME_NOW(&now);
18685 zone->refreshkeytime = now;
18686 zone_settimer(zone, &now);
18687
18688 UNLOCK_ZONE(zone);
18689 }
18690 }
18691
18692 isc_result_t
18693 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
18694 unsigned int *errors)
18695 {
18696 isc_result_t result;
18697 dns_dbnode_t *node = NULL;
18698
18699 REQUIRE(DNS_ZONE_VALID(zone));
18700 REQUIRE(errors != NULL);
18701
18702 result = dns_db_getoriginnode(db, &node);
18703 if (result != ISC_R_SUCCESS)
18704 return (result);
18705 result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
18706 false);
18707 dns_db_detachnode(db, &node);
18708 return (result);
18709 }
18710
18711 isc_result_t
18712 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
18713 isc_result_t result;
18714 dns_dbnode_t *node = NULL;
18715 dns_rdataset_t dnskey, cds, cdnskey;
18716 unsigned char buffer[DNS_DS_BUFFERSIZE];
18717 unsigned char algorithms[256];
18718 unsigned int i;
18719
18720 REQUIRE(DNS_ZONE_VALID(zone));
18721
18722 result = dns_db_getoriginnode(db, &node);
18723 if (result != ISC_R_SUCCESS)
18724 return (result);
18725
18726 dns_rdataset_init(&cds);
18727 dns_rdataset_init(&dnskey);
18728 dns_rdataset_init(&cdnskey);
18729
18730 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
18731 dns_rdatatype_none, 0, &cds, NULL);
18732 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18733 goto failure;
18734
18735 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
18736 dns_rdatatype_none, 0, &cdnskey, NULL);
18737 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18738 goto failure;
18739
18740 if (!dns_rdataset_isassociated(&cds) &&
18741 !dns_rdataset_isassociated(&cdnskey)) {
18742 result = ISC_R_SUCCESS;
18743 goto failure;
18744 }
18745
18746 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
18747 dns_rdatatype_none, 0, &dnskey, NULL);
18748 if (result == ISC_R_NOTFOUND) {
18749 if (dns_rdataset_isassociated(&cds))
18750 result = DNS_R_BADCDS;
18751 else
18752 result = DNS_R_BADCDNSKEY;
18753 goto failure;
18754 }
18755 if (result != ISC_R_SUCCESS)
18756 goto failure;
18757
18758 /*
18759 * For each DNSSEC algorithm in the CDS RRset there must be
18760 * a matching DNSKEY record.
18761 */
18762 if (dns_rdataset_isassociated(&cds)) {
18763 memset(algorithms, 0, sizeof(algorithms));
18764 for (result = dns_rdataset_first(&cds);
18765 result == ISC_R_SUCCESS;
18766 result = dns_rdataset_next(&cds)) {
18767 dns_rdata_t crdata = DNS_RDATA_INIT;
18768 dns_rdata_cds_t structcds;
18769
18770 dns_rdataset_current(&cds, &crdata);
18771 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
18772 if (algorithms[structcds.algorithm] == 0)
18773 algorithms[structcds.algorithm] = 1;
18774 for (result = dns_rdataset_first(&dnskey);
18775 result == ISC_R_SUCCESS;
18776 result = dns_rdataset_next(&dnskey)) {
18777 dns_rdata_t rdata = DNS_RDATA_INIT;
18778 dns_rdata_t dsrdata = DNS_RDATA_INIT;
18779
18780 dns_rdataset_current(&dnskey, &rdata);
18781 CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
18782 structcds.digest_type,
18783 buffer, &dsrdata));
18784 if (crdata.length == dsrdata.length &&
18785 memcmp(crdata.data, dsrdata.data,
18786 dsrdata.length) == 0) {
18787 algorithms[structcds.algorithm] = 2;
18788 }
18789 }
18790 if (result != ISC_R_NOMORE)
18791 goto failure;
18792 }
18793 for (i = 0; i < sizeof(algorithms); i++) {
18794 if (algorithms[i] == 1) {
18795 result = DNS_R_BADCDNSKEY;
18796 goto failure;
18797 }
18798 }
18799 }
18800
18801 /*
18802 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
18803 * a matching DNSKEY record.
18804 */
18805 if (dns_rdataset_isassociated(&cdnskey)) {
18806 memset(algorithms, 0, sizeof(algorithms));
18807 for (result = dns_rdataset_first(&cdnskey);
18808 result == ISC_R_SUCCESS;
18809 result = dns_rdataset_next(&cdnskey)) {
18810 dns_rdata_t crdata = DNS_RDATA_INIT;
18811 dns_rdata_cdnskey_t structcdnskey;
18812
18813 dns_rdataset_current(&cdnskey, &crdata);
18814 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
18815 NULL));
18816 if (algorithms[structcdnskey.algorithm] == 0)
18817 algorithms[structcdnskey.algorithm] = 1;
18818 for (result = dns_rdataset_first(&dnskey);
18819 result == ISC_R_SUCCESS;
18820 result = dns_rdataset_next(&dnskey)) {
18821 dns_rdata_t rdata = DNS_RDATA_INIT;
18822
18823 dns_rdataset_current(&dnskey, &rdata);
18824 if (crdata.length == rdata.length &&
18825 memcmp(crdata.data, rdata.data,
18826 rdata.length) == 0) {
18827 algorithms[structcdnskey.algorithm] = 2;
18828 }
18829 }
18830 if (result != ISC_R_NOMORE)
18831 goto failure;
18832 }
18833 for (i = 0; i < sizeof(algorithms); i++) {
18834 if (algorithms[i] == 1) {
18835 result = DNS_R_BADCDS;
18836 goto failure;
18837 }
18838 }
18839 }
18840 result = ISC_R_SUCCESS;
18841
18842 failure:
18843 if (dns_rdataset_isassociated(&cds))
18844 dns_rdataset_disassociate(&cds);
18845 if (dns_rdataset_isassociated(&dnskey))
18846 dns_rdataset_disassociate(&dnskey);
18847 if (dns_rdataset_isassociated(&cdnskey))
18848 dns_rdataset_disassociate(&cdnskey);
18849 dns_db_detachnode(db, &node);
18850 return (result);
18851 }
18852
18853 void
18854 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
18855 REQUIRE(DNS_ZONE_VALID(zone));
18856
18857 LOCK_ZONE(zone);
18858 zone->automatic = automatic;
18859 UNLOCK_ZONE(zone);
18860 }
18861
18862 bool
18863 dns_zone_getautomatic(dns_zone_t *zone) {
18864 REQUIRE(DNS_ZONE_VALID(zone));
18865 return (zone->automatic);
18866 }
18867
18868 void
18869 dns_zone_setadded(dns_zone_t *zone, bool added) {
18870 REQUIRE(DNS_ZONE_VALID(zone));
18871
18872 LOCK_ZONE(zone);
18873 zone->added = added;
18874 UNLOCK_ZONE(zone);
18875 }
18876
18877 bool
18878 dns_zone_getadded(dns_zone_t *zone) {
18879 REQUIRE(DNS_ZONE_VALID(zone));
18880 return (zone->added);
18881 }
18882
18883 isc_result_t
18884 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
18885 {
18886 isc_time_t loadtime;
18887 isc_result_t result;
18888 dns_zone_t *secure = NULL;
18889
18890 TIME_NOW(&loadtime);
18891
18892 /*
18893 * Lock hierarchy: zmgr, zone, raw.
18894 */
18895 again:
18896 LOCK_ZONE(zone);
18897 INSIST(zone != zone->raw);
18898 if (inline_secure(zone))
18899 LOCK_ZONE(zone->raw);
18900 else if (inline_raw(zone)) {
18901 secure = zone->secure;
18902 TRYLOCK_ZONE(result, secure);
18903 if (result != ISC_R_SUCCESS) {
18904 UNLOCK_ZONE(zone);
18905 secure = NULL;
18906 isc_thread_yield();
18907 goto again;
18908 }
18909 }
18910 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
18911 if (inline_secure(zone))
18912 UNLOCK_ZONE(zone->raw);
18913 else if (secure != NULL)
18914 UNLOCK_ZONE(secure);
18915 UNLOCK_ZONE(zone);
18916 return result;
18917 }
18918
18919 isc_result_t
18920 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
18921 REQUIRE(DNS_ZONE_VALID(zone));
18922 if (interval == 0)
18923 return (ISC_R_RANGE);
18924 /* Maximum value: 24 hours (3600 minutes) */
18925 if (interval > (24 * 60))
18926 interval = (24 * 60);
18927 /* Multiply by 60 for seconds */
18928 zone->refreshkeyinterval = interval * 60;
18929 return (ISC_R_SUCCESS);
18930 }
18931
18932 void
18933 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
18934 REQUIRE(DNS_ZONE_VALID(zone));
18935 zone->requestixfr = flag;
18936 }
18937
18938 bool
18939 dns_zone_getrequestixfr(dns_zone_t *zone) {
18940 REQUIRE(DNS_ZONE_VALID(zone));
18941 return (zone->requestixfr);
18942 }
18943
18944 void
18945 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
18946 REQUIRE(DNS_ZONE_VALID(zone));
18947 zone->requestexpire = flag;
18948 }
18949
18950 bool
18951 dns_zone_getrequestexpire(dns_zone_t *zone) {
18952 REQUIRE(DNS_ZONE_VALID(zone));
18953 return (zone->requestexpire);
18954 }
18955
18956 void
18957 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
18958 REQUIRE(DNS_ZONE_VALID(zone));
18959 zone->updatemethod = method;
18960 }
18961
18962 dns_updatemethod_t
18963 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
18964 REQUIRE(DNS_ZONE_VALID(zone));
18965 return(zone->updatemethod);
18966 }
18967
18968 /*
18969 * Lock hierarchy: zmgr, zone, raw.
18970 */
18971 isc_result_t
18972 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
18973 isc_result_t result;
18974 dns_zonemgr_t *zmgr;
18975
18976 REQUIRE(DNS_ZONE_VALID(zone));
18977 REQUIRE(zone->zmgr != NULL);
18978 REQUIRE(zone->task != NULL);
18979 REQUIRE(zone->loadtask != NULL);
18980 REQUIRE(zone->raw == NULL);
18981
18982 REQUIRE(DNS_ZONE_VALID(raw));
18983 REQUIRE(raw->zmgr == NULL);
18984 REQUIRE(raw->task == NULL);
18985 REQUIRE(raw->loadtask == NULL);
18986 REQUIRE(raw->secure == NULL);
18987
18988 REQUIRE(zone != raw);
18989
18990 /*
18991 * Lock hierarchy: zmgr, zone, raw.
18992 */
18993 zmgr = zone->zmgr;
18994 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18995 LOCK_ZONE(zone);
18996 LOCK_ZONE(raw);
18997
18998 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
18999 NULL, NULL, zone->task, zone_timer, raw,
19000 &raw->timer);
19001 if (result != ISC_R_SUCCESS)
19002 goto unlock;
19003
19004 /*
19005 * The timer "holds" a iref.
19006 */
19007 raw->irefs++;
19008 INSIST(raw->irefs != 0);
19009
19010
19011 /* dns_zone_attach(raw, &zone->raw); */
19012 isc_refcount_increment(&raw->erefs);
19013 zone->raw = raw;
19014
19015 /* dns_zone_iattach(zone, &raw->secure); */
19016 zone_iattach(zone, &raw->secure);
19017
19018 isc_task_attach(zone->task, &raw->task);
19019 isc_task_attach(zone->loadtask, &raw->loadtask);
19020
19021 ISC_LIST_APPEND(zmgr->zones, raw, link);
19022 raw->zmgr = zmgr;
19023 zmgr->refs++;
19024
19025 unlock:
19026 UNLOCK_ZONE(raw);
19027 UNLOCK_ZONE(zone);
19028 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19029 return (result);
19030 }
19031
19032 void
19033 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
19034 REQUIRE(DNS_ZONE_VALID(zone));
19035 REQUIRE(raw != NULL && *raw == NULL);
19036
19037 LOCK(&zone->lock);
19038 INSIST(zone != zone->raw);
19039 if (zone->raw != NULL)
19040 dns_zone_attach(zone->raw, raw);
19041 UNLOCK(&zone->lock);
19042 }
19043
19044 struct keydone {
19045 isc_event_t event;
19046 bool all;
19047 unsigned char data[5];
19048 };
19049
19050 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
19051
19052 static void
19053 keydone(isc_task_t *task, isc_event_t *event) {
19054 const char *me = "keydone";
19055 bool commit = false;
19056 isc_result_t result;
19057 dns_rdata_t rdata = DNS_RDATA_INIT;
19058 dns_dbversion_t *oldver = NULL, *newver = NULL;
19059 dns_zone_t *zone;
19060 dns_db_t *db = NULL;
19061 dns_dbnode_t *node = NULL;
19062 dns_rdataset_t rdataset;
19063 dns_diff_t diff;
19064 struct keydone *kd = (struct keydone *)event;
19065 dns_update_log_t log = { update_log_cb, NULL };
19066 bool clear_pending = false;
19067
19068 UNUSED(task);
19069
19070 zone = event->ev_arg;
19071 INSIST(DNS_ZONE_VALID(zone));
19072
19073 ENTER;
19074
19075 dns_rdataset_init(&rdataset);
19076 dns_diff_init(zone->mctx, &diff);
19077
19078 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19079 if (zone->db != NULL) {
19080 dns_db_attach(zone->db, &db);
19081 }
19082 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19083 if (db == NULL) {
19084 goto failure;
19085 }
19086
19087 dns_db_currentversion(db, &oldver);
19088 result = dns_db_newversion(db, &newver);
19089 if (result != ISC_R_SUCCESS) {
19090 dnssec_log(zone, ISC_LOG_ERROR,
19091 "keydone:dns_db_newversion -> %s",
19092 dns_result_totext(result));
19093 goto failure;
19094 }
19095
19096 result = dns_db_getoriginnode(db, &node);
19097 if (result != ISC_R_SUCCESS) {
19098 goto failure;
19099 }
19100
19101 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
19102 dns_rdatatype_none, 0, &rdataset, NULL);
19103 if (result == ISC_R_NOTFOUND) {
19104 INSIST(!dns_rdataset_isassociated(&rdataset));
19105 goto failure;
19106 }
19107 if (result != ISC_R_SUCCESS) {
19108 INSIST(!dns_rdataset_isassociated(&rdataset));
19109 goto failure;
19110 }
19111
19112 for (result = dns_rdataset_first(&rdataset);
19113 result == ISC_R_SUCCESS;
19114 result = dns_rdataset_next(&rdataset))
19115 {
19116 bool found = false;
19117
19118 dns_rdataset_current(&rdataset, &rdata);
19119
19120 if (kd->all) {
19121 if (rdata.length == 5 && rdata.data[0] != 0 &&
19122 rdata.data[3] == 0 && rdata.data[4] == 1)
19123 {
19124 found = true;
19125 } else if (rdata.data[0] == 0 &&
19126 (rdata.data[2] & PENDINGFLAGS) != 0)
19127 {
19128 found = true;
19129 clear_pending = true;
19130 }
19131 } else if (rdata.length == 5 &&
19132 memcmp(rdata.data, kd->data, 5) == 0)
19133 {
19134 found = true;
19135 }
19136
19137 if (found) {
19138 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
19139 &zone->origin, rdataset.ttl,
19140 &rdata));
19141 }
19142 dns_rdata_reset(&rdata);
19143 }
19144
19145 if (!ISC_LIST_EMPTY(diff.tuples)) {
19146 /* Write changes to journal file. */
19147 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
19148 zone->updatemethod));
19149
19150 result = dns_update_signatures(&log, zone, db,
19151 oldver, newver, &diff,
19152 zone->sigvalidityinterval);
19153 if (!clear_pending) {
19154 CHECK(result);
19155 }
19156
19157 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
19158 commit = true;
19159
19160 LOCK_ZONE(zone);
19161 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
19162 zone_needdump(zone, 30);
19163 UNLOCK_ZONE(zone);
19164 }
19165
19166 failure:
19167 if (dns_rdataset_isassociated(&rdataset)) {
19168 dns_rdataset_disassociate(&rdataset);
19169 }
19170 if (db != NULL) {
19171 if (node != NULL) {
19172 dns_db_detachnode(db, &node);
19173 }
19174 if (oldver != NULL) {
19175 dns_db_closeversion(db, &oldver, false);
19176 }
19177 if (newver != NULL) {
19178 dns_db_closeversion(db, &newver, commit);
19179 }
19180 dns_db_detach(&db);
19181 }
19182 dns_diff_clear(&diff);
19183 isc_event_free(&event);
19184 dns_zone_idetach(&zone);
19185
19186 INSIST(oldver == NULL);
19187 INSIST(newver == NULL);
19188 }
19189
19190 isc_result_t
19191 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
19192 isc_result_t result = ISC_R_SUCCESS;
19193 isc_event_t *e;
19194 isc_buffer_t b;
19195 dns_zone_t *dummy = NULL;
19196 struct keydone *kd;
19197
19198 REQUIRE(DNS_ZONE_VALID(zone));
19199
19200 LOCK_ZONE(zone);
19201
19202 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
19203 zone, sizeof(struct keydone));
19204 if (e == NULL) {
19205 result = ISC_R_NOMEMORY;
19206 goto failure;
19207 }
19208
19209 kd = (struct keydone *) e;
19210 if (strcasecmp(keystr, "all") == 0) {
19211 kd->all = true;
19212 } else {
19213 isc_textregion_t r;
19214 const char *algstr;
19215 dns_keytag_t keyid;
19216 dns_secalg_t alg;
19217 size_t n;
19218
19219 kd->all = false;
19220
19221 n = sscanf(keystr, "%hu/", &keyid);
19222 if (n == 0U) {
19223 CHECK(ISC_R_FAILURE);
19224 }
19225
19226 algstr = strchr(keystr, '/');
19227 if (algstr != NULL) {
19228 algstr++;
19229 } else {
19230 CHECK(ISC_R_FAILURE);
19231 }
19232
19233 n = sscanf(algstr, "%hhu", &alg);
19234 if (n == 0U) {
19235 DE_CONST(algstr, r.base);
19236 r.length = strlen(algstr);
19237 CHECK(dns_secalg_fromtext(&alg, &r));
19238 }
19239
19240 /* construct a private-type rdata */
19241 isc_buffer_init(&b, kd->data, sizeof(kd->data));
19242 isc_buffer_putuint8(&b, alg);
19243 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
19244 isc_buffer_putuint8(&b, (keyid & 0xff));
19245 isc_buffer_putuint8(&b, 0);
19246 isc_buffer_putuint8(&b, 1);
19247 }
19248
19249 zone_iattach(zone, &dummy);
19250 isc_task_send(zone->task, &e);
19251
19252 failure:
19253 if (e != NULL) {
19254 isc_event_free(&e);
19255 }
19256 UNLOCK_ZONE(zone);
19257 return (result);
19258 }
19259
19260 /*
19261 * Called from the zone task's queue after the relevant event is posted by
19262 * dns_zone_setnsec3param().
19263 *
19264 * Check whether NSEC3 chain addition or removal specified by the private-type
19265 * record passed with the event was already queued (or even fully performed).
19266 * If not, modify the relevant private-type records at the zone apex and call
19267 * resume_addnsec3chain().
19268 */
19269 static void
19270 setnsec3param(isc_task_t *task, isc_event_t *event) {
19271 const char *me = "setnsec3param";
19272 bool commit = false;
19273 isc_result_t result;
19274 dns_dbversion_t *oldver = NULL, *newver = NULL;
19275 dns_zone_t *zone;
19276 dns_db_t *db = NULL;
19277 dns_dbnode_t *node = NULL;
19278 dns_rdataset_t prdataset, nrdataset;
19279 dns_diff_t diff;
19280 struct np3event *npe = (struct np3event *)event;
19281 nsec3param_t *np;
19282 dns_update_log_t log = { update_log_cb, NULL };
19283 dns_rdata_t rdata;
19284 bool nseconly;
19285 bool exists = false;
19286
19287 UNUSED(task);
19288
19289 zone = event->ev_arg;
19290 INSIST(DNS_ZONE_VALID(zone));
19291
19292 ENTER;
19293
19294 np = &npe->params;
19295
19296 dns_rdataset_init(&prdataset);
19297 dns_rdataset_init(&nrdataset);
19298 dns_diff_init(zone->mctx, &diff);
19299
19300 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19301 if (zone->db != NULL) {
19302 dns_db_attach(zone->db, &db);
19303 }
19304 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19305 if (db == NULL) {
19306 goto failure;
19307 }
19308
19309 dns_db_currentversion(db, &oldver);
19310 result = dns_db_newversion(db, &newver);
19311 if (result != ISC_R_SUCCESS) {
19312 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19313 dnssec_log(zone, ISC_LOG_ERROR,
19314 "setnsec3param:dns_db_newversion -> %s",
19315 dns_result_totext(result));
19316 goto failure;
19317 }
19318
19319 CHECK(dns_db_getoriginnode(db, &node));
19320
19321 /*
19322 * Does a private-type record already exist for this chain?
19323 */
19324 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
19325 dns_rdatatype_none, 0, &prdataset, NULL);
19326 if (result == ISC_R_SUCCESS) {
19327 for (result = dns_rdataset_first(&prdataset);
19328 result == ISC_R_SUCCESS;
19329 result = dns_rdataset_next(&prdataset))
19330 {
19331 dns_rdata_init(&rdata);
19332 dns_rdataset_current(&prdataset, &rdata);
19333
19334 if (np->length == rdata.length &&
19335 memcmp(rdata.data, np->data, np->length) == 0)
19336 {
19337 exists = true;
19338 break;
19339 }
19340 }
19341 } else if (result != ISC_R_NOTFOUND) {
19342 INSIST(!dns_rdataset_isassociated(&prdataset));
19343 goto failure;
19344 }
19345
19346 /*
19347 * Does the chain already exist?
19348 */
19349 result = dns_db_findrdataset(db, node, newver,
19350 dns_rdatatype_nsec3param,
19351 dns_rdatatype_none, 0, &nrdataset, NULL);
19352 if (result == ISC_R_SUCCESS) {
19353 for (result = dns_rdataset_first(&nrdataset);
19354 result == ISC_R_SUCCESS;
19355 result = dns_rdataset_next(&nrdataset))
19356 {
19357 dns_rdata_init(&rdata);
19358 dns_rdataset_current(&nrdataset, &rdata);
19359
19360 if (np->length == (rdata.length + 1) &&
19361 memcmp(rdata.data, np->data + 1,
19362 np->length - 1) == 0)
19363 {
19364 exists = true;
19365 break;
19366 }
19367 }
19368 } else if (result != ISC_R_NOTFOUND) {
19369 INSIST(!dns_rdataset_isassociated(&nrdataset));
19370 goto failure;
19371 }
19372
19373
19374 /*
19375 * We need to remove any existing NSEC3 chains if the supplied NSEC3
19376 * parameters are supposed to replace the current ones or if we are
19377 * switching to NSEC.
19378 */
19379 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
19380 CHECK(dns_nsec3param_deletechains(db, newver, zone,
19381 !np->nsec, &diff));
19382 }
19383
19384 if (!exists && np->length != 0) {
19385 /*
19386 * We're creating an NSEC3 chain. Add the private-type record
19387 * passed in the event handler's argument to the zone apex.
19388 *
19389 * If the zone is not currently capable of supporting an NSEC3
19390 * chain (due to the DNSKEY RRset at the zone apex not existing
19391 * or containing at least one key using an NSEC-only
19392 * algorithm), add the INITIAL flag, so these parameters can be
19393 * used later when NSEC3 becomes available.
19394 */
19395 dns_rdata_init(&rdata);
19396
19397 np->data[2] |= DNS_NSEC3FLAG_CREATE;
19398 result = dns_nsec_nseconly(db, newver, &nseconly);
19399 if (result == ISC_R_NOTFOUND || nseconly) {
19400 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
19401 }
19402
19403 rdata.length = np->length;
19404 rdata.data = np->data;
19405 rdata.type = zone->privatetype;
19406 rdata.rdclass = zone->rdclass;
19407 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
19408 &zone->origin, 0, &rdata));
19409 }
19410
19411 /*
19412 * If we changed anything in the zone, write changes to journal file
19413 * and set commit to true so that resume_addnsec3chain() will be
19414 * called below in order to kick off adding/removing relevant NSEC3
19415 * records.
19416 */
19417 if (!ISC_LIST_EMPTY(diff.tuples)) {
19418 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
19419 zone->updatemethod));
19420 result = dns_update_signatures(&log, zone, db,
19421 oldver, newver, &diff,
19422 zone->sigvalidityinterval);
19423 if (result != ISC_R_NOTFOUND) {
19424 CHECK(result);
19425 }
19426 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
19427 commit = true;
19428
19429 LOCK_ZONE(zone);
19430 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
19431 zone_needdump(zone, 30);
19432 UNLOCK_ZONE(zone);
19433 }
19434
19435 failure:
19436 if (dns_rdataset_isassociated(&prdataset)) {
19437 dns_rdataset_disassociate(&prdataset);
19438 }
19439 if (dns_rdataset_isassociated(&nrdataset)) {
19440 dns_rdataset_disassociate(&nrdataset);
19441 }
19442 if (node != NULL) {
19443 dns_db_detachnode(db, &node);
19444 }
19445 if (oldver != NULL) {
19446 dns_db_closeversion(db, &oldver, false);
19447 }
19448 if (newver != NULL) {
19449 dns_db_closeversion(db, &newver, commit);
19450 }
19451 if (db != NULL) {
19452 dns_db_detach(&db);
19453 }
19454 if (commit) {
19455 LOCK_ZONE(zone);
19456 resume_addnsec3chain(zone);
19457 UNLOCK_ZONE(zone);
19458 }
19459 dns_diff_clear(&diff);
19460 isc_event_free(&event);
19461 dns_zone_idetach(&zone);
19462
19463 INSIST(oldver == NULL);
19464 INSIST(newver == NULL);
19465 }
19466
19467 /*
19468 * Called when an "rndc signing -nsec3param ..." command is received.
19469 *
19470 * Allocate and prepare an nsec3param_t structure which holds information about
19471 * the NSEC3 changes requested for the zone:
19472 *
19473 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
19474 * field of the structure to true and the "replace" field to the value
19475 * of the "replace" argument, leaving other fields initialized to zeros, to
19476 * signal that the zone should be signed using NSEC instead of NSEC3,
19477 *
19478 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
19479 * the zone apex, convert it to a private-type record and store the latter
19480 * in the "data" field of the nsec3param_t structure.
19481 *
19482 * Once the nsec3param_t structure is prepared, post an event to the zone's
19483 * task which will cause setnsec3param() to be called with the prepared
19484 * structure passed as an argument.
19485 */
19486 isc_result_t
19487 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
19488 uint16_t iter, uint8_t saltlen,
19489 unsigned char *salt, bool replace)
19490 {
19491 isc_result_t result = ISC_R_SUCCESS;
19492 dns_rdata_nsec3param_t param;
19493 dns_rdata_t nrdata = DNS_RDATA_INIT;
19494 dns_rdata_t prdata = DNS_RDATA_INIT;
19495 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
19496 struct np3event *npe;
19497 nsec3param_t *np;
19498 dns_zone_t *dummy = NULL;
19499 isc_buffer_t b;
19500 isc_event_t *e;
19501
19502 REQUIRE(DNS_ZONE_VALID(zone));
19503 REQUIRE(salt != NULL);
19504
19505 LOCK_ZONE(zone);
19506
19507 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
19508 setnsec3param, zone, sizeof(struct np3event));
19509 if (e == NULL) {
19510 result = ISC_R_NOMEMORY;
19511 goto failure;
19512 }
19513
19514 npe = (struct np3event *) e;
19515 np = &npe->params;
19516
19517 np->replace = replace;
19518 if (hash == 0) {
19519 np->length = 0;
19520 np->nsec = true;
19521 } else {
19522 param.common.rdclass = zone->rdclass;
19523 param.common.rdtype = dns_rdatatype_nsec3param;
19524 ISC_LINK_INIT(¶m.common, link);
19525 param.mctx = NULL;
19526 param.hash = hash;
19527 param.flags = flags;
19528 param.iterations = iter;
19529 param.salt_length = saltlen;
19530 param.salt = salt;
19531 isc_buffer_init(&b, nbuf, sizeof(nbuf));
19532 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
19533 dns_rdatatype_nsec3param,
19534 ¶m, &b));
19535 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
19536 np->data, sizeof(np->data));
19537 np->length = prdata.length;
19538 np->nsec = false;
19539 }
19540
19541 /*
19542 * setnsec3param() will silently return early if the zone does not yet
19543 * have a database. Prevent that by queueing the event up if zone->db
19544 * is NULL. All events queued here are subsequently processed by
19545 * receive_secure_db() if it ever gets called or simply freed by
19546 * zone_free() otherwise.
19547 */
19548 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19549 if (zone->db != NULL) {
19550 zone_iattach(zone, &dummy);
19551 isc_task_send(zone->task, &e);
19552 } else {
19553 ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
19554 e = NULL;
19555 }
19556 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19557
19558 failure:
19559 if (e != NULL) {
19560 isc_event_free(&e);
19561 }
19562 UNLOCK_ZONE(zone);
19563 return (result);
19564 }
19565
19566 isc_result_t
19567 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
19568 REQUIRE(DNS_ZONE_VALID(zone));
19569 REQUIRE(loadtime != NULL);
19570
19571 LOCK_ZONE(zone);
19572 *loadtime = zone->loadtime;
19573 UNLOCK_ZONE(zone);
19574 return (ISC_R_SUCCESS);
19575 }
19576
19577 isc_result_t
19578 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
19579 REQUIRE(DNS_ZONE_VALID(zone));
19580 REQUIRE(expiretime != NULL);
19581
19582 LOCK_ZONE(zone);
19583 *expiretime = zone->expiretime;
19584 UNLOCK_ZONE(zone);
19585 return (ISC_R_SUCCESS);
19586 }
19587
19588 isc_result_t
19589 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
19590 REQUIRE(DNS_ZONE_VALID(zone));
19591 REQUIRE(refreshtime != NULL);
19592
19593 LOCK_ZONE(zone);
19594 *refreshtime = zone->refreshtime;
19595 UNLOCK_ZONE(zone);
19596 return (ISC_R_SUCCESS);
19597 }
19598
19599 isc_result_t
19600 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
19601 REQUIRE(DNS_ZONE_VALID(zone));
19602 REQUIRE(refreshkeytime != NULL);
19603
19604 LOCK_ZONE(zone);
19605 *refreshkeytime = zone->refreshkeytime;
19606 UNLOCK_ZONE(zone);
19607 return (ISC_R_SUCCESS);
19608 }
19609
19610 unsigned int
19611 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
19612 dns_include_t *include;
19613 char **array = NULL;
19614 unsigned int n = 0;
19615
19616 REQUIRE(DNS_ZONE_VALID(zone));
19617 REQUIRE(includesp != NULL && *includesp == NULL);
19618
19619 LOCK_ZONE(zone);
19620 if (zone->nincludes == 0)
19621 goto done;
19622
19623 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
19624 if (array == NULL)
19625 goto done;
19626 for (include = ISC_LIST_HEAD(zone->includes);
19627 include != NULL;
19628 include = ISC_LIST_NEXT(include, link)) {
19629 INSIST(n < zone->nincludes);
19630 array[n++] = isc_mem_strdup(zone->mctx, include->name);
19631 }
19632 INSIST(n == zone->nincludes);
19633 *includesp = array;
19634
19635 done:
19636 UNLOCK_ZONE(zone);
19637 return (n);
19638 }
19639
19640 void
19641 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
19642 REQUIRE(DNS_ZONE_VALID(zone));
19643
19644 zone->statlevel = level;
19645 }
19646
19647 dns_zonestat_level_t
19648 dns_zone_getstatlevel(dns_zone_t *zone) {
19649 REQUIRE(DNS_ZONE_VALID(zone));
19650
19651 return (zone->statlevel);
19652 }
19653
19654 static void
19655 setserial(isc_task_t *task, isc_event_t *event) {
19656 uint32_t oldserial, desired;
19657 const char *me = "setserial";
19658 bool commit = false;
19659 isc_result_t result;
19660 dns_dbversion_t *oldver = NULL, *newver = NULL;
19661 dns_zone_t *zone;
19662 dns_db_t *db = NULL;
19663 dns_diff_t diff;
19664 struct ssevent *sse = (struct ssevent *)event;
19665 dns_update_log_t log = { update_log_cb, NULL };
19666 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
19667
19668 UNUSED(task);
19669
19670 zone = event->ev_arg;
19671 INSIST(DNS_ZONE_VALID(zone));
19672
19673 ENTER;
19674
19675 if (zone->update_disabled)
19676 goto failure;
19677
19678 desired = sse->serial;
19679
19680 dns_diff_init(zone->mctx, &diff);
19681
19682 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19683 if (zone->db != NULL)
19684 dns_db_attach(zone->db, &db);
19685 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19686 if (db == NULL)
19687 goto failure;
19688
19689 dns_db_currentversion(db, &oldver);
19690 result = dns_db_newversion(db, &newver);
19691 if (result != ISC_R_SUCCESS) {
19692 dns_zone_log(zone, ISC_LOG_ERROR,
19693 "setserial:dns_db_newversion -> %s",
19694 dns_result_totext(result));
19695 goto failure;
19696 }
19697
19698 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
19699 DNS_DIFFOP_DEL, &oldtuple));
19700 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
19701 newtuple->op = DNS_DIFFOP_ADD;
19702
19703 oldserial = dns_soa_getserial(&oldtuple->rdata);
19704 if (desired == 0U)
19705 desired = 1;
19706 if (!isc_serial_gt(desired, oldserial)) {
19707 if (desired != oldserial)
19708 dns_zone_log(zone, ISC_LOG_INFO,
19709 "setserial: desired serial (%u) "
19710 "out of range (%u-%u)", desired,
19711 oldserial + 1, (oldserial + 0x7fffffff));
19712 goto failure;
19713 }
19714
19715 dns_soa_setserial(desired, &newtuple->rdata);
19716 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
19717 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
19718 result = dns_update_signatures(&log, zone, db,
19719 oldver, newver, &diff,
19720 zone->sigvalidityinterval);
19721 if (result != ISC_R_NOTFOUND)
19722 CHECK(result);
19723
19724 /* Write changes to journal file. */
19725 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
19726 commit = true;
19727
19728 LOCK_ZONE(zone);
19729 zone_needdump(zone, 30);
19730 UNLOCK_ZONE(zone);
19731
19732 failure:
19733 if (oldtuple != NULL)
19734 dns_difftuple_free(&oldtuple);
19735 if (newtuple != NULL)
19736 dns_difftuple_free(&newtuple);
19737 if (oldver != NULL)
19738 dns_db_closeversion(db, &oldver, false);
19739 if (newver != NULL)
19740 dns_db_closeversion(db, &newver, commit);
19741 if (db != NULL)
19742 dns_db_detach(&db);
19743 dns_diff_clear(&diff);
19744 isc_event_free(&event);
19745 dns_zone_idetach(&zone);
19746
19747 INSIST(oldver == NULL);
19748 INSIST(newver == NULL);
19749 }
19750
19751 isc_result_t
19752 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
19753 isc_result_t result = ISC_R_SUCCESS;
19754 dns_zone_t *dummy = NULL;
19755 isc_event_t *e = NULL;
19756 struct ssevent *sse;
19757
19758 REQUIRE(DNS_ZONE_VALID(zone));
19759
19760 LOCK_ZONE(zone);
19761
19762 if (!inline_secure(zone)) {
19763 if (!dns_zone_isdynamic(zone, true)) {
19764 result = DNS_R_NOTDYNAMIC;
19765 goto failure;
19766 }
19767 }
19768
19769 if (zone->update_disabled) {
19770 result = DNS_R_FROZEN;
19771 goto failure;
19772 }
19773
19774 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
19775 setserial, zone, sizeof(struct ssevent));
19776 if (e == NULL) {
19777 result = ISC_R_NOMEMORY;
19778 goto failure;
19779 }
19780
19781 sse = (struct ssevent *)e;
19782 sse->serial = serial;
19783
19784 zone_iattach(zone, &dummy);
19785 isc_task_send(zone->task, &e);
19786
19787 failure:
19788 if (e != NULL)
19789 isc_event_free(&e);
19790 UNLOCK_ZONE(zone);
19791 return (result);
19792 }
19793
19794 isc_stats_t *
19795 dns_zone_getgluecachestats(dns_zone_t *zone) {
19796 REQUIRE(DNS_ZONE_VALID(zone));
19797
19798 return (zone->gluecachestats);
19799 }
19800
19801 bool
19802 dns_zone_isloaded(const dns_zone_t *zone) {
19803 REQUIRE(DNS_ZONE_VALID(zone));
19804
19805 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
19806 }
19807
19808 isc_result_t
19809 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
19810 dns_dbversion_t *version = NULL;
19811 dns_keytable_t *secroots = NULL;
19812 isc_result_t result;
19813 dns_name_t *origin;
19814
19815 const char me[] = "dns_zone_verifydb";
19816 ENTER;
19817
19818 REQUIRE(DNS_ZONE_VALID(zone));
19819 REQUIRE(db != NULL);
19820
19821 if (dns_zone_gettype(zone) != dns_zone_mirror) {
19822 return (ISC_R_SUCCESS);
19823 }
19824
19825 if (ver == NULL) {
19826 dns_db_currentversion(db, &version);
19827 } else {
19828 version = ver;
19829 }
19830
19831 if (zone->view != NULL) {
19832 result = dns_view_getsecroots(zone->view, &secroots);
19833 if (result != ISC_R_SUCCESS) {
19834 goto done;
19835 }
19836 }
19837
19838 origin = dns_db_origin(db);
19839 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
19840 zone->mctx, true, false);
19841
19842 done:
19843 if (secroots != NULL) {
19844 dns_keytable_detach(&secroots);
19845 }
19846
19847 if (ver == NULL) {
19848 dns_db_closeversion(db, &version, false);
19849 }
19850
19851 if (result != ISC_R_SUCCESS) {
19852 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
19853 isc_result_totext(result));
19854 result = DNS_R_VERIFYFAILURE;
19855 }
19856
19857 return (result);
19858 }
19859