zone.c revision 1.14 1 /* $NetBSD: zone.c,v 1.14 2021/04/29 17:26:11 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 https://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 <errno.h>
17 #include <inttypes.h>
18 #include <stdbool.h>
19
20 #include <isc/atomic.h>
21 #include <isc/file.h>
22 #include <isc/hex.h>
23 #include <isc/md.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/kasp.h>
52 #include <dns/keydata.h>
53 #include <dns/keymgr.h>
54 #include <dns/keytable.h>
55 #include <dns/keyvalues.h>
56 #include <dns/log.h>
57 #include <dns/master.h>
58 #include <dns/masterdump.h>
59 #include <dns/message.h>
60 #include <dns/name.h>
61 #include <dns/nsec.h>
62 #include <dns/nsec3.h>
63 #include <dns/peer.h>
64 #include <dns/private.h>
65 #include <dns/rcode.h>
66 #include <dns/rdata.h>
67 #include <dns/rdataclass.h>
68 #include <dns/rdatalist.h>
69 #include <dns/rdataset.h>
70 #include <dns/rdatasetiter.h>
71 #include <dns/rdatastruct.h>
72 #include <dns/rdatatype.h>
73 #include <dns/request.h>
74 #include <dns/resolver.h>
75 #include <dns/result.h>
76 #include <dns/rriterator.h>
77 #include <dns/soa.h>
78 #include <dns/ssu.h>
79 #include <dns/stats.h>
80 #include <dns/time.h>
81 #include <dns/tsig.h>
82 #include <dns/update.h>
83 #include <dns/xfrin.h>
84 #include <dns/zone.h>
85 #include <dns/zoneverify.h>
86 #include <dns/zt.h>
87
88 #include <dst/dst.h>
89
90 #include "zone_p.h"
91
92 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
93 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
94
95 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
96 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
97
98 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
99 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
100
101 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
102 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
103
104 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
105 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
106
107 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
108 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
109
110 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
111 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
112
113 /*%
114 * Ensure 'a' is at least 'min' but not more than 'max'.
115 */
116 #define RANGE(a, min, max) (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
117
118 #define NSEC3REMOVE(x) (((x)&DNS_NSEC3FLAG_REMOVE) != 0)
119
120 /*%
121 * Key flags
122 */
123 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
124 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
125 #define ID(x) dst_key_id(x)
126 #define ALG(x) dst_key_alg(x)
127
128 /*
129 * Default values.
130 */
131 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
132 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
133 #define MAX_XFER_TIME (2 * 3600) /*%< Documented default is 2 hours */
134 #define RESIGN_DELAY 3600 /*%< 1 hour */
135
136 #ifndef DNS_MAX_EXPIRE
137 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
138 #endif /* ifndef DNS_MAX_EXPIRE */
139
140 #ifndef DNS_DUMP_DELAY
141 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
142 #endif /* ifndef DNS_DUMP_DELAY */
143
144 typedef struct dns_notify dns_notify_t;
145 typedef struct dns_stub dns_stub_t;
146 typedef struct dns_load dns_load_t;
147 typedef struct dns_forward dns_forward_t;
148 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
149 typedef struct dns_io dns_io_t;
150 typedef ISC_LIST(dns_io_t) dns_iolist_t;
151 typedef struct dns_signing dns_signing_t;
152 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
153 typedef struct dns_nsec3chain dns_nsec3chain_t;
154 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
155 typedef struct dns_keyfetch dns_keyfetch_t;
156 typedef struct dns_asyncload dns_asyncload_t;
157 typedef struct dns_include dns_include_t;
158
159 #define DNS_ZONE_CHECKLOCK
160 #ifdef DNS_ZONE_CHECKLOCK
161 #define LOCK_ZONE(z) \
162 do { \
163 LOCK(&(z)->lock); \
164 INSIST(!(z)->locked); \
165 (z)->locked = true; \
166 } while (0)
167 #define UNLOCK_ZONE(z) \
168 do { \
169 (z)->locked = false; \
170 UNLOCK(&(z)->lock); \
171 } while (0)
172 #define LOCKED_ZONE(z) ((z)->locked)
173 #define TRYLOCK_ZONE(result, z) \
174 do { \
175 result = isc_mutex_trylock(&(z)->lock); \
176 if (result == ISC_R_SUCCESS) { \
177 INSIST(!(z)->locked); \
178 (z)->locked = true; \
179 } \
180 } while (0)
181 #else /* ifdef DNS_ZONE_CHECKLOCK */
182 #define LOCK_ZONE(z) LOCK(&(z)->lock)
183 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
184 #define LOCKED_ZONE(z) true
185 #define TRYLOCK_ZONE(result, z) \
186 do { \
187 result = isc_mutex_trylock(&(z)->lock); \
188 } while (0)
189 #endif /* ifdef DNS_ZONE_CHECKLOCK */
190
191 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
192 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
193 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
194 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
195
196 #ifdef ENABLE_AFL
197 extern bool dns_fuzzing_resolver;
198 #endif /* ifdef ENABLE_AFL */
199
200 struct dns_zone {
201 /* Unlocked */
202 unsigned int magic;
203 isc_mutex_t lock;
204 #ifdef DNS_ZONE_CHECKLOCK
205 bool locked;
206 #endif /* ifdef DNS_ZONE_CHECKLOCK */
207 isc_mem_t *mctx;
208 isc_refcount_t erefs;
209
210 isc_rwlock_t dblock;
211 dns_db_t *db; /* Locked by dblock */
212
213 /* Locked */
214 dns_zonemgr_t *zmgr;
215 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
216 isc_timer_t *timer;
217 isc_refcount_t irefs;
218 dns_name_t origin;
219 char *masterfile;
220 ISC_LIST(dns_include_t) includes; /* Include files */
221 ISC_LIST(dns_include_t) newincludes; /* Loading */
222 unsigned int nincludes;
223 dns_masterformat_t masterformat;
224 const dns_master_style_t *masterstyle;
225 char *journal;
226 int32_t journalsize;
227 dns_rdataclass_t rdclass;
228 dns_zonetype_t type;
229 #ifdef __NetBSD__
230 atomic_uint_fast32_t flags;
231 atomic_uint_fast32_t options;
232 #else
233 atomic_uint_fast64_t flags;
234 atomic_uint_fast64_t options;
235 #endif
236 unsigned int db_argc;
237 char **db_argv;
238 isc_time_t expiretime;
239 isc_time_t refreshtime;
240 isc_time_t dumptime;
241 isc_time_t loadtime;
242 isc_time_t notifytime;
243 isc_time_t resigntime;
244 isc_time_t keywarntime;
245 isc_time_t signingtime;
246 isc_time_t nsec3chaintime;
247 isc_time_t refreshkeytime;
248 uint32_t refreshkeyinterval;
249 uint32_t refreshkeycount;
250 uint32_t refresh;
251 uint32_t retry;
252 uint32_t expire;
253 uint32_t minimum;
254 isc_stdtime_t key_expiry;
255 isc_stdtime_t log_key_expired_timer;
256 char *keydirectory;
257
258 uint32_t maxrefresh;
259 uint32_t minrefresh;
260 uint32_t maxretry;
261 uint32_t minretry;
262
263 uint32_t maxrecords;
264
265 isc_sockaddr_t *masters;
266 isc_dscp_t *masterdscps;
267 dns_name_t **masterkeynames;
268 bool *mastersok;
269 unsigned int masterscnt;
270 unsigned int curmaster;
271 isc_sockaddr_t masteraddr;
272 dns_notifytype_t notifytype;
273 isc_sockaddr_t *notify;
274 dns_name_t **notifykeynames;
275 isc_dscp_t *notifydscp;
276 unsigned int notifycnt;
277 isc_sockaddr_t notifyfrom;
278 isc_task_t *task;
279 isc_task_t *loadtask;
280 isc_sockaddr_t notifysrc4;
281 isc_sockaddr_t notifysrc6;
282 isc_sockaddr_t xfrsource4;
283 isc_sockaddr_t xfrsource6;
284 isc_sockaddr_t altxfrsource4;
285 isc_sockaddr_t altxfrsource6;
286 isc_sockaddr_t sourceaddr;
287 isc_dscp_t notifysrc4dscp;
288 isc_dscp_t notifysrc6dscp;
289 isc_dscp_t xfrsource4dscp;
290 isc_dscp_t xfrsource6dscp;
291 isc_dscp_t altxfrsource4dscp;
292 isc_dscp_t altxfrsource6dscp;
293 dns_xfrin_ctx_t *xfr; /* task locked */
294 dns_tsigkey_t *tsigkey; /* key used for xfr */
295 /* Access Control Lists */
296 dns_acl_t *update_acl;
297 dns_acl_t *forward_acl;
298 dns_acl_t *notify_acl;
299 dns_acl_t *query_acl;
300 dns_acl_t *queryon_acl;
301 dns_acl_t *xfr_acl;
302 bool update_disabled;
303 bool zero_no_soa_ttl;
304 dns_severity_t check_names;
305 ISC_LIST(dns_notify_t) notifies;
306 dns_request_t *request;
307 dns_loadctx_t *lctx;
308 dns_io_t *readio;
309 dns_dumpctx_t *dctx;
310 dns_io_t *writeio;
311 uint32_t maxxfrin;
312 uint32_t maxxfrout;
313 uint32_t idlein;
314 uint32_t idleout;
315 isc_event_t ctlevent;
316 dns_ssutable_t *ssutable;
317 uint32_t sigvalidityinterval;
318 uint32_t keyvalidityinterval;
319 uint32_t sigresigninginterval;
320 dns_view_t *view;
321 dns_view_t *prev_view;
322 dns_kasp_t *kasp;
323 dns_checkmxfunc_t checkmx;
324 dns_checksrvfunc_t checksrv;
325 dns_checknsfunc_t checkns;
326 /*%
327 * Zones in certain states such as "waiting for zone transfer"
328 * or "zone transfer in progress" are kept on per-state linked lists
329 * in the zone manager using the 'statelink' field. The 'statelist'
330 * field points at the list the zone is currently on. It the zone
331 * is not on any such list, statelist is NULL.
332 */
333 ISC_LINK(dns_zone_t) statelink;
334 dns_zonelist_t *statelist;
335 /*%
336 * Statistics counters about zone management.
337 */
338 isc_stats_t *stats;
339 /*%
340 * Optional per-zone statistics counters. Counted outside of this
341 * module.
342 */
343 dns_zonestat_level_t statlevel;
344 bool requeststats_on;
345 isc_stats_t *requeststats;
346 dns_stats_t *rcvquerystats;
347 dns_stats_t *dnssecsignstats;
348 uint32_t notifydelay;
349 dns_isselffunc_t isself;
350 void *isselfarg;
351
352 char *strnamerd;
353 char *strname;
354 char *strrdclass;
355 char *strviewname;
356
357 /*%
358 * Serial number for deferred journal compaction.
359 */
360 uint32_t compact_serial;
361 /*%
362 * Keys that are signing the zone for the first time.
363 */
364 dns_signinglist_t signing;
365 dns_nsec3chainlist_t nsec3chain;
366 /*%
367 * List of outstanding NSEC3PARAM change requests.
368 */
369 isc_eventlist_t setnsec3param_queue;
370 /*%
371 * Signing / re-signing quantum stopping parameters.
372 */
373 uint32_t signatures;
374 uint32_t nodes;
375 dns_rdatatype_t privatetype;
376
377 /*%
378 * Autosigning/key-maintenance options
379 */
380 #ifdef __NetBSD__
381 atomic_uint_fast32_t keyopts;
382 #else
383 atomic_uint_fast64_t keyopts;
384 #endif
385
386 /*%
387 * True if added by "rndc addzone"
388 */
389 bool added;
390
391 /*%
392 * True if added by automatically by named.
393 */
394 bool automatic;
395
396 /*%
397 * response policy data to be relayed to the database
398 */
399 dns_rpz_zones_t *rpzs;
400 dns_rpz_num_t rpz_num;
401
402 /*%
403 * catalog zone data
404 */
405 dns_catz_zones_t *catzs;
406
407 /*%
408 * parent catalog zone
409 */
410 dns_catz_zone_t *parentcatz;
411
412 /*%
413 * Serial number update method.
414 */
415 dns_updatemethod_t updatemethod;
416
417 /*%
418 * whether ixfr is requested
419 */
420 bool requestixfr;
421 uint32_t ixfr_ratio;
422
423 /*%
424 * whether EDNS EXPIRE is requested
425 */
426 bool requestexpire;
427
428 /*%
429 * Outstanding forwarded UPDATE requests.
430 */
431 dns_forwardlist_t forwards;
432
433 dns_zone_t *raw;
434 dns_zone_t *secure;
435
436 bool sourceserialset;
437 uint32_t sourceserial;
438
439 /*%
440 * maximum zone ttl
441 */
442 dns_ttl_t maxttl;
443
444 /*
445 * Inline zone signing state.
446 */
447 dns_diff_t rss_diff;
448 isc_eventlist_t rss_events;
449 isc_eventlist_t rss_post;
450 dns_dbversion_t *rss_newver;
451 dns_dbversion_t *rss_oldver;
452 dns_db_t *rss_db;
453 dns_zone_t *rss_raw;
454 isc_event_t *rss_event;
455 dns_update_state_t *rss_state;
456
457 isc_stats_t *gluecachestats;
458 };
459
460 #define zonediff_init(z, d) \
461 do { \
462 dns__zonediff_t *_z = (z); \
463 (_z)->diff = (d); \
464 (_z)->offline = false; \
465 } while (0)
466
467 #define DNS_ZONE_FLAG(z, f) ((atomic_load_relaxed(&(z)->flags) & (f)) != 0)
468 #define DNS_ZONE_SETFLAG(z, f) atomic_fetch_or(&(z)->flags, (f))
469 #define DNS_ZONE_CLRFLAG(z, f) atomic_fetch_and(&(z)->flags, ~(f))
470 typedef enum {
471 DNS_ZONEFLG_REFRESH = 0x00000001U, /*%< refresh check in progress */
472 DNS_ZONEFLG_NEEDDUMP = 0x00000002U, /*%< zone need consolidation */
473 DNS_ZONEFLG_USEVC = 0x00000004U, /*%< use tcp for refresh query */
474 DNS_ZONEFLG_DUMPING = 0x00000008U, /*%< a dump is in progress */
475 DNS_ZONEFLG_HASINCLUDE = 0x00000010U, /*%< $INCLUDE in zone file */
476 DNS_ZONEFLG_LOADED = 0x00000020U, /*%< database has loaded */
477 DNS_ZONEFLG_EXITING = 0x00000040U, /*%< zone is being destroyed */
478 DNS_ZONEFLG_EXPIRED = 0x00000080U, /*%< zone has expired */
479 DNS_ZONEFLG_NEEDREFRESH = 0x00000100U, /*%< refresh check needed */
480 DNS_ZONEFLG_UPTODATE = 0x00000200U, /*%< zone contents are
481 * up-to-date */
482 DNS_ZONEFLG_NEEDNOTIFY = 0x00000400U, /*%< need to send out notify
483 * messages */
484 DNS_ZONEFLG_FIXJOURNAL = 0x00000800U, /*%< journal file had
485 * recoverable error,
486 * needs rewriting */
487 DNS_ZONEFLG_NOMASTERS = 0x00001000U, /*%< an attempt to refresh a
488 * zone with no primaries
489 * occurred */
490 DNS_ZONEFLG_LOADING = 0x00002000U, /*%< load from disk in progress*/
491 DNS_ZONEFLG_HAVETIMERS = 0x00004000U, /*%< timer values have been set
492 * from SOA (if not set, we
493 * are still using
494 * default timer values) */
495 DNS_ZONEFLG_FORCEXFER = 0x00008000U, /*%< Force a zone xfer */
496 DNS_ZONEFLG_NOREFRESH = 0x00010000U,
497 DNS_ZONEFLG_DIALNOTIFY = 0x00020000U,
498 DNS_ZONEFLG_DIALREFRESH = 0x00040000U,
499 DNS_ZONEFLG_SHUTDOWN = 0x00080000U,
500 DNS_ZONEFLG_NOIXFR = 0x00100000U, /*%< IXFR failed, force AXFR */
501 DNS_ZONEFLG_FLUSH = 0x00200000U,
502 DNS_ZONEFLG_NOEDNS = 0x00400000U,
503 DNS_ZONEFLG_USEALTXFRSRC = 0x00800000U,
504 DNS_ZONEFLG_SOABEFOREAXFR = 0x01000000U,
505 DNS_ZONEFLG_NEEDCOMPACT = 0x02000000U,
506 DNS_ZONEFLG_REFRESHING = 0x04000000U, /*%< Refreshing keydata */
507 DNS_ZONEFLG_THAW = 0x08000000U,
508 DNS_ZONEFLG_LOADPENDING = 0x10000000U, /*%< Loading scheduled */
509 DNS_ZONEFLG_NODELAY = 0x20000000U,
510 DNS_ZONEFLG_SENDSECURE = 0x40000000U,
511 DNS_ZONEFLG_NEEDSTARTUPNOTIFY = 0x80000000U, /*%< need to send out
512 * notify due to the zone
513 * just being loaded for
514 * the first time. */
515 #ifndef __NetBSD__
516 /*
517 * DO NOT add any new zone flags here until all platforms
518 * support 64-bit enum values. Currently they fail on
519 * Windows.
520 */
521 DNS_ZONEFLG___MAX = UINT64_MAX, /* trick to make the ENUM 64-bit wide */
522 #endif
523 } dns_zoneflg_t;
524
525 #define DNS_ZONE_OPTION(z, o) ((atomic_load_relaxed(&(z)->options) & (o)) != 0)
526 #define DNS_ZONE_SETOPTION(z, o) atomic_fetch_or(&(z)->options, (o))
527 #define DNS_ZONE_CLROPTION(z, o) atomic_fetch_and(&(z)->options, ~(o))
528
529 #define DNS_ZONEKEY_OPTION(z, o) \
530 ((atomic_load_relaxed(&(z)->keyopts) & (o)) != 0)
531 #define DNS_ZONEKEY_SETOPTION(z, o) atomic_fetch_or(&(z)->keyopts, (o))
532 #define DNS_ZONEKEY_CLROPTION(z, o) atomic_fetch_and(&(z)->keyopts, ~(o))
533
534 /* Flags for zone_load() */
535 typedef enum {
536 DNS_ZONELOADFLAG_NOSTAT = 0x00000001U, /* Do not stat() master files */
537 DNS_ZONELOADFLAG_THAW = 0x00000002U, /* Thaw the zone on successful
538 * load. */
539 } dns_zoneloadflag_t;
540
541 #define UNREACH_CACHE_SIZE 10U
542 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
543
544 #define CHECK(op) \
545 do { \
546 result = (op); \
547 if (result != ISC_R_SUCCESS) \
548 goto failure; \
549 } while (0)
550
551 struct dns_unreachable {
552 isc_sockaddr_t remote;
553 isc_sockaddr_t local;
554 atomic_uint_fast32_t expire;
555 atomic_uint_fast32_t last;
556 uint32_t count;
557 };
558
559 struct dns_zonemgr {
560 unsigned int magic;
561 isc_mem_t *mctx;
562 isc_refcount_t refs;
563 isc_taskmgr_t *taskmgr;
564 isc_timermgr_t *timermgr;
565 isc_socketmgr_t *socketmgr;
566 isc_taskpool_t *zonetasks;
567 isc_taskpool_t *loadtasks;
568 isc_task_t *task;
569 isc_pool_t *mctxpool;
570 isc_ratelimiter_t *notifyrl;
571 isc_ratelimiter_t *refreshrl;
572 isc_ratelimiter_t *startupnotifyrl;
573 isc_ratelimiter_t *startuprefreshrl;
574 isc_rwlock_t rwlock;
575 isc_mutex_t iolock;
576 isc_rwlock_t urlock;
577
578 /* Locked by rwlock. */
579 dns_zonelist_t zones;
580 dns_zonelist_t waiting_for_xfrin;
581 dns_zonelist_t xfrin_in_progress;
582
583 /* Configuration data. */
584 uint32_t transfersin;
585 uint32_t transfersperns;
586 unsigned int notifyrate;
587 unsigned int startupnotifyrate;
588 unsigned int serialqueryrate;
589 unsigned int startupserialqueryrate;
590
591 /* Locked by iolock */
592 uint32_t iolimit;
593 uint32_t ioactive;
594 dns_iolist_t high;
595 dns_iolist_t low;
596
597 /* Locked by urlock. */
598 /* LRU cache */
599 struct dns_unreachable unreachable[UNREACH_CACHE_SIZE];
600 };
601
602 /*%
603 * Hold notify state.
604 */
605 struct dns_notify {
606 unsigned int magic;
607 unsigned int flags;
608 isc_mem_t *mctx;
609 dns_zone_t *zone;
610 dns_adbfind_t *find;
611 dns_request_t *request;
612 dns_name_t ns;
613 isc_sockaddr_t dst;
614 dns_tsigkey_t *key;
615 isc_dscp_t dscp;
616 ISC_LINK(dns_notify_t) link;
617 isc_event_t *event;
618 };
619
620 #define DNS_NOTIFY_NOSOA 0x0001U
621 #define DNS_NOTIFY_STARTUP 0x0002U
622
623 /*%
624 * dns_stub holds state while performing a 'stub' transfer.
625 * 'db' is the zone's 'db' or a new one if this is the initial
626 * transfer.
627 */
628
629 struct dns_stub {
630 unsigned int magic;
631 isc_mem_t *mctx;
632 dns_zone_t *zone;
633 dns_db_t *db;
634 dns_dbversion_t *version;
635 atomic_uint_fast32_t pending_requests;
636 };
637
638 /*%
639 * Hold load state.
640 */
641 struct dns_load {
642 unsigned int magic;
643 isc_mem_t *mctx;
644 dns_zone_t *zone;
645 dns_db_t *db;
646 isc_time_t loadtime;
647 dns_rdatacallbacks_t callbacks;
648 };
649
650 /*%
651 * Hold forward state.
652 */
653 struct dns_forward {
654 unsigned int magic;
655 isc_mem_t *mctx;
656 dns_zone_t *zone;
657 isc_buffer_t *msgbuf;
658 dns_request_t *request;
659 uint32_t which;
660 isc_sockaddr_t addr;
661 dns_updatecallback_t callback;
662 void *callback_arg;
663 unsigned int options;
664 ISC_LINK(dns_forward_t) link;
665 };
666
667 /*%
668 * Hold IO request state.
669 */
670 struct dns_io {
671 unsigned int magic;
672 dns_zonemgr_t *zmgr;
673 bool high;
674 isc_task_t *task;
675 ISC_LINK(dns_io_t) link;
676 isc_event_t *event;
677 };
678
679 /*%
680 * Hold state for when we are signing a zone with a new
681 * DNSKEY as result of an update.
682 */
683 struct dns_signing {
684 unsigned int magic;
685 dns_db_t *db;
686 dns_dbiterator_t *dbiterator;
687 dns_secalg_t algorithm;
688 uint16_t keyid;
689 bool deleteit;
690 bool done;
691 ISC_LINK(dns_signing_t) link;
692 };
693
694 struct dns_nsec3chain {
695 unsigned int magic;
696 dns_db_t *db;
697 dns_dbiterator_t *dbiterator;
698 dns_rdata_nsec3param_t nsec3param;
699 unsigned char salt[255];
700 bool done;
701 bool seen_nsec;
702 bool delete_nsec;
703 bool save_delete_nsec;
704 ISC_LINK(dns_nsec3chain_t) link;
705 };
706 /*%<
707 * 'dbiterator' contains a iterator for the database. If we are creating
708 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
709 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
710 * iterated.
711 *
712 * 'nsec3param' contains the parameters of the NSEC3 chain being created
713 * or removed.
714 *
715 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
716 *
717 * 'seen_nsec' will be set to true if, while iterating the zone to create a
718 * NSEC3 chain, a NSEC record is seen.
719 *
720 * 'delete_nsec' will be set to true if, at the completion of the creation
721 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
722 * are in the process of deleting the NSEC chain.
723 *
724 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
725 * so it can be recovered in the event of a error.
726 */
727
728 struct dns_keyfetch {
729 dns_fixedname_t name;
730 dns_rdataset_t keydataset;
731 dns_rdataset_t dnskeyset;
732 dns_rdataset_t dnskeysigset;
733 dns_zone_t *zone;
734 dns_db_t *db;
735 dns_fetch_t *fetch;
736 };
737
738 /*%
739 * Hold state for an asynchronous load
740 */
741 struct dns_asyncload {
742 dns_zone_t *zone;
743 unsigned int flags;
744 dns_zt_zoneloaded_t loaded;
745 void *loaded_arg;
746 };
747
748 /*%
749 * Reference to an include file encountered during loading
750 */
751 struct dns_include {
752 char *name;
753 isc_time_t filetime;
754 ISC_LINK(dns_include_t) link;
755 };
756
757 /*
758 * These can be overridden by the -T mkeytimers option on the command
759 * line, so that we can test with shorter periods than specified in
760 * RFC 5011.
761 */
762 #define HOUR 3600
763 #define DAY (24 * HOUR)
764 #define MONTH (30 * DAY)
765 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
766 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
767 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
768
769 #define SEND_BUFFER_SIZE 2048
770
771 static void
772 zone_settimer(dns_zone_t *, isc_time_t *);
773 static void
774 cancel_refresh(dns_zone_t *);
775 static void
776 zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg,
777 ...) ISC_FORMAT_PRINTF(4, 5);
778 static void
779 notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
780 ISC_FORMAT_PRINTF(3, 4);
781 static void
782 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
783 ISC_FORMAT_PRINTF(3, 4);
784 static void
785 queue_xfrin(dns_zone_t *zone);
786 static isc_result_t
787 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
788 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
789 dns_rdata_t *rdata);
790 static void
791 zone_unload(dns_zone_t *zone);
792 static void
793 zone_expire(dns_zone_t *zone);
794 static void
795 zone_iattach(dns_zone_t *source, dns_zone_t **target);
796 static void
797 zone_idetach(dns_zone_t **zonep);
798 static isc_result_t
799 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump);
800 static inline void
801 zone_attachdb(dns_zone_t *zone, dns_db_t *db);
802 static inline void
803 zone_detachdb(dns_zone_t *zone);
804 static isc_result_t
805 default_journal(dns_zone_t *zone);
806 static void
807 zone_xfrdone(dns_zone_t *zone, isc_result_t result);
808 static isc_result_t
809 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
810 isc_result_t result);
811 static void
812 zone_needdump(dns_zone_t *zone, unsigned int delay);
813 static void
814 zone_shutdown(isc_task_t *, isc_event_t *);
815 static void
816 zone_loaddone(void *arg, isc_result_t result);
817 static isc_result_t
818 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);
819 static void
820 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
821 static void
822 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
823 static void
824 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
825 static void
826 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
827 static isc_result_t
828 zone_send_secureserial(dns_zone_t *zone, uint32_t serial);
829 static void
830 refresh_callback(isc_task_t *, isc_event_t *);
831 static void
832 stub_callback(isc_task_t *, isc_event_t *);
833 static void
834 queue_soa_query(dns_zone_t *zone);
835 static void
836 soa_query(isc_task_t *, isc_event_t *);
837 static void
838 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);
839 static int
840 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);
841 static void
842 notify_cancel(dns_zone_t *zone);
843 static void
844 notify_find_address(dns_notify_t *notify);
845 static void
846 notify_send(dns_notify_t *notify);
847 static isc_result_t
848 notify_createmessage(dns_zone_t *zone, unsigned int flags,
849 dns_message_t **messagep);
850 static void
851 notify_done(isc_task_t *task, isc_event_t *event);
852 static void
853 notify_send_toaddr(isc_task_t *task, isc_event_t *event);
854 static isc_result_t
855 zone_dump(dns_zone_t *, bool);
856 static void
857 got_transfer_quota(isc_task_t *task, isc_event_t *event);
858 static isc_result_t
859 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);
860 static void
861 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
862 static void
863 zonemgr_free(dns_zonemgr_t *zmgr);
864 static isc_result_t
865 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
866 isc_taskaction_t action, void *arg, dns_io_t **iop);
867 static void
868 zonemgr_putio(dns_io_t **iop);
869 static void
870 zonemgr_cancelio(dns_io_t *io);
871 static void
872 rss_post(dns_zone_t *, isc_event_t *);
873
874 static isc_result_t
875 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
876 unsigned int *soacount, uint32_t *serial, uint32_t *refresh,
877 uint32_t *retry, uint32_t *expire, uint32_t *minimum,
878 unsigned int *errors);
879
880 static void
881 zone_freedbargs(dns_zone_t *zone);
882 static void
883 forward_callback(isc_task_t *task, isc_event_t *event);
884 static void
885 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);
886 static void
887 zone_maintenance(dns_zone_t *zone);
888 static void
889 zone_notify(dns_zone_t *zone, isc_time_t *now);
890 static void
891 dump_done(void *arg, isc_result_t result);
892 static isc_result_t
893 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
894 bool deleteit);
895 static isc_result_t
896 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
897 dns_name_t *name, dns_diff_t *diff);
898 static void
899 zone_rekey(dns_zone_t *zone);
900 static isc_result_t
901 zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
902 static void
903 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value);
904 static void
905 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial);
906 static isc_result_t
907 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
908 bool *fixjournal);
909
910 #define ENTER zone_debuglog(zone, me, 1, "enter")
911
912 static const unsigned int dbargc_default = 1;
913 static const char *dbargv_default[] = { "rbt" };
914
915 #define DNS_ZONE_JITTER_ADD(a, b, c) \
916 do { \
917 isc_interval_t _i; \
918 uint32_t _j; \
919 _j = (b)-isc_random_uniform((b) / 4); \
920 isc_interval_set(&_i, _j, 0); \
921 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
922 dns_zone_log(zone, ISC_LOG_WARNING, \
923 "epoch approaching: upgrade required: " \
924 "now + %s failed", \
925 #b); \
926 isc_interval_set(&_i, _j / 2, 0); \
927 (void)isc_time_add((a), &_i, (c)); \
928 } \
929 } while (0)
930
931 #define DNS_ZONE_TIME_ADD(a, b, c) \
932 do { \
933 isc_interval_t _i; \
934 isc_interval_set(&_i, (b), 0); \
935 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
936 dns_zone_log(zone, ISC_LOG_WARNING, \
937 "epoch approaching: upgrade required: " \
938 "now + %s failed", \
939 #b); \
940 isc_interval_set(&_i, (b) / 2, 0); \
941 (void)isc_time_add((a), &_i, (c)); \
942 } \
943 } while (0)
944
945 typedef struct nsec3param nsec3param_t;
946 struct nsec3param {
947 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
948 unsigned int length;
949 bool nsec;
950 bool replace;
951 ISC_LINK(nsec3param_t) link;
952 };
953 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
954 struct np3event {
955 isc_event_t event;
956 nsec3param_t params;
957 };
958
959 struct ssevent {
960 isc_event_t event;
961 uint32_t serial;
962 };
963
964 struct stub_cb_args {
965 dns_stub_t *stub;
966 dns_tsigkey_t *tsig_key;
967 isc_dscp_t dscp;
968 uint16_t udpsize;
969 int timeout;
970 bool reqnsid;
971 };
972
973 struct stub_glue_request {
974 dns_request_t *request;
975 dns_name_t name;
976 struct stub_cb_args *args;
977 bool ipv4;
978 };
979
980 /*%
981 * Increment resolver-related statistics counters. Zone must be locked.
982 */
983 static inline void
984 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
985 if (zone->stats != NULL) {
986 isc_stats_increment(zone->stats, counter);
987 }
988 }
989
990 /***
991 *** Public functions.
992 ***/
993
994 isc_result_t
995 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
996 isc_result_t result;
997 dns_zone_t *zone;
998 isc_time_t now;
999
1000 REQUIRE(zonep != NULL && *zonep == NULL);
1001 REQUIRE(mctx != NULL);
1002
1003 TIME_NOW(&now);
1004 zone = isc_mem_get(mctx, sizeof(*zone));
1005
1006 zone->mctx = NULL;
1007 isc_mem_attach(mctx, &zone->mctx);
1008 isc_mutex_init(&zone->lock);
1009 ZONEDB_INITLOCK(&zone->dblock);
1010 /* XXX MPA check that all elements are initialised */
1011 #ifdef DNS_ZONE_CHECKLOCK
1012 zone->locked = false;
1013 #endif /* ifdef DNS_ZONE_CHECKLOCK */
1014 zone->db = NULL;
1015 zone->zmgr = NULL;
1016 ISC_LINK_INIT(zone, link);
1017 isc_refcount_init(&zone->erefs, 1);
1018 isc_refcount_init(&zone->irefs, 0);
1019 dns_name_init(&zone->origin, NULL);
1020 zone->strnamerd = NULL;
1021 zone->strname = NULL;
1022 zone->strrdclass = NULL;
1023 zone->strviewname = NULL;
1024 zone->masterfile = NULL;
1025 ISC_LIST_INIT(zone->includes);
1026 ISC_LIST_INIT(zone->newincludes);
1027 zone->nincludes = 0;
1028 zone->masterformat = dns_masterformat_none;
1029 zone->masterstyle = NULL;
1030 zone->keydirectory = NULL;
1031 zone->journalsize = -1;
1032 zone->journal = NULL;
1033 zone->rdclass = dns_rdataclass_none;
1034 zone->type = dns_zone_none;
1035 atomic_init(&zone->flags, 0);
1036 atomic_init(&zone->options, 0);
1037 atomic_init(&zone->keyopts, 0);
1038 zone->db_argc = 0;
1039 zone->db_argv = NULL;
1040 isc_time_settoepoch(&zone->expiretime);
1041 isc_time_settoepoch(&zone->refreshtime);
1042 isc_time_settoepoch(&zone->dumptime);
1043 isc_time_settoepoch(&zone->loadtime);
1044 zone->notifytime = now;
1045 isc_time_settoepoch(&zone->resigntime);
1046 isc_time_settoepoch(&zone->keywarntime);
1047 isc_time_settoepoch(&zone->signingtime);
1048 isc_time_settoepoch(&zone->nsec3chaintime);
1049 isc_time_settoepoch(&zone->refreshkeytime);
1050 zone->refreshkeyinterval = 0;
1051 zone->refreshkeycount = 0;
1052 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
1053 zone->retry = DNS_ZONE_DEFAULTRETRY;
1054 zone->expire = 0;
1055 zone->minimum = 0;
1056 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
1057 zone->minrefresh = DNS_ZONE_MINREFRESH;
1058 zone->maxretry = DNS_ZONE_MAXRETRY;
1059 zone->minretry = DNS_ZONE_MINRETRY;
1060 zone->masters = NULL;
1061 zone->masterdscps = NULL;
1062 zone->masterkeynames = NULL;
1063 zone->mastersok = NULL;
1064 zone->masterscnt = 0;
1065 zone->curmaster = 0;
1066 zone->maxttl = 0;
1067 zone->notify = NULL;
1068 zone->notifykeynames = NULL;
1069 zone->notifydscp = NULL;
1070 zone->notifytype = dns_notifytype_yes;
1071 zone->notifycnt = 0;
1072 zone->task = NULL;
1073 zone->loadtask = NULL;
1074 zone->update_acl = NULL;
1075 zone->forward_acl = NULL;
1076 zone->notify_acl = NULL;
1077 zone->query_acl = NULL;
1078 zone->queryon_acl = NULL;
1079 zone->xfr_acl = NULL;
1080 zone->update_disabled = false;
1081 zone->zero_no_soa_ttl = true;
1082 zone->check_names = dns_severity_ignore;
1083 zone->request = NULL;
1084 zone->lctx = NULL;
1085 zone->readio = NULL;
1086 zone->dctx = NULL;
1087 zone->writeio = NULL;
1088 zone->timer = NULL;
1089 zone->idlein = DNS_DEFAULT_IDLEIN;
1090 zone->idleout = DNS_DEFAULT_IDLEOUT;
1091 zone->log_key_expired_timer = 0;
1092 ISC_LIST_INIT(zone->notifies);
1093 isc_sockaddr_any(&zone->notifysrc4);
1094 isc_sockaddr_any6(&zone->notifysrc6);
1095 isc_sockaddr_any(&zone->xfrsource4);
1096 isc_sockaddr_any6(&zone->xfrsource6);
1097 isc_sockaddr_any(&zone->altxfrsource4);
1098 isc_sockaddr_any6(&zone->altxfrsource6);
1099 zone->notifysrc4dscp = -1;
1100 zone->notifysrc6dscp = -1;
1101 zone->xfrsource4dscp = -1;
1102 zone->xfrsource6dscp = -1;
1103 zone->altxfrsource4dscp = -1;
1104 zone->altxfrsource6dscp = -1;
1105 zone->xfr = NULL;
1106 zone->tsigkey = NULL;
1107 zone->maxxfrin = MAX_XFER_TIME;
1108 zone->maxxfrout = MAX_XFER_TIME;
1109 zone->ssutable = NULL;
1110 zone->sigvalidityinterval = 30 * 24 * 3600;
1111 zone->keyvalidityinterval = 0;
1112 zone->sigresigninginterval = 7 * 24 * 3600;
1113 zone->kasp = NULL;
1114 zone->view = NULL;
1115 zone->prev_view = NULL;
1116 zone->checkmx = NULL;
1117 zone->checksrv = NULL;
1118 zone->checkns = NULL;
1119 ISC_LINK_INIT(zone, statelink);
1120 zone->statelist = NULL;
1121 zone->stats = NULL;
1122 zone->requeststats_on = false;
1123 zone->statlevel = dns_zonestat_none;
1124 zone->requeststats = NULL;
1125 zone->rcvquerystats = NULL;
1126 zone->dnssecsignstats = NULL;
1127 zone->notifydelay = 5;
1128 zone->isself = NULL;
1129 zone->isselfarg = NULL;
1130 ISC_LIST_INIT(zone->signing);
1131 ISC_LIST_INIT(zone->nsec3chain);
1132 ISC_LIST_INIT(zone->setnsec3param_queue);
1133 zone->signatures = 10;
1134 zone->nodes = 100;
1135 zone->privatetype = (dns_rdatatype_t)0xffffU;
1136 zone->added = false;
1137 zone->automatic = false;
1138 zone->rpzs = NULL;
1139 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1140
1141 zone->catzs = NULL;
1142 zone->parentcatz = NULL;
1143
1144 ISC_LIST_INIT(zone->forwards);
1145 zone->raw = NULL;
1146 zone->secure = NULL;
1147 zone->sourceserial = 0;
1148 zone->sourceserialset = false;
1149 zone->requestixfr = true;
1150 zone->ixfr_ratio = 100;
1151 zone->requestexpire = true;
1152 ISC_LIST_INIT(zone->rss_events);
1153 ISC_LIST_INIT(zone->rss_post);
1154 zone->rss_db = NULL;
1155 zone->rss_raw = NULL;
1156 zone->rss_newver = NULL;
1157 zone->rss_oldver = NULL;
1158 zone->rss_event = NULL;
1159 zone->rss_state = NULL;
1160 zone->updatemethod = dns_updatemethod_increment;
1161 zone->maxrecords = 0U;
1162
1163 zone->magic = ZONE_MAGIC;
1164
1165 zone->gluecachestats = NULL;
1166 result = isc_stats_create(mctx, &zone->gluecachestats,
1167 dns_gluecachestatscounter_max);
1168 if (result != ISC_R_SUCCESS) {
1169 goto free_refs;
1170 }
1171
1172 /* Must be after magic is set. */
1173 dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1174
1175 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1176 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone, NULL,
1177 NULL);
1178 *zonep = zone;
1179 return (ISC_R_SUCCESS);
1180
1181 free_refs:
1182 isc_refcount_decrement0(&zone->erefs);
1183 isc_refcount_destroy(&zone->erefs);
1184 isc_refcount_destroy(&zone->irefs);
1185 ZONEDB_DESTROYLOCK(&zone->dblock);
1186 isc_mutex_destroy(&zone->lock);
1187 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1188 return (result);
1189 }
1190
1191 /*
1192 * Free a zone. Because we require that there be no more
1193 * outstanding events or references, no locking is necessary.
1194 */
1195 static void
1196 zone_free(dns_zone_t *zone) {
1197 dns_signing_t *signing;
1198 dns_nsec3chain_t *nsec3chain;
1199 isc_event_t *event;
1200 dns_include_t *include;
1201
1202 REQUIRE(DNS_ZONE_VALID(zone));
1203 isc_refcount_destroy(&zone->erefs);
1204 isc_refcount_destroy(&zone->irefs);
1205 REQUIRE(!LOCKED_ZONE(zone));
1206 REQUIRE(zone->timer == NULL);
1207 REQUIRE(zone->zmgr == NULL);
1208
1209 /*
1210 * Managed objects. Order is important.
1211 */
1212 if (zone->request != NULL) {
1213 dns_request_destroy(&zone->request); /* XXXMPA */
1214 }
1215 INSIST(zone->readio == NULL);
1216 INSIST(zone->statelist == NULL);
1217 INSIST(zone->writeio == NULL);
1218
1219 if (zone->task != NULL) {
1220 isc_task_detach(&zone->task);
1221 }
1222 if (zone->loadtask != NULL) {
1223 isc_task_detach(&zone->loadtask);
1224 }
1225 if (zone->view != NULL) {
1226 dns_view_weakdetach(&zone->view);
1227 }
1228 if (zone->prev_view != NULL) {
1229 dns_view_weakdetach(&zone->prev_view);
1230 }
1231
1232 /* Unmanaged objects */
1233 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1234 event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1235 ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1236 isc_event_free(&event);
1237 }
1238 while (!ISC_LIST_EMPTY(zone->rss_post)) {
1239 event = ISC_LIST_HEAD(zone->rss_post);
1240 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1241 isc_event_free(&event);
1242 }
1243 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
1244 signing = ISC_LIST_HEAD(zone->signing))
1245 {
1246 ISC_LIST_UNLINK(zone->signing, signing, link);
1247 dns_db_detach(&signing->db);
1248 dns_dbiterator_destroy(&signing->dbiterator);
1249 isc_mem_put(zone->mctx, signing, sizeof *signing);
1250 }
1251 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
1252 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain))
1253 {
1254 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1255 dns_db_detach(&nsec3chain->db);
1256 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1257 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1258 }
1259 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1260 include = ISC_LIST_HEAD(zone->includes))
1261 {
1262 ISC_LIST_UNLINK(zone->includes, include, link);
1263 isc_mem_free(zone->mctx, include->name);
1264 isc_mem_put(zone->mctx, include, sizeof *include);
1265 }
1266 for (include = ISC_LIST_HEAD(zone->newincludes); include != NULL;
1267 include = ISC_LIST_HEAD(zone->newincludes))
1268 {
1269 ISC_LIST_UNLINK(zone->newincludes, include, link);
1270 isc_mem_free(zone->mctx, include->name);
1271 isc_mem_put(zone->mctx, include, sizeof *include);
1272 }
1273 if (zone->masterfile != NULL) {
1274 isc_mem_free(zone->mctx, zone->masterfile);
1275 }
1276 zone->masterfile = NULL;
1277 if (zone->keydirectory != NULL) {
1278 isc_mem_free(zone->mctx, zone->keydirectory);
1279 }
1280 zone->keydirectory = NULL;
1281 if (zone->kasp != NULL) {
1282 dns_kasp_detach(&zone->kasp);
1283 }
1284 zone->journalsize = -1;
1285 if (zone->journal != NULL) {
1286 isc_mem_free(zone->mctx, zone->journal);
1287 }
1288 zone->journal = NULL;
1289 if (zone->stats != NULL) {
1290 isc_stats_detach(&zone->stats);
1291 }
1292 if (zone->requeststats != NULL) {
1293 isc_stats_detach(&zone->requeststats);
1294 }
1295 if (zone->rcvquerystats != NULL) {
1296 dns_stats_detach(&zone->rcvquerystats);
1297 }
1298 if (zone->dnssecsignstats != NULL) {
1299 dns_stats_detach(&zone->dnssecsignstats);
1300 }
1301 if (zone->db != NULL) {
1302 zone_detachdb(zone);
1303 }
1304 if (zone->rpzs != NULL) {
1305 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1306 dns_rpz_detach_rpzs(&zone->rpzs);
1307 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1308 }
1309 if (zone->catzs != NULL) {
1310 dns_catz_catzs_detach(&zone->catzs);
1311 }
1312 zone_freedbargs(zone);
1313 RUNTIME_CHECK(dns_zone_setprimarieswithkeys(zone, NULL, NULL, 0) ==
1314 ISC_R_SUCCESS);
1315 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1316 zone->check_names = dns_severity_ignore;
1317 if (zone->update_acl != NULL) {
1318 dns_acl_detach(&zone->update_acl);
1319 }
1320 if (zone->forward_acl != NULL) {
1321 dns_acl_detach(&zone->forward_acl);
1322 }
1323 if (zone->notify_acl != NULL) {
1324 dns_acl_detach(&zone->notify_acl);
1325 }
1326 if (zone->query_acl != NULL) {
1327 dns_acl_detach(&zone->query_acl);
1328 }
1329 if (zone->queryon_acl != NULL) {
1330 dns_acl_detach(&zone->queryon_acl);
1331 }
1332 if (zone->xfr_acl != NULL) {
1333 dns_acl_detach(&zone->xfr_acl);
1334 }
1335 if (dns_name_dynamic(&zone->origin)) {
1336 dns_name_free(&zone->origin, zone->mctx);
1337 }
1338 if (zone->strnamerd != NULL) {
1339 isc_mem_free(zone->mctx, zone->strnamerd);
1340 }
1341 if (zone->strname != NULL) {
1342 isc_mem_free(zone->mctx, zone->strname);
1343 }
1344 if (zone->strrdclass != NULL) {
1345 isc_mem_free(zone->mctx, zone->strrdclass);
1346 }
1347 if (zone->strviewname != NULL) {
1348 isc_mem_free(zone->mctx, zone->strviewname);
1349 }
1350 if (zone->ssutable != NULL) {
1351 dns_ssutable_detach(&zone->ssutable);
1352 }
1353 if (zone->gluecachestats != NULL) {
1354 isc_stats_detach(&zone->gluecachestats);
1355 }
1356
1357 /* last stuff */
1358 ZONEDB_DESTROYLOCK(&zone->dblock);
1359 isc_mutex_destroy(&zone->lock);
1360 zone->magic = 0;
1361 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1362 }
1363
1364 /*
1365 * Returns true iff this the signed side of an inline-signing zone.
1366 * Caller should hold zone lock.
1367 */
1368 static inline bool
1369 inline_secure(dns_zone_t *zone) {
1370 REQUIRE(DNS_ZONE_VALID(zone));
1371 if (zone->raw != NULL) {
1372 return (true);
1373 }
1374 return (false);
1375 }
1376
1377 /*
1378 * Returns true iff this the unsigned side of an inline-signing zone
1379 * Caller should hold zone lock.
1380 */
1381 static inline bool
1382 inline_raw(dns_zone_t *zone) {
1383 REQUIRE(DNS_ZONE_VALID(zone));
1384 if (zone->secure != NULL) {
1385 return (true);
1386 }
1387 return (false);
1388 }
1389
1390 /*
1391 * Single shot.
1392 */
1393 void
1394 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1395 char namebuf[1024];
1396
1397 REQUIRE(DNS_ZONE_VALID(zone));
1398 REQUIRE(rdclass != dns_rdataclass_none);
1399
1400 /*
1401 * Test and set.
1402 */
1403 LOCK_ZONE(zone);
1404 INSIST(zone != zone->raw);
1405 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1406 zone->rdclass == rdclass);
1407 zone->rdclass = rdclass;
1408
1409 if (zone->strnamerd != NULL) {
1410 isc_mem_free(zone->mctx, zone->strnamerd);
1411 }
1412 if (zone->strrdclass != NULL) {
1413 isc_mem_free(zone->mctx, zone->strrdclass);
1414 }
1415
1416 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1417 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1418 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1419 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1420
1421 if (inline_secure(zone)) {
1422 dns_zone_setclass(zone->raw, rdclass);
1423 }
1424 UNLOCK_ZONE(zone);
1425 }
1426
1427 dns_rdataclass_t
1428 dns_zone_getclass(dns_zone_t *zone) {
1429 REQUIRE(DNS_ZONE_VALID(zone));
1430
1431 return (zone->rdclass);
1432 }
1433
1434 void
1435 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1436 REQUIRE(DNS_ZONE_VALID(zone));
1437
1438 LOCK_ZONE(zone);
1439 zone->notifytype = notifytype;
1440 UNLOCK_ZONE(zone);
1441 }
1442
1443 isc_result_t
1444 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1445 isc_result_t result;
1446 unsigned int soacount;
1447
1448 REQUIRE(DNS_ZONE_VALID(zone));
1449 REQUIRE(serialp != NULL);
1450
1451 LOCK_ZONE(zone);
1452 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1453 if (zone->db != NULL) {
1454 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1455 serialp, NULL, NULL, NULL, NULL,
1456 NULL);
1457 if (result == ISC_R_SUCCESS && soacount == 0) {
1458 result = ISC_R_FAILURE;
1459 }
1460 } else {
1461 result = DNS_R_NOTLOADED;
1462 }
1463 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1464 UNLOCK_ZONE(zone);
1465
1466 return (result);
1467 }
1468
1469 /*
1470 * Single shot.
1471 */
1472 void
1473 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1474 char namebuf[1024];
1475
1476 REQUIRE(DNS_ZONE_VALID(zone));
1477 REQUIRE(type != dns_zone_none);
1478
1479 /*
1480 * Test and set.
1481 */
1482 LOCK_ZONE(zone);
1483 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1484 zone->type = type;
1485
1486 if (zone->strnamerd != NULL) {
1487 isc_mem_free(zone->mctx, zone->strnamerd);
1488 }
1489
1490 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1491 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1492 UNLOCK_ZONE(zone);
1493 }
1494
1495 static void
1496 zone_freedbargs(dns_zone_t *zone) {
1497 unsigned int i;
1498
1499 /* Free the old database argument list. */
1500 if (zone->db_argv != NULL) {
1501 for (i = 0; i < zone->db_argc; i++) {
1502 isc_mem_free(zone->mctx, zone->db_argv[i]);
1503 }
1504 isc_mem_put(zone->mctx, zone->db_argv,
1505 zone->db_argc * sizeof(*zone->db_argv));
1506 }
1507 zone->db_argc = 0;
1508 zone->db_argv = NULL;
1509 }
1510
1511 isc_result_t
1512 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1513 size_t size = 0;
1514 unsigned int i;
1515 isc_result_t result = ISC_R_SUCCESS;
1516 void *mem;
1517 char **tmp, *tmp2, *base;
1518
1519 REQUIRE(DNS_ZONE_VALID(zone));
1520 REQUIRE(argv != NULL && *argv == NULL);
1521
1522 LOCK_ZONE(zone);
1523 size = (zone->db_argc + 1) * sizeof(char *);
1524 for (i = 0; i < zone->db_argc; i++) {
1525 size += strlen(zone->db_argv[i]) + 1;
1526 }
1527 mem = isc_mem_allocate(mctx, size);
1528 {
1529 tmp = mem;
1530 tmp2 = mem;
1531 base = mem;
1532 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1533 for (i = 0; i < zone->db_argc; i++) {
1534 *tmp++ = tmp2;
1535 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1536 tmp2 += strlen(tmp2) + 1;
1537 }
1538 *tmp = NULL;
1539 }
1540 UNLOCK_ZONE(zone);
1541 *argv = mem;
1542 return (result);
1543 }
1544
1545 void
1546 dns_zone_setdbtype(dns_zone_t *zone, unsigned int dbargc,
1547 const char *const *dbargv) {
1548 char **argv = NULL;
1549 unsigned int i;
1550
1551 REQUIRE(DNS_ZONE_VALID(zone));
1552 REQUIRE(dbargc >= 1);
1553 REQUIRE(dbargv != NULL);
1554
1555 LOCK_ZONE(zone);
1556
1557 /* Set up a new database argument list. */
1558 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1559 for (i = 0; i < dbargc; i++) {
1560 argv[i] = NULL;
1561 }
1562 for (i = 0; i < dbargc; i++) {
1563 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1564 }
1565
1566 /* Free the old list. */
1567 zone_freedbargs(zone);
1568
1569 zone->db_argc = dbargc;
1570 zone->db_argv = argv;
1571
1572 UNLOCK_ZONE(zone);
1573 }
1574
1575 static void
1576 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1577 char namebuf[1024];
1578
1579 if (zone->prev_view == NULL && zone->view != NULL) {
1580 dns_view_weakattach(zone->view, &zone->prev_view);
1581 }
1582
1583 INSIST(zone != zone->raw);
1584 if (zone->view != NULL) {
1585 dns_view_weakdetach(&zone->view);
1586 }
1587 dns_view_weakattach(view, &zone->view);
1588
1589 if (zone->strviewname != NULL) {
1590 isc_mem_free(zone->mctx, zone->strviewname);
1591 }
1592 if (zone->strnamerd != NULL) {
1593 isc_mem_free(zone->mctx, zone->strnamerd);
1594 }
1595
1596 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1597 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1598 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1599 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1600
1601 if (inline_secure(zone)) {
1602 dns_zone_setview(zone->raw, view);
1603 }
1604 }
1605
1606 void
1607 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1608 REQUIRE(DNS_ZONE_VALID(zone));
1609
1610 LOCK_ZONE(zone);
1611 dns_zone_setview_helper(zone, view);
1612 UNLOCK_ZONE(zone);
1613 }
1614
1615 dns_view_t *
1616 dns_zone_getview(dns_zone_t *zone) {
1617 REQUIRE(DNS_ZONE_VALID(zone));
1618
1619 return (zone->view);
1620 }
1621
1622 void
1623 dns_zone_setviewcommit(dns_zone_t *zone) {
1624 REQUIRE(DNS_ZONE_VALID(zone));
1625
1626 LOCK_ZONE(zone);
1627 if (zone->prev_view != NULL) {
1628 dns_view_weakdetach(&zone->prev_view);
1629 }
1630 if (inline_secure(zone)) {
1631 dns_zone_setviewcommit(zone->raw);
1632 }
1633 UNLOCK_ZONE(zone);
1634 }
1635
1636 void
1637 dns_zone_setviewrevert(dns_zone_t *zone) {
1638 REQUIRE(DNS_ZONE_VALID(zone));
1639
1640 LOCK_ZONE(zone);
1641 if (zone->prev_view != NULL) {
1642 dns_zone_setview_helper(zone, zone->prev_view);
1643 dns_view_weakdetach(&zone->prev_view);
1644 }
1645 if (inline_secure(zone)) {
1646 dns_zone_setviewrevert(zone->raw);
1647 }
1648 UNLOCK_ZONE(zone);
1649 }
1650
1651 isc_result_t
1652 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1653 isc_result_t result = ISC_R_SUCCESS;
1654 char namebuf[1024];
1655
1656 REQUIRE(DNS_ZONE_VALID(zone));
1657 REQUIRE(origin != NULL);
1658
1659 LOCK_ZONE(zone);
1660 INSIST(zone != zone->raw);
1661 if (dns_name_dynamic(&zone->origin)) {
1662 dns_name_free(&zone->origin, zone->mctx);
1663 dns_name_init(&zone->origin, NULL);
1664 }
1665 dns_name_dup(origin, zone->mctx, &zone->origin);
1666
1667 if (zone->strnamerd != NULL) {
1668 isc_mem_free(zone->mctx, zone->strnamerd);
1669 }
1670 if (zone->strname != NULL) {
1671 isc_mem_free(zone->mctx, zone->strname);
1672 }
1673
1674 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1675 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1676 zone_name_tostr(zone, namebuf, sizeof namebuf);
1677 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1678
1679 if (inline_secure(zone)) {
1680 result = dns_zone_setorigin(zone->raw, origin);
1681 }
1682 UNLOCK_ZONE(zone);
1683 return (result);
1684 }
1685
1686 static isc_result_t
1687 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1688 char *copy;
1689
1690 if (value != NULL) {
1691 copy = isc_mem_strdup(zone->mctx, value);
1692 } else {
1693 copy = NULL;
1694 }
1695
1696 if (*field != NULL) {
1697 isc_mem_free(zone->mctx, *field);
1698 }
1699
1700 *field = copy;
1701 return (ISC_R_SUCCESS);
1702 }
1703
1704 isc_result_t
1705 dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
1706 const dns_master_style_t *style) {
1707 isc_result_t result = ISC_R_SUCCESS;
1708
1709 REQUIRE(DNS_ZONE_VALID(zone));
1710
1711 LOCK_ZONE(zone);
1712 result = dns_zone_setstring(zone, &zone->masterfile, file);
1713 if (result == ISC_R_SUCCESS) {
1714 zone->masterformat = format;
1715 if (format == dns_masterformat_text) {
1716 zone->masterstyle = style;
1717 }
1718 result = default_journal(zone);
1719 }
1720 UNLOCK_ZONE(zone);
1721
1722 return (result);
1723 }
1724
1725 const char *
1726 dns_zone_getfile(dns_zone_t *zone) {
1727 REQUIRE(DNS_ZONE_VALID(zone));
1728
1729 return (zone->masterfile);
1730 }
1731
1732 dns_ttl_t
1733 dns_zone_getmaxttl(dns_zone_t *zone) {
1734 REQUIRE(DNS_ZONE_VALID(zone));
1735
1736 return (zone->maxttl);
1737 }
1738
1739 void
1740 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1741 REQUIRE(DNS_ZONE_VALID(zone));
1742
1743 LOCK_ZONE(zone);
1744 if (maxttl != 0) {
1745 DNS_ZONE_SETOPTION(zone, DNS_ZONEOPT_CHECKTTL);
1746 } else {
1747 DNS_ZONE_CLROPTION(zone, DNS_ZONEOPT_CHECKTTL);
1748 }
1749 zone->maxttl = maxttl;
1750 UNLOCK_ZONE(zone);
1751
1752 return;
1753 }
1754
1755 static isc_result_t
1756 default_journal(dns_zone_t *zone) {
1757 isc_result_t result;
1758 char *journal;
1759
1760 REQUIRE(DNS_ZONE_VALID(zone));
1761 REQUIRE(LOCKED_ZONE(zone));
1762
1763 if (zone->masterfile != NULL) {
1764 /* Calculate string length including '\0'. */
1765 int len = strlen(zone->masterfile) + sizeof(".jnl");
1766 journal = isc_mem_allocate(zone->mctx, len);
1767 strlcpy(journal, zone->masterfile, len);
1768 strlcat(journal, ".jnl", len);
1769 } else {
1770 journal = NULL;
1771 }
1772 result = dns_zone_setstring(zone, &zone->journal, journal);
1773 if (journal != NULL) {
1774 isc_mem_free(zone->mctx, journal);
1775 }
1776 return (result);
1777 }
1778
1779 isc_result_t
1780 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1781 isc_result_t result = ISC_R_SUCCESS;
1782
1783 REQUIRE(DNS_ZONE_VALID(zone));
1784
1785 LOCK_ZONE(zone);
1786 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1787 UNLOCK_ZONE(zone);
1788
1789 return (result);
1790 }
1791
1792 char *
1793 dns_zone_getjournal(dns_zone_t *zone) {
1794 REQUIRE(DNS_ZONE_VALID(zone));
1795
1796 return (zone->journal);
1797 }
1798
1799 /*
1800 * Return true iff the zone is "dynamic", in the sense that the zone's
1801 * master file (if any) is written by the server, rather than being
1802 * updated manually and read by the server.
1803 *
1804 * This is true for slave zones, mirror zones, stub zones, key zones,
1805 * and zones that allow dynamic updates either by having an update
1806 * policy ("ssutable") or an "allow-update" ACL with a value other than
1807 * exactly "{ none; }".
1808 */
1809 bool
1810 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1811 REQUIRE(DNS_ZONE_VALID(zone));
1812
1813 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
1814 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1815 (zone->type == dns_zone_redirect && zone->masters != NULL))
1816 {
1817 return (true);
1818 }
1819
1820 /* Inline zones are always dynamic. */
1821 if (zone->type == dns_zone_master && zone->raw != NULL) {
1822 return (true);
1823 }
1824
1825 /* If !ignore_freeze, we need check whether updates are disabled. */
1826 if (zone->type == dns_zone_master &&
1827 (!zone->update_disabled || ignore_freeze) &&
1828 ((zone->ssutable != NULL) ||
1829 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1830 {
1831 return (true);
1832 }
1833
1834 return (false);
1835 }
1836
1837 /*
1838 * Set the response policy index and information for a zone.
1839 */
1840 isc_result_t
1841 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1842 dns_rpz_num_t rpz_num) {
1843 /*
1844 * Only RBTDB zones can be used for response policy zones,
1845 * because only they have the code to create the summary data.
1846 * Only zones that are loaded instead of mmap()ed create the
1847 * summary data and so can be policy zones.
1848 */
1849 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1850 strcmp(zone->db_argv[0], "rbt64") != 0)
1851 {
1852 return (ISC_R_NOTIMPLEMENTED);
1853 }
1854 if (zone->masterformat == dns_masterformat_map) {
1855 return (ISC_R_NOTIMPLEMENTED);
1856 }
1857
1858 /*
1859 * This must happen only once or be redundant.
1860 */
1861 LOCK_ZONE(zone);
1862 if (zone->rpzs != NULL) {
1863 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1864 } else {
1865 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1866 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1867 zone->rpz_num = rpz_num;
1868 }
1869 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1870 UNLOCK_ZONE(zone);
1871
1872 return (ISC_R_SUCCESS);
1873 }
1874
1875 dns_rpz_num_t
1876 dns_zone_get_rpz_num(dns_zone_t *zone) {
1877 return (zone->rpz_num);
1878 }
1879
1880 /*
1881 * If a zone is a response policy zone, mark its new database.
1882 */
1883 void
1884 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1885 isc_result_t result;
1886 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1887 return;
1888 }
1889 REQUIRE(zone->rpzs != NULL);
1890 result = dns_db_updatenotify_register(db, dns_rpz_dbupdate_callback,
1891 zone->rpzs->zones[zone->rpz_num]);
1892 REQUIRE(result == ISC_R_SUCCESS);
1893 }
1894
1895 static void
1896 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1897 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1898 return;
1899 }
1900 REQUIRE(zone->rpzs != NULL);
1901 (void)dns_db_updatenotify_unregister(db, dns_rpz_dbupdate_callback,
1902 zone->rpzs->zones[zone->rpz_num]);
1903 }
1904
1905 void
1906 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1907 REQUIRE(DNS_ZONE_VALID(zone));
1908 REQUIRE(catzs != NULL);
1909
1910 LOCK_ZONE(zone);
1911 INSIST(zone->catzs == NULL || zone->catzs == catzs);
1912 dns_catz_catzs_set_view(catzs, zone->view);
1913 if (zone->catzs == NULL) {
1914 dns_catz_catzs_attach(catzs, &zone->catzs);
1915 }
1916 UNLOCK_ZONE(zone);
1917 }
1918
1919 /*
1920 * If a zone is a catalog zone, attach it to update notification in database.
1921 */
1922 void
1923 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1924 REQUIRE(DNS_ZONE_VALID(zone));
1925 REQUIRE(db != NULL);
1926
1927 if (zone->catzs != NULL) {
1928 dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1929 zone->catzs);
1930 }
1931 }
1932
1933 static void
1934 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1935 REQUIRE(DNS_ZONE_VALID(zone));
1936 REQUIRE(db != NULL);
1937
1938 if (zone->catzs != NULL) {
1939 dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
1940 zone->catzs);
1941 }
1942 }
1943
1944 /*
1945 * Set catalog zone ownership of the zone
1946 */
1947 void
1948 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
1949 REQUIRE(DNS_ZONE_VALID(zone));
1950 REQUIRE(catz != NULL);
1951 LOCK_ZONE(zone);
1952 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
1953 zone->parentcatz = catz;
1954 UNLOCK_ZONE(zone);
1955 }
1956
1957 dns_catz_zone_t *
1958 dns_zone_get_parentcatz(const dns_zone_t *zone) {
1959 REQUIRE(DNS_ZONE_VALID(zone));
1960 return (zone->parentcatz);
1961 }
1962
1963 static bool
1964 zone_touched(dns_zone_t *zone) {
1965 isc_result_t result;
1966 isc_time_t modtime;
1967 dns_include_t *include;
1968
1969 REQUIRE(DNS_ZONE_VALID(zone));
1970
1971 result = isc_file_getmodtime(zone->masterfile, &modtime);
1972 if (result != ISC_R_SUCCESS ||
1973 isc_time_compare(&modtime, &zone->loadtime) > 0) {
1974 return (true);
1975 }
1976
1977 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
1978 include = ISC_LIST_NEXT(include, link))
1979 {
1980 result = isc_file_getmodtime(include->name, &modtime);
1981 if (result != ISC_R_SUCCESS ||
1982 isc_time_compare(&modtime, &include->filetime) > 0)
1983 {
1984 return (true);
1985 }
1986 }
1987
1988 return (false);
1989 }
1990
1991 /*
1992 * Note: when dealing with inline-signed zones, external callers will always
1993 * call zone_load() for the secure zone; zone_load() calls itself recursively
1994 * in order to load the raw zone.
1995 */
1996 static isc_result_t
1997 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
1998 isc_result_t result;
1999 isc_time_t now;
2000 isc_time_t loadtime;
2001 dns_db_t *db = NULL;
2002 bool rbt, hasraw, is_dynamic;
2003
2004 REQUIRE(DNS_ZONE_VALID(zone));
2005
2006 if (!locked) {
2007 LOCK_ZONE(zone);
2008 }
2009
2010 INSIST(zone != zone->raw);
2011 hasraw = inline_secure(zone);
2012 if (hasraw) {
2013 /*
2014 * We are trying to load an inline-signed zone. First call
2015 * self recursively to try loading the raw version of the zone.
2016 * Assuming the raw zone file is readable, there are two
2017 * possibilities:
2018 *
2019 * a) the raw zone was not yet loaded and thus it will be
2020 * loaded now, synchronously; if this succeeds, a
2021 * subsequent attempt to load the signed zone file will
2022 * take place and thus zone_postload() will be called
2023 * twice: first for the raw zone and then for the secure
2024 * zone; the latter call will take care of syncing the raw
2025 * version with the secure version,
2026 *
2027 * b) the raw zone was already loaded and we are trying to
2028 * reload it, which will happen asynchronously; this means
2029 * zone_postload() will only be called for the raw zone
2030 * because "result" returned by the zone_load() call below
2031 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
2032 * zone_postload() called for the raw zone will take care
2033 * of syncing the raw version with the secure version.
2034 */
2035 result = zone_load(zone->raw, flags, false);
2036 if (result != ISC_R_SUCCESS) {
2037 if (!locked) {
2038 UNLOCK_ZONE(zone);
2039 }
2040 return (result);
2041 }
2042 LOCK_ZONE(zone->raw);
2043 }
2044
2045 TIME_NOW(&now);
2046
2047 INSIST(zone->type != dns_zone_none);
2048
2049 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
2050 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2051 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2052 }
2053 result = DNS_R_CONTINUE;
2054 goto cleanup;
2055 }
2056
2057 INSIST(zone->db_argc >= 1);
2058
2059 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
2060 strcmp(zone->db_argv[0], "rbt64") == 0;
2061
2062 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
2063 /*
2064 * The zone has no master file configured.
2065 */
2066 result = ISC_R_SUCCESS;
2067 goto cleanup;
2068 }
2069
2070 is_dynamic = dns_zone_isdynamic(zone, false);
2071 if (zone->db != NULL && is_dynamic) {
2072 /*
2073 * This is a slave, stub, or dynamically updated zone being
2074 * reloaded. Do nothing - the database we already
2075 * have is guaranteed to be up-to-date.
2076 */
2077 if (zone->type == dns_zone_master && !hasraw) {
2078 result = DNS_R_DYNAMIC;
2079 } else {
2080 result = ISC_R_SUCCESS;
2081 }
2082 goto cleanup;
2083 }
2084
2085 /*
2086 * Store the current time before the zone is loaded, so that if the
2087 * file changes between the time of the load and the time that
2088 * zone->loadtime is set, then the file will still be reloaded
2089 * the next time dns_zone_load is called.
2090 */
2091 TIME_NOW(&loadtime);
2092
2093 /*
2094 * Don't do the load if the file that stores the zone is older
2095 * than the last time the zone was loaded. If the zone has not
2096 * been loaded yet, zone->loadtime will be the epoch.
2097 */
2098 if (zone->masterfile != NULL) {
2099 isc_time_t filetime;
2100
2101 /*
2102 * The file is already loaded. If we are just doing a
2103 * "rndc reconfig", we are done.
2104 */
2105 if (!isc_time_isepoch(&zone->loadtime) &&
2106 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0)
2107 {
2108 result = ISC_R_SUCCESS;
2109 goto cleanup;
2110 }
2111
2112 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2113 !zone_touched(zone)) {
2114 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2115 ISC_LOG_DEBUG(1),
2116 "skipping load: master file "
2117 "older than last load");
2118 result = DNS_R_UPTODATE;
2119 goto cleanup;
2120 }
2121
2122 /*
2123 * If the file modification time is in the past
2124 * set loadtime to that value.
2125 */
2126 result = isc_file_getmodtime(zone->masterfile, &filetime);
2127 if (result == ISC_R_SUCCESS &&
2128 isc_time_compare(&loadtime, &filetime) > 0) {
2129 loadtime = filetime;
2130 }
2131 }
2132
2133 /*
2134 * Built in zones (with the exception of empty zones) don't need
2135 * to be reloaded.
2136 */
2137 if (zone->type == dns_zone_master &&
2138 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2139 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2140 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
2141 {
2142 result = ISC_R_SUCCESS;
2143 goto cleanup;
2144 }
2145
2146 /*
2147 * Zones associated with a DLZ don't need to be loaded either,
2148 * but we need to associate the database with the zone object.
2149 */
2150 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2151 dns_dlzdb_t *dlzdb;
2152 dns_dlzfindzone_t findzone;
2153
2154 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2155 dlzdb != NULL; dlzdb = ISC_LIST_NEXT(dlzdb, link))
2156 {
2157 INSIST(DNS_DLZ_VALID(dlzdb));
2158 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0) {
2159 break;
2160 }
2161 }
2162
2163 if (dlzdb == NULL) {
2164 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2165 ISC_LOG_ERROR,
2166 "DLZ %s does not exist or is set "
2167 "to 'search yes;'",
2168 zone->db_argv[1]);
2169 result = ISC_R_NOTFOUND;
2170 goto cleanup;
2171 }
2172
2173 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2174 /* ask SDLZ driver if the zone is supported */
2175 findzone = dlzdb->implementation->methods->findzone;
2176 result = (*findzone)(dlzdb->implementation->driverarg,
2177 dlzdb->dbdata, dlzdb->mctx,
2178 zone->view->rdclass, &zone->origin, NULL,
2179 NULL, &db);
2180 if (result != ISC_R_NOTFOUND) {
2181 if (zone->db != NULL) {
2182 zone_detachdb(zone);
2183 }
2184 zone_attachdb(zone, db);
2185 dns_db_detach(&db);
2186 result = ISC_R_SUCCESS;
2187 }
2188 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2189
2190 if (result == ISC_R_SUCCESS) {
2191 if (dlzdb->configure_callback == NULL) {
2192 goto cleanup;
2193 }
2194
2195 result = (*dlzdb->configure_callback)(zone->view, dlzdb,
2196 zone);
2197 if (result != ISC_R_SUCCESS) {
2198 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2199 ISC_LOG_ERROR,
2200 "DLZ configuration callback: %s",
2201 isc_result_totext(result));
2202 }
2203 }
2204 goto cleanup;
2205 }
2206
2207 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2208 zone->type == dns_zone_stub ||
2209 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2210 rbt)
2211 {
2212 if (zone->masterfile == NULL ||
2213 !isc_file_exists(zone->masterfile)) {
2214 if (zone->masterfile != NULL) {
2215 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2216 ISC_LOG_DEBUG(1),
2217 "no master file");
2218 }
2219 zone->refreshtime = now;
2220 if (zone->task != NULL) {
2221 zone_settimer(zone, &now);
2222 }
2223 result = ISC_R_SUCCESS;
2224 goto cleanup;
2225 }
2226 }
2227
2228 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
2229 "starting load");
2230
2231 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
2232 (zone->type == dns_zone_stub) ? dns_dbtype_stub
2233 : dns_dbtype_zone,
2234 zone->rdclass, zone->db_argc - 1,
2235 zone->db_argv + 1, &db);
2236
2237 if (result != ISC_R_SUCCESS) {
2238 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2239 "loading zone: creating database: %s",
2240 isc_result_totext(result));
2241 goto cleanup;
2242 }
2243 dns_db_settask(db, zone->task);
2244
2245 if (zone->type == dns_zone_master || zone->type == dns_zone_slave ||
2246 zone->type == dns_zone_mirror)
2247 {
2248 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2249 if (result == ISC_R_NOTIMPLEMENTED) {
2250 result = ISC_R_SUCCESS;
2251 }
2252 if (result != ISC_R_SUCCESS) {
2253 goto cleanup;
2254 }
2255 }
2256
2257 if (!dns_db_ispersistent(db)) {
2258 if (zone->masterfile != NULL) {
2259 result = zone_startload(db, zone, loadtime);
2260 } else {
2261 result = DNS_R_NOMASTERFILE;
2262 if (zone->type == dns_zone_master ||
2263 (zone->type == dns_zone_redirect &&
2264 zone->masters == NULL))
2265 {
2266 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2267 ISC_LOG_ERROR,
2268 "loading zone: "
2269 "no master file configured");
2270 goto cleanup;
2271 }
2272 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2273 ISC_LOG_INFO,
2274 "loading zone: "
2275 "no master file configured: continuing");
2276 }
2277 }
2278
2279 if (result == DNS_R_CONTINUE) {
2280 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2281 if ((flags & DNS_ZONELOADFLAG_THAW) != 0) {
2282 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2283 }
2284 goto cleanup;
2285 }
2286
2287 result = zone_postload(zone, db, loadtime, result);
2288
2289 cleanup:
2290 if (hasraw) {
2291 UNLOCK_ZONE(zone->raw);
2292 }
2293 if (!locked) {
2294 UNLOCK_ZONE(zone);
2295 }
2296 if (db != NULL) {
2297 dns_db_detach(&db);
2298 }
2299 return (result);
2300 }
2301
2302 isc_result_t
2303 dns_zone_load(dns_zone_t *zone, bool newonly) {
2304 return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2305 }
2306
2307 static void
2308 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2309 dns_asyncload_t *asl = event->ev_arg;
2310 dns_zone_t *zone = asl->zone;
2311 isc_result_t result;
2312
2313 UNUSED(task);
2314
2315 REQUIRE(DNS_ZONE_VALID(zone));
2316
2317 isc_event_free(&event);
2318
2319 LOCK_ZONE(zone);
2320 result = zone_load(zone, asl->flags, true);
2321 if (result != DNS_R_CONTINUE) {
2322 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2323 }
2324 UNLOCK_ZONE(zone);
2325
2326 /* Inform the zone table we've finished loading */
2327 if (asl->loaded != NULL) {
2328 (asl->loaded)(asl->loaded_arg, zone, task);
2329 }
2330
2331 isc_mem_put(zone->mctx, asl, sizeof(*asl));
2332 dns_zone_idetach(&zone);
2333 }
2334
2335 isc_result_t
2336 dns_zone_asyncload(dns_zone_t *zone, bool newonly, dns_zt_zoneloaded_t done,
2337 void *arg) {
2338 isc_event_t *e;
2339 dns_asyncload_t *asl = NULL;
2340
2341 REQUIRE(DNS_ZONE_VALID(zone));
2342
2343 if (zone->zmgr == NULL) {
2344 return (ISC_R_FAILURE);
2345 }
2346
2347 /* If we already have a load pending, stop now */
2348 LOCK_ZONE(zone);
2349 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2350 UNLOCK_ZONE(zone);
2351 return (ISC_R_ALREADYRUNNING);
2352 }
2353
2354 asl = isc_mem_get(zone->mctx, sizeof(*asl));
2355
2356 asl->zone = NULL;
2357 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2358 asl->loaded = done;
2359 asl->loaded_arg = arg;
2360
2361 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr, DNS_EVENT_ZONELOAD,
2362 zone_asyncload, asl, sizeof(isc_event_t));
2363
2364 zone_iattach(zone, &asl->zone);
2365 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2366 isc_task_send(zone->loadtask, &e);
2367 UNLOCK_ZONE(zone);
2368
2369 return (ISC_R_SUCCESS);
2370 }
2371
2372 bool
2373 dns__zone_loadpending(dns_zone_t *zone) {
2374 REQUIRE(DNS_ZONE_VALID(zone));
2375
2376 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2377 }
2378
2379 isc_result_t
2380 dns_zone_loadandthaw(dns_zone_t *zone) {
2381 isc_result_t result;
2382
2383 if (inline_raw(zone)) {
2384 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW, false);
2385 } else {
2386 /*
2387 * When thawing a zone, we don't know what changes
2388 * have been made. If we do DNSSEC maintenance on this
2389 * zone, schedule a full sign for this zone.
2390 */
2391 if (zone->type == dns_zone_master &&
2392 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
2393 {
2394 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
2395 }
2396 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2397 }
2398
2399 switch (result) {
2400 case DNS_R_CONTINUE:
2401 /* Deferred thaw. */
2402 break;
2403 case DNS_R_UPTODATE:
2404 case ISC_R_SUCCESS:
2405 case DNS_R_SEENINCLUDE:
2406 zone->update_disabled = false;
2407 break;
2408 case DNS_R_NOMASTERFILE:
2409 zone->update_disabled = false;
2410 break;
2411 default:
2412 /* Error, remain in disabled state. */
2413 break;
2414 }
2415 return (result);
2416 }
2417
2418 static unsigned int
2419 get_master_options(dns_zone_t *zone) {
2420 unsigned int options;
2421
2422 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2423 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2424 (zone->type == dns_zone_redirect && zone->masters == NULL))
2425 {
2426 options |= DNS_MASTER_SLAVE;
2427 }
2428 if (zone->type == dns_zone_key) {
2429 options |= DNS_MASTER_KEY;
2430 }
2431 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2432 options |= DNS_MASTER_CHECKNS;
2433 }
2434 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2435 options |= DNS_MASTER_FATALNS;
2436 }
2437 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2438 options |= DNS_MASTER_CHECKNAMES;
2439 }
2440 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2441 options |= DNS_MASTER_CHECKNAMESFAIL;
2442 }
2443 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2444 options |= DNS_MASTER_CHECKMX;
2445 }
2446 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2447 options |= DNS_MASTER_CHECKMXFAIL;
2448 }
2449 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2450 options |= DNS_MASTER_CHECKWILDCARD;
2451 }
2452 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2453 options |= DNS_MASTER_CHECKTTL;
2454 }
2455
2456 return (options);
2457 }
2458
2459 static void
2460 zone_registerinclude(const char *filename, void *arg) {
2461 isc_result_t result;
2462 dns_zone_t *zone = (dns_zone_t *)arg;
2463 dns_include_t *inc = NULL;
2464
2465 REQUIRE(DNS_ZONE_VALID(zone));
2466
2467 if (filename == NULL) {
2468 return;
2469 }
2470
2471 /*
2472 * Suppress duplicates.
2473 */
2474 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
2475 inc = ISC_LIST_NEXT(inc, link))
2476 {
2477 if (strcmp(filename, inc->name) == 0) {
2478 return;
2479 }
2480 }
2481
2482 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2483 inc->name = isc_mem_strdup(zone->mctx, filename);
2484 ISC_LINK_INIT(inc, link);
2485
2486 result = isc_file_getmodtime(filename, &inc->filetime);
2487 if (result != ISC_R_SUCCESS) {
2488 isc_time_settoepoch(&inc->filetime);
2489 }
2490
2491 ISC_LIST_APPEND(zone->newincludes, inc, link);
2492 }
2493
2494 static void
2495 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2496 dns_load_t *load = event->ev_arg;
2497 isc_result_t result = ISC_R_SUCCESS;
2498 unsigned int options;
2499
2500 REQUIRE(DNS_LOAD_VALID(load));
2501
2502 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2503 result = ISC_R_CANCELED;
2504 }
2505 isc_event_free(&event);
2506 if (result == ISC_R_CANCELED) {
2507 goto fail;
2508 }
2509
2510 options = get_master_options(load->zone);
2511
2512 result = dns_master_loadfileinc(
2513 load->zone->masterfile, dns_db_origin(load->db),
2514 dns_db_origin(load->db), load->zone->rdclass, options, 0,
2515 &load->callbacks, task, zone_loaddone, load, &load->zone->lctx,
2516 zone_registerinclude, load->zone, load->zone->mctx,
2517 load->zone->masterformat, load->zone->maxttl);
2518 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2519 result != DNS_R_SEENINCLUDE)
2520 {
2521 goto fail;
2522 }
2523 return;
2524
2525 fail:
2526 zone_loaddone(load, result);
2527 }
2528
2529 static void
2530 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2531 isc_result_t result;
2532 unsigned int soacount;
2533
2534 LOCK(&raw->lock);
2535 if (raw->db != NULL) {
2536 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2537 &rawdata->sourceserial, NULL, NULL,
2538 NULL, NULL, NULL);
2539 if (result == ISC_R_SUCCESS && soacount > 0U) {
2540 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2541 }
2542 }
2543 UNLOCK(&raw->lock);
2544 }
2545
2546 static void
2547 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2548 const char me[] = "zone_gotwritehandle";
2549 dns_zone_t *zone = event->ev_arg;
2550 isc_result_t result = ISC_R_SUCCESS;
2551 dns_dbversion_t *version = NULL;
2552 dns_masterrawheader_t rawdata;
2553 dns_db_t *db = NULL;
2554
2555 REQUIRE(DNS_ZONE_VALID(zone));
2556 INSIST(task == zone->task);
2557 ENTER;
2558
2559 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) {
2560 result = ISC_R_CANCELED;
2561 }
2562 isc_event_free(&event);
2563 if (result == ISC_R_CANCELED) {
2564 goto fail;
2565 }
2566
2567 LOCK_ZONE(zone);
2568 INSIST(zone != zone->raw);
2569 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2570 if (zone->db != NULL) {
2571 dns_db_attach(zone->db, &db);
2572 }
2573 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2574 if (db != NULL) {
2575 const dns_master_style_t *output_style;
2576 dns_db_currentversion(db, &version);
2577 dns_master_initrawheader(&rawdata);
2578 if (inline_secure(zone)) {
2579 get_raw_serial(zone->raw, &rawdata);
2580 }
2581 if (zone->type == dns_zone_key) {
2582 output_style = &dns_master_style_keyzone;
2583 } else if (zone->masterstyle != NULL) {
2584 output_style = zone->masterstyle;
2585 } else {
2586 output_style = &dns_master_style_default;
2587 }
2588 result = dns_master_dumpinc(
2589 zone->mctx, db, version, output_style, zone->masterfile,
2590 zone->task, dump_done, zone, &zone->dctx,
2591 zone->masterformat, &rawdata);
2592 dns_db_closeversion(db, &version, false);
2593 } else {
2594 result = ISC_R_CANCELED;
2595 }
2596 if (db != NULL) {
2597 dns_db_detach(&db);
2598 }
2599 UNLOCK_ZONE(zone);
2600 if (result != DNS_R_CONTINUE) {
2601 goto fail;
2602 }
2603 return;
2604
2605 fail:
2606 dump_done(zone, result);
2607 }
2608
2609 /*
2610 * Save the raw serial number for inline-signing zones.
2611 * (XXX: Other information from the header will be used
2612 * for other purposes in the future, but for now this is
2613 * all we're interested in.)
2614 */
2615 static void
2616 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2617 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0) {
2618 return;
2619 }
2620
2621 zone->sourceserial = header->sourceserial;
2622 zone->sourceserialset = true;
2623 }
2624
2625 void
2626 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2627 if (zone == NULL) {
2628 return;
2629 }
2630
2631 LOCK_ZONE(zone);
2632 zone_setrawdata(zone, header);
2633 UNLOCK_ZONE(zone);
2634 }
2635
2636 static isc_result_t
2637 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2638 const char me[] = "zone_startload";
2639 dns_load_t *load;
2640 isc_result_t result;
2641 isc_result_t tresult;
2642 unsigned int options;
2643
2644 ENTER;
2645
2646 dns_zone_rpz_enable_db(zone, db);
2647 dns_zone_catz_enable_db(zone, db);
2648
2649 options = get_master_options(zone);
2650 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2651 options |= DNS_MASTER_MANYERRORS;
2652 }
2653
2654 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2655 load = isc_mem_get(zone->mctx, sizeof(*load));
2656
2657 load->mctx = NULL;
2658 load->zone = NULL;
2659 load->db = NULL;
2660 load->loadtime = loadtime;
2661 load->magic = LOAD_MAGIC;
2662
2663 isc_mem_attach(zone->mctx, &load->mctx);
2664 zone_iattach(zone, &load->zone);
2665 dns_db_attach(db, &load->db);
2666 dns_rdatacallbacks_init(&load->callbacks);
2667 load->callbacks.rawdata = zone_setrawdata;
2668 zone_iattach(zone, &load->callbacks.zone);
2669 result = dns_db_beginload(db, &load->callbacks);
2670 if (result != ISC_R_SUCCESS) {
2671 goto cleanup;
2672 }
2673 result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2674 zone_gotreadhandle, load, &zone->readio);
2675 if (result != ISC_R_SUCCESS) {
2676 /*
2677 * We can't report multiple errors so ignore
2678 * the result of dns_db_endload().
2679 */
2680 (void)dns_db_endload(load->db, &load->callbacks);
2681 goto cleanup;
2682 } else {
2683 result = DNS_R_CONTINUE;
2684 }
2685 } else {
2686 dns_rdatacallbacks_t callbacks;
2687
2688 dns_rdatacallbacks_init(&callbacks);
2689 callbacks.rawdata = zone_setrawdata;
2690 zone_iattach(zone, &callbacks.zone);
2691 result = dns_db_beginload(db, &callbacks);
2692 if (result != ISC_R_SUCCESS) {
2693 zone_idetach(&callbacks.zone);
2694 return (result);
2695 }
2696 result = dns_master_loadfile(
2697 zone->masterfile, &zone->origin, &zone->origin,
2698 zone->rdclass, options, 0, &callbacks,
2699 zone_registerinclude, zone, zone->mctx,
2700 zone->masterformat, zone->maxttl);
2701 tresult = dns_db_endload(db, &callbacks);
2702 if (result == ISC_R_SUCCESS) {
2703 result = tresult;
2704 }
2705 zone_idetach(&callbacks.zone);
2706 }
2707
2708 return (result);
2709
2710 cleanup:
2711 load->magic = 0;
2712 dns_db_detach(&load->db);
2713 zone_idetach(&load->zone);
2714 zone_idetach(&load->callbacks.zone);
2715 isc_mem_detach(&load->mctx);
2716 isc_mem_put(zone->mctx, load, sizeof(*load));
2717 return (result);
2718 }
2719
2720 static bool
2721 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2722 dns_name_t *owner) {
2723 isc_result_t result;
2724 char ownerbuf[DNS_NAME_FORMATSIZE];
2725 char namebuf[DNS_NAME_FORMATSIZE];
2726 char altbuf[DNS_NAME_FORMATSIZE];
2727 dns_fixedname_t fixed;
2728 dns_name_t *foundname;
2729 int level;
2730
2731 /*
2732 * "." means the services does not exist.
2733 */
2734 if (dns_name_equal(name, dns_rootname)) {
2735 return (true);
2736 }
2737
2738 /*
2739 * Outside of zone.
2740 */
2741 if (!dns_name_issubdomain(name, &zone->origin)) {
2742 if (zone->checkmx != NULL) {
2743 return ((zone->checkmx)(zone, name, owner));
2744 }
2745 return (true);
2746 }
2747
2748 if (zone->type == dns_zone_master) {
2749 level = ISC_LOG_ERROR;
2750 } else {
2751 level = ISC_LOG_WARNING;
2752 }
2753
2754 foundname = dns_fixedname_initname(&fixed);
2755
2756 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2757 foundname, NULL, NULL);
2758 if (result == ISC_R_SUCCESS) {
2759 return (true);
2760 }
2761
2762 if (result == DNS_R_NXRRSET) {
2763 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2764 NULL, foundname, NULL, NULL);
2765 if (result == ISC_R_SUCCESS) {
2766 return (true);
2767 }
2768 }
2769
2770 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2771 dns_name_format(name, namebuf, sizeof namebuf);
2772 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2773 result == DNS_R_EMPTYNAME)
2774 {
2775 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2776 level = ISC_LOG_WARNING;
2777 }
2778 dns_zone_log(zone, level,
2779 "%s/MX '%s' has no address records (A or AAAA)",
2780 ownerbuf, namebuf);
2781 return ((level == ISC_LOG_WARNING) ? true : false);
2782 }
2783
2784 if (result == DNS_R_CNAME) {
2785 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2786 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2787 {
2788 level = ISC_LOG_WARNING;
2789 }
2790 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2791 dns_zone_log(zone, level,
2792 "%s/MX '%s' is a CNAME (illegal)",
2793 ownerbuf, namebuf);
2794 }
2795 return ((level == ISC_LOG_WARNING) ? true : false);
2796 }
2797
2798 if (result == DNS_R_DNAME) {
2799 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2800 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2801 {
2802 level = ISC_LOG_WARNING;
2803 }
2804 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2805 dns_name_format(foundname, altbuf, sizeof altbuf);
2806 dns_zone_log(zone, level,
2807 "%s/MX '%s' is below a DNAME"
2808 " '%s' (illegal)",
2809 ownerbuf, namebuf, altbuf);
2810 }
2811 return ((level == ISC_LOG_WARNING) ? true : false);
2812 }
2813
2814 if (zone->checkmx != NULL && result == DNS_R_DELEGATION) {
2815 return ((zone->checkmx)(zone, name, owner));
2816 }
2817
2818 return (true);
2819 }
2820
2821 static bool
2822 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2823 dns_name_t *owner) {
2824 isc_result_t result;
2825 char ownerbuf[DNS_NAME_FORMATSIZE];
2826 char namebuf[DNS_NAME_FORMATSIZE];
2827 char altbuf[DNS_NAME_FORMATSIZE];
2828 dns_fixedname_t fixed;
2829 dns_name_t *foundname;
2830 int level;
2831
2832 /*
2833 * "." means the services does not exist.
2834 */
2835 if (dns_name_equal(name, dns_rootname)) {
2836 return (true);
2837 }
2838
2839 /*
2840 * Outside of zone.
2841 */
2842 if (!dns_name_issubdomain(name, &zone->origin)) {
2843 if (zone->checksrv != NULL) {
2844 return ((zone->checksrv)(zone, name, owner));
2845 }
2846 return (true);
2847 }
2848
2849 if (zone->type == dns_zone_master) {
2850 level = ISC_LOG_ERROR;
2851 } else {
2852 level = ISC_LOG_WARNING;
2853 }
2854
2855 foundname = dns_fixedname_initname(&fixed);
2856
2857 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2858 foundname, NULL, NULL);
2859 if (result == ISC_R_SUCCESS) {
2860 return (true);
2861 }
2862
2863 if (result == DNS_R_NXRRSET) {
2864 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa, 0, 0,
2865 NULL, foundname, NULL, NULL);
2866 if (result == ISC_R_SUCCESS) {
2867 return (true);
2868 }
2869 }
2870
2871 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2872 dns_name_format(name, namebuf, sizeof namebuf);
2873 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2874 result == DNS_R_EMPTYNAME)
2875 {
2876 dns_zone_log(zone, level,
2877 "%s/SRV '%s' has no address records (A or AAAA)",
2878 ownerbuf, namebuf);
2879 /* XXX950 make fatal for 9.5.0. */
2880 return (true);
2881 }
2882
2883 if (result == DNS_R_CNAME) {
2884 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2885 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2886 {
2887 level = ISC_LOG_WARNING;
2888 }
2889 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2890 dns_zone_log(zone, level,
2891 "%s/SRV '%s' is a CNAME (illegal)",
2892 ownerbuf, namebuf);
2893 }
2894 return ((level == ISC_LOG_WARNING) ? true : false);
2895 }
2896
2897 if (result == DNS_R_DNAME) {
2898 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2899 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2900 {
2901 level = ISC_LOG_WARNING;
2902 }
2903 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2904 dns_name_format(foundname, altbuf, sizeof altbuf);
2905 dns_zone_log(zone, level,
2906 "%s/SRV '%s' is below a "
2907 "DNAME '%s' (illegal)",
2908 ownerbuf, namebuf, altbuf);
2909 }
2910 return ((level == ISC_LOG_WARNING) ? true : false);
2911 }
2912
2913 if (zone->checksrv != NULL && result == DNS_R_DELEGATION) {
2914 return ((zone->checksrv)(zone, name, owner));
2915 }
2916
2917 return (true);
2918 }
2919
2920 static bool
2921 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2922 dns_name_t *owner) {
2923 bool answer = true;
2924 isc_result_t result, tresult;
2925 char ownerbuf[DNS_NAME_FORMATSIZE];
2926 char namebuf[DNS_NAME_FORMATSIZE];
2927 char altbuf[DNS_NAME_FORMATSIZE];
2928 dns_fixedname_t fixed;
2929 dns_name_t *foundname;
2930 dns_rdataset_t a;
2931 dns_rdataset_t aaaa;
2932 int level;
2933
2934 /*
2935 * Outside of zone.
2936 */
2937 if (!dns_name_issubdomain(name, &zone->origin)) {
2938 if (zone->checkns != NULL) {
2939 return ((zone->checkns)(zone, name, owner, NULL, NULL));
2940 }
2941 return (true);
2942 }
2943
2944 if (zone->type == dns_zone_master) {
2945 level = ISC_LOG_ERROR;
2946 } else {
2947 level = ISC_LOG_WARNING;
2948 }
2949
2950 foundname = dns_fixedname_initname(&fixed);
2951 dns_rdataset_init(&a);
2952 dns_rdataset_init(&aaaa);
2953
2954 /*
2955 * Perform a regular lookup to catch DNAME records then look
2956 * for glue.
2957 */
2958 result = dns_db_find(db, name, NULL, dns_rdatatype_a, 0, 0, NULL,
2959 foundname, &a, NULL);
2960 switch (result) {
2961 case ISC_R_SUCCESS:
2962 case DNS_R_DNAME:
2963 case DNS_R_CNAME:
2964 break;
2965 default:
2966 if (dns_rdataset_isassociated(&a)) {
2967 dns_rdataset_disassociate(&a);
2968 }
2969 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2970 DNS_DBFIND_GLUEOK, 0, NULL, foundname, &a,
2971 NULL);
2972 }
2973 if (result == ISC_R_SUCCESS) {
2974 dns_rdataset_disassociate(&a);
2975 return (true);
2976 } else if (result == DNS_R_DELEGATION) {
2977 dns_rdataset_disassociate(&a);
2978 }
2979
2980 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2981 result == DNS_R_GLUE)
2982 {
2983 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2984 DNS_DBFIND_GLUEOK, 0, NULL, foundname,
2985 &aaaa, NULL);
2986 if (tresult == ISC_R_SUCCESS) {
2987 if (dns_rdataset_isassociated(&a)) {
2988 dns_rdataset_disassociate(&a);
2989 }
2990 dns_rdataset_disassociate(&aaaa);
2991 return (true);
2992 }
2993 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME) {
2994 dns_rdataset_disassociate(&aaaa);
2995 }
2996 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2997 /*
2998 * Check glue against child zone.
2999 */
3000 if (zone->checkns != NULL) {
3001 answer = (zone->checkns)(zone, name, owner, &a,
3002 &aaaa);
3003 }
3004 if (dns_rdataset_isassociated(&a)) {
3005 dns_rdataset_disassociate(&a);
3006 }
3007 if (dns_rdataset_isassociated(&aaaa)) {
3008 dns_rdataset_disassociate(&aaaa);
3009 }
3010 return (answer);
3011 }
3012 }
3013
3014 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
3015 dns_name_format(name, namebuf, sizeof namebuf);
3016 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
3017 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION)
3018 {
3019 const char *what;
3020 bool required = false;
3021 if (dns_name_issubdomain(name, owner)) {
3022 what = "REQUIRED GLUE ";
3023 required = true;
3024 } else if (result == DNS_R_DELEGATION) {
3025 what = "SIBLING GLUE ";
3026 } else {
3027 what = "";
3028 }
3029
3030 if (result != DNS_R_DELEGATION || required ||
3031 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING))
3032 {
3033 dns_zone_log(zone, level,
3034 "%s/NS '%s' has no %s"
3035 "address records (A or AAAA)",
3036 ownerbuf, namebuf, what);
3037 /*
3038 * Log missing address record.
3039 */
3040 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
3041 {
3042 (void)(zone->checkns)(zone, name, owner, &a,
3043 &aaaa);
3044 }
3045 /* XXX950 make fatal for 9.5.0. */
3046 /* answer = false; */
3047 }
3048 } else if (result == DNS_R_CNAME) {
3049 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
3050 ownerbuf, namebuf);
3051 /* XXX950 make fatal for 9.5.0. */
3052 /* answer = false; */
3053 } else if (result == DNS_R_DNAME) {
3054 dns_name_format(foundname, altbuf, sizeof altbuf);
3055 dns_zone_log(zone, level,
3056 "%s/NS '%s' is below a DNAME '%s' (illegal)",
3057 ownerbuf, namebuf, altbuf);
3058 /* XXX950 make fatal for 9.5.0. */
3059 /* answer = false; */
3060 }
3061
3062 if (dns_rdataset_isassociated(&a)) {
3063 dns_rdataset_disassociate(&a);
3064 }
3065 if (dns_rdataset_isassociated(&aaaa)) {
3066 dns_rdataset_disassociate(&aaaa);
3067 }
3068 return (answer);
3069 }
3070
3071 static bool
3072 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
3073 dns_rdataset_t *rdataset) {
3074 dns_rdataset_t tmprdataset;
3075 isc_result_t result;
3076 bool answer = true;
3077 bool format = true;
3078 int level = ISC_LOG_WARNING;
3079 char ownerbuf[DNS_NAME_FORMATSIZE];
3080 char typebuf[DNS_RDATATYPE_FORMATSIZE];
3081 unsigned int count1 = 0;
3082
3083 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL)) {
3084 level = ISC_LOG_ERROR;
3085 }
3086
3087 dns_rdataset_init(&tmprdataset);
3088 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
3089 result = dns_rdataset_next(rdataset))
3090 {
3091 dns_rdata_t rdata1 = DNS_RDATA_INIT;
3092 unsigned int count2 = 0;
3093
3094 count1++;
3095 dns_rdataset_current(rdataset, &rdata1);
3096 dns_rdataset_clone(rdataset, &tmprdataset);
3097 for (result = dns_rdataset_first(&tmprdataset);
3098 result == ISC_R_SUCCESS;
3099 result = dns_rdataset_next(&tmprdataset))
3100 {
3101 dns_rdata_t rdata2 = DNS_RDATA_INIT;
3102 count2++;
3103 if (count1 >= count2) {
3104 continue;
3105 }
3106 dns_rdataset_current(&tmprdataset, &rdata2);
3107 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
3108 if (format) {
3109 dns_name_format(owner, ownerbuf,
3110 sizeof ownerbuf);
3111 dns_rdatatype_format(rdata1.type,
3112 typebuf,
3113 sizeof(typebuf));
3114 format = false;
3115 }
3116 dns_zone_log(zone, level,
3117 "%s/%s has "
3118 "semantically identical records",
3119 ownerbuf, typebuf);
3120 if (level == ISC_LOG_ERROR) {
3121 answer = false;
3122 }
3123 break;
3124 }
3125 }
3126 dns_rdataset_disassociate(&tmprdataset);
3127 if (!format) {
3128 break;
3129 }
3130 }
3131 return (answer);
3132 }
3133
3134 static bool
3135 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
3136 dns_dbiterator_t *dbiterator = NULL;
3137 dns_dbnode_t *node = NULL;
3138 dns_fixedname_t fixed;
3139 dns_name_t *name;
3140 dns_rdataset_t rdataset;
3141 dns_rdatasetiter_t *rdsit = NULL;
3142 bool ok = true;
3143 isc_result_t result;
3144
3145 name = dns_fixedname_initname(&fixed);
3146 dns_rdataset_init(&rdataset);
3147
3148 result = dns_db_createiterator(db, 0, &dbiterator);
3149 if (result != ISC_R_SUCCESS) {
3150 return (true);
3151 }
3152
3153 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
3154 result = dns_dbiterator_next(dbiterator))
3155 {
3156 result = dns_dbiterator_current(dbiterator, &node, name);
3157 if (result != ISC_R_SUCCESS) {
3158 continue;
3159 }
3160
3161 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
3162 if (result != ISC_R_SUCCESS) {
3163 continue;
3164 }
3165
3166 for (result = dns_rdatasetiter_first(rdsit);
3167 result == ISC_R_SUCCESS;
3168 result = dns_rdatasetiter_next(rdsit))
3169 {
3170 dns_rdatasetiter_current(rdsit, &rdataset);
3171 if (!zone_rrset_check_dup(zone, name, &rdataset)) {
3172 ok = false;
3173 }
3174 dns_rdataset_disassociate(&rdataset);
3175 }
3176 dns_rdatasetiter_destroy(&rdsit);
3177 dns_db_detachnode(db, &node);
3178 }
3179
3180 if (node != NULL) {
3181 dns_db_detachnode(db, &node);
3182 }
3183 dns_dbiterator_destroy(&dbiterator);
3184
3185 return (ok);
3186 }
3187
3188 static bool
3189 isspf(const dns_rdata_t *rdata) {
3190 char buf[1024];
3191 const unsigned char *data = rdata->data;
3192 unsigned int rdl = rdata->length, i = 0, tl, len;
3193
3194 while (rdl > 0U) {
3195 len = tl = *data;
3196 ++data;
3197 --rdl;
3198 INSIST(tl <= rdl);
3199 if (len > sizeof(buf) - i - 1) {
3200 len = sizeof(buf) - i - 1;
3201 }
3202 memmove(buf + i, data, len);
3203 i += len;
3204 data += tl;
3205 rdl -= tl;
3206 }
3207
3208 if (i < 6U) {
3209 return (false);
3210 }
3211
3212 buf[i] = 0;
3213 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' ')) {
3214 return (true);
3215 }
3216 return (false);
3217 }
3218
3219 static bool
3220 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3221 dns_dbiterator_t *dbiterator = NULL;
3222 dns_dbnode_t *node = NULL;
3223 dns_rdataset_t rdataset;
3224 dns_fixedname_t fixed;
3225 dns_fixedname_t fixedbottom;
3226 dns_rdata_mx_t mx;
3227 dns_rdata_ns_t ns;
3228 dns_rdata_in_srv_t srv;
3229 dns_rdata_t rdata;
3230 dns_name_t *name;
3231 dns_name_t *bottom;
3232 isc_result_t result;
3233 bool ok = true, have_spf, have_txt;
3234
3235 name = dns_fixedname_initname(&fixed);
3236 bottom = dns_fixedname_initname(&fixedbottom);
3237 dns_rdataset_init(&rdataset);
3238 dns_rdata_init(&rdata);
3239
3240 result = dns_db_createiterator(db, 0, &dbiterator);
3241 if (result != ISC_R_SUCCESS) {
3242 return (true);
3243 }
3244
3245 result = dns_dbiterator_first(dbiterator);
3246 while (result == ISC_R_SUCCESS) {
3247 result = dns_dbiterator_current(dbiterator, &node, name);
3248 if (result != ISC_R_SUCCESS) {
3249 goto cleanup;
3250 }
3251
3252 /*
3253 * Is this name visible in the zone?
3254 */
3255 if (!dns_name_issubdomain(name, &zone->origin) ||
3256 (dns_name_countlabels(bottom) > 0 &&
3257 dns_name_issubdomain(name, bottom)))
3258 {
3259 goto next;
3260 }
3261
3262 /*
3263 * Don't check the NS records at the origin.
3264 */
3265 if (dns_name_equal(name, &zone->origin)) {
3266 goto checkfordname;
3267 }
3268
3269 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3270 0, 0, &rdataset, NULL);
3271 if (result != ISC_R_SUCCESS) {
3272 goto checkfordname;
3273 }
3274 /*
3275 * Remember bottom of zone due to NS.
3276 */
3277 dns_name_copynf(name, bottom);
3278
3279 result = dns_rdataset_first(&rdataset);
3280 while (result == ISC_R_SUCCESS) {
3281 dns_rdataset_current(&rdataset, &rdata);
3282 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3283 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3284 if (!zone_check_glue(zone, db, &ns.name, name)) {
3285 ok = false;
3286 }
3287 dns_rdata_reset(&rdata);
3288 result = dns_rdataset_next(&rdataset);
3289 }
3290 dns_rdataset_disassociate(&rdataset);
3291 goto next;
3292
3293 checkfordname:
3294 result = dns_db_findrdataset(db, node, NULL,
3295 dns_rdatatype_dname, 0, 0,
3296 &rdataset, NULL);
3297 if (result == ISC_R_SUCCESS) {
3298 /*
3299 * Remember bottom of zone due to DNAME.
3300 */
3301 dns_name_copynf(name, bottom);
3302 dns_rdataset_disassociate(&rdataset);
3303 }
3304
3305 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3306 0, 0, &rdataset, NULL);
3307 if (result != ISC_R_SUCCESS) {
3308 goto checksrv;
3309 }
3310 result = dns_rdataset_first(&rdataset);
3311 while (result == ISC_R_SUCCESS) {
3312 dns_rdataset_current(&rdataset, &rdata);
3313 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3314 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3315 if (!zone_check_mx(zone, db, &mx.mx, name)) {
3316 ok = false;
3317 }
3318 dns_rdata_reset(&rdata);
3319 result = dns_rdataset_next(&rdataset);
3320 }
3321 dns_rdataset_disassociate(&rdataset);
3322
3323 checksrv:
3324 if (zone->rdclass != dns_rdataclass_in) {
3325 goto next;
3326 }
3327 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3328 0, 0, &rdataset, NULL);
3329 if (result != ISC_R_SUCCESS) {
3330 goto checkspf;
3331 }
3332 result = dns_rdataset_first(&rdataset);
3333 while (result == ISC_R_SUCCESS) {
3334 dns_rdataset_current(&rdataset, &rdata);
3335 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3336 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3337 if (!zone_check_srv(zone, db, &srv.target, name)) {
3338 ok = false;
3339 }
3340 dns_rdata_reset(&rdata);
3341 result = dns_rdataset_next(&rdataset);
3342 }
3343 dns_rdataset_disassociate(&rdataset);
3344
3345 checkspf:
3346 /*
3347 * Check if there is a type SPF record without an
3348 * SPF-formatted type TXT record also being present.
3349 */
3350 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF)) {
3351 goto next;
3352 }
3353 if (zone->rdclass != dns_rdataclass_in) {
3354 goto next;
3355 }
3356 have_spf = have_txt = false;
3357 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3358 0, 0, &rdataset, NULL);
3359 if (result == ISC_R_SUCCESS) {
3360 dns_rdataset_disassociate(&rdataset);
3361 have_spf = true;
3362 }
3363 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3364 0, 0, &rdataset, NULL);
3365 if (result != ISC_R_SUCCESS) {
3366 goto notxt;
3367 }
3368 result = dns_rdataset_first(&rdataset);
3369 while (result == ISC_R_SUCCESS) {
3370 dns_rdataset_current(&rdataset, &rdata);
3371 have_txt = isspf(&rdata);
3372 dns_rdata_reset(&rdata);
3373 if (have_txt) {
3374 break;
3375 }
3376 result = dns_rdataset_next(&rdataset);
3377 }
3378 dns_rdataset_disassociate(&rdataset);
3379
3380 notxt:
3381 if (have_spf && !have_txt) {
3382 char namebuf[DNS_NAME_FORMATSIZE];
3383
3384 dns_name_format(name, namebuf, sizeof(namebuf));
3385 dns_zone_log(zone, ISC_LOG_WARNING,
3386 "'%s' found type "
3387 "SPF record but no SPF TXT record found, "
3388 "add matching type TXT record",
3389 namebuf);
3390 }
3391
3392 next:
3393 dns_db_detachnode(db, &node);
3394 result = dns_dbiterator_next(dbiterator);
3395 }
3396
3397 cleanup:
3398 if (node != NULL) {
3399 dns_db_detachnode(db, &node);
3400 }
3401 dns_dbiterator_destroy(&dbiterator);
3402
3403 return (ok);
3404 }
3405
3406 /*
3407 * OpenSSL verification of RSA keys with exponent 3 is known to be
3408 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3409 * if they are in use.
3410 */
3411 static void
3412 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3413 dns_dbnode_t *node = NULL;
3414 dns_dbversion_t *version = NULL;
3415 dns_rdata_dnskey_t dnskey;
3416 dns_rdata_t rdata = DNS_RDATA_INIT;
3417 dns_rdataset_t rdataset;
3418 isc_result_t result;
3419
3420 result = dns_db_findnode(db, &zone->origin, false, &node);
3421 if (result != ISC_R_SUCCESS) {
3422 goto cleanup;
3423 }
3424
3425 dns_db_currentversion(db, &version);
3426 dns_rdataset_init(&rdataset);
3427 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3428 dns_rdatatype_none, 0, &rdataset, NULL);
3429 if (result != ISC_R_SUCCESS) {
3430 goto cleanup;
3431 }
3432
3433 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3434 result = dns_rdataset_next(&rdataset))
3435 {
3436 dns_rdataset_current(&rdataset, &rdata);
3437 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3438 INSIST(result == ISC_R_SUCCESS);
3439
3440 /* RFC 3110, section 4: Performance Considerations:
3441 *
3442 * A public exponent of 3 minimizes the effort needed to verify
3443 * a signature. Use of 3 as the public exponent is weak for
3444 * confidentiality uses since, if the same data can be collected
3445 * encrypted under three different keys with an exponent of 3
3446 * then, using the Chinese Remainder Theorem [NETSEC], the
3447 * original plain text can be easily recovered. If a key is
3448 * known to be used only for authentication, as is the case with
3449 * DNSSEC, then an exponent of 3 is acceptable. However other
3450 * applications in the future may wish to leverage DNS
3451 * distributed keys for applications that do require
3452 * confidentiality. For keys which might have such other uses,
3453 * a more conservative choice would be 65537 (F4, the fourth
3454 * fermat number).
3455 */
3456 if (dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3457 dnskey.data[1] == 3) {
3458 const char *algorithm = "";
3459 isc_region_t r;
3460 bool logit = true;
3461
3462 dns_rdata_toregion(&rdata, &r);
3463
3464 switch (dnskey.algorithm) {
3465 case DNS_KEYALG_RSAMD5:
3466 algorithm = "RSAMD5";
3467 break;
3468 case DNS_KEYALG_RSASHA1:
3469 algorithm = "RSASHA1";
3470 break;
3471 case DNS_KEYALG_NSEC3RSASHA1:
3472 algorithm = "NSEC3RSASHA1";
3473 break;
3474 case DNS_KEYALG_RSASHA256:
3475 algorithm = "RSASHA236";
3476 break;
3477 case DNS_KEYALG_RSASHA512:
3478 algorithm = "RSASHA512";
3479 break;
3480 default:
3481 logit = false;
3482 break;
3483 }
3484
3485 if (logit) {
3486 dnssec_log(zone, ISC_LOG_WARNING,
3487 "weak %s (%u) key found "
3488 "(exponent=3, id=%u)",
3489 algorithm, dnskey.algorithm,
3490 dst_region_computeid(&r));
3491 }
3492 }
3493 dns_rdata_reset(&rdata);
3494 }
3495 dns_rdataset_disassociate(&rdataset);
3496
3497 cleanup:
3498 if (node != NULL) {
3499 dns_db_detachnode(db, &node);
3500 }
3501 if (version != NULL) {
3502 dns_db_closeversion(db, &version, false);
3503 }
3504 }
3505
3506 static void
3507 resume_signingwithkey(dns_zone_t *zone) {
3508 dns_dbnode_t *node = NULL;
3509 dns_dbversion_t *version = NULL;
3510 dns_rdata_t rdata = DNS_RDATA_INIT;
3511 dns_rdataset_t rdataset;
3512 isc_result_t result;
3513 dns_db_t *db = NULL;
3514
3515 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3516 if (zone->db != NULL) {
3517 dns_db_attach(zone->db, &db);
3518 }
3519 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3520 if (db == NULL) {
3521 goto cleanup;
3522 }
3523
3524 result = dns_db_findnode(db, &zone->origin, false, &node);
3525 if (result != ISC_R_SUCCESS) {
3526 goto cleanup;
3527 }
3528
3529 dns_db_currentversion(db, &version);
3530 dns_rdataset_init(&rdataset);
3531 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3532 dns_rdatatype_none, 0, &rdataset, NULL);
3533 if (result != ISC_R_SUCCESS) {
3534 INSIST(!dns_rdataset_isassociated(&rdataset));
3535 goto cleanup;
3536 }
3537
3538 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3539 result = dns_rdataset_next(&rdataset))
3540 {
3541 dns_rdataset_current(&rdataset, &rdata);
3542 if (rdata.length != 5 || rdata.data[0] == 0 ||
3543 rdata.data[4] != 0) {
3544 dns_rdata_reset(&rdata);
3545 continue;
3546 }
3547
3548 result = zone_signwithkey(zone, rdata.data[0],
3549 (rdata.data[1] << 8) | rdata.data[2],
3550 rdata.data[3]);
3551 if (result != ISC_R_SUCCESS) {
3552 dnssec_log(zone, ISC_LOG_ERROR,
3553 "zone_signwithkey failed: %s",
3554 dns_result_totext(result));
3555 }
3556 dns_rdata_reset(&rdata);
3557 }
3558 dns_rdataset_disassociate(&rdataset);
3559
3560 cleanup:
3561 if (db != NULL) {
3562 if (node != NULL) {
3563 dns_db_detachnode(db, &node);
3564 }
3565 if (version != NULL) {
3566 dns_db_closeversion(db, &version, false);
3567 }
3568 dns_db_detach(&db);
3569 }
3570 }
3571
3572 /*
3573 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3574 * supplied NSEC3PARAM RDATA.
3575 *
3576 * Zone must be locked by caller.
3577 */
3578 static isc_result_t
3579 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3580 dns_nsec3chain_t *nsec3chain, *current;
3581 dns_dbversion_t *version = NULL;
3582 bool nseconly = false, nsec3ok = false;
3583 isc_result_t result;
3584 isc_time_t now;
3585 unsigned int options = 0;
3586 char saltbuf[255 * 2 + 1];
3587 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3588 dns_db_t *db = NULL;
3589
3590 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3591 if (zone->db != NULL) {
3592 dns_db_attach(zone->db, &db);
3593 }
3594 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3595
3596 if (db == NULL) {
3597 result = ISC_R_SUCCESS;
3598 goto cleanup;
3599 }
3600
3601 /*
3602 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3603 * chain from it is pointless as it would not be possible for the
3604 * latter to exist in the first place.
3605 */
3606 dns_db_currentversion(db, &version);
3607 result = dns_nsec_nseconly(db, version, &nseconly);
3608 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3609 dns_db_closeversion(db, &version, false);
3610 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3611 result = ISC_R_SUCCESS;
3612 goto cleanup;
3613 }
3614
3615 /*
3616 * Allocate and initialize structure preserving state of
3617 * adding/removing records belonging to this NSEC3 chain between
3618 * separate zone_nsec3chain() calls.
3619 */
3620 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3621
3622 nsec3chain->magic = 0;
3623 nsec3chain->done = false;
3624 nsec3chain->db = NULL;
3625 nsec3chain->dbiterator = NULL;
3626 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3627 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3628 nsec3chain->nsec3param.hash = nsec3param->hash;
3629 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3630 nsec3chain->nsec3param.flags = nsec3param->flags;
3631 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3632 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3633 nsec3chain->nsec3param.salt = nsec3chain->salt;
3634 nsec3chain->seen_nsec = false;
3635 nsec3chain->delete_nsec = false;
3636 nsec3chain->save_delete_nsec = false;
3637
3638 /*
3639 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3640 */
3641 if (nsec3param->flags == 0) {
3642 strlcpy(flags, "NONE", sizeof(flags));
3643 } else {
3644 flags[0] = '\0';
3645 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3646 strlcat(flags, "REMOVE", sizeof(flags));
3647 }
3648 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3649 if (flags[0] == '\0') {
3650 strlcpy(flags, "INITIAL", sizeof(flags));
3651 } else {
3652 strlcat(flags, "|INITIAL", sizeof(flags));
3653 }
3654 }
3655 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3656 if (flags[0] == '\0') {
3657 strlcpy(flags, "CREATE", sizeof(flags));
3658 } else {
3659 strlcat(flags, "|CREATE", sizeof(flags));
3660 }
3661 }
3662 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3663 if (flags[0] == '\0') {
3664 strlcpy(flags, "NONSEC", sizeof(flags));
3665 } else {
3666 strlcat(flags, "|NONSEC", sizeof(flags));
3667 }
3668 }
3669 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3670 if (flags[0] == '\0') {
3671 strlcpy(flags, "OPTOUT", sizeof(flags));
3672 } else {
3673 strlcat(flags, "|OPTOUT", sizeof(flags));
3674 }
3675 }
3676 }
3677 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3678 sizeof(saltbuf));
3679 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3680 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3681 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3682
3683 /*
3684 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3685 * currently being processed, interrupt its processing to avoid
3686 * simultaneously adding and removing records for the same NSEC3 chain.
3687 */
3688 for (current = ISC_LIST_HEAD(zone->nsec3chain); current != NULL;
3689 current = ISC_LIST_NEXT(current, link))
3690 {
3691 if ((current->db == db) &&
3692 (current->nsec3param.hash == nsec3param->hash) &&
3693 (current->nsec3param.iterations ==
3694 nsec3param->iterations) &&
3695 (current->nsec3param.salt_length ==
3696 nsec3param->salt_length) &&
3697 memcmp(current->nsec3param.salt, nsec3param->salt,
3698 nsec3param->salt_length) == 0)
3699 {
3700 current->done = true;
3701 }
3702 }
3703
3704 /*
3705 * Attach zone database to the structure initialized above and create
3706 * an iterator for it with appropriate options in order to avoid
3707 * creating NSEC3 records for NSEC3 records.
3708 */
3709 dns_db_attach(db, &nsec3chain->db);
3710 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3711 options = DNS_DB_NONSEC3;
3712 }
3713 result = dns_db_createiterator(nsec3chain->db, options,
3714 &nsec3chain->dbiterator);
3715 if (result == ISC_R_SUCCESS) {
3716 result = dns_dbiterator_first(nsec3chain->dbiterator);
3717 }
3718 if (result == ISC_R_SUCCESS) {
3719 /*
3720 * Database iterator initialization succeeded. We are now
3721 * ready to kick off adding/removing records belonging to this
3722 * NSEC3 chain. Append the structure initialized above to the
3723 * "nsec3chain" list for the zone and set the appropriate zone
3724 * timer so that zone_nsec3chain() is called as soon as
3725 * possible.
3726 */
3727 dns_dbiterator_pause(nsec3chain->dbiterator);
3728 ISC_LIST_INITANDAPPEND(zone->nsec3chain, nsec3chain, link);
3729 nsec3chain = NULL;
3730 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3731 TIME_NOW(&now);
3732 zone->nsec3chaintime = now;
3733 if (zone->task != NULL) {
3734 zone_settimer(zone, &now);
3735 }
3736 }
3737 }
3738
3739 if (nsec3chain != NULL) {
3740 if (nsec3chain->db != NULL) {
3741 dns_db_detach(&nsec3chain->db);
3742 }
3743 if (nsec3chain->dbiterator != NULL) {
3744 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3745 }
3746 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3747 }
3748
3749 cleanup:
3750 if (db != NULL) {
3751 dns_db_detach(&db);
3752 }
3753 return (result);
3754 }
3755
3756 /*
3757 * Find private-type records at the zone apex which signal that an NSEC3 chain
3758 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3759 * and pass it to zone_addnsec3chain().
3760 *
3761 * Zone must be locked by caller.
3762 */
3763 static void
3764 resume_addnsec3chain(dns_zone_t *zone) {
3765 dns_dbnode_t *node = NULL;
3766 dns_dbversion_t *version = NULL;
3767 dns_rdataset_t rdataset;
3768 isc_result_t result;
3769 dns_rdata_nsec3param_t nsec3param;
3770 bool nseconly = false, nsec3ok = false;
3771 dns_db_t *db = NULL;
3772
3773 INSIST(LOCKED_ZONE(zone));
3774
3775 if (zone->privatetype == 0) {
3776 return;
3777 }
3778
3779 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3780 if (zone->db != NULL) {
3781 dns_db_attach(zone->db, &db);
3782 }
3783 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3784 if (db == NULL) {
3785 goto cleanup;
3786 }
3787
3788 result = dns_db_findnode(db, &zone->origin, false, &node);
3789 if (result != ISC_R_SUCCESS) {
3790 goto cleanup;
3791 }
3792
3793 dns_db_currentversion(db, &version);
3794
3795 /*
3796 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3797 * apex to exist and contain no keys using NSEC-only algorithms.
3798 */
3799 result = dns_nsec_nseconly(db, version, &nseconly);
3800 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3801
3802 /*
3803 * Get the RRset containing all private-type records at the zone apex.
3804 */
3805 dns_rdataset_init(&rdataset);
3806 result = dns_db_findrdataset(db, node, version, zone->privatetype,
3807 dns_rdatatype_none, 0, &rdataset, NULL);
3808 if (result != ISC_R_SUCCESS) {
3809 INSIST(!dns_rdataset_isassociated(&rdataset));
3810 goto cleanup;
3811 }
3812
3813 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3814 result = dns_rdataset_next(&rdataset))
3815 {
3816 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3817 dns_rdata_t rdata = DNS_RDATA_INIT;
3818 dns_rdata_t private = DNS_RDATA_INIT;
3819
3820 dns_rdataset_current(&rdataset, &private);
3821 /*
3822 * Try extracting NSEC3PARAM RDATA from this private-type
3823 * record. Failure means this private-type record does not
3824 * represent an NSEC3PARAM record, so skip it.
3825 */
3826 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3827 sizeof(buf))) {
3828 continue;
3829 }
3830 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3831 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3832 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3833 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3834 {
3835 /*
3836 * Pass the NSEC3PARAM RDATA contained in this
3837 * private-type record to zone_addnsec3chain() so that
3838 * it can kick off adding or removing NSEC3 records.
3839 */
3840 result = zone_addnsec3chain(zone, &nsec3param);
3841 if (result != ISC_R_SUCCESS) {
3842 dnssec_log(zone, ISC_LOG_ERROR,
3843 "zone_addnsec3chain failed: %s",
3844 dns_result_totext(result));
3845 }
3846 }
3847 }
3848 dns_rdataset_disassociate(&rdataset);
3849
3850 cleanup:
3851 if (db != NULL) {
3852 if (node != NULL) {
3853 dns_db_detachnode(db, &node);
3854 }
3855 if (version != NULL) {
3856 dns_db_closeversion(db, &version, false);
3857 }
3858 dns_db_detach(&db);
3859 }
3860 }
3861
3862 static void
3863 set_resigntime(dns_zone_t *zone) {
3864 dns_rdataset_t rdataset;
3865 dns_fixedname_t fixed;
3866 unsigned int resign;
3867 isc_result_t result;
3868 uint32_t nanosecs;
3869 dns_db_t *db = NULL;
3870
3871 INSIST(LOCKED_ZONE(zone));
3872
3873 /* We only re-sign zones that can be dynamically updated */
3874 if (zone->update_disabled) {
3875 return;
3876 }
3877
3878 if (!inline_secure(zone) &&
3879 (zone->type != dns_zone_master ||
3880 (zone->ssutable == NULL &&
3881 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3882 {
3883 return;
3884 }
3885
3886 dns_rdataset_init(&rdataset);
3887 dns_fixedname_init(&fixed);
3888
3889 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3890 if (zone->db != NULL) {
3891 dns_db_attach(zone->db, &db);
3892 }
3893 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3894 if (db == NULL) {
3895 isc_time_settoepoch(&zone->resigntime);
3896 return;
3897 }
3898
3899 result = dns_db_getsigningtime(db, &rdataset,
3900 dns_fixedname_name(&fixed));
3901 if (result != ISC_R_SUCCESS) {
3902 isc_time_settoepoch(&zone->resigntime);
3903 goto cleanup;
3904 }
3905
3906 resign = rdataset.resign - dns_zone_getsigresigninginterval(zone);
3907 dns_rdataset_disassociate(&rdataset);
3908 nanosecs = isc_random_uniform(1000000000);
3909 isc_time_set(&zone->resigntime, resign, nanosecs);
3910
3911 cleanup:
3912 dns_db_detach(&db);
3913 return;
3914 }
3915
3916 static isc_result_t
3917 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3918 dns_dbnode_t *node = NULL;
3919 dns_rdataset_t rdataset;
3920 dns_dbversion_t *version = NULL;
3921 dns_rdata_nsec3param_t nsec3param;
3922 bool ok = false;
3923 isc_result_t result;
3924 dns_rdata_t rdata = DNS_RDATA_INIT;
3925 bool dynamic = (zone->type == dns_zone_master)
3926 ? dns_zone_isdynamic(zone, false)
3927 : false;
3928
3929 dns_rdataset_init(&rdataset);
3930 result = dns_db_findnode(db, &zone->origin, false, &node);
3931 if (result != ISC_R_SUCCESS) {
3932 dns_zone_log(zone, ISC_LOG_ERROR,
3933 "nsec3param lookup failure: %s",
3934 dns_result_totext(result));
3935 return (result);
3936 }
3937 dns_db_currentversion(db, &version);
3938
3939 result = dns_db_findrdataset(db, node, version,
3940 dns_rdatatype_nsec3param,
3941 dns_rdatatype_none, 0, &rdataset, NULL);
3942 if (result == ISC_R_NOTFOUND) {
3943 INSIST(!dns_rdataset_isassociated(&rdataset));
3944 result = ISC_R_SUCCESS;
3945 goto cleanup;
3946 }
3947 if (result != ISC_R_SUCCESS) {
3948 INSIST(!dns_rdataset_isassociated(&rdataset));
3949 dns_zone_log(zone, ISC_LOG_ERROR,
3950 "nsec3param lookup failure: %s",
3951 dns_result_totext(result));
3952 goto cleanup;
3953 }
3954
3955 /*
3956 * For dynamic zones we must support every algorithm so we can
3957 * regenerate all the NSEC3 chains.
3958 * For non-dynamic zones we only need to find a supported algorithm.
3959 */
3960 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
3961 result = dns_rdataset_next(&rdataset))
3962 {
3963 dns_rdataset_current(&rdataset, &rdata);
3964 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3965 dns_rdata_reset(&rdata);
3966 INSIST(result == ISC_R_SUCCESS);
3967 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3968 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3969 {
3970 dns_zone_log(zone, ISC_LOG_WARNING,
3971 "nsec3 test \"unknown\" hash algorithm "
3972 "found: %u",
3973 nsec3param.hash);
3974 ok = true;
3975 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3976 if (dynamic) {
3977 dns_zone_log(zone, ISC_LOG_ERROR,
3978 "unsupported nsec3 hash algorithm"
3979 " in dynamic zone: %u",
3980 nsec3param.hash);
3981 result = DNS_R_BADZONE;
3982 /* Stop second error message. */
3983 ok = true;
3984 break;
3985 } else {
3986 dns_zone_log(zone, ISC_LOG_WARNING,
3987 "unsupported nsec3 hash "
3988 "algorithm: %u",
3989 nsec3param.hash);
3990 }
3991 } else {
3992 ok = true;
3993 }
3994 }
3995 if (result == ISC_R_NOMORE) {
3996 result = ISC_R_SUCCESS;
3997 }
3998
3999 if (!ok) {
4000 result = DNS_R_BADZONE;
4001 dns_zone_log(zone, ISC_LOG_ERROR,
4002 "no supported nsec3 hash algorithm");
4003 }
4004
4005 cleanup:
4006 if (dns_rdataset_isassociated(&rdataset)) {
4007 dns_rdataset_disassociate(&rdataset);
4008 }
4009 dns_db_closeversion(db, &version, false);
4010 dns_db_detachnode(db, &node);
4011 return (result);
4012 }
4013
4014 /*
4015 * Set the timer for refreshing the key zone to the soonest future time
4016 * of the set (current timer, keydata->refresh, keydata->addhd,
4017 * keydata->removehd).
4018 */
4019 static void
4020 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
4021 isc_stdtime_t now, bool force) {
4022 const char me[] = "set_refreshkeytimer";
4023 isc_stdtime_t then;
4024 isc_time_t timenow, timethen;
4025 char timebuf[80];
4026
4027 ENTER;
4028 then = key->refresh;
4029 if (force) {
4030 then = now;
4031 }
4032 if (key->addhd > now && key->addhd < then) {
4033 then = key->addhd;
4034 }
4035 if (key->removehd > now && key->removehd < then) {
4036 then = key->removehd;
4037 }
4038
4039 TIME_NOW(&timenow);
4040 if (then > now) {
4041 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
4042 } else {
4043 timethen = timenow;
4044 }
4045 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
4046 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
4047 {
4048 zone->refreshkeytime = timethen;
4049 }
4050
4051 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
4052 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
4053 zone_settimer(zone, &timenow);
4054 }
4055
4056 /*
4057 * If keynode references a key or a DS rdataset, and if the key
4058 * zone does not contain a KEYDATA record for the corresponding name,
4059 * then create an empty KEYDATA and push it into the zone as a placeholder,
4060 * then schedule a key refresh immediately. This new KEYDATA record will be
4061 * updated during the refresh.
4062 *
4063 * If the key zone is changed, set '*changed' to true.
4064 */
4065 static isc_result_t
4066 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4067 dns_diff_t *diff, dns_keynode_t *keynode, dns_name_t *keyname,
4068 bool *changed) {
4069 const char me[] = "create_keydata";
4070 isc_result_t result = ISC_R_SUCCESS;
4071 dns_rdata_t rdata = DNS_RDATA_INIT;
4072 dns_rdata_keydata_t kd;
4073 unsigned char rrdata[4096];
4074 isc_buffer_t rrdatabuf;
4075 isc_stdtime_t now;
4076
4077 REQUIRE(keynode != NULL);
4078
4079 ENTER;
4080 isc_stdtime_get(&now);
4081
4082 /*
4083 * If the keynode has no trust anchor set, we shouldn't be here.
4084 */
4085 if (!dns_keynode_dsset(keynode, NULL)) {
4086 return (ISC_R_FAILURE);
4087 }
4088
4089 memset(&kd, 0, sizeof(kd));
4090 kd.common.rdclass = zone->rdclass;
4091 kd.common.rdtype = dns_rdatatype_keydata;
4092 ISC_LINK_INIT(&kd.common, link);
4093
4094 isc_buffer_init(&rrdatabuf, rrdata, sizeof(rrdata));
4095
4096 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass, dns_rdatatype_keydata,
4097 &kd, &rrdatabuf));
4098 /* Add rdata to zone. */
4099 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, keyname, 0, &rdata));
4100 *changed = true;
4101
4102 /* Refresh new keys from the zone apex as soon as possible. */
4103 set_refreshkeytimer(zone, &kd, now, true);
4104 return (ISC_R_SUCCESS);
4105
4106 failure:
4107 return (result);
4108 }
4109
4110 /*
4111 * Remove from the key zone all the KEYDATA records found in rdataset.
4112 */
4113 static isc_result_t
4114 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4115 dns_name_t *name, dns_rdataset_t *rdataset) {
4116 dns_rdata_t rdata = DNS_RDATA_INIT;
4117 isc_result_t result, uresult;
4118
4119 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4120 result = dns_rdataset_next(rdataset))
4121 {
4122 dns_rdata_reset(&rdata);
4123 dns_rdataset_current(rdataset, &rdata);
4124 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name, 0,
4125 &rdata);
4126 if (uresult != ISC_R_SUCCESS) {
4127 return (uresult);
4128 }
4129 }
4130 if (result == ISC_R_NOMORE) {
4131 result = ISC_R_SUCCESS;
4132 }
4133 return (result);
4134 }
4135
4136 /*
4137 * Compute the DNSSEC key ID for a DNSKEY record.
4138 */
4139 static isc_result_t
4140 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
4141 dns_keytag_t *tag) {
4142 isc_result_t result;
4143 dns_rdata_t rdata = DNS_RDATA_INIT;
4144 unsigned char data[4096];
4145 isc_buffer_t buffer;
4146 dst_key_t *dstkey = NULL;
4147
4148 isc_buffer_init(&buffer, data, sizeof(data));
4149 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4150 dns_rdatatype_dnskey, dnskey, &buffer);
4151
4152 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
4153 if (result == ISC_R_SUCCESS) {
4154 *tag = dst_key_id(dstkey);
4155 dst_key_free(&dstkey);
4156 }
4157
4158 return (result);
4159 }
4160
4161 /*
4162 * Add key to the security roots.
4163 */
4164 static void
4165 trust_key(dns_zone_t *zone, dns_name_t *keyname, dns_rdata_dnskey_t *dnskey,
4166 bool initial) {
4167 isc_result_t result;
4168 dns_rdata_t rdata = DNS_RDATA_INIT;
4169 unsigned char data[4096], digest[ISC_MAX_MD_SIZE];
4170 isc_buffer_t buffer;
4171 dns_keytable_t *sr = NULL;
4172 dns_rdata_ds_t ds;
4173
4174 result = dns_view_getsecroots(zone->view, &sr);
4175 if (result != ISC_R_SUCCESS) {
4176 return;
4177 }
4178
4179 /* Build DS record for key. */
4180 isc_buffer_init(&buffer, data, sizeof(data));
4181 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4182 dns_rdatatype_dnskey, dnskey, &buffer);
4183 CHECK(dns_ds_fromkeyrdata(keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
4184 &ds));
4185 CHECK(dns_keytable_add(sr, true, initial, keyname, &ds));
4186
4187 dns_keytable_detach(&sr);
4188
4189 failure:
4190 if (sr != NULL) {
4191 dns_keytable_detach(&sr);
4192 }
4193 return;
4194 }
4195
4196 /*
4197 * Add a null key to the security roots for so that all queries
4198 * to the zone will fail.
4199 */
4200 static void
4201 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4202 isc_result_t result;
4203 dns_keytable_t *sr = NULL;
4204
4205 result = dns_view_getsecroots(zone->view, &sr);
4206 if (result == ISC_R_SUCCESS) {
4207 dns_keytable_marksecure(sr, keyname);
4208 dns_keytable_detach(&sr);
4209 }
4210 }
4211
4212 /*
4213 * Scan a set of KEYDATA records from the key zone. The ones that are
4214 * valid (i.e., the add holddown timer has expired) become trusted keys.
4215 */
4216 static void
4217 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4218 isc_result_t result;
4219 dns_rdata_t rdata = DNS_RDATA_INIT;
4220 dns_rdata_keydata_t keydata;
4221 dns_rdata_dnskey_t dnskey;
4222 int trusted = 0, revoked = 0, pending = 0;
4223 isc_stdtime_t now;
4224 dns_keytable_t *sr = NULL;
4225
4226 isc_stdtime_get(&now);
4227
4228 result = dns_view_getsecroots(zone->view, &sr);
4229 if (result == ISC_R_SUCCESS) {
4230 dns_keytable_delete(sr, name);
4231 dns_keytable_detach(&sr);
4232 }
4233
4234 /* Now insert all the accepted trust anchors from this keydata set. */
4235 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
4236 result = dns_rdataset_next(rdataset))
4237 {
4238 dns_rdata_reset(&rdata);
4239 dns_rdataset_current(rdataset, &rdata);
4240
4241 /* Convert rdata to keydata. */
4242 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4243 if (result == ISC_R_UNEXPECTEDEND) {
4244 continue;
4245 }
4246 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4247
4248 /* Set the key refresh timer to force a fast refresh. */
4249 set_refreshkeytimer(zone, &keydata, now, true);
4250
4251 /* If the removal timer is nonzero, this key was revoked. */
4252 if (keydata.removehd != 0) {
4253 revoked++;
4254 continue;
4255 }
4256
4257 /*
4258 * If the add timer is still pending, this key is not
4259 * trusted yet.
4260 */
4261 if (now < keydata.addhd) {
4262 pending++;
4263 continue;
4264 }
4265
4266 /* Convert keydata to dnskey. */
4267 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4268
4269 /* Add to keytables. */
4270 trusted++;
4271 trust_key(zone, name, &dnskey, (keydata.addhd == 0));
4272 }
4273
4274 if (trusted == 0 && pending != 0) {
4275 char namebuf[DNS_NAME_FORMATSIZE];
4276 dns_name_format(name, namebuf, sizeof namebuf);
4277 dnssec_log(zone, ISC_LOG_ERROR,
4278 "No valid trust anchors for '%s'!", namebuf);
4279 dnssec_log(zone, ISC_LOG_ERROR,
4280 "%d key(s) revoked, %d still pending", revoked,
4281 pending);
4282 dnssec_log(zone, ISC_LOG_ERROR, "All queries to '%s' will fail",
4283 namebuf);
4284 fail_secure(zone, name);
4285 }
4286 }
4287
4288 static isc_result_t
4289 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4290 dns_diff_t *diff) {
4291 dns_diff_t temp_diff;
4292 isc_result_t result;
4293
4294 /*
4295 * Create a singleton diff.
4296 */
4297 dns_diff_init(diff->mctx, &temp_diff);
4298 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4299
4300 /*
4301 * Apply it to the database.
4302 */
4303 result = dns_diff_apply(&temp_diff, db, ver);
4304 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4305 if (result != ISC_R_SUCCESS) {
4306 dns_difftuple_free(tuple);
4307 return (result);
4308 }
4309
4310 /*
4311 * Merge it into the current pending journal entry.
4312 */
4313 dns_diff_appendminimal(diff, tuple);
4314
4315 /*
4316 * Do not clear temp_diff.
4317 */
4318 return (ISC_R_SUCCESS);
4319 }
4320
4321 static isc_result_t
4322 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4323 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4324 dns_rdata_t *rdata) {
4325 dns_difftuple_t *tuple = NULL;
4326 isc_result_t result;
4327 result = dns_difftuple_create(diff->mctx, op, name, ttl, rdata, &tuple);
4328 if (result != ISC_R_SUCCESS) {
4329 return (result);
4330 }
4331 return (do_one_tuple(&tuple, db, ver, diff));
4332 }
4333
4334 static isc_result_t
4335 update_soa_serial(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
4336 dns_diff_t *diff, isc_mem_t *mctx,
4337 dns_updatemethod_t method) {
4338 dns_difftuple_t *deltuple = NULL;
4339 dns_difftuple_t *addtuple = NULL;
4340 uint32_t serial;
4341 isc_result_t result;
4342 dns_updatemethod_t used = dns_updatemethod_none;
4343
4344 INSIST(method != dns_updatemethod_none);
4345
4346 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4347 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4348 addtuple->op = DNS_DIFFOP_ADD;
4349
4350 serial = dns_soa_getserial(&addtuple->rdata);
4351 serial = dns_update_soaserial(serial, method, &used);
4352 if (method != used) {
4353 dns_zone_log(zone, ISC_LOG_WARNING,
4354 "update_soa_serial:new serial would be lower than "
4355 "old serial, using increment method instead");
4356 }
4357 dns_soa_setserial(serial, &addtuple->rdata);
4358 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4359 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4360 result = ISC_R_SUCCESS;
4361
4362 failure:
4363 if (addtuple != NULL) {
4364 dns_difftuple_free(&addtuple);
4365 }
4366 if (deltuple != NULL) {
4367 dns_difftuple_free(&deltuple);
4368 }
4369 return (result);
4370 }
4371
4372 /*
4373 * Write all transactions in 'diff' to the zone journal file.
4374 */
4375 static isc_result_t
4376 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4377 const char *caller) {
4378 const char me[] = "zone_journal";
4379 const char *journalfile;
4380 isc_result_t result = ISC_R_SUCCESS;
4381 dns_journal_t *journal = NULL;
4382 unsigned int mode = DNS_JOURNAL_CREATE | DNS_JOURNAL_WRITE;
4383
4384 ENTER;
4385 journalfile = dns_zone_getjournal(zone);
4386 if (journalfile != NULL) {
4387 result = dns_journal_open(zone->mctx, journalfile, mode,
4388 &journal);
4389 if (result != ISC_R_SUCCESS) {
4390 dns_zone_log(zone, ISC_LOG_ERROR,
4391 "%s:dns_journal_open -> %s", caller,
4392 dns_result_totext(result));
4393 return (result);
4394 }
4395
4396 if (sourceserial != NULL) {
4397 dns_journal_set_sourceserial(journal, *sourceserial);
4398 }
4399
4400 result = dns_journal_write_transaction(journal, diff);
4401 if (result != ISC_R_SUCCESS) {
4402 dns_zone_log(zone, ISC_LOG_ERROR,
4403 "%s:dns_journal_write_transaction -> %s",
4404 caller, dns_result_totext(result));
4405 }
4406 dns_journal_destroy(&journal);
4407 }
4408
4409 return (result);
4410 }
4411
4412 /*
4413 * Create an SOA record for a newly-created zone
4414 */
4415 static isc_result_t
4416 add_soa(dns_zone_t *zone, dns_db_t *db) {
4417 isc_result_t result;
4418 dns_rdata_t rdata = DNS_RDATA_INIT;
4419 unsigned char buf[DNS_SOA_BUFFERSIZE];
4420 dns_dbversion_t *ver = NULL;
4421 dns_diff_t diff;
4422
4423 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4424
4425 dns_diff_init(zone->mctx, &diff);
4426 result = dns_db_newversion(db, &ver);
4427 if (result != ISC_R_SUCCESS) {
4428 dns_zone_log(zone, ISC_LOG_ERROR,
4429 "add_soa:dns_db_newversion -> %s",
4430 dns_result_totext(result));
4431 goto failure;
4432 }
4433
4434 /* Build SOA record */
4435 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4436 0, 0, 0, 0, 0, buf, &rdata);
4437 if (result != ISC_R_SUCCESS) {
4438 dns_zone_log(zone, ISC_LOG_ERROR,
4439 "add_soa:dns_soa_buildrdata -> %s",
4440 dns_result_totext(result));
4441 goto failure;
4442 }
4443
4444 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD, &zone->origin, 0,
4445 &rdata);
4446
4447 failure:
4448 dns_diff_clear(&diff);
4449 if (ver != NULL) {
4450 dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4451 }
4452
4453 INSIST(ver == NULL);
4454
4455 return (result);
4456 }
4457
4458 struct addifmissing_arg {
4459 dns_db_t *db;
4460 dns_dbversion_t *ver;
4461 dns_diff_t *diff;
4462 dns_zone_t *zone;
4463 bool *changed;
4464 isc_result_t result;
4465 };
4466
4467 static void
4468 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode,
4469 dns_name_t *keyname, void *arg) {
4470 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4471 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4472 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4473 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4474 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4475 isc_result_t result;
4476 dns_fixedname_t fname;
4477
4478 UNUSED(keytable);
4479
4480 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS) {
4481 return;
4482 }
4483
4484 if (!dns_keynode_managed(keynode)) {
4485 return;
4486 }
4487
4488 /*
4489 * If the keynode has no trust anchor set, return.
4490 */
4491 if (!dns_keynode_dsset(keynode, NULL)) {
4492 return;
4493 }
4494
4495 /*
4496 * Check whether there's already a KEYDATA entry for this name;
4497 * if so, we don't need to add another.
4498 */
4499 dns_fixedname_init(&fname);
4500 result = dns_db_find(db, keyname, ver, dns_rdatatype_keydata,
4501 DNS_DBFIND_NOWILD, 0, NULL,
4502 dns_fixedname_name(&fname), NULL, NULL);
4503 if (result == ISC_R_SUCCESS) {
4504 return;
4505 }
4506
4507 /*
4508 * Create the keydata.
4509 */
4510 result = create_keydata(zone, db, ver, diff, keynode, keyname, changed);
4511 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE) {
4512 ((struct addifmissing_arg *)arg)->result = result;
4513 }
4514 }
4515
4516 /*
4517 * Synchronize the set of initializing keys found in managed-keys {}
4518 * statements with the set of trust anchors found in the managed-keys.bind
4519 * zone. If a domain is no longer named in managed-keys, delete all keys
4520 * from that domain from the key zone. If a domain is configured as an
4521 * initial-key in trust-anchors, but there are no references to it in the
4522 * key zone, load the key zone with the initializing key(s) for that
4523 * domain and schedule a key refresh. If a domain is configured as
4524 * an initial-ds in trust-anchors, fetch the DNSKEY RRset, load the key
4525 * zone with the matching key, and schedule a key refresh.
4526 */
4527 static isc_result_t
4528 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4529 isc_result_t result = ISC_R_SUCCESS;
4530 bool changed = false;
4531 bool commit = false;
4532 dns_keynode_t *keynode = NULL;
4533 dns_view_t *view = zone->view;
4534 dns_keytable_t *sr = NULL;
4535 dns_dbversion_t *ver = NULL;
4536 dns_diff_t diff;
4537 dns_rriterator_t rrit;
4538 struct addifmissing_arg arg;
4539
4540 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4541
4542 dns_diff_init(zone->mctx, &diff);
4543
4544 CHECK(dns_view_getsecroots(view, &sr));
4545
4546 result = dns_db_newversion(db, &ver);
4547 if (result != ISC_R_SUCCESS) {
4548 dnssec_log(zone, ISC_LOG_ERROR,
4549 "sync_keyzone:dns_db_newversion -> %s",
4550 dns_result_totext(result));
4551 goto failure;
4552 }
4553
4554 /*
4555 * Walk the zone DB. If we find any keys whose names are no longer
4556 * in trust-anchors, or which have been changed from initial to static,
4557 * (meaning they are permanent and not RFC5011-maintained), delete
4558 * them from the zone. Otherwise call load_secroots(), which
4559 * loads keys into secroots as appropriate.
4560 */
4561 dns_rriterator_init(&rrit, db, ver, 0);
4562 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
4563 result = dns_rriterator_nextrrset(&rrit))
4564 {
4565 dns_rdataset_t *rdataset = NULL;
4566 dns_name_t *rrname = NULL;
4567 uint32_t ttl;
4568
4569 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4570 if (!dns_rdataset_isassociated(rdataset)) {
4571 dns_rriterator_destroy(&rrit);
4572 goto failure;
4573 }
4574
4575 if (rdataset->type != dns_rdatatype_keydata) {
4576 continue;
4577 }
4578 /*
4579 * Release db wrlock to prevent LOR reports against
4580 * dns_keytable_forall() call below.
4581 */
4582 dns_rriterator_pause(&rrit);
4583 result = dns_keytable_find(sr, rrname, &keynode);
4584 if (result != ISC_R_SUCCESS || !dns_keynode_managed(keynode)) {
4585 CHECK(delete_keydata(db, ver, &diff, rrname, rdataset));
4586 changed = true;
4587 } else {
4588 load_secroots(zone, rrname, rdataset);
4589 }
4590
4591 if (keynode != NULL) {
4592 dns_keytable_detachkeynode(sr, &keynode);
4593 }
4594 }
4595 dns_rriterator_destroy(&rrit);
4596
4597 /*
4598 * Walk secroots to find any initial keys that aren't in
4599 * the zone. If we find any, add them to the zone directly.
4600 * If any DS-style initial keys are found, refresh the key
4601 * zone so that they'll be looked up.
4602 */
4603 arg.db = db;
4604 arg.ver = ver;
4605 arg.result = ISC_R_SUCCESS;
4606 arg.diff = &diff;
4607 arg.zone = zone;
4608 arg.changed = &changed;
4609 dns_keytable_forall(sr, addifmissing, &arg);
4610 result = arg.result;
4611 if (changed) {
4612 /* Write changes to journal file. */
4613 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
4614 zone->updatemethod));
4615 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4616
4617 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4618 zone_needdump(zone, 30);
4619 commit = true;
4620 }
4621
4622 failure:
4623 if (result != ISC_R_SUCCESS && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4624 {
4625 dnssec_log(zone, ISC_LOG_ERROR,
4626 "unable to synchronize managed keys: %s",
4627 dns_result_totext(result));
4628 isc_time_settoepoch(&zone->refreshkeytime);
4629 }
4630 if (keynode != NULL) {
4631 dns_keytable_detachkeynode(sr, &keynode);
4632 }
4633 if (sr != NULL) {
4634 dns_keytable_detach(&sr);
4635 }
4636 if (ver != NULL) {
4637 dns_db_closeversion(db, &ver, commit);
4638 }
4639 dns_diff_clear(&diff);
4640
4641 INSIST(ver == NULL);
4642
4643 return (result);
4644 }
4645
4646 isc_result_t
4647 dns_zone_synckeyzone(dns_zone_t *zone) {
4648 isc_result_t result;
4649 dns_db_t *db = NULL;
4650
4651 if (zone->type != dns_zone_key) {
4652 return (DNS_R_BADZONE);
4653 }
4654
4655 CHECK(dns_zone_getdb(zone, &db));
4656
4657 LOCK_ZONE(zone);
4658 result = sync_keyzone(zone, db);
4659 UNLOCK_ZONE(zone);
4660
4661 failure:
4662 if (db != NULL) {
4663 dns_db_detach(&db);
4664 }
4665 return (result);
4666 }
4667
4668 static void
4669 maybe_send_secure(dns_zone_t *zone) {
4670 isc_result_t result;
4671
4672 /*
4673 * We've finished loading, or else failed to load, an inline-signing
4674 * 'secure' zone. We now need information about the status of the
4675 * 'raw' zone. If we failed to load, then we need it to send a
4676 * copy of its database; if we succeeded, we need it to send its
4677 * serial number so that we can sync with it. If it has not yet
4678 * loaded, we set a flag so that it will send the necessary
4679 * information when it has finished loading.
4680 */
4681 if (zone->raw->db != NULL) {
4682 if (zone->db != NULL) {
4683 uint32_t serial;
4684 unsigned int soacount;
4685
4686 result = zone_get_from_db(zone->raw, zone->raw->db,
4687 NULL, &soacount, &serial,
4688 NULL, NULL, NULL, NULL, NULL);
4689 if (result == ISC_R_SUCCESS && soacount > 0U) {
4690 zone_send_secureserial(zone->raw, serial);
4691 }
4692 } else {
4693 zone_send_securedb(zone->raw, zone->raw->db);
4694 }
4695 } else {
4696 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4697 }
4698 }
4699
4700 static bool
4701 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4702 isc_result_t result;
4703 bool answer = false;
4704 dns_diff_t diff;
4705
4706 dns_diff_init(mctx, &diff);
4707 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4708 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples)) {
4709 answer = true;
4710 }
4711 dns_diff_clear(&diff);
4712 return (answer);
4713 }
4714
4715 /*
4716 * The zone is presumed to be locked.
4717 * If this is a inline_raw zone the secure version is also locked.
4718 */
4719 static isc_result_t
4720 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4721 isc_result_t result) {
4722 unsigned int soacount = 0;
4723 unsigned int nscount = 0;
4724 unsigned int errors = 0;
4725 uint32_t serial, oldserial, refresh, retry, expire, minimum;
4726 isc_time_t now;
4727 bool needdump = false;
4728 bool fixjournal = false;
4729 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4730 bool nomaster = false;
4731 bool had_db = false;
4732 dns_include_t *inc;
4733 bool is_dynamic = false;
4734
4735 INSIST(LOCKED_ZONE(zone));
4736 if (inline_raw(zone)) {
4737 INSIST(LOCKED_ZONE(zone->secure));
4738 }
4739
4740 TIME_NOW(&now);
4741
4742 /*
4743 * Initiate zone transfer? We may need a error code that
4744 * indicates that the "permanent" form does not exist.
4745 * XXX better error feedback to log.
4746 */
4747 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4748 if (zone->type == dns_zone_slave ||
4749 zone->type == dns_zone_mirror ||
4750 zone->type == dns_zone_stub ||
4751 (zone->type == dns_zone_redirect && zone->masters == NULL))
4752 {
4753 if (result == ISC_R_FILENOTFOUND) {
4754 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4755 ISC_LOG_DEBUG(1),
4756 "no master file");
4757 } else if (result != DNS_R_NOMASTERFILE) {
4758 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4759 ISC_LOG_ERROR,
4760 "loading from master file %s "
4761 "failed: %s",
4762 zone->masterfile,
4763 dns_result_totext(result));
4764 }
4765 } else if (zone->type == dns_zone_master &&
4766 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4767 {
4768 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4769 ISC_LOG_DEBUG(1),
4770 "no master file, requesting db");
4771 maybe_send_secure(zone);
4772 } else {
4773 int level = ISC_LOG_ERROR;
4774 if (zone->type == dns_zone_key &&
4775 result == ISC_R_FILENOTFOUND) {
4776 level = ISC_LOG_DEBUG(1);
4777 }
4778 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4779 "loading from master file %s failed: %s",
4780 zone->masterfile,
4781 dns_result_totext(result));
4782 nomaster = true;
4783 }
4784
4785 if (zone->type != dns_zone_key) {
4786 goto cleanup;
4787 }
4788 }
4789
4790 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4791 "number of nodes in database: %u", dns_db_nodecount(db));
4792
4793 if (result == DNS_R_SEENINCLUDE) {
4794 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4795 } else {
4796 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4797 }
4798
4799 /*
4800 * If there's no master file for a key zone, then the zone is new:
4801 * create an SOA record. (We do this now, instead of later, so that
4802 * if there happens to be a journal file, we can roll forward from
4803 * a sane starting point.)
4804 */
4805 if (nomaster && zone->type == dns_zone_key) {
4806 result = add_soa(zone, db);
4807 if (result != ISC_R_SUCCESS) {
4808 goto cleanup;
4809 }
4810 }
4811
4812 /*
4813 * Apply update log, if any, on initial load.
4814 */
4815 if (zone->journal != NULL &&
4816 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4817 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4818 {
4819 result = zone_journal_rollforward(zone, db, &needdump,
4820 &fixjournal);
4821 if (result != ISC_R_SUCCESS) {
4822 goto cleanup;
4823 }
4824 }
4825
4826 /*
4827 * Obtain ns, soa and cname counts for top of zone.
4828 */
4829 INSIST(db != NULL);
4830 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4831 &refresh, &retry, &expire, &minimum, &errors);
4832 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4833 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4834 "could not find NS and/or SOA records");
4835 }
4836
4837 /*
4838 * Process any queued NSEC3PARAM change requests. Only for dynamic
4839 * zones, an inline-signing zone will perform this action when
4840 * receiving the secure db (receive_secure_db).
4841 */
4842 is_dynamic = dns_zone_isdynamic(zone, true);
4843 if (is_dynamic) {
4844 isc_event_t *setnsec3param_event;
4845 dns_zone_t *dummy;
4846
4847 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
4848 setnsec3param_event =
4849 ISC_LIST_HEAD(zone->setnsec3param_queue);
4850 ISC_LIST_UNLINK(zone->setnsec3param_queue,
4851 setnsec3param_event, ev_link);
4852 dummy = NULL;
4853 zone_iattach(zone, &dummy);
4854 isc_task_send(zone->task, &setnsec3param_event);
4855 }
4856 }
4857
4858 /*
4859 * Check to make sure the journal is up to date, and remove the
4860 * journal file if it isn't, as we wouldn't be able to apply
4861 * updates otherwise.
4862 */
4863 if (zone->journal != NULL && is_dynamic &&
4864 !DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4865 {
4866 uint32_t jserial;
4867 dns_journal_t *journal = NULL;
4868 bool empty = false;
4869
4870 result = dns_journal_open(zone->mctx, zone->journal,
4871 DNS_JOURNAL_READ, &journal);
4872 if (result == ISC_R_SUCCESS) {
4873 jserial = dns_journal_last_serial(journal);
4874 empty = dns_journal_empty(journal);
4875 dns_journal_destroy(&journal);
4876 } else {
4877 jserial = serial;
4878 result = ISC_R_SUCCESS;
4879 }
4880
4881 if (jserial != serial) {
4882 if (!empty) {
4883 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4884 ISC_LOG_INFO,
4885 "journal file is out of date: "
4886 "removing journal file");
4887 }
4888 if (remove(zone->journal) < 0 && errno != ENOENT) {
4889 char strbuf[ISC_STRERRORSIZE];
4890 strerror_r(errno, strbuf, sizeof(strbuf));
4891 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
4892 DNS_LOGMODULE_ZONE,
4893 ISC_LOG_WARNING,
4894 "unable to remove journal "
4895 "'%s': '%s'",
4896 zone->journal, strbuf);
4897 }
4898 }
4899 }
4900
4901 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4902 "loaded; checking validity");
4903
4904 /*
4905 * Master / Slave / Mirror / Stub zones require both NS and SOA records
4906 * at the top of the zone.
4907 */
4908
4909 switch (zone->type) {
4910 case dns_zone_dlz:
4911 case dns_zone_master:
4912 case dns_zone_slave:
4913 case dns_zone_mirror:
4914 case dns_zone_stub:
4915 case dns_zone_redirect:
4916 if (soacount != 1) {
4917 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4918 ISC_LOG_ERROR, "has %d SOA records",
4919 soacount);
4920 result = DNS_R_BADZONE;
4921 }
4922 if (nscount == 0) {
4923 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4924 ISC_LOG_ERROR, "has no NS records");
4925 result = DNS_R_BADZONE;
4926 }
4927 if (result != ISC_R_SUCCESS) {
4928 goto cleanup;
4929 }
4930 if (zone->type == dns_zone_master && errors != 0) {
4931 result = DNS_R_BADZONE;
4932 goto cleanup;
4933 }
4934 if (zone->type != dns_zone_stub &&
4935 zone->type != dns_zone_redirect) {
4936 result = check_nsec3param(zone, db);
4937 if (result != ISC_R_SUCCESS) {
4938 goto cleanup;
4939 }
4940 }
4941 if (zone->type == dns_zone_master &&
4942 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4943 !integrity_checks(zone, db))
4944 {
4945 result = DNS_R_BADZONE;
4946 goto cleanup;
4947 }
4948 if (zone->type == dns_zone_master &&
4949 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4950 !zone_check_dup(zone, db))
4951 {
4952 result = DNS_R_BADZONE;
4953 goto cleanup;
4954 }
4955
4956 if (zone->type == dns_zone_master) {
4957 result = dns_zone_cdscheck(zone, db, NULL);
4958 if (result != ISC_R_SUCCESS) {
4959 dns_zone_log(zone, ISC_LOG_ERROR,
4960 "CDS/CDNSKEY consistency checks "
4961 "failed");
4962 goto cleanup;
4963 }
4964 }
4965
4966 result = dns_zone_verifydb(zone, db, NULL);
4967 if (result != ISC_R_SUCCESS) {
4968 goto cleanup;
4969 }
4970
4971 if (zone->db != NULL) {
4972 unsigned int oldsoacount;
4973
4974 /*
4975 * This is checked in zone_replacedb() for slave zones
4976 * as they don't reload from disk.
4977 */
4978 result = zone_get_from_db(zone, zone->db, NULL,
4979 &oldsoacount, &oldserial,
4980 NULL, NULL, NULL, NULL, NULL);
4981 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4982 RUNTIME_CHECK(soacount > 0U);
4983 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4984 !isc_serial_gt(serial, oldserial))
4985 {
4986 uint32_t serialmin, serialmax;
4987
4988 INSIST(zone->type == dns_zone_master);
4989 INSIST(zone->raw == NULL);
4990
4991 if (serial == oldserial &&
4992 zone_unchanged(zone->db, db, zone->mctx)) {
4993 dns_zone_logc(zone,
4994 DNS_LOGCATEGORY_ZONELOAD,
4995 ISC_LOG_INFO,
4996 "ixfr-from-differences: "
4997 "unchanged");
4998 goto done;
4999 }
5000
5001 serialmin = (oldserial + 1) & 0xffffffffU;
5002 serialmax = (oldserial + 0x7fffffffU) &
5003 0xffffffffU;
5004 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5005 ISC_LOG_ERROR,
5006 "ixfr-from-differences: "
5007 "new serial (%u) out of range "
5008 "[%u - %u]",
5009 serial, serialmin, serialmax);
5010 result = DNS_R_BADZONE;
5011 goto cleanup;
5012 } else if (!isc_serial_ge(serial, oldserial)) {
5013 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5014 ISC_LOG_ERROR,
5015 "zone serial (%u/%u) has gone "
5016 "backwards",
5017 serial, oldserial);
5018 } else if (serial == oldserial && !hasinclude &&
5019 strcmp(zone->db_argv[0], "_builtin") != 0)
5020 {
5021 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5022 ISC_LOG_ERROR,
5023 "zone serial (%u) unchanged. "
5024 "zone may fail to transfer "
5025 "to slaves.",
5026 serial);
5027 }
5028 }
5029
5030 if (zone->type == dns_zone_master &&
5031 (zone->update_acl != NULL || zone->ssutable != NULL) &&
5032 dns_zone_getsigresigninginterval(zone) < (3 * refresh) &&
5033 dns_db_issecure(db))
5034 {
5035 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5036 ISC_LOG_WARNING,
5037 "sig-re-signing-interval less than "
5038 "3 * refresh.");
5039 }
5040
5041 zone->refresh = RANGE(refresh, zone->minrefresh,
5042 zone->maxrefresh);
5043 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
5044 zone->expire = RANGE(expire, zone->refresh + zone->retry,
5045 DNS_MAX_EXPIRE);
5046 zone->minimum = minimum;
5047 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
5048
5049 if (zone->type == dns_zone_slave ||
5050 zone->type == dns_zone_mirror ||
5051 zone->type == dns_zone_stub ||
5052 (zone->type == dns_zone_redirect && zone->masters != NULL))
5053 {
5054 isc_time_t t;
5055 uint32_t delay;
5056
5057 result = isc_file_getmodtime(zone->journal, &t);
5058 if (result != ISC_R_SUCCESS) {
5059 result = isc_file_getmodtime(zone->masterfile,
5060 &t);
5061 }
5062 if (result == ISC_R_SUCCESS) {
5063 DNS_ZONE_TIME_ADD(&t, zone->expire,
5064 &zone->expiretime);
5065 } else {
5066 DNS_ZONE_TIME_ADD(&now, zone->retry,
5067 &zone->expiretime);
5068 }
5069
5070 delay = (zone->retry -
5071 isc_random_uniform((zone->retry * 3) / 4));
5072 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
5073 if (isc_time_compare(&zone->refreshtime,
5074 &zone->expiretime) >= 0) {
5075 zone->refreshtime = now;
5076 }
5077 }
5078
5079 break;
5080
5081 case dns_zone_key:
5082 result = sync_keyzone(zone, db);
5083 if (result != ISC_R_SUCCESS) {
5084 goto cleanup;
5085 }
5086 break;
5087
5088 default:
5089 UNEXPECTED_ERROR(__FILE__, __LINE__, "unexpected zone type %d",
5090 zone->type);
5091 result = ISC_R_UNEXPECTED;
5092 goto cleanup;
5093 }
5094
5095 /*
5096 * Check for weak DNSKEY's.
5097 */
5098 if (zone->type == dns_zone_master) {
5099 zone_check_dnskeys(zone, db);
5100 }
5101
5102 /*
5103 * Schedule DNSSEC key refresh.
5104 */
5105 if (zone->type == dns_zone_master &&
5106 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
5107 {
5108 zone->refreshkeytime = now;
5109 }
5110
5111 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
5112 if (zone->db != NULL) {
5113 had_db = true;
5114 result = zone_replacedb(zone, db, false);
5115 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5116 if (result != ISC_R_SUCCESS) {
5117 goto cleanup;
5118 }
5119 } else {
5120 zone_attachdb(zone, db);
5121 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
5122 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED |
5123 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
5124 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
5125 inline_raw(zone)) {
5126 if (zone->secure->db == NULL) {
5127 zone_send_securedb(zone, db);
5128 } else {
5129 zone_send_secureserial(zone, serial);
5130 }
5131 }
5132 }
5133
5134 /*
5135 * Finished loading inline-signing zone; need to get status
5136 * from the raw side now.
5137 */
5138 if (zone->type == dns_zone_master && inline_secure(zone)) {
5139 maybe_send_secure(zone);
5140 }
5141
5142 result = ISC_R_SUCCESS;
5143
5144 if (fixjournal) {
5145 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
5146 zone_journal_compact(zone, zone->db, 0);
5147 }
5148 if (needdump) {
5149 if (zone->type == dns_zone_key) {
5150 zone_needdump(zone, 30);
5151 } else {
5152 zone_needdump(zone, DNS_DUMP_DELAY);
5153 }
5154 }
5155
5156 if (zone->task != NULL) {
5157 if (zone->type == dns_zone_master) {
5158 set_resigntime(zone);
5159 resume_signingwithkey(zone);
5160 resume_addnsec3chain(zone);
5161 }
5162
5163 is_dynamic = dns_zone_isdynamic(zone, false);
5164 if (zone->type == dns_zone_master &&
5165 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
5166 is_dynamic && dns_db_issecure(db))
5167 {
5168 dns_name_t *name;
5169 dns_fixedname_t fixed;
5170 dns_rdataset_t next;
5171
5172 dns_rdataset_init(&next);
5173 name = dns_fixedname_initname(&fixed);
5174
5175 result = dns_db_getsigningtime(db, &next, name);
5176 if (result == ISC_R_SUCCESS) {
5177 isc_stdtime_t timenow;
5178 char namebuf[DNS_NAME_FORMATSIZE];
5179 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5180
5181 isc_stdtime_get(&timenow);
5182 dns_name_format(name, namebuf, sizeof(namebuf));
5183 dns_rdatatype_format(next.covers, typebuf,
5184 sizeof(typebuf));
5185 dnssec_log(
5186 zone, ISC_LOG_DEBUG(3),
5187 "next resign: %s/%s "
5188 "in %d seconds",
5189 namebuf, typebuf,
5190 next.resign - timenow -
5191 dns_zone_getsigresigninginterval(
5192 zone));
5193 dns_rdataset_disassociate(&next);
5194 } else {
5195 dnssec_log(zone, ISC_LOG_WARNING,
5196 "signed dynamic zone has no "
5197 "resign event scheduled");
5198 }
5199 }
5200
5201 zone_settimer(zone, &now);
5202 }
5203
5204 /*
5205 * Clear old include list.
5206 */
5207 for (inc = ISC_LIST_HEAD(zone->includes); inc != NULL;
5208 inc = ISC_LIST_HEAD(zone->includes))
5209 {
5210 ISC_LIST_UNLINK(zone->includes, inc, link);
5211 isc_mem_free(zone->mctx, inc->name);
5212 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5213 }
5214 zone->nincludes = 0;
5215
5216 /*
5217 * Transfer new include list.
5218 */
5219 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5220 inc = ISC_LIST_HEAD(zone->newincludes))
5221 {
5222 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5223 ISC_LIST_APPEND(zone->includes, inc, link);
5224 zone->nincludes++;
5225 }
5226
5227 if (!dns_db_ispersistent(db)) {
5228 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5229 "loaded serial %u%s", serial,
5230 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5231 }
5232
5233 if (!had_db && zone->type == dns_zone_mirror) {
5234 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5235 "mirror zone is now in use");
5236 }
5237
5238 zone->loadtime = loadtime;
5239 goto done;
5240
5241 cleanup:
5242 if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
5243 dnssec_log(zone, ISC_LOG_ERROR,
5244 "failed to initialize managed-keys (%s): "
5245 "DNSSEC validation is at risk",
5246 isc_result_totext(result));
5247 }
5248
5249 for (inc = ISC_LIST_HEAD(zone->newincludes); inc != NULL;
5250 inc = ISC_LIST_HEAD(zone->newincludes))
5251 {
5252 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5253 isc_mem_free(zone->mctx, inc->name);
5254 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5255 }
5256 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
5257 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
5258 (zone->type == dns_zone_redirect && zone->masters != NULL))
5259 {
5260 if (result != ISC_R_NOMEMORY) {
5261 if (zone->journal != NULL) {
5262 zone_saveunique(zone, zone->journal,
5263 "jn-XXXXXXXX");
5264 }
5265 if (zone->masterfile != NULL) {
5266 zone_saveunique(zone, zone->masterfile,
5267 "db-XXXXXXXX");
5268 }
5269 }
5270
5271 /* Mark the zone for immediate refresh. */
5272 zone->refreshtime = now;
5273 if (zone->task != NULL) {
5274 zone_settimer(zone, &now);
5275 }
5276 result = ISC_R_SUCCESS;
5277 } else if (zone->type == dns_zone_master ||
5278 zone->type == dns_zone_redirect) {
5279 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5280 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5281 ISC_LOG_ERROR,
5282 "not loaded due to errors.");
5283 } else if (zone->type == dns_zone_master) {
5284 result = ISC_R_SUCCESS;
5285 }
5286 }
5287
5288 done:
5289 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5290 /*
5291 * If this is an inline-signed zone and we were called for the raw
5292 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5293 * as well, but only if this is a reload, not an initial zone load: in
5294 * the former case, zone_postload() will not be run for the secure
5295 * zone; in the latter case, it will be. Check which case we are
5296 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5297 * secure zone: if it is set, this must be a reload.
5298 */
5299 if (inline_raw(zone) && DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5300 {
5301 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5302 /*
5303 * Re-start zone maintenance if it had been stalled
5304 * due to DNS_ZONEFLG_LOADPENDING being set when
5305 * zone_maintenance was called.
5306 */
5307 if (zone->secure->task != NULL) {
5308 zone_settimer(zone->secure, &now);
5309 }
5310 }
5311
5312 zone_debuglog(zone, "zone_postload", 99, "done");
5313
5314 return (result);
5315 }
5316
5317 static bool
5318 exit_check(dns_zone_t *zone) {
5319 REQUIRE(LOCKED_ZONE(zone));
5320
5321 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) &&
5322 isc_refcount_current(&zone->irefs) == 0)
5323 {
5324 /*
5325 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5326 */
5327 INSIST(isc_refcount_current(&zone->erefs) == 0);
5328 return (true);
5329 }
5330 return (false);
5331 }
5332
5333 static bool
5334 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5335 dns_name_t *name, bool logit) {
5336 isc_result_t result;
5337 char namebuf[DNS_NAME_FORMATSIZE];
5338 char altbuf[DNS_NAME_FORMATSIZE];
5339 dns_fixedname_t fixed;
5340 dns_name_t *foundname;
5341 int level;
5342
5343 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS)) {
5344 return (true);
5345 }
5346
5347 if (zone->type == dns_zone_master) {
5348 level = ISC_LOG_ERROR;
5349 } else {
5350 level = ISC_LOG_WARNING;
5351 }
5352
5353 foundname = dns_fixedname_initname(&fixed);
5354
5355 result = dns_db_find(db, name, version, dns_rdatatype_a, 0, 0, NULL,
5356 foundname, NULL, NULL);
5357 if (result == ISC_R_SUCCESS) {
5358 return (true);
5359 }
5360
5361 if (result == DNS_R_NXRRSET) {
5362 result = dns_db_find(db, name, version, dns_rdatatype_aaaa, 0,
5363 0, NULL, foundname, NULL, NULL);
5364 if (result == ISC_R_SUCCESS) {
5365 return (true);
5366 }
5367 }
5368
5369 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5370 result == DNS_R_EMPTYNAME)
5371 {
5372 if (logit) {
5373 dns_name_format(name, namebuf, sizeof namebuf);
5374 dns_zone_log(zone, level,
5375 "NS '%s' has no address "
5376 "records (A or AAAA)",
5377 namebuf);
5378 }
5379 return (false);
5380 }
5381
5382 if (result == DNS_R_CNAME) {
5383 if (logit) {
5384 dns_name_format(name, namebuf, sizeof namebuf);
5385 dns_zone_log(zone, level,
5386 "NS '%s' is a CNAME "
5387 "(illegal)",
5388 namebuf);
5389 }
5390 return (false);
5391 }
5392
5393 if (result == DNS_R_DNAME) {
5394 if (logit) {
5395 dns_name_format(name, namebuf, sizeof namebuf);
5396 dns_name_format(foundname, altbuf, sizeof altbuf);
5397 dns_zone_log(zone, level,
5398 "NS '%s' is below a DNAME "
5399 "'%s' (illegal)",
5400 namebuf, altbuf);
5401 }
5402 return (false);
5403 }
5404
5405 return (true);
5406 }
5407
5408 static isc_result_t
5409 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5410 dns_dbversion_t *version, unsigned int *nscount,
5411 unsigned int *errors, bool logit) {
5412 isc_result_t result;
5413 unsigned int count = 0;
5414 unsigned int ecount = 0;
5415 dns_rdataset_t rdataset;
5416 dns_rdata_t rdata;
5417 dns_rdata_ns_t ns;
5418
5419 dns_rdataset_init(&rdataset);
5420 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5421 dns_rdatatype_none, 0, &rdataset, NULL);
5422 if (result == ISC_R_NOTFOUND) {
5423 INSIST(!dns_rdataset_isassociated(&rdataset));
5424 goto success;
5425 }
5426 if (result != ISC_R_SUCCESS) {
5427 INSIST(!dns_rdataset_isassociated(&rdataset));
5428 goto invalidate_rdataset;
5429 }
5430
5431 result = dns_rdataset_first(&rdataset);
5432 while (result == ISC_R_SUCCESS) {
5433 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5434 (zone->type == dns_zone_master ||
5435 zone->type == dns_zone_slave ||
5436 zone->type == dns_zone_mirror))
5437 {
5438 dns_rdata_init(&rdata);
5439 dns_rdataset_current(&rdataset, &rdata);
5440 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5441 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5442 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5443 !zone_check_ns(zone, db, version, &ns.name, logit))
5444 {
5445 ecount++;
5446 }
5447 }
5448 count++;
5449 result = dns_rdataset_next(&rdataset);
5450 }
5451 dns_rdataset_disassociate(&rdataset);
5452
5453 success:
5454 if (nscount != NULL) {
5455 *nscount = count;
5456 }
5457 if (errors != NULL) {
5458 *errors = ecount;
5459 }
5460
5461 result = ISC_R_SUCCESS;
5462
5463 invalidate_rdataset:
5464 dns_rdataset_invalidate(&rdataset);
5465
5466 return (result);
5467 }
5468
5469 static isc_result_t
5470 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5471 unsigned int *soacount, uint32_t *serial, uint32_t *refresh,
5472 uint32_t *retry, uint32_t *expire, uint32_t *minimum) {
5473 isc_result_t result;
5474 unsigned int count;
5475 dns_rdataset_t rdataset;
5476 dns_rdata_t rdata = DNS_RDATA_INIT;
5477 dns_rdata_soa_t soa;
5478
5479 dns_rdataset_init(&rdataset);
5480 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5481 dns_rdatatype_none, 0, &rdataset, NULL);
5482 if (result == ISC_R_NOTFOUND) {
5483 INSIST(!dns_rdataset_isassociated(&rdataset));
5484 if (soacount != NULL) {
5485 *soacount = 0;
5486 }
5487 if (serial != NULL) {
5488 *serial = 0;
5489 }
5490 if (refresh != NULL) {
5491 *refresh = 0;
5492 }
5493 if (retry != NULL) {
5494 *retry = 0;
5495 }
5496 if (expire != NULL) {
5497 *expire = 0;
5498 }
5499 if (minimum != NULL) {
5500 *minimum = 0;
5501 }
5502 result = ISC_R_SUCCESS;
5503 goto invalidate_rdataset;
5504 }
5505 if (result != ISC_R_SUCCESS) {
5506 INSIST(!dns_rdataset_isassociated(&rdataset));
5507 goto invalidate_rdataset;
5508 }
5509
5510 count = 0;
5511 result = dns_rdataset_first(&rdataset);
5512 while (result == ISC_R_SUCCESS) {
5513 dns_rdata_init(&rdata);
5514 dns_rdataset_current(&rdataset, &rdata);
5515 count++;
5516 if (count == 1) {
5517 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5518 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5519 }
5520
5521 result = dns_rdataset_next(&rdataset);
5522 dns_rdata_reset(&rdata);
5523 }
5524 dns_rdataset_disassociate(&rdataset);
5525
5526 if (soacount != NULL) {
5527 *soacount = count;
5528 }
5529
5530 if (count > 0) {
5531 if (serial != NULL) {
5532 *serial = soa.serial;
5533 }
5534 if (refresh != NULL) {
5535 *refresh = soa.refresh;
5536 }
5537 if (retry != NULL) {
5538 *retry = soa.retry;
5539 }
5540 if (expire != NULL) {
5541 *expire = soa.expire;
5542 }
5543 if (minimum != NULL) {
5544 *minimum = soa.minimum;
5545 }
5546 } else {
5547 if (soacount != NULL) {
5548 *soacount = 0;
5549 }
5550 if (serial != NULL) {
5551 *serial = 0;
5552 }
5553 if (refresh != NULL) {
5554 *refresh = 0;
5555 }
5556 if (retry != NULL) {
5557 *retry = 0;
5558 }
5559 if (expire != NULL) {
5560 *expire = 0;
5561 }
5562 if (minimum != NULL) {
5563 *minimum = 0;
5564 }
5565 }
5566
5567 result = ISC_R_SUCCESS;
5568
5569 invalidate_rdataset:
5570 dns_rdataset_invalidate(&rdataset);
5571
5572 return (result);
5573 }
5574
5575 /*
5576 * zone must be locked.
5577 */
5578 static isc_result_t
5579 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5580 unsigned int *soacount, uint32_t *serial, uint32_t *refresh,
5581 uint32_t *retry, uint32_t *expire, uint32_t *minimum,
5582 unsigned int *errors) {
5583 isc_result_t result;
5584 isc_result_t answer = ISC_R_SUCCESS;
5585 dns_dbversion_t *version = NULL;
5586 dns_dbnode_t *node;
5587
5588 REQUIRE(db != NULL);
5589 REQUIRE(zone != NULL);
5590
5591 dns_db_currentversion(db, &version);
5592
5593 if (nscount != NULL) {
5594 *nscount = 0;
5595 }
5596 if (soacount != NULL) {
5597 *soacount = 0;
5598 }
5599 if (serial != NULL) {
5600 *serial = 0;
5601 }
5602 if (refresh != NULL) {
5603 *refresh = 0;
5604 }
5605 if (retry != NULL) {
5606 *retry = 0;
5607 }
5608 if (expire != NULL) {
5609 *expire = 0;
5610 }
5611 if (errors != NULL) {
5612 *errors = 0;
5613 }
5614
5615 node = NULL;
5616 result = dns_db_findnode(db, &zone->origin, false, &node);
5617 if (result != ISC_R_SUCCESS) {
5618 answer = result;
5619 goto closeversion;
5620 }
5621
5622 if (nscount != NULL || errors != NULL) {
5623 result = zone_count_ns_rr(zone, db, node, version, nscount,
5624 errors, true);
5625 if (result != ISC_R_SUCCESS) {
5626 answer = result;
5627 }
5628 }
5629
5630 if (soacount != NULL || serial != NULL || refresh != NULL ||
5631 retry != NULL || expire != NULL || minimum != NULL)
5632 {
5633 result = zone_load_soa_rr(db, node, version, soacount, serial,
5634 refresh, retry, expire, minimum);
5635 if (result != ISC_R_SUCCESS) {
5636 answer = result;
5637 }
5638 }
5639
5640 dns_db_detachnode(db, &node);
5641 closeversion:
5642 dns_db_closeversion(db, &version, false);
5643
5644 return (answer);
5645 }
5646
5647 void
5648 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5649 REQUIRE(DNS_ZONE_VALID(source));
5650 REQUIRE(target != NULL && *target == NULL);
5651 isc_refcount_increment(&source->erefs);
5652 *target = source;
5653 }
5654
5655 void
5656 dns_zone_detach(dns_zone_t **zonep) {
5657 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5658 dns_zone_t *zone = *zonep;
5659 *zonep = NULL;
5660
5661 bool free_now = false;
5662 dns_zone_t *raw = NULL;
5663 dns_zone_t *secure = NULL;
5664 if (isc_refcount_decrement(&zone->erefs) == 1) {
5665 isc_refcount_destroy(&zone->erefs);
5666
5667 LOCK_ZONE(zone);
5668 INSIST(zone != zone->raw);
5669 /*
5670 * We just detached the last external reference.
5671 */
5672 if (zone->task != NULL) {
5673 /*
5674 * This zone is being managed. Post
5675 * its control event and let it clean
5676 * up synchronously in the context of
5677 * its task.
5678 */
5679 isc_event_t *ev = &zone->ctlevent;
5680 isc_task_send(zone->task, &ev);
5681 } else {
5682 /*
5683 * This zone is not being managed; it has
5684 * no task and can have no outstanding
5685 * events. Free it immediately.
5686 */
5687 /*
5688 * Unmanaged zones should not have non-null views;
5689 * we have no way of detaching from the view here
5690 * without causing deadlock because this code is called
5691 * with the view already locked.
5692 */
5693 INSIST(zone->view == NULL);
5694 free_now = true;
5695 raw = zone->raw;
5696 zone->raw = NULL;
5697 secure = zone->secure;
5698 zone->secure = NULL;
5699 }
5700 UNLOCK_ZONE(zone);
5701 }
5702 if (free_now) {
5703 if (raw != NULL) {
5704 dns_zone_detach(&raw);
5705 }
5706 if (secure != NULL) {
5707 dns_zone_idetach(&secure);
5708 }
5709 zone_free(zone);
5710 }
5711 }
5712
5713 void
5714 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5715 REQUIRE(DNS_ZONE_VALID(source));
5716
5717 LOCK_ZONE(source);
5718 zone_iattach(source, target);
5719 UNLOCK_ZONE(source);
5720 }
5721
5722 static void
5723 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5724 REQUIRE(DNS_ZONE_VALID(source));
5725 REQUIRE(LOCKED_ZONE(source));
5726 REQUIRE(target != NULL && *target == NULL);
5727 INSIST(isc_refcount_increment0(&source->irefs) +
5728 isc_refcount_current(&source->erefs) >
5729 0);
5730 *target = source;
5731 }
5732
5733 static void
5734 zone_idetach(dns_zone_t **zonep) {
5735 dns_zone_t *zone;
5736
5737 /*
5738 * 'zone' locked by caller.
5739 */
5740 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5741 REQUIRE(LOCKED_ZONE(*zonep));
5742
5743 zone = *zonep;
5744 *zonep = NULL;
5745
5746 INSIST(isc_refcount_decrement(&zone->irefs) - 1 +
5747 isc_refcount_current(&zone->erefs) >
5748 0);
5749 }
5750
5751 void
5752 dns_zone_idetach(dns_zone_t **zonep) {
5753 dns_zone_t *zone;
5754 bool free_needed;
5755
5756 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5757
5758 zone = *zonep;
5759 *zonep = NULL;
5760
5761 if (isc_refcount_decrement(&zone->irefs) == 1) {
5762 LOCK_ZONE(zone);
5763 free_needed = exit_check(zone);
5764 UNLOCK_ZONE(zone);
5765 if (free_needed) {
5766 zone_free(zone);
5767 }
5768 }
5769 }
5770
5771 isc_mem_t *
5772 dns_zone_getmctx(dns_zone_t *zone) {
5773 REQUIRE(DNS_ZONE_VALID(zone));
5774
5775 return (zone->mctx);
5776 }
5777
5778 dns_zonemgr_t *
5779 dns_zone_getmgr(dns_zone_t *zone) {
5780 REQUIRE(DNS_ZONE_VALID(zone));
5781
5782 return (zone->zmgr);
5783 }
5784
5785 void
5786 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value) {
5787 REQUIRE(DNS_ZONE_VALID(zone));
5788
5789 if (value) {
5790 DNS_ZONE_SETFLAG(zone, flags);
5791 } else {
5792 DNS_ZONE_CLRFLAG(zone, flags);
5793 }
5794 }
5795
5796 void
5797 dns_zone_setkasp(dns_zone_t *zone, dns_kasp_t *kasp) {
5798 REQUIRE(DNS_ZONE_VALID(zone));
5799
5800 LOCK_ZONE(zone);
5801 if (zone->kasp != NULL) {
5802 dns_kasp_t *oldkasp = zone->kasp;
5803 zone->kasp = NULL;
5804 dns_kasp_detach(&oldkasp);
5805 }
5806 zone->kasp = kasp;
5807 UNLOCK_ZONE(zone);
5808 }
5809
5810 dns_kasp_t *
5811 dns_zone_getkasp(dns_zone_t *zone) {
5812 REQUIRE(DNS_ZONE_VALID(zone));
5813
5814 return (zone->kasp);
5815 }
5816
5817 static bool
5818 statefile_exist(dns_zone_t *zone) {
5819 isc_result_t ret;
5820 dns_dnsseckeylist_t keys;
5821 dns_dnsseckey_t *key = NULL;
5822 isc_stdtime_t now;
5823 isc_time_t timenow;
5824 bool found = false;
5825
5826 TIME_NOW(&timenow);
5827 now = isc_time_seconds(&timenow);
5828
5829 ISC_LIST_INIT(keys);
5830
5831 ret = dns_dnssec_findmatchingkeys(dns_zone_getorigin(zone),
5832 dns_zone_getkeydirectory(zone), now,
5833 dns_zone_getmctx(zone), &keys);
5834 if (ret == ISC_R_SUCCESS) {
5835 for (key = ISC_LIST_HEAD(keys); key != NULL;
5836 key = ISC_LIST_NEXT(key, link)) {
5837 if (dst_key_haskasp(key->key)) {
5838 found = true;
5839 break;
5840 }
5841 }
5842 }
5843
5844 /* Clean up keys */
5845 while (!ISC_LIST_EMPTY(keys)) {
5846 key = ISC_LIST_HEAD(keys);
5847 ISC_LIST_UNLINK(keys, key, link);
5848 dns_dnsseckey_destroy(dns_zone_getmctx(zone), &key);
5849 }
5850
5851 return (found);
5852 }
5853
5854 bool
5855 dns_zone_secure_to_insecure(dns_zone_t *zone, bool reconfig) {
5856 REQUIRE(DNS_ZONE_VALID(zone));
5857
5858 /*
5859 * If checking during reconfig, the zone is not yet updated
5860 * with the new kasp configuration, so only check the key
5861 * files.
5862 */
5863 if (reconfig) {
5864 return (statefile_exist(zone));
5865 }
5866
5867 if (zone->kasp == NULL) {
5868 return (false);
5869 }
5870 if (strcmp(dns_kasp_getname(zone->kasp), "none") != 0) {
5871 return (false);
5872 }
5873 /*
5874 * "dnssec-policy none", but if there are key state files
5875 * this zone used to be secure but is transitioning back to
5876 * insecure.
5877 */
5878 return (statefile_exist(zone));
5879 }
5880
5881 bool
5882 dns_zone_use_kasp(dns_zone_t *zone) {
5883 dns_kasp_t *kasp = dns_zone_getkasp(zone);
5884
5885 if (kasp == NULL) {
5886 return (false);
5887 } else if (strcmp(dns_kasp_getname(kasp), "none") != 0) {
5888 return (true);
5889 }
5890 return dns_zone_secure_to_insecure(zone, false);
5891 }
5892
5893 void
5894 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option, bool value) {
5895 REQUIRE(DNS_ZONE_VALID(zone));
5896
5897 if (value) {
5898 DNS_ZONE_SETOPTION(zone, option);
5899 } else {
5900 DNS_ZONE_CLROPTION(zone, option);
5901 }
5902 }
5903
5904 dns_zoneopt_t
5905 dns_zone_getoptions(dns_zone_t *zone) {
5906 REQUIRE(DNS_ZONE_VALID(zone));
5907
5908 return (atomic_load_relaxed(&zone->options));
5909 }
5910
5911 void
5912 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value) {
5913 REQUIRE(DNS_ZONE_VALID(zone));
5914
5915 if (value) {
5916 DNS_ZONEKEY_SETOPTION(zone, keyopt);
5917 } else {
5918 DNS_ZONEKEY_CLROPTION(zone, keyopt);
5919 }
5920 }
5921
5922 unsigned int
5923 dns_zone_getkeyopts(dns_zone_t *zone) {
5924 REQUIRE(DNS_ZONE_VALID(zone));
5925
5926 return (atomic_load_relaxed(&zone->keyopts));
5927 }
5928
5929 isc_result_t
5930 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5931 REQUIRE(DNS_ZONE_VALID(zone));
5932
5933 LOCK_ZONE(zone);
5934 zone->xfrsource4 = *xfrsource;
5935 UNLOCK_ZONE(zone);
5936
5937 return (ISC_R_SUCCESS);
5938 }
5939
5940 isc_sockaddr_t *
5941 dns_zone_getxfrsource4(dns_zone_t *zone) {
5942 REQUIRE(DNS_ZONE_VALID(zone));
5943 return (&zone->xfrsource4);
5944 }
5945
5946 isc_result_t
5947 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5948 REQUIRE(DNS_ZONE_VALID(zone));
5949
5950 LOCK_ZONE(zone);
5951 zone->xfrsource4dscp = dscp;
5952 UNLOCK_ZONE(zone);
5953
5954 return (ISC_R_SUCCESS);
5955 }
5956
5957 isc_dscp_t
5958 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5959 REQUIRE(DNS_ZONE_VALID(zone));
5960 return (zone->xfrsource4dscp);
5961 }
5962
5963 isc_result_t
5964 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5965 REQUIRE(DNS_ZONE_VALID(zone));
5966
5967 LOCK_ZONE(zone);
5968 zone->xfrsource6 = *xfrsource;
5969 UNLOCK_ZONE(zone);
5970
5971 return (ISC_R_SUCCESS);
5972 }
5973
5974 isc_sockaddr_t *
5975 dns_zone_getxfrsource6(dns_zone_t *zone) {
5976 REQUIRE(DNS_ZONE_VALID(zone));
5977 return (&zone->xfrsource6);
5978 }
5979
5980 isc_dscp_t
5981 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5982 REQUIRE(DNS_ZONE_VALID(zone));
5983 return (zone->xfrsource6dscp);
5984 }
5985
5986 isc_result_t
5987 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5988 REQUIRE(DNS_ZONE_VALID(zone));
5989
5990 LOCK_ZONE(zone);
5991 zone->xfrsource6dscp = dscp;
5992 UNLOCK_ZONE(zone);
5993
5994 return (ISC_R_SUCCESS);
5995 }
5996
5997 isc_result_t
5998 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5999 const isc_sockaddr_t *altxfrsource) {
6000 REQUIRE(DNS_ZONE_VALID(zone));
6001
6002 LOCK_ZONE(zone);
6003 zone->altxfrsource4 = *altxfrsource;
6004 UNLOCK_ZONE(zone);
6005
6006 return (ISC_R_SUCCESS);
6007 }
6008
6009 isc_sockaddr_t *
6010 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
6011 REQUIRE(DNS_ZONE_VALID(zone));
6012 return (&zone->altxfrsource4);
6013 }
6014
6015 isc_result_t
6016 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6017 REQUIRE(DNS_ZONE_VALID(zone));
6018
6019 LOCK_ZONE(zone);
6020 zone->altxfrsource4dscp = dscp;
6021 UNLOCK_ZONE(zone);
6022
6023 return (ISC_R_SUCCESS);
6024 }
6025
6026 isc_dscp_t
6027 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
6028 REQUIRE(DNS_ZONE_VALID(zone));
6029 return (zone->altxfrsource4dscp);
6030 }
6031
6032 isc_result_t
6033 dns_zone_setaltxfrsource6(dns_zone_t *zone,
6034 const isc_sockaddr_t *altxfrsource) {
6035 REQUIRE(DNS_ZONE_VALID(zone));
6036
6037 LOCK_ZONE(zone);
6038 zone->altxfrsource6 = *altxfrsource;
6039 UNLOCK_ZONE(zone);
6040
6041 return (ISC_R_SUCCESS);
6042 }
6043
6044 isc_sockaddr_t *
6045 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
6046 REQUIRE(DNS_ZONE_VALID(zone));
6047 return (&zone->altxfrsource6);
6048 }
6049
6050 isc_result_t
6051 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6052 REQUIRE(DNS_ZONE_VALID(zone));
6053
6054 LOCK_ZONE(zone);
6055 zone->altxfrsource6dscp = dscp;
6056 UNLOCK_ZONE(zone);
6057
6058 return (ISC_R_SUCCESS);
6059 }
6060
6061 isc_dscp_t
6062 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
6063 REQUIRE(DNS_ZONE_VALID(zone));
6064 return (zone->altxfrsource6dscp);
6065 }
6066
6067 isc_result_t
6068 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6069 REQUIRE(DNS_ZONE_VALID(zone));
6070
6071 LOCK_ZONE(zone);
6072 zone->notifysrc4 = *notifysrc;
6073 UNLOCK_ZONE(zone);
6074
6075 return (ISC_R_SUCCESS);
6076 }
6077
6078 isc_sockaddr_t *
6079 dns_zone_getnotifysrc4(dns_zone_t *zone) {
6080 REQUIRE(DNS_ZONE_VALID(zone));
6081 return (&zone->notifysrc4);
6082 }
6083
6084 isc_result_t
6085 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6086 REQUIRE(DNS_ZONE_VALID(zone));
6087
6088 LOCK_ZONE(zone);
6089 zone->notifysrc4dscp = dscp;
6090 UNLOCK_ZONE(zone);
6091
6092 return (ISC_R_SUCCESS);
6093 }
6094
6095 isc_dscp_t
6096 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
6097 REQUIRE(DNS_ZONE_VALID(zone));
6098 return (zone->notifysrc4dscp);
6099 }
6100
6101 isc_result_t
6102 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
6103 REQUIRE(DNS_ZONE_VALID(zone));
6104
6105 LOCK_ZONE(zone);
6106 zone->notifysrc6 = *notifysrc;
6107 UNLOCK_ZONE(zone);
6108
6109 return (ISC_R_SUCCESS);
6110 }
6111
6112 isc_sockaddr_t *
6113 dns_zone_getnotifysrc6(dns_zone_t *zone) {
6114 REQUIRE(DNS_ZONE_VALID(zone));
6115 return (&zone->notifysrc6);
6116 }
6117
6118 static bool
6119 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
6120 uint32_t count) {
6121 unsigned int i;
6122
6123 for (i = 0; i < count; i++) {
6124 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i])) {
6125 return (false);
6126 }
6127 }
6128 return (true);
6129 }
6130
6131 static bool
6132 same_keynames(dns_name_t *const *oldlist, dns_name_t *const *newlist,
6133 uint32_t count) {
6134 unsigned int i;
6135
6136 if (oldlist == NULL && newlist == NULL) {
6137 return (true);
6138 }
6139 if (oldlist == NULL || newlist == NULL) {
6140 return (false);
6141 }
6142
6143 for (i = 0; i < count; i++) {
6144 if (oldlist[i] == NULL && newlist[i] == NULL) {
6145 continue;
6146 }
6147 if (oldlist[i] == NULL || newlist[i] == NULL ||
6148 !dns_name_equal(oldlist[i], newlist[i]))
6149 {
6150 return (false);
6151 }
6152 }
6153 return (true);
6154 }
6155
6156 static void
6157 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
6158 dns_name_t ***keynamesp, unsigned int *countp,
6159 isc_mem_t *mctx) {
6160 unsigned int count;
6161 isc_sockaddr_t *addrs;
6162 isc_dscp_t *dscps;
6163 dns_name_t **keynames;
6164
6165 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
6166 keynamesp != NULL);
6167
6168 count = *countp;
6169 *countp = 0;
6170 addrs = *addrsp;
6171 *addrsp = NULL;
6172 dscps = *dscpsp;
6173 *dscpsp = NULL;
6174 keynames = *keynamesp;
6175 *keynamesp = NULL;
6176
6177 if (addrs != NULL) {
6178 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
6179 }
6180
6181 if (dscps != NULL) {
6182 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
6183 }
6184
6185 if (keynames != NULL) {
6186 unsigned int i;
6187 for (i = 0; i < count; i++) {
6188 if (keynames[i] != NULL) {
6189 dns_name_free(keynames[i], mctx);
6190 isc_mem_put(mctx, keynames[i],
6191 sizeof(dns_name_t));
6192 keynames[i] = NULL;
6193 }
6194 }
6195 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
6196 }
6197 }
6198
6199 static isc_result_t
6200 set_addrkeylist(unsigned int count, const isc_sockaddr_t *addrs,
6201 isc_sockaddr_t **newaddrsp, const isc_dscp_t *dscp,
6202 isc_dscp_t **newdscpp, dns_name_t **names,
6203 dns_name_t ***newnamesp, isc_mem_t *mctx) {
6204 isc_sockaddr_t *newaddrs = NULL;
6205 isc_dscp_t *newdscp = NULL;
6206 dns_name_t **newnames = NULL;
6207 unsigned int i;
6208
6209 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
6210 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
6211 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
6212
6213 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
6214 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
6215
6216 if (dscp != NULL) {
6217 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
6218 memmove(newdscp, dscp, count * sizeof(*newdscp));
6219 } else {
6220 newdscp = NULL;
6221 }
6222
6223 if (names != NULL) {
6224 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
6225 for (i = 0; i < count; i++) {
6226 newnames[i] = NULL;
6227 }
6228 for (i = 0; i < count; i++) {
6229 if (names[i] != NULL) {
6230 newnames[i] = isc_mem_get(mctx,
6231 sizeof(dns_name_t));
6232 dns_name_init(newnames[i], NULL);
6233 dns_name_dup(names[i], mctx, newnames[i]);
6234 }
6235 }
6236 } else {
6237 newnames = NULL;
6238 }
6239
6240 *newdscpp = newdscp;
6241 *newaddrsp = newaddrs;
6242 *newnamesp = newnames;
6243 return (ISC_R_SUCCESS);
6244 }
6245
6246 isc_result_t
6247 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
6248 REQUIRE(DNS_ZONE_VALID(zone));
6249
6250 LOCK_ZONE(zone);
6251 zone->notifysrc6dscp = dscp;
6252 UNLOCK_ZONE(zone);
6253
6254 return (ISC_R_SUCCESS);
6255 }
6256
6257 isc_dscp_t
6258 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
6259 REQUIRE(DNS_ZONE_VALID(zone));
6260 return (zone->notifysrc6dscp);
6261 }
6262
6263 isc_result_t
6264 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
6265 uint32_t count) {
6266 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
6267 count));
6268 }
6269
6270 isc_result_t
6271 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6272 dns_name_t **keynames, uint32_t count) {
6273 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
6274 count));
6275 }
6276
6277 isc_result_t
6278 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6279 const isc_dscp_t *dscps, dns_name_t **keynames,
6280 uint32_t count) {
6281 isc_result_t result;
6282 isc_sockaddr_t *newaddrs = NULL;
6283 isc_dscp_t *newdscps = NULL;
6284 dns_name_t **newnames = NULL;
6285
6286 REQUIRE(DNS_ZONE_VALID(zone));
6287 REQUIRE(count == 0 || notify != NULL);
6288 if (keynames != NULL) {
6289 REQUIRE(count != 0);
6290 }
6291
6292 LOCK_ZONE(zone);
6293
6294 if (count == zone->notifycnt &&
6295 same_addrs(zone->notify, notify, count) &&
6296 same_keynames(zone->notifykeynames, keynames, count))
6297 {
6298 goto unlock;
6299 }
6300
6301 clear_addresskeylist(&zone->notify, &zone->notifydscp,
6302 &zone->notifykeynames, &zone->notifycnt,
6303 zone->mctx);
6304
6305 if (count == 0) {
6306 goto unlock;
6307 }
6308
6309 /*
6310 * Set up the notify and notifykey lists
6311 */
6312 result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
6313 keynames, &newnames, zone->mctx);
6314 if (result != ISC_R_SUCCESS) {
6315 goto unlock;
6316 }
6317
6318 /*
6319 * Everything is ok so attach to the zone.
6320 */
6321 zone->notify = newaddrs;
6322 zone->notifydscp = newdscps;
6323 zone->notifykeynames = newnames;
6324 zone->notifycnt = count;
6325 unlock:
6326 UNLOCK_ZONE(zone);
6327 return (ISC_R_SUCCESS);
6328 }
6329
6330 isc_result_t
6331 dns_zone_setprimaries(dns_zone_t *zone, const isc_sockaddr_t *masters,
6332 uint32_t count) {
6333 isc_result_t result;
6334
6335 result = dns_zone_setprimarieswithkeys(zone, masters, NULL, count);
6336 return (result);
6337 }
6338
6339 isc_result_t
6340 dns_zone_setprimarieswithkeys(dns_zone_t *zone, const isc_sockaddr_t *masters,
6341 dns_name_t **keynames, uint32_t count) {
6342 isc_result_t result = ISC_R_SUCCESS;
6343 isc_sockaddr_t *newaddrs = NULL;
6344 isc_dscp_t *newdscps = NULL;
6345 dns_name_t **newnames = NULL;
6346 bool *newok;
6347 unsigned int i;
6348
6349 REQUIRE(DNS_ZONE_VALID(zone));
6350 REQUIRE(count == 0 || masters != NULL);
6351 if (keynames != NULL) {
6352 REQUIRE(count != 0);
6353 }
6354
6355 LOCK_ZONE(zone);
6356 /*
6357 * The refresh code assumes that 'primaries' wouldn't change under it.
6358 * If it will change then kill off any current refresh in progress
6359 * and update the primaries info. If it won't change then we can just
6360 * unlock and exit.
6361 */
6362 if (count != zone->masterscnt ||
6363 !same_addrs(zone->masters, masters, count) ||
6364 !same_keynames(zone->masterkeynames, keynames, count))
6365 {
6366 if (zone->request != NULL) {
6367 dns_request_cancel(zone->request);
6368 }
6369 } else {
6370 goto unlock;
6371 }
6372
6373 /*
6374 * This needs to happen before clear_addresskeylist() sets
6375 * zone->masterscnt to 0:
6376 */
6377 if (zone->mastersok != NULL) {
6378 isc_mem_put(zone->mctx, zone->mastersok,
6379 zone->masterscnt * sizeof(bool));
6380 zone->mastersok = NULL;
6381 }
6382 clear_addresskeylist(&zone->masters, &zone->masterdscps,
6383 &zone->masterkeynames, &zone->masterscnt,
6384 zone->mctx);
6385 /*
6386 * If count == 0, don't allocate any space for masters, mastersok or
6387 * keynames so internally, those pointers are NULL if count == 0
6388 */
6389 if (count == 0) {
6390 goto unlock;
6391 }
6392
6393 /*
6394 * mastersok must contain count elements
6395 */
6396 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6397 for (i = 0; i < count; i++) {
6398 newok[i] = false;
6399 }
6400
6401 /*
6402 * Now set up the primaries and primary key lists
6403 */
6404 result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
6405 keynames, &newnames, zone->mctx);
6406 INSIST(newdscps == NULL);
6407 if (result != ISC_R_SUCCESS) {
6408 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6409 goto unlock;
6410 }
6411
6412 /*
6413 * Everything is ok so attach to the zone.
6414 */
6415 zone->curmaster = 0;
6416 zone->mastersok = newok;
6417 zone->masters = newaddrs;
6418 zone->masterdscps = newdscps;
6419 zone->masterkeynames = newnames;
6420 zone->masterscnt = count;
6421 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6422
6423 unlock:
6424 UNLOCK_ZONE(zone);
6425 return (result);
6426 }
6427
6428 isc_result_t
6429 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6430 isc_result_t result = ISC_R_SUCCESS;
6431
6432 REQUIRE(DNS_ZONE_VALID(zone));
6433
6434 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6435 if (zone->db == NULL) {
6436 result = DNS_R_NOTLOADED;
6437 } else {
6438 dns_db_attach(zone->db, dpb);
6439 }
6440 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6441
6442 return (result);
6443 }
6444
6445 void
6446 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6447 REQUIRE(DNS_ZONE_VALID(zone));
6448 REQUIRE(zone->type == dns_zone_staticstub);
6449
6450 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6451 REQUIRE(zone->db == NULL);
6452 dns_db_attach(db, &zone->db);
6453 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6454 }
6455
6456 /*
6457 * Coordinates the starting of routine jobs.
6458 */
6459 void
6460 dns_zone_maintenance(dns_zone_t *zone) {
6461 const char me[] = "dns_zone_maintenance";
6462 isc_time_t now;
6463
6464 REQUIRE(DNS_ZONE_VALID(zone));
6465 ENTER;
6466
6467 LOCK_ZONE(zone);
6468 TIME_NOW(&now);
6469 zone_settimer(zone, &now);
6470 UNLOCK_ZONE(zone);
6471 }
6472
6473 static inline bool
6474 was_dumping(dns_zone_t *zone) {
6475 REQUIRE(LOCKED_ZONE(zone));
6476
6477 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6478 return (true);
6479 }
6480
6481 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6482 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6483 isc_time_settoepoch(&zone->dumptime);
6484 return (false);
6485 }
6486
6487 /*%
6488 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6489 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6490 * Only load the public part of a given key if it is not active at timestamp
6491 * 'now'. Store the number of keys found in 'nkeys'.
6492 */
6493 isc_result_t
6494 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6495 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6496 dst_key_t **keys, unsigned int *nkeys) {
6497 isc_result_t result;
6498 dns_dbnode_t *node = NULL;
6499 const char *directory = dns_zone_getkeydirectory(zone);
6500
6501 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6502 memset(keys, 0, sizeof(*keys) * maxkeys);
6503 result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6504 directory, now, mctx, maxkeys, keys,
6505 nkeys);
6506 if (result == ISC_R_NOTFOUND) {
6507 result = ISC_R_SUCCESS;
6508 }
6509 failure:
6510 if (node != NULL) {
6511 dns_db_detachnode(db, &node);
6512 }
6513 return (result);
6514 }
6515
6516 static isc_result_t
6517 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6518 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata) {
6519 isc_result_t result;
6520
6521 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0) {
6522 return (ISC_R_SUCCESS);
6523 }
6524 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6525 name, ttl, rdata);
6526 if (result != ISC_R_SUCCESS) {
6527 return (result);
6528 }
6529 rdata->flags |= DNS_RDATA_OFFLINE;
6530 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6531 name, ttl, rdata);
6532 zonediff->offline = true;
6533 return (result);
6534 }
6535
6536 static void
6537 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when,
6538 isc_stdtime_t now) {
6539 unsigned int delta;
6540 char timebuf[80];
6541
6542 zone->key_expiry = when;
6543 if (when <= now) {
6544 dns_zone_log(zone, ISC_LOG_ERROR,
6545 "DNSKEY RRSIG(s) have expired");
6546 isc_time_settoepoch(&zone->keywarntime);
6547 } else if (when < now + 7 * 24 * 3600) {
6548 isc_time_t t;
6549 isc_time_set(&t, when, 0);
6550 isc_time_formattimestamp(&t, timebuf, 80);
6551 dns_zone_log(zone, ISC_LOG_WARNING,
6552 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6553 timebuf);
6554 delta = when - now;
6555 delta--; /* loop prevention */
6556 delta /= 24 * 3600; /* to whole days */
6557 delta *= 24 * 3600; /* to seconds */
6558 isc_time_set(&zone->keywarntime, when - delta, 0);
6559 } else {
6560 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6561 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6562 dns_zone_log(zone, ISC_LOG_NOTICE, "setting keywarntime to %s",
6563 timebuf);
6564 }
6565 }
6566
6567 /*
6568 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6569 * have no new key.
6570 */
6571 static bool
6572 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6573 bool *warn) {
6574 unsigned int i = 0;
6575 isc_result_t ret;
6576 bool have_ksk = false, have_zsk = false;
6577 bool have_pksk = false, have_pzsk = false;
6578
6579 for (i = 0; i < nkeys; i++) {
6580 bool ksk, zsk;
6581
6582 if (have_pksk && have_ksk && have_pzsk && have_zsk) {
6583 break;
6584 }
6585
6586 if (rrsig_ptr->algorithm != dst_key_alg(keys[i])) {
6587 continue;
6588 }
6589
6590 ret = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6591 if (ret != ISC_R_SUCCESS) {
6592 ksk = KSK(keys[i]);
6593 }
6594 ret = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6595 if (ret != ISC_R_SUCCESS) {
6596 zsk = !KSK(keys[i]);
6597 }
6598
6599 if (ksk) {
6600 have_ksk = true;
6601 if (dst_key_isprivate(keys[i])) {
6602 have_pksk = true;
6603 }
6604 }
6605 if (zsk) {
6606 have_zsk = true;
6607 if (dst_key_isprivate(keys[i])) {
6608 have_pzsk = true;
6609 }
6610 }
6611 }
6612
6613 if (have_zsk && have_ksk && !have_pzsk) {
6614 *warn = true;
6615 }
6616
6617 /*
6618 * It's okay to delete a signature if there is an active key
6619 * with the same algorithm to replace it.
6620 */
6621 if (have_pksk || have_pzsk) {
6622 return (true);
6623 }
6624
6625 /*
6626 * Failing that, it is *not* okay to delete a signature
6627 * if the associated public key is still in the DNSKEY RRset
6628 */
6629 for (i = 0; i < nkeys; i++) {
6630 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6631 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6632 {
6633 return (false);
6634 }
6635 }
6636
6637 /*
6638 * But if the key is gone, then go ahead.
6639 */
6640 return (true);
6641 }
6642
6643 /*
6644 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6645 * See also update.c:del_keysigs().
6646 */
6647 static isc_result_t
6648 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6649 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6650 unsigned int nkeys, isc_stdtime_t now, bool incremental) {
6651 isc_result_t result;
6652 dns_dbnode_t *node = NULL;
6653 dns_rdataset_t rdataset;
6654 unsigned int i;
6655 dns_rdata_rrsig_t rrsig;
6656 bool found;
6657 int64_t timewarn = 0, timemaybe = 0;
6658
6659 dns_rdataset_init(&rdataset);
6660
6661 if (type == dns_rdatatype_nsec3) {
6662 result = dns_db_findnsec3node(db, name, false, &node);
6663 } else {
6664 result = dns_db_findnode(db, name, false, &node);
6665 }
6666 if (result == ISC_R_NOTFOUND) {
6667 return (ISC_R_SUCCESS);
6668 }
6669 if (result != ISC_R_SUCCESS) {
6670 goto failure;
6671 }
6672 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6673 (isc_stdtime_t)0, &rdataset, NULL);
6674 dns_db_detachnode(db, &node);
6675
6676 if (result == ISC_R_NOTFOUND) {
6677 INSIST(!dns_rdataset_isassociated(&rdataset));
6678 return (ISC_R_SUCCESS);
6679 }
6680 if (result != ISC_R_SUCCESS) {
6681 INSIST(!dns_rdataset_isassociated(&rdataset));
6682 goto failure;
6683 }
6684
6685 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
6686 result = dns_rdataset_next(&rdataset))
6687 {
6688 dns_rdata_t rdata = DNS_RDATA_INIT;
6689
6690 dns_rdataset_current(&rdataset, &rdata);
6691 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6692 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6693
6694 if (type != dns_rdatatype_dnskey && type != dns_rdatatype_cds &&
6695 type != dns_rdatatype_cdnskey)
6696 {
6697 bool warn = false, deleted = false;
6698 if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
6699 result = update_one_rr(db, ver, zonediff->diff,
6700 DNS_DIFFOP_DELRESIGN,
6701 name, rdataset.ttl,
6702 &rdata);
6703 if (result != ISC_R_SUCCESS) {
6704 break;
6705 }
6706 deleted = true;
6707 }
6708 if (warn) {
6709 /*
6710 * At this point, we've got an RRSIG,
6711 * which is signed by an inactive key.
6712 * An administrator needs to provide a new
6713 * key/alg, but until that time, we want to
6714 * keep the old RRSIG. Marking the key as
6715 * offline will prevent us spinning waiting
6716 * for the private part.
6717 */
6718 if (incremental && !deleted) {
6719 result = offline(db, ver, zonediff,
6720 name, rdataset.ttl,
6721 &rdata);
6722 if (result != ISC_R_SUCCESS) {
6723 break;
6724 }
6725 }
6726
6727 /*
6728 * Log the key id and algorithm of
6729 * the inactive key with no replacement
6730 */
6731 if (zone->log_key_expired_timer <= now) {
6732 char origin[DNS_NAME_FORMATSIZE];
6733 char algbuf[DNS_NAME_FORMATSIZE];
6734 dns_name_format(&zone->origin, origin,
6735 sizeof(origin));
6736 dns_secalg_format(rrsig.algorithm,
6737 algbuf,
6738 sizeof(algbuf));
6739 dns_zone_log(zone, ISC_LOG_WARNING,
6740 "Key %s/%s/%d "
6741 "missing or inactive "
6742 "and has no replacement: "
6743 "retaining signatures.",
6744 origin, algbuf,
6745 rrsig.keyid);
6746 zone->log_key_expired_timer = now +
6747 3600;
6748 }
6749 }
6750 continue;
6751 }
6752
6753 /*
6754 * KSK RRSIGs requires special processing.
6755 */
6756 found = false;
6757 for (i = 0; i < nkeys; i++) {
6758 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6759 rrsig.keyid == dst_key_id(keys[i]))
6760 {
6761 found = true;
6762 /*
6763 * Mark offline DNSKEY.
6764 * We want the earliest offline expire time
6765 * iff there is a new offline signature.
6766 */
6767 if (!dst_key_inactive(keys[i]) &&
6768 !dst_key_isprivate(keys[i])) {
6769 int64_t timeexpire = dns_time64_from32(
6770 rrsig.timeexpire);
6771 if (timewarn != 0 &&
6772 timewarn > timeexpire) {
6773 timewarn = timeexpire;
6774 }
6775 if (rdata.flags & DNS_RDATA_OFFLINE) {
6776 if (timemaybe == 0 ||
6777 timemaybe > timeexpire) {
6778 timemaybe = timeexpire;
6779 }
6780 break;
6781 }
6782 if (timewarn == 0) {
6783 timewarn = timemaybe;
6784 }
6785 if (timewarn == 0 ||
6786 timewarn > timeexpire) {
6787 timewarn = timeexpire;
6788 }
6789 result = offline(db, ver, zonediff,
6790 name, rdataset.ttl,
6791 &rdata);
6792 break;
6793 }
6794 result = update_one_rr(db, ver, zonediff->diff,
6795 DNS_DIFFOP_DELRESIGN,
6796 name, rdataset.ttl,
6797 &rdata);
6798 break;
6799 }
6800 }
6801
6802 /*
6803 * If there is not a matching DNSKEY then
6804 * delete the RRSIG.
6805 */
6806 if (!found) {
6807 result = update_one_rr(db, ver, zonediff->diff,
6808 DNS_DIFFOP_DELRESIGN, name,
6809 rdataset.ttl, &rdata);
6810 }
6811 if (result != ISC_R_SUCCESS) {
6812 break;
6813 }
6814 }
6815
6816 dns_rdataset_disassociate(&rdataset);
6817 if (result == ISC_R_NOMORE) {
6818 result = ISC_R_SUCCESS;
6819 }
6820 if (timewarn > 0) {
6821 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6822 if (timewarn == stdwarn) {
6823 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6824 now);
6825 } else {
6826 dns_zone_log(zone, ISC_LOG_ERROR,
6827 "key expiry warning time out of range");
6828 }
6829 }
6830 failure:
6831 if (node != NULL) {
6832 dns_db_detachnode(db, &node);
6833 }
6834 return (result);
6835 }
6836
6837 static isc_result_t
6838 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name, dns_zone_t *zone,
6839 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6840 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
6841 isc_stdtime_t expire, bool check_ksk, bool keyset_kskonly) {
6842 isc_result_t result;
6843 dns_dbnode_t *node = NULL;
6844 dns_stats_t *dnssecsignstats;
6845 dns_rdataset_t rdataset;
6846 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6847 unsigned char data[1024]; /* XXX */
6848 isc_buffer_t buffer;
6849 unsigned int i, j;
6850 bool use_kasp = false;
6851
6852 if (dns_zone_use_kasp(zone)) {
6853 check_ksk = false;
6854 keyset_kskonly = true;
6855 use_kasp = true;
6856 }
6857
6858 dns_rdataset_init(&rdataset);
6859 isc_buffer_init(&buffer, data, sizeof(data));
6860
6861 if (type == dns_rdatatype_nsec3) {
6862 result = dns_db_findnsec3node(db, name, false, &node);
6863 } else {
6864 result = dns_db_findnode(db, name, false, &node);
6865 }
6866 if (result == ISC_R_NOTFOUND) {
6867 return (ISC_R_SUCCESS);
6868 }
6869 if (result != ISC_R_SUCCESS) {
6870 goto failure;
6871 }
6872 result = dns_db_findrdataset(db, node, ver, type, 0, (isc_stdtime_t)0,
6873 &rdataset, NULL);
6874 dns_db_detachnode(db, &node);
6875 if (result == ISC_R_NOTFOUND) {
6876 INSIST(!dns_rdataset_isassociated(&rdataset));
6877 return (ISC_R_SUCCESS);
6878 }
6879 if (result != ISC_R_SUCCESS) {
6880 INSIST(!dns_rdataset_isassociated(&rdataset));
6881 goto failure;
6882 }
6883
6884 for (i = 0; i < nkeys; i++) {
6885 bool both = false;
6886
6887 /* Don't add signatures for offline or inactive keys */
6888 if (!dst_key_isprivate(keys[i])) {
6889 continue;
6890 }
6891 if (dst_key_inactive(keys[i])) {
6892 continue;
6893 }
6894
6895 if (check_ksk && !REVOKE(keys[i])) {
6896 bool have_ksk, have_nonksk;
6897 if (KSK(keys[i])) {
6898 have_ksk = true;
6899 have_nonksk = false;
6900 } else {
6901 have_ksk = false;
6902 have_nonksk = true;
6903 }
6904
6905 for (j = 0; j < nkeys; j++) {
6906 if (j == i || ALG(keys[i]) != ALG(keys[j])) {
6907 continue;
6908 }
6909
6910 /* Don't consider inactive keys, however
6911 * the key may be temporary offline, so do
6912 * consider keys which private key files are
6913 * unavailable.
6914 */
6915 if (dst_key_inactive(keys[j])) {
6916 continue;
6917 }
6918
6919 if (REVOKE(keys[j])) {
6920 continue;
6921 }
6922 if (KSK(keys[j])) {
6923 have_ksk = true;
6924 } else {
6925 have_nonksk = true;
6926 }
6927 both = have_ksk && have_nonksk;
6928 if (both) {
6929 break;
6930 }
6931 }
6932 }
6933 if (use_kasp) {
6934 /*
6935 * A dnssec-policy is found. Check what RRsets this
6936 * key should sign.
6937 */
6938 isc_result_t kresult;
6939 isc_stdtime_t when;
6940 bool ksk = false;
6941 bool zsk = false;
6942
6943 kresult = dst_key_getbool(keys[i], DST_BOOL_KSK, &ksk);
6944 if (kresult != ISC_R_SUCCESS) {
6945 if (KSK(keys[i])) {
6946 ksk = true;
6947 }
6948 }
6949 kresult = dst_key_getbool(keys[i], DST_BOOL_ZSK, &zsk);
6950 if (kresult != ISC_R_SUCCESS) {
6951 if (!KSK(keys[i])) {
6952 zsk = true;
6953 }
6954 }
6955
6956 if (type == dns_rdatatype_dnskey ||
6957 type == dns_rdatatype_cdnskey ||
6958 type == dns_rdatatype_cds)
6959 {
6960 /*
6961 * DNSKEY RRset is signed with KSK.
6962 * CDS and CDNSKEY RRsets too (RFC 7344, 4.1).
6963 */
6964 if (!ksk) {
6965 continue;
6966 }
6967 } else if (!zsk) {
6968 /*
6969 * Other RRsets are signed with ZSK.
6970 */
6971 continue;
6972 } else if (!dst_key_is_signing(keys[i], DST_BOOL_ZSK,
6973 inception, &when)) {
6974 /*
6975 * This key is not active for zone-signing.
6976 */
6977 continue;
6978 }
6979
6980 /*
6981 * If this key is revoked, it may only sign the
6982 * DNSKEY RRset.
6983 */
6984 if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
6985 continue;
6986 }
6987 } else if (both) {
6988 /*
6989 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6990 */
6991 if (type == dns_rdatatype_dnskey ||
6992 type == dns_rdatatype_cdnskey ||
6993 type == dns_rdatatype_cds)
6994 {
6995 if (!KSK(keys[i]) && keyset_kskonly) {
6996 continue;
6997 }
6998 } else if (KSK(keys[i])) {
6999 continue;
7000 }
7001 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
7002 continue;
7003 }
7004
7005 /* Calculate the signature, creating a RRSIG RDATA. */
7006 isc_buffer_clear(&buffer);
7007 CHECK(dns_dnssec_sign(name, &rdataset, keys[i], &inception,
7008 &expire, mctx, &buffer, &sig_rdata));
7009
7010 /* Update the database and journal with the RRSIG. */
7011 /* XXX inefficient - will cause dataset merging */
7012 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN, name,
7013 rdataset.ttl, &sig_rdata));
7014 dns_rdata_reset(&sig_rdata);
7015 isc_buffer_init(&buffer, data, sizeof(data));
7016
7017 /* Update DNSSEC sign statistics. */
7018 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7019 if (dnssecsignstats != NULL) {
7020 /* Generated a new signature. */
7021 dns_dnssecsignstats_increment(dnssecsignstats,
7022 ID(keys[i]),
7023 (uint8_t)ALG(keys[i]),
7024 dns_dnssecsignstats_sign);
7025 /* This is a refresh. */
7026 dns_dnssecsignstats_increment(
7027 dnssecsignstats, ID(keys[i]),
7028 (uint8_t)ALG(keys[i]),
7029 dns_dnssecsignstats_refresh);
7030 }
7031 }
7032
7033 failure:
7034 if (dns_rdataset_isassociated(&rdataset)) {
7035 dns_rdataset_disassociate(&rdataset);
7036 }
7037 if (node != NULL) {
7038 dns_db_detachnode(db, &node);
7039 }
7040 return (result);
7041 }
7042
7043 static void
7044 zone_resigninc(dns_zone_t *zone) {
7045 const char *me = "zone_resigninc";
7046 dns_db_t *db = NULL;
7047 dns_dbversion_t *version = NULL;
7048 dns_diff_t _sig_diff;
7049 dns__zonediff_t zonediff;
7050 dns_fixedname_t fixed;
7051 dns_name_t *name;
7052 dns_rdataset_t rdataset;
7053 dns_rdatatype_t covers;
7054 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7055 bool check_ksk, keyset_kskonly = false;
7056 isc_result_t result;
7057 isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
7058 uint32_t sigvalidityinterval, expiryinterval;
7059 unsigned int i;
7060 unsigned int nkeys = 0;
7061 unsigned int resign;
7062
7063 ENTER;
7064
7065 dns_rdataset_init(&rdataset);
7066 dns_diff_init(zone->mctx, &_sig_diff);
7067 zonediff_init(&zonediff, &_sig_diff);
7068
7069 /*
7070 * Zone is frozen or automatic resigning is disabled.
7071 * Pause for 5 minutes.
7072 */
7073 if (zone->update_disabled ||
7074 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN)) {
7075 result = ISC_R_FAILURE;
7076 goto failure;
7077 }
7078
7079 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7080 dns_db_attach(zone->db, &db);
7081 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7082
7083 result = dns_db_newversion(db, &version);
7084 if (result != ISC_R_SUCCESS) {
7085 dns_zone_log(zone, ISC_LOG_ERROR,
7086 "zone_resigninc:dns_db_newversion -> %s",
7087 dns_result_totext(result));
7088 goto failure;
7089 }
7090
7091 isc_stdtime_get(&now);
7092
7093 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7094 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7095 if (result != ISC_R_SUCCESS) {
7096 dns_zone_log(zone, ISC_LOG_ERROR,
7097 "zone_resigninc:dns__zone_findkeys -> %s",
7098 dns_result_totext(result));
7099 goto failure;
7100 }
7101
7102 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7103 inception = now - 3600; /* Allow for clock skew. */
7104 soaexpire = now + sigvalidityinterval;
7105 expiryinterval = dns_zone_getsigresigninginterval(zone);
7106 if (expiryinterval > sigvalidityinterval) {
7107 expiryinterval = sigvalidityinterval;
7108 } else {
7109 expiryinterval = sigvalidityinterval - expiryinterval;
7110 }
7111
7112 /*
7113 * Spread out signatures over time if they happen to be
7114 * clumped. We don't do this for each add_sigs() call as
7115 * we still want some clustering to occur. In normal operations
7116 * the records should be re-signed as they fall due and they should
7117 * already be spread out. However if the server is off for a
7118 * period we need to ensure that the clusters don't become
7119 * synchronised by using the full jitter range.
7120 */
7121 if (sigvalidityinterval >= 3600U) {
7122 uint32_t normaljitter, fulljitter;
7123 if (sigvalidityinterval > 7200U) {
7124 normaljitter = isc_random_uniform(3600);
7125 fulljitter = isc_random_uniform(expiryinterval);
7126 } else {
7127 normaljitter = fulljitter = isc_random_uniform(1200);
7128 }
7129 expire = soaexpire - normaljitter - 1;
7130 fullexpire = soaexpire - fulljitter - 1;
7131 } else {
7132 expire = fullexpire = soaexpire - 1;
7133 }
7134 stop = now + 5;
7135
7136 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7137 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7138
7139 name = dns_fixedname_initname(&fixed);
7140 result = dns_db_getsigningtime(db, &rdataset, name);
7141 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
7142 dns_zone_log(zone, ISC_LOG_ERROR,
7143 "zone_resigninc:dns_db_getsigningtime -> %s",
7144 dns_result_totext(result));
7145 }
7146
7147 i = 0;
7148 while (result == ISC_R_SUCCESS) {
7149 resign = rdataset.resign -
7150 dns_zone_getsigresigninginterval(zone);
7151 covers = rdataset.covers;
7152 dns_rdataset_disassociate(&rdataset);
7153
7154 /*
7155 * Stop if we hit the SOA as that means we have walked the
7156 * entire zone. The SOA record should always be the most
7157 * recent signature.
7158 */
7159 /* XXXMPA increase number of RRsets signed pre call */
7160 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
7161 resign > stop) {
7162 break;
7163 }
7164
7165 result = del_sigs(zone, db, version, name, covers, &zonediff,
7166 zone_keys, nkeys, now, true);
7167 if (result != ISC_R_SUCCESS) {
7168 dns_zone_log(zone, ISC_LOG_ERROR,
7169 "zone_resigninc:del_sigs -> %s",
7170 dns_result_totext(result));
7171 break;
7172 }
7173
7174 /*
7175 * If re-signing is over 5 minutes late use 'fullexpire'
7176 * to redistribute the signature over the complete
7177 * re-signing window, otherwise only add a small amount
7178 * of jitter.
7179 */
7180 result = add_sigs(db, version, name, zone, covers,
7181 zonediff.diff, zone_keys, nkeys, zone->mctx,
7182 inception,
7183 resign > (now - 300) ? expire : fullexpire,
7184 check_ksk, keyset_kskonly);
7185 if (result != ISC_R_SUCCESS) {
7186 dns_zone_log(zone, ISC_LOG_ERROR,
7187 "zone_resigninc:add_sigs -> %s",
7188 dns_result_totext(result));
7189 break;
7190 }
7191 result = dns_db_getsigningtime(db, &rdataset, name);
7192 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
7193 result = ISC_R_SUCCESS;
7194 break;
7195 }
7196 if (result != ISC_R_SUCCESS) {
7197 dns_zone_log(zone, ISC_LOG_ERROR,
7198 "zone_resigninc:dns_db_getsigningtime -> "
7199 "%s",
7200 dns_result_totext(result));
7201 }
7202 }
7203
7204 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS) {
7205 goto failure;
7206 }
7207
7208 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
7209 &zonediff, zone_keys, nkeys, now, true);
7210 if (result != ISC_R_SUCCESS) {
7211 dns_zone_log(zone, ISC_LOG_ERROR,
7212 "zone_resigninc:del_sigs -> %s",
7213 dns_result_totext(result));
7214 goto failure;
7215 }
7216
7217 /*
7218 * Did we change anything in the zone?
7219 */
7220 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
7221 /*
7222 * Commit the changes if any key has been marked as offline.
7223 */
7224 if (zonediff.offline) {
7225 dns_db_closeversion(db, &version, true);
7226 }
7227 goto failure;
7228 }
7229
7230 /* Increment SOA serial if we have made changes */
7231 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
7232 zone->updatemethod);
7233 if (result != ISC_R_SUCCESS) {
7234 dns_zone_log(zone, ISC_LOG_ERROR,
7235 "zone_resigninc:update_soa_serial -> %s",
7236 dns_result_totext(result));
7237 goto failure;
7238 }
7239
7240 /*
7241 * Generate maximum life time signatures so that the above loop
7242 * termination is sensible.
7243 */
7244 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
7245 zonediff.diff, zone_keys, nkeys, zone->mctx,
7246 inception, soaexpire, check_ksk, keyset_kskonly);
7247 if (result != ISC_R_SUCCESS) {
7248 dns_zone_log(zone, ISC_LOG_ERROR,
7249 "zone_resigninc:add_sigs -> %s",
7250 dns_result_totext(result));
7251 goto failure;
7252 }
7253
7254 /* Write changes to journal file. */
7255 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
7256
7257 /* Everything has succeeded. Commit the changes. */
7258 dns_db_closeversion(db, &version, true);
7259
7260 failure:
7261 dns_diff_clear(&_sig_diff);
7262 for (i = 0; i < nkeys; i++) {
7263 dst_key_free(&zone_keys[i]);
7264 }
7265 if (version != NULL) {
7266 dns_db_closeversion(db, &version, false);
7267 dns_db_detach(&db);
7268 } else if (db != NULL) {
7269 dns_db_detach(&db);
7270 }
7271
7272 LOCK_ZONE(zone);
7273 if (result == ISC_R_SUCCESS) {
7274 set_resigntime(zone);
7275 zone_needdump(zone, DNS_DUMP_DELAY);
7276 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
7277 } else {
7278 /*
7279 * Something failed. Retry in 5 minutes.
7280 */
7281 isc_interval_t ival;
7282 isc_interval_set(&ival, 300, 0);
7283 isc_time_nowplusinterval(&zone->resigntime, &ival);
7284 }
7285 UNLOCK_ZONE(zone);
7286
7287 INSIST(version == NULL);
7288 }
7289
7290 static isc_result_t
7291 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
7292 dns_name_t *newname, bool bottom) {
7293 isc_result_t result;
7294 dns_dbiterator_t *dbit = NULL;
7295 dns_rdatasetiter_t *rdsit = NULL;
7296 dns_dbnode_t *node = NULL;
7297
7298 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
7299 CHECK(dns_dbiterator_seek(dbit, oldname));
7300 do {
7301 result = dns_dbiterator_next(dbit);
7302 if (result == ISC_R_NOMORE) {
7303 CHECK(dns_dbiterator_first(dbit));
7304 }
7305 CHECK(dns_dbiterator_current(dbit, &node, newname));
7306 if (bottom && dns_name_issubdomain(newname, oldname) &&
7307 !dns_name_equal(newname, oldname))
7308 {
7309 dns_db_detachnode(db, &node);
7310 continue;
7311 }
7312 /*
7313 * Is this node empty?
7314 */
7315 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
7316 result = dns_rdatasetiter_first(rdsit);
7317 dns_db_detachnode(db, &node);
7318 dns_rdatasetiter_destroy(&rdsit);
7319 if (result != ISC_R_NOMORE) {
7320 break;
7321 }
7322 } while (1);
7323 failure:
7324 if (node != NULL) {
7325 dns_db_detachnode(db, &node);
7326 }
7327 if (dbit != NULL) {
7328 dns_dbiterator_destroy(&dbit);
7329 }
7330 return (result);
7331 }
7332
7333 static bool
7334 signed_with_good_key(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
7335 dns_dbversion_t *version, dns_rdatatype_t type,
7336 dst_key_t *key) {
7337 isc_result_t result;
7338 dns_rdataset_t rdataset;
7339 dns_rdata_t rdata = DNS_RDATA_INIT;
7340 dns_rdata_rrsig_t rrsig;
7341 int count = 0;
7342 dns_kasp_t *kasp = dns_zone_getkasp(zone);
7343
7344 dns_rdataset_init(&rdataset);
7345 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
7346 type, 0, &rdataset, NULL);
7347 if (result != ISC_R_SUCCESS) {
7348 INSIST(!dns_rdataset_isassociated(&rdataset));
7349 return (false);
7350 }
7351 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7352 result = dns_rdataset_next(&rdataset))
7353 {
7354 dns_rdataset_current(&rdataset, &rdata);
7355 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
7356 INSIST(result == ISC_R_SUCCESS);
7357 if (rrsig.algorithm == dst_key_alg(key) &&
7358 rrsig.keyid == dst_key_id(key)) {
7359 dns_rdataset_disassociate(&rdataset);
7360 return (true);
7361 }
7362 if (rrsig.algorithm == dst_key_alg(key)) {
7363 count++;
7364 }
7365 dns_rdata_reset(&rdata);
7366 }
7367
7368 if (dns_zone_use_kasp(zone)) {
7369 dns_kasp_key_t *kkey;
7370 int zsk_count = 0;
7371 bool approved;
7372
7373 LOCK(&kasp->lock);
7374 for (kkey = ISC_LIST_HEAD(dns_kasp_keys(kasp)); kkey != NULL;
7375 kkey = ISC_LIST_NEXT(kkey, link))
7376 {
7377 if (dns_kasp_key_algorithm(kkey) != dst_key_alg(key)) {
7378 continue;
7379 }
7380 if (dns_kasp_key_zsk(kkey)) {
7381 zsk_count++;
7382 }
7383 }
7384 UNLOCK(&kasp->lock);
7385
7386 if (type == dns_rdatatype_dnskey ||
7387 type == dns_rdatatype_cdnskey || type == dns_rdatatype_cds)
7388 {
7389 /*
7390 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7391 * (RFC 7344, section 4.1 specifies that they must
7392 * be signed with a key in the current DS RRset,
7393 * which would only include KSK's.)
7394 */
7395 approved = false;
7396 } else {
7397 approved = (zsk_count == count);
7398 }
7399
7400 dns_rdataset_disassociate(&rdataset);
7401 return (approved);
7402 }
7403
7404 dns_rdataset_disassociate(&rdataset);
7405 return (false);
7406 }
7407
7408 static isc_result_t
7409 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7410 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom, dns_diff_t *diff) {
7411 dns_fixedname_t fixed;
7412 dns_name_t *next;
7413 dns_rdata_t rdata = DNS_RDATA_INIT;
7414 isc_result_t result;
7415 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
7416
7417 next = dns_fixedname_initname(&fixed);
7418
7419 CHECK(next_active(db, version, name, next, bottom));
7420 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer, &rdata));
7421 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
7422 &rdata));
7423 failure:
7424 return (result);
7425 }
7426
7427 static isc_result_t
7428 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7429 dns_dbversion_t *version, bool *is_bottom_of_zone) {
7430 isc_result_t result;
7431 dns_rdatasetiter_t *iterator = NULL;
7432 dns_rdataset_t rdataset;
7433 bool seen_soa = false, seen_ns = false, seen_dname = false;
7434
7435 REQUIRE(is_bottom_of_zone != NULL);
7436
7437 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7438 if (result != ISC_R_SUCCESS) {
7439 if (result == ISC_R_NOTFOUND) {
7440 result = ISC_R_SUCCESS;
7441 }
7442 return (result);
7443 }
7444
7445 dns_rdataset_init(&rdataset);
7446 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7447 result = dns_rdatasetiter_next(iterator))
7448 {
7449 dns_rdatasetiter_current(iterator, &rdataset);
7450 switch (rdataset.type) {
7451 case dns_rdatatype_soa:
7452 seen_soa = true;
7453 break;
7454 case dns_rdatatype_ns:
7455 seen_ns = true;
7456 break;
7457 case dns_rdatatype_dname:
7458 seen_dname = true;
7459 break;
7460 }
7461 dns_rdataset_disassociate(&rdataset);
7462 }
7463 if (result != ISC_R_NOMORE) {
7464 goto failure;
7465 }
7466 if ((seen_ns && !seen_soa) || seen_dname) {
7467 *is_bottom_of_zone = true;
7468 }
7469 result = ISC_R_SUCCESS;
7470
7471 failure:
7472 dns_rdatasetiter_destroy(&iterator);
7473
7474 return (result);
7475 }
7476
7477 static isc_result_t
7478 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7479 dns_dbnode_t *node, dns_dbversion_t *version, bool build_nsec3,
7480 bool build_nsec, dst_key_t *key, isc_stdtime_t inception,
7481 isc_stdtime_t expire, unsigned int minimum, bool is_ksk,
7482 bool is_zsk, bool keyset_kskonly, bool is_bottom_of_zone,
7483 dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx) {
7484 isc_result_t result;
7485 dns_rdatasetiter_t *iterator = NULL;
7486 dns_rdataset_t rdataset;
7487 dns_rdata_t rdata = DNS_RDATA_INIT;
7488 dns_stats_t *dnssecsignstats;
7489
7490 isc_buffer_t buffer;
7491 unsigned char data[1024];
7492 bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7493
7494 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7495 if (result != ISC_R_SUCCESS) {
7496 if (result == ISC_R_NOTFOUND) {
7497 result = ISC_R_SUCCESS;
7498 }
7499 return (result);
7500 }
7501
7502 dns_rdataset_init(&rdataset);
7503 isc_buffer_init(&buffer, data, sizeof(data));
7504 seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7505 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
7506 result = dns_rdatasetiter_next(iterator))
7507 {
7508 dns_rdatasetiter_current(iterator, &rdataset);
7509 if (rdataset.type == dns_rdatatype_soa) {
7510 seen_soa = true;
7511 } else if (rdataset.type == dns_rdatatype_ns) {
7512 seen_ns = true;
7513 } else if (rdataset.type == dns_rdatatype_ds) {
7514 seen_ds = true;
7515 } else if (rdataset.type == dns_rdatatype_nsec) {
7516 seen_nsec = true;
7517 } else if (rdataset.type == dns_rdatatype_nsec3) {
7518 seen_nsec3 = true;
7519 }
7520 if (rdataset.type != dns_rdatatype_rrsig) {
7521 seen_rr = true;
7522 }
7523 dns_rdataset_disassociate(&rdataset);
7524 }
7525 if (result != ISC_R_NOMORE) {
7526 goto failure;
7527 }
7528 /*
7529 * Going from insecure to NSEC3.
7530 * Don't generate NSEC3 records for NSEC3 records.
7531 */
7532 if (build_nsec3 && !seen_nsec3 && seen_rr) {
7533 bool unsecure = !seen_ds && seen_ns && !seen_soa;
7534 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum, unsecure,
7535 diff));
7536 (*signatures)--;
7537 }
7538 /*
7539 * Going from insecure to NSEC.
7540 * Don't generate NSEC records for NSEC3 records.
7541 */
7542 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7543 /*
7544 * Build a NSEC record except at the origin.
7545 */
7546 if (!dns_name_equal(name, dns_db_origin(db))) {
7547 CHECK(add_nsec(db, version, name, node, minimum,
7548 is_bottom_of_zone, diff));
7549 /* Count a NSEC generation as a signature generation. */
7550 (*signatures)--;
7551 }
7552 }
7553 result = dns_rdatasetiter_first(iterator);
7554 while (result == ISC_R_SUCCESS) {
7555 isc_stdtime_t when;
7556
7557 dns_rdatasetiter_current(iterator, &rdataset);
7558 if (rdataset.type == dns_rdatatype_soa ||
7559 rdataset.type == dns_rdatatype_rrsig) {
7560 goto next_rdataset;
7561 }
7562 if (rdataset.type == dns_rdatatype_dnskey ||
7563 rdataset.type == dns_rdatatype_cdnskey ||
7564 rdataset.type == dns_rdatatype_cds)
7565 {
7566 /*
7567 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7568 * (RFC 7344, section 4.1 specifies that they must
7569 * be signed with a key in the current DS RRset,
7570 * which would only include KSK's.)
7571 */
7572 if (!is_ksk && keyset_kskonly) {
7573 goto next_rdataset;
7574 }
7575 } else if (!is_zsk) {
7576 goto next_rdataset;
7577 } else if (is_zsk && !dst_key_is_signing(key, DST_BOOL_ZSK,
7578 inception, &when)) {
7579 /* Only applies to dnssec-policy. */
7580 if (dns_zone_use_kasp(zone)) {
7581 goto next_rdataset;
7582 }
7583 }
7584
7585 if (seen_ns && !seen_soa && rdataset.type != dns_rdatatype_ds &&
7586 rdataset.type != dns_rdatatype_nsec)
7587 {
7588 goto next_rdataset;
7589 }
7590 if (signed_with_good_key(zone, db, node, version, rdataset.type,
7591 key)) {
7592 goto next_rdataset;
7593 }
7594
7595 /* Calculate the signature, creating a RRSIG RDATA. */
7596 isc_buffer_clear(&buffer);
7597 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception, &expire,
7598 mctx, &buffer, &rdata));
7599 /* Update the database and journal with the RRSIG. */
7600 /* XXX inefficient - will cause dataset merging */
7601 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7602 name, rdataset.ttl, &rdata));
7603 dns_rdata_reset(&rdata);
7604
7605 /* Update DNSSEC sign statistics. */
7606 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7607 if (dnssecsignstats != NULL) {
7608 /* Generated a new signature. */
7609 dns_dnssecsignstats_increment(dnssecsignstats, ID(key),
7610 ALG(key),
7611 dns_dnssecsignstats_sign);
7612 /* This is a refresh. */
7613 dns_dnssecsignstats_increment(
7614 dnssecsignstats, ID(key), ALG(key),
7615 dns_dnssecsignstats_refresh);
7616 }
7617
7618 (*signatures)--;
7619 next_rdataset:
7620 dns_rdataset_disassociate(&rdataset);
7621 result = dns_rdatasetiter_next(iterator);
7622 }
7623 if (result == ISC_R_NOMORE) {
7624 result = ISC_R_SUCCESS;
7625 }
7626 failure:
7627 if (dns_rdataset_isassociated(&rdataset)) {
7628 dns_rdataset_disassociate(&rdataset);
7629 }
7630 if (iterator != NULL) {
7631 dns_rdatasetiter_destroy(&iterator);
7632 }
7633 return (result);
7634 }
7635
7636 /*
7637 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7638 */
7639 static isc_result_t
7640 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7641 dns_ttl_t minimum, bool update_only, dns_diff_t *diff) {
7642 isc_result_t result;
7643 dns_rdataset_t rdataset;
7644 dns_dbnode_t *node = NULL;
7645
7646 CHECK(dns_db_getoriginnode(db, &node));
7647 if (update_only) {
7648 dns_rdataset_init(&rdataset);
7649 result = dns_db_findrdataset(
7650 db, node, version, dns_rdatatype_nsec,
7651 dns_rdatatype_none, 0, &rdataset, NULL);
7652 if (dns_rdataset_isassociated(&rdataset)) {
7653 dns_rdataset_disassociate(&rdataset);
7654 }
7655 if (result == ISC_R_NOTFOUND) {
7656 goto success;
7657 }
7658 if (result != ISC_R_SUCCESS) {
7659 goto failure;
7660 }
7661 }
7662 CHECK(delete_nsec(db, version, node, name, diff));
7663 CHECK(add_nsec(db, version, name, node, minimum, false, diff));
7664 success:
7665 result = ISC_R_SUCCESS;
7666 failure:
7667 if (node != NULL) {
7668 dns_db_detachnode(db, &node);
7669 }
7670 return (result);
7671 }
7672
7673 static isc_result_t
7674 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7675 dns_dbversion_t *version, bool build_nsec3, dns_ttl_t minimum,
7676 dns_diff_t *diff) {
7677 isc_result_t result;
7678 dns_dbnode_t *node = NULL;
7679 dns_rdataset_t rdataset;
7680 dns_rdata_t rdata = DNS_RDATA_INIT;
7681 unsigned char data[5];
7682 bool seen_done = false;
7683 bool have_rr = false;
7684
7685 dns_rdataset_init(&rdataset);
7686 result = dns_db_getoriginnode(signing->db, &node);
7687 if (result != ISC_R_SUCCESS) {
7688 goto failure;
7689 }
7690
7691 result = dns_db_findrdataset(signing->db, node, version,
7692 zone->privatetype, dns_rdatatype_none, 0,
7693 &rdataset, NULL);
7694 if (result == ISC_R_NOTFOUND) {
7695 INSIST(!dns_rdataset_isassociated(&rdataset));
7696 result = ISC_R_SUCCESS;
7697 goto failure;
7698 }
7699 if (result != ISC_R_SUCCESS) {
7700 INSIST(!dns_rdataset_isassociated(&rdataset));
7701 goto failure;
7702 }
7703 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7704 result = dns_rdataset_next(&rdataset))
7705 {
7706 dns_rdataset_current(&rdataset, &rdata);
7707 /*
7708 * If we don't match the algorithm or keyid skip the record.
7709 */
7710 if (rdata.length != 5 || rdata.data[0] != signing->algorithm ||
7711 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7712 rdata.data[2] != (signing->keyid & 0xff))
7713 {
7714 have_rr = true;
7715 dns_rdata_reset(&rdata);
7716 continue;
7717 }
7718 /*
7719 * We have a match. If we were signing (!signing->deleteit)
7720 * and we already have a record indicating that we have
7721 * finished signing (rdata.data[4] != 0) then keep it.
7722 * Otherwise it needs to be deleted as we have removed all
7723 * the signatures (signing->deleteit), so any record indicating
7724 * completion is now out of date, or we have finished signing
7725 * with the new record so we no longer need to remember that
7726 * we need to sign the zone with the matching key across a
7727 * nameserver re-start.
7728 */
7729 if (!signing->deleteit && rdata.data[4] != 0) {
7730 seen_done = true;
7731 have_rr = true;
7732 } else {
7733 CHECK(update_one_rr(signing->db, version, diff,
7734 DNS_DIFFOP_DEL, &zone->origin,
7735 rdataset.ttl, &rdata));
7736 }
7737 dns_rdata_reset(&rdata);
7738 }
7739 if (result == ISC_R_NOMORE) {
7740 result = ISC_R_SUCCESS;
7741 }
7742 if (!signing->deleteit && !seen_done) {
7743 /*
7744 * If we were signing then we need to indicate that we have
7745 * finished signing the zone with this key. If it is already
7746 * there we don't need to add it a second time.
7747 */
7748 data[0] = signing->algorithm;
7749 data[1] = (signing->keyid >> 8) & 0xff;
7750 data[2] = signing->keyid & 0xff;
7751 data[3] = 0;
7752 data[4] = 1;
7753 rdata.length = sizeof(data);
7754 rdata.data = data;
7755 rdata.type = zone->privatetype;
7756 rdata.rdclass = dns_db_class(signing->db);
7757 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7758 &zone->origin, rdataset.ttl, &rdata));
7759 } else if (!have_rr) {
7760 dns_name_t *origin = dns_db_origin(signing->db);
7761 /*
7762 * Rebuild the NSEC/NSEC3 record for the origin as we no
7763 * longer have any private records.
7764 */
7765 if (build_nsec3) {
7766 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7767 minimum, false, diff));
7768 }
7769 CHECK(updatesecure(signing->db, version, origin, minimum, true,
7770 diff));
7771 }
7772
7773 failure:
7774 if (dns_rdataset_isassociated(&rdataset)) {
7775 dns_rdataset_disassociate(&rdataset);
7776 }
7777 if (node != NULL) {
7778 dns_db_detachnode(signing->db, &node);
7779 }
7780 return (result);
7781 }
7782
7783 /*
7784 * Called from zone_nsec3chain() in order to update zone records indicating
7785 * processing status of given NSEC3 chain:
7786 *
7787 * - If the supplied dns_nsec3chain_t structure has been fully processed
7788 * (which is indicated by "active" being set to false):
7789 *
7790 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7791 *
7792 * - remove all private-type records containing NSEC3PARAM RDATA matching
7793 * the relevant NSEC3 chain.
7794 *
7795 * - If the supplied dns_nsec3chain_t structure has not been fully processed
7796 * (which is indicated by "active" being set to true), only remove the
7797 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7798 * "flags" field set to 0.
7799 *
7800 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7801 * in the relevant private-type record, but with the "flags" field set to
7802 * 0, indicating that this NSEC3 chain is now complete for this zone.
7803 *
7804 * Note that this function is called at different processing stages for NSEC3
7805 * chain additions vs. removals and needs to handle all cases properly.
7806 */
7807 static isc_result_t
7808 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7809 bool active, dns_rdatatype_t privatetype, dns_diff_t *diff) {
7810 dns_dbnode_t *node = NULL;
7811 dns_name_t *name = dns_db_origin(db);
7812 dns_rdata_t rdata = DNS_RDATA_INIT;
7813 dns_rdataset_t rdataset;
7814 dns_rdata_nsec3param_t nsec3param;
7815 isc_result_t result;
7816 isc_buffer_t buffer;
7817 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7818 dns_ttl_t ttl = 0;
7819 bool nseconly = false, nsec3ok = false;
7820
7821 dns_rdataset_init(&rdataset);
7822
7823 result = dns_db_getoriginnode(db, &node);
7824 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7825 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
7826 0, &rdataset, NULL);
7827 if (result == ISC_R_NOTFOUND) {
7828 goto try_private;
7829 }
7830 if (result != ISC_R_SUCCESS) {
7831 goto failure;
7832 }
7833
7834 /*
7835 * Preserve the existing ttl.
7836 */
7837 ttl = rdataset.ttl;
7838
7839 /*
7840 * Delete all NSEC3PARAM records which match that in nsec3chain.
7841 */
7842 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7843 result = dns_rdataset_next(&rdataset))
7844 {
7845 dns_rdataset_current(&rdataset, &rdata);
7846 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7847
7848 if (nsec3param.hash != chain->nsec3param.hash ||
7849 (active && nsec3param.flags != 0) ||
7850 nsec3param.iterations != chain->nsec3param.iterations ||
7851 nsec3param.salt_length != chain->nsec3param.salt_length ||
7852 memcmp(nsec3param.salt, chain->nsec3param.salt,
7853 nsec3param.salt_length))
7854 {
7855 dns_rdata_reset(&rdata);
7856 continue;
7857 }
7858
7859 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7860 rdataset.ttl, &rdata));
7861 dns_rdata_reset(&rdata);
7862 }
7863 if (result != ISC_R_NOMORE) {
7864 goto failure;
7865 }
7866
7867 dns_rdataset_disassociate(&rdataset);
7868
7869 try_private:
7870
7871 if (active) {
7872 goto add;
7873 }
7874
7875 result = dns_nsec_nseconly(db, ver, &nseconly);
7876 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
7877
7878 /*
7879 * Delete all private records which match that in nsec3chain.
7880 */
7881 result = dns_db_findrdataset(db, node, ver, privatetype, 0, 0,
7882 &rdataset, NULL);
7883 if (result == ISC_R_NOTFOUND) {
7884 goto add;
7885 }
7886 if (result != ISC_R_SUCCESS) {
7887 goto failure;
7888 }
7889
7890 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7891 result = dns_rdataset_next(&rdataset))
7892 {
7893 dns_rdata_t private = DNS_RDATA_INIT;
7894 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
7895
7896 dns_rdataset_current(&rdataset, &private);
7897 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
7898 sizeof(buf))) {
7899 continue;
7900 }
7901 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7902
7903 if ((!nsec3ok &&
7904 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
7905 nsec3param.hash != chain->nsec3param.hash ||
7906 nsec3param.iterations != chain->nsec3param.iterations ||
7907 nsec3param.salt_length != chain->nsec3param.salt_length ||
7908 memcmp(nsec3param.salt, chain->nsec3param.salt,
7909 nsec3param.salt_length))
7910 {
7911 dns_rdata_reset(&rdata);
7912 continue;
7913 }
7914
7915 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7916 rdataset.ttl, &private));
7917 dns_rdata_reset(&rdata);
7918 }
7919 if (result != ISC_R_NOMORE) {
7920 goto failure;
7921 }
7922
7923 add:
7924 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
7925 result = ISC_R_SUCCESS;
7926 goto failure;
7927 }
7928
7929 /*
7930 * Add a NSEC3PARAM record which matches that in nsec3chain but
7931 * with all flags bits cleared.
7932 *
7933 * Note: we do not clear chain->nsec3param.flags as this change
7934 * may be reversed.
7935 */
7936 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
7937 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
7938 dns_rdatatype_nsec3param, &chain->nsec3param,
7939 &buffer));
7940 rdata.data[1] = 0; /* Clear flag bits. */
7941 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
7942
7943 failure:
7944 dns_db_detachnode(db, &node);
7945 if (dns_rdataset_isassociated(&rdataset)) {
7946 dns_rdataset_disassociate(&rdataset);
7947 }
7948 return (result);
7949 }
7950
7951 static isc_result_t
7952 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7953 dns_name_t *name, dns_diff_t *diff) {
7954 dns_rdataset_t rdataset;
7955 isc_result_t result;
7956
7957 dns_rdataset_init(&rdataset);
7958
7959 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
7960 &rdataset, NULL);
7961 if (result == ISC_R_NOTFOUND) {
7962 return (ISC_R_SUCCESS);
7963 }
7964 if (result != ISC_R_SUCCESS) {
7965 return (result);
7966 }
7967 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
7968 result = dns_rdataset_next(&rdataset))
7969 {
7970 dns_rdata_t rdata = DNS_RDATA_INIT;
7971
7972 dns_rdataset_current(&rdataset, &rdata);
7973 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7974 rdataset.ttl, &rdata));
7975 }
7976 if (result == ISC_R_NOMORE) {
7977 result = ISC_R_SUCCESS;
7978 }
7979 failure:
7980 dns_rdataset_disassociate(&rdataset);
7981 return (result);
7982 }
7983
7984 static isc_result_t
7985 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7986 dns_name_t *name, const dns_rdata_nsec3param_t *param,
7987 dns_diff_t *diff) {
7988 dns_rdataset_t rdataset;
7989 dns_rdata_nsec3_t nsec3;
7990 isc_result_t result;
7991
7992 dns_rdataset_init(&rdataset);
7993 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3, 0, 0,
7994 &rdataset, NULL);
7995 if (result == ISC_R_NOTFOUND) {
7996 return (ISC_R_SUCCESS);
7997 }
7998 if (result != ISC_R_SUCCESS) {
7999 return (result);
8000 }
8001
8002 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8003 result = dns_rdataset_next(&rdataset))
8004 {
8005 dns_rdata_t rdata = DNS_RDATA_INIT;
8006
8007 dns_rdataset_current(&rdataset, &rdata);
8008 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
8009 if (nsec3.hash != param->hash ||
8010 nsec3.iterations != param->iterations ||
8011 nsec3.salt_length != param->salt_length ||
8012 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
8013 {
8014 continue;
8015 }
8016 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
8017 rdataset.ttl, &rdata));
8018 }
8019 if (result == ISC_R_NOMORE) {
8020 result = ISC_R_SUCCESS;
8021 }
8022 failure:
8023 dns_rdataset_disassociate(&rdataset);
8024 return (result);
8025 }
8026
8027 static isc_result_t
8028 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
8029 const dns_rdata_nsec3param_t *param, bool *answer) {
8030 dns_dbnode_t *node = NULL;
8031 dns_rdata_t rdata = DNS_RDATA_INIT;
8032 dns_rdata_nsec3param_t myparam;
8033 dns_rdataset_t rdataset;
8034 isc_result_t result;
8035
8036 *answer = false;
8037
8038 result = dns_db_getoriginnode(db, &node);
8039 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8040
8041 dns_rdataset_init(&rdataset);
8042
8043 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec, 0, 0,
8044 &rdataset, NULL);
8045 if (result == ISC_R_SUCCESS) {
8046 dns_rdataset_disassociate(&rdataset);
8047 dns_db_detachnode(db, &node);
8048 return (result);
8049 }
8050 if (result != ISC_R_NOTFOUND) {
8051 dns_db_detachnode(db, &node);
8052 return (result);
8053 }
8054
8055 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param, 0,
8056 0, &rdataset, NULL);
8057 if (result == ISC_R_NOTFOUND) {
8058 *answer = true;
8059 dns_db_detachnode(db, &node);
8060 return (ISC_R_SUCCESS);
8061 }
8062 if (result != ISC_R_SUCCESS) {
8063 dns_db_detachnode(db, &node);
8064 return (result);
8065 }
8066
8067 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
8068 result = dns_rdataset_next(&rdataset))
8069 {
8070 dns_rdataset_current(&rdataset, &rdata);
8071 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
8072 dns_rdata_reset(&rdata);
8073 /*
8074 * Ignore any NSEC3PARAM removals.
8075 */
8076 if (NSEC3REMOVE(myparam.flags)) {
8077 continue;
8078 }
8079 /*
8080 * Ignore the chain that we are in the process of deleting.
8081 */
8082 if (myparam.hash == param->hash &&
8083 myparam.iterations == param->iterations &&
8084 myparam.salt_length == param->salt_length &&
8085 !memcmp(myparam.salt, param->salt, myparam.salt_length))
8086 {
8087 continue;
8088 }
8089 /*
8090 * Found an active NSEC3 chain.
8091 */
8092 break;
8093 }
8094 if (result == ISC_R_NOMORE) {
8095 *answer = true;
8096 result = ISC_R_SUCCESS;
8097 }
8098
8099 failure:
8100 if (dns_rdataset_isassociated(&rdataset)) {
8101 dns_rdataset_disassociate(&rdataset);
8102 }
8103 dns_db_detachnode(db, &node);
8104 return (result);
8105 }
8106
8107 /*%
8108 * Given a tuple which is part of a diff, return a pointer to the next tuple in
8109 * that diff which has the same name and type (or NULL if no such tuple is
8110 * found).
8111 */
8112 static dns_difftuple_t *
8113 find_next_matching_tuple(dns_difftuple_t *cur) {
8114 dns_difftuple_t *next = cur;
8115
8116 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
8117 if (cur->rdata.type == next->rdata.type &&
8118 dns_name_equal(&cur->name, &next->name))
8119 {
8120 return (next);
8121 }
8122 }
8123
8124 return (NULL);
8125 }
8126
8127 /*%
8128 * Remove all tuples with the same name and type as 'cur' from 'src' and append
8129 * them to 'dst'.
8130 */
8131 static void
8132 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
8133 do {
8134 dns_difftuple_t *next = find_next_matching_tuple(cur);
8135 ISC_LIST_UNLINK(src->tuples, cur, link);
8136 dns_diff_appendminimal(dst, &cur);
8137 cur = next;
8138 } while (cur != NULL);
8139 }
8140
8141 /*%
8142 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
8143 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
8144 * along with tuples representing relevant signature changes.
8145 */
8146 isc_result_t
8147 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
8148 dst_key_t *zone_keys[], unsigned int nkeys,
8149 dns_zone_t *zone, isc_stdtime_t inception,
8150 isc_stdtime_t expire, isc_stdtime_t keyexpire,
8151 isc_stdtime_t now, bool check_ksk, bool keyset_kskonly,
8152 dns__zonediff_t *zonediff) {
8153 dns_difftuple_t *tuple;
8154 isc_result_t result;
8155
8156 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
8157 isc_stdtime_t exp = expire;
8158
8159 if (keyexpire != 0 &&
8160 (tuple->rdata.type == dns_rdatatype_dnskey ||
8161 tuple->rdata.type == dns_rdatatype_cdnskey ||
8162 tuple->rdata.type == dns_rdatatype_cds))
8163 {
8164 exp = keyexpire;
8165 }
8166
8167 result = del_sigs(zone, db, version, &tuple->name,
8168 tuple->rdata.type, zonediff, zone_keys, nkeys,
8169 now, false);
8170 if (result != ISC_R_SUCCESS) {
8171 dns_zone_log(zone, ISC_LOG_ERROR,
8172 "dns__zone_updatesigs:del_sigs -> %s",
8173 dns_result_totext(result));
8174 return (result);
8175 }
8176 result = add_sigs(db, version, &tuple->name, zone,
8177 tuple->rdata.type, zonediff->diff, zone_keys,
8178 nkeys, zone->mctx, inception, exp, check_ksk,
8179 keyset_kskonly);
8180 if (result != ISC_R_SUCCESS) {
8181 dns_zone_log(zone, ISC_LOG_ERROR,
8182 "dns__zone_updatesigs:add_sigs -> %s",
8183 dns_result_totext(result));
8184 return (result);
8185 }
8186
8187 /*
8188 * Signature changes for all RRs with name tuple->name and type
8189 * tuple->rdata.type were appended to zonediff->diff. Now we
8190 * remove all the "raw" changes with the same name and type
8191 * from diff (so that they are not processed by this loop
8192 * again) and append them to zonediff so that they get applied.
8193 */
8194 move_matching_tuples(tuple, diff, zonediff->diff);
8195 }
8196 return (ISC_R_SUCCESS);
8197 }
8198
8199 /*
8200 * Incrementally build and sign a new NSEC3 chain using the parameters
8201 * requested.
8202 */
8203 static void
8204 zone_nsec3chain(dns_zone_t *zone) {
8205 const char *me = "zone_nsec3chain";
8206 dns_db_t *db = NULL;
8207 dns_dbnode_t *node = NULL;
8208 dns_dbversion_t *version = NULL;
8209 dns_diff_t _sig_diff;
8210 dns_diff_t nsec_diff;
8211 dns_diff_t nsec3_diff;
8212 dns_diff_t param_diff;
8213 dns__zonediff_t zonediff;
8214 dns_fixedname_t fixed;
8215 dns_fixedname_t nextfixed;
8216 dns_name_t *name, *nextname;
8217 dns_rdataset_t rdataset;
8218 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
8219 dns_nsec3chainlist_t cleanup;
8220 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8221 int32_t signatures;
8222 bool check_ksk, keyset_kskonly;
8223 bool delegation;
8224 bool first;
8225 isc_result_t result;
8226 isc_stdtime_t now, inception, soaexpire, expire;
8227 uint32_t jitter, sigvalidityinterval, expiryinterval;
8228 unsigned int i;
8229 unsigned int nkeys = 0;
8230 uint32_t nodes;
8231 bool unsecure = false;
8232 bool seen_soa, seen_ns, seen_dname, seen_ds;
8233 bool seen_nsec, seen_nsec3, seen_rr;
8234 dns_rdatasetiter_t *iterator = NULL;
8235 bool buildnsecchain;
8236 bool updatensec = false;
8237 dns_rdatatype_t privatetype = zone->privatetype;
8238
8239 ENTER;
8240
8241 dns_rdataset_init(&rdataset);
8242 name = dns_fixedname_initname(&fixed);
8243 nextname = dns_fixedname_initname(&nextfixed);
8244 dns_diff_init(zone->mctx, ¶m_diff);
8245 dns_diff_init(zone->mctx, &nsec3_diff);
8246 dns_diff_init(zone->mctx, &nsec_diff);
8247 dns_diff_init(zone->mctx, &_sig_diff);
8248 zonediff_init(&zonediff, &_sig_diff);
8249 ISC_LIST_INIT(cleanup);
8250
8251 /*
8252 * Updates are disabled. Pause for 5 minutes.
8253 */
8254 if (zone->update_disabled) {
8255 result = ISC_R_FAILURE;
8256 goto failure;
8257 }
8258
8259 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8260 /*
8261 * This function is called when zone timer fires, after the latter gets
8262 * set by zone_addnsec3chain(). If the action triggering the call to
8263 * zone_addnsec3chain() is closely followed by a zone deletion request,
8264 * it might turn out that the timer thread will not be woken up until
8265 * after the zone is deleted by rmzone(), which calls dns_db_detach()
8266 * for zone->db, causing the latter to become NULL. Return immediately
8267 * if that happens.
8268 */
8269 if (zone->db != NULL) {
8270 dns_db_attach(zone->db, &db);
8271 }
8272 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8273 if (db == NULL) {
8274 return;
8275 }
8276
8277 result = dns_db_newversion(db, &version);
8278 if (result != ISC_R_SUCCESS) {
8279 dnssec_log(zone, ISC_LOG_ERROR,
8280 "zone_nsec3chain:dns_db_newversion -> %s",
8281 dns_result_totext(result));
8282 goto failure;
8283 }
8284
8285 isc_stdtime_get(&now);
8286
8287 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8288 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8289 if (result != ISC_R_SUCCESS) {
8290 dnssec_log(zone, ISC_LOG_ERROR,
8291 "zone_nsec3chain:dns__zone_findkeys -> %s",
8292 dns_result_totext(result));
8293 goto failure;
8294 }
8295
8296 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8297 inception = now - 3600; /* Allow for clock skew. */
8298 soaexpire = now + sigvalidityinterval;
8299 expiryinterval = dns_zone_getsigresigninginterval(zone);
8300 if (expiryinterval > sigvalidityinterval) {
8301 expiryinterval = sigvalidityinterval;
8302 } else {
8303 expiryinterval = sigvalidityinterval - expiryinterval;
8304 }
8305
8306 /*
8307 * Spread out signatures over time if they happen to be
8308 * clumped. We don't do this for each add_sigs() call as
8309 * we still want some clustering to occur.
8310 */
8311 if (sigvalidityinterval >= 3600U) {
8312 if (sigvalidityinterval > 7200U) {
8313 jitter = isc_random_uniform(expiryinterval);
8314 } else {
8315 jitter = isc_random_uniform(1200);
8316 }
8317 expire = soaexpire - jitter - 1;
8318 } else {
8319 expire = soaexpire - 1;
8320 }
8321
8322 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8323 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8324
8325 /*
8326 * We keep pulling nodes off each iterator in turn until
8327 * we have no more nodes to pull off or we reach the limits
8328 * for this quantum.
8329 */
8330 nodes = zone->nodes;
8331 signatures = zone->signatures;
8332 LOCK_ZONE(zone);
8333 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8334 UNLOCK_ZONE(zone);
8335 first = true;
8336
8337 if (nsec3chain != NULL) {
8338 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8339 }
8340 /*
8341 * Generate new NSEC3 chains first.
8342 *
8343 * The following while loop iterates over nodes in the zone database,
8344 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
8345 * them. Once all nodes are processed, the "delete_nsec" field is
8346 * consulted to check whether we are supposed to remove NSEC records
8347 * from the zone database; if so, the database iterator is reset to
8348 * point to the first node and the loop traverses all of them again,
8349 * this time removing NSEC records. If we hit a node which is obscured
8350 * by a delegation or a DNAME, nodes are skipped over until we find one
8351 * that is not obscured by the same obscuring name and then normal
8352 * processing is resumed.
8353 *
8354 * The above is repeated until all requested NSEC3 chain changes are
8355 * applied or when we reach the limits for this quantum, whichever
8356 * happens first.
8357 *
8358 * Note that the "signatures" variable is only used here to limit the
8359 * amount of work performed. Actual DNSSEC signatures are only
8360 * generated by dns__zone_updatesigs() calls later in this function.
8361 */
8362 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8363 dns_dbiterator_pause(nsec3chain->dbiterator);
8364
8365 LOCK_ZONE(zone);
8366 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8367
8368 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8369 if (nsec3chain->done || nsec3chain->db != zone->db) {
8370 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
8371 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8372 }
8373 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8374 UNLOCK_ZONE(zone);
8375 if (ISC_LIST_TAIL(cleanup) == nsec3chain) {
8376 goto next_addchain;
8377 }
8378
8379 /*
8380 * Possible future db.
8381 */
8382 if (nsec3chain->db != db) {
8383 goto next_addchain;
8384 }
8385
8386 if (NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8387 goto next_addchain;
8388 }
8389
8390 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8391
8392 if (nsec3chain->delete_nsec) {
8393 delegation = false;
8394 dns_dbiterator_pause(nsec3chain->dbiterator);
8395 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
8396 goto next_addnode;
8397 }
8398 /*
8399 * On the first pass we need to check if the current node
8400 * has not been obscured.
8401 */
8402 delegation = false;
8403 unsecure = false;
8404 if (first) {
8405 dns_fixedname_t ffound;
8406 dns_name_t *found;
8407 found = dns_fixedname_initname(&ffound);
8408 result = dns_db_find(
8409 db, name, version, dns_rdatatype_soa,
8410 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8411 if ((result == DNS_R_DELEGATION ||
8412 result == DNS_R_DNAME) &&
8413 !dns_name_equal(name, found))
8414 {
8415 /*
8416 * Remember the obscuring name so that
8417 * we skip all obscured names.
8418 */
8419 dns_name_copynf(found, name);
8420 delegation = true;
8421 goto next_addnode;
8422 }
8423 }
8424
8425 /*
8426 * Check to see if this is a bottom of zone node.
8427 */
8428 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8429 if (result == ISC_R_NOTFOUND) {
8430 /* Empty node? */
8431 goto next_addnode;
8432 }
8433 if (result != ISC_R_SUCCESS) {
8434 goto failure;
8435 }
8436
8437 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
8438 for (result = dns_rdatasetiter_first(iterator);
8439 result == ISC_R_SUCCESS;
8440 result = dns_rdatasetiter_next(iterator))
8441 {
8442 dns_rdatasetiter_current(iterator, &rdataset);
8443 INSIST(rdataset.type != dns_rdatatype_nsec3);
8444 if (rdataset.type == dns_rdatatype_soa) {
8445 seen_soa = true;
8446 } else if (rdataset.type == dns_rdatatype_ns) {
8447 seen_ns = true;
8448 } else if (rdataset.type == dns_rdatatype_dname) {
8449 seen_dname = true;
8450 } else if (rdataset.type == dns_rdatatype_ds) {
8451 seen_ds = true;
8452 } else if (rdataset.type == dns_rdatatype_nsec) {
8453 seen_nsec = true;
8454 }
8455 dns_rdataset_disassociate(&rdataset);
8456 }
8457 dns_rdatasetiter_destroy(&iterator);
8458 /*
8459 * Is there a NSEC chain than needs to be cleaned up?
8460 */
8461 if (seen_nsec) {
8462 nsec3chain->seen_nsec = true;
8463 }
8464 if (seen_ns && !seen_soa && !seen_ds) {
8465 unsecure = true;
8466 }
8467 if ((seen_ns && !seen_soa) || seen_dname) {
8468 delegation = true;
8469 }
8470
8471 /*
8472 * Process one node.
8473 */
8474 dns_dbiterator_pause(nsec3chain->dbiterator);
8475 result = dns_nsec3_addnsec3(
8476 db, version, name, &nsec3chain->nsec3param,
8477 zone->minimum, unsecure, &nsec3_diff);
8478 if (result != ISC_R_SUCCESS) {
8479 dnssec_log(zone, ISC_LOG_ERROR,
8480 "zone_nsec3chain:"
8481 "dns_nsec3_addnsec3 -> %s",
8482 dns_result_totext(result));
8483 goto failure;
8484 }
8485
8486 /*
8487 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8488 * two signatures. Additionally there will, in general, be
8489 * two signature generated below.
8490 *
8491 * If we are only changing the optout flag the cost is half
8492 * that of the cost of generating a completely new chain.
8493 */
8494 signatures -= 4;
8495
8496 /*
8497 * Go onto next node.
8498 */
8499 next_addnode:
8500 first = false;
8501 dns_db_detachnode(db, &node);
8502 do {
8503 result = dns_dbiterator_next(nsec3chain->dbiterator);
8504
8505 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8506 dns_dbiterator_pause(nsec3chain->dbiterator);
8507 CHECK(fixup_nsec3param(db, version, nsec3chain,
8508 false, privatetype,
8509 ¶m_diff));
8510 LOCK_ZONE(zone);
8511 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8512 link);
8513 UNLOCK_ZONE(zone);
8514 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8515 goto next_addchain;
8516 }
8517 if (result == ISC_R_NOMORE) {
8518 dns_dbiterator_pause(nsec3chain->dbiterator);
8519 if (nsec3chain->seen_nsec) {
8520 CHECK(fixup_nsec3param(
8521 db, version, nsec3chain, true,
8522 privatetype, ¶m_diff));
8523 nsec3chain->delete_nsec = true;
8524 goto same_addchain;
8525 }
8526 CHECK(fixup_nsec3param(db, version, nsec3chain,
8527 false, privatetype,
8528 ¶m_diff));
8529 LOCK_ZONE(zone);
8530 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8531 link);
8532 UNLOCK_ZONE(zone);
8533 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8534 goto next_addchain;
8535 } else if (result != ISC_R_SUCCESS) {
8536 dnssec_log(zone, ISC_LOG_ERROR,
8537 "zone_nsec3chain:"
8538 "dns_dbiterator_next -> %s",
8539 dns_result_totext(result));
8540 goto failure;
8541 } else if (delegation) {
8542 dns_dbiterator_current(nsec3chain->dbiterator,
8543 &node, nextname);
8544 dns_db_detachnode(db, &node);
8545 if (!dns_name_issubdomain(nextname, name)) {
8546 break;
8547 }
8548 } else {
8549 break;
8550 }
8551 } while (1);
8552 continue;
8553
8554 same_addchain:
8555 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8556 first = true;
8557 continue;
8558
8559 next_addchain:
8560 dns_dbiterator_pause(nsec3chain->dbiterator);
8561 nsec3chain = nextnsec3chain;
8562 first = true;
8563 if (nsec3chain != NULL) {
8564 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8565 }
8566 }
8567
8568 if (nsec3chain != NULL) {
8569 goto skip_removals;
8570 }
8571
8572 /*
8573 * Process removals.
8574 *
8575 * This is a counterpart of the above while loop which takes care of
8576 * removing an NSEC3 chain. It starts with determining whether the
8577 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8578 * NSEC chain by iterating over all nodes in the zone database and only
8579 * then goes on to remove NSEC3 records be iterating over all nodes
8580 * again and calling deletematchingnsec3() for each of them; otherwise,
8581 * it starts removing NSEC3 records immediately. Rules for processing
8582 * obscured nodes and interrupting work are the same as for the while
8583 * loop above.
8584 */
8585 LOCK_ZONE(zone);
8586 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8587 UNLOCK_ZONE(zone);
8588 first = true;
8589 buildnsecchain = false;
8590 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8591 dns_dbiterator_pause(nsec3chain->dbiterator);
8592
8593 LOCK_ZONE(zone);
8594 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8595 UNLOCK_ZONE(zone);
8596
8597 if (nsec3chain->db != db) {
8598 goto next_removechain;
8599 }
8600
8601 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8602 goto next_removechain;
8603 }
8604
8605 /*
8606 * Work out if we need to build a NSEC chain as a consequence
8607 * of removing this NSEC3 chain.
8608 */
8609 if (first && !updatensec &&
8610 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8611 {
8612 result = need_nsec_chain(db, version,
8613 &nsec3chain->nsec3param,
8614 &buildnsecchain);
8615 if (result != ISC_R_SUCCESS) {
8616 dnssec_log(zone, ISC_LOG_ERROR,
8617 "zone_nsec3chain:"
8618 "need_nsec_chain -> %s",
8619 dns_result_totext(result));
8620 goto failure;
8621 }
8622 }
8623
8624 if (first) {
8625 dnssec_log(zone, ISC_LOG_DEBUG(3),
8626 "zone_nsec3chain:buildnsecchain = %u\n",
8627 buildnsecchain);
8628 }
8629
8630 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8631 dns_dbiterator_pause(nsec3chain->dbiterator);
8632 delegation = false;
8633
8634 if (!buildnsecchain) {
8635 /*
8636 * Delete the NSEC3PARAM record matching this chain.
8637 */
8638 if (first) {
8639 result = fixup_nsec3param(
8640 db, version, nsec3chain, true,
8641 privatetype, ¶m_diff);
8642 if (result != ISC_R_SUCCESS) {
8643 dnssec_log(zone, ISC_LOG_ERROR,
8644 "zone_nsec3chain:"
8645 "fixup_nsec3param -> %s",
8646 dns_result_totext(result));
8647 goto failure;
8648 }
8649 }
8650
8651 /*
8652 * Delete the NSEC3 records.
8653 */
8654 result = deletematchingnsec3(db, version, node, name,
8655 &nsec3chain->nsec3param,
8656 &nsec3_diff);
8657 if (result != ISC_R_SUCCESS) {
8658 dnssec_log(zone, ISC_LOG_ERROR,
8659 "zone_nsec3chain:"
8660 "deletematchingnsec3 -> %s",
8661 dns_result_totext(result));
8662 goto failure;
8663 }
8664 goto next_removenode;
8665 }
8666
8667 if (first) {
8668 dns_fixedname_t ffound;
8669 dns_name_t *found;
8670 found = dns_fixedname_initname(&ffound);
8671 result = dns_db_find(
8672 db, name, version, dns_rdatatype_soa,
8673 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
8674 if ((result == DNS_R_DELEGATION ||
8675 result == DNS_R_DNAME) &&
8676 !dns_name_equal(name, found))
8677 {
8678 /*
8679 * Remember the obscuring name so that
8680 * we skip all obscured names.
8681 */
8682 dns_name_copynf(found, name);
8683 delegation = true;
8684 goto next_removenode;
8685 }
8686 }
8687
8688 /*
8689 * Check to see if this is a bottom of zone node.
8690 */
8691 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8692 if (result == ISC_R_NOTFOUND) {
8693 /* Empty node? */
8694 goto next_removenode;
8695 }
8696 if (result != ISC_R_SUCCESS) {
8697 goto failure;
8698 }
8699
8700 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
8701 seen_rr = false;
8702 for (result = dns_rdatasetiter_first(iterator);
8703 result == ISC_R_SUCCESS;
8704 result = dns_rdatasetiter_next(iterator))
8705 {
8706 dns_rdatasetiter_current(iterator, &rdataset);
8707 if (rdataset.type == dns_rdatatype_soa) {
8708 seen_soa = true;
8709 } else if (rdataset.type == dns_rdatatype_ns) {
8710 seen_ns = true;
8711 } else if (rdataset.type == dns_rdatatype_dname) {
8712 seen_dname = true;
8713 } else if (rdataset.type == dns_rdatatype_nsec) {
8714 seen_nsec = true;
8715 } else if (rdataset.type == dns_rdatatype_nsec3) {
8716 seen_nsec3 = true;
8717 } else if (rdataset.type != dns_rdatatype_rrsig) {
8718 seen_rr = true;
8719 }
8720 dns_rdataset_disassociate(&rdataset);
8721 }
8722 dns_rdatasetiter_destroy(&iterator);
8723
8724 if (!seen_rr || seen_nsec3 || seen_nsec) {
8725 goto next_removenode;
8726 }
8727 if ((seen_ns && !seen_soa) || seen_dname) {
8728 delegation = true;
8729 }
8730
8731 /*
8732 * Add a NSEC record except at the origin.
8733 */
8734 if (!dns_name_equal(name, dns_db_origin(db))) {
8735 dns_dbiterator_pause(nsec3chain->dbiterator);
8736 CHECK(add_nsec(db, version, name, node, zone->minimum,
8737 delegation, &nsec_diff));
8738 signatures--;
8739 }
8740
8741 next_removenode:
8742 first = false;
8743 dns_db_detachnode(db, &node);
8744 do {
8745 result = dns_dbiterator_next(nsec3chain->dbiterator);
8746 if (result == ISC_R_NOMORE && buildnsecchain) {
8747 /*
8748 * The NSEC chain should now be built.
8749 * We can now remove the NSEC3 chain.
8750 */
8751 updatensec = true;
8752 goto same_removechain;
8753 }
8754 if (result == ISC_R_NOMORE) {
8755 dns_dbiterator_pause(nsec3chain->dbiterator);
8756 LOCK_ZONE(zone);
8757 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8758 link);
8759 UNLOCK_ZONE(zone);
8760 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8761 result = fixup_nsec3param(
8762 db, version, nsec3chain, false,
8763 privatetype, ¶m_diff);
8764 if (result != ISC_R_SUCCESS) {
8765 dnssec_log(zone, ISC_LOG_ERROR,
8766 "zone_nsec3chain:"
8767 "fixup_nsec3param -> %s",
8768 dns_result_totext(result));
8769 goto failure;
8770 }
8771 goto next_removechain;
8772 } else if (result != ISC_R_SUCCESS) {
8773 dnssec_log(zone, ISC_LOG_ERROR,
8774 "zone_nsec3chain:"
8775 "dns_dbiterator_next -> %s",
8776 dns_result_totext(result));
8777 goto failure;
8778 } else if (delegation) {
8779 dns_dbiterator_current(nsec3chain->dbiterator,
8780 &node, nextname);
8781 dns_db_detachnode(db, &node);
8782 if (!dns_name_issubdomain(nextname, name)) {
8783 break;
8784 }
8785 } else {
8786 break;
8787 }
8788 } while (1);
8789 continue;
8790
8791 same_removechain:
8792 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8793 buildnsecchain = false;
8794 first = true;
8795 continue;
8796
8797 next_removechain:
8798 dns_dbiterator_pause(nsec3chain->dbiterator);
8799 nsec3chain = nextnsec3chain;
8800 first = true;
8801 }
8802
8803 skip_removals:
8804 /*
8805 * We may need to update the NSEC/NSEC3 records for the zone apex.
8806 */
8807 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8808 bool rebuild_nsec = false, rebuild_nsec3 = false;
8809 result = dns_db_getoriginnode(db, &node);
8810 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8811 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8812 if (result != ISC_R_SUCCESS) {
8813 dnssec_log(zone, ISC_LOG_ERROR,
8814 "zone_nsec3chain:dns_db_allrdatasets -> %s",
8815 dns_result_totext(result));
8816 goto failure;
8817 }
8818 for (result = dns_rdatasetiter_first(iterator);
8819 result == ISC_R_SUCCESS;
8820 result = dns_rdatasetiter_next(iterator))
8821 {
8822 dns_rdatasetiter_current(iterator, &rdataset);
8823 if (rdataset.type == dns_rdatatype_nsec) {
8824 rebuild_nsec = true;
8825 } else if (rdataset.type == dns_rdatatype_nsec3param) {
8826 rebuild_nsec3 = true;
8827 }
8828 dns_rdataset_disassociate(&rdataset);
8829 }
8830 dns_rdatasetiter_destroy(&iterator);
8831 dns_db_detachnode(db, &node);
8832
8833 if (rebuild_nsec) {
8834 if (nsec3chain != NULL) {
8835 dns_dbiterator_pause(nsec3chain->dbiterator);
8836 }
8837
8838 result = updatesecure(db, version, &zone->origin,
8839 zone->minimum, true, &nsec_diff);
8840 if (result != ISC_R_SUCCESS) {
8841 dnssec_log(zone, ISC_LOG_ERROR,
8842 "zone_nsec3chain:updatesecure -> %s",
8843 dns_result_totext(result));
8844 goto failure;
8845 }
8846 }
8847
8848 if (rebuild_nsec3) {
8849 if (nsec3chain != NULL) {
8850 dns_dbiterator_pause(nsec3chain->dbiterator);
8851 }
8852
8853 result = dns_nsec3_addnsec3s(
8854 db, version, dns_db_origin(db), zone->minimum,
8855 false, &nsec3_diff);
8856 if (result != ISC_R_SUCCESS) {
8857 dnssec_log(zone, ISC_LOG_ERROR,
8858 "zone_nsec3chain:"
8859 "dns_nsec3_addnsec3s -> %s",
8860 dns_result_totext(result));
8861 goto failure;
8862 }
8863 }
8864 }
8865
8866 /*
8867 * Add / update signatures for the NSEC3 records.
8868 */
8869 if (nsec3chain != NULL) {
8870 dns_dbiterator_pause(nsec3chain->dbiterator);
8871 }
8872 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
8873 nkeys, zone, inception, expire, 0, now,
8874 check_ksk, keyset_kskonly, &zonediff);
8875 if (result != ISC_R_SUCCESS) {
8876 dnssec_log(zone, ISC_LOG_ERROR,
8877 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8878 dns_result_totext(result));
8879 goto failure;
8880 }
8881
8882 /*
8883 * We have changed the NSEC3PARAM or private RRsets
8884 * above so we need to update the signatures.
8885 */
8886 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
8887 nkeys, zone, inception, expire, 0, now,
8888 check_ksk, keyset_kskonly, &zonediff);
8889 if (result != ISC_R_SUCCESS) {
8890 dnssec_log(zone, ISC_LOG_ERROR,
8891 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8892 dns_result_totext(result));
8893 goto failure;
8894 }
8895
8896 if (updatensec) {
8897 result = updatesecure(db, version, &zone->origin, zone->minimum,
8898 false, &nsec_diff);
8899 if (result != ISC_R_SUCCESS) {
8900 dnssec_log(zone, ISC_LOG_ERROR,
8901 "zone_nsec3chain:updatesecure -> %s",
8902 dns_result_totext(result));
8903 goto failure;
8904 }
8905 }
8906
8907 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys, nkeys,
8908 zone, inception, expire, 0, now,
8909 check_ksk, keyset_kskonly, &zonediff);
8910 if (result != ISC_R_SUCCESS) {
8911 dnssec_log(zone, ISC_LOG_ERROR,
8912 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8913 dns_result_totext(result));
8914 goto failure;
8915 }
8916
8917 /*
8918 * If we made no effective changes to the zone then we can just
8919 * cleanup otherwise we need to increment the serial.
8920 */
8921 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8922 /*
8923 * No need to call dns_db_closeversion() here as it is
8924 * called with commit = true below.
8925 */
8926 goto done;
8927 }
8928
8929 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8930 &zonediff, zone_keys, nkeys, now, false);
8931 if (result != ISC_R_SUCCESS) {
8932 dnssec_log(zone, ISC_LOG_ERROR,
8933 "zone_nsec3chain:del_sigs -> %s",
8934 dns_result_totext(result));
8935 goto failure;
8936 }
8937
8938 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
8939 zone->updatemethod);
8940 if (result != ISC_R_SUCCESS) {
8941 dnssec_log(zone, ISC_LOG_ERROR,
8942 "zone_nsec3chain:update_soa_serial -> %s",
8943 dns_result_totext(result));
8944 goto failure;
8945 }
8946
8947 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
8948 zonediff.diff, zone_keys, nkeys, zone->mctx,
8949 inception, soaexpire, check_ksk, keyset_kskonly);
8950 if (result != ISC_R_SUCCESS) {
8951 dnssec_log(zone, ISC_LOG_ERROR,
8952 "zone_nsec3chain:add_sigs -> %s",
8953 dns_result_totext(result));
8954 goto failure;
8955 }
8956
8957 /* Write changes to journal file. */
8958 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
8959
8960 LOCK_ZONE(zone);
8961 zone_needdump(zone, DNS_DUMP_DELAY);
8962 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8963 UNLOCK_ZONE(zone);
8964
8965 done:
8966 /*
8967 * Pause all iterators so that dns_db_closeversion() can succeed.
8968 */
8969 LOCK_ZONE(zone);
8970 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
8971 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8972 {
8973 dns_dbiterator_pause(nsec3chain->dbiterator);
8974 }
8975 UNLOCK_ZONE(zone);
8976
8977 /*
8978 * Everything has succeeded. Commit the changes.
8979 * Unconditionally commit as zonediff.offline not checked above.
8980 */
8981 dns_db_closeversion(db, &version, true);
8982
8983 /*
8984 * Everything succeeded so we can clean these up now.
8985 */
8986 nsec3chain = ISC_LIST_HEAD(cleanup);
8987 while (nsec3chain != NULL) {
8988 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8989 dns_db_detach(&nsec3chain->db);
8990 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8991 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8992 nsec3chain = ISC_LIST_HEAD(cleanup);
8993 }
8994
8995 LOCK_ZONE(zone);
8996 set_resigntime(zone);
8997 UNLOCK_ZONE(zone);
8998
8999 failure:
9000 if (result != ISC_R_SUCCESS) {
9001 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
9002 dns_result_totext(result));
9003 }
9004
9005 /*
9006 * On error roll back the current nsec3chain.
9007 */
9008 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
9009 if (nsec3chain->done) {
9010 dns_db_detach(&nsec3chain->db);
9011 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9012 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9013 } else {
9014 result = dns_dbiterator_first(nsec3chain->dbiterator);
9015 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9016 dns_dbiterator_pause(nsec3chain->dbiterator);
9017 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9018 }
9019 }
9020
9021 /*
9022 * Rollback the cleanup list.
9023 */
9024 nsec3chain = ISC_LIST_TAIL(cleanup);
9025 while (nsec3chain != NULL) {
9026 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
9027 if (nsec3chain->done) {
9028 dns_db_detach(&nsec3chain->db);
9029 dns_dbiterator_destroy(&nsec3chain->dbiterator);
9030 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
9031 } else {
9032 LOCK_ZONE(zone);
9033 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
9034 UNLOCK_ZONE(zone);
9035 result = dns_dbiterator_first(nsec3chain->dbiterator);
9036 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9037 dns_dbiterator_pause(nsec3chain->dbiterator);
9038 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
9039 }
9040 nsec3chain = ISC_LIST_TAIL(cleanup);
9041 }
9042
9043 LOCK_ZONE(zone);
9044 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain); nsec3chain != NULL;
9045 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
9046 {
9047 dns_dbiterator_pause(nsec3chain->dbiterator);
9048 }
9049 UNLOCK_ZONE(zone);
9050
9051 dns_diff_clear(¶m_diff);
9052 dns_diff_clear(&nsec3_diff);
9053 dns_diff_clear(&nsec_diff);
9054 dns_diff_clear(&_sig_diff);
9055
9056 if (iterator != NULL) {
9057 dns_rdatasetiter_destroy(&iterator);
9058 }
9059
9060 for (i = 0; i < nkeys; i++) {
9061 dst_key_free(&zone_keys[i]);
9062 }
9063
9064 if (node != NULL) {
9065 dns_db_detachnode(db, &node);
9066 }
9067 if (version != NULL) {
9068 dns_db_closeversion(db, &version, false);
9069 dns_db_detach(&db);
9070 } else if (db != NULL) {
9071 dns_db_detach(&db);
9072 }
9073
9074 LOCK_ZONE(zone);
9075 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
9076 isc_interval_t interval;
9077 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9078 isc_interval_set(&interval, 60, 0); /* 1 minute */
9079 } else {
9080 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9081 }
9082 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
9083 } else {
9084 isc_time_settoepoch(&zone->nsec3chaintime);
9085 }
9086 UNLOCK_ZONE(zone);
9087
9088 INSIST(version == NULL);
9089 }
9090
9091 /*%
9092 * Delete all RRSIG records with the given algorithm and keyid.
9093 * Remove the NSEC record and RRSIGs if nkeys is zero.
9094 * If all remaining RRsets are signed with the given algorithm
9095 * set *has_algp to true.
9096 */
9097 static isc_result_t
9098 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
9099 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
9100 uint16_t keyid, bool *has_algp, dns_diff_t *diff) {
9101 dns_rdata_rrsig_t rrsig;
9102 dns_rdataset_t rdataset;
9103 dns_rdatasetiter_t *iterator = NULL;
9104 isc_result_t result;
9105 bool alg_missed = false;
9106 bool alg_found = false;
9107
9108 char namebuf[DNS_NAME_FORMATSIZE];
9109 dns_name_format(name, namebuf, sizeof(namebuf));
9110
9111 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
9112 if (result != ISC_R_SUCCESS) {
9113 if (result == ISC_R_NOTFOUND) {
9114 result = ISC_R_SUCCESS;
9115 }
9116 return (result);
9117 }
9118
9119 dns_rdataset_init(&rdataset);
9120 for (result = dns_rdatasetiter_first(iterator); result == ISC_R_SUCCESS;
9121 result = dns_rdatasetiter_next(iterator))
9122 {
9123 bool has_alg = false;
9124 dns_rdatasetiter_current(iterator, &rdataset);
9125 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
9126 for (result = dns_rdataset_first(&rdataset);
9127 result == ISC_R_SUCCESS;
9128 result = dns_rdataset_next(&rdataset))
9129 {
9130 dns_rdata_t rdata = DNS_RDATA_INIT;
9131 dns_rdataset_current(&rdataset, &rdata);
9132 CHECK(update_one_rr(db, version, diff,
9133 DNS_DIFFOP_DEL, name,
9134 rdataset.ttl, &rdata));
9135 }
9136 if (result != ISC_R_NOMORE) {
9137 goto failure;
9138 }
9139 dns_rdataset_disassociate(&rdataset);
9140 continue;
9141 }
9142 if (rdataset.type != dns_rdatatype_rrsig) {
9143 dns_rdataset_disassociate(&rdataset);
9144 continue;
9145 }
9146 for (result = dns_rdataset_first(&rdataset);
9147 result == ISC_R_SUCCESS;
9148 result = dns_rdataset_next(&rdataset))
9149 {
9150 dns_rdata_t rdata = DNS_RDATA_INIT;
9151 dns_rdataset_current(&rdataset, &rdata);
9152 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
9153 if (nkeys != 0 && (rrsig.algorithm != algorithm ||
9154 rrsig.keyid != keyid)) {
9155 if (rrsig.algorithm == algorithm) {
9156 has_alg = true;
9157 }
9158 continue;
9159 }
9160 CHECK(update_one_rr(db, version, diff,
9161 DNS_DIFFOP_DELRESIGN, name,
9162 rdataset.ttl, &rdata));
9163 }
9164 dns_rdataset_disassociate(&rdataset);
9165 if (result != ISC_R_NOMORE) {
9166 break;
9167 }
9168
9169 /*
9170 * After deleting, if there's still a signature for
9171 * 'algorithm', set alg_found; if not, set alg_missed.
9172 */
9173 if (has_alg) {
9174 alg_found = true;
9175 } else {
9176 alg_missed = true;
9177 }
9178 }
9179 if (result == ISC_R_NOMORE) {
9180 result = ISC_R_SUCCESS;
9181 }
9182
9183 /*
9184 * Set `has_algp` if the algorithm was found in every RRset:
9185 * i.e., found in at least one, and not missing from any.
9186 */
9187 *has_algp = (alg_found && !alg_missed);
9188 failure:
9189 if (dns_rdataset_isassociated(&rdataset)) {
9190 dns_rdataset_disassociate(&rdataset);
9191 }
9192 dns_rdatasetiter_destroy(&iterator);
9193 return (result);
9194 }
9195
9196 /*
9197 * Incrementally sign the zone using the keys requested.
9198 * Builds the NSEC chain if required.
9199 */
9200 static void
9201 zone_sign(dns_zone_t *zone) {
9202 const char *me = "zone_sign";
9203 dns_db_t *db = NULL;
9204 dns_dbnode_t *node = NULL;
9205 dns_dbversion_t *version = NULL;
9206 dns_diff_t _sig_diff;
9207 dns_diff_t post_diff;
9208 dns__zonediff_t zonediff;
9209 dns_fixedname_t fixed;
9210 dns_fixedname_t nextfixed;
9211 dns_kasp_t *kasp;
9212 dns_name_t *name, *nextname;
9213 dns_rdataset_t rdataset;
9214 dns_signing_t *signing, *nextsigning;
9215 dns_signinglist_t cleanup;
9216 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
9217 int32_t signatures;
9218 bool check_ksk, keyset_kskonly, is_ksk, is_zsk;
9219 bool with_ksk, with_zsk;
9220 bool commit = false;
9221 bool is_bottom_of_zone;
9222 bool build_nsec = false;
9223 bool build_nsec3 = false;
9224 bool use_kasp = false;
9225 bool first;
9226 isc_result_t result;
9227 isc_stdtime_t now, inception, soaexpire, expire;
9228 uint32_t jitter, sigvalidityinterval, expiryinterval;
9229 unsigned int i, j;
9230 unsigned int nkeys = 0;
9231 uint32_t nodes;
9232
9233 ENTER;
9234
9235 dns_rdataset_init(&rdataset);
9236 name = dns_fixedname_initname(&fixed);
9237 nextname = dns_fixedname_initname(&nextfixed);
9238 dns_diff_init(zone->mctx, &_sig_diff);
9239 dns_diff_init(zone->mctx, &post_diff);
9240 zonediff_init(&zonediff, &_sig_diff);
9241 ISC_LIST_INIT(cleanup);
9242
9243 /*
9244 * Updates are disabled. Pause for 1 minute.
9245 */
9246 if (zone->update_disabled) {
9247 result = ISC_R_FAILURE;
9248 goto cleanup;
9249 }
9250
9251 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9252 if (zone->db != NULL) {
9253 dns_db_attach(zone->db, &db);
9254 }
9255 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9256 if (db == NULL) {
9257 result = ISC_R_FAILURE;
9258 goto cleanup;
9259 }
9260
9261 result = dns_db_newversion(db, &version);
9262 if (result != ISC_R_SUCCESS) {
9263 dnssec_log(zone, ISC_LOG_ERROR,
9264 "zone_sign:dns_db_newversion -> %s",
9265 dns_result_totext(result));
9266 goto cleanup;
9267 }
9268
9269 isc_stdtime_get(&now);
9270
9271 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
9272 DNS_MAXZONEKEYS, zone_keys, &nkeys);
9273 if (result != ISC_R_SUCCESS) {
9274 dnssec_log(zone, ISC_LOG_ERROR,
9275 "zone_sign:dns__zone_findkeys -> %s",
9276 dns_result_totext(result));
9277 goto cleanup;
9278 }
9279
9280 kasp = dns_zone_getkasp(zone);
9281 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
9282 inception = now - 3600; /* Allow for clock skew. */
9283 soaexpire = now + sigvalidityinterval;
9284 expiryinterval = dns_zone_getsigresigninginterval(zone);
9285 if (expiryinterval > sigvalidityinterval) {
9286 expiryinterval = sigvalidityinterval;
9287 } else {
9288 expiryinterval = sigvalidityinterval - expiryinterval;
9289 }
9290
9291 /*
9292 * Spread out signatures over time if they happen to be
9293 * clumped. We don't do this for each add_sigs() call as
9294 * we still want some clustering to occur.
9295 */
9296 if (sigvalidityinterval >= 3600U) {
9297 if (sigvalidityinterval > 7200U) {
9298 jitter = isc_random_uniform(expiryinterval);
9299 } else {
9300 jitter = isc_random_uniform(1200);
9301 }
9302 expire = soaexpire - jitter - 1;
9303 } else {
9304 expire = soaexpire - 1;
9305 }
9306
9307 /*
9308 * We keep pulling nodes off each iterator in turn until
9309 * we have no more nodes to pull off or we reach the limits
9310 * for this quantum.
9311 */
9312 nodes = zone->nodes;
9313 signatures = zone->signatures;
9314 signing = ISC_LIST_HEAD(zone->signing);
9315 first = true;
9316
9317 if (dns_zone_use_kasp(zone)) {
9318 check_ksk = false;
9319 keyset_kskonly = true;
9320 use_kasp = true;
9321 } else {
9322 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
9323 keyset_kskonly = DNS_ZONE_OPTION(zone,
9324 DNS_ZONEOPT_DNSKEYKSKONLY);
9325 }
9326 dnssec_log(zone, ISC_LOG_DEBUG(3), "zone_sign:use kasp -> %s",
9327 use_kasp ? "yes" : "no");
9328
9329 /* Determine which type of chain to build */
9330 if (use_kasp) {
9331 build_nsec3 = dns_kasp_nsec3(kasp);
9332 build_nsec = !build_nsec3;
9333 } else {
9334 CHECK(dns_private_chains(db, version, zone->privatetype,
9335 &build_nsec, &build_nsec3));
9336 /* If neither chain is found, default to NSEC */
9337 if (!build_nsec && !build_nsec3) {
9338 build_nsec = true;
9339 }
9340 }
9341
9342 while (signing != NULL && nodes-- > 0 && signatures > 0) {
9343 bool has_alg = false;
9344
9345 dns_dbiterator_pause(signing->dbiterator);
9346 nextsigning = ISC_LIST_NEXT(signing, link);
9347
9348 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9349 if (signing->done || signing->db != zone->db) {
9350 /*
9351 * The zone has been reloaded. We will have to
9352 * created new signings as part of the reload
9353 * process so we can destroy this one.
9354 */
9355 ISC_LIST_UNLINK(zone->signing, signing, link);
9356 ISC_LIST_APPEND(cleanup, signing, link);
9357 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9358 goto next_signing;
9359 }
9360 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9361
9362 if (signing->db != db) {
9363 goto next_signing;
9364 }
9365
9366 is_bottom_of_zone = false;
9367
9368 if (first && signing->deleteit) {
9369 /*
9370 * Remove the key we are deleting from consideration.
9371 */
9372 for (i = 0, j = 0; i < nkeys; i++) {
9373 /*
9374 * Find the key we want to remove.
9375 */
9376 if (ALG(zone_keys[i]) == signing->algorithm &&
9377 dst_key_id(zone_keys[i]) == signing->keyid)
9378 {
9379 bool ksk = false;
9380 isc_result_t ret = dst_key_getbool(
9381 zone_keys[i], DST_BOOL_KSK,
9382 &ksk);
9383 if (ret != ISC_R_SUCCESS) {
9384 ksk = KSK(zone_keys[i]);
9385 }
9386 if (ksk) {
9387 dst_key_free(&zone_keys[i]);
9388 }
9389 continue;
9390 }
9391 zone_keys[j] = zone_keys[i];
9392 j++;
9393 }
9394 for (i = j; i < nkeys; i++) {
9395 zone_keys[i] = NULL;
9396 }
9397 nkeys = j;
9398 }
9399
9400 dns_dbiterator_current(signing->dbiterator, &node, name);
9401
9402 if (signing->deleteit) {
9403 dns_dbiterator_pause(signing->dbiterator);
9404 CHECK(del_sig(db, version, name, node, nkeys,
9405 signing->algorithm, signing->keyid,
9406 &has_alg, zonediff.diff));
9407 }
9408
9409 /*
9410 * On the first pass we need to check if the current node
9411 * has not been obscured.
9412 */
9413 if (first) {
9414 dns_fixedname_t ffound;
9415 dns_name_t *found;
9416 found = dns_fixedname_initname(&ffound);
9417 result = dns_db_find(
9418 db, name, version, dns_rdatatype_soa,
9419 DNS_DBFIND_NOWILD, 0, NULL, found, NULL, NULL);
9420 if ((result == DNS_R_DELEGATION ||
9421 result == DNS_R_DNAME) &&
9422 !dns_name_equal(name, found))
9423 {
9424 /*
9425 * Remember the obscuring name so that
9426 * we skip all obscured names.
9427 */
9428 dns_name_copynf(found, name);
9429 is_bottom_of_zone = true;
9430 goto next_node;
9431 }
9432 }
9433
9434 /*
9435 * Process one node.
9436 */
9437 with_ksk = false;
9438 with_zsk = false;
9439 dns_dbiterator_pause(signing->dbiterator);
9440
9441 CHECK(check_if_bottom_of_zone(db, node, version,
9442 &is_bottom_of_zone));
9443
9444 for (i = 0; !has_alg && i < nkeys; i++) {
9445 bool both = false;
9446
9447 /*
9448 * Find the keys we want to sign with.
9449 */
9450 if (!dst_key_isprivate(zone_keys[i])) {
9451 continue;
9452 }
9453 if (dst_key_inactive(zone_keys[i])) {
9454 continue;
9455 }
9456
9457 /*
9458 * When adding look for the specific key.
9459 */
9460 if (!signing->deleteit &&
9461 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
9462 dst_key_id(zone_keys[i]) != signing->keyid))
9463 {
9464 continue;
9465 }
9466
9467 /*
9468 * When deleting make sure we are properly signed
9469 * with the algorithm that was being removed.
9470 */
9471 if (signing->deleteit &&
9472 ALG(zone_keys[i]) != signing->algorithm) {
9473 continue;
9474 }
9475
9476 /*
9477 * Do we do KSK processing?
9478 */
9479 if (check_ksk && !REVOKE(zone_keys[i])) {
9480 bool have_ksk, have_nonksk;
9481 if (KSK(zone_keys[i])) {
9482 have_ksk = true;
9483 have_nonksk = false;
9484 } else {
9485 have_ksk = false;
9486 have_nonksk = true;
9487 }
9488 for (j = 0; j < nkeys; j++) {
9489 if (j == i || (ALG(zone_keys[i]) !=
9490 ALG(zone_keys[j]))) {
9491 continue;
9492 }
9493 /* Don't consider inactive keys, however
9494 * the key may be temporary offline, so
9495 * do consider keys which private key
9496 * files are unavailable.
9497 */
9498 if (dst_key_inactive(zone_keys[j])) {
9499 continue;
9500 }
9501 if (REVOKE(zone_keys[j])) {
9502 continue;
9503 }
9504 if (KSK(zone_keys[j])) {
9505 have_ksk = true;
9506 } else {
9507 have_nonksk = true;
9508 }
9509 both = have_ksk && have_nonksk;
9510 if (both) {
9511 break;
9512 }
9513 }
9514 }
9515 if (use_kasp) {
9516 /*
9517 * A dnssec-policy is found. Check what
9518 * RRsets this key can sign.
9519 */
9520 isc_result_t kresult;
9521 is_ksk = false;
9522 kresult = dst_key_getbool(
9523 zone_keys[i], DST_BOOL_KSK, &is_ksk);
9524 if (kresult != ISC_R_SUCCESS) {
9525 if (KSK(zone_keys[i])) {
9526 is_ksk = true;
9527 }
9528 }
9529
9530 is_zsk = false;
9531 kresult = dst_key_getbool(
9532 zone_keys[i], DST_BOOL_ZSK, &is_zsk);
9533 if (kresult != ISC_R_SUCCESS) {
9534 if (!KSK(zone_keys[i])) {
9535 is_zsk = true;
9536 }
9537 }
9538 /* Treat as if we have both KSK and ZSK. */
9539 both = true;
9540 } else if (both || REVOKE(zone_keys[i])) {
9541 is_ksk = KSK(zone_keys[i]);
9542 is_zsk = !KSK(zone_keys[i]);
9543 } else {
9544 is_ksk = false;
9545 is_zsk = true;
9546 }
9547
9548 /*
9549 * If deleting signatures, we need to ensure that
9550 * the RRset is still signed at least once by a
9551 * KSK and a ZSK.
9552 */
9553 if (signing->deleteit && is_zsk && with_zsk) {
9554 continue;
9555 }
9556
9557 if (signing->deleteit && is_ksk && with_ksk) {
9558 continue;
9559 }
9560
9561 CHECK(sign_a_node(
9562 db, zone, name, node, version, build_nsec3,
9563 build_nsec, zone_keys[i], inception, expire,
9564 zone->minimum, is_ksk, is_zsk,
9565 (both && keyset_kskonly), is_bottom_of_zone,
9566 zonediff.diff, &signatures, zone->mctx));
9567 /*
9568 * If we are adding we are done. Look for other keys
9569 * of the same algorithm if deleting.
9570 */
9571 if (!signing->deleteit) {
9572 break;
9573 }
9574 if (is_zsk) {
9575 with_zsk = true;
9576 }
9577 if (is_ksk) {
9578 with_ksk = true;
9579 }
9580 }
9581
9582 /*
9583 * Go onto next node.
9584 */
9585 next_node:
9586 first = false;
9587 dns_db_detachnode(db, &node);
9588 do {
9589 result = dns_dbiterator_next(signing->dbiterator);
9590 if (result == ISC_R_NOMORE) {
9591 ISC_LIST_UNLINK(zone->signing, signing, link);
9592 ISC_LIST_APPEND(cleanup, signing, link);
9593 dns_dbiterator_pause(signing->dbiterator);
9594 if (nkeys != 0 && build_nsec) {
9595 /*
9596 * We have finished regenerating the
9597 * zone with a zone signing key.
9598 * The NSEC chain is now complete and
9599 * there is a full set of signatures
9600 * for the zone. We can now clear the
9601 * OPT bit from the NSEC record.
9602 */
9603 result = updatesecure(
9604 db, version, &zone->origin,
9605 zone->minimum, false,
9606 &post_diff);
9607 if (result != ISC_R_SUCCESS) {
9608 dnssec_log(zone, ISC_LOG_ERROR,
9609 "updatesecure -> %s",
9610 dns_result_totext(
9611 result));
9612 goto cleanup;
9613 }
9614 }
9615 result = updatesignwithkey(
9616 zone, signing, version, build_nsec3,
9617 zone->minimum, &post_diff);
9618 if (result != ISC_R_SUCCESS) {
9619 dnssec_log(zone, ISC_LOG_ERROR,
9620 "updatesignwithkey -> %s",
9621 dns_result_totext(result));
9622 goto cleanup;
9623 }
9624 build_nsec = false;
9625 goto next_signing;
9626 } else if (result != ISC_R_SUCCESS) {
9627 dnssec_log(zone, ISC_LOG_ERROR,
9628 "zone_sign:"
9629 "dns_dbiterator_next -> %s",
9630 dns_result_totext(result));
9631 goto cleanup;
9632 } else if (is_bottom_of_zone) {
9633 dns_dbiterator_current(signing->dbiterator,
9634 &node, nextname);
9635 dns_db_detachnode(db, &node);
9636 if (!dns_name_issubdomain(nextname, name)) {
9637 break;
9638 }
9639 } else {
9640 break;
9641 }
9642 } while (1);
9643 continue;
9644
9645 next_signing:
9646 dns_dbiterator_pause(signing->dbiterator);
9647 signing = nextsigning;
9648 first = true;
9649 }
9650
9651 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9652 result = dns__zone_updatesigs(&post_diff, db, version,
9653 zone_keys, nkeys, zone, inception,
9654 expire, 0, now, check_ksk,
9655 keyset_kskonly, &zonediff);
9656 if (result != ISC_R_SUCCESS) {
9657 dnssec_log(zone, ISC_LOG_ERROR,
9658 "zone_sign:dns__zone_updatesigs -> %s",
9659 dns_result_totext(result));
9660 goto cleanup;
9661 }
9662 }
9663
9664 /*
9665 * Have we changed anything?
9666 */
9667 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9668 if (zonediff.offline) {
9669 commit = true;
9670 }
9671 result = ISC_R_SUCCESS;
9672 goto pauseall;
9673 }
9674
9675 commit = true;
9676
9677 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9678 &zonediff, zone_keys, nkeys, now, false);
9679 if (result != ISC_R_SUCCESS) {
9680 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9681 dns_result_totext(result));
9682 goto cleanup;
9683 }
9684
9685 result = update_soa_serial(zone, db, version, zonediff.diff, zone->mctx,
9686 zone->updatemethod);
9687 if (result != ISC_R_SUCCESS) {
9688 dnssec_log(zone, ISC_LOG_ERROR,
9689 "zone_sign:update_soa_serial -> %s",
9690 dns_result_totext(result));
9691 goto cleanup;
9692 }
9693
9694 /*
9695 * Generate maximum life time signatures so that the above loop
9696 * termination is sensible.
9697 */
9698 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9699 zonediff.diff, zone_keys, nkeys, zone->mctx,
9700 inception, soaexpire, check_ksk, keyset_kskonly);
9701 if (result != ISC_R_SUCCESS) {
9702 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9703 dns_result_totext(result));
9704 goto cleanup;
9705 }
9706
9707 /*
9708 * Write changes to journal file.
9709 */
9710 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
9711
9712 pauseall:
9713 /*
9714 * Pause all iterators so that dns_db_closeversion() can succeed.
9715 */
9716 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
9717 signing = ISC_LIST_NEXT(signing, link))
9718 {
9719 dns_dbiterator_pause(signing->dbiterator);
9720 }
9721
9722 for (signing = ISC_LIST_HEAD(cleanup); signing != NULL;
9723 signing = ISC_LIST_NEXT(signing, link))
9724 {
9725 dns_dbiterator_pause(signing->dbiterator);
9726 }
9727
9728 /*
9729 * Everything has succeeded. Commit the changes.
9730 */
9731 dns_db_closeversion(db, &version, commit);
9732
9733 /*
9734 * Everything succeeded so we can clean these up now.
9735 */
9736 signing = ISC_LIST_HEAD(cleanup);
9737 while (signing != NULL) {
9738 ISC_LIST_UNLINK(cleanup, signing, link);
9739 dns_db_detach(&signing->db);
9740 dns_dbiterator_destroy(&signing->dbiterator);
9741 isc_mem_put(zone->mctx, signing, sizeof *signing);
9742 signing = ISC_LIST_HEAD(cleanup);
9743 }
9744
9745 LOCK_ZONE(zone);
9746 set_resigntime(zone);
9747 if (commit) {
9748 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9749 zone_needdump(zone, DNS_DUMP_DELAY);
9750 }
9751 UNLOCK_ZONE(zone);
9752
9753 failure:
9754 if (result != ISC_R_SUCCESS) {
9755 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
9756 dns_result_totext(result));
9757 }
9758
9759 cleanup:
9760 /*
9761 * Pause all dbiterators.
9762 */
9763 for (signing = ISC_LIST_HEAD(zone->signing); signing != NULL;
9764 signing = ISC_LIST_NEXT(signing, link))
9765 {
9766 dns_dbiterator_pause(signing->dbiterator);
9767 }
9768
9769 /*
9770 * Rollback the cleanup list.
9771 */
9772 signing = ISC_LIST_HEAD(cleanup);
9773 while (signing != NULL) {
9774 ISC_LIST_UNLINK(cleanup, signing, link);
9775 ISC_LIST_PREPEND(zone->signing, signing, link);
9776 dns_dbiterator_first(signing->dbiterator);
9777 dns_dbiterator_pause(signing->dbiterator);
9778 signing = ISC_LIST_HEAD(cleanup);
9779 }
9780
9781 dns_diff_clear(&_sig_diff);
9782
9783 for (i = 0; i < nkeys; i++) {
9784 dst_key_free(&zone_keys[i]);
9785 }
9786
9787 if (node != NULL) {
9788 dns_db_detachnode(db, &node);
9789 }
9790
9791 if (version != NULL) {
9792 dns_db_closeversion(db, &version, false);
9793 dns_db_detach(&db);
9794 } else if (db != NULL) {
9795 dns_db_detach(&db);
9796 }
9797
9798 LOCK_ZONE(zone);
9799 if (ISC_LIST_HEAD(zone->signing) != NULL) {
9800 isc_interval_t interval;
9801 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9802 isc_interval_set(&interval, 60, 0); /* 1 minute */
9803 } else {
9804 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9805 }
9806 isc_time_nowplusinterval(&zone->signingtime, &interval);
9807 } else {
9808 isc_time_settoepoch(&zone->signingtime);
9809 }
9810 UNLOCK_ZONE(zone);
9811
9812 INSIST(version == NULL);
9813 }
9814
9815 static isc_result_t
9816 normalize_key(dns_rdata_t *rr, dns_rdata_t *target, unsigned char *data,
9817 int size) {
9818 dns_rdata_dnskey_t dnskey;
9819 dns_rdata_keydata_t keydata;
9820 isc_buffer_t buf;
9821 isc_result_t result;
9822
9823 dns_rdata_reset(target);
9824 isc_buffer_init(&buf, data, size);
9825
9826 switch (rr->type) {
9827 case dns_rdatatype_dnskey:
9828 result = dns_rdata_tostruct(rr, &dnskey, NULL);
9829 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9830 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
9831 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9832 &dnskey, &buf);
9833 break;
9834 case dns_rdatatype_keydata:
9835 result = dns_rdata_tostruct(rr, &keydata, NULL);
9836 if (result == ISC_R_UNEXPECTEDEND) {
9837 return (result);
9838 }
9839 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9840 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9841 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9842 &dnskey, &buf);
9843 break;
9844 default:
9845 INSIST(0);
9846 ISC_UNREACHABLE();
9847 }
9848 return (ISC_R_SUCCESS);
9849 }
9850
9851 /*
9852 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
9853 * a KEYDATA rdataset from the key zone.
9854 *
9855 * 'rr' contains either a DNSKEY record, or a KEYDATA record
9856 *
9857 * After normalizing keys to the same format (DNSKEY, with revoke bit
9858 * cleared), return true if a key that matches 'rr' is found in
9859 * 'rdset', or false if not.
9860 */
9861
9862 static bool
9863 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
9864 unsigned char data1[4096], data2[4096];
9865 dns_rdata_t rdata, rdata1, rdata2;
9866 isc_result_t result;
9867
9868 dns_rdata_init(&rdata);
9869 dns_rdata_init(&rdata1);
9870 dns_rdata_init(&rdata2);
9871
9872 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
9873 if (result != ISC_R_SUCCESS) {
9874 return (false);
9875 }
9876
9877 for (result = dns_rdataset_first(rdset); result == ISC_R_SUCCESS;
9878 result = dns_rdataset_next(rdset))
9879 {
9880 dns_rdata_reset(&rdata);
9881 dns_rdataset_current(rdset, &rdata);
9882 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
9883 if (result != ISC_R_SUCCESS) {
9884 continue;
9885 }
9886 if (dns_rdata_compare(&rdata1, &rdata2) == 0) {
9887 return (true);
9888 }
9889 }
9890
9891 return (false);
9892 }
9893
9894 /*
9895 * Calculate the refresh interval for a keydata zone, per
9896 * RFC5011: MAX(1 hr,
9897 * MIN(15 days,
9898 * 1/2 * OrigTTL,
9899 * 1/2 * RRSigExpirationInterval))
9900 * or for retries: MAX(1 hr,
9901 * MIN(1 day,
9902 * 1/10 * OrigTTL,
9903 * 1/10 * RRSigExpirationInterval))
9904 */
9905 static inline isc_stdtime_t
9906 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
9907 isc_result_t result;
9908 uint32_t t;
9909 dns_rdataset_t *rdset;
9910 dns_rdata_t sigrr = DNS_RDATA_INIT;
9911 dns_rdata_sig_t sig;
9912 isc_stdtime_t now;
9913
9914 isc_stdtime_get(&now);
9915
9916 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
9917 rdset = &kfetch->dnskeysigset;
9918 } else {
9919 return (now + dns_zone_mkey_hour);
9920 }
9921
9922 result = dns_rdataset_first(rdset);
9923 if (result != ISC_R_SUCCESS) {
9924 return (now + dns_zone_mkey_hour);
9925 }
9926
9927 dns_rdataset_current(rdset, &sigrr);
9928 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9929 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9930
9931 if (!retry) {
9932 t = sig.originalttl / 2;
9933
9934 if (isc_serial_gt(sig.timeexpire, now)) {
9935 uint32_t exp = (sig.timeexpire - now) / 2;
9936 if (t > exp) {
9937 t = exp;
9938 }
9939 }
9940
9941 if (t > (15 * dns_zone_mkey_day)) {
9942 t = (15 * dns_zone_mkey_day);
9943 }
9944
9945 if (t < dns_zone_mkey_hour) {
9946 t = dns_zone_mkey_hour;
9947 }
9948 } else {
9949 t = sig.originalttl / 10;
9950
9951 if (isc_serial_gt(sig.timeexpire, now)) {
9952 uint32_t exp = (sig.timeexpire - now) / 10;
9953 if (t > exp) {
9954 t = exp;
9955 }
9956 }
9957
9958 if (t > dns_zone_mkey_day) {
9959 t = dns_zone_mkey_day;
9960 }
9961
9962 if (t < dns_zone_mkey_hour) {
9963 t = dns_zone_mkey_hour;
9964 }
9965 }
9966
9967 return (now + t);
9968 }
9969
9970 /*
9971 * This routine is called when no changes are needed in a KEYDATA
9972 * record except to simply update the refresh timer. Caller should
9973 * hold zone lock.
9974 */
9975 static isc_result_t
9976 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff) {
9977 isc_result_t result;
9978 isc_buffer_t keyb;
9979 unsigned char key_buf[4096];
9980 dns_rdata_t rdata = DNS_RDATA_INIT;
9981 dns_rdata_keydata_t keydata;
9982 dns_name_t *name;
9983 dns_zone_t *zone = kfetch->zone;
9984 isc_stdtime_t now;
9985
9986 name = dns_fixedname_name(&kfetch->name);
9987 isc_stdtime_get(&now);
9988
9989 for (result = dns_rdataset_first(&kfetch->keydataset);
9990 result == ISC_R_SUCCESS;
9991 result = dns_rdataset_next(&kfetch->keydataset))
9992 {
9993 dns_rdata_reset(&rdata);
9994 dns_rdataset_current(&kfetch->keydataset, &rdata);
9995
9996 /* Delete old version */
9997 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL, name,
9998 0, &rdata));
9999
10000 /* Update refresh timer */
10001 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
10002 if (result == ISC_R_UNEXPECTEDEND) {
10003 continue;
10004 }
10005 if (result != ISC_R_SUCCESS) {
10006 goto failure;
10007 }
10008 keydata.refresh = refresh_time(kfetch, true);
10009 set_refreshkeytimer(zone, &keydata, now, false);
10010
10011 dns_rdata_reset(&rdata);
10012 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10013 CHECK(dns_rdata_fromstruct(&rdata, zone->rdclass,
10014 dns_rdatatype_keydata, &keydata,
10015 &keyb));
10016
10017 /* Insert updated version */
10018 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD, name,
10019 0, &rdata));
10020 }
10021 result = ISC_R_SUCCESS;
10022 failure:
10023 return (result);
10024 }
10025
10026 /*
10027 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
10028 */
10029 static bool
10030 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
10031 isc_result_t result;
10032 dns_name_t *keyname;
10033 isc_mem_t *mctx;
10034 dns_rdata_t sigrr = DNS_RDATA_INIT;
10035 dns_rdata_t rr = DNS_RDATA_INIT;
10036 dns_rdata_rrsig_t sig;
10037 dns_rdata_dnskey_t dnskey;
10038 dst_key_t *dstkey = NULL;
10039 unsigned char key_buf[4096];
10040 isc_buffer_t keyb;
10041 bool answer = false;
10042
10043 REQUIRE(kfetch != NULL && keydata != NULL);
10044 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
10045
10046 keyname = dns_fixedname_name(&kfetch->name);
10047 mctx = kfetch->zone->view->mctx;
10048
10049 /* Generate a key from keydata */
10050 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10051 dns_keydata_todnskey(keydata, &dnskey, NULL);
10052 dns_rdata_fromstruct(&rr, keydata->common.rdclass, dns_rdatatype_dnskey,
10053 &dnskey, &keyb);
10054 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
10055 if (result != ISC_R_SUCCESS) {
10056 return (false);
10057 }
10058
10059 /* See if that key generated any of the signatures */
10060 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
10061 result == ISC_R_SUCCESS;
10062 result = dns_rdataset_next(&kfetch->dnskeysigset))
10063 {
10064 dns_fixedname_t fixed;
10065 dns_fixedname_init(&fixed);
10066
10067 dns_rdata_reset(&sigrr);
10068 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
10069 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10070 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10071
10072 if (dst_key_alg(dstkey) == sig.algorithm &&
10073 dst_key_rid(dstkey) == sig.keyid) {
10074 result = dns_dnssec_verify(
10075 keyname, &kfetch->dnskeyset, dstkey, false, 0,
10076 mctx, &sigrr, dns_fixedname_name(&fixed));
10077
10078 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
10079 "Confirm revoked DNSKEY is self-signed: %s",
10080 dns_result_totext(result));
10081
10082 if (result == ISC_R_SUCCESS) {
10083 answer = true;
10084 break;
10085 }
10086 }
10087 }
10088
10089 dst_key_free(&dstkey);
10090 return (answer);
10091 }
10092
10093 /*
10094 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
10095 * anchors are being managed; scan the keyset, and update the key zone and the
10096 * local trust anchors according to RFC5011.
10097 */
10098 static void
10099 keyfetch_done(isc_task_t *task, isc_event_t *event) {
10100 isc_result_t result, eresult;
10101 dns_fetchevent_t *devent;
10102 dns_keyfetch_t *kfetch;
10103 dns_zone_t *zone;
10104 isc_mem_t *mctx = NULL;
10105 dns_keytable_t *secroots = NULL;
10106 dns_dbversion_t *ver = NULL;
10107 dns_diff_t diff;
10108 bool alldone = false;
10109 bool commit = false;
10110 dns_name_t *keyname = NULL;
10111 dns_rdata_t sigrr = DNS_RDATA_INIT;
10112 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
10113 dns_rdata_t keydatarr = DNS_RDATA_INIT;
10114 dns_rdata_rrsig_t sig;
10115 dns_rdata_dnskey_t dnskey;
10116 dns_rdata_keydata_t keydata;
10117 bool initializing;
10118 char namebuf[DNS_NAME_FORMATSIZE];
10119 unsigned char key_buf[4096];
10120 isc_buffer_t keyb;
10121 dst_key_t *dstkey = NULL;
10122 isc_stdtime_t now;
10123 int pending = 0;
10124 bool secure = false, initial = false;
10125 bool free_needed;
10126 dns_keynode_t *keynode = NULL;
10127 dns_rdataset_t *dnskeys = NULL, *dnskeysigs = NULL;
10128 dns_rdataset_t *keydataset = NULL, dsset;
10129
10130 UNUSED(task);
10131 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
10132 INSIST(event->ev_arg != NULL);
10133
10134 kfetch = event->ev_arg;
10135 zone = kfetch->zone;
10136 isc_mem_attach(zone->mctx, &mctx);
10137 keyname = dns_fixedname_name(&kfetch->name);
10138 dnskeys = &kfetch->dnskeyset;
10139 dnskeysigs = &kfetch->dnskeysigset;
10140 keydataset = &kfetch->keydataset;
10141
10142 devent = (dns_fetchevent_t *)event;
10143 eresult = devent->result;
10144
10145 /* Free resources which are not of interest */
10146 if (devent->node != NULL) {
10147 dns_db_detachnode(devent->db, &devent->node);
10148 }
10149 if (devent->db != NULL) {
10150 dns_db_detach(&devent->db);
10151 }
10152 isc_event_free(&event);
10153 dns_resolver_destroyfetch(&kfetch->fetch);
10154
10155 LOCK_ZONE(zone);
10156 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
10157 goto cleanup;
10158 }
10159
10160 isc_stdtime_get(&now);
10161 dns_name_format(keyname, namebuf, sizeof(namebuf));
10162
10163 result = dns_view_getsecroots(zone->view, &secroots);
10164 INSIST(result == ISC_R_SUCCESS);
10165
10166 dns_diff_init(mctx, &diff);
10167
10168 CHECK(dns_db_newversion(kfetch->db, &ver));
10169
10170 zone->refreshkeycount--;
10171 alldone = (zone->refreshkeycount == 0);
10172
10173 if (alldone) {
10174 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10175 }
10176
10177 dnssec_log(zone, ISC_LOG_DEBUG(3),
10178 "Returned from key fetch in keyfetch_done() for '%s': %s",
10179 namebuf, dns_result_totext(eresult));
10180
10181 /* Fetch failed */
10182 if (eresult != ISC_R_SUCCESS || !dns_rdataset_isassociated(dnskeys)) {
10183 dnssec_log(zone, ISC_LOG_WARNING,
10184 "Unable to fetch DNSKEY set '%s': %s", namebuf,
10185 dns_result_totext(eresult));
10186 CHECK(minimal_update(kfetch, ver, &diff));
10187 goto done;
10188 }
10189
10190 /* No RRSIGs found */
10191 if (!dns_rdataset_isassociated(dnskeysigs)) {
10192 dnssec_log(zone, ISC_LOG_WARNING,
10193 "No DNSKEY RRSIGs found for '%s': %s", namebuf,
10194 dns_result_totext(eresult));
10195 CHECK(minimal_update(kfetch, ver, &diff));
10196 goto done;
10197 }
10198
10199 /*
10200 * Clear any cached trust level, as we need to run validation
10201 * over again; trusted keys might have changed.
10202 */
10203 dnskeys->trust = dnskeysigs->trust = dns_trust_none;
10204
10205 /* Look up the trust anchor */
10206 result = dns_keytable_find(secroots, keyname, &keynode);
10207 if (result != ISC_R_SUCCESS) {
10208 goto anchors_done;
10209 }
10210
10211 /*
10212 * If the keynode has a DS trust anchor, use it for verification.
10213 */
10214 dns_rdataset_init(&dsset);
10215 if (dns_keynode_dsset(keynode, &dsset)) {
10216 for (result = dns_rdataset_first(dnskeysigs);
10217 result == ISC_R_SUCCESS;
10218 result = dns_rdataset_next(dnskeysigs))
10219 {
10220 isc_result_t tresult;
10221 dns_rdata_t keyrdata = DNS_RDATA_INIT;
10222
10223 dns_rdata_reset(&sigrr);
10224 dns_rdataset_current(dnskeysigs, &sigrr);
10225 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
10226 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10227
10228 for (tresult = dns_rdataset_first(&dsset);
10229 tresult == ISC_R_SUCCESS;
10230 tresult = dns_rdataset_next(&dsset))
10231 {
10232 dns_rdata_t dsrdata = DNS_RDATA_INIT;
10233 dns_rdata_ds_t ds;
10234
10235 dns_rdata_reset(&dsrdata);
10236 dns_rdataset_current(&dsset, &dsrdata);
10237 tresult = dns_rdata_tostruct(&dsrdata, &ds,
10238 NULL);
10239 RUNTIME_CHECK(tresult == ISC_R_SUCCESS);
10240
10241 if (ds.key_tag != sig.keyid ||
10242 ds.algorithm != sig.algorithm) {
10243 continue;
10244 }
10245
10246 result = dns_dnssec_matchdskey(
10247 keyname, &dsrdata, dnskeys, &keyrdata);
10248 if (result == ISC_R_SUCCESS) {
10249 break;
10250 }
10251 }
10252
10253 if (tresult == ISC_R_NOMORE) {
10254 continue;
10255 }
10256
10257 result = dns_dnssec_keyfromrdata(keyname, &keyrdata,
10258 mctx, &dstkey);
10259 if (result != ISC_R_SUCCESS) {
10260 continue;
10261 }
10262
10263 result = dns_dnssec_verify(keyname, dnskeys, dstkey,
10264 false, 0, mctx, &sigrr,
10265 NULL);
10266 dst_key_free(&dstkey);
10267
10268 dnssec_log(zone, ISC_LOG_DEBUG(3),
10269 "Verifying DNSKEY set for zone "
10270 "'%s' using DS %d/%d: %s",
10271 namebuf, sig.keyid, sig.algorithm,
10272 dns_result_totext(result));
10273
10274 if (result == ISC_R_SUCCESS) {
10275 dnskeys->trust = dns_trust_secure;
10276 dnskeysigs->trust = dns_trust_secure;
10277 initial = dns_keynode_initial(keynode);
10278 dns_keynode_trust(keynode);
10279 secure = true;
10280 break;
10281 }
10282 }
10283 dns_rdataset_disassociate(&dsset);
10284 }
10285
10286 anchors_done:
10287 if (keynode != NULL) {
10288 dns_keytable_detachkeynode(secroots, &keynode);
10289 }
10290
10291 /*
10292 * If we were not able to verify the answer using the current
10293 * trusted keys then all we can do is look at any revoked keys.
10294 */
10295 if (!secure) {
10296 dnssec_log(zone, ISC_LOG_INFO,
10297 "DNSKEY set for zone '%s' could not be verified "
10298 "with current keys",
10299 namebuf);
10300 }
10301
10302 /*
10303 * First scan keydataset to find keys that are not in dnskeyset
10304 * - Missing keys which are not scheduled for removal,
10305 * log a warning
10306 * - Missing keys which are scheduled for removal and
10307 * the remove hold-down timer has completed should
10308 * be removed from the key zone
10309 * - Missing keys whose acceptance timers have not yet
10310 * completed, log a warning and reset the acceptance
10311 * timer to 30 days in the future
10312 * - All keys not being removed have their refresh timers
10313 * updated
10314 */
10315 initializing = true;
10316 for (result = dns_rdataset_first(keydataset); result == ISC_R_SUCCESS;
10317 result = dns_rdataset_next(keydataset))
10318 {
10319 dns_keytag_t keytag;
10320
10321 dns_rdata_reset(&keydatarr);
10322 dns_rdataset_current(keydataset, &keydatarr);
10323 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10324 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10325
10326 dns_keydata_todnskey(&keydata, &dnskey, NULL);
10327 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10328 if (result != ISC_R_SUCCESS) {
10329 /*
10330 * Skip if we cannot compute the key tag.
10331 * This may happen if the algorithm is unsupported
10332 */
10333 dns_zone_log(zone, ISC_LOG_ERROR,
10334 "Cannot compute tag for key in zone %s: "
10335 "%s "
10336 "(skipping)",
10337 namebuf, dns_result_totext(result));
10338 continue;
10339 }
10340 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10341
10342 /*
10343 * If any keydata record has a nonzero add holddown, then
10344 * there was a pre-existing trust anchor for this domain;
10345 * that means we are *not* initializing it and shouldn't
10346 * automatically trust all the keys we find at the zone apex.
10347 */
10348 initializing = initializing && (keydata.addhd == 0);
10349
10350 if (!matchkey(dnskeys, &keydatarr)) {
10351 bool deletekey = false;
10352
10353 if (!secure) {
10354 if (keydata.removehd != 0 &&
10355 keydata.removehd <= now) {
10356 deletekey = true;
10357 }
10358 } else if (keydata.addhd == 0) {
10359 deletekey = true;
10360 } else if (keydata.addhd > now) {
10361 dnssec_log(zone, ISC_LOG_INFO,
10362 "Pending key %d for zone %s "
10363 "unexpectedly missing "
10364 "restarting 30-day acceptance "
10365 "timer",
10366 keytag, namebuf);
10367 if (keydata.addhd < now + dns_zone_mkey_month) {
10368 keydata.addhd = now +
10369 dns_zone_mkey_month;
10370 }
10371 keydata.refresh = refresh_time(kfetch, false);
10372 } else if (keydata.removehd == 0) {
10373 dnssec_log(zone, ISC_LOG_INFO,
10374 "Active key %d for zone %s "
10375 "unexpectedly missing",
10376 keytag, namebuf);
10377 keydata.refresh = now + dns_zone_mkey_hour;
10378 } else if (keydata.removehd <= now) {
10379 deletekey = true;
10380 dnssec_log(zone, ISC_LOG_INFO,
10381 "Revoked key %d for zone %s "
10382 "missing: deleting from "
10383 "managed keys database",
10384 keytag, namebuf);
10385 } else {
10386 keydata.refresh = refresh_time(kfetch, false);
10387 }
10388
10389 if (secure || deletekey) {
10390 /* Delete old version */
10391 CHECK(update_one_rr(kfetch->db, ver, &diff,
10392 DNS_DIFFOP_DEL, keyname, 0,
10393 &keydatarr));
10394 }
10395
10396 if (!secure || deletekey) {
10397 continue;
10398 }
10399
10400 dns_rdata_reset(&keydatarr);
10401 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10402 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10403 dns_rdatatype_keydata, &keydata,
10404 &keyb);
10405
10406 /* Insert updated version */
10407 CHECK(update_one_rr(kfetch->db, ver, &diff,
10408 DNS_DIFFOP_ADD, keyname, 0,
10409 &keydatarr));
10410
10411 set_refreshkeytimer(zone, &keydata, now, false);
10412 }
10413 }
10414
10415 /*
10416 * Next scan dnskeyset:
10417 * - If new keys are found (i.e., lacking a match in keydataset)
10418 * add them to the key zone and set the acceptance timer
10419 * to 30 days in the future (or to immediately if we've
10420 * determined that we're initializing the zone for the
10421 * first time)
10422 * - Previously-known keys that have been revoked
10423 * must be scheduled for removal from the key zone (or,
10424 * if they hadn't been accepted as trust anchors yet
10425 * anyway, removed at once)
10426 * - Previously-known unrevoked keys whose acceptance timers
10427 * have completed are promoted to trust anchors
10428 * - All keys not being removed have their refresh
10429 * timers updated
10430 */
10431 for (result = dns_rdataset_first(dnskeys); result == ISC_R_SUCCESS;
10432 result = dns_rdataset_next(dnskeys))
10433 {
10434 bool revoked = false;
10435 bool newkey = false;
10436 bool updatekey = false;
10437 bool deletekey = false;
10438 bool trustkey = false;
10439 dns_keytag_t keytag;
10440
10441 dns_rdata_reset(&dnskeyrr);
10442 dns_rdataset_current(dnskeys, &dnskeyrr);
10443 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10444 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10445
10446 /* Skip ZSK's */
10447 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
10448 continue;
10449 }
10450
10451 result = compute_tag(keyname, &dnskey, mctx, &keytag);
10452 if (result != ISC_R_SUCCESS) {
10453 /*
10454 * Skip if we cannot compute the key tag.
10455 * This may happen if the algorithm is unsupported
10456 */
10457 dns_zone_log(zone, ISC_LOG_ERROR,
10458 "Cannot compute tag for key in zone %s: "
10459 "%s "
10460 "(skipping)",
10461 namebuf, dns_result_totext(result));
10462 continue;
10463 }
10464 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10465
10466 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
10467
10468 if (matchkey(keydataset, &dnskeyrr)) {
10469 dns_rdata_reset(&keydatarr);
10470 dns_rdataset_current(keydataset, &keydatarr);
10471 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
10472 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10473
10474 if (revoked && revocable(kfetch, &keydata)) {
10475 if (keydata.addhd > now) {
10476 /*
10477 * Key wasn't trusted yet, and now
10478 * it's been revoked? Just remove it
10479 */
10480 deletekey = true;
10481 dnssec_log(zone, ISC_LOG_INFO,
10482 "Pending key %d for "
10483 "zone %s is now revoked: "
10484 "deleting from the "
10485 "managed keys database",
10486 keytag, namebuf);
10487 } else if (keydata.removehd == 0) {
10488 /*
10489 * Remove key from secroots.
10490 */
10491 dns_view_untrust(zone->view, keyname,
10492 &dnskey);
10493
10494 /* If initializing, delete now */
10495 if (keydata.addhd == 0) {
10496 deletekey = true;
10497 } else {
10498 keydata.removehd =
10499 now +
10500 dns_zone_mkey_month;
10501 keydata.flags |=
10502 DNS_KEYFLAG_REVOKE;
10503 }
10504
10505 dnssec_log(zone, ISC_LOG_INFO,
10506 "Trusted key %d for "
10507 "zone %s is now revoked",
10508 keytag, namebuf);
10509 } else if (keydata.removehd < now) {
10510 /* Scheduled for removal */
10511 deletekey = true;
10512
10513 dnssec_log(zone, ISC_LOG_INFO,
10514 "Revoked key %d for "
10515 "zone %s removal timer "
10516 "complete: deleting from "
10517 "the managed keys database",
10518 keytag, namebuf);
10519 }
10520 } else if (revoked && keydata.removehd == 0) {
10521 dnssec_log(zone, ISC_LOG_WARNING,
10522 "Active key %d for zone "
10523 "%s is revoked but "
10524 "did not self-sign; "
10525 "ignoring",
10526 keytag, namebuf);
10527 continue;
10528 } else if (secure) {
10529 if (keydata.removehd != 0) {
10530 /*
10531 * Key isn't revoked--but it
10532 * seems it used to be.
10533 * Remove it now and add it
10534 * back as if it were a fresh key,
10535 * with a 30-day acceptance timer.
10536 */
10537 deletekey = true;
10538 newkey = true;
10539 keydata.removehd = 0;
10540 keydata.addhd = now +
10541 dns_zone_mkey_month;
10542
10543 dnssec_log(zone, ISC_LOG_INFO,
10544 "Revoked key %d for "
10545 "zone %s has returned: "
10546 "starting 30-day "
10547 "acceptance timer",
10548 keytag, namebuf);
10549 } else if (keydata.addhd > now) {
10550 pending++;
10551 } else if (keydata.addhd == 0) {
10552 keydata.addhd = now;
10553 }
10554
10555 if (keydata.addhd <= now) {
10556 trustkey = true;
10557 dnssec_log(zone, ISC_LOG_INFO,
10558 "Key %d for zone %s "
10559 "is now trusted (%s)",
10560 keytag, namebuf,
10561 initial ? "initializing key "
10562 "verified"
10563 : "acceptance timer "
10564 "complete");
10565 }
10566 } else if (keydata.addhd > now) {
10567 /*
10568 * Not secure, and key is pending:
10569 * reset the acceptance timer
10570 */
10571 pending++;
10572 keydata.addhd = now + dns_zone_mkey_month;
10573 dnssec_log(zone, ISC_LOG_INFO,
10574 "Pending key %d "
10575 "for zone %s was "
10576 "not validated: restarting "
10577 "30-day acceptance timer",
10578 keytag, namebuf);
10579 }
10580
10581 if (!deletekey && !newkey) {
10582 updatekey = true;
10583 }
10584 } else if (secure) {
10585 /*
10586 * Key wasn't in the key zone but it's
10587 * revoked now anyway, so just skip it
10588 */
10589 if (revoked) {
10590 continue;
10591 }
10592
10593 /* Key wasn't in the key zone: add it */
10594 newkey = true;
10595
10596 if (initializing) {
10597 dnssec_log(zone, ISC_LOG_WARNING,
10598 "Initializing automatic trust "
10599 "anchor management for zone '%s'; "
10600 "DNSKEY ID %d is now trusted, "
10601 "waiving the normal 30-day "
10602 "waiting period.",
10603 namebuf, keytag);
10604 trustkey = true;
10605 } else {
10606 dnssec_log(zone, ISC_LOG_INFO,
10607 "New key %d observed "
10608 "for zone '%s': "
10609 "starting 30-day "
10610 "acceptance timer",
10611 keytag, namebuf);
10612 }
10613 } else {
10614 /*
10615 * No previously known key, and the key is not
10616 * secure, so skip it.
10617 */
10618 continue;
10619 }
10620
10621 /* Delete old version */
10622 if (deletekey || !newkey) {
10623 CHECK(update_one_rr(kfetch->db, ver, &diff,
10624 DNS_DIFFOP_DEL, keyname, 0,
10625 &keydatarr));
10626 }
10627
10628 if (updatekey) {
10629 /* Set refresh timer */
10630 keydata.refresh = refresh_time(kfetch, false);
10631 dns_rdata_reset(&keydatarr);
10632 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10633 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10634 dns_rdatatype_keydata, &keydata,
10635 &keyb);
10636
10637 /* Insert updated version */
10638 CHECK(update_one_rr(kfetch->db, ver, &diff,
10639 DNS_DIFFOP_ADD, keyname, 0,
10640 &keydatarr));
10641 } else if (newkey) {
10642 /* Convert DNSKEY to KEYDATA */
10643 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10644 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10645 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10646 NULL);
10647 keydata.addhd = initializing
10648 ? now
10649 : now + dns_zone_mkey_month;
10650 keydata.refresh = refresh_time(kfetch, false);
10651 dns_rdata_reset(&keydatarr);
10652 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10653 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10654 dns_rdatatype_keydata, &keydata,
10655 &keyb);
10656
10657 /* Insert into key zone */
10658 CHECK(update_one_rr(kfetch->db, ver, &diff,
10659 DNS_DIFFOP_ADD, keyname, 0,
10660 &keydatarr));
10661 }
10662
10663 if (trustkey) {
10664 /* Trust this key. */
10665 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10666 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10667 trust_key(zone, keyname, &dnskey, false);
10668 }
10669
10670 if (secure && !deletekey) {
10671 INSIST(newkey || updatekey);
10672 set_refreshkeytimer(zone, &keydata, now, false);
10673 }
10674 }
10675
10676 /*
10677 * RFC5011 says, "A trust point that has all of its trust anchors
10678 * revoked is considered deleted and is treated as if the trust
10679 * point was never configured." But if someone revoked their
10680 * active key before the standby was trusted, that would mean the
10681 * zone would suddenly be nonsecured. We avoid this by checking to
10682 * see if there's pending keydata. If so, we put a null key in
10683 * the security roots; then all queries to the zone will fail.
10684 */
10685 if (pending != 0) {
10686 fail_secure(zone, keyname);
10687 }
10688
10689 done:
10690 if (!ISC_LIST_EMPTY(diff.tuples)) {
10691 /* Write changes to journal file. */
10692 CHECK(update_soa_serial(zone, kfetch->db, ver, &diff, mctx,
10693 zone->updatemethod));
10694 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10695 commit = true;
10696
10697 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10698 zone_needdump(zone, 30);
10699 } else if (result == ISC_R_NOMORE) {
10700 /*
10701 * If "updatekey" was true for all keys found in the DNSKEY
10702 * response and the previous update of those keys happened
10703 * during the same second (only possible if a key refresh was
10704 * externally triggered), it may happen that all relevant
10705 * update_one_rr() calls will return ISC_R_SUCCESS, but
10706 * diff.tuples will remain empty. Reset result to
10707 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
10708 */
10709 result = ISC_R_SUCCESS;
10710 }
10711
10712 failure:
10713 if (result != ISC_R_SUCCESS) {
10714 dnssec_log(zone, ISC_LOG_ERROR,
10715 "error during managed-keys processing (%s): "
10716 "DNSSEC validation may be at risk",
10717 isc_result_totext(result));
10718 }
10719 dns_diff_clear(&diff);
10720 if (ver != NULL) {
10721 dns_db_closeversion(kfetch->db, &ver, commit);
10722 }
10723
10724 cleanup:
10725 dns_db_detach(&kfetch->db);
10726
10727 isc_refcount_decrement(&zone->irefs);
10728
10729 kfetch->zone = NULL;
10730
10731 if (dns_rdataset_isassociated(keydataset)) {
10732 dns_rdataset_disassociate(keydataset);
10733 }
10734 if (dns_rdataset_isassociated(dnskeys)) {
10735 dns_rdataset_disassociate(dnskeys);
10736 }
10737 if (dns_rdataset_isassociated(dnskeysigs)) {
10738 dns_rdataset_disassociate(dnskeysigs);
10739 }
10740
10741 dns_name_free(keyname, mctx);
10742 isc_mem_putanddetach(&mctx, kfetch, sizeof(dns_keyfetch_t));
10743
10744 if (secroots != NULL) {
10745 dns_keytable_detach(&secroots);
10746 }
10747
10748 free_needed = exit_check(zone);
10749 UNLOCK_ZONE(zone);
10750 if (free_needed) {
10751 zone_free(zone);
10752 }
10753
10754 INSIST(ver == NULL);
10755 }
10756
10757 /*
10758 * Refresh the data in the key zone. Initiate a fetch to look up
10759 * DNSKEY records at the trust anchor name.
10760 */
10761 static void
10762 zone_refreshkeys(dns_zone_t *zone) {
10763 const char me[] = "zone_refreshkeys";
10764 isc_result_t result;
10765 dns_rriterator_t rrit;
10766 dns_db_t *db = NULL;
10767 dns_dbversion_t *ver = NULL;
10768 dns_diff_t diff;
10769 dns_rdata_t rdata = DNS_RDATA_INIT;
10770 dns_rdata_keydata_t kd;
10771 isc_stdtime_t now;
10772 bool commit = false;
10773 bool fetching = false, fetch_err = false;
10774 bool timerset = false;
10775
10776 ENTER;
10777 REQUIRE(zone->db != NULL);
10778
10779 isc_stdtime_get(&now);
10780
10781 LOCK_ZONE(zone);
10782 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10783 isc_time_settoepoch(&zone->refreshkeytime);
10784 UNLOCK_ZONE(zone);
10785 return;
10786 }
10787
10788 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10789 dns_db_attach(zone->db, &db);
10790 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10791
10792 dns_diff_init(zone->mctx, &diff);
10793
10794 CHECK(dns_db_newversion(db, &ver));
10795
10796 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
10797
10798 dns_rriterator_init(&rrit, db, ver, 0);
10799 for (result = dns_rriterator_first(&rrit); result == ISC_R_SUCCESS;
10800 result = dns_rriterator_nextrrset(&rrit))
10801 {
10802 isc_stdtime_t timer = 0xffffffff;
10803 dns_name_t *name = NULL, *kname = NULL;
10804 dns_rdataset_t *kdset = NULL;
10805 dns_keyfetch_t *kfetch;
10806 uint32_t ttl;
10807
10808 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
10809 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
10810 !dns_rdataset_isassociated(kdset))
10811 {
10812 continue;
10813 }
10814
10815 /*
10816 * Scan the stored keys looking for ones that need
10817 * removal or refreshing
10818 */
10819 for (result = dns_rdataset_first(kdset);
10820 result == ISC_R_SUCCESS; result = dns_rdataset_next(kdset))
10821 {
10822 dns_rdata_reset(&rdata);
10823 dns_rdataset_current(kdset, &rdata);
10824 result = dns_rdata_tostruct(&rdata, &kd, NULL);
10825 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10826
10827 /* Removal timer expired? */
10828 if (kd.removehd != 0 && kd.removehd < now) {
10829 dns_rriterator_pause(&rrit);
10830 CHECK(update_one_rr(db, ver, &diff,
10831 DNS_DIFFOP_DEL, name, ttl,
10832 &rdata));
10833 continue;
10834 }
10835
10836 /* Acceptance timer expired? */
10837 if (kd.addhd <= now) {
10838 timer = kd.addhd;
10839 }
10840
10841 /* Or do we just need to refresh the keyset? */
10842 if (timer > kd.refresh) {
10843 timer = kd.refresh;
10844 }
10845
10846 dns_rriterator_pause(&rrit);
10847 set_refreshkeytimer(zone, &kd, now, false);
10848 timerset = true;
10849 }
10850
10851 if (timer > now) {
10852 continue;
10853 }
10854
10855 dns_rriterator_pause(&rrit);
10856
10857 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
10858
10859 zone->refreshkeycount++;
10860 kfetch->zone = zone;
10861 isc_refcount_increment0(&zone->irefs);
10862 kname = dns_fixedname_initname(&kfetch->name);
10863 dns_name_dup(name, zone->mctx, kname);
10864 dns_rdataset_init(&kfetch->dnskeyset);
10865 dns_rdataset_init(&kfetch->dnskeysigset);
10866 dns_rdataset_init(&kfetch->keydataset);
10867 dns_rdataset_clone(kdset, &kfetch->keydataset);
10868 kfetch->db = NULL;
10869 dns_db_attach(db, &kfetch->db);
10870 kfetch->fetch = NULL;
10871
10872 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
10873 char namebuf[DNS_NAME_FORMATSIZE];
10874 dns_name_format(kname, namebuf, sizeof(namebuf));
10875 dnssec_log(zone, ISC_LOG_DEBUG(3),
10876 "Creating key fetch in "
10877 "zone_refreshkeys() for '%s'",
10878 namebuf);
10879 }
10880
10881 /*
10882 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is
10883 * not set and the cache still holds a non-expired, validated
10884 * version of the RRset being queried for by the time the
10885 * response is received, the cached RRset will be passed to
10886 * keyfetch_done() instead of the one received in the response
10887 * as the latter will have a lower trust level due to not being
10888 * validated until keyfetch_done() is called.
10889 */
10890
10891 #ifdef ENABLE_AFL
10892 if (!dns_fuzzing_resolver) {
10893 #endif /* ifdef ENABLE_AFL */
10894 result = dns_resolver_createfetch(
10895 zone->view->resolver, kname,
10896 dns_rdatatype_dnskey, NULL, NULL, NULL, NULL, 0,
10897 DNS_FETCHOPT_NOVALIDATE |
10898 DNS_FETCHOPT_UNSHARED |
10899 DNS_FETCHOPT_NOCACHED,
10900 0, NULL, zone->task, keyfetch_done, kfetch,
10901 &kfetch->dnskeyset, &kfetch->dnskeysigset,
10902 &kfetch->fetch);
10903 #ifdef ENABLE_AFL
10904 } else {
10905 result = ISC_R_FAILURE;
10906 }
10907 #endif /* ifdef ENABLE_AFL */
10908 if (result == ISC_R_SUCCESS) {
10909 fetching = true;
10910 } else {
10911 zone->refreshkeycount--;
10912 isc_refcount_decrement(&zone->irefs);
10913 dns_db_detach(&kfetch->db);
10914 dns_rdataset_disassociate(&kfetch->keydataset);
10915 dns_name_free(kname, zone->mctx);
10916 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
10917 dnssec_log(zone, ISC_LOG_WARNING,
10918 "Failed to create fetch for DNSKEY update");
10919 fetch_err = true;
10920 }
10921 }
10922 if (!ISC_LIST_EMPTY(diff.tuples)) {
10923 CHECK(update_soa_serial(zone, db, ver, &diff, zone->mctx,
10924 zone->updatemethod));
10925 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
10926 commit = true;
10927 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10928 zone_needdump(zone, 30);
10929 }
10930
10931 failure:
10932 if (fetch_err) {
10933 /*
10934 * Error during a key fetch; retry in an hour.
10935 */
10936 isc_time_t timenow, timethen;
10937 char timebuf[80];
10938
10939 TIME_NOW(&timenow);
10940 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
10941 zone->refreshkeytime = timethen;
10942 zone_settimer(zone, &timenow);
10943
10944 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
10945 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
10946 timebuf);
10947 } else if (!timerset) {
10948 isc_time_settoepoch(&zone->refreshkeytime);
10949 }
10950
10951 if (!fetching) {
10952 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10953 }
10954
10955 dns_diff_clear(&diff);
10956 if (ver != NULL) {
10957 dns_rriterator_destroy(&rrit);
10958 dns_db_closeversion(db, &ver, commit);
10959 }
10960 dns_db_detach(&db);
10961
10962 UNLOCK_ZONE(zone);
10963
10964 INSIST(ver == NULL);
10965 }
10966
10967 static void
10968 zone_maintenance(dns_zone_t *zone) {
10969 const char me[] = "zone_maintenance";
10970 isc_time_t now;
10971 isc_result_t result;
10972 bool dumping, load_pending, viewok;
10973 bool need_notify;
10974
10975 REQUIRE(DNS_ZONE_VALID(zone));
10976 ENTER;
10977
10978 /*
10979 * Are we pending load/reload?
10980 */
10981 LOCK_ZONE(zone);
10982 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
10983 UNLOCK_ZONE(zone);
10984
10985 if (load_pending) {
10986 return;
10987 }
10988
10989 /*
10990 * Configuring the view of this zone may have
10991 * failed, for example because the config file
10992 * had a syntax error. In that case, the view
10993 * adb or resolver will be NULL, and we had better not try
10994 * to do further maintenance on it.
10995 */
10996 LOCK_ZONE(zone);
10997 viewok = (zone->view != NULL && zone->view->adb != NULL);
10998 UNLOCK_ZONE(zone);
10999 if (!viewok) {
11000 return;
11001 }
11002
11003 TIME_NOW(&now);
11004
11005 /*
11006 * Expire check.
11007 */
11008 switch (zone->type) {
11009 case dns_zone_redirect:
11010 if (zone->masters == NULL) {
11011 break;
11012 }
11013 /* FALLTHROUGH */
11014 case dns_zone_slave:
11015 case dns_zone_mirror:
11016 case dns_zone_stub:
11017 LOCK_ZONE(zone);
11018 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
11019 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11020 {
11021 zone_expire(zone);
11022 zone->refreshtime = now;
11023 }
11024 UNLOCK_ZONE(zone);
11025 break;
11026 default:
11027 break;
11028 }
11029
11030 /*
11031 * Up to date check.
11032 */
11033 switch (zone->type) {
11034 case dns_zone_redirect:
11035 if (zone->masters == NULL) {
11036 break;
11037 }
11038 /* FALLTHROUGH */
11039 case dns_zone_slave:
11040 case dns_zone_mirror:
11041 case dns_zone_stub:
11042 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
11043 isc_time_compare(&now, &zone->refreshtime) >= 0)
11044 {
11045 dns_zone_refresh(zone);
11046 }
11047 break;
11048 default:
11049 break;
11050 }
11051
11052 /*
11053 * Secondaries send notifies before backing up to disk,
11054 * primaries after.
11055 */
11056 LOCK_ZONE(zone);
11057 need_notify = (zone->type == dns_zone_slave ||
11058 zone->type == dns_zone_mirror) &&
11059 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11060 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11061 (isc_time_compare(&now, &zone->notifytime) >= 0);
11062 UNLOCK_ZONE(zone);
11063
11064 if (need_notify) {
11065 zone_notify(zone, &now);
11066 }
11067
11068 /*
11069 * Do we need to consolidate the backing store?
11070 */
11071 switch (zone->type) {
11072 case dns_zone_master:
11073 case dns_zone_slave:
11074 case dns_zone_mirror:
11075 case dns_zone_key:
11076 case dns_zone_redirect:
11077 case dns_zone_stub:
11078 LOCK_ZONE(zone);
11079 if (zone->masterfile != NULL &&
11080 isc_time_compare(&now, &zone->dumptime) >= 0 &&
11081 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11082 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11083 {
11084 dumping = was_dumping(zone);
11085 } else {
11086 dumping = true;
11087 }
11088 UNLOCK_ZONE(zone);
11089 if (!dumping) {
11090 result = zone_dump(zone, true); /* task locked */
11091 if (result != ISC_R_SUCCESS) {
11092 dns_zone_log(zone, ISC_LOG_WARNING,
11093 "dump failed: %s",
11094 dns_result_totext(result));
11095 }
11096 }
11097 break;
11098 default:
11099 break;
11100 }
11101
11102 /*
11103 * Master/redirect zones send notifies now, if needed
11104 */
11105 switch (zone->type) {
11106 case dns_zone_master:
11107 case dns_zone_redirect:
11108 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
11109 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
11110 isc_time_compare(&now, &zone->notifytime) >= 0)
11111 {
11112 zone_notify(zone, &now);
11113 }
11114 default:
11115 break;
11116 }
11117
11118 /*
11119 * Do we need to refresh keys?
11120 */
11121 switch (zone->type) {
11122 case dns_zone_key:
11123 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
11124 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
11125 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING))
11126 {
11127 zone_refreshkeys(zone);
11128 }
11129 }
11130 break;
11131 case dns_zone_master:
11132 if (!isc_time_isepoch(&zone->refreshkeytime) &&
11133 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
11134 zone->rss_event == NULL)
11135 {
11136 zone_rekey(zone);
11137 }
11138 default:
11139 break;
11140 }
11141
11142 switch (zone->type) {
11143 case dns_zone_master:
11144 case dns_zone_redirect:
11145 case dns_zone_slave:
11146 /*
11147 * Do we need to sign/resign some RRsets?
11148 */
11149 if (zone->rss_event != NULL) {
11150 break;
11151 }
11152 if (!isc_time_isepoch(&zone->signingtime) &&
11153 isc_time_compare(&now, &zone->signingtime) >= 0)
11154 {
11155 zone_sign(zone);
11156 } else if (!isc_time_isepoch(&zone->resigntime) &&
11157 isc_time_compare(&now, &zone->resigntime) >= 0)
11158 {
11159 zone_resigninc(zone);
11160 } else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
11161 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
11162 {
11163 zone_nsec3chain(zone);
11164 }
11165 /*
11166 * Do we need to issue a key expiry warning?
11167 */
11168 if (!isc_time_isepoch(&zone->keywarntime) &&
11169 isc_time_compare(&now, &zone->keywarntime) >= 0)
11170 {
11171 set_key_expiry_warning(zone, zone->key_expiry,
11172 isc_time_seconds(&now));
11173 }
11174 break;
11175
11176 default:
11177 break;
11178 }
11179 LOCK_ZONE(zone);
11180 zone_settimer(zone, &now);
11181 UNLOCK_ZONE(zone);
11182 }
11183
11184 void
11185 dns_zone_markdirty(dns_zone_t *zone) {
11186 uint32_t serial;
11187 isc_result_t result = ISC_R_SUCCESS;
11188 dns_zone_t *secure = NULL;
11189
11190 /*
11191 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
11192 * could result in a deadlock due to a LOR so we will spin if we
11193 * can't obtain the both locks.
11194 */
11195 again:
11196 LOCK_ZONE(zone);
11197 if (zone->type == dns_zone_master) {
11198 if (inline_raw(zone)) {
11199 unsigned int soacount;
11200 secure = zone->secure;
11201 INSIST(secure != zone);
11202 TRYLOCK_ZONE(result, secure);
11203 if (result != ISC_R_SUCCESS) {
11204 UNLOCK_ZONE(zone);
11205 secure = NULL;
11206 isc_thread_yield();
11207 goto again;
11208 }
11209
11210 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11211 if (zone->db != NULL) {
11212 result = zone_get_from_db(
11213 zone, zone->db, NULL, &soacount,
11214 &serial, NULL, NULL, NULL, NULL, NULL);
11215 } else {
11216 result = DNS_R_NOTLOADED;
11217 }
11218 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11219 if (result == ISC_R_SUCCESS && soacount > 0U) {
11220 zone_send_secureserial(zone, serial);
11221 }
11222 }
11223
11224 /* XXXMPA make separate call back */
11225 if (result == ISC_R_SUCCESS) {
11226 set_resigntime(zone);
11227 if (zone->task != NULL) {
11228 isc_time_t now;
11229 TIME_NOW(&now);
11230 zone_settimer(zone, &now);
11231 }
11232 }
11233 }
11234 if (secure != NULL) {
11235 UNLOCK_ZONE(secure);
11236 }
11237 zone_needdump(zone, DNS_DUMP_DELAY);
11238 UNLOCK_ZONE(zone);
11239 }
11240
11241 void
11242 dns_zone_expire(dns_zone_t *zone) {
11243 REQUIRE(DNS_ZONE_VALID(zone));
11244
11245 LOCK_ZONE(zone);
11246 zone_expire(zone);
11247 UNLOCK_ZONE(zone);
11248 }
11249
11250 static void
11251 zone_expire(dns_zone_t *zone) {
11252 dns_db_t *db = NULL;
11253
11254 /*
11255 * 'zone' locked by caller.
11256 */
11257
11258 REQUIRE(LOCKED_ZONE(zone));
11259
11260 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
11261
11262 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
11263 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
11264 zone->retry = DNS_ZONE_DEFAULTRETRY;
11265 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11266
11267 /*
11268 * An RPZ zone has expired; before unloading it, we must
11269 * first remove it from the RPZ summary database. The
11270 * easiest way to do this is "update" it with an empty
11271 * database so that the update callback synchronizes
11272 * the diff automatically.
11273 */
11274 if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
11275 isc_result_t result;
11276 dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
11277
11278 CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
11279 dns_dbtype_zone, zone->rdclass, 0, NULL,
11280 &db));
11281 CHECK(dns_rpz_dbupdate_callback(db, rpz));
11282 dns_zone_log(zone, ISC_LOG_WARNING,
11283 "response-policy zone expired; "
11284 "policies unloaded");
11285 }
11286
11287 failure:
11288 if (db != NULL) {
11289 dns_db_detach(&db);
11290 }
11291
11292 zone_unload(zone);
11293 }
11294
11295 void
11296 dns_zone_refresh(dns_zone_t *zone) {
11297 isc_interval_t i;
11298 uint32_t oldflags;
11299 unsigned int j;
11300 isc_result_t result;
11301
11302 REQUIRE(DNS_ZONE_VALID(zone));
11303
11304 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11305 return;
11306 }
11307
11308 /*
11309 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
11310 * in progress at a time.
11311 */
11312
11313 LOCK_ZONE(zone);
11314 oldflags = atomic_load(&zone->flags);
11315 if (zone->masterscnt == 0) {
11316 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
11317 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0) {
11318 dns_zone_log(zone, ISC_LOG_ERROR,
11319 "cannot refresh: no primaries");
11320 }
11321 goto unlock;
11322 }
11323 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
11324 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11325 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11326 if ((oldflags & (DNS_ZONEFLG_REFRESH | DNS_ZONEFLG_LOADING)) != 0) {
11327 goto unlock;
11328 }
11329
11330 /*
11331 * Set the next refresh time as if refresh check has failed.
11332 * Setting this to the retry time will do that. XXXMLG
11333 * If we are successful it will be reset using zone->refresh.
11334 */
11335 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
11336 0);
11337 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
11338 if (result != ISC_R_SUCCESS) {
11339 dns_zone_log(zone, ISC_LOG_WARNING,
11340 "isc_time_nowplusinterval() failed: %s",
11341 dns_result_totext(result));
11342 }
11343
11344 /*
11345 * When lacking user-specified timer values from the SOA,
11346 * do exponential backoff of the retry time up to a
11347 * maximum of six hours.
11348 */
11349 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) {
11350 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
11351 }
11352
11353 zone->curmaster = 0;
11354 for (j = 0; j < zone->masterscnt; j++) {
11355 zone->mastersok[j] = false;
11356 }
11357 /* initiate soa query */
11358 queue_soa_query(zone);
11359 unlock:
11360 UNLOCK_ZONE(zone);
11361 }
11362
11363 static isc_result_t
11364 zone_journal_rollforward(dns_zone_t *zone, dns_db_t *db, bool *needdump,
11365 bool *fixjournal) {
11366 dns_journal_t *journal = NULL;
11367 unsigned int options;
11368 isc_result_t result;
11369
11370 if (zone->type == dns_zone_master &&
11371 (inline_secure(zone) ||
11372 (zone->update_acl != NULL || zone->ssutable != NULL)))
11373 {
11374 options = DNS_JOURNALOPT_RESIGN;
11375 } else {
11376 options = 0;
11377 }
11378
11379 result = dns_journal_open(zone->mctx, zone->journal, DNS_JOURNAL_READ,
11380 &journal);
11381 if (result == ISC_R_NOTFOUND) {
11382 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(3),
11383 "no journal file, but that's OK ");
11384 return (ISC_R_SUCCESS);
11385 } else if (result != ISC_R_SUCCESS) {
11386 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11387 "journal open failed: %s",
11388 dns_result_totext(result));
11389 return (result);
11390 }
11391
11392 if (dns_journal_empty(journal)) {
11393 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
11394 "journal empty");
11395 dns_journal_destroy(&journal);
11396 return (ISC_R_SUCCESS);
11397 }
11398
11399 result = dns_journal_rollforward(journal, db, options);
11400 switch (result) {
11401 case ISC_R_SUCCESS:
11402 *needdump = true;
11403 /* FALLTHROUGH */
11404 case DNS_R_UPTODATE:
11405 if (dns_journal_recovered(journal)) {
11406 *fixjournal = true;
11407 dns_zone_logc(
11408 zone, DNS_LOGCATEGORY_ZONELOAD,
11409 ISC_LOG_DEBUG(1),
11410 "journal rollforward completed successfully "
11411 "using old journal format: %s",
11412 dns_result_totext(result));
11413 } else {
11414 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
11415 ISC_LOG_DEBUG(1),
11416 "journal rollforward completed "
11417 "successfully: %s",
11418 dns_result_totext(result));
11419 }
11420
11421 dns_journal_destroy(&journal);
11422 return (ISC_R_SUCCESS);
11423 case ISC_R_NOTFOUND:
11424 case ISC_R_RANGE:
11425 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11426 "journal rollforward failed: journal out of sync "
11427 "with zone");
11428 dns_journal_destroy(&journal);
11429 return (result);
11430 default:
11431 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
11432 "journal rollforward failed: %s",
11433 dns_result_totext(result));
11434 dns_journal_destroy(&journal);
11435 return (result);
11436 }
11437 }
11438
11439 static void
11440 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
11441 isc_result_t result;
11442 int32_t journalsize;
11443 dns_dbversion_t *ver = NULL;
11444 uint64_t dbsize;
11445 uint32_t options = 0;
11446
11447 INSIST(LOCKED_ZONE(zone));
11448 if (inline_raw(zone)) {
11449 INSIST(LOCKED_ZONE(zone->secure));
11450 }
11451
11452 journalsize = zone->journalsize;
11453 if (journalsize == -1) {
11454 journalsize = DNS_JOURNAL_SIZE_MAX;
11455 dns_db_currentversion(db, &ver);
11456 result = dns_db_getsize(db, ver, NULL, &dbsize);
11457 dns_db_closeversion(db, &ver, false);
11458 if (result != ISC_R_SUCCESS) {
11459 dns_zone_log(zone, ISC_LOG_ERROR,
11460 "zone_journal_compact: "
11461 "could not get zone size: %s",
11462 isc_result_totext(result));
11463 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
11464 journalsize = (int32_t)dbsize * 2;
11465 }
11466 }
11467 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FIXJOURNAL)) {
11468 options |= DNS_JOURNAL_COMPACTALL;
11469 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FIXJOURNAL);
11470 zone_debuglog(zone, "zone_journal_compact", 1,
11471 "repair full journal");
11472 } else {
11473 zone_debuglog(zone, "zone_journal_compact", 1,
11474 "target journal size %d", journalsize);
11475 }
11476 result = dns_journal_compact(zone->mctx, zone->journal, serial, options,
11477 journalsize);
11478 switch (result) {
11479 case ISC_R_SUCCESS:
11480 case ISC_R_NOSPACE:
11481 case ISC_R_NOTFOUND:
11482 dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s",
11483 dns_result_totext(result));
11484 break;
11485 default:
11486 dns_zone_log(zone, ISC_LOG_ERROR,
11487 "dns_journal_compact failed: %s",
11488 dns_result_totext(result));
11489 break;
11490 }
11491 }
11492
11493 isc_result_t
11494 dns_zone_flush(dns_zone_t *zone) {
11495 isc_result_t result = ISC_R_SUCCESS;
11496 bool dumping;
11497
11498 REQUIRE(DNS_ZONE_VALID(zone));
11499
11500 LOCK_ZONE(zone);
11501 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
11502 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11503 zone->masterfile != NULL) {
11504 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11505 result = ISC_R_ALREADYRUNNING;
11506 dumping = was_dumping(zone);
11507 } else {
11508 dumping = true;
11509 }
11510 UNLOCK_ZONE(zone);
11511 if (!dumping) {
11512 result = zone_dump(zone, true); /* Unknown task. */
11513 }
11514 return (result);
11515 }
11516
11517 isc_result_t
11518 dns_zone_dump(dns_zone_t *zone) {
11519 isc_result_t result = ISC_R_ALREADYRUNNING;
11520 bool dumping;
11521
11522 REQUIRE(DNS_ZONE_VALID(zone));
11523
11524 LOCK_ZONE(zone);
11525 dumping = was_dumping(zone);
11526 UNLOCK_ZONE(zone);
11527 if (!dumping) {
11528 result = zone_dump(zone, false); /* Unknown task. */
11529 }
11530 return (result);
11531 }
11532
11533 static void
11534 zone_needdump(dns_zone_t *zone, unsigned int delay) {
11535 const char me[] = "zone_needdump";
11536 isc_time_t dumptime;
11537 isc_time_t now;
11538
11539 /*
11540 * 'zone' locked by caller
11541 */
11542
11543 REQUIRE(DNS_ZONE_VALID(zone));
11544 REQUIRE(LOCKED_ZONE(zone));
11545 ENTER;
11546
11547 /*
11548 * Do we have a place to dump to and are we loaded?
11549 */
11550 if (zone->masterfile == NULL ||
11551 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
11552 return;
11553 }
11554
11555 TIME_NOW(&now);
11556 /* add some noise */
11557 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
11558
11559 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11560 if (isc_time_isepoch(&zone->dumptime) ||
11561 isc_time_compare(&zone->dumptime, &dumptime) > 0)
11562 {
11563 zone->dumptime = dumptime;
11564 }
11565 if (zone->task != NULL) {
11566 zone_settimer(zone, &now);
11567 }
11568 }
11569
11570 static void
11571 dump_done(void *arg, isc_result_t result) {
11572 const char me[] = "dump_done";
11573 dns_zone_t *zone = arg;
11574 dns_zone_t *secure = NULL;
11575 dns_db_t *db;
11576 dns_dbversion_t *version;
11577 bool again = false;
11578 bool compact = false;
11579 uint32_t serial;
11580 isc_result_t tresult;
11581
11582 REQUIRE(DNS_ZONE_VALID(zone));
11583
11584 ENTER;
11585
11586 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
11587 /*
11588 * We don't own these, zone->dctx must stay valid.
11589 */
11590 db = dns_dumpctx_db(zone->dctx);
11591 version = dns_dumpctx_version(zone->dctx);
11592 tresult = dns_db_getsoaserial(db, version, &serial);
11593
11594 /*
11595 * Handle lock order inversion.
11596 */
11597 again:
11598 LOCK_ZONE(zone);
11599 if (inline_raw(zone)) {
11600 secure = zone->secure;
11601 INSIST(secure != zone);
11602 TRYLOCK_ZONE(result, secure);
11603 if (result != ISC_R_SUCCESS) {
11604 UNLOCK_ZONE(zone);
11605 secure = NULL;
11606 isc_thread_yield();
11607 goto again;
11608 }
11609 }
11610
11611 /*
11612 * If there is a secure version of this zone
11613 * use its serial if it is less than ours.
11614 */
11615 if (tresult == ISC_R_SUCCESS && secure != NULL) {
11616 uint32_t sserial;
11617 isc_result_t mresult;
11618
11619 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
11620 if (secure->db != NULL) {
11621 mresult = dns_db_getsoaserial(zone->secure->db,
11622 NULL, &sserial);
11623 if (mresult == ISC_R_SUCCESS &&
11624 isc_serial_lt(sserial, serial)) {
11625 serial = sserial;
11626 }
11627 }
11628 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
11629 }
11630 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
11631 dns_db_t *zdb = NULL;
11632 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
11633 zone_journal_compact(zone, zdb, serial);
11634 dns_db_detach(&zdb);
11635 }
11636 } else if (tresult == ISC_R_SUCCESS) {
11637 compact = true;
11638 zone->compact_serial = serial;
11639 }
11640 if (secure != NULL) {
11641 UNLOCK_ZONE(secure);
11642 }
11643 UNLOCK_ZONE(zone);
11644 }
11645
11646 LOCK_ZONE(zone);
11647 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11648 if (compact) {
11649 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
11650 }
11651 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
11652 /*
11653 * Try again in a short while.
11654 */
11655 zone_needdump(zone, DNS_DUMP_DELAY);
11656 } else if (result == ISC_R_SUCCESS &&
11657 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
11658 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11659 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11660 {
11661 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11662 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
11663 isc_time_settoepoch(&zone->dumptime);
11664 again = true;
11665 } else if (result == ISC_R_SUCCESS) {
11666 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
11667 }
11668
11669 if (zone->dctx != NULL) {
11670 dns_dumpctx_detach(&zone->dctx);
11671 }
11672 zonemgr_putio(&zone->writeio);
11673 UNLOCK_ZONE(zone);
11674 if (again) {
11675 (void)zone_dump(zone, false);
11676 }
11677 dns_zone_idetach(&zone);
11678 }
11679
11680 static isc_result_t
11681 zone_dump(dns_zone_t *zone, bool compact) {
11682 const char me[] = "zone_dump";
11683 isc_result_t result;
11684 dns_dbversion_t *version = NULL;
11685 bool again;
11686 dns_db_t *db = NULL;
11687 char *masterfile = NULL;
11688 dns_masterformat_t masterformat = dns_masterformat_none;
11689
11690 /*
11691 * 'compact' MUST only be set if we are task locked.
11692 */
11693
11694 REQUIRE(DNS_ZONE_VALID(zone));
11695 ENTER;
11696
11697 redo:
11698 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11699 if (zone->db != NULL) {
11700 dns_db_attach(zone->db, &db);
11701 }
11702 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11703 LOCK_ZONE(zone);
11704 if (zone->masterfile != NULL) {
11705 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
11706 masterformat = zone->masterformat;
11707 }
11708 UNLOCK_ZONE(zone);
11709 if (db == NULL) {
11710 result = DNS_R_NOTLOADED;
11711 goto fail;
11712 }
11713 if (masterfile == NULL) {
11714 result = DNS_R_NOMASTERFILE;
11715 goto fail;
11716 }
11717
11718 if (compact && zone->type != dns_zone_stub) {
11719 dns_zone_t *dummy = NULL;
11720 LOCK_ZONE(zone);
11721 zone_iattach(zone, &dummy);
11722 result = zonemgr_getio(zone->zmgr, false, zone->task,
11723 zone_gotwritehandle, zone,
11724 &zone->writeio);
11725 if (result != ISC_R_SUCCESS) {
11726 zone_idetach(&dummy);
11727 } else {
11728 result = DNS_R_CONTINUE;
11729 }
11730 UNLOCK_ZONE(zone);
11731 } else {
11732 const dns_master_style_t *output_style;
11733
11734 dns_masterrawheader_t rawdata;
11735 dns_db_currentversion(db, &version);
11736 dns_master_initrawheader(&rawdata);
11737 if (inline_secure(zone)) {
11738 get_raw_serial(zone->raw, &rawdata);
11739 }
11740 if (zone->type == dns_zone_key) {
11741 output_style = &dns_master_style_keyzone;
11742 } else {
11743 output_style = &dns_master_style_default;
11744 }
11745 result = dns_master_dump(zone->mctx, db, version, output_style,
11746 masterfile, masterformat, &rawdata);
11747 dns_db_closeversion(db, &version, false);
11748 }
11749 fail:
11750 if (db != NULL) {
11751 dns_db_detach(&db);
11752 }
11753 if (masterfile != NULL) {
11754 isc_mem_free(zone->mctx, masterfile);
11755 }
11756 masterfile = NULL;
11757
11758 if (result == DNS_R_CONTINUE) {
11759 return (ISC_R_SUCCESS); /* XXXMPA */
11760 }
11761
11762 again = false;
11763 LOCK_ZONE(zone);
11764 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11765 if (result != ISC_R_SUCCESS) {
11766 /*
11767 * Try again in a short while.
11768 */
11769 zone_needdump(zone, DNS_DUMP_DELAY);
11770 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
11771 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11772 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11773 {
11774 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11775 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
11776 isc_time_settoepoch(&zone->dumptime);
11777 again = true;
11778 } else {
11779 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
11780 }
11781 UNLOCK_ZONE(zone);
11782 if (again) {
11783 goto redo;
11784 }
11785
11786 return (result);
11787 }
11788
11789 static isc_result_t
11790 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
11791 dns_masterformat_t format, const uint32_t rawversion) {
11792 isc_result_t result;
11793 dns_dbversion_t *version = NULL;
11794 dns_db_t *db = NULL;
11795 dns_masterrawheader_t rawdata;
11796
11797 REQUIRE(DNS_ZONE_VALID(zone));
11798
11799 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11800 if (zone->db != NULL) {
11801 dns_db_attach(zone->db, &db);
11802 }
11803 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11804 if (db == NULL) {
11805 return (DNS_R_NOTLOADED);
11806 }
11807
11808 dns_db_currentversion(db, &version);
11809 dns_master_initrawheader(&rawdata);
11810 if (rawversion == 0) {
11811 rawdata.flags |= DNS_MASTERRAW_COMPAT;
11812 } else if (inline_secure(zone)) {
11813 get_raw_serial(zone->raw, &rawdata);
11814 } else if (zone->sourceserialset) {
11815 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
11816 rawdata.sourceserial = zone->sourceserial;
11817 }
11818 result = dns_master_dumptostream(zone->mctx, db, version, style, format,
11819 &rawdata, fd);
11820 dns_db_closeversion(db, &version, false);
11821 dns_db_detach(&db);
11822 return (result);
11823 }
11824
11825 isc_result_t
11826 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
11827 const dns_master_style_t *style,
11828 const uint32_t rawversion) {
11829 return (dumptostream(zone, fd, style, format, rawversion));
11830 }
11831
11832 void
11833 dns_zone_unload(dns_zone_t *zone) {
11834 REQUIRE(DNS_ZONE_VALID(zone));
11835
11836 LOCK_ZONE(zone);
11837 zone_unload(zone);
11838 UNLOCK_ZONE(zone);
11839 }
11840
11841 static void
11842 notify_cancel(dns_zone_t *zone) {
11843 dns_notify_t *notify;
11844
11845 /*
11846 * 'zone' locked by caller.
11847 */
11848
11849 REQUIRE(LOCKED_ZONE(zone));
11850
11851 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
11852 notify = ISC_LIST_NEXT(notify, link))
11853 {
11854 if (notify->find != NULL) {
11855 dns_adb_cancelfind(notify->find);
11856 }
11857 if (notify->request != NULL) {
11858 dns_request_cancel(notify->request);
11859 }
11860 }
11861 }
11862
11863 static void
11864 forward_cancel(dns_zone_t *zone) {
11865 dns_forward_t *forward;
11866
11867 /*
11868 * 'zone' locked by caller.
11869 */
11870
11871 REQUIRE(LOCKED_ZONE(zone));
11872
11873 for (forward = ISC_LIST_HEAD(zone->forwards); forward != NULL;
11874 forward = ISC_LIST_NEXT(forward, link))
11875 {
11876 if (forward->request != NULL) {
11877 dns_request_cancel(forward->request);
11878 }
11879 }
11880 }
11881
11882 static void
11883 zone_unload(dns_zone_t *zone) {
11884 /*
11885 * 'zone' locked by caller.
11886 */
11887
11888 REQUIRE(LOCKED_ZONE(zone));
11889
11890 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11891 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
11892 {
11893 if (zone->writeio != NULL) {
11894 zonemgr_cancelio(zone->writeio);
11895 }
11896
11897 if (zone->dctx != NULL) {
11898 dns_dumpctx_cancel(zone->dctx);
11899 }
11900 }
11901 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11902 zone_detachdb(zone);
11903 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11904 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
11905 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11906
11907 if (zone->type == dns_zone_mirror) {
11908 dns_zone_log(zone, ISC_LOG_INFO,
11909 "mirror zone is no longer in use; "
11910 "reverting to normal recursion");
11911 }
11912 }
11913
11914 void
11915 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
11916 REQUIRE(DNS_ZONE_VALID(zone));
11917 REQUIRE(val > 0);
11918
11919 zone->minrefresh = val;
11920 }
11921
11922 void
11923 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
11924 REQUIRE(DNS_ZONE_VALID(zone));
11925 REQUIRE(val > 0);
11926
11927 zone->maxrefresh = val;
11928 }
11929
11930 void
11931 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
11932 REQUIRE(DNS_ZONE_VALID(zone));
11933 REQUIRE(val > 0);
11934
11935 zone->minretry = val;
11936 }
11937
11938 void
11939 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
11940 REQUIRE(DNS_ZONE_VALID(zone));
11941 REQUIRE(val > 0);
11942
11943 zone->maxretry = val;
11944 }
11945
11946 uint32_t
11947 dns_zone_getmaxrecords(dns_zone_t *zone) {
11948 REQUIRE(DNS_ZONE_VALID(zone));
11949
11950 return (zone->maxrecords);
11951 }
11952
11953 void
11954 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
11955 REQUIRE(DNS_ZONE_VALID(zone));
11956
11957 zone->maxrecords = val;
11958 }
11959
11960 static bool
11961 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
11962 isc_sockaddr_t *addr, dns_tsigkey_t *key) {
11963 dns_notify_t *notify;
11964 dns_zonemgr_t *zmgr;
11965 isc_result_t result;
11966
11967 for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL;
11968 notify = ISC_LIST_NEXT(notify, link))
11969 {
11970 if (notify->request != NULL) {
11971 continue;
11972 }
11973 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
11974 dns_name_equal(name, ¬ify->ns))
11975 {
11976 goto requeue;
11977 }
11978 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
11979 notify->key == key)
11980 {
11981 goto requeue;
11982 }
11983 }
11984 return (false);
11985
11986 requeue:
11987 /*
11988 * If we are enqueued on the startup ratelimiter and this is
11989 * not a startup notify, re-enqueue on the normal notify
11990 * ratelimiter.
11991 */
11992 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
11993 (notify->flags & DNS_NOTIFY_STARTUP) != 0)
11994 {
11995 zmgr = notify->zone->zmgr;
11996 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
11997 notify->event);
11998 if (result != ISC_R_SUCCESS) {
11999 return (true);
12000 }
12001
12002 notify->flags &= ~DNS_NOTIFY_STARTUP;
12003 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
12004 notify->zone->task,
12005 ¬ify->event);
12006 if (result != ISC_R_SUCCESS) {
12007 isc_event_free(¬ify->event);
12008 return (false);
12009 }
12010 }
12011
12012 return (true);
12013 }
12014
12015 static bool
12016 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
12017 dns_tsigkey_t *key = NULL;
12018 isc_sockaddr_t src;
12019 isc_sockaddr_t any;
12020 bool isself;
12021 isc_netaddr_t dstaddr;
12022 isc_result_t result;
12023
12024 if (zone->view == NULL || zone->isself == NULL) {
12025 return (false);
12026 }
12027
12028 switch (isc_sockaddr_pf(dst)) {
12029 case PF_INET:
12030 src = zone->notifysrc4;
12031 isc_sockaddr_any(&any);
12032 break;
12033 case PF_INET6:
12034 src = zone->notifysrc6;
12035 isc_sockaddr_any6(&any);
12036 break;
12037 default:
12038 return (false);
12039 }
12040
12041 /*
12042 * When sending from any the kernel will assign a source address
12043 * that matches the destination address.
12044 */
12045 if (isc_sockaddr_eqaddr(&any, &src)) {
12046 src = *dst;
12047 }
12048
12049 isc_netaddr_fromsockaddr(&dstaddr, dst);
12050 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
12051 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12052 return (false);
12053 }
12054 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
12055 zone->isselfarg);
12056 if (key != NULL) {
12057 dns_tsigkey_detach(&key);
12058 }
12059 return (isself);
12060 }
12061
12062 static void
12063 notify_destroy(dns_notify_t *notify, bool locked) {
12064 isc_mem_t *mctx;
12065
12066 REQUIRE(DNS_NOTIFY_VALID(notify));
12067
12068 if (notify->zone != NULL) {
12069 if (!locked) {
12070 LOCK_ZONE(notify->zone);
12071 }
12072 REQUIRE(LOCKED_ZONE(notify->zone));
12073 if (ISC_LINK_LINKED(notify, link)) {
12074 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
12075 }
12076 if (!locked) {
12077 UNLOCK_ZONE(notify->zone);
12078 }
12079 if (locked) {
12080 zone_idetach(¬ify->zone);
12081 } else {
12082 dns_zone_idetach(¬ify->zone);
12083 }
12084 }
12085 if (notify->find != NULL) {
12086 dns_adb_destroyfind(¬ify->find);
12087 }
12088 if (notify->request != NULL) {
12089 dns_request_destroy(¬ify->request);
12090 }
12091 if (dns_name_dynamic(¬ify->ns)) {
12092 dns_name_free(¬ify->ns, notify->mctx);
12093 }
12094 if (notify->key != NULL) {
12095 dns_tsigkey_detach(¬ify->key);
12096 }
12097 mctx = notify->mctx;
12098 isc_mem_put(notify->mctx, notify, sizeof(*notify));
12099 isc_mem_detach(&mctx);
12100 }
12101
12102 static isc_result_t
12103 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
12104 dns_notify_t *notify;
12105
12106 REQUIRE(notifyp != NULL && *notifyp == NULL);
12107
12108 notify = isc_mem_get(mctx, sizeof(*notify));
12109
12110 notify->mctx = NULL;
12111 isc_mem_attach(mctx, ¬ify->mctx);
12112 notify->flags = flags;
12113 notify->zone = NULL;
12114 notify->find = NULL;
12115 notify->request = NULL;
12116 notify->key = NULL;
12117 notify->event = NULL;
12118 isc_sockaddr_any(¬ify->dst);
12119 dns_name_init(¬ify->ns, NULL);
12120 ISC_LINK_INIT(notify, link);
12121 notify->magic = NOTIFY_MAGIC;
12122 *notifyp = notify;
12123 return (ISC_R_SUCCESS);
12124 }
12125
12126 /*
12127 * XXXAG should check for DNS_ZONEFLG_EXITING
12128 */
12129 static void
12130 process_adb_event(isc_task_t *task, isc_event_t *ev) {
12131 dns_notify_t *notify;
12132 isc_eventtype_t result;
12133
12134 UNUSED(task);
12135
12136 notify = ev->ev_arg;
12137 REQUIRE(DNS_NOTIFY_VALID(notify));
12138 INSIST(task == notify->zone->task);
12139 result = ev->ev_type;
12140 isc_event_free(&ev);
12141 if (result == DNS_EVENT_ADBMOREADDRESSES) {
12142 dns_adb_destroyfind(¬ify->find);
12143 notify_find_address(notify);
12144 return;
12145 }
12146 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
12147 LOCK_ZONE(notify->zone);
12148 notify_send(notify);
12149 UNLOCK_ZONE(notify->zone);
12150 }
12151 notify_destroy(notify, false);
12152 }
12153
12154 static void
12155 notify_find_address(dns_notify_t *notify) {
12156 isc_result_t result;
12157 unsigned int options;
12158
12159 REQUIRE(DNS_NOTIFY_VALID(notify));
12160 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET | DNS_ADBFIND_INET6 |
12161 DNS_ADBFIND_RETURNLAME;
12162
12163 if (notify->zone->view->adb == NULL) {
12164 goto destroy;
12165 }
12166
12167 result = dns_adb_createfind(
12168 notify->zone->view->adb, notify->zone->task, process_adb_event,
12169 notify, ¬ify->ns, dns_rootname, 0, options, 0, NULL,
12170 notify->zone->view->dstport, 0, NULL, ¬ify->find);
12171
12172 /* Something failed? */
12173 if (result != ISC_R_SUCCESS) {
12174 goto destroy;
12175 }
12176
12177 /* More addresses pending? */
12178 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0) {
12179 return;
12180 }
12181
12182 /* We have as many addresses as we can get. */
12183 LOCK_ZONE(notify->zone);
12184 notify_send(notify);
12185 UNLOCK_ZONE(notify->zone);
12186
12187 destroy:
12188 notify_destroy(notify, false);
12189 }
12190
12191 static isc_result_t
12192 notify_send_queue(dns_notify_t *notify, bool startup) {
12193 isc_event_t *e;
12194 isc_result_t result;
12195
12196 INSIST(notify->event == NULL);
12197 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
12198 notify_send_toaddr, notify, sizeof(isc_event_t));
12199 if (startup) {
12200 notify->event = e;
12201 }
12202 e->ev_arg = notify;
12203 e->ev_sender = NULL;
12204 result = isc_ratelimiter_enqueue(
12205 startup ? notify->zone->zmgr->startupnotifyrl
12206 : notify->zone->zmgr->notifyrl,
12207 notify->zone->task, &e);
12208 if (result != ISC_R_SUCCESS) {
12209 isc_event_free(&e);
12210 notify->event = NULL;
12211 }
12212 return (result);
12213 }
12214
12215 static void
12216 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
12217 dns_notify_t *notify;
12218 isc_result_t result;
12219 dns_message_t *message = NULL;
12220 isc_netaddr_t dstip;
12221 dns_tsigkey_t *key = NULL;
12222 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
12223 isc_sockaddr_t src;
12224 unsigned int options, timeout;
12225 bool have_notifysource = false;
12226 bool have_notifydscp = false;
12227 isc_dscp_t dscp = -1;
12228
12229 notify = event->ev_arg;
12230 REQUIRE(DNS_NOTIFY_VALID(notify));
12231
12232 UNUSED(task);
12233
12234 LOCK_ZONE(notify->zone);
12235
12236 notify->event = NULL;
12237
12238 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
12239 result = ISC_R_CANCELED;
12240 goto cleanup;
12241 }
12242
12243 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
12244 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
12245 notify->zone->view->requestmgr == NULL || notify->zone->db == NULL)
12246 {
12247 result = ISC_R_CANCELED;
12248 goto cleanup;
12249 }
12250
12251 /*
12252 * The raw IPv4 address should also exist. Don't send to the
12253 * mapped form.
12254 */
12255 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
12256 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr))
12257 {
12258 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12259 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12260 "notify: ignoring IPv6 mapped IPV4 address: %s",
12261 addrbuf);
12262 result = ISC_R_CANCELED;
12263 goto cleanup;
12264 }
12265
12266 result = notify_createmessage(notify->zone, notify->flags, &message);
12267 if (result != ISC_R_SUCCESS) {
12268 goto cleanup;
12269 }
12270
12271 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
12272 if (notify->key != NULL) {
12273 /* Transfer ownership of key */
12274 key = notify->key;
12275 notify->key = NULL;
12276 } else {
12277 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
12278 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
12279 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12280 notify_log(notify->zone, ISC_LOG_ERROR,
12281 "NOTIFY to %s not sent. "
12282 "Peer TSIG key lookup failure.",
12283 addrbuf);
12284 goto cleanup_message;
12285 }
12286 }
12287
12288 if (key != NULL) {
12289 char namebuf[DNS_NAME_FORMATSIZE];
12290
12291 dns_name_format(&key->name, namebuf, sizeof(namebuf));
12292 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12293 "sending notify to %s : TSIG (%s)", addrbuf,
12294 namebuf);
12295 } else {
12296 notify_log(notify->zone, ISC_LOG_DEBUG(3),
12297 "sending notify to %s", addrbuf);
12298 }
12299 options = 0;
12300 if (notify->zone->view->peers != NULL) {
12301 dns_peer_t *peer = NULL;
12302 bool usetcp = false;
12303 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
12304 &dstip, &peer);
12305 if (result == ISC_R_SUCCESS) {
12306 result = dns_peer_getnotifysource(peer, &src);
12307 if (result == ISC_R_SUCCESS) {
12308 have_notifysource = true;
12309 }
12310 dns_peer_getnotifydscp(peer, &dscp);
12311 if (dscp != -1) {
12312 have_notifydscp = true;
12313 }
12314 result = dns_peer_getforcetcp(peer, &usetcp);
12315 if (result == ISC_R_SUCCESS && usetcp) {
12316 options |= DNS_FETCHOPT_TCP;
12317 }
12318 }
12319 }
12320 switch (isc_sockaddr_pf(¬ify->dst)) {
12321 case PF_INET:
12322 if (!have_notifysource) {
12323 src = notify->zone->notifysrc4;
12324 }
12325 if (!have_notifydscp) {
12326 dscp = notify->zone->notifysrc4dscp;
12327 }
12328 break;
12329 case PF_INET6:
12330 if (!have_notifysource) {
12331 src = notify->zone->notifysrc6;
12332 }
12333 if (!have_notifydscp) {
12334 dscp = notify->zone->notifysrc6dscp;
12335 }
12336 break;
12337 default:
12338 result = ISC_R_NOTIMPLEMENTED;
12339 goto cleanup_key;
12340 }
12341 timeout = 15;
12342 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY)) {
12343 timeout = 30;
12344 }
12345 result = dns_request_createvia(
12346 notify->zone->view->requestmgr, message, &src, ¬ify->dst,
12347 dscp, options, key, timeout * 3, timeout, 0, notify->zone->task,
12348 notify_done, notify, ¬ify->request);
12349 if (result == ISC_R_SUCCESS) {
12350 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
12351 inc_stats(notify->zone,
12352 dns_zonestatscounter_notifyoutv4);
12353 } else {
12354 inc_stats(notify->zone,
12355 dns_zonestatscounter_notifyoutv6);
12356 }
12357 }
12358
12359 cleanup_key:
12360 if (key != NULL) {
12361 dns_tsigkey_detach(&key);
12362 }
12363 cleanup_message:
12364 dns_message_detach(&message);
12365 cleanup:
12366 UNLOCK_ZONE(notify->zone);
12367 isc_event_free(&event);
12368 if (result != ISC_R_SUCCESS) {
12369 notify_destroy(notify, false);
12370 }
12371 }
12372
12373 static void
12374 notify_send(dns_notify_t *notify) {
12375 dns_adbaddrinfo_t *ai;
12376 isc_sockaddr_t dst;
12377 isc_result_t result;
12378 dns_notify_t *newnotify = NULL;
12379 unsigned int flags;
12380 bool startup;
12381
12382 /*
12383 * Zone lock held by caller.
12384 */
12385 REQUIRE(DNS_NOTIFY_VALID(notify));
12386 REQUIRE(LOCKED_ZONE(notify->zone));
12387
12388 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING)) {
12389 return;
12390 }
12391
12392 for (ai = ISC_LIST_HEAD(notify->find->list); ai != NULL;
12393 ai = ISC_LIST_NEXT(ai, publink))
12394 {
12395 dst = ai->sockaddr;
12396 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
12397 NULL)) {
12398 continue;
12399 }
12400 if (notify_isself(notify->zone, &dst)) {
12401 continue;
12402 }
12403 newnotify = NULL;
12404 flags = notify->flags & DNS_NOTIFY_NOSOA;
12405 result = notify_create(notify->mctx, flags, &newnotify);
12406 if (result != ISC_R_SUCCESS) {
12407 goto cleanup;
12408 }
12409 zone_iattach(notify->zone, &newnotify->zone);
12410 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
12411 newnotify->dst = dst;
12412 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
12413 result = notify_send_queue(newnotify, startup);
12414 if (result != ISC_R_SUCCESS) {
12415 goto cleanup;
12416 }
12417 newnotify = NULL;
12418 }
12419
12420 cleanup:
12421 if (newnotify != NULL) {
12422 notify_destroy(newnotify, true);
12423 }
12424 }
12425
12426 void
12427 dns_zone_notify(dns_zone_t *zone) {
12428 isc_time_t now;
12429
12430 REQUIRE(DNS_ZONE_VALID(zone));
12431
12432 LOCK_ZONE(zone);
12433 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12434
12435 TIME_NOW(&now);
12436 zone_settimer(zone, &now);
12437 UNLOCK_ZONE(zone);
12438 }
12439
12440 static void
12441 zone_notify(dns_zone_t *zone, isc_time_t *now) {
12442 dns_dbnode_t *node = NULL;
12443 dns_db_t *zonedb = NULL;
12444 dns_dbversion_t *version = NULL;
12445 dns_name_t *origin = NULL;
12446 dns_name_t master;
12447 dns_rdata_ns_t ns;
12448 dns_rdata_soa_t soa;
12449 uint32_t serial;
12450 dns_rdata_t rdata = DNS_RDATA_INIT;
12451 dns_rdataset_t nsrdset;
12452 dns_rdataset_t soardset;
12453 isc_result_t result;
12454 unsigned int i;
12455 isc_sockaddr_t dst;
12456 bool isqueued;
12457 dns_notifytype_t notifytype;
12458 unsigned int flags = 0;
12459 bool loggednotify = false;
12460 bool startup;
12461
12462 REQUIRE(DNS_ZONE_VALID(zone));
12463
12464 LOCK_ZONE(zone);
12465 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12466 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
12467 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
12468 notifytype = zone->notifytype;
12469 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
12470 UNLOCK_ZONE(zone);
12471
12472 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12473 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
12474 {
12475 return;
12476 }
12477
12478 if (notifytype == dns_notifytype_no) {
12479 return;
12480 }
12481
12482 if (notifytype == dns_notifytype_masteronly &&
12483 zone->type != dns_zone_master) {
12484 return;
12485 }
12486
12487 origin = &zone->origin;
12488
12489 /*
12490 * If the zone is dialup we are done as we don't want to send
12491 * the current soa so as to force a refresh query.
12492 */
12493 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
12494 flags |= DNS_NOTIFY_NOSOA;
12495 }
12496
12497 /*
12498 * Record that this was a notify due to starting up.
12499 */
12500 if (startup) {
12501 flags |= DNS_NOTIFY_STARTUP;
12502 }
12503
12504 /*
12505 * Get SOA RRset.
12506 */
12507 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12508 if (zone->db != NULL) {
12509 dns_db_attach(zone->db, &zonedb);
12510 }
12511 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12512 if (zonedb == NULL) {
12513 return;
12514 }
12515 dns_db_currentversion(zonedb, &version);
12516 result = dns_db_findnode(zonedb, origin, false, &node);
12517 if (result != ISC_R_SUCCESS) {
12518 goto cleanup1;
12519 }
12520
12521 dns_rdataset_init(&soardset);
12522 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
12523 dns_rdatatype_none, 0, &soardset, NULL);
12524 if (result != ISC_R_SUCCESS) {
12525 goto cleanup2;
12526 }
12527
12528 /*
12529 * Find serial and master server's name.
12530 */
12531 dns_name_init(&master, NULL);
12532 result = dns_rdataset_first(&soardset);
12533 if (result != ISC_R_SUCCESS) {
12534 goto cleanup3;
12535 }
12536 dns_rdataset_current(&soardset, &rdata);
12537 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12538 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12539 dns_rdata_reset(&rdata);
12540 dns_name_dup(&soa.origin, zone->mctx, &master);
12541 serial = soa.serial;
12542 dns_rdataset_disassociate(&soardset);
12543
12544 /*
12545 * Enqueue notify requests for 'also-notify' servers.
12546 */
12547 LOCK_ZONE(zone);
12548 for (i = 0; i < zone->notifycnt; i++) {
12549 dns_tsigkey_t *key = NULL;
12550 dns_notify_t *notify = NULL;
12551
12552 if ((zone->notifykeynames != NULL) &&
12553 (zone->notifykeynames[i] != NULL)) {
12554 dns_view_t *view = dns_zone_getview(zone);
12555 dns_name_t *keyname = zone->notifykeynames[i];
12556 (void)dns_view_gettsig(view, keyname, &key);
12557 }
12558
12559 dst = zone->notify[i];
12560 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
12561 if (key != NULL) {
12562 dns_tsigkey_detach(&key);
12563 }
12564 continue;
12565 }
12566
12567 result = notify_create(zone->mctx, flags, ¬ify);
12568 if (result != ISC_R_SUCCESS) {
12569 if (key != NULL) {
12570 dns_tsigkey_detach(&key);
12571 }
12572 continue;
12573 }
12574
12575 zone_iattach(zone, ¬ify->zone);
12576 notify->dst = dst;
12577
12578 INSIST(notify->key == NULL);
12579
12580 if (key != NULL) {
12581 notify->key = key;
12582 key = NULL;
12583 }
12584
12585 ISC_LIST_APPEND(zone->notifies, notify, link);
12586 result = notify_send_queue(notify, startup);
12587 if (result != ISC_R_SUCCESS) {
12588 notify_destroy(notify, true);
12589 }
12590 if (!loggednotify) {
12591 notify_log(zone, ISC_LOG_INFO,
12592 "sending notifies (serial %u)", serial);
12593 loggednotify = true;
12594 }
12595 }
12596 UNLOCK_ZONE(zone);
12597
12598 if (notifytype == dns_notifytype_explicit) {
12599 goto cleanup3;
12600 }
12601
12602 /*
12603 * Process NS RRset to generate notifies.
12604 */
12605
12606 dns_rdataset_init(&nsrdset);
12607 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
12608 dns_rdatatype_none, 0, &nsrdset, NULL);
12609 if (result != ISC_R_SUCCESS) {
12610 goto cleanup3;
12611 }
12612
12613 result = dns_rdataset_first(&nsrdset);
12614 while (result == ISC_R_SUCCESS) {
12615 dns_notify_t *notify = NULL;
12616
12617 dns_rdataset_current(&nsrdset, &rdata);
12618 result = dns_rdata_tostruct(&rdata, &ns, NULL);
12619 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12620 dns_rdata_reset(&rdata);
12621 /*
12622 * Don't notify the master server unless explicitly
12623 * configured to do so.
12624 */
12625 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
12626 dns_name_compare(&master, &ns.name) == 0)
12627 {
12628 result = dns_rdataset_next(&nsrdset);
12629 continue;
12630 }
12631
12632 if (!loggednotify) {
12633 notify_log(zone, ISC_LOG_INFO,
12634 "sending notifies (serial %u)", serial);
12635 loggednotify = true;
12636 }
12637
12638 LOCK_ZONE(zone);
12639 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
12640 UNLOCK_ZONE(zone);
12641 if (isqueued) {
12642 result = dns_rdataset_next(&nsrdset);
12643 continue;
12644 }
12645 result = notify_create(zone->mctx, flags, ¬ify);
12646 if (result != ISC_R_SUCCESS) {
12647 continue;
12648 }
12649 dns_zone_iattach(zone, ¬ify->zone);
12650 dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
12651 LOCK_ZONE(zone);
12652 ISC_LIST_APPEND(zone->notifies, notify, link);
12653 UNLOCK_ZONE(zone);
12654 notify_find_address(notify);
12655 result = dns_rdataset_next(&nsrdset);
12656 }
12657 dns_rdataset_disassociate(&nsrdset);
12658
12659 cleanup3:
12660 if (dns_name_dynamic(&master)) {
12661 dns_name_free(&master, zone->mctx);
12662 }
12663 cleanup2:
12664 dns_db_detachnode(zonedb, &node);
12665 cleanup1:
12666 dns_db_closeversion(zonedb, &version, false);
12667 dns_db_detach(&zonedb);
12668 }
12669
12670 /***
12671 *** Private
12672 ***/
12673 static inline isc_result_t
12674 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype, dns_name_t *name,
12675 dns_message_t **messagep) {
12676 dns_message_t *message = NULL;
12677 dns_name_t *qname = NULL;
12678 dns_rdataset_t *qrdataset = NULL;
12679 isc_result_t result;
12680
12681 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
12682
12683 message->opcode = dns_opcode_query;
12684 message->rdclass = zone->rdclass;
12685
12686 result = dns_message_gettempname(message, &qname);
12687 if (result != ISC_R_SUCCESS) {
12688 goto cleanup;
12689 }
12690
12691 result = dns_message_gettemprdataset(message, &qrdataset);
12692 if (result != ISC_R_SUCCESS) {
12693 goto cleanup;
12694 }
12695
12696 /*
12697 * Make question.
12698 */
12699 dns_name_init(qname, NULL);
12700 dns_name_clone(name, qname);
12701 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
12702 ISC_LIST_APPEND(qname->list, qrdataset, link);
12703 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
12704
12705 *messagep = message;
12706 return (ISC_R_SUCCESS);
12707
12708 cleanup:
12709 if (qname != NULL) {
12710 dns_message_puttempname(message, &qname);
12711 }
12712 if (qrdataset != NULL) {
12713 dns_message_puttemprdataset(message, &qrdataset);
12714 }
12715 dns_message_detach(&message);
12716 return (result);
12717 }
12718
12719 static isc_result_t
12720 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
12721 bool reqexpire) {
12722 isc_result_t result;
12723 dns_rdataset_t *rdataset = NULL;
12724 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
12725 int count = 0;
12726
12727 /* Set EDNS options if applicable. */
12728 if (reqnsid) {
12729 INSIST(count < DNS_EDNSOPTIONS);
12730 ednsopts[count].code = DNS_OPT_NSID;
12731 ednsopts[count].length = 0;
12732 ednsopts[count].value = NULL;
12733 count++;
12734 }
12735 if (reqexpire) {
12736 INSIST(count < DNS_EDNSOPTIONS);
12737 ednsopts[count].code = DNS_OPT_EXPIRE;
12738 ednsopts[count].length = 0;
12739 ednsopts[count].value = NULL;
12740 count++;
12741 }
12742 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
12743 ednsopts, count);
12744 if (result != ISC_R_SUCCESS) {
12745 return (result);
12746 }
12747
12748 return (dns_message_setopt(message, rdataset));
12749 }
12750
12751 /*
12752 * Called when stub zone update is finished.
12753 * Update zone refresh, retry, expire values accordingly with
12754 * SOA received from master, sync database to file, restart
12755 * zone management timer.
12756 */
12757 static void
12758 stub_finish_zone_update(dns_stub_t *stub, isc_time_t now) {
12759 uint32_t refresh, retry, expire;
12760 isc_result_t result;
12761 isc_interval_t i;
12762 unsigned int soacount;
12763 dns_zone_t *zone = stub->zone;
12764
12765 /*
12766 * Tidy up.
12767 */
12768 dns_db_closeversion(stub->db, &stub->version, true);
12769 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12770 if (zone->db == NULL) {
12771 zone_attachdb(zone, stub->db);
12772 }
12773 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
12774 &refresh, &retry, &expire, NULL, NULL);
12775 if (result == ISC_R_SUCCESS && soacount > 0U) {
12776 zone->refresh = RANGE(refresh, zone->minrefresh,
12777 zone->maxrefresh);
12778 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
12779 zone->expire = RANGE(expire, zone->refresh + zone->retry,
12780 DNS_MAX_EXPIRE);
12781 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12782 }
12783 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12784 dns_db_detach(&stub->db);
12785
12786 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12787 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
12788 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12789 isc_interval_set(&i, zone->expire, 0);
12790 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
12791
12792 if (zone->masterfile != NULL) {
12793 zone_needdump(zone, 0);
12794 }
12795
12796 zone_settimer(zone, &now);
12797 }
12798
12799 /*
12800 * Process answers for A and AAAA queries when
12801 * resolving nameserver addresses for which glue
12802 * was missing in a previous answer for a NS query.
12803 */
12804 static void
12805 stub_glue_response_cb(isc_task_t *task, isc_event_t *event) {
12806 const char me[] = "stub_glue_response_cb";
12807 dns_requestevent_t *revent = (dns_requestevent_t *)event;
12808 dns_stub_t *stub = NULL;
12809 dns_message_t *msg = NULL;
12810 dns_zone_t *zone = NULL;
12811 char master[ISC_SOCKADDR_FORMATSIZE];
12812 char source[ISC_SOCKADDR_FORMATSIZE];
12813 uint32_t addr_count, cnamecnt;
12814 isc_result_t result;
12815 isc_time_t now;
12816 struct stub_glue_request *request;
12817 struct stub_cb_args *cb_args;
12818 dns_rdataset_t *addr_rdataset = NULL;
12819 dns_dbnode_t *node = NULL;
12820
12821 UNUSED(task);
12822
12823 request = revent->ev_arg;
12824 cb_args = request->args;
12825 stub = cb_args->stub;
12826 INSIST(DNS_STUB_VALID(stub));
12827
12828 zone = stub->zone;
12829
12830 ENTER;
12831
12832 TIME_NOW(&now);
12833
12834 LOCK_ZONE(zone);
12835
12836 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12837 zone_debuglog(zone, me, 1, "exiting");
12838 goto cleanup;
12839 }
12840
12841 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12842 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12843
12844 if (revent->result != ISC_R_SUCCESS) {
12845 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
12846 &zone->sourceaddr, &now);
12847 dns_zone_log(zone, ISC_LOG_INFO,
12848 "could not refresh stub from master %s"
12849 " (source %s): %s",
12850 master, source, dns_result_totext(revent->result));
12851 goto cleanup;
12852 }
12853
12854 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12855 result = dns_request_getresponse(revent->request, msg, 0);
12856 if (result != ISC_R_SUCCESS) {
12857 dns_zone_log(zone, ISC_LOG_INFO,
12858 "refreshing stub: unable to parse response (%s)",
12859 isc_result_totext(result));
12860 goto cleanup;
12861 }
12862
12863 /*
12864 * Unexpected rcode.
12865 */
12866 if (msg->rcode != dns_rcode_noerror) {
12867 char rcode[128];
12868 isc_buffer_t rb;
12869
12870 isc_buffer_init(&rb, rcode, sizeof(rcode));
12871 (void)dns_rcode_totext(msg->rcode, &rb);
12872
12873 dns_zone_log(zone, ISC_LOG_INFO,
12874 "refreshing stub: "
12875 "unexpected rcode (%.*s) from %s (source %s)",
12876 (int)rb.used, rcode, master, source);
12877 goto cleanup;
12878 }
12879
12880 /*
12881 * We need complete messages.
12882 */
12883 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
12884 if (dns_request_usedtcp(revent->request)) {
12885 dns_zone_log(zone, ISC_LOG_INFO,
12886 "refreshing stub: truncated TCP "
12887 "response from master %s (source %s)",
12888 master, source);
12889 }
12890 goto cleanup;
12891 }
12892
12893 /*
12894 * If non-auth log.
12895 */
12896 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
12897 dns_zone_log(zone, ISC_LOG_INFO,
12898 "refreshing stub: "
12899 "non-authoritative answer from "
12900 "master %s (source %s)",
12901 master, source);
12902 goto cleanup;
12903 }
12904
12905 /*
12906 * Sanity checks.
12907 */
12908 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12909 addr_count = message_count(msg, DNS_SECTION_ANSWER,
12910 request->ipv4 ? dns_rdatatype_a
12911 : dns_rdatatype_aaaa);
12912
12913 if (cnamecnt != 0) {
12914 dns_zone_log(zone, ISC_LOG_INFO,
12915 "refreshing stub: unexpected CNAME response "
12916 "from master %s (source %s)",
12917 master, source);
12918 goto cleanup;
12919 }
12920
12921 if (addr_count == 0) {
12922 dns_zone_log(zone, ISC_LOG_INFO,
12923 "refreshing stub: no %s records in response "
12924 "from master %s (source %s)",
12925 request->ipv4 ? "A" : "AAAA", master, source);
12926 goto cleanup;
12927 }
12928 /*
12929 * Extract A or AAAA RRset from message.
12930 */
12931 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &request->name,
12932 request->ipv4 ? dns_rdatatype_a
12933 : dns_rdatatype_aaaa,
12934 dns_rdatatype_none, NULL, &addr_rdataset);
12935 if (result != ISC_R_SUCCESS) {
12936 if (result != DNS_R_NXDOMAIN && result != DNS_R_NXRRSET) {
12937 char namebuf[DNS_NAME_FORMATSIZE];
12938 dns_name_format(&request->name, namebuf,
12939 sizeof(namebuf));
12940 dns_zone_log(
12941 zone, ISC_LOG_INFO,
12942 "refreshing stub: dns_message_findname(%s/%s) "
12943 "failed (%s)",
12944 namebuf, request->ipv4 ? "A" : "AAAA",
12945 isc_result_totext(result));
12946 }
12947 goto cleanup;
12948 }
12949
12950 result = dns_db_findnode(stub->db, &request->name, true, &node);
12951 if (result != ISC_R_SUCCESS) {
12952 dns_zone_log(zone, ISC_LOG_INFO,
12953 "refreshing stub: "
12954 "dns_db_findnode() failed: %s",
12955 dns_result_totext(result));
12956 goto cleanup;
12957 }
12958
12959 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
12960 addr_rdataset, 0, NULL);
12961 if (result != ISC_R_SUCCESS) {
12962 dns_zone_log(zone, ISC_LOG_INFO,
12963 "refreshing stub: "
12964 "dns_db_addrdataset() failed: %s",
12965 dns_result_totext(result));
12966 }
12967 dns_db_detachnode(stub->db, &node);
12968
12969 cleanup:
12970 if (msg != NULL) {
12971 dns_message_detach(&msg);
12972 }
12973 isc_event_free(&event);
12974 dns_name_free(&request->name, zone->mctx);
12975 dns_request_destroy(&request->request);
12976 isc_mem_put(zone->mctx, request, sizeof(*request));
12977
12978 /* If last request, release all related resources */
12979 if (atomic_fetch_sub_release(&stub->pending_requests, 1) == 1) {
12980 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
12981 stub_finish_zone_update(stub, now);
12982 UNLOCK_ZONE(zone);
12983 stub->magic = 0;
12984 dns_zone_idetach(&stub->zone);
12985 INSIST(stub->db == NULL);
12986 INSIST(stub->version == NULL);
12987 isc_mem_put(stub->mctx, stub, sizeof(*stub));
12988 } else {
12989 UNLOCK_ZONE(zone);
12990 }
12991 }
12992
12993 /*
12994 * Create and send an A or AAAA query to the master
12995 * server of the stub zone given.
12996 */
12997 static isc_result_t
12998 stub_request_nameserver_address(struct stub_cb_args *args, bool ipv4,
12999 const dns_name_t *name) {
13000 dns_message_t *message = NULL;
13001 dns_zone_t *zone;
13002 isc_result_t result;
13003 struct stub_glue_request *request;
13004
13005 zone = args->stub->zone;
13006 request = isc_mem_get(zone->mctx, sizeof(*request));
13007 request->request = NULL;
13008 request->args = args;
13009 request->name = (dns_name_t)DNS_NAME_INITEMPTY;
13010 request->ipv4 = ipv4;
13011 dns_name_dup(name, zone->mctx, &request->name);
13012
13013 result = create_query(zone, ipv4 ? dns_rdatatype_a : dns_rdatatype_aaaa,
13014 &request->name, &message);
13015 INSIST(result == ISC_R_SUCCESS);
13016
13017 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13018 result = add_opt(message, args->udpsize, args->reqnsid, false);
13019 if (result != ISC_R_SUCCESS) {
13020 zone_debuglog(zone, "stub_send_query", 1,
13021 "unable to add opt record: %s",
13022 dns_result_totext(result));
13023 goto fail;
13024 }
13025 }
13026
13027 atomic_fetch_add_release(&args->stub->pending_requests, 1);
13028
13029 result = dns_request_createvia(
13030 zone->view->requestmgr, message, &zone->sourceaddr,
13031 &zone->masteraddr, args->dscp, DNS_REQUESTOPT_TCP,
13032 args->tsig_key, args->timeout * 3, args->timeout, 0, zone->task,
13033 stub_glue_response_cb, request, &request->request);
13034
13035 if (result != ISC_R_SUCCESS) {
13036 INSIST(atomic_fetch_sub_release(&args->stub->pending_requests,
13037 1) > 1);
13038 zone_debuglog(zone, "stub_send_query", 1,
13039 "dns_request_createvia() failed: %s",
13040 dns_result_totext(result));
13041 goto fail;
13042 }
13043
13044 dns_message_detach(&message);
13045
13046 return (ISC_R_SUCCESS);
13047
13048 fail:
13049 dns_name_free(&request->name, zone->mctx);
13050 isc_mem_put(zone->mctx, request, sizeof(*request));
13051
13052 if (message != NULL) {
13053 dns_message_detach(&message);
13054 }
13055
13056 return (result);
13057 }
13058
13059 static inline isc_result_t
13060 save_nsrrset(dns_message_t *message, dns_name_t *name,
13061 struct stub_cb_args *cb_args, dns_db_t *db,
13062 dns_dbversion_t *version) {
13063 dns_rdataset_t *nsrdataset = NULL;
13064 dns_rdataset_t *rdataset = NULL;
13065 dns_dbnode_t *node = NULL;
13066 dns_rdata_ns_t ns;
13067 isc_result_t result;
13068 dns_rdata_t rdata = DNS_RDATA_INIT;
13069 bool has_glue = false;
13070 dns_name_t *ns_name;
13071 /*
13072 * List of NS entries in answer, keep names that will be used
13073 * to resolve missing A/AAAA glue for each entry.
13074 */
13075 dns_namelist_t ns_list;
13076 ISC_LIST_INIT(ns_list);
13077
13078 /*
13079 * Extract NS RRset from message.
13080 */
13081 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
13082 dns_rdatatype_ns, dns_rdatatype_none,
13083 NULL, &nsrdataset);
13084 if (result != ISC_R_SUCCESS) {
13085 goto done;
13086 }
13087
13088 /*
13089 * Add NS rdataset.
13090 */
13091 result = dns_db_findnode(db, name, true, &node);
13092 if (result != ISC_R_SUCCESS) {
13093 goto done;
13094 }
13095 result = dns_db_addrdataset(db, node, version, 0, nsrdataset, 0, NULL);
13096 dns_db_detachnode(db, &node);
13097 if (result != ISC_R_SUCCESS) {
13098 goto done;
13099 }
13100 /*
13101 * Add glue rdatasets.
13102 */
13103 for (result = dns_rdataset_first(nsrdataset); result == ISC_R_SUCCESS;
13104 result = dns_rdataset_next(nsrdataset))
13105 {
13106 dns_rdataset_current(nsrdataset, &rdata);
13107 result = dns_rdata_tostruct(&rdata, &ns, NULL);
13108 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13109 dns_rdata_reset(&rdata);
13110
13111 if (!dns_name_issubdomain(&ns.name, name)) {
13112 continue;
13113 }
13114 rdataset = NULL;
13115 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
13116 &ns.name, dns_rdatatype_aaaa,
13117 dns_rdatatype_none, NULL,
13118 &rdataset);
13119 if (result == ISC_R_SUCCESS) {
13120 has_glue = true;
13121 result = dns_db_findnode(db, &ns.name, true, &node);
13122 if (result != ISC_R_SUCCESS) {
13123 goto done;
13124 }
13125 result = dns_db_addrdataset(db, node, version, 0,
13126 rdataset, 0, NULL);
13127 dns_db_detachnode(db, &node);
13128 if (result != ISC_R_SUCCESS) {
13129 goto done;
13130 }
13131 }
13132
13133 rdataset = NULL;
13134 result = dns_message_findname(
13135 message, DNS_SECTION_ADDITIONAL, &ns.name,
13136 dns_rdatatype_a, dns_rdatatype_none, NULL, &rdataset);
13137 if (result == ISC_R_SUCCESS) {
13138 has_glue = true;
13139 result = dns_db_findnode(db, &ns.name, true, &node);
13140 if (result != ISC_R_SUCCESS) {
13141 goto done;
13142 }
13143 result = dns_db_addrdataset(db, node, version, 0,
13144 rdataset, 0, NULL);
13145 dns_db_detachnode(db, &node);
13146 if (result != ISC_R_SUCCESS) {
13147 goto done;
13148 }
13149 }
13150
13151 /*
13152 * If no glue is found so far, we add the name to the list to
13153 * resolve the A/AAAA glue later. If any glue is found in any
13154 * iteration step, this list will be discarded and only the glue
13155 * provided in this message will be used.
13156 */
13157 if (!has_glue && dns_name_issubdomain(&ns.name, name)) {
13158 dns_name_t *tmp_name;
13159 tmp_name = isc_mem_get(cb_args->stub->mctx,
13160 sizeof(*tmp_name));
13161 dns_name_init(tmp_name, NULL);
13162 dns_name_dup(&ns.name, cb_args->stub->mctx, tmp_name);
13163 ISC_LIST_APPEND(ns_list, tmp_name, link);
13164 }
13165 }
13166
13167 if (result != ISC_R_NOMORE) {
13168 goto done;
13169 }
13170
13171 /*
13172 * If no glue records were found, we attempt to resolve A/AAAA
13173 * for each NS entry found in the answer.
13174 */
13175 if (!has_glue) {
13176 for (ns_name = ISC_LIST_HEAD(ns_list); ns_name != NULL;
13177 ns_name = ISC_LIST_NEXT(ns_name, link))
13178 {
13179 /*
13180 * Resolve NS IPv4 address/A.
13181 */
13182 result = stub_request_nameserver_address(cb_args, true,
13183 ns_name);
13184 if (result != ISC_R_SUCCESS) {
13185 goto done;
13186 }
13187 /*
13188 * Resolve NS IPv6 address/AAAA.
13189 */
13190 result = stub_request_nameserver_address(cb_args, false,
13191 ns_name);
13192 if (result != ISC_R_SUCCESS) {
13193 goto done;
13194 }
13195 }
13196 }
13197
13198 result = ISC_R_SUCCESS;
13199
13200 done:
13201 while ((ns_name = ISC_LIST_HEAD(ns_list)) != NULL) {
13202 ISC_LIST_UNLINK(ns_list, ns_name, link);
13203 dns_name_free(ns_name, cb_args->stub->mctx);
13204 isc_mem_put(cb_args->stub->mctx, ns_name, sizeof(*ns_name));
13205 }
13206 return (result);
13207 }
13208
13209 static void
13210 stub_callback(isc_task_t *task, isc_event_t *event) {
13211 const char me[] = "stub_callback";
13212 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13213 dns_stub_t *stub = NULL;
13214 dns_message_t *msg = NULL;
13215 dns_zone_t *zone = NULL;
13216 char master[ISC_SOCKADDR_FORMATSIZE];
13217 char source[ISC_SOCKADDR_FORMATSIZE];
13218 uint32_t nscnt, cnamecnt;
13219 isc_result_t result;
13220 isc_time_t now;
13221 bool exiting = false;
13222 unsigned int j;
13223 struct stub_cb_args *cb_args;
13224
13225 cb_args = revent->ev_arg;
13226 stub = cb_args->stub;
13227 INSIST(DNS_STUB_VALID(stub));
13228
13229 UNUSED(task);
13230
13231 zone = stub->zone;
13232
13233 ENTER;
13234
13235 TIME_NOW(&now);
13236
13237 LOCK_ZONE(zone);
13238
13239 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13240 zone_debuglog(zone, me, 1, "exiting");
13241 exiting = true;
13242 goto next_master;
13243 }
13244
13245 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13246 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13247
13248 if (revent->result != ISC_R_SUCCESS) {
13249 if (revent->result == ISC_R_TIMEDOUT &&
13250 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
13251 {
13252 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13253 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13254 "refreshing stub: timeout retrying "
13255 " without EDNS master %s (source %s)",
13256 master, source);
13257 goto same_master;
13258 }
13259 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
13260 &zone->sourceaddr, &now);
13261 dns_zone_log(zone, ISC_LOG_INFO,
13262 "could not refresh stub from master %s"
13263 " (source %s): %s",
13264 master, source, dns_result_totext(revent->result));
13265 goto next_master;
13266 }
13267
13268 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13269
13270 result = dns_request_getresponse(revent->request, msg, 0);
13271 if (result != ISC_R_SUCCESS) {
13272 goto next_master;
13273 }
13274
13275 /*
13276 * Unexpected rcode.
13277 */
13278 if (msg->rcode != dns_rcode_noerror) {
13279 char rcode[128];
13280 isc_buffer_t rb;
13281
13282 isc_buffer_init(&rb, rcode, sizeof(rcode));
13283 (void)dns_rcode_totext(msg->rcode, &rb);
13284
13285 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13286 (msg->rcode == dns_rcode_servfail ||
13287 msg->rcode == dns_rcode_notimp ||
13288 msg->rcode == dns_rcode_formerr))
13289 {
13290 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13291 "refreshing stub: rcode (%.*s) retrying "
13292 "without EDNS master %s (source %s)",
13293 (int)rb.used, rcode, master, source);
13294 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13295 goto same_master;
13296 }
13297
13298 dns_zone_log(zone, ISC_LOG_INFO,
13299 "refreshing stub: "
13300 "unexpected rcode (%.*s) from %s (source %s)",
13301 (int)rb.used, rcode, master, source);
13302 goto next_master;
13303 }
13304
13305 /*
13306 * We need complete messages.
13307 */
13308 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13309 if (dns_request_usedtcp(revent->request)) {
13310 dns_zone_log(zone, ISC_LOG_INFO,
13311 "refreshing stub: truncated TCP "
13312 "response from master %s (source %s)",
13313 master, source);
13314 goto next_master;
13315 }
13316 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13317 goto same_master;
13318 }
13319
13320 /*
13321 * If non-auth log and next master.
13322 */
13323 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13324 dns_zone_log(zone, ISC_LOG_INFO,
13325 "refreshing stub: "
13326 "non-authoritative answer from "
13327 "master %s (source %s)",
13328 master, source);
13329 goto next_master;
13330 }
13331
13332 /*
13333 * Sanity checks.
13334 */
13335 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13336 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
13337
13338 if (cnamecnt != 0) {
13339 dns_zone_log(zone, ISC_LOG_INFO,
13340 "refreshing stub: unexpected CNAME response "
13341 "from master %s (source %s)",
13342 master, source);
13343 goto next_master;
13344 }
13345
13346 if (nscnt == 0) {
13347 dns_zone_log(zone, ISC_LOG_INFO,
13348 "refreshing stub: no NS records in response "
13349 "from master %s (source %s)",
13350 master, source);
13351 goto next_master;
13352 }
13353
13354 atomic_fetch_add(&stub->pending_requests, 1);
13355
13356 /*
13357 * Save answer.
13358 */
13359 result = save_nsrrset(msg, &zone->origin, cb_args, stub->db,
13360 stub->version);
13361 if (result != ISC_R_SUCCESS) {
13362 dns_zone_log(zone, ISC_LOG_INFO,
13363 "refreshing stub: unable to save NS records "
13364 "from master %s (source %s)",
13365 master, source);
13366 goto next_master;
13367 }
13368
13369 dns_message_detach(&msg);
13370 isc_event_free(&event);
13371 dns_request_destroy(&zone->request);
13372
13373 /*
13374 * Check to see if there are no outstanding requests and
13375 * finish off if that is so.
13376 */
13377 if (atomic_fetch_sub(&stub->pending_requests, 1) == 1) {
13378 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13379 stub_finish_zone_update(stub, now);
13380 goto free_stub;
13381 }
13382
13383 UNLOCK_ZONE(zone);
13384 return;
13385
13386 next_master:
13387 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13388 if (stub->version != NULL) {
13389 dns_db_closeversion(stub->db, &stub->version, false);
13390 }
13391 if (stub->db != NULL) {
13392 dns_db_detach(&stub->db);
13393 }
13394 if (msg != NULL) {
13395 dns_message_detach(&msg);
13396 }
13397 isc_event_free(&event);
13398 dns_request_destroy(&zone->request);
13399 /*
13400 * Skip to next failed / untried master.
13401 */
13402 do {
13403 zone->curmaster++;
13404 } while (zone->curmaster < zone->masterscnt &&
13405 zone->mastersok[zone->curmaster]);
13406 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13407 if (exiting || zone->curmaster >= zone->masterscnt) {
13408 bool done = true;
13409 if (!exiting &&
13410 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13411 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13412 {
13413 /*
13414 * Did we get a good answer from all the primaries?
13415 */
13416 for (j = 0; j < zone->masterscnt; j++) {
13417 if (!zone->mastersok[j]) {
13418 {
13419 done = false;
13420 break;
13421 }
13422 }
13423 }
13424 } else {
13425 done = true;
13426 }
13427 if (!done) {
13428 zone->curmaster = 0;
13429 /*
13430 * Find the next failed master.
13431 */
13432 while (zone->curmaster < zone->masterscnt &&
13433 zone->mastersok[zone->curmaster]) {
13434 zone->curmaster++;
13435 }
13436 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13437 } else {
13438 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13439
13440 zone_settimer(zone, &now);
13441 goto free_stub;
13442 }
13443 }
13444 queue_soa_query(zone);
13445 goto free_stub;
13446
13447 same_master:
13448 isc_mem_put(zone->mctx, cb_args, sizeof(*cb_args));
13449 if (msg != NULL) {
13450 dns_message_detach(&msg);
13451 }
13452 isc_event_free(&event);
13453 dns_request_destroy(&zone->request);
13454 ns_query(zone, NULL, stub);
13455 UNLOCK_ZONE(zone);
13456 goto done;
13457
13458 free_stub:
13459 UNLOCK_ZONE(zone);
13460 stub->magic = 0;
13461 dns_zone_idetach(&stub->zone);
13462 INSIST(stub->db == NULL);
13463 INSIST(stub->version == NULL);
13464 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13465
13466 done:
13467 INSIST(event == NULL);
13468 return;
13469 }
13470
13471 /*
13472 * Get the EDNS EXPIRE option from the response and if it exists trim
13473 * expire to be not more than it.
13474 */
13475 static void
13476 get_edns_expire(dns_zone_t *zone, dns_message_t *message, uint32_t *expirep) {
13477 isc_result_t result;
13478 uint32_t expire;
13479 dns_rdata_t rdata = DNS_RDATA_INIT;
13480 isc_buffer_t optbuf;
13481 uint16_t optcode;
13482 uint16_t optlen;
13483
13484 REQUIRE(expirep != NULL);
13485 REQUIRE(message != NULL);
13486
13487 if (message->opt == NULL) {
13488 return;
13489 }
13490
13491 result = dns_rdataset_first(message->opt);
13492 if (result == ISC_R_SUCCESS) {
13493 dns_rdataset_current(message->opt, &rdata);
13494 isc_buffer_init(&optbuf, rdata.data, rdata.length);
13495 isc_buffer_add(&optbuf, rdata.length);
13496 while (isc_buffer_remaininglength(&optbuf) >= 4) {
13497 optcode = isc_buffer_getuint16(&optbuf);
13498 optlen = isc_buffer_getuint16(&optbuf);
13499 /*
13500 * A EDNS EXPIRE response has a length of 4.
13501 */
13502 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
13503 isc_buffer_forward(&optbuf, optlen);
13504 continue;
13505 }
13506 expire = isc_buffer_getuint32(&optbuf);
13507 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13508 "got EDNS EXPIRE of %u", expire);
13509 /*
13510 * Trim *expirep?
13511 */
13512 if (expire < *expirep) {
13513 *expirep = expire;
13514 }
13515 break;
13516 }
13517 }
13518 }
13519
13520 /*
13521 * Set the file modification time zone->expire seconds before expiretime.
13522 */
13523 static void
13524 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
13525 isc_result_t result;
13526 isc_time_t when;
13527 isc_interval_t i;
13528
13529 isc_interval_set(&i, zone->expire, 0);
13530 result = isc_time_subtract(expiretime, &i, &when);
13531 if (result != ISC_R_SUCCESS) {
13532 return;
13533 }
13534
13535 result = ISC_R_FAILURE;
13536 if (zone->journal != NULL) {
13537 result = isc_file_settime(zone->journal, &when);
13538 }
13539 if (result == ISC_R_SUCCESS &&
13540 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13541 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
13542 {
13543 result = isc_file_settime(zone->masterfile, &when);
13544 } else if (result != ISC_R_SUCCESS) {
13545 result = isc_file_settime(zone->masterfile, &when);
13546 }
13547
13548 /*
13549 * Someone removed the file from underneath us!
13550 */
13551 if (result == ISC_R_FILENOTFOUND) {
13552 zone_needdump(zone, DNS_DUMP_DELAY);
13553 } else if (result != ISC_R_SUCCESS) {
13554 dns_zone_log(zone, ISC_LOG_ERROR,
13555 "refresh: could not set "
13556 "file modification time of '%s': %s",
13557 zone->masterfile, dns_result_totext(result));
13558 }
13559 }
13560
13561 /*
13562 * An SOA query has finished (successfully or not).
13563 */
13564 static void
13565 refresh_callback(isc_task_t *task, isc_event_t *event) {
13566 const char me[] = "refresh_callback";
13567 dns_requestevent_t *revent = (dns_requestevent_t *)event;
13568 dns_zone_t *zone;
13569 dns_message_t *msg = NULL;
13570 uint32_t soacnt, cnamecnt, soacount, nscount;
13571 isc_time_t now;
13572 char master[ISC_SOCKADDR_FORMATSIZE];
13573 char source[ISC_SOCKADDR_FORMATSIZE];
13574 dns_rdataset_t *rdataset = NULL;
13575 dns_rdata_t rdata = DNS_RDATA_INIT;
13576 dns_rdata_soa_t soa;
13577 isc_result_t result;
13578 uint32_t serial, oldserial = 0;
13579 unsigned int j;
13580 bool do_queue_xfrin = false;
13581
13582 zone = revent->ev_arg;
13583 INSIST(DNS_ZONE_VALID(zone));
13584
13585 UNUSED(task);
13586
13587 ENTER;
13588
13589 TIME_NOW(&now);
13590
13591 LOCK_ZONE(zone);
13592
13593 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
13594 isc_event_free(&event);
13595 dns_request_destroy(&zone->request);
13596 goto detach;
13597 }
13598
13599 /*
13600 * if timeout log and next master;
13601 */
13602
13603 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
13604 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
13605
13606 if (revent->result != ISC_R_SUCCESS) {
13607 if (revent->result == ISC_R_TIMEDOUT &&
13608 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS))
13609 {
13610 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13611 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13612 "refresh: timeout retrying without EDNS "
13613 "master %s (source %s)",
13614 master, source);
13615 goto same_master;
13616 }
13617 if (revent->result == ISC_R_TIMEDOUT &&
13618 !dns_request_usedtcp(revent->request)) {
13619 dns_zone_log(zone, ISC_LOG_INFO,
13620 "refresh: retry limit for "
13621 "master %s exceeded (source %s)",
13622 master, source);
13623 /* Try with slave with TCP. */
13624 if ((zone->type == dns_zone_slave ||
13625 zone->type == dns_zone_mirror ||
13626 zone->type == dns_zone_redirect) &&
13627 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
13628 {
13629 if (!dns_zonemgr_unreachable(
13630 zone->zmgr, &zone->masteraddr,
13631 &zone->sourceaddr, &now))
13632 {
13633 DNS_ZONE_SETFLAG(
13634 zone,
13635 DNS_ZONEFLG_SOABEFOREAXFR);
13636 goto tcp_transfer;
13637 }
13638 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13639 "refresh: skipped tcp fallback "
13640 "as master %s (source %s) is "
13641 "unreachable (cached)",
13642 master, source);
13643 }
13644 } else {
13645 dns_zone_log(zone, ISC_LOG_INFO,
13646 "refresh: failure trying master "
13647 "%s (source %s): %s",
13648 master, source,
13649 dns_result_totext(revent->result));
13650 }
13651 goto next_master;
13652 }
13653
13654 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
13655 result = dns_request_getresponse(revent->request, msg, 0);
13656 if (result != ISC_R_SUCCESS) {
13657 dns_zone_log(zone, ISC_LOG_INFO,
13658 "refresh: failure trying master "
13659 "%s (source %s): %s",
13660 master, source, dns_result_totext(result));
13661 goto next_master;
13662 }
13663
13664 /*
13665 * Unexpected rcode.
13666 */
13667 if (msg->rcode != dns_rcode_noerror) {
13668 char rcode[128];
13669 isc_buffer_t rb;
13670
13671 isc_buffer_init(&rb, rcode, sizeof(rcode));
13672 (void)dns_rcode_totext(msg->rcode, &rb);
13673
13674 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13675 (msg->rcode == dns_rcode_servfail ||
13676 msg->rcode == dns_rcode_notimp ||
13677 msg->rcode == dns_rcode_formerr))
13678 {
13679 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13680 "refresh: rcode (%.*s) retrying without "
13681 "EDNS master %s (source %s)",
13682 (int)rb.used, rcode, master, source);
13683 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13684 goto same_master;
13685 }
13686 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
13687 msg->rcode == dns_rcode_badvers) {
13688 dns_zone_log(zone, ISC_LOG_DEBUG(1),
13689 "refresh: rcode (%.*s) retrying without "
13690 "EDNS EXPIRE OPTION master %s (source %s)",
13691 (int)rb.used, rcode, master, source);
13692 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13693 goto same_master;
13694 }
13695 dns_zone_log(zone, ISC_LOG_INFO,
13696 "refresh: unexpected rcode (%.*s) from "
13697 "master %s (source %s)",
13698 (int)rb.used, rcode, master, source);
13699 /*
13700 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
13701 */
13702 if (msg->rcode == dns_rcode_refused &&
13703 (zone->type == dns_zone_slave ||
13704 zone->type == dns_zone_mirror ||
13705 zone->type == dns_zone_redirect))
13706 {
13707 goto tcp_transfer;
13708 }
13709 goto next_master;
13710 }
13711
13712 /*
13713 * If truncated punt to zone transfer which will query again.
13714 */
13715 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
13716 if (zone->type == dns_zone_slave ||
13717 zone->type == dns_zone_mirror ||
13718 zone->type == dns_zone_redirect)
13719 {
13720 dns_zone_log(zone, ISC_LOG_INFO,
13721 "refresh: truncated UDP answer, "
13722 "initiating TCP zone xfer "
13723 "for master %s (source %s)",
13724 master, source);
13725 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
13726 goto tcp_transfer;
13727 } else {
13728 INSIST(zone->type == dns_zone_stub);
13729 if (dns_request_usedtcp(revent->request)) {
13730 dns_zone_log(zone, ISC_LOG_INFO,
13731 "refresh: truncated TCP response "
13732 "from master %s (source %s)",
13733 master, source);
13734 goto next_master;
13735 }
13736 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
13737 goto same_master;
13738 }
13739 }
13740
13741 /*
13742 * if non-auth log and next master;
13743 */
13744 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
13745 dns_zone_log(zone, ISC_LOG_INFO,
13746 "refresh: non-authoritative answer from "
13747 "master %s (source %s)",
13748 master, source);
13749 goto next_master;
13750 }
13751
13752 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
13753 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
13754 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
13755 soacount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_soa);
13756
13757 /*
13758 * There should not be a CNAME record at top of zone.
13759 */
13760 if (cnamecnt != 0) {
13761 dns_zone_log(zone, ISC_LOG_INFO,
13762 "refresh: CNAME at top of zone "
13763 "in master %s (source %s)",
13764 master, source);
13765 goto next_master;
13766 }
13767
13768 /*
13769 * if referral log and next master;
13770 */
13771 if (soacnt == 0 && soacount == 0 && nscount != 0) {
13772 dns_zone_log(zone, ISC_LOG_INFO,
13773 "refresh: referral response "
13774 "from master %s (source %s)",
13775 master, source);
13776 goto next_master;
13777 }
13778
13779 /*
13780 * if nodata log and next master;
13781 */
13782 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
13783 dns_zone_log(zone, ISC_LOG_INFO,
13784 "refresh: NODATA response "
13785 "from master %s (source %s)",
13786 master, source);
13787 goto next_master;
13788 }
13789
13790 /*
13791 * Only one soa at top of zone.
13792 */
13793 if (soacnt != 1) {
13794 dns_zone_log(zone, ISC_LOG_INFO,
13795 "refresh: answer SOA count (%d) != 1 "
13796 "from master %s (source %s)",
13797 soacnt, master, source);
13798 goto next_master;
13799 }
13800
13801 /*
13802 * Extract serial
13803 */
13804 rdataset = NULL;
13805 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
13806 dns_rdatatype_soa, dns_rdatatype_none,
13807 NULL, &rdataset);
13808 if (result != ISC_R_SUCCESS) {
13809 dns_zone_log(zone, ISC_LOG_INFO,
13810 "refresh: unable to get SOA record "
13811 "from master %s (source %s)",
13812 master, source);
13813 goto next_master;
13814 }
13815
13816 result = dns_rdataset_first(rdataset);
13817 if (result != ISC_R_SUCCESS) {
13818 dns_zone_log(zone, ISC_LOG_INFO,
13819 "refresh: dns_rdataset_first() failed");
13820 goto next_master;
13821 }
13822
13823 dns_rdataset_current(rdataset, &rdata);
13824 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13825 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13826
13827 serial = soa.serial;
13828 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
13829 unsigned int dbsoacount;
13830 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
13831 &oldserial, NULL, NULL, NULL, NULL,
13832 NULL);
13833 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13834 RUNTIME_CHECK(dbsoacount > 0U);
13835 zone_debuglog(zone, me, 1, "serial: new %u, old %u", serial,
13836 oldserial);
13837 } else {
13838 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
13839 serial);
13840 }
13841
13842 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
13843 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
13844 isc_serial_gt(serial, oldserial))
13845 {
13846 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
13847 &zone->sourceaddr, &now))
13848 {
13849 dns_zone_log(zone, ISC_LOG_INFO,
13850 "refresh: skipping %s as master %s "
13851 "(source %s) is unreachable (cached)",
13852 (zone->type == dns_zone_slave ||
13853 zone->type == dns_zone_mirror ||
13854 zone->type == dns_zone_redirect)
13855 ? "zone transfer"
13856 : "NS query",
13857 master, source);
13858 goto next_master;
13859 }
13860 tcp_transfer:
13861 isc_event_free(&event);
13862 dns_request_destroy(&zone->request);
13863 if (zone->type == dns_zone_slave ||
13864 zone->type == dns_zone_mirror ||
13865 zone->type == dns_zone_redirect)
13866 {
13867 do_queue_xfrin = true;
13868 } else {
13869 INSIST(zone->type == dns_zone_stub);
13870 ns_query(zone, rdataset, NULL);
13871 }
13872 if (msg != NULL) {
13873 dns_message_detach(&msg);
13874 }
13875 } else if (isc_serial_eq(soa.serial, oldserial)) {
13876 isc_time_t expiretime;
13877 uint32_t expire;
13878
13879 /*
13880 * Compute the new expire time based on this response.
13881 */
13882 expire = zone->expire;
13883 get_edns_expire(zone, msg, &expire);
13884 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
13885
13886 /*
13887 * Has the expire time improved?
13888 */
13889 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
13890 zone->expiretime = expiretime;
13891 if (zone->masterfile != NULL) {
13892 setmodtime(zone, &expiretime);
13893 }
13894 }
13895
13896 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
13897 zone->mastersok[zone->curmaster] = true;
13898 goto next_master;
13899 } else {
13900 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER)) {
13901 dns_zone_log(zone, ISC_LOG_INFO,
13902 "serial number (%u) "
13903 "received from master %s < ours (%u)",
13904 soa.serial, master, oldserial);
13905 } else {
13906 zone_debuglog(zone, me, 1, "ahead");
13907 }
13908 zone->mastersok[zone->curmaster] = true;
13909 goto next_master;
13910 }
13911 if (msg != NULL) {
13912 dns_message_detach(&msg);
13913 }
13914 goto detach;
13915
13916 next_master:
13917 if (msg != NULL) {
13918 dns_message_detach(&msg);
13919 }
13920 isc_event_free(&event);
13921 dns_request_destroy(&zone->request);
13922 /*
13923 * Skip to next failed / untried master.
13924 */
13925 do {
13926 zone->curmaster++;
13927 } while (zone->curmaster < zone->masterscnt &&
13928 zone->mastersok[zone->curmaster]);
13929 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
13930 if (zone->curmaster >= zone->masterscnt) {
13931 bool done = true;
13932 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
13933 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
13934 {
13935 /*
13936 * Did we get a good answer from all the primaries?
13937 */
13938 for (j = 0; j < zone->masterscnt; j++) {
13939 if (!zone->mastersok[j]) {
13940 {
13941 done = false;
13942 break;
13943 }
13944 }
13945 }
13946 } else {
13947 done = true;
13948 }
13949 if (!done) {
13950 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13951 zone->curmaster = 0;
13952 /*
13953 * Find the next failed master.
13954 */
13955 while (zone->curmaster < zone->masterscnt &&
13956 zone->mastersok[zone->curmaster]) {
13957 zone->curmaster++;
13958 }
13959 goto requeue;
13960 }
13961 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13962 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
13963 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13964 zone->refreshtime = now;
13965 }
13966 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
13967 zone_settimer(zone, &now);
13968 goto detach;
13969 }
13970
13971 requeue:
13972 queue_soa_query(zone);
13973 goto detach;
13974
13975 same_master:
13976 if (msg != NULL) {
13977 dns_message_detach(&msg);
13978 }
13979 isc_event_free(&event);
13980 dns_request_destroy(&zone->request);
13981 queue_soa_query(zone);
13982
13983 detach:
13984 UNLOCK_ZONE(zone);
13985 if (do_queue_xfrin) {
13986 queue_xfrin(zone);
13987 }
13988 dns_zone_idetach(&zone);
13989 return;
13990 }
13991
13992 static void
13993 queue_soa_query(dns_zone_t *zone) {
13994 const char me[] = "queue_soa_query";
13995 isc_event_t *e;
13996 dns_zone_t *dummy = NULL;
13997 isc_result_t result;
13998
13999 ENTER;
14000 /*
14001 * Locked by caller
14002 */
14003 REQUIRE(LOCKED_ZONE(zone));
14004
14005 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14006 cancel_refresh(zone);
14007 return;
14008 }
14009
14010 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE, soa_query,
14011 zone, sizeof(isc_event_t));
14012
14013 /*
14014 * Attach so that we won't clean up
14015 * until the event is delivered.
14016 */
14017 zone_iattach(zone, &dummy);
14018
14019 e->ev_arg = zone;
14020 e->ev_sender = NULL;
14021 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
14022 if (result != ISC_R_SUCCESS) {
14023 zone_idetach(&dummy);
14024 isc_event_free(&e);
14025 cancel_refresh(zone);
14026 }
14027 }
14028
14029 static void
14030 soa_query(isc_task_t *task, isc_event_t *event) {
14031 const char me[] = "soa_query";
14032 isc_result_t result = ISC_R_FAILURE;
14033 dns_message_t *message = NULL;
14034 dns_zone_t *zone = event->ev_arg;
14035 dns_zone_t *dummy = NULL;
14036 isc_netaddr_t masterip;
14037 dns_tsigkey_t *key = NULL;
14038 uint32_t options;
14039 bool cancel = true;
14040 int timeout;
14041 bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
14042 uint16_t udpsize = SEND_BUFFER_SIZE;
14043 isc_dscp_t dscp = -1;
14044
14045 REQUIRE(DNS_ZONE_VALID(zone));
14046
14047 UNUSED(task);
14048
14049 ENTER;
14050
14051 LOCK_ZONE(zone);
14052 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
14053 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
14054 zone->view->requestmgr == NULL)
14055 {
14056 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14057 cancel = false;
14058 }
14059 goto cleanup;
14060 }
14061
14062 again:
14063 result = create_query(zone, dns_rdatatype_soa, &zone->origin, &message);
14064 if (result != ISC_R_SUCCESS) {
14065 goto cleanup;
14066 }
14067
14068 INSIST(zone->masterscnt > 0);
14069 INSIST(zone->curmaster < zone->masterscnt);
14070
14071 zone->masteraddr = zone->masters[zone->curmaster];
14072
14073 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14074 /*
14075 * First, look for a tsig key in the master statement, then
14076 * try for a server key.
14077 */
14078 if ((zone->masterkeynames != NULL) &&
14079 (zone->masterkeynames[zone->curmaster] != NULL))
14080 {
14081 dns_view_t *view = dns_zone_getview(zone);
14082 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14083 result = dns_view_gettsig(view, keyname, &key);
14084 if (result != ISC_R_SUCCESS) {
14085 char namebuf[DNS_NAME_FORMATSIZE];
14086 dns_name_format(keyname, namebuf, sizeof(namebuf));
14087 dns_zone_log(zone, ISC_LOG_ERROR,
14088 "unable to find key: %s", namebuf);
14089 goto skip_master;
14090 }
14091 }
14092 if (key == NULL) {
14093 result = dns_view_getpeertsig(zone->view, &masterip, &key);
14094 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14095 char addrbuf[ISC_NETADDR_FORMATSIZE];
14096 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
14097 dns_zone_log(zone, ISC_LOG_ERROR,
14098 "unable to find TSIG key for %s", addrbuf);
14099 goto skip_master;
14100 }
14101 }
14102
14103 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ? DNS_REQUESTOPT_TCP
14104 : 0;
14105 have_xfrsource = have_xfrdscp = false;
14106 reqnsid = zone->view->requestnsid;
14107 reqexpire = zone->requestexpire;
14108 if (zone->view->peers != NULL) {
14109 dns_peer_t *peer = NULL;
14110 bool edns, usetcp;
14111 result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14112 &peer);
14113 if (result == ISC_R_SUCCESS) {
14114 result = dns_peer_getsupportedns(peer, &edns);
14115 if (result == ISC_R_SUCCESS && !edns) {
14116 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14117 }
14118 result = dns_peer_gettransfersource(peer,
14119 &zone->sourceaddr);
14120 if (result == ISC_R_SUCCESS) {
14121 have_xfrsource = true;
14122 }
14123 (void)dns_peer_gettransferdscp(peer, &dscp);
14124 if (dscp != -1) {
14125 have_xfrdscp = true;
14126 }
14127 if (zone->view->resolver != NULL) {
14128 udpsize = dns_resolver_getudpsize(
14129 zone->view->resolver);
14130 }
14131 (void)dns_peer_getudpsize(peer, &udpsize);
14132 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14133 (void)dns_peer_getrequestexpire(peer, &reqexpire);
14134 result = dns_peer_getforcetcp(peer, &usetcp);
14135 if (result == ISC_R_SUCCESS && usetcp) {
14136 options |= DNS_REQUESTOPT_TCP;
14137 }
14138 }
14139 }
14140
14141 switch (isc_sockaddr_pf(&zone->masteraddr)) {
14142 case PF_INET:
14143 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14144 if (isc_sockaddr_equal(&zone->altxfrsource4,
14145 &zone->xfrsource4)) {
14146 goto skip_master;
14147 }
14148 zone->sourceaddr = zone->altxfrsource4;
14149 if (!have_xfrdscp) {
14150 dscp = zone->altxfrsource4dscp;
14151 }
14152 } else if (!have_xfrsource) {
14153 zone->sourceaddr = zone->xfrsource4;
14154 if (!have_xfrdscp) {
14155 dscp = zone->xfrsource4dscp;
14156 }
14157 }
14158 break;
14159 case PF_INET6:
14160 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14161 if (isc_sockaddr_equal(&zone->altxfrsource6,
14162 &zone->xfrsource6)) {
14163 goto skip_master;
14164 }
14165 zone->sourceaddr = zone->altxfrsource6;
14166 if (!have_xfrdscp) {
14167 dscp = zone->altxfrsource6dscp;
14168 }
14169 } else if (!have_xfrsource) {
14170 zone->sourceaddr = zone->xfrsource6;
14171 if (!have_xfrdscp) {
14172 dscp = zone->xfrsource6dscp;
14173 }
14174 }
14175 break;
14176 default:
14177 result = ISC_R_NOTIMPLEMENTED;
14178 goto cleanup;
14179 }
14180
14181 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14182 result = add_opt(message, udpsize, reqnsid, reqexpire);
14183 if (result != ISC_R_SUCCESS) {
14184 zone_debuglog(zone, me, 1,
14185 "unable to add opt record: %s",
14186 dns_result_totext(result));
14187 }
14188 }
14189
14190 zone_iattach(zone, &dummy);
14191 timeout = 15;
14192 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14193 timeout = 30;
14194 }
14195 result = dns_request_createvia(
14196 zone->view->requestmgr, message, &zone->sourceaddr,
14197 &zone->masteraddr, dscp, options, key, timeout * 3, timeout, 0,
14198 zone->task, refresh_callback, zone, &zone->request);
14199 if (result != ISC_R_SUCCESS) {
14200 zone_idetach(&dummy);
14201 zone_debuglog(zone, me, 1,
14202 "dns_request_createvia4() failed: %s",
14203 dns_result_totext(result));
14204 goto skip_master;
14205 } else {
14206 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET) {
14207 inc_stats(zone, dns_zonestatscounter_soaoutv4);
14208 } else {
14209 inc_stats(zone, dns_zonestatscounter_soaoutv6);
14210 }
14211 }
14212 cancel = false;
14213
14214 cleanup:
14215 if (key != NULL) {
14216 dns_tsigkey_detach(&key);
14217 }
14218 if (result != ISC_R_SUCCESS) {
14219 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14220 }
14221 if (message != NULL) {
14222 dns_message_detach(&message);
14223 }
14224 if (cancel) {
14225 cancel_refresh(zone);
14226 }
14227 isc_event_free(&event);
14228 UNLOCK_ZONE(zone);
14229 dns_zone_idetach(&zone);
14230 return;
14231
14232 skip_master:
14233 if (key != NULL) {
14234 dns_tsigkey_detach(&key);
14235 }
14236 dns_message_detach(&message);
14237 /*
14238 * Skip to next failed / untried master.
14239 */
14240 do {
14241 zone->curmaster++;
14242 } while (zone->curmaster < zone->masterscnt &&
14243 zone->mastersok[zone->curmaster]);
14244 if (zone->curmaster < zone->masterscnt) {
14245 goto again;
14246 }
14247 zone->curmaster = 0;
14248 goto cleanup;
14249 }
14250
14251 static void
14252 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
14253 const char me[] = "ns_query";
14254 isc_result_t result;
14255 dns_message_t *message = NULL;
14256 isc_netaddr_t masterip;
14257 dns_tsigkey_t *key = NULL;
14258 dns_dbnode_t *node = NULL;
14259 int timeout;
14260 bool have_xfrsource = false, have_xfrdscp = false;
14261 bool reqnsid;
14262 uint16_t udpsize = SEND_BUFFER_SIZE;
14263 isc_dscp_t dscp = -1;
14264 struct stub_cb_args *cb_args;
14265
14266 REQUIRE(DNS_ZONE_VALID(zone));
14267 REQUIRE(LOCKED_ZONE(zone));
14268 REQUIRE((soardataset != NULL && stub == NULL) ||
14269 (soardataset == NULL && stub != NULL));
14270 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
14271
14272 ENTER;
14273
14274 if (stub == NULL) {
14275 stub = isc_mem_get(zone->mctx, sizeof(*stub));
14276 stub->magic = STUB_MAGIC;
14277 stub->mctx = zone->mctx;
14278 stub->zone = NULL;
14279 stub->db = NULL;
14280 stub->version = NULL;
14281 atomic_init(&stub->pending_requests, 0);
14282
14283 /*
14284 * Attach so that the zone won't disappear from under us.
14285 */
14286 zone_iattach(zone, &stub->zone);
14287
14288 /*
14289 * If a db exists we will update it, otherwise we create a
14290 * new one and attach it to the zone once we have the NS
14291 * RRset and glue.
14292 */
14293 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14294 if (zone->db != NULL) {
14295 dns_db_attach(zone->db, &stub->db);
14296 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14297 } else {
14298 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14299
14300 INSIST(zone->db_argc >= 1);
14301 result = dns_db_create(zone->mctx, zone->db_argv[0],
14302 &zone->origin, dns_dbtype_stub,
14303 zone->rdclass, zone->db_argc - 1,
14304 zone->db_argv + 1, &stub->db);
14305 if (result != ISC_R_SUCCESS) {
14306 dns_zone_log(zone, ISC_LOG_ERROR,
14307 "refreshing stub: "
14308 "could not create "
14309 "database: %s",
14310 dns_result_totext(result));
14311 goto cleanup;
14312 }
14313 dns_db_settask(stub->db, zone->task);
14314 }
14315
14316 result = dns_db_newversion(stub->db, &stub->version);
14317 if (result != ISC_R_SUCCESS) {
14318 dns_zone_log(zone, ISC_LOG_INFO,
14319 "refreshing stub: "
14320 "dns_db_newversion() failed: %s",
14321 dns_result_totext(result));
14322 goto cleanup;
14323 }
14324
14325 /*
14326 * Update SOA record.
14327 */
14328 result = dns_db_findnode(stub->db, &zone->origin, true, &node);
14329 if (result != ISC_R_SUCCESS) {
14330 dns_zone_log(zone, ISC_LOG_INFO,
14331 "refreshing stub: "
14332 "dns_db_findnode() failed: %s",
14333 dns_result_totext(result));
14334 goto cleanup;
14335 }
14336
14337 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
14338 soardataset, 0, NULL);
14339 dns_db_detachnode(stub->db, &node);
14340 if (result != ISC_R_SUCCESS) {
14341 dns_zone_log(zone, ISC_LOG_INFO,
14342 "refreshing stub: "
14343 "dns_db_addrdataset() failed: %s",
14344 dns_result_totext(result));
14345 goto cleanup;
14346 }
14347 }
14348
14349 /*
14350 * XXX Optimisation: Create message when zone is setup and reuse.
14351 */
14352 result = create_query(zone, dns_rdatatype_ns, &zone->origin, &message);
14353 INSIST(result == ISC_R_SUCCESS);
14354
14355 INSIST(zone->masterscnt > 0);
14356 INSIST(zone->curmaster < zone->masterscnt);
14357 zone->masteraddr = zone->masters[zone->curmaster];
14358
14359 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
14360 /*
14361 * First, look for a tsig key in the master statement, then
14362 * try for a server key.
14363 */
14364 if ((zone->masterkeynames != NULL) &&
14365 (zone->masterkeynames[zone->curmaster] != NULL))
14366 {
14367 dns_view_t *view = dns_zone_getview(zone);
14368 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
14369 result = dns_view_gettsig(view, keyname, &key);
14370 if (result != ISC_R_SUCCESS) {
14371 char namebuf[DNS_NAME_FORMATSIZE];
14372 dns_name_format(keyname, namebuf, sizeof(namebuf));
14373 dns_zone_log(zone, ISC_LOG_ERROR,
14374 "unable to find key: %s", namebuf);
14375 }
14376 }
14377 if (key == NULL) {
14378 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
14379 }
14380
14381 reqnsid = zone->view->requestnsid;
14382 if (zone->view->peers != NULL) {
14383 dns_peer_t *peer = NULL;
14384 bool edns;
14385 result = dns_peerlist_peerbyaddr(zone->view->peers, &masterip,
14386 &peer);
14387 if (result == ISC_R_SUCCESS) {
14388 result = dns_peer_getsupportedns(peer, &edns);
14389 if (result == ISC_R_SUCCESS && !edns) {
14390 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
14391 }
14392 result = dns_peer_gettransfersource(peer,
14393 &zone->sourceaddr);
14394 if (result == ISC_R_SUCCESS) {
14395 have_xfrsource = true;
14396 }
14397 result = dns_peer_gettransferdscp(peer, &dscp);
14398 if (result == ISC_R_SUCCESS && dscp != -1) {
14399 have_xfrdscp = true;
14400 }
14401 if (zone->view->resolver != NULL) {
14402 udpsize = dns_resolver_getudpsize(
14403 zone->view->resolver);
14404 }
14405 (void)dns_peer_getudpsize(peer, &udpsize);
14406 (void)dns_peer_getrequestnsid(peer, &reqnsid);
14407 }
14408 }
14409 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
14410 result = add_opt(message, udpsize, reqnsid, false);
14411 if (result != ISC_R_SUCCESS) {
14412 zone_debuglog(zone, me, 1,
14413 "unable to add opt record: %s",
14414 dns_result_totext(result));
14415 }
14416 }
14417
14418 /*
14419 * Always use TCP so that we shouldn't truncate in additional section.
14420 */
14421 switch (isc_sockaddr_pf(&zone->masteraddr)) {
14422 case PF_INET:
14423 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14424 zone->sourceaddr = zone->altxfrsource4;
14425 if (!have_xfrdscp) {
14426 dscp = zone->altxfrsource4dscp;
14427 }
14428 } else if (!have_xfrsource) {
14429 zone->sourceaddr = zone->xfrsource4;
14430 if (!have_xfrdscp) {
14431 dscp = zone->xfrsource4dscp;
14432 }
14433 }
14434 break;
14435 case PF_INET6:
14436 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
14437 zone->sourceaddr = zone->altxfrsource6;
14438 if (!have_xfrdscp) {
14439 dscp = zone->altxfrsource6dscp;
14440 }
14441 } else if (!have_xfrsource) {
14442 zone->sourceaddr = zone->xfrsource6;
14443 if (!have_xfrdscp) {
14444 dscp = zone->xfrsource6dscp;
14445 }
14446 }
14447 break;
14448 default:
14449 result = ISC_R_NOTIMPLEMENTED;
14450 POST(result);
14451 goto cleanup;
14452 }
14453 timeout = 15;
14454 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH)) {
14455 timeout = 30;
14456 }
14457
14458 /* Save request parameters so we can reuse them later on
14459 for resolving missing glue A/AAAA records. */
14460 cb_args = isc_mem_get(zone->mctx, sizeof(*cb_args));
14461 cb_args->stub = stub;
14462 cb_args->tsig_key = key;
14463 cb_args->dscp = dscp;
14464 cb_args->udpsize = udpsize;
14465 cb_args->timeout = timeout;
14466 cb_args->reqnsid = reqnsid;
14467
14468 result = dns_request_createvia(
14469 zone->view->requestmgr, message, &zone->sourceaddr,
14470 &zone->masteraddr, dscp, DNS_REQUESTOPT_TCP, key, timeout * 3,
14471 timeout, 0, zone->task, stub_callback, cb_args, &zone->request);
14472 if (result != ISC_R_SUCCESS) {
14473 zone_debuglog(zone, me, 1, "dns_request_createvia() failed: %s",
14474 dns_result_totext(result));
14475 goto cleanup;
14476 }
14477 dns_message_detach(&message);
14478 goto unlock;
14479
14480 cleanup:
14481 cancel_refresh(zone);
14482 stub->magic = 0;
14483 if (stub->version != NULL) {
14484 dns_db_closeversion(stub->db, &stub->version, false);
14485 }
14486 if (stub->db != NULL) {
14487 dns_db_detach(&stub->db);
14488 }
14489 if (stub->zone != NULL) {
14490 zone_idetach(&stub->zone);
14491 }
14492 isc_mem_put(stub->mctx, stub, sizeof(*stub));
14493 if (message != NULL) {
14494 dns_message_detach(&message);
14495 }
14496 unlock:
14497 if (key != NULL) {
14498 dns_tsigkey_detach(&key);
14499 }
14500 return;
14501 }
14502
14503 /*
14504 * Handle the control event. Note that although this event causes the zone
14505 * to shut down, it is not a shutdown event in the sense of the task library.
14506 */
14507 static void
14508 zone_shutdown(isc_task_t *task, isc_event_t *event) {
14509 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14510 bool free_needed, linked = false;
14511 dns_zone_t *raw = NULL, *secure = NULL;
14512
14513 UNUSED(task);
14514 REQUIRE(DNS_ZONE_VALID(zone));
14515 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
14516 INSIST(isc_refcount_current(&zone->erefs) == 0);
14517
14518 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
14519
14520 /*
14521 * Stop things being restarted after we cancel them below.
14522 */
14523 LOCK_ZONE(zone);
14524 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
14525 UNLOCK_ZONE(zone);
14526
14527 /*
14528 * If we were waiting for xfrin quota, step out of
14529 * the queue.
14530 * If there's no zone manager, we can't be waiting for the
14531 * xfrin quota
14532 */
14533 if (zone->zmgr != NULL) {
14534 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14535 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
14536 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
14537 statelink);
14538 linked = true;
14539 zone->statelist = NULL;
14540 }
14541 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
14542 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
14543 statelink);
14544 zone->statelist = NULL;
14545 zmgr_resume_xfrs(zone->zmgr, false);
14546 }
14547 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
14548 }
14549
14550 /*
14551 * In task context, no locking required. See zone_xfrdone().
14552 */
14553 if (zone->xfr != NULL) {
14554 dns_xfrin_shutdown(zone->xfr);
14555 }
14556
14557 /* Safe to release the zone now */
14558 if (zone->zmgr != NULL) {
14559 dns_zonemgr_releasezone(zone->zmgr, zone);
14560 }
14561
14562 LOCK_ZONE(zone);
14563 INSIST(zone != zone->raw);
14564 if (linked) {
14565 isc_refcount_decrement(&zone->irefs);
14566 }
14567 if (zone->request != NULL) {
14568 dns_request_cancel(zone->request);
14569 }
14570
14571 if (zone->readio != NULL) {
14572 zonemgr_cancelio(zone->readio);
14573 }
14574
14575 if (zone->lctx != NULL) {
14576 dns_loadctx_cancel(zone->lctx);
14577 }
14578
14579 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
14580 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14581 {
14582 if (zone->writeio != NULL) {
14583 zonemgr_cancelio(zone->writeio);
14584 }
14585
14586 if (zone->dctx != NULL) {
14587 dns_dumpctx_cancel(zone->dctx);
14588 }
14589 }
14590
14591 notify_cancel(zone);
14592
14593 forward_cancel(zone);
14594
14595 if (zone->timer != NULL) {
14596 isc_timer_detach(&zone->timer);
14597 isc_refcount_decrement(&zone->irefs);
14598 }
14599
14600 /*
14601 * We have now canceled everything set the flag to allow exit_check()
14602 * to succeed. We must not unlock between setting this flag and
14603 * calling exit_check().
14604 */
14605 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
14606 free_needed = exit_check(zone);
14607 if (inline_secure(zone)) {
14608 raw = zone->raw;
14609 zone->raw = NULL;
14610 }
14611 if (inline_raw(zone)) {
14612 secure = zone->secure;
14613 zone->secure = NULL;
14614 }
14615 UNLOCK_ZONE(zone);
14616 if (raw != NULL) {
14617 dns_zone_detach(&raw);
14618 }
14619 if (secure != NULL) {
14620 dns_zone_idetach(&secure);
14621 }
14622 if (free_needed) {
14623 zone_free(zone);
14624 }
14625 }
14626
14627 static void
14628 zone_timer(isc_task_t *task, isc_event_t *event) {
14629 const char me[] = "zone_timer";
14630 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
14631
14632 UNUSED(task);
14633 REQUIRE(DNS_ZONE_VALID(zone));
14634
14635 ENTER;
14636
14637 zone_maintenance(zone);
14638
14639 isc_event_free(&event);
14640 }
14641
14642 static void
14643 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
14644 const char me[] = "zone_settimer";
14645 isc_time_t next;
14646 isc_result_t result;
14647
14648 REQUIRE(DNS_ZONE_VALID(zone));
14649 REQUIRE(LOCKED_ZONE(zone));
14650 ENTER;
14651
14652 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
14653 return;
14654 }
14655
14656 isc_time_settoepoch(&next);
14657
14658 switch (zone->type) {
14659 case dns_zone_redirect:
14660 if (zone->masters != NULL) {
14661 goto treat_as_slave;
14662 }
14663 /* FALLTHROUGH */
14664
14665 case dns_zone_master:
14666 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
14667 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
14668 {
14669 next = zone->notifytime;
14670 }
14671 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
14672 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14673 {
14674 INSIST(!isc_time_isepoch(&zone->dumptime));
14675 if (isc_time_isepoch(&next) ||
14676 isc_time_compare(&zone->dumptime, &next) < 0) {
14677 next = zone->dumptime;
14678 }
14679 }
14680 if (zone->type == dns_zone_redirect) {
14681 break;
14682 }
14683 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
14684 !isc_time_isepoch(&zone->refreshkeytime))
14685 {
14686 if (isc_time_isepoch(&next) ||
14687 isc_time_compare(&zone->refreshkeytime, &next) < 0)
14688 {
14689 next = zone->refreshkeytime;
14690 }
14691 }
14692 if (!isc_time_isepoch(&zone->resigntime)) {
14693 if (isc_time_isepoch(&next) ||
14694 isc_time_compare(&zone->resigntime, &next) < 0) {
14695 next = zone->resigntime;
14696 }
14697 }
14698 if (!isc_time_isepoch(&zone->keywarntime)) {
14699 if (isc_time_isepoch(&next) ||
14700 isc_time_compare(&zone->keywarntime, &next) < 0) {
14701 next = zone->keywarntime;
14702 }
14703 }
14704 if (!isc_time_isepoch(&zone->signingtime)) {
14705 if (isc_time_isepoch(&next) ||
14706 isc_time_compare(&zone->signingtime, &next) < 0) {
14707 next = zone->signingtime;
14708 }
14709 }
14710 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
14711 if (isc_time_isepoch(&next) ||
14712 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
14713 {
14714 next = zone->nsec3chaintime;
14715 }
14716 }
14717 break;
14718
14719 case dns_zone_slave:
14720 case dns_zone_mirror:
14721 treat_as_slave:
14722 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
14723 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
14724 {
14725 next = zone->notifytime;
14726 }
14727 /* FALLTHROUGH */
14728
14729 case dns_zone_stub:
14730 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
14731 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
14732 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
14733 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
14734 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
14735 !isc_time_isepoch(&zone->refreshtime) &&
14736 (isc_time_isepoch(&next) ||
14737 isc_time_compare(&zone->refreshtime, &next) < 0))
14738 {
14739 next = zone->refreshtime;
14740 }
14741 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
14742 !isc_time_isepoch(&zone->expiretime))
14743 {
14744 if (isc_time_isepoch(&next) ||
14745 isc_time_compare(&zone->expiretime, &next) < 0) {
14746 next = zone->expiretime;
14747 }
14748 }
14749 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
14750 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14751 {
14752 INSIST(!isc_time_isepoch(&zone->dumptime));
14753 if (isc_time_isepoch(&next) ||
14754 isc_time_compare(&zone->dumptime, &next) < 0) {
14755 next = zone->dumptime;
14756 }
14757 }
14758 break;
14759
14760 case dns_zone_key:
14761 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
14762 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING))
14763 {
14764 INSIST(!isc_time_isepoch(&zone->dumptime));
14765 if (isc_time_isepoch(&next) ||
14766 isc_time_compare(&zone->dumptime, &next) < 0) {
14767 next = zone->dumptime;
14768 }
14769 }
14770 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
14771 if (isc_time_isepoch(&next) ||
14772 (!isc_time_isepoch(&zone->refreshkeytime) &&
14773 isc_time_compare(&zone->refreshkeytime, &next) <
14774 0))
14775 {
14776 next = zone->refreshkeytime;
14777 }
14778 }
14779 break;
14780
14781 default:
14782 break;
14783 }
14784
14785 if (isc_time_isepoch(&next)) {
14786 zone_debuglog(zone, me, 10, "settimer inactive");
14787 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
14788 NULL, NULL, true);
14789 if (result != ISC_R_SUCCESS) {
14790 dns_zone_log(zone, ISC_LOG_ERROR,
14791 "could not deactivate zone timer: %s",
14792 isc_result_totext(result));
14793 }
14794 } else {
14795 if (isc_time_compare(&next, now) <= 0) {
14796 next = *now;
14797 }
14798 result = isc_timer_reset(zone->timer, isc_timertype_once, &next,
14799 NULL, true);
14800 if (result != ISC_R_SUCCESS) {
14801 dns_zone_log(zone, ISC_LOG_ERROR,
14802 "could not reset zone timer: %s",
14803 isc_result_totext(result));
14804 }
14805 }
14806 }
14807
14808 static void
14809 cancel_refresh(dns_zone_t *zone) {
14810 const char me[] = "cancel_refresh";
14811 isc_time_t now;
14812
14813 /*
14814 * 'zone' locked by caller.
14815 */
14816
14817 REQUIRE(DNS_ZONE_VALID(zone));
14818 REQUIRE(LOCKED_ZONE(zone));
14819
14820 ENTER;
14821
14822 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
14823 TIME_NOW(&now);
14824 zone_settimer(zone, &now);
14825 }
14826
14827 static isc_result_t
14828 notify_createmessage(dns_zone_t *zone, unsigned int flags,
14829 dns_message_t **messagep) {
14830 dns_db_t *zonedb = NULL;
14831 dns_dbnode_t *node = NULL;
14832 dns_dbversion_t *version = NULL;
14833 dns_message_t *message = NULL;
14834 dns_rdataset_t rdataset;
14835 dns_rdata_t rdata = DNS_RDATA_INIT;
14836
14837 dns_name_t *tempname = NULL;
14838 dns_rdata_t *temprdata = NULL;
14839 dns_rdatalist_t *temprdatalist = NULL;
14840 dns_rdataset_t *temprdataset = NULL;
14841
14842 isc_result_t result;
14843 isc_region_t r;
14844 isc_buffer_t *b = NULL;
14845
14846 REQUIRE(DNS_ZONE_VALID(zone));
14847 REQUIRE(messagep != NULL && *messagep == NULL);
14848
14849 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER, &message);
14850
14851 message->opcode = dns_opcode_notify;
14852 message->flags |= DNS_MESSAGEFLAG_AA;
14853 message->rdclass = zone->rdclass;
14854
14855 result = dns_message_gettempname(message, &tempname);
14856 if (result != ISC_R_SUCCESS) {
14857 goto cleanup;
14858 }
14859
14860 result = dns_message_gettemprdataset(message, &temprdataset);
14861 if (result != ISC_R_SUCCESS) {
14862 goto cleanup;
14863 }
14864
14865 /*
14866 * Make question.
14867 */
14868 dns_name_init(tempname, NULL);
14869 dns_name_clone(&zone->origin, tempname);
14870 dns_rdataset_makequestion(temprdataset, zone->rdclass,
14871 dns_rdatatype_soa);
14872 ISC_LIST_APPEND(tempname->list, temprdataset, link);
14873 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
14874 tempname = NULL;
14875 temprdataset = NULL;
14876
14877 if ((flags & DNS_NOTIFY_NOSOA) != 0) {
14878 goto done;
14879 }
14880
14881 result = dns_message_gettempname(message, &tempname);
14882 if (result != ISC_R_SUCCESS) {
14883 goto soa_cleanup;
14884 }
14885 result = dns_message_gettemprdata(message, &temprdata);
14886 if (result != ISC_R_SUCCESS) {
14887 goto soa_cleanup;
14888 }
14889 result = dns_message_gettemprdataset(message, &temprdataset);
14890 if (result != ISC_R_SUCCESS) {
14891 goto soa_cleanup;
14892 }
14893 result = dns_message_gettemprdatalist(message, &temprdatalist);
14894 if (result != ISC_R_SUCCESS) {
14895 goto soa_cleanup;
14896 }
14897
14898 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14899 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
14900 dns_db_attach(zone->db, &zonedb);
14901 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14902
14903 dns_name_init(tempname, NULL);
14904 dns_name_clone(&zone->origin, tempname);
14905 dns_db_currentversion(zonedb, &version);
14906 result = dns_db_findnode(zonedb, tempname, false, &node);
14907 if (result != ISC_R_SUCCESS) {
14908 goto soa_cleanup;
14909 }
14910
14911 dns_rdataset_init(&rdataset);
14912 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
14913 dns_rdatatype_none, 0, &rdataset, NULL);
14914 if (result != ISC_R_SUCCESS) {
14915 goto soa_cleanup;
14916 }
14917 result = dns_rdataset_first(&rdataset);
14918 if (result != ISC_R_SUCCESS) {
14919 goto soa_cleanup;
14920 }
14921 dns_rdataset_current(&rdataset, &rdata);
14922 dns_rdata_toregion(&rdata, &r);
14923 isc_buffer_allocate(zone->mctx, &b, r.length);
14924 isc_buffer_putmem(b, r.base, r.length);
14925 isc_buffer_usedregion(b, &r);
14926 dns_rdata_init(temprdata);
14927 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
14928 dns_message_takebuffer(message, &b);
14929 result = dns_rdataset_next(&rdataset);
14930 dns_rdataset_disassociate(&rdataset);
14931 if (result != ISC_R_NOMORE) {
14932 goto soa_cleanup;
14933 }
14934 temprdatalist->rdclass = rdata.rdclass;
14935 temprdatalist->type = rdata.type;
14936 temprdatalist->ttl = rdataset.ttl;
14937 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
14938
14939 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
14940 if (result != ISC_R_SUCCESS) {
14941 goto soa_cleanup;
14942 }
14943
14944 ISC_LIST_APPEND(tempname->list, temprdataset, link);
14945 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
14946 temprdatalist = NULL;
14947 temprdataset = NULL;
14948 temprdata = NULL;
14949 tempname = NULL;
14950
14951 soa_cleanup:
14952 if (node != NULL) {
14953 dns_db_detachnode(zonedb, &node);
14954 }
14955 if (version != NULL) {
14956 dns_db_closeversion(zonedb, &version, false);
14957 }
14958 if (zonedb != NULL) {
14959 dns_db_detach(&zonedb);
14960 }
14961 if (tempname != NULL) {
14962 dns_message_puttempname(message, &tempname);
14963 }
14964 if (temprdata != NULL) {
14965 dns_message_puttemprdata(message, &temprdata);
14966 }
14967 if (temprdataset != NULL) {
14968 dns_message_puttemprdataset(message, &temprdataset);
14969 }
14970 if (temprdatalist != NULL) {
14971 dns_message_puttemprdatalist(message, &temprdatalist);
14972 }
14973
14974 done:
14975 *messagep = message;
14976 return (ISC_R_SUCCESS);
14977
14978 cleanup:
14979 if (tempname != NULL) {
14980 dns_message_puttempname(message, &tempname);
14981 }
14982 if (temprdataset != NULL) {
14983 dns_message_puttemprdataset(message, &temprdataset);
14984 }
14985 dns_message_detach(&message);
14986 return (result);
14987 }
14988
14989 isc_result_t
14990 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
14991 isc_sockaddr_t *to, dns_message_t *msg) {
14992 unsigned int i;
14993 dns_rdata_soa_t soa;
14994 dns_rdataset_t *rdataset = NULL;
14995 dns_rdata_t rdata = DNS_RDATA_INIT;
14996 isc_result_t result;
14997 char fromtext[ISC_SOCKADDR_FORMATSIZE];
14998 int match = 0;
14999 isc_netaddr_t netaddr;
15000 uint32_t serial = 0;
15001 bool have_serial = false;
15002 dns_tsigkey_t *tsigkey;
15003 const dns_name_t *tsig;
15004
15005 REQUIRE(DNS_ZONE_VALID(zone));
15006
15007 /*
15008 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
15009 * ROLLOVER.
15010 *
15011 * SOA: RFC1996
15012 * Check that 'from' is a valid notify source, (zone->masters).
15013 * Return DNS_R_REFUSED if not.
15014 *
15015 * If the notify message contains a serial number check it
15016 * against the zones serial and return if <= current serial
15017 *
15018 * If a refresh check is progress, if so just record the
15019 * fact we received a NOTIFY and from where and return.
15020 * We will perform a new refresh check when the current one
15021 * completes. Return ISC_R_SUCCESS.
15022 *
15023 * Otherwise initiate a refresh check using 'from' as the
15024 * first address to check. Return ISC_R_SUCCESS.
15025 */
15026
15027 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
15028
15029 /*
15030 * Notify messages are processed by the raw zone.
15031 */
15032 LOCK_ZONE(zone);
15033 INSIST(zone != zone->raw);
15034 if (inline_secure(zone)) {
15035 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
15036 UNLOCK_ZONE(zone);
15037 return (result);
15038 }
15039 /*
15040 * We only handle NOTIFY (SOA) at the present.
15041 */
15042 if (isc_sockaddr_pf(from) == PF_INET) {
15043 inc_stats(zone, dns_zonestatscounter_notifyinv4);
15044 } else {
15045 inc_stats(zone, dns_zonestatscounter_notifyinv6);
15046 }
15047 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
15048 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
15049 dns_rdatatype_soa, dns_rdatatype_none, NULL,
15050 NULL) != ISC_R_SUCCESS)
15051 {
15052 UNLOCK_ZONE(zone);
15053 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
15054 dns_zone_log(zone, ISC_LOG_NOTICE,
15055 "NOTIFY with no "
15056 "question section from: %s",
15057 fromtext);
15058 return (DNS_R_FORMERR);
15059 }
15060 dns_zone_log(zone, ISC_LOG_NOTICE,
15061 "NOTIFY zone does not match");
15062 return (DNS_R_NOTIMP);
15063 }
15064
15065 /*
15066 * If we are a master zone just succeed.
15067 */
15068 if (zone->type == dns_zone_master) {
15069 UNLOCK_ZONE(zone);
15070 return (ISC_R_SUCCESS);
15071 }
15072
15073 isc_netaddr_fromsockaddr(&netaddr, from);
15074 for (i = 0; i < zone->masterscnt; i++) {
15075 if (isc_sockaddr_eqaddr(from, &zone->masters[i])) {
15076 break;
15077 }
15078 if (zone->view->aclenv.match_mapped &&
15079 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
15080 isc_sockaddr_pf(&zone->masters[i]) == AF_INET)
15081 {
15082 isc_netaddr_t na1, na2;
15083 isc_netaddr_fromv4mapped(&na1, &netaddr);
15084 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
15085 if (isc_netaddr_equal(&na1, &na2)) {
15086 break;
15087 }
15088 }
15089 }
15090
15091 /*
15092 * Accept notify requests from non masters if they are on
15093 * 'zone->notify_acl'.
15094 */
15095 tsigkey = dns_message_gettsigkey(msg);
15096 tsig = dns_tsigkey_identity(tsigkey);
15097 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
15098 (dns_acl_match(&netaddr, tsig, zone->notify_acl,
15099 &zone->view->aclenv, &match,
15100 NULL) == ISC_R_SUCCESS) &&
15101 match > 0)
15102 {
15103 /* Accept notify. */
15104 } else if (i >= zone->masterscnt) {
15105 UNLOCK_ZONE(zone);
15106 dns_zone_log(zone, ISC_LOG_INFO,
15107 "refused notify from non-master: %s", fromtext);
15108 inc_stats(zone, dns_zonestatscounter_notifyrej);
15109 return (DNS_R_REFUSED);
15110 }
15111
15112 /*
15113 * If the zone is loaded and there are answers check the serial
15114 * to see if we need to do a refresh. Do not worry about this
15115 * check if we are a dialup zone as we use the notify request
15116 * to trigger a refresh check.
15117 */
15118 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
15119 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
15120 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH))
15121 {
15122 result = dns_message_findname(
15123 msg, DNS_SECTION_ANSWER, &zone->origin,
15124 dns_rdatatype_soa, dns_rdatatype_none, NULL, &rdataset);
15125 if (result == ISC_R_SUCCESS) {
15126 result = dns_rdataset_first(rdataset);
15127 }
15128 if (result == ISC_R_SUCCESS) {
15129 uint32_t oldserial;
15130 unsigned int soacount;
15131
15132 dns_rdataset_current(rdataset, &rdata);
15133 result = dns_rdata_tostruct(&rdata, &soa, NULL);
15134 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15135 serial = soa.serial;
15136 have_serial = true;
15137 /*
15138 * The following should safely be performed without DB
15139 * lock and succeed in this context.
15140 */
15141 result = zone_get_from_db(zone, zone->db, NULL,
15142 &soacount, &oldserial, NULL,
15143 NULL, NULL, NULL, NULL);
15144 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15145 RUNTIME_CHECK(soacount > 0U);
15146 if (isc_serial_le(serial, oldserial)) {
15147 dns_zone_log(zone, ISC_LOG_INFO,
15148 "notify from %s: "
15149 "zone is up to date",
15150 fromtext);
15151 UNLOCK_ZONE(zone);
15152 return (ISC_R_SUCCESS);
15153 }
15154 }
15155 }
15156
15157 /*
15158 * If we got this far and there was a refresh in progress just
15159 * let it complete. Record where we got the notify from so we
15160 * can perform a refresh check when the current one completes
15161 */
15162 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
15163 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15164 zone->notifyfrom = *from;
15165 UNLOCK_ZONE(zone);
15166 if (have_serial) {
15167 dns_zone_log(zone, ISC_LOG_INFO,
15168 "notify from %s: serial %u: refresh in "
15169 "progress, refresh check queued",
15170 fromtext, serial);
15171 } else {
15172 dns_zone_log(zone, ISC_LOG_INFO,
15173 "notify from %s: refresh in progress, "
15174 "refresh check queued",
15175 fromtext);
15176 }
15177 return (ISC_R_SUCCESS);
15178 }
15179 if (have_serial) {
15180 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
15181 fromtext, serial);
15182 } else {
15183 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
15184 fromtext);
15185 }
15186 zone->notifyfrom = *from;
15187 UNLOCK_ZONE(zone);
15188
15189 if (to != NULL) {
15190 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
15191 }
15192 dns_zone_refresh(zone);
15193 return (ISC_R_SUCCESS);
15194 }
15195
15196 void
15197 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
15198 REQUIRE(DNS_ZONE_VALID(zone));
15199
15200 LOCK_ZONE(zone);
15201 if (zone->notify_acl != NULL) {
15202 dns_acl_detach(&zone->notify_acl);
15203 }
15204 dns_acl_attach(acl, &zone->notify_acl);
15205 UNLOCK_ZONE(zone);
15206 }
15207
15208 void
15209 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
15210 REQUIRE(DNS_ZONE_VALID(zone));
15211
15212 LOCK_ZONE(zone);
15213 if (zone->query_acl != NULL) {
15214 dns_acl_detach(&zone->query_acl);
15215 }
15216 dns_acl_attach(acl, &zone->query_acl);
15217 UNLOCK_ZONE(zone);
15218 }
15219
15220 void
15221 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
15222 REQUIRE(DNS_ZONE_VALID(zone));
15223
15224 LOCK_ZONE(zone);
15225 if (zone->queryon_acl != NULL) {
15226 dns_acl_detach(&zone->queryon_acl);
15227 }
15228 dns_acl_attach(acl, &zone->queryon_acl);
15229 UNLOCK_ZONE(zone);
15230 }
15231
15232 void
15233 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
15234 REQUIRE(DNS_ZONE_VALID(zone));
15235
15236 LOCK_ZONE(zone);
15237 if (zone->update_acl != NULL) {
15238 dns_acl_detach(&zone->update_acl);
15239 }
15240 dns_acl_attach(acl, &zone->update_acl);
15241 UNLOCK_ZONE(zone);
15242 }
15243
15244 void
15245 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
15246 REQUIRE(DNS_ZONE_VALID(zone));
15247
15248 LOCK_ZONE(zone);
15249 if (zone->forward_acl != NULL) {
15250 dns_acl_detach(&zone->forward_acl);
15251 }
15252 dns_acl_attach(acl, &zone->forward_acl);
15253 UNLOCK_ZONE(zone);
15254 }
15255
15256 void
15257 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
15258 REQUIRE(DNS_ZONE_VALID(zone));
15259
15260 LOCK_ZONE(zone);
15261 if (zone->xfr_acl != NULL) {
15262 dns_acl_detach(&zone->xfr_acl);
15263 }
15264 dns_acl_attach(acl, &zone->xfr_acl);
15265 UNLOCK_ZONE(zone);
15266 }
15267
15268 dns_acl_t *
15269 dns_zone_getnotifyacl(dns_zone_t *zone) {
15270 REQUIRE(DNS_ZONE_VALID(zone));
15271
15272 return (zone->notify_acl);
15273 }
15274
15275 dns_acl_t *
15276 dns_zone_getqueryacl(dns_zone_t *zone) {
15277 REQUIRE(DNS_ZONE_VALID(zone));
15278
15279 return (zone->query_acl);
15280 }
15281
15282 dns_acl_t *
15283 dns_zone_getqueryonacl(dns_zone_t *zone) {
15284 REQUIRE(DNS_ZONE_VALID(zone));
15285
15286 return (zone->queryon_acl);
15287 }
15288
15289 dns_acl_t *
15290 dns_zone_getupdateacl(dns_zone_t *zone) {
15291 REQUIRE(DNS_ZONE_VALID(zone));
15292
15293 return (zone->update_acl);
15294 }
15295
15296 dns_acl_t *
15297 dns_zone_getforwardacl(dns_zone_t *zone) {
15298 REQUIRE(DNS_ZONE_VALID(zone));
15299
15300 return (zone->forward_acl);
15301 }
15302
15303 dns_acl_t *
15304 dns_zone_getxfracl(dns_zone_t *zone) {
15305 REQUIRE(DNS_ZONE_VALID(zone));
15306
15307 return (zone->xfr_acl);
15308 }
15309
15310 void
15311 dns_zone_clearupdateacl(dns_zone_t *zone) {
15312 REQUIRE(DNS_ZONE_VALID(zone));
15313
15314 LOCK_ZONE(zone);
15315 if (zone->update_acl != NULL) {
15316 dns_acl_detach(&zone->update_acl);
15317 }
15318 UNLOCK_ZONE(zone);
15319 }
15320
15321 void
15322 dns_zone_clearforwardacl(dns_zone_t *zone) {
15323 REQUIRE(DNS_ZONE_VALID(zone));
15324
15325 LOCK_ZONE(zone);
15326 if (zone->forward_acl != NULL) {
15327 dns_acl_detach(&zone->forward_acl);
15328 }
15329 UNLOCK_ZONE(zone);
15330 }
15331
15332 void
15333 dns_zone_clearnotifyacl(dns_zone_t *zone) {
15334 REQUIRE(DNS_ZONE_VALID(zone));
15335
15336 LOCK_ZONE(zone);
15337 if (zone->notify_acl != NULL) {
15338 dns_acl_detach(&zone->notify_acl);
15339 }
15340 UNLOCK_ZONE(zone);
15341 }
15342
15343 void
15344 dns_zone_clearqueryacl(dns_zone_t *zone) {
15345 REQUIRE(DNS_ZONE_VALID(zone));
15346
15347 LOCK_ZONE(zone);
15348 if (zone->query_acl != NULL) {
15349 dns_acl_detach(&zone->query_acl);
15350 }
15351 UNLOCK_ZONE(zone);
15352 }
15353
15354 void
15355 dns_zone_clearqueryonacl(dns_zone_t *zone) {
15356 REQUIRE(DNS_ZONE_VALID(zone));
15357
15358 LOCK_ZONE(zone);
15359 if (zone->queryon_acl != NULL) {
15360 dns_acl_detach(&zone->queryon_acl);
15361 }
15362 UNLOCK_ZONE(zone);
15363 }
15364
15365 void
15366 dns_zone_clearxfracl(dns_zone_t *zone) {
15367 REQUIRE(DNS_ZONE_VALID(zone));
15368
15369 LOCK_ZONE(zone);
15370 if (zone->xfr_acl != NULL) {
15371 dns_acl_detach(&zone->xfr_acl);
15372 }
15373 UNLOCK_ZONE(zone);
15374 }
15375
15376 bool
15377 dns_zone_getupdatedisabled(dns_zone_t *zone) {
15378 REQUIRE(DNS_ZONE_VALID(zone));
15379 return (zone->update_disabled);
15380 }
15381
15382 void
15383 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
15384 REQUIRE(DNS_ZONE_VALID(zone));
15385 zone->update_disabled = state;
15386 }
15387
15388 bool
15389 dns_zone_getzeronosoattl(dns_zone_t *zone) {
15390 REQUIRE(DNS_ZONE_VALID(zone));
15391 return (zone->zero_no_soa_ttl);
15392 }
15393
15394 void
15395 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
15396 REQUIRE(DNS_ZONE_VALID(zone));
15397 zone->zero_no_soa_ttl = state;
15398 }
15399
15400 void
15401 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
15402 REQUIRE(DNS_ZONE_VALID(zone));
15403
15404 zone->check_names = severity;
15405 }
15406
15407 dns_severity_t
15408 dns_zone_getchecknames(dns_zone_t *zone) {
15409 REQUIRE(DNS_ZONE_VALID(zone));
15410
15411 return (zone->check_names);
15412 }
15413
15414 void
15415 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
15416 REQUIRE(DNS_ZONE_VALID(zone));
15417
15418 zone->journalsize = size;
15419 }
15420
15421 int32_t
15422 dns_zone_getjournalsize(dns_zone_t *zone) {
15423 REQUIRE(DNS_ZONE_VALID(zone));
15424
15425 return (zone->journalsize);
15426 }
15427
15428 static void
15429 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
15430 isc_result_t result = ISC_R_FAILURE;
15431 isc_buffer_t buffer;
15432
15433 REQUIRE(buf != NULL);
15434 REQUIRE(length > 1U);
15435
15436 /*
15437 * Leave space for terminating '\0'.
15438 */
15439 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15440 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
15441 if (dns_name_dynamic(&zone->origin)) {
15442 result = dns_name_totext(&zone->origin, true, &buffer);
15443 }
15444 if (result != ISC_R_SUCCESS &&
15445 isc_buffer_availablelength(&buffer) >=
15446 (sizeof("<UNKNOWN>") - 1))
15447 {
15448 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15449 }
15450
15451 if (isc_buffer_availablelength(&buffer) > 0) {
15452 isc_buffer_putstr(&buffer, "/");
15453 }
15454 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
15455 }
15456
15457 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
15458 strcmp(zone->view->name, "_default") != 0 &&
15459 strlen(zone->view->name) < isc_buffer_availablelength(&buffer))
15460 {
15461 isc_buffer_putstr(&buffer, "/");
15462 isc_buffer_putstr(&buffer, zone->view->name);
15463 }
15464 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer)) {
15465 isc_buffer_putstr(&buffer, " (signed)");
15466 }
15467 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer)) {
15468 isc_buffer_putstr(&buffer, " (unsigned)");
15469 }
15470
15471 buf[isc_buffer_usedlength(&buffer)] = '\0';
15472 }
15473
15474 static void
15475 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
15476 isc_result_t result = ISC_R_FAILURE;
15477 isc_buffer_t buffer;
15478
15479 REQUIRE(buf != NULL);
15480 REQUIRE(length > 1U);
15481
15482 /*
15483 * Leave space for terminating '\0'.
15484 */
15485 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15486 if (dns_name_dynamic(&zone->origin)) {
15487 result = dns_name_totext(&zone->origin, true, &buffer);
15488 }
15489 if (result != ISC_R_SUCCESS &&
15490 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
15491 {
15492 isc_buffer_putstr(&buffer, "<UNKNOWN>");
15493 }
15494
15495 buf[isc_buffer_usedlength(&buffer)] = '\0';
15496 }
15497
15498 static void
15499 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
15500 isc_buffer_t buffer;
15501
15502 REQUIRE(buf != NULL);
15503 REQUIRE(length > 1U);
15504
15505 /*
15506 * Leave space for terminating '\0'.
15507 */
15508 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15509 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
15510
15511 buf[isc_buffer_usedlength(&buffer)] = '\0';
15512 }
15513
15514 static void
15515 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
15516 isc_buffer_t buffer;
15517
15518 REQUIRE(buf != NULL);
15519 REQUIRE(length > 1U);
15520
15521 /*
15522 * Leave space for terminating '\0'.
15523 */
15524 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
15525
15526 if (zone->view == NULL) {
15527 isc_buffer_putstr(&buffer, "_none");
15528 } else if (strlen(zone->view->name) <
15529 isc_buffer_availablelength(&buffer)) {
15530 isc_buffer_putstr(&buffer, zone->view->name);
15531 } else {
15532 isc_buffer_putstr(&buffer, "_toolong");
15533 }
15534
15535 buf[isc_buffer_usedlength(&buffer)] = '\0';
15536 }
15537
15538 void
15539 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
15540 REQUIRE(DNS_ZONE_VALID(zone));
15541 REQUIRE(buf != NULL);
15542
15543 LOCK_ZONE(zone);
15544 zone_namerd_tostr(zone, buf, length);
15545 UNLOCK_ZONE(zone);
15546 }
15547
15548 void
15549 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
15550 REQUIRE(DNS_ZONE_VALID(zone));
15551 REQUIRE(buf != NULL);
15552 zone_name_tostr(zone, buf, length);
15553 }
15554
15555 void
15556 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
15557 const char *prefix, const char *fmt, va_list ap) {
15558 char message[4096];
15559 const char *zstr;
15560
15561 REQUIRE(DNS_ZONE_VALID(zone));
15562
15563 if (!isc_log_wouldlog(dns_lctx, level)) {
15564 return;
15565 }
15566
15567 vsnprintf(message, sizeof(message), fmt, ap);
15568
15569 switch (zone->type) {
15570 case dns_zone_key:
15571 zstr = "managed-keys-zone";
15572 break;
15573 case dns_zone_redirect:
15574 zstr = "redirect-zone";
15575 break;
15576 default:
15577 zstr = "zone ";
15578 }
15579
15580 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
15581 "%s%s%s%s: %s", (prefix != NULL ? prefix : ""),
15582 (prefix != NULL ? ": " : ""), zstr, zone->strnamerd,
15583 message);
15584 }
15585
15586 static void
15587 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
15588 va_list ap;
15589
15590 va_start(ap, fmt);
15591 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
15592 va_end(ap);
15593 }
15594
15595 void
15596 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category, int level,
15597 const char *fmt, ...) {
15598 va_list ap;
15599
15600 va_start(ap, fmt);
15601 dns_zone_logv(zone, category, level, NULL, fmt, ap);
15602 va_end(ap);
15603 }
15604
15605 void
15606 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
15607 va_list ap;
15608
15609 va_start(ap, fmt);
15610 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
15611 va_end(ap);
15612 }
15613
15614 static void
15615 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel, const char *fmt,
15616 ...) {
15617 int level = ISC_LOG_DEBUG(debuglevel);
15618 va_list ap;
15619
15620 va_start(ap, fmt);
15621 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
15622 va_end(ap);
15623 }
15624
15625 static void
15626 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
15627 va_list ap;
15628
15629 va_start(ap, fmt);
15630 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
15631 va_end(ap);
15632 }
15633
15634 static int
15635 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type) {
15636 isc_result_t result;
15637 dns_name_t *name;
15638 dns_rdataset_t *curr;
15639 int count = 0;
15640
15641 result = dns_message_firstname(msg, section);
15642 while (result == ISC_R_SUCCESS) {
15643 name = NULL;
15644 dns_message_currentname(msg, section, &name);
15645
15646 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
15647 curr = ISC_LIST_PREV(curr, link))
15648 {
15649 if (curr->type == type) {
15650 count++;
15651 }
15652 }
15653 result = dns_message_nextname(msg, section);
15654 }
15655
15656 return (count);
15657 }
15658
15659 void
15660 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
15661 REQUIRE(DNS_ZONE_VALID(zone));
15662
15663 zone->maxxfrin = maxxfrin;
15664 }
15665
15666 uint32_t
15667 dns_zone_getmaxxfrin(dns_zone_t *zone) {
15668 REQUIRE(DNS_ZONE_VALID(zone));
15669
15670 return (zone->maxxfrin);
15671 }
15672
15673 void
15674 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
15675 REQUIRE(DNS_ZONE_VALID(zone));
15676 zone->maxxfrout = maxxfrout;
15677 }
15678
15679 uint32_t
15680 dns_zone_getmaxxfrout(dns_zone_t *zone) {
15681 REQUIRE(DNS_ZONE_VALID(zone));
15682
15683 return (zone->maxxfrout);
15684 }
15685
15686 dns_zonetype_t
15687 dns_zone_gettype(dns_zone_t *zone) {
15688 REQUIRE(DNS_ZONE_VALID(zone));
15689
15690 return (zone->type);
15691 }
15692
15693 const char *
15694 dns_zonetype_name(dns_zonetype_t type) {
15695 switch (type) {
15696 case dns_zone_none:
15697 return ("none");
15698 case dns_zone_master:
15699 return ("primary");
15700 case dns_zone_slave:
15701 return ("secondary");
15702 case dns_zone_mirror:
15703 return ("mirror");
15704 case dns_zone_stub:
15705 return ("stub");
15706 case dns_zone_staticstub:
15707 return ("static-stub");
15708 case dns_zone_key:
15709 return ("key");
15710 case dns_zone_dlz:
15711 return ("dlz");
15712 case dns_zone_redirect:
15713 return ("redirect");
15714 default:
15715 return ("unknown");
15716 }
15717 }
15718
15719 dns_zonetype_t
15720 dns_zone_getredirecttype(dns_zone_t *zone) {
15721 REQUIRE(DNS_ZONE_VALID(zone));
15722 REQUIRE(zone->type == dns_zone_redirect);
15723
15724 return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
15725 }
15726
15727 dns_name_t *
15728 dns_zone_getorigin(dns_zone_t *zone) {
15729 REQUIRE(DNS_ZONE_VALID(zone));
15730
15731 return (&zone->origin);
15732 }
15733
15734 void
15735 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
15736 REQUIRE(DNS_ZONE_VALID(zone));
15737
15738 LOCK_ZONE(zone);
15739 if (zone->task != NULL) {
15740 isc_task_detach(&zone->task);
15741 }
15742 isc_task_attach(task, &zone->task);
15743 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15744 if (zone->db != NULL) {
15745 dns_db_settask(zone->db, zone->task);
15746 }
15747 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15748 UNLOCK_ZONE(zone);
15749 }
15750
15751 void
15752 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
15753 REQUIRE(DNS_ZONE_VALID(zone));
15754 isc_task_attach(zone->task, target);
15755 }
15756
15757 void
15758 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
15759 REQUIRE(DNS_ZONE_VALID(zone));
15760
15761 if (idlein == 0) {
15762 idlein = DNS_DEFAULT_IDLEIN;
15763 }
15764 zone->idlein = idlein;
15765 }
15766
15767 uint32_t
15768 dns_zone_getidlein(dns_zone_t *zone) {
15769 REQUIRE(DNS_ZONE_VALID(zone));
15770
15771 return (zone->idlein);
15772 }
15773
15774 void
15775 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
15776 REQUIRE(DNS_ZONE_VALID(zone));
15777
15778 zone->idleout = idleout;
15779 }
15780
15781 uint32_t
15782 dns_zone_getidleout(dns_zone_t *zone) {
15783 REQUIRE(DNS_ZONE_VALID(zone));
15784
15785 return (zone->idleout);
15786 }
15787
15788 static void
15789 notify_done(isc_task_t *task, isc_event_t *event) {
15790 dns_requestevent_t *revent = (dns_requestevent_t *)event;
15791 dns_notify_t *notify;
15792 isc_result_t result;
15793 dns_message_t *message = NULL;
15794 isc_buffer_t buf;
15795 char rcode[128];
15796 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
15797
15798 UNUSED(task);
15799
15800 notify = event->ev_arg;
15801 REQUIRE(DNS_NOTIFY_VALID(notify));
15802 INSIST(task == notify->zone->task);
15803
15804 isc_buffer_init(&buf, rcode, sizeof(rcode));
15805 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
15806 dns_message_create(notify->zone->mctx, DNS_MESSAGE_INTENTPARSE,
15807 &message);
15808
15809 result = revent->result;
15810 if (result == ISC_R_SUCCESS) {
15811 result =
15812 dns_request_getresponse(revent->request, message,
15813 DNS_MESSAGEPARSE_PRESERVEORDER);
15814 }
15815 if (result == ISC_R_SUCCESS) {
15816 result = dns_rcode_totext(message->rcode, &buf);
15817 }
15818 if (result == ISC_R_SUCCESS) {
15819 notify_log(notify->zone, ISC_LOG_DEBUG(3),
15820 "notify response from %s: %.*s", addrbuf,
15821 (int)buf.used, rcode);
15822 } else {
15823 notify_log(notify->zone, ISC_LOG_DEBUG(2),
15824 "notify to %s failed: %s", addrbuf,
15825 dns_result_totext(result));
15826 }
15827
15828 /*
15829 * Old bind's return formerr if they see a soa record. Retry w/o
15830 * the soa if we see a formerr and had sent a SOA.
15831 */
15832 isc_event_free(&event);
15833 if (message->rcode == dns_rcode_formerr &&
15834 (notify->flags & DNS_NOTIFY_NOSOA) == 0)
15835 {
15836 bool startup;
15837
15838 notify->flags |= DNS_NOTIFY_NOSOA;
15839 dns_request_destroy(¬ify->request);
15840 startup = (notify->flags & DNS_NOTIFY_STARTUP);
15841 result = notify_send_queue(notify, startup);
15842 if (result != ISC_R_SUCCESS) {
15843 notify_destroy(notify, false);
15844 }
15845 } else {
15846 if (result == ISC_R_TIMEDOUT) {
15847 notify_log(notify->zone, ISC_LOG_DEBUG(1),
15848 "notify to %s: retries exceeded", addrbuf);
15849 }
15850 notify_destroy(notify, false);
15851 }
15852 dns_message_detach(&message);
15853 }
15854
15855 struct secure_event {
15856 isc_event_t e;
15857 dns_db_t *db;
15858 uint32_t serial;
15859 };
15860
15861 static void
15862 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
15863 UNUSED(arg);
15864 dns_zone_log(zone, level, "%s", message);
15865 }
15866
15867 static isc_result_t
15868 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
15869 uint32_t start, uint32_t end, dns_difftuple_t **soatuplep,
15870 dns_diff_t *diff) {
15871 isc_result_t result;
15872 dns_difftuple_t *tuple = NULL;
15873 dns_diffop_t op = DNS_DIFFOP_ADD;
15874 int n_soa = 0;
15875
15876 REQUIRE(soatuplep != NULL);
15877
15878 if (start == end) {
15879 return (DNS_R_UNCHANGED);
15880 }
15881
15882 CHECK(dns_journal_iter_init(journal, start, end, NULL));
15883 for (result = dns_journal_first_rr(journal); result == ISC_R_SUCCESS;
15884 result = dns_journal_next_rr(journal))
15885 {
15886 dns_name_t *name = NULL;
15887 uint32_t ttl;
15888 dns_rdata_t *rdata = NULL;
15889 dns_journal_current_rr(journal, &name, &ttl, &rdata);
15890
15891 if (rdata->type == dns_rdatatype_soa) {
15892 n_soa++;
15893 if (n_soa == 2) {
15894 /*
15895 * Save the latest raw SOA record.
15896 */
15897 if (*soatuplep != NULL) {
15898 dns_difftuple_free(soatuplep);
15899 }
15900 CHECK(dns_difftuple_create(
15901 diff->mctx, DNS_DIFFOP_ADD, name, ttl,
15902 rdata, soatuplep));
15903 }
15904 if (n_soa == 3) {
15905 n_soa = 1;
15906 }
15907 continue;
15908 }
15909
15910 /* Sanity. */
15911 if (n_soa == 0) {
15912 dns_zone_log(raw, ISC_LOG_ERROR,
15913 "corrupt journal file: '%s'\n",
15914 raw->journal);
15915 return (ISC_R_FAILURE);
15916 }
15917
15918 if (zone->privatetype != 0 && rdata->type == zone->privatetype)
15919 {
15920 continue;
15921 }
15922
15923 if (rdata->type == dns_rdatatype_nsec ||
15924 rdata->type == dns_rdatatype_rrsig ||
15925 rdata->type == dns_rdatatype_nsec3 ||
15926 rdata->type == dns_rdatatype_dnskey ||
15927 rdata->type == dns_rdatatype_nsec3param)
15928 {
15929 continue;
15930 }
15931
15932 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
15933
15934 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
15935 &tuple));
15936 dns_diff_appendminimal(diff, &tuple);
15937 }
15938 if (result == ISC_R_NOMORE) {
15939 result = ISC_R_SUCCESS;
15940 }
15941
15942 failure:
15943 return (result);
15944 }
15945
15946 static isc_result_t
15947 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
15948 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
15949 dns_diff_t *diff) {
15950 isc_result_t result;
15951 dns_db_t *rawdb = NULL;
15952 dns_dbversion_t *rawver = NULL;
15953 dns_difftuple_t *tuple = NULL, *next;
15954 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
15955 dns_rdata_soa_t oldsoa, newsoa;
15956
15957 REQUIRE(DNS_ZONE_VALID(seczone));
15958 REQUIRE(soatuple != NULL && *soatuple == NULL);
15959
15960 if (!seczone->sourceserialset) {
15961 return (DNS_R_UNCHANGED);
15962 }
15963
15964 dns_db_attach(raw->db, &rawdb);
15965 dns_db_currentversion(rawdb, &rawver);
15966 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
15967 dns_db_closeversion(rawdb, &rawver, false);
15968 dns_db_detach(&rawdb);
15969
15970 if (result != ISC_R_SUCCESS) {
15971 return (result);
15972 }
15973
15974 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL; tuple = next) {
15975 next = ISC_LIST_NEXT(tuple, link);
15976 if (tuple->rdata.type == dns_rdatatype_nsec ||
15977 tuple->rdata.type == dns_rdatatype_rrsig ||
15978 tuple->rdata.type == dns_rdatatype_dnskey ||
15979 tuple->rdata.type == dns_rdatatype_nsec3 ||
15980 tuple->rdata.type == dns_rdatatype_nsec3param)
15981 {
15982 ISC_LIST_UNLINK(diff->tuples, tuple, link);
15983 dns_difftuple_free(&tuple);
15984 continue;
15985 }
15986 if (tuple->rdata.type == dns_rdatatype_soa) {
15987 if (tuple->op == DNS_DIFFOP_DEL) {
15988 INSIST(oldtuple == NULL);
15989 oldtuple = tuple;
15990 }
15991 if (tuple->op == DNS_DIFFOP_ADD) {
15992 INSIST(newtuple == NULL);
15993 newtuple = tuple;
15994 }
15995 }
15996 }
15997
15998 if (oldtuple != NULL && newtuple != NULL) {
15999 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
16000 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16001
16002 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
16003 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16004
16005 /*
16006 * If the SOA records are the same except for the serial
16007 * remove them from the diff.
16008 */
16009 if (oldsoa.refresh == newsoa.refresh &&
16010 oldsoa.retry == newsoa.retry &&
16011 oldsoa.minimum == newsoa.minimum &&
16012 oldsoa.expire == newsoa.expire &&
16013 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
16014 dns_name_equal(&oldsoa.contact, &newsoa.contact))
16015 {
16016 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16017 dns_difftuple_free(&oldtuple);
16018 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16019 dns_difftuple_free(&newtuple);
16020 }
16021 }
16022
16023 if (ISC_LIST_EMPTY(diff->tuples)) {
16024 return (DNS_R_UNCHANGED);
16025 }
16026
16027 /*
16028 * If there are still SOA records in the diff they can now be removed
16029 * saving the new SOA record.
16030 */
16031 if (oldtuple != NULL) {
16032 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
16033 dns_difftuple_free(&oldtuple);
16034 }
16035
16036 if (newtuple != NULL) {
16037 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
16038 *soatuple = newtuple;
16039 }
16040
16041 return (ISC_R_SUCCESS);
16042 }
16043
16044 static void
16045 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
16046 static char me[] = "receive_secure_serial";
16047 isc_result_t result = ISC_R_SUCCESS;
16048 dns_journal_t *rjournal = NULL;
16049 dns_journal_t *sjournal = NULL;
16050 uint32_t start, end;
16051 dns_zone_t *zone;
16052 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
16053 dns_update_log_t log = { update_log_cb, NULL };
16054 uint32_t newserial = 0, desired = 0;
16055 isc_time_t timenow;
16056 int level = ISC_LOG_ERROR;
16057
16058 UNUSED(task);
16059
16060 zone = event->ev_arg;
16061 end = ((struct secure_event *)event)->serial;
16062
16063 ENTER;
16064
16065 LOCK_ZONE(zone);
16066
16067 /*
16068 * If we are already processing a receive secure serial event
16069 * for the zone, just queue the new one and exit.
16070 */
16071 if (zone->rss_event != NULL && zone->rss_event != event) {
16072 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
16073 UNLOCK_ZONE(zone);
16074 return;
16075 }
16076
16077 nextevent:
16078 if (zone->rss_event != NULL) {
16079 INSIST(zone->rss_event == event);
16080 UNLOCK_ZONE(zone);
16081 } else {
16082 zone->rss_event = event;
16083 dns_diff_init(zone->mctx, &zone->rss_diff);
16084
16085 /*
16086 * zone->db may be NULL, if the load from disk failed.
16087 */
16088 result = ISC_R_SUCCESS;
16089 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16090 if (zone->db != NULL) {
16091 dns_db_attach(zone->db, &zone->rss_db);
16092 } else {
16093 result = ISC_R_FAILURE;
16094 }
16095 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16096
16097 if (result == ISC_R_SUCCESS && zone->raw != NULL) {
16098 dns_zone_attach(zone->raw, &zone->rss_raw);
16099 } else {
16100 result = ISC_R_FAILURE;
16101 }
16102
16103 UNLOCK_ZONE(zone);
16104
16105 CHECK(result);
16106
16107 /*
16108 * We first attempt to sync the raw zone to the secure zone
16109 * by using the raw zone's journal, applying all the deltas
16110 * from the latest source-serial of the secure zone up to
16111 * the current serial number of the raw zone.
16112 *
16113 * If that fails, then we'll fall back to a direct comparison
16114 * between raw and secure zones.
16115 */
16116 CHECK(dns_journal_open(zone->rss_raw->mctx,
16117 zone->rss_raw->journal,
16118 DNS_JOURNAL_WRITE, &rjournal));
16119
16120 result = dns_journal_open(zone->mctx, zone->journal,
16121 DNS_JOURNAL_READ, &sjournal);
16122 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16123 goto failure;
16124 }
16125
16126 if (!dns_journal_get_sourceserial(rjournal, &start)) {
16127 start = dns_journal_first_serial(rjournal);
16128 dns_journal_set_sourceserial(rjournal, start);
16129 }
16130 if (sjournal != NULL) {
16131 uint32_t serial;
16132 /*
16133 * We read the secure journal first, if that
16134 * exists use its value provided it is greater
16135 * that from the raw journal.
16136 */
16137 if (dns_journal_get_sourceserial(sjournal, &serial)) {
16138 if (isc_serial_gt(serial, start)) {
16139 start = serial;
16140 }
16141 }
16142 dns_journal_destroy(&sjournal);
16143 }
16144
16145 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
16146 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
16147
16148 /*
16149 * Try to apply diffs from the raw zone's journal to the secure
16150 * zone. If that fails, we recover by syncing up the databases
16151 * directly.
16152 */
16153 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
16154 start, end, &soatuple,
16155 &zone->rss_diff);
16156 if (result == DNS_R_UNCHANGED) {
16157 level = ISC_LOG_INFO;
16158 goto failure;
16159 } else if (result != ISC_R_SUCCESS) {
16160 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
16161 zone->rss_oldver, &soatuple,
16162 &zone->rss_diff));
16163 }
16164
16165 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
16166 zone->rss_newver));
16167
16168 if (soatuple != NULL) {
16169 uint32_t oldserial;
16170
16171 CHECK(dns_db_createsoatuple(
16172 zone->rss_db, zone->rss_oldver,
16173 zone->rss_diff.mctx, DNS_DIFFOP_DEL, &tuple));
16174 oldserial = dns_soa_getserial(&tuple->rdata);
16175 newserial = desired =
16176 dns_soa_getserial(&soatuple->rdata);
16177 if (!isc_serial_gt(newserial, oldserial)) {
16178 newserial = oldserial + 1;
16179 if (newserial == 0) {
16180 newserial++;
16181 }
16182 dns_soa_setserial(newserial, &soatuple->rdata);
16183 }
16184 CHECK(do_one_tuple(&tuple, zone->rss_db,
16185 zone->rss_newver, &zone->rss_diff));
16186 CHECK(do_one_tuple(&soatuple, zone->rss_db,
16187 zone->rss_newver, &zone->rss_diff));
16188 } else {
16189 CHECK(update_soa_serial(zone, zone->rss_db,
16190 zone->rss_newver,
16191 &zone->rss_diff, zone->mctx,
16192 zone->updatemethod));
16193 }
16194 }
16195 result = dns_update_signaturesinc(
16196 &log, zone, zone->rss_db, zone->rss_oldver, zone->rss_newver,
16197 &zone->rss_diff, zone->sigvalidityinterval, &zone->rss_state);
16198 if (result == DNS_R_CONTINUE) {
16199 if (rjournal != NULL) {
16200 dns_journal_destroy(&rjournal);
16201 }
16202 isc_task_send(task, &event);
16203 return;
16204 }
16205 /*
16206 * If something went wrong while trying to update the secure zone and
16207 * the latter was already signed before, do not apply raw zone deltas
16208 * to it as that would break existing DNSSEC signatures. However, if
16209 * the secure zone was not yet signed (e.g. because no signing keys
16210 * were created for it), commence applying raw zone deltas to it so
16211 * that contents of the raw zone and the secure zone are kept in sync.
16212 */
16213 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
16214 goto failure;
16215 }
16216
16217 if (rjournal == NULL) {
16218 CHECK(dns_journal_open(zone->rss_raw->mctx,
16219 zone->rss_raw->journal,
16220 DNS_JOURNAL_WRITE, &rjournal));
16221 }
16222 CHECK(zone_journal(zone, &zone->rss_diff, &end,
16223 "receive_secure_serial"));
16224
16225 dns_journal_set_sourceserial(rjournal, end);
16226 dns_journal_commit(rjournal);
16227
16228 LOCK_ZONE(zone);
16229 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16230
16231 zone->sourceserial = end;
16232 zone->sourceserialset = true;
16233 zone_needdump(zone, DNS_DUMP_DELAY);
16234
16235 /*
16236 * Set resign time to make sure it is set to the earliest
16237 * signature expiration.
16238 */
16239 set_resigntime(zone);
16240 TIME_NOW(&timenow);
16241 zone_settimer(zone, &timenow);
16242 UNLOCK_ZONE(zone);
16243
16244 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
16245 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
16246
16247 if (newserial != 0) {
16248 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
16249 newserial, desired);
16250 }
16251
16252 failure:
16253 isc_event_free(&zone->rss_event);
16254 event = ISC_LIST_HEAD(zone->rss_events);
16255
16256 if (zone->rss_raw != NULL) {
16257 dns_zone_detach(&zone->rss_raw);
16258 }
16259 if (result != ISC_R_SUCCESS) {
16260 LOCK_ZONE(zone);
16261 set_resigntime(zone);
16262 TIME_NOW(&timenow);
16263 zone_settimer(zone, &timenow);
16264 UNLOCK_ZONE(zone);
16265 dns_zone_log(zone, level, "receive_secure_serial: %s",
16266 dns_result_totext(result));
16267 }
16268 if (tuple != NULL) {
16269 dns_difftuple_free(&tuple);
16270 }
16271 if (soatuple != NULL) {
16272 dns_difftuple_free(&soatuple);
16273 }
16274 if (zone->rss_db != NULL) {
16275 if (zone->rss_oldver != NULL) {
16276 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
16277 false);
16278 }
16279 if (zone->rss_newver != NULL) {
16280 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
16281 false);
16282 }
16283 dns_db_detach(&zone->rss_db);
16284 }
16285 INSIST(zone->rss_oldver == NULL);
16286 INSIST(zone->rss_newver == NULL);
16287 if (rjournal != NULL) {
16288 dns_journal_destroy(&rjournal);
16289 }
16290 dns_diff_clear(&zone->rss_diff);
16291
16292 if (event != NULL) {
16293 LOCK_ZONE(zone);
16294 isc_refcount_decrement(&zone->irefs);
16295 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
16296 goto nextevent;
16297 }
16298
16299 event = ISC_LIST_HEAD(zone->rss_post);
16300 while (event != NULL) {
16301 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
16302 rss_post(zone, event);
16303 event = ISC_LIST_HEAD(zone->rss_post);
16304 }
16305
16306 dns_zone_idetach(&zone);
16307 }
16308
16309 static isc_result_t
16310 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
16311 isc_event_t *e;
16312 dns_zone_t *dummy = NULL;
16313
16314 e = isc_event_allocate(zone->secure->mctx, zone,
16315 DNS_EVENT_ZONESECURESERIAL,
16316 receive_secure_serial, zone->secure,
16317 sizeof(struct secure_event));
16318 ((struct secure_event *)e)->serial = serial;
16319 INSIST(LOCKED_ZONE(zone->secure));
16320 zone_iattach(zone->secure, &dummy);
16321 isc_task_send(zone->secure->task, &e);
16322
16323 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16324 return (ISC_R_SUCCESS);
16325 }
16326
16327 static isc_result_t
16328 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
16329 dns_rdataset_t *rdataset, uint32_t oldserial) {
16330 dns_rdata_soa_t soa;
16331 dns_rdata_t rdata = DNS_RDATA_INIT;
16332 dns_rdatalist_t temprdatalist;
16333 dns_rdataset_t temprdataset;
16334 isc_buffer_t b;
16335 isc_result_t result;
16336 unsigned char buf[DNS_SOA_BUFFERSIZE];
16337 dns_fixedname_t fixed;
16338 dns_name_t *name;
16339
16340 result = dns_rdataset_first(rdataset);
16341 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16342 dns_rdataset_current(rdataset, &rdata);
16343 result = dns_rdata_tostruct(&rdata, &soa, NULL);
16344 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16345
16346 if (isc_serial_gt(soa.serial, oldserial)) {
16347 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
16348 NULL));
16349 }
16350 /*
16351 * Always bump the serial.
16352 */
16353 oldserial++;
16354 if (oldserial == 0) {
16355 oldserial++;
16356 }
16357 soa.serial = oldserial;
16358
16359 /*
16360 * Construct a replacement rdataset.
16361 */
16362 dns_rdata_reset(&rdata);
16363 isc_buffer_init(&b, buf, sizeof(buf));
16364 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
16365 dns_rdatatype_soa, &soa, &b);
16366 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16367 dns_rdatalist_init(&temprdatalist);
16368 temprdatalist.rdclass = rdata.rdclass;
16369 temprdatalist.type = rdata.type;
16370 temprdatalist.ttl = rdataset->ttl;
16371 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
16372
16373 dns_rdataset_init(&temprdataset);
16374 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
16375 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16376
16377 name = dns_fixedname_initname(&fixed);
16378 result = dns_db_nodefullname(db, node, name);
16379 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16380 dns_rdataset_getownercase(rdataset, name);
16381 dns_rdataset_setownercase(&temprdataset, name);
16382 return (dns_db_addrdataset(db, node, version, 0, &temprdataset, 0,
16383 NULL));
16384 }
16385
16386 /*
16387 * This function should populate an nsec3paramlist_t with the
16388 * nsecparam_t data from a zone.
16389 */
16390 static isc_result_t
16391 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
16392 isc_result_t result;
16393 dns_dbnode_t *node = NULL;
16394 dns_rdataset_t rdataset, prdataset;
16395 dns_dbversion_t *version = NULL;
16396 nsec3param_t *nsec3param = NULL;
16397 nsec3param_t *nsec3p = NULL;
16398 nsec3param_t *next;
16399 dns_db_t *db = NULL;
16400 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
16401
16402 REQUIRE(DNS_ZONE_VALID(zone));
16403 REQUIRE(nsec3list != NULL);
16404 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
16405
16406 dns_rdataset_init(&rdataset);
16407 dns_rdataset_init(&prdataset);
16408
16409 dns_db_attach(zone->db, &db);
16410 CHECK(dns_db_getoriginnode(db, &node));
16411
16412 dns_db_currentversion(db, &version);
16413 result = dns_db_findrdataset(db, node, version,
16414 dns_rdatatype_nsec3param,
16415 dns_rdatatype_none, 0, &rdataset, NULL);
16416
16417 if (result != ISC_R_SUCCESS) {
16418 goto getprivate;
16419 }
16420
16421 /*
16422 * Walk nsec3param rdataset making a list of parameters (note that
16423 * multiple simultaneous nsec3 chains are annoyingly legal -- this
16424 * is why we use an nsec3list, even though we will usually only
16425 * have one).
16426 */
16427 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
16428 result = dns_rdataset_next(&rdataset))
16429 {
16430 dns_rdata_t rdata = DNS_RDATA_INIT;
16431 dns_rdata_t private = DNS_RDATA_INIT;
16432
16433 dns_rdataset_current(&rdataset, &rdata);
16434 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16435 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16436 "looping through nsec3param data");
16437 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16438 ISC_LINK_INIT(nsec3param, link);
16439
16440 /*
16441 * now transfer the data from the rdata to
16442 * the nsec3param
16443 */
16444 dns_nsec3param_toprivate(&rdata, &private, zone->privatetype,
16445 nsec3param->data,
16446 sizeof(nsec3param->data));
16447 nsec3param->length = private.length;
16448 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16449 }
16450
16451 getprivate:
16452 result = dns_db_findrdataset(db, node, version, zone->privatetype,
16453 dns_rdatatype_none, 0, &prdataset, NULL);
16454 if (result != ISC_R_SUCCESS) {
16455 goto done;
16456 }
16457
16458 /*
16459 * walk private type records, converting them to nsec3 parameters
16460 * using dns_nsec3param_fromprivate(), do the right thing based on
16461 * CREATE and REMOVE flags
16462 */
16463 for (result = dns_rdataset_first(&prdataset); result == ISC_R_SUCCESS;
16464 result = dns_rdataset_next(&prdataset))
16465 {
16466 dns_rdata_t rdata = DNS_RDATA_INIT;
16467 dns_rdata_t private = DNS_RDATA_INIT;
16468
16469 dns_rdataset_current(&prdataset, &private);
16470 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16471 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16472 "looping through nsec3param private data");
16473
16474 /*
16475 * Do we have a valid private record?
16476 */
16477 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
16478 sizeof(buf))) {
16479 continue;
16480 }
16481
16482 /*
16483 * Remove any NSEC3PARAM records scheduled to be removed.
16484 */
16485 if (NSEC3REMOVE(rdata.data[1])) {
16486 /*
16487 * Zero out the flags.
16488 */
16489 rdata.data[1] = 0;
16490
16491 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL;
16492 nsec3p = next) {
16493 next = ISC_LIST_NEXT(nsec3p, link);
16494
16495 if (nsec3p->length == rdata.length + 1 &&
16496 memcmp(rdata.data, nsec3p->data + 1,
16497 nsec3p->length - 1) == 0)
16498 {
16499 ISC_LIST_UNLINK(*nsec3list, nsec3p,
16500 link);
16501 isc_mem_put(zone->mctx, nsec3p,
16502 sizeof(nsec3param_t));
16503 }
16504 }
16505 continue;
16506 }
16507
16508 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
16509 ISC_LINK_INIT(nsec3param, link);
16510
16511 /*
16512 * Copy the remaining private records so the nsec/nsec3
16513 * chain gets created.
16514 */
16515 INSIST(private.length <= sizeof(nsec3param->data));
16516 memmove(nsec3param->data, private.data, private.length);
16517 nsec3param->length = private.length;
16518 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
16519 }
16520
16521 done:
16522 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND) {
16523 result = ISC_R_SUCCESS;
16524 }
16525
16526 failure:
16527 if (node != NULL) {
16528 dns_db_detachnode(db, &node);
16529 }
16530 if (version != NULL) {
16531 dns_db_closeversion(db, &version, false);
16532 }
16533 if (db != NULL) {
16534 dns_db_detach(&db);
16535 }
16536 if (dns_rdataset_isassociated(&rdataset)) {
16537 dns_rdataset_disassociate(&rdataset);
16538 }
16539 if (dns_rdataset_isassociated(&prdataset)) {
16540 dns_rdataset_disassociate(&prdataset);
16541 }
16542 return (result);
16543 }
16544
16545 /*
16546 * Populate new zone db with private type records found by save_nsec3param().
16547 */
16548 static isc_result_t
16549 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
16550 nsec3paramlist_t *nsec3list) {
16551 isc_result_t result = ISC_R_SUCCESS;
16552 dns_diff_t diff;
16553 dns_rdata_t rdata;
16554 nsec3param_t *nsec3p = NULL;
16555 nsec3param_t *next;
16556
16557 REQUIRE(DNS_ZONE_VALID(zone));
16558 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
16559
16560 dns_diff_init(zone->mctx, &diff);
16561
16562 /*
16563 * Loop through the list of private-type records, set the INITIAL
16564 * and CREATE flags, and the add the record to the apex of the tree
16565 * in db.
16566 */
16567 for (nsec3p = ISC_LIST_HEAD(*nsec3list); nsec3p != NULL; nsec3p = next)
16568 {
16569 next = ISC_LIST_NEXT(nsec3p, link);
16570 dns_rdata_init(&rdata);
16571 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
16572 rdata.length = nsec3p->length;
16573 rdata.data = nsec3p->data;
16574 rdata.type = zone->privatetype;
16575 rdata.rdclass = zone->rdclass;
16576 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
16577 &zone->origin, 0, &rdata);
16578 if (result != ISC_R_SUCCESS) {
16579 break;
16580 }
16581 }
16582
16583 dns_diff_clear(&diff);
16584 return (result);
16585 }
16586
16587 static isc_result_t
16588 copy_non_dnssec_records(dns_zone_t *zone, dns_db_t *db, dns_db_t *version,
16589 dns_db_t *rawdb, dns_dbiterator_t *dbiterator,
16590 unsigned int *oldserial) {
16591 dns_dbnode_t *rawnode = NULL, *node = NULL;
16592 dns_fixedname_t fixed;
16593 dns_name_t *name = dns_fixedname_initname(&fixed);
16594 dns_rdataset_t rdataset;
16595 dns_rdatasetiter_t *rdsit = NULL;
16596 isc_result_t result;
16597
16598 result = dns_dbiterator_current(dbiterator, &rawnode, name);
16599 if (result != ISC_R_SUCCESS) {
16600 return (ISC_R_SUCCESS);
16601 }
16602
16603 dns_dbiterator_pause(dbiterator);
16604
16605 result = dns_db_findnode(db, name, true, &node);
16606 if (result != ISC_R_SUCCESS) {
16607 goto cleanup;
16608 }
16609
16610 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
16611 if (result != ISC_R_SUCCESS) {
16612 goto cleanup;
16613 }
16614
16615 dns_rdataset_init(&rdataset);
16616
16617 for (result = dns_rdatasetiter_first(rdsit); result == ISC_R_SUCCESS;
16618 result = dns_rdatasetiter_next(rdsit))
16619 {
16620 dns_rdatasetiter_current(rdsit, &rdataset);
16621 if (rdataset.type == dns_rdatatype_nsec ||
16622 rdataset.type == dns_rdatatype_rrsig ||
16623 rdataset.type == dns_rdatatype_nsec3 ||
16624 rdataset.type == dns_rdatatype_dnskey ||
16625 rdataset.type == dns_rdatatype_nsec3param)
16626 {
16627 /*
16628 * Allow DNSSEC records with dnssec-policy.
16629 * WMM: Perhaps add config option for it.
16630 */
16631 if (!dns_zone_use_kasp(zone)) {
16632 dns_rdataset_disassociate(&rdataset);
16633 continue;
16634 }
16635 }
16636 if (rdataset.type == dns_rdatatype_soa && oldserial != NULL) {
16637 result = checkandaddsoa(db, node, version, &rdataset,
16638 *oldserial);
16639 } else {
16640 result = dns_db_addrdataset(db, node, version, 0,
16641 &rdataset, 0, NULL);
16642 }
16643 dns_rdataset_disassociate(&rdataset);
16644 if (result != ISC_R_SUCCESS) {
16645 goto cleanup;
16646 }
16647 }
16648 if (result == ISC_R_NOMORE) {
16649 result = ISC_R_SUCCESS;
16650 }
16651
16652 cleanup:
16653 if (rdsit != NULL) {
16654 dns_rdatasetiter_destroy(&rdsit);
16655 }
16656 if (rawnode) {
16657 dns_db_detachnode(rawdb, &rawnode);
16658 }
16659 if (node) {
16660 dns_db_detachnode(db, &node);
16661 }
16662 return (result);
16663 }
16664
16665 static void
16666 receive_secure_db(isc_task_t *task, isc_event_t *event) {
16667 isc_result_t result;
16668 dns_zone_t *zone;
16669 dns_db_t *rawdb, *db = NULL;
16670 dns_dbiterator_t *dbiterator = NULL;
16671 dns_dbversion_t *version = NULL;
16672 isc_time_t loadtime;
16673 unsigned int oldserial = 0, *oldserialp = NULL;
16674 nsec3paramlist_t nsec3list;
16675 isc_event_t *setnsec3param_event;
16676 dns_zone_t *dummy;
16677
16678 UNUSED(task);
16679
16680 ISC_LIST_INIT(nsec3list);
16681
16682 zone = event->ev_arg;
16683 rawdb = ((struct secure_event *)event)->db;
16684 isc_event_free(&event);
16685
16686 LOCK_ZONE(zone);
16687 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
16688 result = ISC_R_SHUTTINGDOWN;
16689 goto failure;
16690 }
16691
16692 TIME_NOW(&loadtime);
16693 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16694 if (zone->db != NULL) {
16695 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
16696 if (result == ISC_R_SUCCESS) {
16697 oldserialp = &oldserial;
16698 }
16699
16700 /*
16701 * assemble nsec3parameters from the old zone, and set a flag
16702 * if any are found
16703 */
16704 result = save_nsec3param(zone, &nsec3list);
16705 if (result != ISC_R_SUCCESS) {
16706 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16707 goto failure;
16708 }
16709 }
16710 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16711
16712 result = dns_db_create(zone->mctx, zone->db_argv[0], &zone->origin,
16713 dns_dbtype_zone, zone->rdclass,
16714 zone->db_argc - 1, zone->db_argv + 1, &db);
16715 if (result != ISC_R_SUCCESS) {
16716 goto failure;
16717 }
16718
16719 result = dns_db_setgluecachestats(db, zone->gluecachestats);
16720 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
16721 goto failure;
16722 }
16723
16724 result = dns_db_newversion(db, &version);
16725 if (result != ISC_R_SUCCESS) {
16726 goto failure;
16727 }
16728
16729 result = dns_db_createiterator(rawdb, 0, &dbiterator);
16730 if (result != ISC_R_SUCCESS) {
16731 goto failure;
16732 }
16733
16734 for (result = dns_dbiterator_first(dbiterator); result == ISC_R_SUCCESS;
16735 result = dns_dbiterator_next(dbiterator))
16736 {
16737 result = copy_non_dnssec_records(zone, db, version, rawdb,
16738 dbiterator, oldserialp);
16739 if (result != ISC_R_SUCCESS) {
16740 goto failure;
16741 }
16742 }
16743 dns_dbiterator_destroy(&dbiterator);
16744 if (result != ISC_R_NOMORE) {
16745 goto failure;
16746 }
16747
16748 /*
16749 * Call restore_nsec3param() to create private-type records from
16750 * the old nsec3 parameters and insert them into db
16751 */
16752 if (!ISC_LIST_EMPTY(nsec3list)) {
16753 result = restore_nsec3param(zone, db, version, &nsec3list);
16754 if (result != ISC_R_SUCCESS) {
16755 goto failure;
16756 }
16757 }
16758
16759 dns_db_closeversion(db, &version, true);
16760
16761 /*
16762 * Lock hierarchy: zmgr, zone, raw.
16763 */
16764 INSIST(zone != zone->raw);
16765 LOCK_ZONE(zone->raw);
16766 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
16767 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
16768 zone_needdump(zone, 0); /* XXXMPA */
16769 UNLOCK_ZONE(zone->raw);
16770
16771 /*
16772 * Process any queued NSEC3PARAM change requests.
16773 */
16774 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
16775 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
16776 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
16777 ev_link);
16778 dummy = NULL;
16779 zone_iattach(zone, &dummy);
16780 isc_task_send(zone->task, &setnsec3param_event);
16781 }
16782
16783 failure:
16784 UNLOCK_ZONE(zone);
16785 if (dbiterator != NULL) {
16786 dns_dbiterator_destroy(&dbiterator);
16787 }
16788 if (result != ISC_R_SUCCESS) {
16789 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
16790 dns_result_totext(result));
16791 }
16792
16793 while (!ISC_LIST_EMPTY(nsec3list)) {
16794 nsec3param_t *nsec3p;
16795 nsec3p = ISC_LIST_HEAD(nsec3list);
16796 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
16797 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
16798 }
16799 if (db != NULL) {
16800 if (version != NULL) {
16801 dns_db_closeversion(db, &version, false);
16802 }
16803 dns_db_detach(&db);
16804 }
16805 dns_db_detach(&rawdb);
16806 dns_zone_idetach(&zone);
16807
16808 INSIST(version == NULL);
16809 }
16810
16811 static isc_result_t
16812 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
16813 isc_event_t *e;
16814 dns_db_t *dummy = NULL;
16815 dns_zone_t *secure = NULL;
16816
16817 e = isc_event_allocate(zone->secure->mctx, zone, DNS_EVENT_ZONESECUREDB,
16818 receive_secure_db, zone->secure,
16819 sizeof(struct secure_event));
16820 dns_db_attach(db, &dummy);
16821 ((struct secure_event *)e)->db = dummy;
16822 INSIST(LOCKED_ZONE(zone->secure));
16823 zone_iattach(zone->secure, &secure);
16824 isc_task_send(zone->secure->task, &e);
16825 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
16826 return (ISC_R_SUCCESS);
16827 }
16828
16829 isc_result_t
16830 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
16831 isc_result_t result;
16832 dns_zone_t *secure = NULL;
16833
16834 REQUIRE(DNS_ZONE_VALID(zone));
16835 again:
16836 LOCK_ZONE(zone);
16837 if (inline_raw(zone)) {
16838 secure = zone->secure;
16839 INSIST(secure != zone);
16840 TRYLOCK_ZONE(result, secure);
16841 if (result != ISC_R_SUCCESS) {
16842 UNLOCK_ZONE(zone);
16843 secure = NULL;
16844 isc_thread_yield();
16845 goto again;
16846 }
16847 }
16848 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
16849 result = zone_replacedb(zone, db, dump);
16850 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
16851 if (secure != NULL) {
16852 UNLOCK_ZONE(secure);
16853 }
16854 UNLOCK_ZONE(zone);
16855 return (result);
16856 }
16857
16858 static isc_result_t
16859 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
16860 dns_dbversion_t *ver;
16861 isc_result_t result;
16862 unsigned int soacount = 0;
16863 unsigned int nscount = 0;
16864
16865 /*
16866 * 'zone' and 'zone->db' locked by caller.
16867 */
16868 REQUIRE(DNS_ZONE_VALID(zone));
16869 REQUIRE(LOCKED_ZONE(zone));
16870 if (inline_raw(zone)) {
16871 REQUIRE(LOCKED_ZONE(zone->secure));
16872 }
16873
16874 result = zone_get_from_db(zone, db, &nscount, &soacount, NULL, NULL,
16875 NULL, NULL, NULL, NULL);
16876 if (result == ISC_R_SUCCESS) {
16877 if (soacount != 1) {
16878 dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records",
16879 soacount);
16880 result = DNS_R_BADZONE;
16881 }
16882 if (nscount == 0 && zone->type != dns_zone_key) {
16883 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
16884 result = DNS_R_BADZONE;
16885 }
16886 if (result != ISC_R_SUCCESS) {
16887 return (result);
16888 }
16889 } else {
16890 dns_zone_log(zone, ISC_LOG_ERROR,
16891 "retrieving SOA and NS records failed: %s",
16892 dns_result_totext(result));
16893 return (result);
16894 }
16895
16896 result = check_nsec3param(zone, db);
16897 if (result != ISC_R_SUCCESS) {
16898 return (result);
16899 }
16900
16901 ver = NULL;
16902 dns_db_currentversion(db, &ver);
16903
16904 /*
16905 * The initial version of a slave zone is always dumped;
16906 * subsequent versions may be journaled instead if this
16907 * is enabled in the configuration.
16908 */
16909 if (zone->db != NULL && zone->journal != NULL &&
16910 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
16911 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
16912 {
16913 uint32_t serial, oldserial;
16914
16915 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
16916
16917 result = dns_db_getsoaserial(db, ver, &serial);
16918 if (result != ISC_R_SUCCESS) {
16919 dns_zone_log(zone, ISC_LOG_ERROR,
16920 "ixfr-from-differences: unable to get "
16921 "new serial");
16922 goto fail;
16923 }
16924
16925 /*
16926 * This is checked in zone_postload() for master zones.
16927 */
16928 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
16929 &oldserial, NULL, NULL, NULL, NULL,
16930 NULL);
16931 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16932 RUNTIME_CHECK(soacount > 0U);
16933 if ((zone->type == dns_zone_slave ||
16934 (zone->type == dns_zone_redirect &&
16935 zone->masters != NULL)) &&
16936 !isc_serial_gt(serial, oldserial))
16937 {
16938 uint32_t serialmin, serialmax;
16939 serialmin = (oldserial + 1) & 0xffffffffU;
16940 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
16941 dns_zone_log(zone, ISC_LOG_ERROR,
16942 "ixfr-from-differences: failed: "
16943 "new serial (%u) out of range [%u - %u]",
16944 serial, serialmin, serialmax);
16945 result = ISC_R_RANGE;
16946 goto fail;
16947 }
16948
16949 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
16950 zone->journal);
16951 if (result != ISC_R_SUCCESS) {
16952 char strbuf[ISC_STRERRORSIZE];
16953 strerror_r(errno, strbuf, sizeof(strbuf));
16954 dns_zone_log(zone, ISC_LOG_ERROR,
16955 "ixfr-from-differences: failed: "
16956 "%s",
16957 strbuf);
16958 goto fallback;
16959 }
16960 if (dump) {
16961 zone_needdump(zone, DNS_DUMP_DELAY);
16962 } else {
16963 zone_journal_compact(zone, zone->db, serial);
16964 }
16965 if (zone->type == dns_zone_master && inline_raw(zone)) {
16966 zone_send_secureserial(zone, serial);
16967 }
16968 } else {
16969 fallback:
16970 if (dump && zone->masterfile != NULL) {
16971 /*
16972 * If DNS_ZONEFLG_FORCEXFER was set we don't want
16973 * to keep the old masterfile.
16974 */
16975 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
16976 remove(zone->masterfile) < 0 && errno != ENOENT)
16977 {
16978 char strbuf[ISC_STRERRORSIZE];
16979 strerror_r(errno, strbuf, sizeof(strbuf));
16980 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16981 DNS_LOGMODULE_ZONE,
16982 ISC_LOG_WARNING,
16983 "unable to remove masterfile "
16984 "'%s': '%s'",
16985 zone->masterfile, strbuf);
16986 }
16987 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) {
16988 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
16989 } else {
16990 zone_needdump(zone, 0);
16991 }
16992 }
16993 if (dump && zone->journal != NULL) {
16994 /*
16995 * The in-memory database just changed, and
16996 * because 'dump' is set, it didn't change by
16997 * being loaded from disk. Also, we have not
16998 * journaled diffs for this change.
16999 * Therefore, the on-disk journal is missing
17000 * the deltas for this change. Since it can
17001 * no longer be used to bring the zone
17002 * up-to-date, it is useless and should be
17003 * removed.
17004 */
17005 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17006 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
17007 "removing journal file");
17008 if (remove(zone->journal) < 0 && errno != ENOENT) {
17009 char strbuf[ISC_STRERRORSIZE];
17010 strerror_r(errno, strbuf, sizeof(strbuf));
17011 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17012 DNS_LOGMODULE_ZONE,
17013 ISC_LOG_WARNING,
17014 "unable to remove journal "
17015 "'%s': '%s'",
17016 zone->journal, strbuf);
17017 }
17018 }
17019
17020 if (inline_raw(zone)) {
17021 zone_send_securedb(zone, db);
17022 }
17023 }
17024
17025 dns_db_closeversion(db, &ver, false);
17026
17027 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
17028
17029 if (zone->db != NULL) {
17030 zone_detachdb(zone);
17031 }
17032 zone_attachdb(zone, db);
17033 dns_db_settask(zone->db, zone->task);
17034 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
17035 return (ISC_R_SUCCESS);
17036
17037 fail:
17038 dns_db_closeversion(db, &ver, false);
17039 return (result);
17040 }
17041
17042 /* The caller must hold the dblock as a writer. */
17043 static inline void
17044 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
17045 REQUIRE(zone->db == NULL && db != NULL);
17046
17047 dns_db_attach(db, &zone->db);
17048 }
17049
17050 /* The caller must hold the dblock as a writer. */
17051 static inline void
17052 zone_detachdb(dns_zone_t *zone) {
17053 REQUIRE(zone->db != NULL);
17054
17055 dns_db_detach(&zone->db);
17056 }
17057
17058 static void
17059 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
17060 isc_time_t now;
17061 bool again = false;
17062 unsigned int soacount;
17063 unsigned int nscount;
17064 uint32_t serial, refresh, retry, expire, minimum;
17065 isc_result_t xfrresult = result;
17066 bool free_needed;
17067 dns_zone_t *secure = NULL;
17068
17069 REQUIRE(DNS_ZONE_VALID(zone));
17070
17071 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17072 "zone transfer finished: %s", dns_result_totext(result));
17073
17074 /*
17075 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
17076 * could result in a deadlock due to a LOR so we will spin if we
17077 * can't obtain the both locks.
17078 */
17079 again:
17080 LOCK_ZONE(zone);
17081 if (inline_raw(zone)) {
17082 secure = zone->secure;
17083 INSIST(secure != zone);
17084 TRYLOCK_ZONE(result, secure);
17085 if (result != ISC_R_SUCCESS) {
17086 UNLOCK_ZONE(zone);
17087 secure = NULL;
17088 isc_thread_yield();
17089 goto again;
17090 }
17091 }
17092
17093 INSIST(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH));
17094 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
17095 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
17096
17097 TIME_NOW(&now);
17098 switch (xfrresult) {
17099 case ISC_R_SUCCESS:
17100 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
17101 /* FALLTHROUGH */
17102 case DNS_R_UPTODATE:
17103 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17104 /*
17105 * Has the zone expired underneath us?
17106 */
17107 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17108 if (zone->db == NULL) {
17109 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17110 goto same_master;
17111 }
17112
17113 /*
17114 * Update the zone structure's data from the actual
17115 * SOA received.
17116 */
17117 nscount = 0;
17118 soacount = 0;
17119 INSIST(zone->db != NULL);
17120 result = zone_get_from_db(zone, zone->db, &nscount, &soacount,
17121 &serial, &refresh, &retry, &expire,
17122 &minimum, NULL);
17123 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17124 if (result == ISC_R_SUCCESS) {
17125 if (soacount != 1) {
17126 dns_zone_log(zone, ISC_LOG_ERROR,
17127 "transferred zone "
17128 "has %d SOA records",
17129 soacount);
17130 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17131 {
17132 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17133 zone->retry = DNS_ZONE_DEFAULTRETRY;
17134 }
17135 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17136 zone_unload(zone);
17137 goto next_master;
17138 }
17139 if (nscount == 0) {
17140 dns_zone_log(zone, ISC_LOG_ERROR,
17141 "transferred zone "
17142 "has no NS records");
17143 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
17144 {
17145 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
17146 zone->retry = DNS_ZONE_DEFAULTRETRY;
17147 }
17148 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17149 zone_unload(zone);
17150 goto next_master;
17151 }
17152 zone->refresh = RANGE(refresh, zone->minrefresh,
17153 zone->maxrefresh);
17154 zone->retry = RANGE(retry, zone->minretry,
17155 zone->maxretry);
17156 zone->expire = RANGE(expire,
17157 zone->refresh + zone->retry,
17158 DNS_MAX_EXPIRE);
17159 zone->minimum = minimum;
17160 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
17161 }
17162
17163 /*
17164 * Set our next update/expire times.
17165 */
17166 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
17167 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
17168 zone->refreshtime = now;
17169 DNS_ZONE_TIME_ADD(&now, zone->expire,
17170 &zone->expiretime);
17171 } else {
17172 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
17173 &zone->refreshtime);
17174 DNS_ZONE_TIME_ADD(&now, zone->expire,
17175 &zone->expiretime);
17176 }
17177 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
17178 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
17179 if (zone->tsigkey != NULL) {
17180 char namebuf[DNS_NAME_FORMATSIZE];
17181 dns_name_format(&zone->tsigkey->name, namebuf,
17182 sizeof(namebuf));
17183 snprintf(buf, sizeof(buf), ": TSIG '%s'",
17184 namebuf);
17185 } else {
17186 buf[0] = '\0';
17187 }
17188 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17189 ISC_LOG_INFO, "transferred serial %u%s",
17190 serial, buf);
17191 if (inline_raw(zone)) {
17192 zone_send_secureserial(zone, serial);
17193 }
17194 }
17195
17196 /*
17197 * This is not necessary if we just performed a AXFR
17198 * however it is necessary for an IXFR / UPTODATE and
17199 * won't hurt with an AXFR.
17200 */
17201 if (zone->masterfile != NULL || zone->journal != NULL) {
17202 unsigned int delay = DNS_DUMP_DELAY;
17203
17204 result = ISC_R_FAILURE;
17205 if (zone->journal != NULL) {
17206 result = isc_file_settime(zone->journal, &now);
17207 }
17208 if (result != ISC_R_SUCCESS && zone->masterfile != NULL)
17209 {
17210 result = isc_file_settime(zone->masterfile,
17211 &now);
17212 }
17213
17214 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
17215 result == ISC_R_FILENOTFOUND)
17216 {
17217 delay = 0;
17218 }
17219
17220 if ((result == ISC_R_SUCCESS ||
17221 result == ISC_R_FILENOTFOUND) &&
17222 zone->masterfile != NULL)
17223 {
17224 zone_needdump(zone, delay);
17225 } else if (result != ISC_R_SUCCESS) {
17226 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17227 ISC_LOG_ERROR,
17228 "transfer: could not set file "
17229 "modification time of '%s': %s",
17230 zone->masterfile,
17231 dns_result_totext(result));
17232 }
17233 }
17234 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
17235 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
17236 break;
17237
17238 case DNS_R_BADIXFR:
17239 /* Force retry with AXFR. */
17240 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOIXFR);
17241 goto same_master;
17242
17243 case DNS_R_TOOMANYRECORDS:
17244 case DNS_R_VERIFYFAILURE:
17245 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
17246 inc_stats(zone, dns_zonestatscounter_xfrfail);
17247 break;
17248
17249 default:
17250 next_master:
17251 /*
17252 * Skip to next failed / untried master.
17253 */
17254 do {
17255 zone->curmaster++;
17256 } while (zone->curmaster < zone->masterscnt &&
17257 zone->mastersok[zone->curmaster]);
17258 /* FALLTHROUGH */
17259 same_master:
17260 if (zone->curmaster >= zone->masterscnt) {
17261 zone->curmaster = 0;
17262 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
17263 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC))
17264 {
17265 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17266 DNS_ZONE_SETFLAG(zone,
17267 DNS_ZONEFLG_USEALTXFRSRC);
17268 while (zone->curmaster < zone->masterscnt &&
17269 zone->mastersok[zone->curmaster]) {
17270 zone->curmaster++;
17271 }
17272 again = true;
17273 } else {
17274 DNS_ZONE_CLRFLAG(zone,
17275 DNS_ZONEFLG_USEALTXFRSRC);
17276 }
17277 } else {
17278 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
17279 again = true;
17280 }
17281 inc_stats(zone, dns_zonestatscounter_xfrfail);
17282 break;
17283 }
17284 zone_settimer(zone, &now);
17285
17286 /*
17287 * If creating the transfer object failed, zone->xfr is NULL.
17288 * Otherwise, we are called as the done callback of a zone
17289 * transfer object that just entered its shutting-down
17290 * state. Since we are no longer responsible for shutting
17291 * it down, we can detach our reference.
17292 */
17293 if (zone->xfr != NULL) {
17294 dns_xfrin_detach(&zone->xfr);
17295 }
17296
17297 if (zone->tsigkey != NULL) {
17298 dns_tsigkey_detach(&zone->tsigkey);
17299 }
17300
17301 /*
17302 * Handle any deferred journal compaction.
17303 */
17304 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
17305 dns_db_t *db = NULL;
17306 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
17307 zone_journal_compact(zone, db, zone->compact_serial);
17308 dns_db_detach(&db);
17309 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
17310 }
17311 }
17312
17313 if (secure != NULL) {
17314 UNLOCK_ZONE(secure);
17315 }
17316 /*
17317 * This transfer finishing freed up a transfer quota slot.
17318 * Let any other zones waiting for quota have it.
17319 */
17320 if (zone->zmgr != NULL &&
17321 zone->statelist == &zone->zmgr->xfrin_in_progress) {
17322 UNLOCK_ZONE(zone);
17323 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17324 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
17325 zone->statelist = NULL;
17326 zmgr_resume_xfrs(zone->zmgr, false);
17327 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
17328 LOCK_ZONE(zone);
17329 }
17330
17331 /*
17332 * Retry with a different server if necessary.
17333 */
17334 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17335 queue_soa_query(zone);
17336 }
17337
17338 isc_refcount_decrement(&zone->irefs);
17339 free_needed = exit_check(zone);
17340 UNLOCK_ZONE(zone);
17341 if (free_needed) {
17342 zone_free(zone);
17343 }
17344 }
17345
17346 static void
17347 zone_loaddone(void *arg, isc_result_t result) {
17348 static char me[] = "zone_loaddone";
17349 dns_load_t *load = arg;
17350 dns_zone_t *zone;
17351 isc_result_t tresult;
17352 dns_zone_t *secure = NULL;
17353
17354 REQUIRE(DNS_LOAD_VALID(load));
17355 zone = load->zone;
17356
17357 ENTER;
17358
17359 /*
17360 * If zone loading failed, remove the update db callbacks prior
17361 * to calling the list of callbacks in the zone load structure.
17362 */
17363 if (result != ISC_R_SUCCESS) {
17364 dns_zone_rpz_disable_db(zone, load->db);
17365 dns_zone_catz_disable_db(zone, load->db);
17366 }
17367
17368 tresult = dns_db_endload(load->db, &load->callbacks);
17369 if (tresult != ISC_R_SUCCESS &&
17370 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
17371 {
17372 result = tresult;
17373 }
17374
17375 /*
17376 * Lock hierarchy: zmgr, zone, raw.
17377 */
17378 again:
17379 LOCK_ZONE(zone);
17380 INSIST(zone != zone->raw);
17381 if (inline_secure(zone)) {
17382 LOCK_ZONE(zone->raw);
17383 } else if (inline_raw(zone)) {
17384 secure = zone->secure;
17385 TRYLOCK_ZONE(tresult, secure);
17386 if (tresult != ISC_R_SUCCESS) {
17387 UNLOCK_ZONE(zone);
17388 secure = NULL;
17389 isc_thread_yield();
17390 goto again;
17391 }
17392 }
17393 (void)zone_postload(zone, load->db, load->loadtime, result);
17394 zonemgr_putio(&zone->readio);
17395 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
17396 zone_idetach(&load->callbacks.zone);
17397 /*
17398 * Leave the zone frozen if the reload fails.
17399 */
17400 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
17401 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
17402 {
17403 zone->update_disabled = false;
17404 }
17405 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
17406 if (inline_secure(zone)) {
17407 UNLOCK_ZONE(zone->raw);
17408 } else if (secure != NULL) {
17409 UNLOCK_ZONE(secure);
17410 }
17411 UNLOCK_ZONE(zone);
17412
17413 load->magic = 0;
17414 dns_db_detach(&load->db);
17415 if (load->zone->lctx != NULL) {
17416 dns_loadctx_detach(&load->zone->lctx);
17417 }
17418 dns_zone_idetach(&load->zone);
17419 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
17420 }
17421
17422 void
17423 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
17424 REQUIRE(DNS_ZONE_VALID(zone));
17425 REQUIRE(table != NULL);
17426 REQUIRE(*table == NULL);
17427
17428 LOCK_ZONE(zone);
17429 if (zone->ssutable != NULL) {
17430 dns_ssutable_attach(zone->ssutable, table);
17431 }
17432 UNLOCK_ZONE(zone);
17433 }
17434
17435 void
17436 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
17437 REQUIRE(DNS_ZONE_VALID(zone));
17438
17439 LOCK_ZONE(zone);
17440 if (zone->ssutable != NULL) {
17441 dns_ssutable_detach(&zone->ssutable);
17442 }
17443 if (table != NULL) {
17444 dns_ssutable_attach(table, &zone->ssutable);
17445 }
17446 UNLOCK_ZONE(zone);
17447 }
17448
17449 void
17450 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17451 REQUIRE(DNS_ZONE_VALID(zone));
17452
17453 zone->sigvalidityinterval = interval;
17454 }
17455
17456 uint32_t
17457 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
17458 REQUIRE(DNS_ZONE_VALID(zone));
17459
17460 return (zone->sigvalidityinterval);
17461 }
17462
17463 void
17464 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
17465 REQUIRE(DNS_ZONE_VALID(zone));
17466
17467 zone->keyvalidityinterval = interval;
17468 }
17469
17470 uint32_t
17471 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
17472 REQUIRE(DNS_ZONE_VALID(zone));
17473
17474 return (zone->keyvalidityinterval);
17475 }
17476
17477 void
17478 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
17479 isc_time_t now;
17480
17481 REQUIRE(DNS_ZONE_VALID(zone));
17482
17483 LOCK_ZONE(zone);
17484 zone->sigresigninginterval = interval;
17485 set_resigntime(zone);
17486 if (zone->task != NULL) {
17487 TIME_NOW(&now);
17488 zone_settimer(zone, &now);
17489 }
17490 UNLOCK_ZONE(zone);
17491 }
17492
17493 uint32_t
17494 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
17495 REQUIRE(DNS_ZONE_VALID(zone));
17496
17497 return (zone->sigresigninginterval);
17498 }
17499
17500 static void
17501 queue_xfrin(dns_zone_t *zone) {
17502 const char me[] = "queue_xfrin";
17503 isc_result_t result;
17504 dns_zonemgr_t *zmgr = zone->zmgr;
17505
17506 ENTER;
17507
17508 INSIST(zone->statelist == NULL);
17509
17510 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17511 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
17512 isc_refcount_increment0(&zone->irefs);
17513 zone->statelist = &zmgr->waiting_for_xfrin;
17514 result = zmgr_start_xfrin_ifquota(zmgr, zone);
17515 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
17516
17517 if (result == ISC_R_QUOTA) {
17518 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
17519 "zone transfer deferred due to quota");
17520 } else if (result != ISC_R_SUCCESS) {
17521 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
17522 "starting zone transfer: %s",
17523 isc_result_totext(result));
17524 }
17525 }
17526
17527 /*
17528 * This event callback is called when a zone has received
17529 * any necessary zone transfer quota. This is the time
17530 * to go ahead and start the transfer.
17531 */
17532 static void
17533 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
17534 isc_result_t result = ISC_R_SUCCESS;
17535 dns_peer_t *peer = NULL;
17536 char master[ISC_SOCKADDR_FORMATSIZE];
17537 char source[ISC_SOCKADDR_FORMATSIZE];
17538 dns_rdatatype_t xfrtype;
17539 dns_zone_t *zone = event->ev_arg;
17540 isc_netaddr_t masterip;
17541 isc_sockaddr_t sourceaddr;
17542 isc_sockaddr_t masteraddr;
17543 isc_time_t now;
17544 const char *soa_before = "";
17545 isc_dscp_t dscp = -1;
17546 bool loaded;
17547
17548 UNUSED(task);
17549
17550 INSIST(task == zone->task);
17551
17552 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17553 result = ISC_R_CANCELED;
17554 goto cleanup;
17555 }
17556
17557 TIME_NOW(&now);
17558
17559 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
17560 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
17561 &zone->sourceaddr, &now))
17562 {
17563 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
17564 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
17565 "got_transfer_quota: skipping zone transfer as "
17566 "master %s (source %s) is unreachable (cached)",
17567 master, source);
17568 result = ISC_R_CANCELED;
17569 goto cleanup;
17570 }
17571
17572 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
17573 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
17574
17575 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
17576 soa_before = "SOA before ";
17577 }
17578 /*
17579 * Decide whether we should request IXFR or AXFR.
17580 */
17581 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17582 loaded = (zone->db != NULL);
17583 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17584
17585 if (!loaded) {
17586 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17587 "no database exists yet, requesting AXFR of "
17588 "initial version from %s",
17589 master);
17590 xfrtype = dns_rdatatype_axfr;
17591 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
17592 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17593 "forced reload, requesting AXFR of "
17594 "initial version from %s",
17595 master);
17596 xfrtype = dns_rdatatype_axfr;
17597 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOIXFR)) {
17598 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_DEBUG(1),
17599 "retrying with AXFR from %s due to "
17600 "previous IXFR failure",
17601 master);
17602 xfrtype = dns_rdatatype_axfr;
17603 LOCK_ZONE(zone);
17604 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOIXFR);
17605 UNLOCK_ZONE(zone);
17606 } else {
17607 bool use_ixfr = true;
17608 if (peer != NULL) {
17609 result = dns_peer_getrequestixfr(peer, &use_ixfr);
17610 }
17611 if (peer == NULL || result != ISC_R_SUCCESS) {
17612 use_ixfr = zone->requestixfr;
17613 }
17614 if (!use_ixfr) {
17615 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17616 ISC_LOG_DEBUG(1),
17617 "IXFR disabled, "
17618 "requesting %sAXFR from %s",
17619 soa_before, master);
17620 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR)) {
17621 xfrtype = dns_rdatatype_soa;
17622 } else {
17623 xfrtype = dns_rdatatype_axfr;
17624 }
17625 } else {
17626 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
17627 ISC_LOG_DEBUG(1),
17628 "requesting IXFR from %s", master);
17629 xfrtype = dns_rdatatype_ixfr;
17630 }
17631 }
17632
17633 /*
17634 * Determine if we should attempt to sign the request with TSIG.
17635 */
17636 result = ISC_R_NOTFOUND;
17637
17638 /*
17639 * First, look for a tsig key in the master statement, then
17640 * try for a server key.
17641 */
17642 if ((zone->masterkeynames != NULL) &&
17643 (zone->masterkeynames[zone->curmaster] != NULL))
17644 {
17645 dns_view_t *view = dns_zone_getview(zone);
17646 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
17647 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
17648 }
17649 if (zone->tsigkey == NULL) {
17650 result = dns_view_getpeertsig(zone->view, &masterip,
17651 &zone->tsigkey);
17652 }
17653
17654 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
17655 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
17656 "could not get TSIG key for zone transfer: %s",
17657 isc_result_totext(result));
17658 }
17659
17660 if (zone->masterdscps != NULL) {
17661 dscp = zone->masterdscps[zone->curmaster];
17662 }
17663
17664 LOCK_ZONE(zone);
17665 masteraddr = zone->masteraddr;
17666 sourceaddr = zone->sourceaddr;
17667 switch (isc_sockaddr_pf(&masteraddr)) {
17668 case PF_INET:
17669 if (dscp == -1) {
17670 dscp = zone->xfrsource4dscp;
17671 }
17672 break;
17673 case PF_INET6:
17674 if (dscp == -1) {
17675 dscp = zone->xfrsource6dscp;
17676 }
17677 break;
17678 default:
17679 INSIST(0);
17680 ISC_UNREACHABLE();
17681 }
17682 UNLOCK_ZONE(zone);
17683 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
17684 result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr, dscp,
17685 zone->tsigkey, zone->mctx,
17686 zone->zmgr->timermgr, zone->zmgr->socketmgr,
17687 zone->task, zone_xfrdone, &zone->xfr);
17688 if (result == ISC_R_SUCCESS) {
17689 LOCK_ZONE(zone);
17690 if (xfrtype == dns_rdatatype_axfr) {
17691 if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
17692 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
17693 } else {
17694 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
17695 }
17696 } else if (xfrtype == dns_rdatatype_ixfr) {
17697 if (isc_sockaddr_pf(&masteraddr) == PF_INET) {
17698 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
17699 } else {
17700 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
17701 }
17702 }
17703 UNLOCK_ZONE(zone);
17704 }
17705 cleanup:
17706 /*
17707 * Any failure in this function is handled like a failed
17708 * zone transfer. This ensures that we get removed from
17709 * zmgr->xfrin_in_progress.
17710 */
17711 if (result != ISC_R_SUCCESS) {
17712 zone_xfrdone(zone, result);
17713 }
17714
17715 isc_event_free(&event);
17716 }
17717
17718 /*
17719 * Update forwarding support.
17720 */
17721
17722 static void
17723 forward_destroy(dns_forward_t *forward) {
17724 forward->magic = 0;
17725 if (forward->request != NULL) {
17726 dns_request_destroy(&forward->request);
17727 }
17728 if (forward->msgbuf != NULL) {
17729 isc_buffer_free(&forward->msgbuf);
17730 }
17731 if (forward->zone != NULL) {
17732 LOCK(&forward->zone->lock);
17733 if (ISC_LINK_LINKED(forward, link)) {
17734 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
17735 }
17736 UNLOCK(&forward->zone->lock);
17737 dns_zone_idetach(&forward->zone);
17738 }
17739 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
17740 }
17741
17742 static isc_result_t
17743 sendtomaster(dns_forward_t *forward) {
17744 isc_result_t result;
17745 isc_sockaddr_t src;
17746 isc_dscp_t dscp = -1;
17747
17748 LOCK_ZONE(forward->zone);
17749
17750 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
17751 UNLOCK_ZONE(forward->zone);
17752 return (ISC_R_CANCELED);
17753 }
17754
17755 if (forward->which >= forward->zone->masterscnt) {
17756 UNLOCK_ZONE(forward->zone);
17757 return (ISC_R_NOMORE);
17758 }
17759
17760 forward->addr = forward->zone->masters[forward->which];
17761 /*
17762 * Always use TCP regardless of whether the original update
17763 * used TCP.
17764 * XXX The timeout may but a bit small if we are far down a
17765 * transfer graph and the master has to try several masters.
17766 */
17767 switch (isc_sockaddr_pf(&forward->addr)) {
17768 case PF_INET:
17769 src = forward->zone->xfrsource4;
17770 dscp = forward->zone->xfrsource4dscp;
17771 break;
17772 case PF_INET6:
17773 src = forward->zone->xfrsource6;
17774 dscp = forward->zone->xfrsource6dscp;
17775 break;
17776 default:
17777 result = ISC_R_NOTIMPLEMENTED;
17778 goto unlock;
17779 }
17780 result = dns_request_createraw(forward->zone->view->requestmgr,
17781 forward->msgbuf, &src, &forward->addr,
17782 dscp, forward->options, 15 /* XXX */, 0,
17783 0, forward->zone->task, forward_callback,
17784 forward, &forward->request);
17785 if (result == ISC_R_SUCCESS) {
17786 if (!ISC_LINK_LINKED(forward, link)) {
17787 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
17788 }
17789 }
17790
17791 unlock:
17792 UNLOCK_ZONE(forward->zone);
17793 return (result);
17794 }
17795
17796 static void
17797 forward_callback(isc_task_t *task, isc_event_t *event) {
17798 const char me[] = "forward_callback";
17799 dns_requestevent_t *revent = (dns_requestevent_t *)event;
17800 dns_message_t *msg = NULL;
17801 char master[ISC_SOCKADDR_FORMATSIZE];
17802 isc_result_t result;
17803 dns_forward_t *forward;
17804 dns_zone_t *zone;
17805
17806 UNUSED(task);
17807
17808 forward = revent->ev_arg;
17809 INSIST(DNS_FORWARD_VALID(forward));
17810 zone = forward->zone;
17811 INSIST(DNS_ZONE_VALID(zone));
17812
17813 ENTER;
17814
17815 isc_sockaddr_format(&forward->addr, master, sizeof(master));
17816
17817 if (revent->result != ISC_R_SUCCESS) {
17818 dns_zone_log(zone, ISC_LOG_INFO,
17819 "could not forward dynamic update to %s: %s",
17820 master, dns_result_totext(revent->result));
17821 goto next_master;
17822 }
17823
17824 dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
17825
17826 result = dns_request_getresponse(revent->request, msg,
17827 DNS_MESSAGEPARSE_PRESERVEORDER |
17828 DNS_MESSAGEPARSE_CLONEBUFFER);
17829 if (result != ISC_R_SUCCESS) {
17830 goto next_master;
17831 }
17832
17833 switch (msg->rcode) {
17834 /*
17835 * Pass these rcodes back to client.
17836 */
17837 case dns_rcode_noerror:
17838 case dns_rcode_yxdomain:
17839 case dns_rcode_yxrrset:
17840 case dns_rcode_nxrrset:
17841 case dns_rcode_refused:
17842 case dns_rcode_nxdomain: {
17843 char rcode[128];
17844 isc_buffer_t rb;
17845
17846 isc_buffer_init(&rb, rcode, sizeof(rcode));
17847 (void)dns_rcode_totext(msg->rcode, &rb);
17848 dns_zone_log(zone, ISC_LOG_INFO,
17849 "forwarded dynamic update: "
17850 "master %s returned: %.*s",
17851 master, (int)rb.used, rcode);
17852 break;
17853 }
17854
17855 /* These should not occur if the primaries/zone are valid. */
17856 case dns_rcode_notzone:
17857 case dns_rcode_notauth: {
17858 char rcode[128];
17859 isc_buffer_t rb;
17860
17861 isc_buffer_init(&rb, rcode, sizeof(rcode));
17862 (void)dns_rcode_totext(msg->rcode, &rb);
17863 dns_zone_log(zone, ISC_LOG_WARNING,
17864 "forwarding dynamic update: "
17865 "unexpected response: master %s returned: %.*s",
17866 master, (int)rb.used, rcode);
17867 goto next_master;
17868 }
17869
17870 /* Try another server for these rcodes. */
17871 case dns_rcode_formerr:
17872 case dns_rcode_servfail:
17873 case dns_rcode_notimp:
17874 case dns_rcode_badvers:
17875 default:
17876 goto next_master;
17877 }
17878
17879 /* call callback */
17880 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
17881 msg = NULL;
17882 dns_request_destroy(&forward->request);
17883 forward_destroy(forward);
17884 isc_event_free(&event);
17885 return;
17886
17887 next_master:
17888 if (msg != NULL) {
17889 dns_message_detach(&msg);
17890 }
17891 isc_event_free(&event);
17892 forward->which++;
17893 dns_request_destroy(&forward->request);
17894 result = sendtomaster(forward);
17895 if (result != ISC_R_SUCCESS) {
17896 /* call callback */
17897 dns_zone_log(zone, ISC_LOG_DEBUG(3),
17898 "exhausted dynamic update forwarder list");
17899 (forward->callback)(forward->callback_arg, result, NULL);
17900 forward_destroy(forward);
17901 }
17902 }
17903
17904 isc_result_t
17905 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
17906 dns_updatecallback_t callback, void *callback_arg) {
17907 dns_forward_t *forward;
17908 isc_result_t result;
17909 isc_region_t *mr;
17910
17911 REQUIRE(DNS_ZONE_VALID(zone));
17912 REQUIRE(msg != NULL);
17913 REQUIRE(callback != NULL);
17914
17915 forward = isc_mem_get(zone->mctx, sizeof(*forward));
17916
17917 forward->request = NULL;
17918 forward->zone = NULL;
17919 forward->msgbuf = NULL;
17920 forward->which = 0;
17921 forward->mctx = 0;
17922 forward->callback = callback;
17923 forward->callback_arg = callback_arg;
17924 ISC_LINK_INIT(forward, link);
17925 forward->magic = FORWARD_MAGIC;
17926 forward->options = DNS_REQUESTOPT_TCP;
17927 /*
17928 * If we have a SIG(0) signed message we need to preserve the
17929 * query id as that is included in the SIG(0) computation.
17930 */
17931 if (msg->sig0 != NULL) {
17932 forward->options |= DNS_REQUESTOPT_FIXEDID;
17933 }
17934
17935 mr = dns_message_getrawmessage(msg);
17936 if (mr == NULL) {
17937 result = ISC_R_UNEXPECTEDEND;
17938 goto cleanup;
17939 }
17940
17941 isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
17942 result = isc_buffer_copyregion(forward->msgbuf, mr);
17943 if (result != ISC_R_SUCCESS) {
17944 goto cleanup;
17945 }
17946
17947 isc_mem_attach(zone->mctx, &forward->mctx);
17948 dns_zone_iattach(zone, &forward->zone);
17949 result = sendtomaster(forward);
17950
17951 cleanup:
17952 if (result != ISC_R_SUCCESS) {
17953 forward_destroy(forward);
17954 }
17955 return (result);
17956 }
17957
17958 isc_result_t
17959 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
17960 REQUIRE(DNS_ZONE_VALID(zone));
17961 REQUIRE(next != NULL && *next == NULL);
17962
17963 *next = ISC_LIST_NEXT(zone, link);
17964 if (*next == NULL) {
17965 return (ISC_R_NOMORE);
17966 } else {
17967 return (ISC_R_SUCCESS);
17968 }
17969 }
17970
17971 isc_result_t
17972 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
17973 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17974 REQUIRE(first != NULL && *first == NULL);
17975
17976 *first = ISC_LIST_HEAD(zmgr->zones);
17977 if (*first == NULL) {
17978 return (ISC_R_NOMORE);
17979 } else {
17980 return (ISC_R_SUCCESS);
17981 }
17982 }
17983
17984 /***
17985 *** Zone manager.
17986 ***/
17987
17988 isc_result_t
17989 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
17990 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
17991 dns_zonemgr_t **zmgrp) {
17992 dns_zonemgr_t *zmgr;
17993 isc_result_t result;
17994
17995 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
17996 zmgr->mctx = NULL;
17997 isc_refcount_init(&zmgr->refs, 1);
17998 isc_mem_attach(mctx, &zmgr->mctx);
17999 zmgr->taskmgr = taskmgr;
18000 zmgr->timermgr = timermgr;
18001 zmgr->socketmgr = socketmgr;
18002 zmgr->zonetasks = NULL;
18003 zmgr->loadtasks = NULL;
18004 zmgr->mctxpool = NULL;
18005 zmgr->task = NULL;
18006 zmgr->notifyrl = NULL;
18007 zmgr->refreshrl = NULL;
18008 zmgr->startupnotifyrl = NULL;
18009 zmgr->startuprefreshrl = NULL;
18010 ISC_LIST_INIT(zmgr->zones);
18011 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
18012 ISC_LIST_INIT(zmgr->xfrin_in_progress);
18013 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
18014 isc_rwlock_init(&zmgr->rwlock, 0, 0);
18015
18016 zmgr->transfersin = 10;
18017 zmgr->transfersperns = 2;
18018
18019 /* Unreachable lock. */
18020 isc_rwlock_init(&zmgr->urlock, 0, 0);
18021
18022 /* Create a single task for queueing of SOA queries. */
18023 result = isc_task_create(taskmgr, 1, &zmgr->task);
18024 if (result != ISC_R_SUCCESS) {
18025 goto free_urlock;
18026 }
18027
18028 isc_task_setname(zmgr->task, "zmgr", zmgr);
18029 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18030 &zmgr->notifyrl);
18031 if (result != ISC_R_SUCCESS) {
18032 goto free_task;
18033 }
18034
18035 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18036 &zmgr->refreshrl);
18037 if (result != ISC_R_SUCCESS) {
18038 goto free_notifyrl;
18039 }
18040
18041 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18042 &zmgr->startupnotifyrl);
18043 if (result != ISC_R_SUCCESS) {
18044 goto free_refreshrl;
18045 }
18046
18047 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
18048 &zmgr->startuprefreshrl);
18049 if (result != ISC_R_SUCCESS) {
18050 goto free_startupnotifyrl;
18051 }
18052
18053 /* default to 20 refresh queries / notifies per second. */
18054 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
18055 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
18056 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
18057 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
18058 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
18059 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
18060
18061 zmgr->iolimit = 1;
18062 zmgr->ioactive = 0;
18063 ISC_LIST_INIT(zmgr->high);
18064 ISC_LIST_INIT(zmgr->low);
18065
18066 isc_mutex_init(&zmgr->iolock);
18067
18068 zmgr->magic = ZONEMGR_MAGIC;
18069
18070 *zmgrp = zmgr;
18071 return (ISC_R_SUCCESS);
18072
18073 #if 0
18074 free_iolock:
18075 isc_mutex_destroy(&zmgr->iolock);
18076 #endif /* if 0 */
18077 free_startupnotifyrl:
18078 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18079 free_refreshrl:
18080 isc_ratelimiter_detach(&zmgr->refreshrl);
18081 free_notifyrl:
18082 isc_ratelimiter_detach(&zmgr->notifyrl);
18083 free_task:
18084 isc_task_detach(&zmgr->task);
18085 free_urlock:
18086 isc_rwlock_destroy(&zmgr->urlock);
18087 isc_rwlock_destroy(&zmgr->rwlock);
18088 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18089 isc_mem_detach(&mctx);
18090 return (result);
18091 }
18092
18093 isc_result_t
18094 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
18095 isc_result_t result;
18096 isc_mem_t *mctx = NULL;
18097 dns_zone_t *zone = NULL;
18098 void *item;
18099
18100 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18101 REQUIRE(zonep != NULL && *zonep == NULL);
18102
18103 if (zmgr->mctxpool == NULL) {
18104 return (ISC_R_FAILURE);
18105 }
18106
18107 item = isc_pool_get(zmgr->mctxpool);
18108 if (item == NULL) {
18109 return (ISC_R_FAILURE);
18110 }
18111
18112 isc_mem_attach((isc_mem_t *)item, &mctx);
18113 result = dns_zone_create(&zone, mctx);
18114 isc_mem_detach(&mctx);
18115
18116 if (result == ISC_R_SUCCESS) {
18117 *zonep = zone;
18118 }
18119
18120 return (result);
18121 }
18122
18123 isc_result_t
18124 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18125 isc_result_t result;
18126
18127 REQUIRE(DNS_ZONE_VALID(zone));
18128 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18129
18130 if (zmgr->zonetasks == NULL) {
18131 return (ISC_R_FAILURE);
18132 }
18133
18134 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18135 LOCK_ZONE(zone);
18136 REQUIRE(zone->task == NULL);
18137 REQUIRE(zone->timer == NULL);
18138 REQUIRE(zone->zmgr == NULL);
18139
18140 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
18141 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
18142
18143 /*
18144 * Set the task name. The tag will arbitrarily point to one
18145 * of the zones sharing the task (in practice, the one
18146 * to be managed last).
18147 */
18148 isc_task_setname(zone->task, "zone", zone);
18149 isc_task_setname(zone->loadtask, "loadzone", zone);
18150
18151 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
18152 NULL, zone->task, zone_timer, zone,
18153 &zone->timer);
18154
18155 if (result != ISC_R_SUCCESS) {
18156 goto cleanup_tasks;
18157 }
18158
18159 /*
18160 * The timer "holds" a iref.
18161 */
18162 isc_refcount_increment0(&zone->irefs);
18163
18164 ISC_LIST_APPEND(zmgr->zones, zone, link);
18165 zone->zmgr = zmgr;
18166 isc_refcount_increment(&zmgr->refs);
18167
18168 goto unlock;
18169
18170 cleanup_tasks:
18171 isc_task_detach(&zone->loadtask);
18172 isc_task_detach(&zone->task);
18173
18174 unlock:
18175 UNLOCK_ZONE(zone);
18176 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18177 return (result);
18178 }
18179
18180 void
18181 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18182 bool free_now = false;
18183
18184 REQUIRE(DNS_ZONE_VALID(zone));
18185 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18186 REQUIRE(zone->zmgr == zmgr);
18187
18188 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18189 LOCK_ZONE(zone);
18190
18191 ISC_LIST_UNLINK(zmgr->zones, zone, link);
18192 zone->zmgr = NULL;
18193
18194 if (isc_refcount_decrement(&zmgr->refs) == 1) {
18195 free_now = true;
18196 }
18197
18198 UNLOCK_ZONE(zone);
18199 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18200
18201 if (free_now) {
18202 zonemgr_free(zmgr);
18203 }
18204 ENSURE(zone->zmgr == NULL);
18205 }
18206
18207 void
18208 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
18209 REQUIRE(DNS_ZONEMGR_VALID(source));
18210 REQUIRE(target != NULL && *target == NULL);
18211
18212 isc_refcount_increment(&source->refs);
18213
18214 *target = source;
18215 }
18216
18217 void
18218 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
18219 dns_zonemgr_t *zmgr;
18220
18221 REQUIRE(zmgrp != NULL);
18222 zmgr = *zmgrp;
18223 *zmgrp = NULL;
18224 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18225
18226 if (isc_refcount_decrement(&zmgr->refs) == 1) {
18227 zonemgr_free(zmgr);
18228 }
18229 }
18230
18231 isc_result_t
18232 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
18233 dns_zone_t *p;
18234
18235 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18236
18237 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18238 for (p = ISC_LIST_HEAD(zmgr->zones); p != NULL;
18239 p = ISC_LIST_NEXT(p, link)) {
18240 dns_zone_maintenance(p);
18241 }
18242 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18243
18244 /*
18245 * Recent configuration changes may have increased the
18246 * amount of available transfers quota. Make sure any
18247 * transfers currently blocked on quota get started if
18248 * possible.
18249 */
18250 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18251 zmgr_resume_xfrs(zmgr, true);
18252 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18253 return (ISC_R_SUCCESS);
18254 }
18255
18256 void
18257 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
18258 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18259
18260 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18261 zmgr_resume_xfrs(zmgr, true);
18262 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18263 }
18264
18265 void
18266 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
18267 dns_zone_t *zone;
18268
18269 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18270
18271 isc_ratelimiter_shutdown(zmgr->notifyrl);
18272 isc_ratelimiter_shutdown(zmgr->refreshrl);
18273 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
18274 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
18275
18276 if (zmgr->task != NULL) {
18277 isc_task_destroy(&zmgr->task);
18278 }
18279 if (zmgr->zonetasks != NULL) {
18280 isc_taskpool_destroy(&zmgr->zonetasks);
18281 }
18282 if (zmgr->loadtasks != NULL) {
18283 isc_taskpool_destroy(&zmgr->loadtasks);
18284 }
18285 if (zmgr->mctxpool != NULL) {
18286 isc_pool_destroy(&zmgr->mctxpool);
18287 }
18288
18289 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18290 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
18291 zone = ISC_LIST_NEXT(zone, link))
18292 {
18293 LOCK_ZONE(zone);
18294 forward_cancel(zone);
18295 UNLOCK_ZONE(zone);
18296 }
18297 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
18298 }
18299
18300 static isc_result_t
18301 mctxinit(void **target, void *arg) {
18302 isc_mem_t *mctx = NULL;
18303
18304 UNUSED(arg);
18305
18306 REQUIRE(target != NULL && *target == NULL);
18307
18308 isc_mem_create(&mctx);
18309 isc_mem_setname(mctx, "zonemgr-pool", NULL);
18310
18311 *target = mctx;
18312 return (ISC_R_SUCCESS);
18313 }
18314
18315 static void
18316 mctxfree(void **target) {
18317 isc_mem_t *mctx = *(isc_mem_t **)target;
18318 isc_mem_detach(&mctx);
18319 *target = NULL;
18320 }
18321
18322 #define ZONES_PER_TASK 100
18323 #define ZONES_PER_MCTX 1000
18324
18325 isc_result_t
18326 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
18327 isc_result_t result;
18328 int ntasks = num_zones / ZONES_PER_TASK;
18329 int nmctx = num_zones / ZONES_PER_MCTX;
18330 isc_taskpool_t *pool = NULL;
18331 isc_pool_t *mctxpool = NULL;
18332
18333 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18334
18335 /*
18336 * For anything fewer than 1000 zones we use 10 tasks in
18337 * the task pools. More than that, and we'll scale at one
18338 * task per 100 zones. Similarly, for anything smaller than
18339 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
18340 */
18341 if (ntasks < 10) {
18342 ntasks = 10;
18343 }
18344 if (nmctx < 2) {
18345 nmctx = 2;
18346 }
18347
18348 /* Create or resize the zone task pools. */
18349 if (zmgr->zonetasks == NULL) {
18350 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
18351 2, &pool);
18352 } else {
18353 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
18354 }
18355
18356 if (result == ISC_R_SUCCESS) {
18357 zmgr->zonetasks = pool;
18358 }
18359
18360 pool = NULL;
18361 if (zmgr->loadtasks == NULL) {
18362 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx, ntasks,
18363 2, &pool);
18364 } else {
18365 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
18366 }
18367
18368 if (result == ISC_R_SUCCESS) {
18369 zmgr->loadtasks = pool;
18370 }
18371
18372 /*
18373 * We always set all tasks in the zone-load task pool to
18374 * privileged. This prevents other tasks in the system from
18375 * running while the server task manager is in privileged
18376 * mode.
18377 *
18378 * NOTE: If we start using task privileges for any other
18379 * part of the system than zone tasks, then this will need to be
18380 * revisted. In that case we'd want to turn on privileges for
18381 * zone tasks only when we were loading, and turn them off the
18382 * rest of the time. For now, however, it's okay to just
18383 * set it and forget it.
18384 */
18385 isc_taskpool_setprivilege(zmgr->loadtasks, true);
18386
18387 /* Create or resize the zone memory context pool. */
18388 if (zmgr->mctxpool == NULL) {
18389 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree, mctxinit,
18390 NULL, &mctxpool);
18391 } else {
18392 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
18393 }
18394
18395 if (result == ISC_R_SUCCESS) {
18396 zmgr->mctxpool = mctxpool;
18397 }
18398
18399 return (result);
18400 }
18401
18402 static void
18403 zonemgr_free(dns_zonemgr_t *zmgr) {
18404 isc_mem_t *mctx;
18405
18406 INSIST(ISC_LIST_EMPTY(zmgr->zones));
18407
18408 zmgr->magic = 0;
18409
18410 isc_refcount_destroy(&zmgr->refs);
18411 isc_mutex_destroy(&zmgr->iolock);
18412 isc_ratelimiter_detach(&zmgr->notifyrl);
18413 isc_ratelimiter_detach(&zmgr->refreshrl);
18414 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
18415 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
18416
18417 isc_rwlock_destroy(&zmgr->urlock);
18418 isc_rwlock_destroy(&zmgr->rwlock);
18419 mctx = zmgr->mctx;
18420 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
18421 isc_mem_detach(&mctx);
18422 }
18423
18424 void
18425 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
18426 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18427
18428 zmgr->transfersin = value;
18429 }
18430
18431 uint32_t
18432 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
18433 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18434
18435 return (zmgr->transfersin);
18436 }
18437
18438 void
18439 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
18440 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18441
18442 zmgr->transfersperns = value;
18443 }
18444
18445 uint32_t
18446 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
18447 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18448
18449 return (zmgr->transfersperns);
18450 }
18451
18452 /*
18453 * Try to start a new incoming zone transfer to fill a quota
18454 * slot that was just vacated.
18455 *
18456 * Requires:
18457 * The zone manager is locked by the caller.
18458 */
18459 static void
18460 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
18461 dns_zone_t *zone;
18462 dns_zone_t *next;
18463
18464 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin); zone != NULL;
18465 zone = next) {
18466 isc_result_t result;
18467 next = ISC_LIST_NEXT(zone, statelink);
18468 result = zmgr_start_xfrin_ifquota(zmgr, zone);
18469 if (result == ISC_R_SUCCESS) {
18470 if (multi) {
18471 continue;
18472 }
18473 /*
18474 * We successfully filled the slot. We're done.
18475 */
18476 break;
18477 } else if (result == ISC_R_QUOTA) {
18478 /*
18479 * Not enough quota. This is probably the per-server
18480 * quota, because we usually get called when a unit of
18481 * global quota has just been freed. Try the next
18482 * zone, it may succeed if it uses another master.
18483 */
18484 continue;
18485 } else {
18486 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN,
18487 ISC_LOG_DEBUG(1),
18488 "starting zone transfer: %s",
18489 isc_result_totext(result));
18490 break;
18491 }
18492 }
18493 }
18494
18495 /*
18496 * Try to start an incoming zone transfer for 'zone', quota permitting.
18497 *
18498 * Requires:
18499 * The zone manager is locked by the caller.
18500 *
18501 * Returns:
18502 * ISC_R_SUCCESS There was enough quota and we attempted to
18503 * start a transfer. zone_xfrdone() has been or will
18504 * be called.
18505 * ISC_R_QUOTA Not enough quota.
18506 * Others Failure.
18507 */
18508 static isc_result_t
18509 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
18510 dns_peer_t *peer = NULL;
18511 isc_netaddr_t masterip;
18512 uint32_t nxfrsin, nxfrsperns;
18513 dns_zone_t *x;
18514 uint32_t maxtransfersin, maxtransfersperns;
18515 isc_event_t *e;
18516
18517 /*
18518 * If we are exiting just pretend we got quota so the zone will
18519 * be cleaned up in the zone's task context.
18520 */
18521 LOCK_ZONE(zone);
18522 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
18523 UNLOCK_ZONE(zone);
18524 goto gotquota;
18525 }
18526
18527 /*
18528 * Find any configured information about the server we'd
18529 * like to transfer this zone from.
18530 */
18531 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
18532 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
18533 UNLOCK_ZONE(zone);
18534
18535 /*
18536 * Determine the total maximum number of simultaneous
18537 * transfers allowed, and the maximum for this specific
18538 * master.
18539 */
18540 maxtransfersin = zmgr->transfersin;
18541 maxtransfersperns = zmgr->transfersperns;
18542 if (peer != NULL) {
18543 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
18544 }
18545
18546 /*
18547 * Count the total number of transfers that are in progress,
18548 * and the number of transfers in progress from this master.
18549 * We linearly scan a list of all transfers; if this turns
18550 * out to be too slow, we could hash on the master address.
18551 */
18552 nxfrsin = nxfrsperns = 0;
18553 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress); x != NULL;
18554 x = ISC_LIST_NEXT(x, statelink))
18555 {
18556 isc_netaddr_t xip;
18557
18558 LOCK_ZONE(x);
18559 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
18560 UNLOCK_ZONE(x);
18561
18562 nxfrsin++;
18563 if (isc_netaddr_equal(&xip, &masterip)) {
18564 nxfrsperns++;
18565 }
18566 }
18567
18568 /* Enforce quota. */
18569 if (nxfrsin >= maxtransfersin) {
18570 return (ISC_R_QUOTA);
18571 }
18572
18573 if (nxfrsperns >= maxtransfersperns) {
18574 return (ISC_R_QUOTA);
18575 }
18576
18577 gotquota:
18578 /*
18579 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
18580 * list and send it an event to let it start the actual transfer in the
18581 * context of its own task.
18582 */
18583 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
18584 got_transfer_quota, zone, sizeof(isc_event_t));
18585
18586 LOCK_ZONE(zone);
18587 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
18588 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
18589 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
18590 zone->statelist = &zmgr->xfrin_in_progress;
18591 isc_task_send(zone->task, &e);
18592 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
18593 "Transfer started.");
18594 UNLOCK_ZONE(zone);
18595
18596 return (ISC_R_SUCCESS);
18597 }
18598
18599 void
18600 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
18601 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18602 REQUIRE(iolimit > 0);
18603
18604 zmgr->iolimit = iolimit;
18605 }
18606
18607 uint32_t
18608 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
18609 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18610
18611 return (zmgr->iolimit);
18612 }
18613
18614 /*
18615 * Get permission to request a file handle from the OS.
18616 * An event will be sent to action when one is available.
18617 * There are two queues available (high and low), the high
18618 * queue will be serviced before the low one.
18619 *
18620 * zonemgr_putio() must be called after the event is delivered to
18621 * 'action'.
18622 */
18623
18624 static isc_result_t
18625 zonemgr_getio(dns_zonemgr_t *zmgr, bool high, isc_task_t *task,
18626 isc_taskaction_t action, void *arg, dns_io_t **iop) {
18627 dns_io_t *io;
18628 bool queue;
18629
18630 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18631 REQUIRE(iop != NULL && *iop == NULL);
18632
18633 io = isc_mem_get(zmgr->mctx, sizeof(*io));
18634
18635 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
18636 action, arg, sizeof(*io->event));
18637
18638 io->zmgr = zmgr;
18639 io->high = high;
18640 io->task = NULL;
18641 isc_task_attach(task, &io->task);
18642 ISC_LINK_INIT(io, link);
18643 io->magic = IO_MAGIC;
18644
18645 LOCK(&zmgr->iolock);
18646 zmgr->ioactive++;
18647 queue = (zmgr->ioactive > zmgr->iolimit);
18648 if (queue) {
18649 if (io->high) {
18650 ISC_LIST_APPEND(zmgr->high, io, link);
18651 } else {
18652 ISC_LIST_APPEND(zmgr->low, io, link);
18653 }
18654 }
18655 UNLOCK(&zmgr->iolock);
18656 *iop = io;
18657
18658 if (!queue) {
18659 isc_task_send(io->task, &io->event);
18660 }
18661 return (ISC_R_SUCCESS);
18662 }
18663
18664 static void
18665 zonemgr_putio(dns_io_t **iop) {
18666 dns_io_t *io;
18667 dns_io_t *next;
18668 dns_zonemgr_t *zmgr;
18669
18670 REQUIRE(iop != NULL);
18671 io = *iop;
18672 *iop = NULL;
18673 REQUIRE(DNS_IO_VALID(io));
18674
18675 INSIST(!ISC_LINK_LINKED(io, link));
18676 INSIST(io->event == NULL);
18677
18678 zmgr = io->zmgr;
18679 isc_task_detach(&io->task);
18680 io->magic = 0;
18681 isc_mem_put(zmgr->mctx, io, sizeof(*io));
18682
18683 LOCK(&zmgr->iolock);
18684 INSIST(zmgr->ioactive > 0);
18685 zmgr->ioactive--;
18686 next = HEAD(zmgr->high);
18687 if (next == NULL) {
18688 next = HEAD(zmgr->low);
18689 }
18690 if (next != NULL) {
18691 if (next->high) {
18692 ISC_LIST_UNLINK(zmgr->high, next, link);
18693 } else {
18694 ISC_LIST_UNLINK(zmgr->low, next, link);
18695 }
18696 INSIST(next->event != NULL);
18697 }
18698 UNLOCK(&zmgr->iolock);
18699 if (next != NULL) {
18700 isc_task_send(next->task, &next->event);
18701 }
18702 }
18703
18704 static void
18705 zonemgr_cancelio(dns_io_t *io) {
18706 bool send_event = false;
18707
18708 REQUIRE(DNS_IO_VALID(io));
18709
18710 /*
18711 * If we are queued to be run then dequeue.
18712 */
18713 LOCK(&io->zmgr->iolock);
18714 if (ISC_LINK_LINKED(io, link)) {
18715 if (io->high) {
18716 ISC_LIST_UNLINK(io->zmgr->high, io, link);
18717 } else {
18718 ISC_LIST_UNLINK(io->zmgr->low, io, link);
18719 }
18720
18721 send_event = true;
18722 INSIST(io->event != NULL);
18723 }
18724 UNLOCK(&io->zmgr->iolock);
18725 if (send_event) {
18726 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
18727 isc_task_send(io->task, &io->event);
18728 }
18729 }
18730
18731 static void
18732 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
18733 char *buf;
18734 int buflen;
18735 isc_result_t result;
18736
18737 buflen = strlen(path) + strlen(templat) + 2;
18738
18739 buf = isc_mem_get(zone->mctx, buflen);
18740
18741 result = isc_file_template(path, templat, buf, buflen);
18742 if (result != ISC_R_SUCCESS) {
18743 goto cleanup;
18744 }
18745
18746 result = isc_file_renameunique(path, buf);
18747 if (result != ISC_R_SUCCESS) {
18748 goto cleanup;
18749 }
18750
18751 dns_zone_log(zone, ISC_LOG_WARNING,
18752 "unable to load from '%s'; "
18753 "renaming file to '%s' for failure analysis and "
18754 "retransferring.",
18755 path, buf);
18756
18757 cleanup:
18758 isc_mem_put(zone->mctx, buf, buflen);
18759 }
18760
18761 static void
18762 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
18763 isc_interval_t interval;
18764 uint32_t s, ns;
18765 uint32_t pertic;
18766 isc_result_t result;
18767
18768 if (value == 0) {
18769 value = 1;
18770 }
18771
18772 if (value == 1) {
18773 s = 1;
18774 ns = 0;
18775 pertic = 1;
18776 } else if (value <= 10) {
18777 s = 0;
18778 ns = 1000000000 / value;
18779 pertic = 1;
18780 } else {
18781 s = 0;
18782 ns = (1000000000 / value) * 10;
18783 pertic = 10;
18784 }
18785
18786 isc_interval_set(&interval, s, ns);
18787
18788 result = isc_ratelimiter_setinterval(rl, &interval);
18789 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18790 isc_ratelimiter_setpertic(rl, pertic);
18791
18792 *rate = value;
18793 }
18794
18795 void
18796 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
18797 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18798
18799 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
18800 }
18801
18802 void
18803 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
18804 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18805
18806 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
18807 }
18808
18809 void
18810 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
18811 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18812
18813 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
18814 /* XXXMPA separate out once we have the code to support this. */
18815 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
18816 }
18817
18818 unsigned int
18819 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
18820 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18821
18822 return (zmgr->notifyrate);
18823 }
18824
18825 unsigned int
18826 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
18827 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18828
18829 return (zmgr->startupnotifyrate);
18830 }
18831
18832 unsigned int
18833 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
18834 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18835
18836 return (zmgr->serialqueryrate);
18837 }
18838
18839 bool
18840 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
18841 isc_sockaddr_t *local, isc_time_t *now) {
18842 unsigned int i;
18843 uint32_t seconds = isc_time_seconds(now);
18844 uint32_t count = 0;
18845
18846 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18847
18848 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
18849 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
18850 if (atomic_load(&zmgr->unreachable[i].expire) >= seconds &&
18851 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
18852 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
18853 {
18854 atomic_store_relaxed(&zmgr->unreachable[i].last,
18855 seconds);
18856 count = zmgr->unreachable[i].count;
18857 break;
18858 }
18859 }
18860 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
18861 return (i < UNREACH_CACHE_SIZE && count > 1U);
18862 }
18863
18864 void
18865 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
18866 isc_sockaddr_t *local) {
18867 unsigned int i;
18868 char master[ISC_SOCKADDR_FORMATSIZE];
18869 char source[ISC_SOCKADDR_FORMATSIZE];
18870
18871 isc_sockaddr_format(remote, master, sizeof(master));
18872 isc_sockaddr_format(local, source, sizeof(source));
18873
18874 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18875
18876 RWLOCK(&zmgr->urlock, isc_rwlocktype_read);
18877 for (i = 0; i < UNREACH_CACHE_SIZE; i++) {
18878 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
18879 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
18880 {
18881 atomic_store_relaxed(&zmgr->unreachable[i].expire, 0);
18882 break;
18883 }
18884 }
18885 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_read);
18886 }
18887
18888 void
18889 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
18890 isc_sockaddr_t *local, isc_time_t *now) {
18891 uint32_t seconds = isc_time_seconds(now);
18892 uint32_t expire = 0, last = seconds;
18893 unsigned int slot = UNREACH_CACHE_SIZE, oldest = 0;
18894 bool update_entry = true;
18895 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
18896
18897 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
18898 for (unsigned int i = 0; i < UNREACH_CACHE_SIZE; i++) {
18899 /* Existing entry? */
18900 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
18901 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
18902 {
18903 update_entry = false;
18904 slot = i;
18905 expire = atomic_load_relaxed(
18906 &zmgr->unreachable[i].expire);
18907 break;
18908 }
18909 /* Pick first empty slot? */
18910 if (atomic_load_relaxed(&zmgr->unreachable[i].expire) < seconds)
18911 {
18912 slot = i;
18913 break;
18914 }
18915 /* The worst case, least recently used slot? */
18916 if (atomic_load_relaxed(&zmgr->unreachable[i].last) < last) {
18917 last = atomic_load_relaxed(&zmgr->unreachable[i].last);
18918 oldest = i;
18919 }
18920 }
18921
18922 /* We haven't found any existing or free slots, use the oldest */
18923 if (slot == UNREACH_CACHE_SIZE) {
18924 slot = oldest;
18925 }
18926
18927 if (expire < seconds) {
18928 /* Expired or new entry, reset count to 1 */
18929 zmgr->unreachable[slot].count = 1;
18930 } else {
18931 zmgr->unreachable[slot].count++;
18932 }
18933 atomic_store_relaxed(&zmgr->unreachable[slot].expire,
18934 seconds + UNREACH_HOLD_TIME);
18935 atomic_store_relaxed(&zmgr->unreachable[slot].last, seconds);
18936 if (update_entry) {
18937 zmgr->unreachable[slot].remote = *remote;
18938 zmgr->unreachable[slot].local = *local;
18939 }
18940
18941 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
18942 }
18943
18944 void
18945 dns_zone_forcereload(dns_zone_t *zone) {
18946 REQUIRE(DNS_ZONE_VALID(zone));
18947
18948 if (zone->type == dns_zone_master ||
18949 (zone->type == dns_zone_redirect && zone->masters == NULL))
18950 {
18951 return;
18952 }
18953
18954 LOCK_ZONE(zone);
18955 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
18956 UNLOCK_ZONE(zone);
18957 dns_zone_refresh(zone);
18958 }
18959
18960 bool
18961 dns_zone_isforced(dns_zone_t *zone) {
18962 REQUIRE(DNS_ZONE_VALID(zone));
18963
18964 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
18965 }
18966
18967 isc_result_t
18968 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
18969 /*
18970 * This function is obsoleted.
18971 */
18972 UNUSED(zone);
18973 UNUSED(on);
18974 return (ISC_R_NOTIMPLEMENTED);
18975 }
18976
18977 uint64_t *
18978 dns_zone_getstatscounters(dns_zone_t *zone) {
18979 /*
18980 * This function is obsoleted.
18981 */
18982 UNUSED(zone);
18983 return (NULL);
18984 }
18985
18986 void
18987 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
18988 REQUIRE(DNS_ZONE_VALID(zone));
18989 REQUIRE(zone->stats == NULL);
18990
18991 LOCK_ZONE(zone);
18992 zone->stats = NULL;
18993 isc_stats_attach(stats, &zone->stats);
18994 UNLOCK_ZONE(zone);
18995 }
18996
18997 void
18998 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
18999 REQUIRE(DNS_ZONE_VALID(zone));
19000
19001 LOCK_ZONE(zone);
19002 if (zone->requeststats_on && stats == NULL) {
19003 zone->requeststats_on = false;
19004 } else if (!zone->requeststats_on && stats != NULL) {
19005 if (zone->requeststats == NULL) {
19006 isc_stats_attach(stats, &zone->requeststats);
19007 zone->requeststats_on = true;
19008 }
19009 }
19010 UNLOCK_ZONE(zone);
19011 }
19012
19013 void
19014 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
19015 REQUIRE(DNS_ZONE_VALID(zone));
19016
19017 LOCK_ZONE(zone);
19018 if (zone->requeststats_on && stats != NULL) {
19019 if (zone->rcvquerystats == NULL) {
19020 dns_stats_attach(stats, &zone->rcvquerystats);
19021 zone->requeststats_on = true;
19022 }
19023 }
19024 UNLOCK_ZONE(zone);
19025 }
19026
19027 void
19028 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
19029 REQUIRE(DNS_ZONE_VALID(zone));
19030
19031 LOCK_ZONE(zone);
19032 if (stats != NULL && zone->dnssecsignstats == NULL) {
19033 dns_stats_attach(stats, &zone->dnssecsignstats);
19034 }
19035 UNLOCK_ZONE(zone);
19036 }
19037
19038 dns_stats_t *
19039 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
19040 REQUIRE(DNS_ZONE_VALID(zone));
19041
19042 return (zone->dnssecsignstats);
19043 }
19044
19045 isc_stats_t *
19046 dns_zone_getrequeststats(dns_zone_t *zone) {
19047 /*
19048 * We don't lock zone for efficiency reason. This is not catastrophic
19049 * because requeststats must always be valid when requeststats_on is
19050 * true.
19051 * Some counters may be incremented while requeststats_on is becoming
19052 * false, or some cannot be incremented just after the statistics are
19053 * installed, but it shouldn't matter much in practice.
19054 */
19055 if (zone->requeststats_on) {
19056 return (zone->requeststats);
19057 } else {
19058 return (NULL);
19059 }
19060 }
19061
19062 /*
19063 * Return the received query stats bucket
19064 * see note from dns_zone_getrequeststats()
19065 */
19066 dns_stats_t *
19067 dns_zone_getrcvquerystats(dns_zone_t *zone) {
19068 if (zone->requeststats_on) {
19069 return (zone->rcvquerystats);
19070 } else {
19071 return (NULL);
19072 }
19073 }
19074
19075 void
19076 dns_zone_dialup(dns_zone_t *zone) {
19077 REQUIRE(DNS_ZONE_VALID(zone));
19078
19079 zone_debuglog(zone, "dns_zone_dialup", 3, "notify = %d, refresh = %d",
19080 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
19081 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
19082
19083 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY)) {
19084 dns_zone_notify(zone);
19085 }
19086 if (zone->type != dns_zone_master && zone->masters != NULL &&
19087 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
19088 {
19089 dns_zone_refresh(zone);
19090 }
19091 }
19092
19093 void
19094 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
19095 REQUIRE(DNS_ZONE_VALID(zone));
19096
19097 LOCK_ZONE(zone);
19098 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
19099 DNS_ZONEFLG_DIALREFRESH |
19100 DNS_ZONEFLG_NOREFRESH);
19101 switch (dialup) {
19102 case dns_dialuptype_no:
19103 break;
19104 case dns_dialuptype_yes:
19105 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
19106 DNS_ZONEFLG_DIALREFRESH |
19107 DNS_ZONEFLG_NOREFRESH));
19108 break;
19109 case dns_dialuptype_notify:
19110 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19111 break;
19112 case dns_dialuptype_notifypassive:
19113 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
19114 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19115 break;
19116 case dns_dialuptype_refresh:
19117 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
19118 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19119 break;
19120 case dns_dialuptype_passive:
19121 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
19122 break;
19123 default:
19124 INSIST(0);
19125 ISC_UNREACHABLE();
19126 }
19127 UNLOCK_ZONE(zone);
19128 }
19129
19130 isc_result_t
19131 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
19132 isc_result_t result = ISC_R_SUCCESS;
19133
19134 REQUIRE(DNS_ZONE_VALID(zone));
19135
19136 LOCK_ZONE(zone);
19137 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
19138 UNLOCK_ZONE(zone);
19139
19140 return (result);
19141 }
19142
19143 const char *
19144 dns_zone_getkeydirectory(dns_zone_t *zone) {
19145 REQUIRE(DNS_ZONE_VALID(zone));
19146
19147 return (zone->keydirectory);
19148 }
19149
19150 unsigned int
19151 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
19152 dns_zone_t *zone;
19153 unsigned int count = 0;
19154
19155 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
19156
19157 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19158 switch (state) {
19159 case DNS_ZONESTATE_XFERRUNNING:
19160 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
19161 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19162 {
19163 count++;
19164 }
19165 break;
19166 case DNS_ZONESTATE_XFERDEFERRED:
19167 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
19168 zone != NULL; zone = ISC_LIST_NEXT(zone, statelink))
19169 {
19170 count++;
19171 }
19172 break;
19173 case DNS_ZONESTATE_SOAQUERY:
19174 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19175 zone = ISC_LIST_NEXT(zone, link))
19176 {
19177 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
19178 count++;
19179 }
19180 }
19181 break;
19182 case DNS_ZONESTATE_ANY:
19183 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19184 zone = ISC_LIST_NEXT(zone, link))
19185 {
19186 dns_view_t *view = zone->view;
19187 if (view != NULL && strcmp(view->name, "_bind") == 0) {
19188 continue;
19189 }
19190 count++;
19191 }
19192 break;
19193 case DNS_ZONESTATE_AUTOMATIC:
19194 for (zone = ISC_LIST_HEAD(zmgr->zones); zone != NULL;
19195 zone = ISC_LIST_NEXT(zone, link))
19196 {
19197 dns_view_t *view = zone->view;
19198 if (view != NULL && strcmp(view->name, "_bind") == 0) {
19199 continue;
19200 }
19201 if (zone->automatic) {
19202 count++;
19203 }
19204 }
19205 break;
19206 default:
19207 INSIST(0);
19208 ISC_UNREACHABLE();
19209 }
19210
19211 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
19212
19213 return (count);
19214 }
19215
19216 isc_result_t
19217 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
19218 dns_rdata_t *rdata) {
19219 bool ok = true;
19220 bool fail = false;
19221 char namebuf[DNS_NAME_FORMATSIZE];
19222 char namebuf2[DNS_NAME_FORMATSIZE];
19223 char typebuf[DNS_RDATATYPE_FORMATSIZE];
19224 int level = ISC_LOG_WARNING;
19225 dns_name_t bad;
19226
19227 REQUIRE(DNS_ZONE_VALID(zone));
19228
19229 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
19230 rdata->type != dns_rdatatype_nsec3)
19231 {
19232 return (ISC_R_SUCCESS);
19233 }
19234
19235 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
19236 rdata->type == dns_rdatatype_nsec3)
19237 {
19238 level = ISC_LOG_ERROR;
19239 fail = true;
19240 }
19241
19242 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
19243 if (!ok) {
19244 dns_name_format(name, namebuf, sizeof(namebuf));
19245 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
19246 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
19247 dns_result_totext(DNS_R_BADOWNERNAME));
19248 if (fail) {
19249 return (DNS_R_BADOWNERNAME);
19250 }
19251 }
19252
19253 dns_name_init(&bad, NULL);
19254 ok = dns_rdata_checknames(rdata, name, &bad);
19255 if (!ok) {
19256 dns_name_format(name, namebuf, sizeof(namebuf));
19257 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
19258 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
19259 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
19260 namebuf2, dns_result_totext(DNS_R_BADNAME));
19261 if (fail) {
19262 return (DNS_R_BADNAME);
19263 }
19264 }
19265
19266 return (ISC_R_SUCCESS);
19267 }
19268
19269 void
19270 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
19271 REQUIRE(DNS_ZONE_VALID(zone));
19272 zone->checkmx = checkmx;
19273 }
19274
19275 void
19276 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
19277 REQUIRE(DNS_ZONE_VALID(zone));
19278 zone->checksrv = checksrv;
19279 }
19280
19281 void
19282 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
19283 REQUIRE(DNS_ZONE_VALID(zone));
19284 zone->checkns = checkns;
19285 }
19286
19287 void
19288 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
19289 REQUIRE(DNS_ZONE_VALID(zone));
19290
19291 LOCK_ZONE(zone);
19292 zone->isself = isself;
19293 zone->isselfarg = arg;
19294 UNLOCK_ZONE(zone);
19295 }
19296
19297 void
19298 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
19299 REQUIRE(DNS_ZONE_VALID(zone));
19300
19301 LOCK_ZONE(zone);
19302 zone->notifydelay = delay;
19303 UNLOCK_ZONE(zone);
19304 }
19305
19306 uint32_t
19307 dns_zone_getnotifydelay(dns_zone_t *zone) {
19308 REQUIRE(DNS_ZONE_VALID(zone));
19309
19310 return (zone->notifydelay);
19311 }
19312
19313 isc_result_t
19314 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
19315 bool deleteit) {
19316 isc_result_t result;
19317 REQUIRE(DNS_ZONE_VALID(zone));
19318
19319 dnssec_log(zone, ISC_LOG_NOTICE,
19320 "dns_zone_signwithkey(algorithm=%u, keyid=%u)", algorithm,
19321 keyid);
19322 LOCK_ZONE(zone);
19323 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
19324 UNLOCK_ZONE(zone);
19325
19326 return (result);
19327 }
19328
19329 /*
19330 * Called when a dynamic update for an NSEC3PARAM record is received.
19331 *
19332 * If set, transform the NSEC3 salt into human-readable form so that it can be
19333 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
19334 */
19335 isc_result_t
19336 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
19337 isc_result_t result;
19338 char salt[255 * 2 + 1];
19339
19340 REQUIRE(DNS_ZONE_VALID(zone));
19341
19342 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
19343 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19344 dnssec_log(zone, ISC_LOG_NOTICE,
19345 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
19346 nsec3param->hash, nsec3param->iterations, salt);
19347 LOCK_ZONE(zone);
19348 result = zone_addnsec3chain(zone, nsec3param);
19349 UNLOCK_ZONE(zone);
19350
19351 return (result);
19352 }
19353
19354 void
19355 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
19356 REQUIRE(DNS_ZONE_VALID(zone));
19357
19358 if (nodes == 0) {
19359 nodes = 1;
19360 }
19361 zone->nodes = nodes;
19362 }
19363
19364 void
19365 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
19366 REQUIRE(DNS_ZONE_VALID(zone));
19367
19368 /*
19369 * We treat signatures as a signed value so explicitly
19370 * limit its range here.
19371 */
19372 if (signatures > INT32_MAX) {
19373 signatures = INT32_MAX;
19374 } else if (signatures == 0) {
19375 signatures = 1;
19376 }
19377 zone->signatures = signatures;
19378 }
19379
19380 uint32_t
19381 dns_zone_getsignatures(dns_zone_t *zone) {
19382 REQUIRE(DNS_ZONE_VALID(zone));
19383 return (zone->signatures);
19384 }
19385
19386 void
19387 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
19388 REQUIRE(DNS_ZONE_VALID(zone));
19389 zone->privatetype = type;
19390 }
19391
19392 dns_rdatatype_t
19393 dns_zone_getprivatetype(dns_zone_t *zone) {
19394 REQUIRE(DNS_ZONE_VALID(zone));
19395 return (zone->privatetype);
19396 }
19397
19398 static isc_result_t
19399 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
19400 bool deleteit) {
19401 dns_signing_t *signing;
19402 dns_signing_t *current;
19403 isc_result_t result = ISC_R_SUCCESS;
19404 isc_time_t now;
19405 dns_db_t *db = NULL;
19406
19407 signing = isc_mem_get(zone->mctx, sizeof *signing);
19408
19409 signing->magic = 0;
19410 signing->db = NULL;
19411 signing->dbiterator = NULL;
19412 signing->algorithm = algorithm;
19413 signing->keyid = keyid;
19414 signing->deleteit = deleteit;
19415 signing->done = false;
19416
19417 TIME_NOW(&now);
19418
19419 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19420 if (zone->db != NULL) {
19421 dns_db_attach(zone->db, &db);
19422 }
19423 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19424
19425 if (db == NULL) {
19426 result = ISC_R_NOTFOUND;
19427 goto cleanup;
19428 }
19429
19430 dns_db_attach(db, &signing->db);
19431
19432 for (current = ISC_LIST_HEAD(zone->signing); current != NULL;
19433 current = ISC_LIST_NEXT(current, link))
19434 {
19435 if (current->db == signing->db &&
19436 current->algorithm == signing->algorithm &&
19437 current->keyid == signing->keyid)
19438 {
19439 if (current->deleteit != signing->deleteit) {
19440 current->done = true;
19441 } else {
19442 goto cleanup;
19443 }
19444 }
19445 }
19446
19447 result = dns_db_createiterator(signing->db, 0, &signing->dbiterator);
19448
19449 if (result == ISC_R_SUCCESS) {
19450 result = dns_dbiterator_first(signing->dbiterator);
19451 }
19452 if (result == ISC_R_SUCCESS) {
19453 dns_dbiterator_pause(signing->dbiterator);
19454 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
19455 signing = NULL;
19456 if (isc_time_isepoch(&zone->signingtime)) {
19457 zone->signingtime = now;
19458 if (zone->task != NULL) {
19459 zone_settimer(zone, &now);
19460 }
19461 }
19462 }
19463
19464 cleanup:
19465 if (signing != NULL) {
19466 if (signing->db != NULL) {
19467 dns_db_detach(&signing->db);
19468 }
19469 if (signing->dbiterator != NULL) {
19470 dns_dbiterator_destroy(&signing->dbiterator);
19471 }
19472 isc_mem_put(zone->mctx, signing, sizeof *signing);
19473 }
19474 if (db != NULL) {
19475 dns_db_detach(&db);
19476 }
19477 return (result);
19478 }
19479
19480 static void
19481 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
19482 dns_dnsseckey_t *key;
19483 while (!ISC_LIST_EMPTY(*list)) {
19484 key = ISC_LIST_HEAD(*list);
19485 ISC_LIST_UNLINK(*list, key, link);
19486 dns_dnsseckey_destroy(mctx, &key);
19487 }
19488 }
19489
19490 /* Called once; *timep should be set to the current time. */
19491 static isc_result_t
19492 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
19493 isc_result_t result;
19494 isc_stdtime_t now, then = 0, event;
19495 int i;
19496
19497 now = *timep;
19498
19499 for (i = 0; i <= DST_MAX_TIMES; i++) {
19500 result = dst_key_gettime(key, i, &event);
19501 if (result == ISC_R_SUCCESS && event > now &&
19502 (then == 0 || event < then)) {
19503 then = event;
19504 }
19505 }
19506
19507 if (then != 0) {
19508 *timep = then;
19509 return (ISC_R_SUCCESS);
19510 }
19511
19512 return (ISC_R_NOTFOUND);
19513 }
19514
19515 static isc_result_t
19516 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
19517 const dns_rdata_t *rdata, bool *flag) {
19518 dns_rdataset_t rdataset;
19519 dns_dbnode_t *node = NULL;
19520 isc_result_t result;
19521
19522 dns_rdataset_init(&rdataset);
19523 if (rdata->type == dns_rdatatype_nsec3) {
19524 CHECK(dns_db_findnsec3node(db, name, false, &node));
19525 } else {
19526 CHECK(dns_db_findnode(db, name, false, &node));
19527 }
19528 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
19529 (isc_stdtime_t)0, &rdataset, NULL);
19530 if (result == ISC_R_NOTFOUND) {
19531 *flag = false;
19532 result = ISC_R_SUCCESS;
19533 goto failure;
19534 }
19535
19536 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
19537 result = dns_rdataset_next(&rdataset))
19538 {
19539 dns_rdata_t myrdata = DNS_RDATA_INIT;
19540 dns_rdataset_current(&rdataset, &myrdata);
19541 if (!dns_rdata_compare(&myrdata, rdata)) {
19542 break;
19543 }
19544 }
19545 dns_rdataset_disassociate(&rdataset);
19546 if (result == ISC_R_SUCCESS) {
19547 *flag = true;
19548 } else if (result == ISC_R_NOMORE) {
19549 *flag = false;
19550 result = ISC_R_SUCCESS;
19551 }
19552
19553 failure:
19554 if (node != NULL) {
19555 dns_db_detachnode(db, &node);
19556 }
19557 return (result);
19558 }
19559
19560 /*
19561 * Add records to signal the state of signing or of key removal.
19562 */
19563 static isc_result_t
19564 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
19565 dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all) {
19566 dns_difftuple_t *tuple, *newtuple = NULL;
19567 dns_rdata_dnskey_t dnskey;
19568 dns_rdata_t rdata = DNS_RDATA_INIT;
19569 bool flag;
19570 isc_region_t r;
19571 isc_result_t result = ISC_R_SUCCESS;
19572 uint16_t keyid;
19573 unsigned char buf[5];
19574 dns_name_t *name = dns_db_origin(db);
19575
19576 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
19577 tuple = ISC_LIST_NEXT(tuple, link))
19578 {
19579 if (tuple->rdata.type != dns_rdatatype_dnskey) {
19580 continue;
19581 }
19582
19583 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
19584 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19585 if ((dnskey.flags & (DNS_KEYFLAG_OWNERMASK |
19586 DNS_KEYTYPE_NOAUTH)) != DNS_KEYOWNER_ZONE)
19587 {
19588 continue;
19589 }
19590
19591 dns_rdata_toregion(&tuple->rdata, &r);
19592
19593 keyid = dst_region_computeid(&r);
19594
19595 buf[0] = dnskey.algorithm;
19596 buf[1] = (keyid & 0xff00) >> 8;
19597 buf[2] = (keyid & 0xff);
19598 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
19599 buf[4] = 0;
19600 rdata.data = buf;
19601 rdata.length = sizeof(buf);
19602 rdata.type = privatetype;
19603 rdata.rdclass = tuple->rdata.rdclass;
19604
19605 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
19606 CHECK(rr_exists(db, ver, name, &rdata, &flag));
19607 if (flag) {
19608 continue;
19609 }
19610
19611 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
19612 name, 0, &rdata, &newtuple));
19613 CHECK(do_one_tuple(&newtuple, db, ver, diff));
19614 INSIST(newtuple == NULL);
19615 }
19616
19617 /*
19618 * Remove any record which says this operation has already
19619 * completed.
19620 */
19621 buf[4] = 1;
19622 CHECK(rr_exists(db, ver, name, &rdata, &flag));
19623 if (flag) {
19624 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
19625 name, 0, &rdata, &newtuple));
19626 CHECK(do_one_tuple(&newtuple, db, ver, diff));
19627 INSIST(newtuple == NULL);
19628 }
19629 }
19630 failure:
19631 return (result);
19632 }
19633
19634 /*
19635 * See if dns__zone_updatesigs() will update signature for RRset 'rrtype' at
19636 * the apex, and if not tickle them and cause to sign so that newly activated
19637 * keys are used.
19638 */
19639 static isc_result_t
19640 tickle_apex_rrset(dns_rdatatype_t rrtype, dns_zone_t *zone, dns_db_t *db,
19641 dns_dbversion_t *ver, isc_stdtime_t now, dns_diff_t *diff,
19642 dns__zonediff_t *zonediff, dst_key_t **keys,
19643 unsigned int nkeys, isc_stdtime_t inception,
19644 isc_stdtime_t keyexpire, bool check_ksk,
19645 bool keyset_kskonly) {
19646 dns_difftuple_t *tuple;
19647 isc_result_t result;
19648
19649 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
19650 tuple = ISC_LIST_NEXT(tuple, link))
19651 {
19652 if (tuple->rdata.type == rrtype &&
19653 dns_name_equal(&tuple->name, &zone->origin)) {
19654 break;
19655 }
19656 }
19657
19658 if (tuple == NULL) {
19659 result = del_sigs(zone, db, ver, &zone->origin, rrtype,
19660 zonediff, keys, nkeys, now, false);
19661 if (result != ISC_R_SUCCESS) {
19662 dnssec_log(zone, ISC_LOG_ERROR,
19663 "sign_apex:del_sigs -> %s",
19664 dns_result_totext(result));
19665 return (result);
19666 }
19667 result = add_sigs(db, ver, &zone->origin, zone, rrtype,
19668 zonediff->diff, keys, nkeys, zone->mctx,
19669 inception, keyexpire, check_ksk,
19670 keyset_kskonly);
19671 if (result != ISC_R_SUCCESS) {
19672 dnssec_log(zone, ISC_LOG_ERROR,
19673 "sign_apex:add_sigs -> %s",
19674 dns_result_totext(result));
19675 return (result);
19676 }
19677 }
19678
19679 return (ISC_R_SUCCESS);
19680 }
19681
19682 static isc_result_t
19683 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19684 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff) {
19685 isc_result_t result;
19686 isc_stdtime_t inception, soaexpire, keyexpire;
19687 bool check_ksk, keyset_kskonly;
19688 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
19689 unsigned int nkeys = 0, i;
19690
19691 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
19692 DNS_MAXZONEKEYS, zone_keys, &nkeys);
19693 if (result != ISC_R_SUCCESS) {
19694 dnssec_log(zone, ISC_LOG_ERROR,
19695 "sign_apex:dns__zone_findkeys -> %s",
19696 dns_result_totext(result));
19697 return (result);
19698 }
19699
19700 inception = now - 3600; /* Allow for clock skew. */
19701 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
19702
19703 keyexpire = dns_zone_getkeyvalidityinterval(zone);
19704 if (keyexpire == 0) {
19705 keyexpire = soaexpire - 1;
19706 } else {
19707 keyexpire += now;
19708 }
19709
19710 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
19711 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
19712
19713 /*
19714 * See if dns__zone_updatesigs() will update DNSKEY/CDS/CDNSKEY
19715 * signature and if not cause them to sign so that newly activated
19716 * keys are used.
19717 */
19718 result = tickle_apex_rrset(dns_rdatatype_dnskey, zone, db, ver, now,
19719 diff, zonediff, zone_keys, nkeys, inception,
19720 keyexpire, check_ksk, keyset_kskonly);
19721 if (result != ISC_R_SUCCESS) {
19722 goto failure;
19723 }
19724 result = tickle_apex_rrset(dns_rdatatype_cds, zone, db, ver, now, diff,
19725 zonediff, zone_keys, nkeys, inception,
19726 keyexpire, check_ksk, keyset_kskonly);
19727 if (result != ISC_R_SUCCESS) {
19728 goto failure;
19729 }
19730 result = tickle_apex_rrset(dns_rdatatype_cdnskey, zone, db, ver, now,
19731 diff, zonediff, zone_keys, nkeys, inception,
19732 keyexpire, check_ksk, keyset_kskonly);
19733 if (result != ISC_R_SUCCESS) {
19734 goto failure;
19735 }
19736
19737 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
19738 inception, soaexpire, keyexpire, now,
19739 check_ksk, keyset_kskonly, zonediff);
19740
19741 if (result != ISC_R_SUCCESS) {
19742 dnssec_log(zone, ISC_LOG_ERROR,
19743 "sign_apex:dns__zone_updatesigs -> %s",
19744 dns_result_totext(result));
19745 goto failure;
19746 }
19747
19748 failure:
19749 for (i = 0; i < nkeys; i++) {
19750 dst_key_free(&zone_keys[i]);
19751 }
19752 return (result);
19753 }
19754
19755 /*
19756 * Prevent the zone entering a inconsistent state where
19757 * NSEC only DNSKEYs are present with NSEC3 chains.
19758 * See update.c:check_dnssec()
19759 */
19760 static bool
19761 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19762 dns_diff_t *diff) {
19763 isc_result_t result;
19764 dns_difftuple_t *tuple;
19765 bool nseconly = false, nsec3 = false;
19766 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
19767
19768 /* Scan the tuples for an NSEC-only DNSKEY */
19769 for (tuple = ISC_LIST_HEAD(diff->tuples); tuple != NULL;
19770 tuple = ISC_LIST_NEXT(tuple, link))
19771 {
19772 uint8_t alg;
19773 if (tuple->rdata.type != dns_rdatatype_dnskey ||
19774 tuple->op != DNS_DIFFOP_ADD) {
19775 continue;
19776 }
19777
19778 alg = tuple->rdata.data[3];
19779 if (alg == DST_ALG_RSASHA1) {
19780 nseconly = true;
19781 break;
19782 }
19783 }
19784
19785 /* Check existing DB for NSEC-only DNSKEY */
19786 if (!nseconly) {
19787 result = dns_nsec_nseconly(db, ver, &nseconly);
19788 if (result == ISC_R_NOTFOUND) {
19789 result = ISC_R_SUCCESS;
19790 }
19791 CHECK(result);
19792 }
19793
19794 /* Check existing DB for NSEC3 */
19795 if (!nsec3) {
19796 CHECK(dns_nsec3_activex(db, ver, false, privatetype, &nsec3));
19797 }
19798
19799 /* Refuse to allow NSEC3 with NSEC-only keys */
19800 if (nseconly && nsec3) {
19801 dnssec_log(zone, ISC_LOG_ERROR,
19802 "NSEC only DNSKEYs and NSEC3 chains not allowed");
19803 goto failure;
19804 }
19805
19806 return (true);
19807
19808 failure:
19809 return (false);
19810 }
19811
19812 static isc_result_t
19813 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19814 dns_diff_t *diff) {
19815 isc_result_t result;
19816 dns_dbnode_t *node = NULL;
19817 dns_rdataset_t rdataset;
19818
19819 dns_rdataset_init(&rdataset);
19820 CHECK(dns_db_getoriginnode(db, &node));
19821
19822 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
19823 dns_rdatatype_none, 0, &rdataset, NULL);
19824 if (dns_rdataset_isassociated(&rdataset)) {
19825 dns_rdataset_disassociate(&rdataset);
19826 }
19827 if (result != ISC_R_NOTFOUND) {
19828 goto failure;
19829 }
19830
19831 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
19832
19833 failure:
19834 if (node != NULL) {
19835 dns_db_detachnode(db, &node);
19836 }
19837 return (result);
19838 }
19839
19840 /*
19841 * Given an RRSIG rdataset and an algorithm, determine whether there
19842 * are any signatures using that algorithm.
19843 */
19844 static bool
19845 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
19846 dns_rdata_t rdata = DNS_RDATA_INIT;
19847 dns_rdata_rrsig_t rrsig;
19848 isc_result_t result;
19849
19850 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
19851 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
19852 return (false);
19853 }
19854
19855 for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS;
19856 result = dns_rdataset_next(rdataset))
19857 {
19858 dns_rdataset_current(rdataset, &rdata);
19859 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
19860 RUNTIME_CHECK(result == ISC_R_SUCCESS);
19861 dns_rdata_reset(&rdata);
19862 if (rrsig.algorithm == alg) {
19863 return (true);
19864 }
19865 }
19866
19867 return (false);
19868 }
19869
19870 static isc_result_t
19871 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
19872 dns_diff_t *diff) {
19873 dns_name_t *origin;
19874 bool build_nsec3;
19875 isc_result_t result;
19876
19877 origin = dns_db_origin(db);
19878 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
19879 &build_nsec3));
19880 if (build_nsec3) {
19881 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
19882 false, zone->privatetype, diff));
19883 }
19884 CHECK(updatesecure(db, ver, origin, zone->minimum, true, diff));
19885
19886 failure:
19887 return (result);
19888 }
19889
19890 static void
19891 dnssec_report(const char *format, ...) {
19892 va_list args;
19893 va_start(args, format);
19894 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
19895 ISC_LOG_INFO, format, args);
19896 va_end(args);
19897 }
19898
19899 static void
19900 zone_rekey(dns_zone_t *zone) {
19901 isc_result_t result;
19902 dns_db_t *db = NULL;
19903 dns_dbnode_t *node = NULL;
19904 dns_dbversion_t *ver = NULL;
19905 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
19906 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
19907 dns_dnsseckey_t *key = NULL;
19908 dns_diff_t diff, _sig_diff;
19909 dns_kasp_t *kasp;
19910 dns__zonediff_t zonediff;
19911 bool commit = false, newactive = false;
19912 bool newalg = false;
19913 bool fullsign, use_kasp;
19914 dns_ttl_t ttl = 3600;
19915 const char *dir = NULL;
19916 isc_mem_t *mctx = NULL;
19917 isc_stdtime_t now, nexttime = 0;
19918 isc_time_t timenow;
19919 isc_interval_t ival;
19920 char timebuf[80];
19921
19922 REQUIRE(DNS_ZONE_VALID(zone));
19923
19924 ISC_LIST_INIT(dnskeys);
19925 ISC_LIST_INIT(keys);
19926 ISC_LIST_INIT(rmkeys);
19927 dns_rdataset_init(&soaset);
19928 dns_rdataset_init(&soasigs);
19929 dns_rdataset_init(&keyset);
19930 dns_rdataset_init(&keysigs);
19931 dns_rdataset_init(&cdsset);
19932 dns_rdataset_init(&cdnskeyset);
19933 dir = dns_zone_getkeydirectory(zone);
19934 mctx = zone->mctx;
19935 dns_diff_init(mctx, &diff);
19936 dns_diff_init(mctx, &_sig_diff);
19937 zonediff_init(&zonediff, &_sig_diff);
19938
19939 CHECK(dns_zone_getdb(zone, &db));
19940 CHECK(dns_db_newversion(db, &ver));
19941 CHECK(dns_db_getoriginnode(db, &node));
19942
19943 TIME_NOW(&timenow);
19944 now = isc_time_seconds(&timenow);
19945
19946 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
19947
19948 /* Get the SOA record's TTL */
19949 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
19950 dns_rdatatype_none, 0, &soaset, &soasigs));
19951 ttl = soaset.ttl;
19952 dns_rdataset_disassociate(&soaset);
19953
19954 /* Get the DNSKEY rdataset */
19955 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
19956 dns_rdatatype_none, 0, &keyset, &keysigs);
19957 if (result == ISC_R_SUCCESS) {
19958 ttl = keyset.ttl;
19959 CHECK(dns_dnssec_keylistfromrdataset(
19960 &zone->origin, dir, mctx, &keyset, &keysigs, &soasigs,
19961 false, false, &dnskeys));
19962 } else if (result != ISC_R_NOTFOUND) {
19963 goto failure;
19964 }
19965
19966 /* Get the CDS rdataset */
19967 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
19968 dns_rdatatype_none, 0, &cdsset, NULL);
19969 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset)) {
19970 dns_rdataset_disassociate(&cdsset);
19971 }
19972
19973 /* Get the CDNSKEY rdataset */
19974 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
19975 dns_rdatatype_none, 0, &cdnskeyset, NULL);
19976 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset)) {
19977 dns_rdataset_disassociate(&cdnskeyset);
19978 }
19979
19980 /*
19981 * True when called from "rndc sign". Indicates the zone should be
19982 * fully signed now.
19983 */
19984 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
19985
19986 kasp = dns_zone_getkasp(zone);
19987 use_kasp = dns_zone_use_kasp(zone);
19988 if (kasp != NULL) {
19989 LOCK(&kasp->lock);
19990 }
19991
19992 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
19993 &keys);
19994 if (result != ISC_R_SUCCESS) {
19995 dnssec_log(zone, ISC_LOG_DEBUG(1),
19996 "zone_rekey:dns_dnssec_findmatchingkeys failed: %s",
19997 isc_result_totext(result));
19998 }
19999
20000 if (use_kasp && (result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND)) {
20001 result = dns_keymgr_run(&zone->origin, zone->rdclass, dir, mctx,
20002 &keys, kasp, now, &nexttime);
20003 if (result != ISC_R_SUCCESS) {
20004 dnssec_log(zone, ISC_LOG_ERROR,
20005 "zone_rekey:dns_dnssec_keymgr failed: %s",
20006 isc_result_totext(result));
20007 goto failure;
20008 }
20009 }
20010
20011 if (kasp != NULL) {
20012 UNLOCK(&kasp->lock);
20013 }
20014
20015 if (result == ISC_R_SUCCESS) {
20016 /*
20017 * Publish CDS/CDNSKEY DELETE records if the zone is
20018 * transitioning from secure to insecure.
20019 */
20020 bool cds_delete = dns_zone_secure_to_insecure(zone, false);
20021 isc_stdtime_t when;
20022
20023 /*
20024 * Only update DNSKEY TTL if we have a policy.
20025 */
20026 if (kasp != NULL && strcmp(dns_kasp_getname(kasp), "none") != 0)
20027 {
20028 ttl = dns_kasp_dnskeyttl(kasp);
20029 }
20030
20031 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
20032 &zone->origin, ttl, &diff, mctx,
20033 dnssec_report);
20034 /*
20035 * Keys couldn't be updated for some reason;
20036 * try again later.
20037 */
20038 if (result != ISC_R_SUCCESS) {
20039 dnssec_log(zone, ISC_LOG_ERROR,
20040 "zone_rekey:couldn't update zone keys: %s",
20041 isc_result_totext(result));
20042 goto failure;
20043 }
20044
20045 /*
20046 * Update CDS / CDNSKEY records.
20047 */
20048 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
20049 &cdnskeyset, now, ttl, &diff,
20050 mctx);
20051 if (result != ISC_R_SUCCESS) {
20052 dnssec_log(zone, ISC_LOG_ERROR,
20053 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
20054 isc_result_totext(result));
20055 goto failure;
20056 }
20057
20058 if (cds_delete) {
20059 /*
20060 * Only publish CDS/CDNSKEY DELETE records if there is
20061 * a KSK that can be used to verify the RRset. This
20062 * means there must be a key with the KSK role that is
20063 * published and is used for signing.
20064 */
20065 cds_delete = false;
20066 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20067 key = ISC_LIST_NEXT(key, link)) {
20068 dst_key_t *dstk = key->key;
20069 bool ksk = false;
20070 (void)dst_key_getbool(dstk, DST_BOOL_KSK, &ksk);
20071 if (!ksk) {
20072 continue;
20073 }
20074
20075 if (dst_key_haskasp(dstk) &&
20076 dst_key_is_published(dstk, now, &when) &&
20077 dst_key_is_signing(dstk, DST_BOOL_KSK, now,
20078 &when))
20079 {
20080 cds_delete = true;
20081 break;
20082 }
20083 }
20084 }
20085 result = dns_dnssec_syncdelete(&cdsset, &cdnskeyset,
20086 &zone->origin, zone->rdclass,
20087 ttl, &diff, mctx, cds_delete);
20088 if (result != ISC_R_SUCCESS) {
20089 dnssec_log(zone, ISC_LOG_ERROR,
20090 "zone_rekey:couldn't update CDS/CDNSKEY "
20091 "DELETE records: %s",
20092 isc_result_totext(result));
20093 goto failure;
20094 }
20095
20096 /*
20097 * See if any pre-existing keys have newly become active;
20098 * also, see if any new key is for a new algorithm, as in that
20099 * event, we need to sign the zone fully. (If there's a new
20100 * key, but it's for an already-existing algorithm, then
20101 * the zone signing can be handled incrementally.)
20102 */
20103 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20104 key = ISC_LIST_NEXT(key, link)) {
20105 if (!key->first_sign) {
20106 continue;
20107 }
20108
20109 newactive = true;
20110
20111 if (!dns_rdataset_isassociated(&keysigs)) {
20112 newalg = true;
20113 break;
20114 }
20115
20116 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
20117 /*
20118 * This isn't a new algorithm; clear
20119 * first_sign so we won't sign the
20120 * whole zone with this key later.
20121 */
20122 key->first_sign = false;
20123 } else {
20124 newalg = true;
20125 break;
20126 }
20127 }
20128
20129 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
20130 dnskey_sane(zone, db, ver, &diff))
20131 {
20132 CHECK(dns_diff_apply(&diff, db, ver));
20133 CHECK(clean_nsec3param(zone, db, ver, &diff));
20134 CHECK(add_signing_records(db, zone->privatetype, ver,
20135 &diff, (newalg || fullsign)));
20136 CHECK(update_soa_serial(zone, db, ver, &diff, mctx,
20137 zone->updatemethod));
20138 CHECK(add_chains(zone, db, ver, &diff));
20139 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
20140 CHECK(zone_journal(zone, zonediff.diff, NULL,
20141 "zone_rekey"));
20142 commit = true;
20143 }
20144 }
20145
20146 dns_db_closeversion(db, &ver, true);
20147
20148 LOCK_ZONE(zone);
20149
20150 if (commit) {
20151 dns_difftuple_t *tuple;
20152
20153 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
20154
20155 zone_needdump(zone, DNS_DUMP_DELAY);
20156
20157 zone_settimer(zone, &timenow);
20158
20159 /* Remove any signatures from removed keys. */
20160 if (!ISC_LIST_EMPTY(rmkeys)) {
20161 for (key = ISC_LIST_HEAD(rmkeys); key != NULL;
20162 key = ISC_LIST_NEXT(key, link)) {
20163 result = zone_signwithkey(
20164 zone, dst_key_alg(key->key),
20165 dst_key_id(key->key), true);
20166 if (result != ISC_R_SUCCESS) {
20167 dnssec_log(zone, ISC_LOG_ERROR,
20168 "zone_signwithkey failed: "
20169 "%s",
20170 dns_result_totext(result));
20171 }
20172 }
20173 }
20174
20175 if (fullsign) {
20176 /*
20177 * "rndc sign" was called, so we now sign the zone
20178 * with all active keys, whether they're new or not.
20179 */
20180 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20181 key = ISC_LIST_NEXT(key, link)) {
20182 if (!key->force_sign && !key->hint_sign) {
20183 continue;
20184 }
20185
20186 result = zone_signwithkey(
20187 zone, dst_key_alg(key->key),
20188 dst_key_id(key->key), false);
20189 if (result != ISC_R_SUCCESS) {
20190 dnssec_log(zone, ISC_LOG_ERROR,
20191 "zone_signwithkey failed: "
20192 "%s",
20193 dns_result_totext(result));
20194 }
20195 }
20196 } else if (newalg) {
20197 /*
20198 * We haven't been told to sign fully, but a new
20199 * algorithm was added to the DNSKEY. We sign
20200 * the full zone, but only with newly active
20201 * keys.
20202 */
20203 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20204 key = ISC_LIST_NEXT(key, link)) {
20205 if (!key->first_sign) {
20206 continue;
20207 }
20208
20209 result = zone_signwithkey(
20210 zone, dst_key_alg(key->key),
20211 dst_key_id(key->key), false);
20212 if (result != ISC_R_SUCCESS) {
20213 dnssec_log(zone, ISC_LOG_ERROR,
20214 "zone_signwithkey failed: "
20215 "%s",
20216 dns_result_totext(result));
20217 }
20218 }
20219 }
20220
20221 /*
20222 * Clear fullsign flag, if it was set, so we don't do
20223 * another full signing next time.
20224 */
20225 DNS_ZONEKEY_CLROPTION(zone, DNS_ZONEKEY_FULLSIGN);
20226
20227 /*
20228 * Cause the zone to add/delete NSEC3 chains for the
20229 * deferred NSEC3PARAM changes.
20230 */
20231 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
20232 tuple != NULL; tuple = ISC_LIST_NEXT(tuple, link))
20233 {
20234 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
20235 dns_rdata_t rdata = DNS_RDATA_INIT;
20236 dns_rdata_nsec3param_t nsec3param;
20237
20238 if (tuple->rdata.type != zone->privatetype ||
20239 tuple->op != DNS_DIFFOP_ADD) {
20240 continue;
20241 }
20242
20243 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
20244 buf, sizeof(buf))) {
20245 continue;
20246 }
20247
20248 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
20249 RUNTIME_CHECK(result == ISC_R_SUCCESS);
20250 if (nsec3param.flags == 0) {
20251 continue;
20252 }
20253
20254 result = zone_addnsec3chain(zone, &nsec3param);
20255 if (result != ISC_R_SUCCESS) {
20256 dnssec_log(zone, ISC_LOG_ERROR,
20257 "zone_addnsec3chain failed: %s",
20258 dns_result_totext(result));
20259 }
20260 }
20261
20262 /*
20263 * Activate any NSEC3 chain updates that may have
20264 * been scheduled before this rekey.
20265 */
20266 if (fullsign || newalg) {
20267 resume_addnsec3chain(zone);
20268 }
20269
20270 /*
20271 * Schedule the next resigning event
20272 */
20273 set_resigntime(zone);
20274 }
20275
20276 isc_time_settoepoch(&zone->refreshkeytime);
20277
20278 /*
20279 * If keymgr provided a next time, use the calculated next rekey time.
20280 */
20281 if (use_kasp) {
20282 isc_time_t timenext;
20283 uint32_t nexttime_seconds;
20284
20285 /*
20286 * Set the key refresh timer to the next scheduled key event
20287 * or to 'dnssec-loadkeys-interval' seconds in the future
20288 * if no next key event is scheduled (nexttime == 0).
20289 */
20290 if (nexttime > 0) {
20291 nexttime_seconds = nexttime - now;
20292 } else {
20293 nexttime_seconds = zone->refreshkeyinterval;
20294 }
20295
20296 DNS_ZONE_TIME_ADD(&timenow, nexttime_seconds, &timenext);
20297 zone->refreshkeytime = timenext;
20298 zone_settimer(zone, &timenow);
20299 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
20300
20301 dnssec_log(zone, ISC_LOG_DEBUG(3),
20302 "next key event in %u seconds", nexttime_seconds);
20303 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
20304 }
20305 /*
20306 * If we're doing key maintenance, set the key refresh timer to
20307 * the next scheduled key event or to 'dnssec-loadkeys-interval'
20308 * seconds in the future, whichever is sooner.
20309 */
20310 else if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
20311 {
20312 isc_time_t timethen;
20313 isc_stdtime_t then;
20314
20315 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
20316 &timethen);
20317 zone->refreshkeytime = timethen;
20318
20319 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20320 key = ISC_LIST_NEXT(key, link)) {
20321 then = now;
20322 result = next_keyevent(key->key, &then);
20323 if (result != ISC_R_SUCCESS) {
20324 continue;
20325 }
20326
20327 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
20328 if (isc_time_compare(&timethen, &zone->refreshkeytime) <
20329 0) {
20330 zone->refreshkeytime = timethen;
20331 }
20332 }
20333
20334 zone_settimer(zone, &timenow);
20335
20336 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
20337 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
20338 }
20339 UNLOCK_ZONE(zone);
20340
20341 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
20342 for (key = ISC_LIST_HEAD(dnskeys); key != NULL;
20343 key = ISC_LIST_NEXT(key, link)) {
20344 /* This debug log is used in the kasp system test */
20345 char algbuf[DNS_SECALG_FORMATSIZE];
20346 dns_secalg_format(dst_key_alg(key->key), algbuf,
20347 sizeof(algbuf));
20348 dnssec_log(zone, ISC_LOG_DEBUG(3),
20349 "zone_rekey done: key %d/%s",
20350 dst_key_id(key->key), algbuf);
20351 }
20352 }
20353
20354 result = ISC_R_SUCCESS;
20355
20356 failure:
20357 LOCK_ZONE(zone);
20358 if (result != ISC_R_SUCCESS) {
20359 /*
20360 * Something went wrong; try again in ten minutes or
20361 * after a key refresh interval, whichever is shorter.
20362 */
20363 isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600),
20364 0);
20365 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
20366 }
20367 UNLOCK_ZONE(zone);
20368
20369 dns_diff_clear(&diff);
20370 dns_diff_clear(&_sig_diff);
20371
20372 clear_keylist(&dnskeys, mctx);
20373 clear_keylist(&keys, mctx);
20374 clear_keylist(&rmkeys, mctx);
20375
20376 if (ver != NULL) {
20377 dns_db_closeversion(db, &ver, false);
20378 }
20379 if (dns_rdataset_isassociated(&cdsset)) {
20380 dns_rdataset_disassociate(&cdsset);
20381 }
20382 if (dns_rdataset_isassociated(&keyset)) {
20383 dns_rdataset_disassociate(&keyset);
20384 }
20385 if (dns_rdataset_isassociated(&keysigs)) {
20386 dns_rdataset_disassociate(&keysigs);
20387 }
20388 if (dns_rdataset_isassociated(&soasigs)) {
20389 dns_rdataset_disassociate(&soasigs);
20390 }
20391 if (dns_rdataset_isassociated(&cdnskeyset)) {
20392 dns_rdataset_disassociate(&cdnskeyset);
20393 }
20394 if (node != NULL) {
20395 dns_db_detachnode(db, &node);
20396 }
20397 if (db != NULL) {
20398 dns_db_detach(&db);
20399 }
20400
20401 INSIST(ver == NULL);
20402 }
20403
20404 void
20405 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
20406 isc_time_t now;
20407
20408 if (zone->type == dns_zone_master && zone->task != NULL) {
20409 LOCK_ZONE(zone);
20410
20411 if (fullsign) {
20412 DNS_ZONEKEY_SETOPTION(zone, DNS_ZONEKEY_FULLSIGN);
20413 }
20414
20415 TIME_NOW(&now);
20416 zone->refreshkeytime = now;
20417 zone_settimer(zone, &now);
20418
20419 UNLOCK_ZONE(zone);
20420 }
20421 }
20422
20423 isc_result_t
20424 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
20425 unsigned int *errors) {
20426 isc_result_t result;
20427 dns_dbnode_t *node = NULL;
20428
20429 REQUIRE(DNS_ZONE_VALID(zone));
20430 REQUIRE(errors != NULL);
20431
20432 result = dns_db_getoriginnode(db, &node);
20433 if (result != ISC_R_SUCCESS) {
20434 return (result);
20435 }
20436 result = zone_count_ns_rr(zone, db, node, version, NULL, errors, false);
20437 dns_db_detachnode(db, &node);
20438 return (result);
20439 }
20440
20441 isc_result_t
20442 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
20443 isc_result_t result;
20444 dns_dbnode_t *node = NULL;
20445 dns_rdataset_t dnskey, cds, cdnskey;
20446 unsigned char buffer[DNS_DS_BUFFERSIZE];
20447 unsigned char algorithms[256];
20448 unsigned int i;
20449 bool empty = false;
20450
20451 enum { notexpected = 0, expected = 1, found = 2 };
20452
20453 REQUIRE(DNS_ZONE_VALID(zone));
20454
20455 result = dns_db_getoriginnode(db, &node);
20456 if (result != ISC_R_SUCCESS) {
20457 return (result);
20458 }
20459
20460 dns_rdataset_init(&cds);
20461 dns_rdataset_init(&dnskey);
20462 dns_rdataset_init(&cdnskey);
20463
20464 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
20465 dns_rdatatype_none, 0, &cds, NULL);
20466 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
20467 goto failure;
20468 }
20469
20470 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
20471 dns_rdatatype_none, 0, &cdnskey, NULL);
20472 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
20473 goto failure;
20474 }
20475
20476 if (!dns_rdataset_isassociated(&cds) &&
20477 !dns_rdataset_isassociated(&cdnskey)) {
20478 result = ISC_R_SUCCESS;
20479 goto failure;
20480 }
20481
20482 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
20483 dns_rdatatype_none, 0, &dnskey, NULL);
20484 if (result == ISC_R_NOTFOUND) {
20485 empty = true;
20486 } else if (result != ISC_R_SUCCESS) {
20487 goto failure;
20488 }
20489
20490 /*
20491 * For each DNSSEC algorithm in the CDS RRset there must be
20492 * a matching DNSKEY record with the exception of a CDS deletion
20493 * record which must be by itself.
20494 */
20495 if (dns_rdataset_isassociated(&cds)) {
20496 bool delete = false;
20497 memset(algorithms, notexpected, sizeof(algorithms));
20498 for (result = dns_rdataset_first(&cds); result == ISC_R_SUCCESS;
20499 result = dns_rdataset_next(&cds))
20500 {
20501 dns_rdata_t crdata = DNS_RDATA_INIT;
20502 dns_rdata_cds_t structcds;
20503
20504 dns_rdataset_current(&cds, &crdata);
20505 /*
20506 * CDS deletion record has this form "0 0 0 00" which
20507 * is 5 zero octets.
20508 */
20509 if (crdata.length == 5U &&
20510 memcmp(crdata.data,
20511 (unsigned char[5]){ 0, 0, 0, 0, 0 }, 5) == 0)
20512 {
20513 delete = true;
20514 continue;
20515 }
20516
20517 if (empty) {
20518 result = DNS_R_BADCDS;
20519 goto failure;
20520 }
20521
20522 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
20523 if (algorithms[structcds.algorithm] == 0) {
20524 algorithms[structcds.algorithm] = expected;
20525 }
20526 for (result = dns_rdataset_first(&dnskey);
20527 result == ISC_R_SUCCESS;
20528 result = dns_rdataset_next(&dnskey))
20529 {
20530 dns_rdata_t rdata = DNS_RDATA_INIT;
20531 dns_rdata_t dsrdata = DNS_RDATA_INIT;
20532
20533 dns_rdataset_current(&dnskey, &rdata);
20534 CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
20535 structcds.digest_type,
20536 buffer, &dsrdata));
20537 if (crdata.length == dsrdata.length &&
20538 memcmp(crdata.data, dsrdata.data,
20539 dsrdata.length) == 0)
20540 {
20541 algorithms[structcds.algorithm] = found;
20542 }
20543 }
20544 if (result != ISC_R_NOMORE) {
20545 goto failure;
20546 }
20547 }
20548 for (i = 0; i < sizeof(algorithms); i++) {
20549 if (delete) {
20550 if (algorithms[i] != notexpected) {
20551 result = DNS_R_BADCDS;
20552 goto failure;
20553 }
20554 } else if (algorithms[i] == expected) {
20555 result = DNS_R_BADCDS;
20556 goto failure;
20557 }
20558 }
20559 }
20560
20561 /*
20562 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
20563 * a matching DNSKEY record with the exception of a CDNSKEY deletion
20564 * record which must be by itself.
20565 */
20566 if (dns_rdataset_isassociated(&cdnskey)) {
20567 bool delete = false;
20568 memset(algorithms, notexpected, sizeof(algorithms));
20569 for (result = dns_rdataset_first(&cdnskey);
20570 result == ISC_R_SUCCESS;
20571 result = dns_rdataset_next(&cdnskey))
20572 {
20573 dns_rdata_t crdata = DNS_RDATA_INIT;
20574 dns_rdata_cdnskey_t structcdnskey;
20575
20576 dns_rdataset_current(&cdnskey, &crdata);
20577 /*
20578 * CDNSKEY deletion record has this form
20579 * "0 3 0 AA==" which is 2 zero octets, a 3,
20580 * and 2 zero octets.
20581 */
20582 if (crdata.length == 5U &&
20583 memcmp(crdata.data,
20584 (unsigned char[5]){ 0, 0, 3, 0, 0 }, 5) == 0)
20585 {
20586 delete = true;
20587 continue;
20588 }
20589
20590 if (empty) {
20591 result = DNS_R_BADCDNSKEY;
20592 goto failure;
20593 }
20594
20595 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
20596 NULL));
20597 if (algorithms[structcdnskey.algorithm] == 0) {
20598 algorithms[structcdnskey.algorithm] = expected;
20599 }
20600 for (result = dns_rdataset_first(&dnskey);
20601 result == ISC_R_SUCCESS;
20602 result = dns_rdataset_next(&dnskey))
20603 {
20604 dns_rdata_t rdata = DNS_RDATA_INIT;
20605
20606 dns_rdataset_current(&dnskey, &rdata);
20607 if (crdata.length == rdata.length &&
20608 memcmp(crdata.data, rdata.data,
20609 rdata.length) == 0)
20610 {
20611 algorithms[structcdnskey.algorithm] =
20612 found;
20613 }
20614 }
20615 if (result != ISC_R_NOMORE) {
20616 goto failure;
20617 }
20618 }
20619 for (i = 0; i < sizeof(algorithms); i++) {
20620 if (delete) {
20621 if (algorithms[i] != notexpected) {
20622 result = DNS_R_BADCDNSKEY;
20623 goto failure;
20624 }
20625 } else if (algorithms[i] == expected) {
20626 result = DNS_R_BADCDNSKEY;
20627 goto failure;
20628 }
20629 }
20630 }
20631 result = ISC_R_SUCCESS;
20632
20633 failure:
20634 if (dns_rdataset_isassociated(&cds)) {
20635 dns_rdataset_disassociate(&cds);
20636 }
20637 if (dns_rdataset_isassociated(&dnskey)) {
20638 dns_rdataset_disassociate(&dnskey);
20639 }
20640 if (dns_rdataset_isassociated(&cdnskey)) {
20641 dns_rdataset_disassociate(&cdnskey);
20642 }
20643 dns_db_detachnode(db, &node);
20644 return (result);
20645 }
20646
20647 void
20648 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
20649 REQUIRE(DNS_ZONE_VALID(zone));
20650
20651 LOCK_ZONE(zone);
20652 zone->automatic = automatic;
20653 UNLOCK_ZONE(zone);
20654 }
20655
20656 bool
20657 dns_zone_getautomatic(dns_zone_t *zone) {
20658 REQUIRE(DNS_ZONE_VALID(zone));
20659 return (zone->automatic);
20660 }
20661
20662 void
20663 dns_zone_setadded(dns_zone_t *zone, bool added) {
20664 REQUIRE(DNS_ZONE_VALID(zone));
20665
20666 LOCK_ZONE(zone);
20667 zone->added = added;
20668 UNLOCK_ZONE(zone);
20669 }
20670
20671 bool
20672 dns_zone_getadded(dns_zone_t *zone) {
20673 REQUIRE(DNS_ZONE_VALID(zone));
20674 return (zone->added);
20675 }
20676
20677 isc_result_t
20678 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db) {
20679 isc_time_t loadtime;
20680 isc_result_t result;
20681 dns_zone_t *secure = NULL;
20682
20683 TIME_NOW(&loadtime);
20684
20685 /*
20686 * Lock hierarchy: zmgr, zone, raw.
20687 */
20688 again:
20689 LOCK_ZONE(zone);
20690 INSIST(zone != zone->raw);
20691 if (inline_secure(zone)) {
20692 LOCK_ZONE(zone->raw);
20693 } else if (inline_raw(zone)) {
20694 secure = zone->secure;
20695 TRYLOCK_ZONE(result, secure);
20696 if (result != ISC_R_SUCCESS) {
20697 UNLOCK_ZONE(zone);
20698 secure = NULL;
20699 isc_thread_yield();
20700 goto again;
20701 }
20702 }
20703 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
20704 if (inline_secure(zone)) {
20705 UNLOCK_ZONE(zone->raw);
20706 } else if (secure != NULL) {
20707 UNLOCK_ZONE(secure);
20708 }
20709 UNLOCK_ZONE(zone);
20710 return (result);
20711 }
20712
20713 isc_result_t
20714 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
20715 REQUIRE(DNS_ZONE_VALID(zone));
20716 if (interval == 0) {
20717 return (ISC_R_RANGE);
20718 }
20719 /* Maximum value: 24 hours (3600 minutes) */
20720 if (interval > (24 * 60)) {
20721 interval = (24 * 60);
20722 }
20723 /* Multiply by 60 for seconds */
20724 zone->refreshkeyinterval = interval * 60;
20725 return (ISC_R_SUCCESS);
20726 }
20727
20728 void
20729 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
20730 REQUIRE(DNS_ZONE_VALID(zone));
20731 zone->requestixfr = flag;
20732 }
20733
20734 bool
20735 dns_zone_getrequestixfr(dns_zone_t *zone) {
20736 REQUIRE(DNS_ZONE_VALID(zone));
20737 return (zone->requestixfr);
20738 }
20739
20740 void
20741 dns_zone_setixfrratio(dns_zone_t *zone, uint32_t ratio) {
20742 REQUIRE(DNS_ZONE_VALID(zone));
20743 zone->ixfr_ratio = ratio;
20744 }
20745
20746 uint32_t
20747 dns_zone_getixfrratio(dns_zone_t *zone) {
20748 REQUIRE(DNS_ZONE_VALID(zone));
20749 return (zone->ixfr_ratio);
20750 }
20751
20752 void
20753 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
20754 REQUIRE(DNS_ZONE_VALID(zone));
20755 zone->requestexpire = flag;
20756 }
20757
20758 bool
20759 dns_zone_getrequestexpire(dns_zone_t *zone) {
20760 REQUIRE(DNS_ZONE_VALID(zone));
20761 return (zone->requestexpire);
20762 }
20763
20764 void
20765 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
20766 REQUIRE(DNS_ZONE_VALID(zone));
20767 zone->updatemethod = method;
20768 }
20769
20770 dns_updatemethod_t
20771 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
20772 REQUIRE(DNS_ZONE_VALID(zone));
20773 return (zone->updatemethod);
20774 }
20775
20776 /*
20777 * Lock hierarchy: zmgr, zone, raw.
20778 */
20779 isc_result_t
20780 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
20781 isc_result_t result;
20782 dns_zonemgr_t *zmgr;
20783
20784 REQUIRE(DNS_ZONE_VALID(zone));
20785 REQUIRE(zone->zmgr != NULL);
20786 REQUIRE(zone->task != NULL);
20787 REQUIRE(zone->loadtask != NULL);
20788 REQUIRE(zone->raw == NULL);
20789
20790 REQUIRE(DNS_ZONE_VALID(raw));
20791 REQUIRE(raw->zmgr == NULL);
20792 REQUIRE(raw->task == NULL);
20793 REQUIRE(raw->loadtask == NULL);
20794 REQUIRE(raw->secure == NULL);
20795
20796 REQUIRE(zone != raw);
20797
20798 /*
20799 * Lock hierarchy: zmgr, zone, raw.
20800 */
20801 zmgr = zone->zmgr;
20802 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
20803 LOCK_ZONE(zone);
20804 LOCK_ZONE(raw);
20805
20806 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, NULL,
20807 NULL, zone->task, zone_timer, raw,
20808 &raw->timer);
20809 if (result != ISC_R_SUCCESS) {
20810 goto unlock;
20811 }
20812
20813 /*
20814 * The timer "holds" a iref.
20815 */
20816 isc_refcount_increment0(&raw->irefs);
20817
20818 /* dns_zone_attach(raw, &zone->raw); */
20819 isc_refcount_increment(&raw->erefs);
20820 zone->raw = raw;
20821
20822 /* dns_zone_iattach(zone, &raw->secure); */
20823 zone_iattach(zone, &raw->secure);
20824
20825 isc_task_attach(zone->task, &raw->task);
20826 isc_task_attach(zone->loadtask, &raw->loadtask);
20827
20828 ISC_LIST_APPEND(zmgr->zones, raw, link);
20829 raw->zmgr = zmgr;
20830 isc_refcount_increment(&zmgr->refs);
20831
20832 unlock:
20833 UNLOCK_ZONE(raw);
20834 UNLOCK_ZONE(zone);
20835 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
20836 return (result);
20837 }
20838
20839 void
20840 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
20841 REQUIRE(DNS_ZONE_VALID(zone));
20842 REQUIRE(raw != NULL && *raw == NULL);
20843
20844 LOCK(&zone->lock);
20845 INSIST(zone != zone->raw);
20846 if (zone->raw != NULL) {
20847 dns_zone_attach(zone->raw, raw);
20848 }
20849 UNLOCK(&zone->lock);
20850 }
20851
20852 struct keydone {
20853 isc_event_t event;
20854 bool all;
20855 unsigned char data[5];
20856 };
20857
20858 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL)
20859
20860 static void
20861 keydone(isc_task_t *task, isc_event_t *event) {
20862 const char *me = "keydone";
20863 bool commit = false;
20864 isc_result_t result;
20865 dns_rdata_t rdata = DNS_RDATA_INIT;
20866 dns_dbversion_t *oldver = NULL, *newver = NULL;
20867 dns_zone_t *zone;
20868 dns_db_t *db = NULL;
20869 dns_dbnode_t *node = NULL;
20870 dns_rdataset_t rdataset;
20871 dns_diff_t diff;
20872 struct keydone *kd = (struct keydone *)event;
20873 dns_update_log_t log = { update_log_cb, NULL };
20874 bool clear_pending = false;
20875
20876 UNUSED(task);
20877
20878 zone = event->ev_arg;
20879 INSIST(DNS_ZONE_VALID(zone));
20880
20881 ENTER;
20882
20883 dns_rdataset_init(&rdataset);
20884 dns_diff_init(zone->mctx, &diff);
20885
20886 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
20887 if (zone->db != NULL) {
20888 dns_db_attach(zone->db, &db);
20889 }
20890 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
20891 if (db == NULL) {
20892 goto failure;
20893 }
20894
20895 dns_db_currentversion(db, &oldver);
20896 result = dns_db_newversion(db, &newver);
20897 if (result != ISC_R_SUCCESS) {
20898 dnssec_log(zone, ISC_LOG_ERROR,
20899 "keydone:dns_db_newversion -> %s",
20900 dns_result_totext(result));
20901 goto failure;
20902 }
20903
20904 result = dns_db_getoriginnode(db, &node);
20905 if (result != ISC_R_SUCCESS) {
20906 goto failure;
20907 }
20908
20909 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
20910 dns_rdatatype_none, 0, &rdataset, NULL);
20911 if (result == ISC_R_NOTFOUND) {
20912 INSIST(!dns_rdataset_isassociated(&rdataset));
20913 goto failure;
20914 }
20915 if (result != ISC_R_SUCCESS) {
20916 INSIST(!dns_rdataset_isassociated(&rdataset));
20917 goto failure;
20918 }
20919
20920 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
20921 result = dns_rdataset_next(&rdataset))
20922 {
20923 bool found = false;
20924
20925 dns_rdataset_current(&rdataset, &rdata);
20926
20927 if (kd->all) {
20928 if (rdata.length == 5 && rdata.data[0] != 0 &&
20929 rdata.data[3] == 0 && rdata.data[4] == 1)
20930 {
20931 found = true;
20932 } else if (rdata.data[0] == 0 &&
20933 (rdata.data[2] & PENDINGFLAGS) != 0) {
20934 found = true;
20935 clear_pending = true;
20936 }
20937 } else if (rdata.length == 5 &&
20938 memcmp(rdata.data, kd->data, 5) == 0) {
20939 found = true;
20940 }
20941
20942 if (found) {
20943 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
20944 &zone->origin, rdataset.ttl,
20945 &rdata));
20946 }
20947 dns_rdata_reset(&rdata);
20948 }
20949
20950 if (!ISC_LIST_EMPTY(diff.tuples)) {
20951 /* Write changes to journal file. */
20952 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
20953 zone->updatemethod));
20954
20955 result = dns_update_signatures(&log, zone, db, oldver, newver,
20956 &diff,
20957 zone->sigvalidityinterval);
20958 if (!clear_pending) {
20959 CHECK(result);
20960 }
20961
20962 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
20963 commit = true;
20964
20965 LOCK_ZONE(zone);
20966 DNS_ZONE_SETFLAG(zone,
20967 DNS_ZONEFLG_LOADED | DNS_ZONEFLG_NEEDNOTIFY);
20968 zone_needdump(zone, 30);
20969 UNLOCK_ZONE(zone);
20970 }
20971
20972 failure:
20973 if (dns_rdataset_isassociated(&rdataset)) {
20974 dns_rdataset_disassociate(&rdataset);
20975 }
20976 if (db != NULL) {
20977 if (node != NULL) {
20978 dns_db_detachnode(db, &node);
20979 }
20980 if (oldver != NULL) {
20981 dns_db_closeversion(db, &oldver, false);
20982 }
20983 if (newver != NULL) {
20984 dns_db_closeversion(db, &newver, commit);
20985 }
20986 dns_db_detach(&db);
20987 }
20988 dns_diff_clear(&diff);
20989 isc_event_free(&event);
20990 dns_zone_idetach(&zone);
20991
20992 INSIST(oldver == NULL);
20993 INSIST(newver == NULL);
20994 }
20995
20996 isc_result_t
20997 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
20998 isc_result_t result = ISC_R_SUCCESS;
20999 isc_event_t *e;
21000 isc_buffer_t b;
21001 dns_zone_t *dummy = NULL;
21002 struct keydone *kd;
21003
21004 REQUIRE(DNS_ZONE_VALID(zone));
21005
21006 LOCK_ZONE(zone);
21007
21008 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
21009 zone, sizeof(struct keydone));
21010
21011 kd = (struct keydone *)e;
21012 if (strcasecmp(keystr, "all") == 0) {
21013 kd->all = true;
21014 } else {
21015 isc_textregion_t r;
21016 const char *algstr;
21017 dns_keytag_t keyid;
21018 dns_secalg_t alg;
21019 size_t n;
21020
21021 kd->all = false;
21022
21023 n = sscanf(keystr, "%hu/", &keyid);
21024 if (n == 0U) {
21025 CHECK(ISC_R_FAILURE);
21026 }
21027
21028 algstr = strchr(keystr, '/');
21029 if (algstr != NULL) {
21030 algstr++;
21031 } else {
21032 CHECK(ISC_R_FAILURE);
21033 }
21034
21035 n = sscanf(algstr, "%hhu", &alg);
21036 if (n == 0U) {
21037 DE_CONST(algstr, r.base);
21038 r.length = strlen(algstr);
21039 CHECK(dns_secalg_fromtext(&alg, &r));
21040 }
21041
21042 /* construct a private-type rdata */
21043 isc_buffer_init(&b, kd->data, sizeof(kd->data));
21044 isc_buffer_putuint8(&b, alg);
21045 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
21046 isc_buffer_putuint8(&b, (keyid & 0xff));
21047 isc_buffer_putuint8(&b, 0);
21048 isc_buffer_putuint8(&b, 1);
21049 }
21050
21051 zone_iattach(zone, &dummy);
21052 isc_task_send(zone->task, &e);
21053
21054 failure:
21055 if (e != NULL) {
21056 isc_event_free(&e);
21057 }
21058 UNLOCK_ZONE(zone);
21059 return (result);
21060 }
21061
21062 /*
21063 * Called from the zone task's queue after the relevant event is posted by
21064 * dns_zone_setnsec3param().
21065 */
21066 static void
21067 setnsec3param(isc_task_t *task, isc_event_t *event) {
21068 const char *me = "setnsec3param";
21069 dns_zone_t *zone = event->ev_arg;
21070
21071 INSIST(DNS_ZONE_VALID(zone));
21072
21073 UNUSED(task);
21074
21075 ENTER;
21076
21077 /*
21078 * If receive_secure_serial is still processing or we have a
21079 * queued event append rss_post queue.
21080 */
21081 if (zone->rss_newver != NULL || ISC_LIST_HEAD(zone->rss_post) != NULL) {
21082 /*
21083 * Wait for receive_secure_serial() to finish processing.
21084 */
21085 ISC_LIST_APPEND(zone->rss_post, event, ev_link);
21086 } else {
21087 rss_post(zone, event);
21088 }
21089 dns_zone_idetach(&zone);
21090 }
21091
21092 /*
21093 * Check whether NSEC3 chain addition or removal specified by the private-type
21094 * record passed with the event was already queued (or even fully performed).
21095 * If not, modify the relevant private-type records at the zone apex and call
21096 * resume_addnsec3chain().
21097 */
21098 static void
21099 rss_post(dns_zone_t *zone, isc_event_t *event) {
21100 const char *me = "rss_post";
21101 bool commit = false;
21102 isc_result_t result;
21103 dns_dbversion_t *oldver = NULL, *newver = NULL;
21104 dns_db_t *db = NULL;
21105 dns_dbnode_t *node = NULL;
21106 dns_rdataset_t prdataset, nrdataset;
21107 dns_diff_t diff;
21108 struct np3event *npe = (struct np3event *)event;
21109 nsec3param_t *np;
21110 dns_update_log_t log = { update_log_cb, NULL };
21111 dns_rdata_t rdata;
21112 bool nseconly;
21113 bool exists = false;
21114
21115 ENTER;
21116
21117 np = &npe->params;
21118
21119 dns_rdataset_init(&prdataset);
21120 dns_rdataset_init(&nrdataset);
21121 dns_diff_init(zone->mctx, &diff);
21122
21123 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
21124 if (zone->db != NULL) {
21125 dns_db_attach(zone->db, &db);
21126 }
21127 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
21128 if (db == NULL) {
21129 goto failure;
21130 }
21131
21132 dns_db_currentversion(db, &oldver);
21133 result = dns_db_newversion(db, &newver);
21134 if (result != ISC_R_SUCCESS) {
21135 dnssec_log(zone, ISC_LOG_ERROR,
21136 "setnsec3param:dns_db_newversion -> %s",
21137 dns_result_totext(result));
21138 goto failure;
21139 }
21140
21141 CHECK(dns_db_getoriginnode(db, &node));
21142
21143 /*
21144 * Does a private-type record already exist for this chain?
21145 */
21146 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
21147 dns_rdatatype_none, 0, &prdataset, NULL);
21148 if (result == ISC_R_SUCCESS) {
21149 for (result = dns_rdataset_first(&prdataset);
21150 result == ISC_R_SUCCESS;
21151 result = dns_rdataset_next(&prdataset))
21152 {
21153 dns_rdata_init(&rdata);
21154 dns_rdataset_current(&prdataset, &rdata);
21155
21156 if (np->length == rdata.length &&
21157 memcmp(rdata.data, np->data, np->length) == 0) {
21158 exists = true;
21159 break;
21160 }
21161 }
21162 } else if (result != ISC_R_NOTFOUND) {
21163 INSIST(!dns_rdataset_isassociated(&prdataset));
21164 goto failure;
21165 }
21166
21167 /*
21168 * Does the chain already exist?
21169 */
21170 result = dns_db_findrdataset(db, node, newver, dns_rdatatype_nsec3param,
21171 dns_rdatatype_none, 0, &nrdataset, NULL);
21172 if (result == ISC_R_SUCCESS) {
21173 for (result = dns_rdataset_first(&nrdataset);
21174 result == ISC_R_SUCCESS;
21175 result = dns_rdataset_next(&nrdataset))
21176 {
21177 dns_rdata_init(&rdata);
21178 dns_rdataset_current(&nrdataset, &rdata);
21179
21180 if (np->length == (rdata.length + 1) &&
21181 memcmp(rdata.data, np->data + 1, np->length - 1) ==
21182 0)
21183 {
21184 exists = true;
21185 break;
21186 }
21187 }
21188 } else if (result != ISC_R_NOTFOUND) {
21189 INSIST(!dns_rdataset_isassociated(&nrdataset));
21190 goto failure;
21191 }
21192
21193 /*
21194 * We need to remove any existing NSEC3 chains if the supplied NSEC3
21195 * parameters are supposed to replace the current ones or if we are
21196 * switching to NSEC.
21197 */
21198 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
21199 CHECK(dns_nsec3param_deletechains(db, newver, zone, !np->nsec,
21200 &diff));
21201 }
21202
21203 if (!exists && np->length != 0) {
21204 /*
21205 * We're creating an NSEC3 chain. Add the private-type record
21206 * passed in the event handler's argument to the zone apex.
21207 *
21208 * If the zone is not currently capable of supporting an NSEC3
21209 * chain (due to the DNSKEY RRset at the zone apex not existing
21210 * or containing at least one key using an NSEC-only
21211 * algorithm), add the INITIAL flag, so these parameters can be
21212 * used later when NSEC3 becomes available.
21213 */
21214 dns_rdata_init(&rdata);
21215
21216 np->data[2] |= DNS_NSEC3FLAG_CREATE;
21217 result = dns_nsec_nseconly(db, newver, &nseconly);
21218 if (result == ISC_R_NOTFOUND || nseconly) {
21219 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
21220 }
21221
21222 rdata.length = np->length;
21223 rdata.data = np->data;
21224 rdata.type = zone->privatetype;
21225 rdata.rdclass = zone->rdclass;
21226 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
21227 &zone->origin, 0, &rdata));
21228 }
21229
21230 /*
21231 * If we changed anything in the zone, write changes to journal file
21232 * and set commit to true so that resume_addnsec3chain() will be
21233 * called below in order to kick off adding/removing relevant NSEC3
21234 * records.
21235 */
21236 if (!ISC_LIST_EMPTY(diff.tuples)) {
21237 CHECK(update_soa_serial(zone, db, newver, &diff, zone->mctx,
21238 zone->updatemethod));
21239 result = dns_update_signatures(&log, zone, db, oldver, newver,
21240 &diff,
21241 zone->sigvalidityinterval);
21242 if (result != ISC_R_NOTFOUND) {
21243 CHECK(result);
21244 }
21245 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
21246 commit = true;
21247
21248 LOCK_ZONE(zone);
21249 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
21250 zone_needdump(zone, 30);
21251 UNLOCK_ZONE(zone);
21252 }
21253
21254 failure:
21255 if (dns_rdataset_isassociated(&prdataset)) {
21256 dns_rdataset_disassociate(&prdataset);
21257 }
21258 if (dns_rdataset_isassociated(&nrdataset)) {
21259 dns_rdataset_disassociate(&nrdataset);
21260 }
21261 if (node != NULL) {
21262 dns_db_detachnode(db, &node);
21263 }
21264 if (oldver != NULL) {
21265 dns_db_closeversion(db, &oldver, false);
21266 }
21267 if (newver != NULL) {
21268 dns_db_closeversion(db, &newver, commit);
21269 }
21270 if (db != NULL) {
21271 dns_db_detach(&db);
21272 }
21273 if (commit) {
21274 LOCK_ZONE(zone);
21275 resume_addnsec3chain(zone);
21276 UNLOCK_ZONE(zone);
21277 }
21278 dns_diff_clear(&diff);
21279 isc_event_free(&event);
21280
21281 INSIST(oldver == NULL);
21282 INSIST(newver == NULL);
21283 }
21284
21285 static void
21286 salt2text(unsigned char *salt, uint8_t saltlen, unsigned char *text,
21287 unsigned int textlen) {
21288 isc_region_t r;
21289 isc_buffer_t buf;
21290 isc_result_t result;
21291
21292 r.base = salt;
21293 r.length = (unsigned int)saltlen;
21294
21295 isc_buffer_init(&buf, text, textlen);
21296 result = isc_hex_totext(&r, 2, "", &buf);
21297 if (result == ISC_R_SUCCESS) {
21298 text[saltlen * 2] = 0;
21299 } else {
21300 text[0] = 0;
21301 }
21302 }
21303
21304 /*
21305 * Check if zone has NSEC3PARAM (and thus a chain) with the right parameters.
21306 *
21307 * If 'salt' is NULL, a match is found if the salt has the requested length,
21308 * otherwise the NSEC3 salt must match the requested salt value too.
21309 *
21310 * Returns ISC_R_SUCCESS, if a match is found, or an error if no match is
21311 * found, or if the db lookup failed.
21312 */
21313 isc_result_t
21314 dns__zone_lookup_nsec3param(dns_zone_t *zone, dns_rdata_nsec3param_t *lookup,
21315 dns_rdata_nsec3param_t *param,
21316 unsigned char saltbuf[255], bool resalt) {
21317 isc_result_t result = ISC_R_UNEXPECTED;
21318 dns_dbnode_t *node = NULL;
21319 dns_db_t *db = NULL;
21320 dns_dbversion_t *version = NULL;
21321 dns_rdataset_t rdataset;
21322 dns_rdata_nsec3param_t nsec3param;
21323 dns_rdata_t rdata = DNS_RDATA_INIT;
21324
21325 REQUIRE(DNS_ZONE_VALID(zone));
21326
21327 dns_rdataset_init(&rdataset);
21328
21329 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
21330 if (zone->db != NULL) {
21331 dns_db_attach(zone->db, &db);
21332 }
21333 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
21334 if (db == NULL) {
21335 goto setparam;
21336 }
21337
21338 result = dns_db_findnode(db, &zone->origin, false, &node);
21339 if (result != ISC_R_SUCCESS) {
21340 dns_zone_log(zone, ISC_LOG_ERROR,
21341 "nsec3param lookup failure: %s",
21342 dns_result_totext(result));
21343 goto setparam;
21344 }
21345 dns_db_currentversion(db, &version);
21346
21347 result = dns_db_findrdataset(db, node, version,
21348 dns_rdatatype_nsec3param,
21349 dns_rdatatype_none, 0, &rdataset, NULL);
21350 if (result != ISC_R_SUCCESS) {
21351 INSIST(!dns_rdataset_isassociated(&rdataset));
21352 if (result != ISC_R_NOTFOUND) {
21353 dns_zone_log(zone, ISC_LOG_ERROR,
21354 "nsec3param lookup failure: %s",
21355 dns_result_totext(result));
21356 }
21357 goto setparam;
21358 }
21359
21360 for (result = dns_rdataset_first(&rdataset); result == ISC_R_SUCCESS;
21361 result = dns_rdataset_next(&rdataset))
21362 {
21363 dns_rdataset_current(&rdataset, &rdata);
21364 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
21365 INSIST(result == ISC_R_SUCCESS);
21366 dns_rdata_reset(&rdata);
21367
21368 /* Check parameters. */
21369 if (nsec3param.hash != lookup->hash) {
21370 continue;
21371 }
21372 if (nsec3param.iterations != lookup->iterations) {
21373 continue;
21374 }
21375 if (nsec3param.salt_length != lookup->salt_length) {
21376 continue;
21377 }
21378 if (lookup->salt != NULL) {
21379 if (memcmp(nsec3param.salt, lookup->salt,
21380 lookup->salt_length) != 0) {
21381 continue;
21382 }
21383 }
21384 /* Found a match. */
21385 result = ISC_R_SUCCESS;
21386 param->hash = nsec3param.hash;
21387 param->flags = nsec3param.flags;
21388 param->iterations = nsec3param.iterations;
21389 param->salt_length = nsec3param.salt_length;
21390 param->salt = nsec3param.salt;
21391 break;
21392 }
21393
21394 setparam:
21395 if (result != ISC_R_SUCCESS) {
21396 /* Found no match. */
21397 result = ISC_R_NOTFOUND;
21398 param->hash = lookup->hash;
21399 param->flags = lookup->flags;
21400 param->iterations = lookup->iterations;
21401 param->salt_length = lookup->salt_length;
21402 param->salt = lookup->salt;
21403 }
21404
21405 if (param->salt_length == 0) {
21406 DE_CONST("-", param->salt);
21407 } else if (resalt || param->salt == NULL) {
21408 unsigned char *newsalt;
21409 unsigned char salttext[255 * 2 + 1];
21410 do {
21411 /* Generate a new salt. */
21412 result = dns_nsec3_generate_salt(saltbuf,
21413 param->salt_length);
21414 if (result != ISC_R_SUCCESS) {
21415 break;
21416 }
21417 newsalt = saltbuf;
21418 salt2text(newsalt, param->salt_length, salttext,
21419 sizeof(salttext));
21420 dnssec_log(zone, ISC_LOG_INFO, "generated salt: %s",
21421 salttext);
21422 /* Check for salt conflict. */
21423 if (param->salt != NULL &&
21424 memcmp(newsalt, param->salt, param->salt_length) ==
21425 0)
21426 {
21427 result = ISC_R_SUCCESS;
21428 } else {
21429 param->salt = newsalt;
21430 result = DNS_R_NSEC3RESALT;
21431 }
21432 } while (result == ISC_R_SUCCESS);
21433
21434 INSIST(result != ISC_R_SUCCESS);
21435 }
21436
21437 if (dns_rdataset_isassociated(&rdataset)) {
21438 dns_rdataset_disassociate(&rdataset);
21439 }
21440 if (node != NULL) {
21441 dns_db_detachnode(db, &node);
21442 }
21443 if (version != NULL) {
21444 dns_db_closeversion(db, &version, false);
21445 }
21446 if (db != NULL) {
21447 dns_db_detach(&db);
21448 }
21449
21450 return (result);
21451 }
21452
21453 /*
21454 * Called when an "rndc signing -nsec3param ..." command is received, or the
21455 * 'dnssec-policy' has changed.
21456 *
21457 * Allocate and prepare an nsec3param_t structure which holds information about
21458 * the NSEC3 changes requested for the zone:
21459 *
21460 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
21461 * field of the structure to true and the "replace" field to the value
21462 * of the "replace" argument, leaving other fields initialized to zeros, to
21463 * signal that the zone should be signed using NSEC instead of NSEC3,
21464 *
21465 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
21466 * the zone apex, convert it to a private-type record and store the latter
21467 * in the "data" field of the nsec3param_t structure.
21468 *
21469 * Once the nsec3param_t structure is prepared, post an event to the zone's
21470 * task which will cause setnsec3param() to be called with the prepared
21471 * structure passed as an argument.
21472 */
21473 isc_result_t
21474 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
21475 uint16_t iter, uint8_t saltlen, unsigned char *salt,
21476 bool replace, bool resalt) {
21477 isc_result_t result = ISC_R_SUCCESS;
21478 dns_rdata_nsec3param_t param, lookup;
21479 dns_rdata_t nrdata = DNS_RDATA_INIT;
21480 dns_rdata_t prdata = DNS_RDATA_INIT;
21481 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
21482 unsigned char saltbuf[255];
21483 struct np3event *npe;
21484 nsec3param_t *np;
21485 dns_zone_t *dummy = NULL;
21486 isc_buffer_t b;
21487 isc_event_t *e = NULL;
21488
21489 REQUIRE(DNS_ZONE_VALID(zone));
21490
21491 LOCK_ZONE(zone);
21492
21493 /*
21494 * First check if the requested NSEC3 parameters are already set,
21495 * if so, no need to set again.
21496 */
21497 if (hash != 0) {
21498 lookup.hash = hash;
21499 lookup.flags = flags;
21500 lookup.iterations = iter;
21501 lookup.salt_length = saltlen;
21502 lookup.salt = salt;
21503 param.salt = NULL;
21504 result = dns__zone_lookup_nsec3param(zone, &lookup, ¶m,
21505 saltbuf, resalt);
21506 if (result == ISC_R_SUCCESS) {
21507 UNLOCK_ZONE(zone);
21508 return (ISC_R_SUCCESS);
21509 }
21510 INSIST(param.salt != NULL);
21511 }
21512
21513 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
21514 setnsec3param, zone, sizeof(struct np3event));
21515
21516 npe = (struct np3event *)e;
21517 np = &npe->params;
21518
21519 np->replace = replace;
21520 if (hash == 0) {
21521 np->length = 0;
21522 np->nsec = true;
21523 dnssec_log(zone, ISC_LOG_DEBUG(3), "setnsec3param:nsec");
21524 } else {
21525 param.common.rdclass = zone->rdclass;
21526 param.common.rdtype = dns_rdatatype_nsec3param;
21527 ISC_LINK_INIT(¶m.common, link);
21528 param.mctx = NULL;
21529 /* nsec3 specific param set in dns__zone_lookup_nsec3param() */
21530 isc_buffer_init(&b, nbuf, sizeof(nbuf));
21531 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
21532 dns_rdatatype_nsec3param, ¶m,
21533 &b));
21534 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
21535 np->data, sizeof(np->data));
21536 np->length = prdata.length;
21537 np->nsec = false;
21538
21539 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
21540 unsigned char salttext[255 * 2 + 1];
21541 salt2text(param.salt, param.salt_length, salttext,
21542 sizeof(salttext));
21543 dnssec_log(zone, ISC_LOG_DEBUG(3),
21544 "setnsec3param:nsec3 %u %u %u %s",
21545 param.hash, param.flags, param.iterations,
21546 salttext);
21547 }
21548 }
21549
21550 /*
21551 * setnsec3param() will silently return early if the zone does not yet
21552 * have a database. Prevent that by queueing the event up if zone->db
21553 * is NULL. All events queued here are subsequently processed by
21554 * receive_secure_db() if it ever gets called or simply freed by
21555 * zone_free() otherwise.
21556 */
21557
21558 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
21559 if (zone->db != NULL) {
21560 zone_iattach(zone, &dummy);
21561 isc_task_send(zone->task, &e);
21562 } else {
21563 ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
21564 e = NULL;
21565 }
21566 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
21567
21568 result = ISC_R_SUCCESS;
21569
21570 failure:
21571 if (e != NULL) {
21572 isc_event_free(&e);
21573 }
21574 UNLOCK_ZONE(zone);
21575 return (result);
21576 }
21577
21578 isc_result_t
21579 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
21580 REQUIRE(DNS_ZONE_VALID(zone));
21581 REQUIRE(loadtime != NULL);
21582
21583 LOCK_ZONE(zone);
21584 *loadtime = zone->loadtime;
21585 UNLOCK_ZONE(zone);
21586 return (ISC_R_SUCCESS);
21587 }
21588
21589 isc_result_t
21590 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
21591 REQUIRE(DNS_ZONE_VALID(zone));
21592 REQUIRE(expiretime != NULL);
21593
21594 LOCK_ZONE(zone);
21595 *expiretime = zone->expiretime;
21596 UNLOCK_ZONE(zone);
21597 return (ISC_R_SUCCESS);
21598 }
21599
21600 isc_result_t
21601 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
21602 REQUIRE(DNS_ZONE_VALID(zone));
21603 REQUIRE(refreshtime != NULL);
21604
21605 LOCK_ZONE(zone);
21606 *refreshtime = zone->refreshtime;
21607 UNLOCK_ZONE(zone);
21608 return (ISC_R_SUCCESS);
21609 }
21610
21611 isc_result_t
21612 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
21613 REQUIRE(DNS_ZONE_VALID(zone));
21614 REQUIRE(refreshkeytime != NULL);
21615
21616 LOCK_ZONE(zone);
21617 *refreshkeytime = zone->refreshkeytime;
21618 UNLOCK_ZONE(zone);
21619 return (ISC_R_SUCCESS);
21620 }
21621
21622 unsigned int
21623 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
21624 dns_include_t *include;
21625 char **array = NULL;
21626 unsigned int n = 0;
21627
21628 REQUIRE(DNS_ZONE_VALID(zone));
21629 REQUIRE(includesp != NULL && *includesp == NULL);
21630
21631 LOCK_ZONE(zone);
21632 if (zone->nincludes == 0) {
21633 goto done;
21634 }
21635
21636 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
21637 for (include = ISC_LIST_HEAD(zone->includes); include != NULL;
21638 include = ISC_LIST_NEXT(include, link))
21639 {
21640 INSIST(n < zone->nincludes);
21641 array[n++] = isc_mem_strdup(zone->mctx, include->name);
21642 }
21643 INSIST(n == zone->nincludes);
21644 *includesp = array;
21645
21646 done:
21647 UNLOCK_ZONE(zone);
21648 return (n);
21649 }
21650
21651 void
21652 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
21653 REQUIRE(DNS_ZONE_VALID(zone));
21654
21655 zone->statlevel = level;
21656 }
21657
21658 dns_zonestat_level_t
21659 dns_zone_getstatlevel(dns_zone_t *zone) {
21660 REQUIRE(DNS_ZONE_VALID(zone));
21661
21662 return (zone->statlevel);
21663 }
21664
21665 static void
21666 setserial(isc_task_t *task, isc_event_t *event) {
21667 uint32_t oldserial, desired;
21668 const char *me = "setserial";
21669 bool commit = false;
21670 isc_result_t result;
21671 dns_dbversion_t *oldver = NULL, *newver = NULL;
21672 dns_zone_t *zone;
21673 dns_db_t *db = NULL;
21674 dns_diff_t diff;
21675 struct ssevent *sse = (struct ssevent *)event;
21676 dns_update_log_t log = { update_log_cb, NULL };
21677 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
21678
21679 UNUSED(task);
21680
21681 zone = event->ev_arg;
21682 INSIST(DNS_ZONE_VALID(zone));
21683
21684 ENTER;
21685
21686 if (zone->update_disabled) {
21687 goto failure;
21688 }
21689
21690 desired = sse->serial;
21691
21692 dns_diff_init(zone->mctx, &diff);
21693
21694 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
21695 if (zone->db != NULL) {
21696 dns_db_attach(zone->db, &db);
21697 }
21698 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
21699 if (db == NULL) {
21700 goto failure;
21701 }
21702
21703 dns_db_currentversion(db, &oldver);
21704 result = dns_db_newversion(db, &newver);
21705 if (result != ISC_R_SUCCESS) {
21706 dns_zone_log(zone, ISC_LOG_ERROR,
21707 "setserial:dns_db_newversion -> %s",
21708 dns_result_totext(result));
21709 goto failure;
21710 }
21711
21712 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx, DNS_DIFFOP_DEL,
21713 &oldtuple));
21714 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
21715 newtuple->op = DNS_DIFFOP_ADD;
21716
21717 oldserial = dns_soa_getserial(&oldtuple->rdata);
21718 if (desired == 0U) {
21719 desired = 1;
21720 }
21721 if (!isc_serial_gt(desired, oldserial)) {
21722 if (desired != oldserial) {
21723 dns_zone_log(zone, ISC_LOG_INFO,
21724 "setserial: desired serial (%u) "
21725 "out of range (%u-%u)",
21726 desired, oldserial + 1,
21727 (oldserial + 0x7fffffff));
21728 }
21729 goto failure;
21730 }
21731
21732 dns_soa_setserial(desired, &newtuple->rdata);
21733 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
21734 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
21735 result = dns_update_signatures(&log, zone, db, oldver, newver, &diff,
21736 zone->sigvalidityinterval);
21737 if (result != ISC_R_NOTFOUND) {
21738 CHECK(result);
21739 }
21740
21741 /* Write changes to journal file. */
21742 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
21743 commit = true;
21744
21745 LOCK_ZONE(zone);
21746 zone_needdump(zone, 30);
21747 UNLOCK_ZONE(zone);
21748
21749 failure:
21750 if (oldtuple != NULL) {
21751 dns_difftuple_free(&oldtuple);
21752 }
21753 if (newtuple != NULL) {
21754 dns_difftuple_free(&newtuple);
21755 }
21756 if (oldver != NULL) {
21757 dns_db_closeversion(db, &oldver, false);
21758 }
21759 if (newver != NULL) {
21760 dns_db_closeversion(db, &newver, commit);
21761 }
21762 if (db != NULL) {
21763 dns_db_detach(&db);
21764 }
21765 dns_diff_clear(&diff);
21766 isc_event_free(&event);
21767 dns_zone_idetach(&zone);
21768
21769 INSIST(oldver == NULL);
21770 INSIST(newver == NULL);
21771 }
21772
21773 isc_result_t
21774 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
21775 isc_result_t result = ISC_R_SUCCESS;
21776 dns_zone_t *dummy = NULL;
21777 isc_event_t *e = NULL;
21778 struct ssevent *sse;
21779
21780 REQUIRE(DNS_ZONE_VALID(zone));
21781
21782 LOCK_ZONE(zone);
21783
21784 if (!inline_secure(zone)) {
21785 if (!dns_zone_isdynamic(zone, true)) {
21786 result = DNS_R_NOTDYNAMIC;
21787 goto failure;
21788 }
21789 }
21790
21791 if (zone->update_disabled) {
21792 result = DNS_R_FROZEN;
21793 goto failure;
21794 }
21795
21796 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL, setserial,
21797 zone, sizeof(struct ssevent));
21798
21799 sse = (struct ssevent *)e;
21800 sse->serial = serial;
21801
21802 zone_iattach(zone, &dummy);
21803 isc_task_send(zone->task, &e);
21804
21805 failure:
21806 if (e != NULL) {
21807 isc_event_free(&e);
21808 }
21809 UNLOCK_ZONE(zone);
21810 return (result);
21811 }
21812
21813 isc_stats_t *
21814 dns_zone_getgluecachestats(dns_zone_t *zone) {
21815 REQUIRE(DNS_ZONE_VALID(zone));
21816
21817 return (zone->gluecachestats);
21818 }
21819
21820 bool
21821 dns_zone_isloaded(dns_zone_t *zone) {
21822 REQUIRE(DNS_ZONE_VALID(zone));
21823
21824 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
21825 }
21826
21827 isc_result_t
21828 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
21829 dns_dbversion_t *version = NULL;
21830 dns_keytable_t *secroots = NULL;
21831 isc_result_t result;
21832 dns_name_t *origin;
21833
21834 const char me[] = "dns_zone_verifydb";
21835
21836 REQUIRE(DNS_ZONE_VALID(zone));
21837 REQUIRE(db != NULL);
21838
21839 ENTER;
21840
21841 if (dns_zone_gettype(zone) != dns_zone_mirror) {
21842 return (ISC_R_SUCCESS);
21843 }
21844
21845 if (ver == NULL) {
21846 dns_db_currentversion(db, &version);
21847 } else {
21848 version = ver;
21849 }
21850
21851 if (zone->view != NULL) {
21852 result = dns_view_getsecroots(zone->view, &secroots);
21853 if (result != ISC_R_SUCCESS) {
21854 goto done;
21855 }
21856 }
21857
21858 origin = dns_db_origin(db);
21859 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
21860 zone->mctx, true, false, dnssec_report);
21861
21862 done:
21863 if (secroots != NULL) {
21864 dns_keytable_detach(&secroots);
21865 }
21866
21867 if (ver == NULL) {
21868 dns_db_closeversion(db, &version, false);
21869 }
21870
21871 if (result != ISC_R_SUCCESS) {
21872 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
21873 isc_result_totext(result));
21874 result = DNS_R_VERIFYFAILURE;
21875 }
21876
21877 return (result);
21878 }
21879