zone.c revision 1.5.2.3 1 /* $NetBSD: zone.c,v 1.5.2.3 2020/04/13 08:02:57 martin Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <config.h>
17
18 #include <errno.h>
19 #include <inttypes.h>
20 #include <stdbool.h>
21
22 #include <isc/file.h>
23 #include <isc/hex.h>
24 #include <isc/mutex.h>
25 #include <isc/pool.h>
26 #include <isc/print.h>
27 #include <isc/random.h>
28 #include <isc/ratelimiter.h>
29 #include <isc/refcount.h>
30 #include <isc/rwlock.h>
31 #include <isc/serial.h>
32 #include <isc/stats.h>
33 #include <isc/stdtime.h>
34 #include <isc/strerr.h>
35 #include <isc/string.h>
36 #include <isc/taskpool.h>
37 #include <isc/thread.h>
38 #include <isc/timer.h>
39 #include <isc/util.h>
40
41 #include <dns/acl.h>
42 #include <dns/adb.h>
43 #include <dns/callbacks.h>
44 #include <dns/catz.h>
45 #include <dns/db.h>
46 #include <dns/dbiterator.h>
47 #include <dns/dlz.h>
48 #include <dns/dnssec.h>
49 #include <dns/events.h>
50 #include <dns/journal.h>
51 #include <dns/keydata.h>
52 #include <dns/keytable.h>
53 #include <dns/keyvalues.h>
54 #include <dns/log.h>
55 #include <dns/master.h>
56 #include <dns/masterdump.h>
57 #include <dns/message.h>
58 #include <dns/name.h>
59 #include <dns/nsec.h>
60 #include <dns/nsec3.h>
61 #include <dns/peer.h>
62 #include <dns/private.h>
63 #include <dns/rcode.h>
64 #include <dns/rdata.h>
65 #include <dns/rdataclass.h>
66 #include <dns/rdatalist.h>
67 #include <dns/rdataset.h>
68 #include <dns/rdatasetiter.h>
69 #include <dns/rdatastruct.h>
70 #include <dns/rdatatype.h>
71 #include <dns/request.h>
72 #include <dns/resolver.h>
73 #include <dns/result.h>
74 #include <dns/rriterator.h>
75 #include <dns/soa.h>
76 #include <dns/ssu.h>
77 #include <dns/stats.h>
78 #include <dns/time.h>
79 #include <dns/tsig.h>
80 #include <dns/update.h>
81 #include <dns/xfrin.h>
82 #include <dns/zone.h>
83 #include <dns/zoneverify.h>
84 #include <dns/zt.h>
85
86 #include <dst/dst.h>
87
88 #include "zone_p.h"
89
90 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
91 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
92
93 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
94 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
95
96 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
97 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
98
99 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
100 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
101
102 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
103 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
104
105 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
106 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
107
108 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
109 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
110
111 /*%
112 * Ensure 'a' is at least 'min' but not more than 'max'.
113 */
114 #define RANGE(a, min, max) \
115 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
116
117 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
118
119 /*%
120 * Key flags
121 */
122 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
123 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
124 #define ALG(x) dst_key_alg(x)
125
126 /*
127 * Default values.
128 */
129 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
130 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
131 #define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
132 #define RESIGN_DELAY 3600 /*%< 1 hour */
133
134 #ifndef DNS_MAX_EXPIRE
135 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
136 #endif
137
138 #ifndef DNS_DUMP_DELAY
139 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
140 #endif
141
142 typedef struct dns_notify dns_notify_t;
143 typedef struct dns_stub dns_stub_t;
144 typedef struct dns_load dns_load_t;
145 typedef struct dns_forward dns_forward_t;
146 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
147 typedef struct dns_io dns_io_t;
148 typedef ISC_LIST(dns_io_t) dns_iolist_t;
149 typedef struct dns_signing dns_signing_t;
150 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
151 typedef struct dns_nsec3chain dns_nsec3chain_t;
152 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
153 typedef struct dns_keyfetch dns_keyfetch_t;
154 typedef struct dns_asyncload dns_asyncload_t;
155 typedef struct dns_include dns_include_t;
156
157 #define DNS_ZONE_CHECKLOCK
158 #ifdef DNS_ZONE_CHECKLOCK
159 #define LOCK_ZONE(z) \
160 do { LOCK(&(z)->lock); \
161 INSIST((z)->locked == false); \
162 (z)->locked = true; \
163 } while (/*CONSTCOND*/0)
164 #define UNLOCK_ZONE(z) \
165 do { (z)->locked = false; UNLOCK(&(z)->lock); } while (/*CONSTCON*/0)
166 #define LOCKED_ZONE(z) ((z)->locked)
167 #define TRYLOCK_ZONE(result, z) \
168 do { \
169 result = isc_mutex_trylock(&(z)->lock); \
170 if (result == ISC_R_SUCCESS) { \
171 INSIST((z)->locked == false); \
172 (z)->locked = true; \
173 } \
174 } while (/*CONSTCOND*/0)
175 #else
176 #define LOCK_ZONE(z) LOCK(&(z)->lock)
177 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
178 #define LOCKED_ZONE(z) true
179 #define TRYLOCK_ZONE(result, z) \
180 do { result = isc_mutex_trylock(&(z)->lock); } while (/*CONSTCOND*/0)
181 #endif
182
183 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
184 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
185 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
186 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
187
188 #ifdef ENABLE_AFL
189 extern bool dns_fuzzing_resolver;
190 #endif
191
192 struct dns_zone {
193 /* Unlocked */
194 unsigned int magic;
195 isc_mutex_t lock;
196 #ifdef DNS_ZONE_CHECKLOCK
197 bool locked;
198 #endif
199 isc_mem_t *mctx;
200 isc_refcount_t erefs;
201
202 isc_rwlock_t dblock;
203 dns_db_t *db; /* Locked by dblock */
204
205 /* Locked */
206 dns_zonemgr_t *zmgr;
207 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
208 isc_timer_t *timer;
209 unsigned int irefs;
210 dns_name_t origin;
211 char *masterfile;
212 ISC_LIST(dns_include_t) includes; /* Include files */
213 ISC_LIST(dns_include_t) newincludes; /* Loading */
214 unsigned int nincludes;
215 dns_masterformat_t masterformat;
216 const dns_master_style_t *masterstyle;
217 char *journal;
218 int32_t journalsize;
219 dns_rdataclass_t rdclass;
220 dns_zonetype_t type;
221 unsigned int flags;
222 dns_zoneopt_t options;
223 unsigned int db_argc;
224 char **db_argv;
225 isc_time_t expiretime;
226 isc_time_t refreshtime;
227 isc_time_t dumptime;
228 isc_time_t loadtime;
229 isc_time_t notifytime;
230 isc_time_t resigntime;
231 isc_time_t keywarntime;
232 isc_time_t signingtime;
233 isc_time_t nsec3chaintime;
234 isc_time_t refreshkeytime;
235 uint32_t refreshkeyinterval;
236 uint32_t refreshkeycount;
237 uint32_t refresh;
238 uint32_t retry;
239 uint32_t expire;
240 uint32_t minimum;
241 isc_stdtime_t key_expiry;
242 isc_stdtime_t log_key_expired_timer;
243 char *keydirectory;
244
245 uint32_t maxrefresh;
246 uint32_t minrefresh;
247 uint32_t maxretry;
248 uint32_t minretry;
249
250 uint32_t maxrecords;
251
252 isc_sockaddr_t *masters;
253 isc_dscp_t *masterdscps;
254 dns_name_t **masterkeynames;
255 bool *mastersok;
256 unsigned int masterscnt;
257 unsigned int curmaster;
258 isc_sockaddr_t masteraddr;
259 dns_notifytype_t notifytype;
260 isc_sockaddr_t *notify;
261 dns_name_t **notifykeynames;
262 isc_dscp_t *notifydscp;
263 unsigned int notifycnt;
264 isc_sockaddr_t notifyfrom;
265 isc_task_t *task;
266 isc_task_t *loadtask;
267 isc_sockaddr_t notifysrc4;
268 isc_sockaddr_t notifysrc6;
269 isc_sockaddr_t xfrsource4;
270 isc_sockaddr_t xfrsource6;
271 isc_sockaddr_t altxfrsource4;
272 isc_sockaddr_t altxfrsource6;
273 isc_sockaddr_t sourceaddr;
274 isc_dscp_t notifysrc4dscp;
275 isc_dscp_t notifysrc6dscp;
276 isc_dscp_t xfrsource4dscp;
277 isc_dscp_t xfrsource6dscp;
278 isc_dscp_t altxfrsource4dscp;
279 isc_dscp_t altxfrsource6dscp;
280 dns_xfrin_ctx_t *xfr; /* task locked */
281 dns_tsigkey_t *tsigkey; /* key used for xfr */
282 /* Access Control Lists */
283 dns_acl_t *update_acl;
284 dns_acl_t *forward_acl;
285 dns_acl_t *notify_acl;
286 dns_acl_t *query_acl;
287 dns_acl_t *queryon_acl;
288 dns_acl_t *xfr_acl;
289 bool update_disabled;
290 bool zero_no_soa_ttl;
291 dns_severity_t check_names;
292 ISC_LIST(dns_notify_t) notifies;
293 dns_request_t *request;
294 dns_loadctx_t *lctx;
295 dns_io_t *readio;
296 dns_dumpctx_t *dctx;
297 dns_io_t *writeio;
298 uint32_t maxxfrin;
299 uint32_t maxxfrout;
300 uint32_t idlein;
301 uint32_t idleout;
302 isc_event_t ctlevent;
303 dns_ssutable_t *ssutable;
304 uint32_t sigvalidityinterval;
305 uint32_t keyvalidityinterval;
306 uint32_t sigresigninginterval;
307 dns_view_t *view;
308 dns_view_t *prev_view;
309 dns_checkmxfunc_t checkmx;
310 dns_checksrvfunc_t checksrv;
311 dns_checknsfunc_t checkns;
312 /*%
313 * Zones in certain states such as "waiting for zone transfer"
314 * or "zone transfer in progress" are kept on per-state linked lists
315 * in the zone manager using the 'statelink' field. The 'statelist'
316 * field points at the list the zone is currently on. It the zone
317 * is not on any such list, statelist is NULL.
318 */
319 ISC_LINK(dns_zone_t) statelink;
320 dns_zonelist_t *statelist;
321 /*%
322 * Statistics counters about zone management.
323 */
324 isc_stats_t *stats;
325 /*%
326 * Optional per-zone statistics counters. Counted outside of this
327 * module.
328 */
329 dns_zonestat_level_t statlevel;
330 bool requeststats_on;
331 isc_stats_t *requeststats;
332 dns_stats_t *rcvquerystats;
333 dns_stats_t *dnssecsignstats;
334 dns_stats_t *dnssecrefreshstats;
335 uint32_t notifydelay;
336 dns_isselffunc_t isself;
337 void *isselfarg;
338
339 char * strnamerd;
340 char * strname;
341 char * strrdclass;
342 char * strviewname;
343
344 /*%
345 * Serial number for deferred journal compaction.
346 */
347 uint32_t compact_serial;
348 /*%
349 * Keys that are signing the zone for the first time.
350 */
351 dns_signinglist_t signing;
352 dns_nsec3chainlist_t nsec3chain;
353 /*%
354 * List of outstanding NSEC3PARAM change requests.
355 */
356 isc_eventlist_t setnsec3param_queue;
357 /*%
358 * Signing / re-signing quantum stopping parameters.
359 */
360 uint32_t signatures;
361 uint32_t nodes;
362 dns_rdatatype_t privatetype;
363
364 /*%
365 * Autosigning/key-maintenance options
366 */
367 uint32_t keyopts;
368
369 /*%
370 * True if added by "rndc addzone"
371 */
372 bool added;
373
374 /*%
375 * True if added by automatically by named.
376 */
377 bool automatic;
378
379 /*%
380 * response policy data to be relayed to the database
381 */
382 dns_rpz_zones_t *rpzs;
383 dns_rpz_num_t rpz_num;
384
385 /*%
386 * catalog zone data
387 */
388 dns_catz_zones_t *catzs;
389
390 /*%
391 * parent catalog zone
392 */
393 dns_catz_zone_t *parentcatz;
394
395 /*%
396 * Serial number update method.
397 */
398 dns_updatemethod_t updatemethod;
399
400 /*%
401 * whether ixfr is requested
402 */
403 bool requestixfr;
404
405 /*%
406 * whether EDNS EXPIRE is requested
407 */
408 bool requestexpire;
409
410 /*%
411 * Outstanding forwarded UPDATE requests.
412 */
413 dns_forwardlist_t forwards;
414
415 dns_zone_t *raw;
416 dns_zone_t *secure;
417
418 bool sourceserialset;
419 uint32_t sourceserial;
420
421 /*%
422 * maximum zone ttl
423 */
424 dns_ttl_t maxttl;
425
426 /*
427 * Inline zone signing state.
428 */
429 dns_diff_t rss_diff;
430 isc_eventlist_t rss_events;
431 isc_eventlist_t rss_post;
432 dns_dbversion_t *rss_newver;
433 dns_dbversion_t *rss_oldver;
434 dns_db_t *rss_db;
435 dns_zone_t *rss_raw;
436 isc_event_t *rss_event;
437 dns_update_state_t *rss_state;
438
439 isc_stats_t *gluecachestats;
440 };
441
442 #define zonediff_init(z, d) \
443 do { \
444 dns__zonediff_t *_z = (z); \
445 (_z)->diff = (d); \
446 (_z)->offline = false; \
447 } while (/*CONSTCOND*/0)
448
449 #define DNS_ZONE_FLAG(z,f) ((z)->flags & (f))
450 #define DNS_ZONE_SETFLAG(z,f) do { \
451 INSIST(LOCKED_ZONE(z)); \
452 (z)->flags |= (f); \
453 } while (/*CONSTCOND*/0)
454 #define DNS_ZONE_CLRFLAG(z,f) do { \
455 INSIST(LOCKED_ZONE(z)); \
456 (z)->flags &= ~(f); \
457 } while (/*CONSTCOND*/0)
458 /* XXX MPA these may need to go back into zone.h */
459 #define DNS_ZONEFLG_REFRESH 0x00000001U /*%< refresh check in progress */
460 #define DNS_ZONEFLG_NEEDDUMP 0x00000002U /*%< zone need consolidation */
461 #define DNS_ZONEFLG_USEVC 0x00000004U /*%< use tcp for refresh query */
462 #define DNS_ZONEFLG_DUMPING 0x00000008U /*%< a dump is in progress */
463 #define DNS_ZONEFLG_HASINCLUDE 0x00000010U /*%< $INCLUDE in zone file */
464 #define DNS_ZONEFLG_LOADED 0x00000020U /*%< database has loaded */
465 #define DNS_ZONEFLG_EXITING 0x00000040U /*%< zone is being destroyed */
466 #define DNS_ZONEFLG_EXPIRED 0x00000080U /*%< zone has expired */
467 #define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /*%< refresh check needed */
468 #define DNS_ZONEFLG_UPTODATE 0x00000200U /*%< zone contents are
469 * uptodate */
470 #define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /*%< need to send out notify
471 * messages */
472 #define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /*%< generate a journal diff on
473 * reload */
474 #define DNS_ZONEFLG_NOMASTERS 0x00001000U /*%< an attempt to refresh a
475 * zone with no masters
476 * occurred */
477 #define DNS_ZONEFLG_LOADING 0x00002000U /*%< load from disk in progress*/
478 #define DNS_ZONEFLG_HAVETIMERS 0x00004000U /*%< timer values have been set
479 * from SOA (if not set, we
480 * are still using
481 * default timer values) */
482 #define DNS_ZONEFLG_FORCEXFER 0x00008000U /*%< Force a zone xfer */
483 #define DNS_ZONEFLG_NOREFRESH 0x00010000U
484 #define DNS_ZONEFLG_DIALNOTIFY 0x00020000U
485 #define DNS_ZONEFLG_DIALREFRESH 0x00040000U
486 #define DNS_ZONEFLG_SHUTDOWN 0x00080000U
487 #define DNS_ZONEFLAG_NOIXFR 0x00100000U /*%< IXFR failed, force AXFR */
488 #define DNS_ZONEFLG_FLUSH 0x00200000U
489 #define DNS_ZONEFLG_NOEDNS 0x00400000U
490 #define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
491 #define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
492 #define DNS_ZONEFLG_NEEDCOMPACT 0x02000000U
493 #define DNS_ZONEFLG_REFRESHING 0x04000000U /*%< Refreshing keydata */
494 #define DNS_ZONEFLG_THAW 0x08000000U
495 #define DNS_ZONEFLG_LOADPENDING 0x10000000U /*%< Loading scheduled */
496 #define DNS_ZONEFLG_NODELAY 0x20000000U
497 #define DNS_ZONEFLG_SENDSECURE 0x40000000U
498 #define DNS_ZONEFLG_NEEDSTARTUPNOTIFY 0x80000000U /*%< need to send out notify
499 * due to the zone just
500 * being loaded for the
501 * first time. */
502
503 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
504 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
505
506 /* Flags for zone_load() */
507 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
508 #define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
509 load. */
510
511 #define UNREACH_CHACHE_SIZE 10U
512 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
513
514 #define CHECK(op) \
515 do { result = (op); \
516 if (result != ISC_R_SUCCESS) goto failure; \
517 } while (/*CONSTCOND*/0)
518
519 struct dns_unreachable {
520 isc_sockaddr_t remote;
521 isc_sockaddr_t local;
522 uint32_t expire;
523 uint32_t last;
524 uint32_t count;
525 };
526
527 struct dns_zonemgr {
528 unsigned int magic;
529 isc_mem_t * mctx;
530 int refs; /* Locked by rwlock */
531 isc_taskmgr_t * taskmgr;
532 isc_timermgr_t * timermgr;
533 isc_socketmgr_t * socketmgr;
534 isc_taskpool_t * zonetasks;
535 isc_taskpool_t * loadtasks;
536 isc_task_t * task;
537 isc_pool_t * mctxpool;
538 isc_ratelimiter_t * notifyrl;
539 isc_ratelimiter_t * refreshrl;
540 isc_ratelimiter_t * startupnotifyrl;
541 isc_ratelimiter_t * startuprefreshrl;
542 isc_rwlock_t rwlock;
543 isc_mutex_t iolock;
544 isc_rwlock_t urlock;
545
546 /* Locked by rwlock. */
547 dns_zonelist_t zones;
548 dns_zonelist_t waiting_for_xfrin;
549 dns_zonelist_t xfrin_in_progress;
550
551 /* Configuration data. */
552 uint32_t transfersin;
553 uint32_t transfersperns;
554 unsigned int notifyrate;
555 unsigned int startupnotifyrate;
556 unsigned int serialqueryrate;
557 unsigned int startupserialqueryrate;
558
559 /* Locked by iolock */
560 uint32_t iolimit;
561 uint32_t ioactive;
562 dns_iolist_t high;
563 dns_iolist_t low;
564
565 /* Locked by urlock. */
566 /* LRU cache */
567 struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
568 };
569
570 /*%
571 * Hold notify state.
572 */
573 struct dns_notify {
574 unsigned int magic;
575 unsigned int flags;
576 isc_mem_t *mctx;
577 dns_zone_t *zone;
578 dns_adbfind_t *find;
579 dns_request_t *request;
580 dns_name_t ns;
581 isc_sockaddr_t dst;
582 dns_tsigkey_t *key;
583 isc_dscp_t dscp;
584 ISC_LINK(dns_notify_t) link;
585 isc_event_t *event;
586 };
587
588 #define DNS_NOTIFY_NOSOA 0x0001U
589 #define DNS_NOTIFY_STARTUP 0x0002U
590
591 /*%
592 * dns_stub holds state while performing a 'stub' transfer.
593 * 'db' is the zone's 'db' or a new one if this is the initial
594 * transfer.
595 */
596
597 struct dns_stub {
598 unsigned int magic;
599 isc_mem_t *mctx;
600 dns_zone_t *zone;
601 dns_db_t *db;
602 dns_dbversion_t *version;
603 };
604
605 /*%
606 * Hold load state.
607 */
608 struct dns_load {
609 unsigned int magic;
610 isc_mem_t *mctx;
611 dns_zone_t *zone;
612 dns_db_t *db;
613 isc_time_t loadtime;
614 dns_rdatacallbacks_t callbacks;
615 };
616
617 /*%
618 * Hold forward state.
619 */
620 struct dns_forward {
621 unsigned int magic;
622 isc_mem_t *mctx;
623 dns_zone_t *zone;
624 isc_buffer_t *msgbuf;
625 dns_request_t *request;
626 uint32_t which;
627 isc_sockaddr_t addr;
628 dns_updatecallback_t callback;
629 void *callback_arg;
630 unsigned int options;
631 ISC_LINK(dns_forward_t) link;
632 };
633
634 /*%
635 * Hold IO request state.
636 */
637 struct dns_io {
638 unsigned int magic;
639 dns_zonemgr_t *zmgr;
640 bool high;
641 isc_task_t *task;
642 ISC_LINK(dns_io_t) link;
643 isc_event_t *event;
644 };
645
646 /*%
647 * Hold state for when we are signing a zone with a new
648 * DNSKEY as result of an update.
649 */
650 struct dns_signing {
651 unsigned int magic;
652 dns_db_t *db;
653 dns_dbiterator_t *dbiterator;
654 dns_secalg_t algorithm;
655 uint16_t keyid;
656 bool deleteit;
657 bool done;
658 ISC_LINK(dns_signing_t) link;
659 };
660
661 struct dns_nsec3chain {
662 unsigned int magic;
663 dns_db_t *db;
664 dns_dbiterator_t *dbiterator;
665 dns_rdata_nsec3param_t nsec3param;
666 unsigned char salt[255];
667 bool done;
668 bool seen_nsec;
669 bool delete_nsec;
670 bool save_delete_nsec;
671 ISC_LINK(dns_nsec3chain_t) link;
672 };
673 /*%<
674 * 'dbiterator' contains a iterator for the database. If we are creating
675 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
676 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
677 * iterated.
678 *
679 * 'nsec3param' contains the parameters of the NSEC3 chain being created
680 * or removed.
681 *
682 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
683 *
684 * 'seen_nsec' will be set to true if, while iterating the zone to create a
685 * NSEC3 chain, a NSEC record is seen.
686 *
687 * 'delete_nsec' will be set to true if, at the completion of the creation
688 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
689 * are in the process of deleting the NSEC chain.
690 *
691 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
692 * so it can be recovered in the event of a error.
693 */
694
695 struct dns_keyfetch {
696 dns_fixedname_t name;
697 dns_rdataset_t keydataset;
698 dns_rdataset_t dnskeyset;
699 dns_rdataset_t dnskeysigset;
700 dns_zone_t *zone;
701 dns_db_t *db;
702 dns_fetch_t *fetch;
703 };
704
705 /*%
706 * Hold state for an asynchronous load
707 */
708 struct dns_asyncload {
709 dns_zone_t *zone;
710 unsigned int flags;
711 dns_zt_zoneloaded_t loaded;
712 void *loaded_arg;
713 };
714
715 /*%
716 * Reference to an include file encountered during loading
717 */
718 struct dns_include {
719 char *name;
720 isc_time_t filetime;
721 ISC_LINK(dns_include_t) link;
722 };
723
724 /*
725 * These can be overridden by the -T mkeytimers option on the command
726 * line, so that we can test with shorter periods than specified in
727 * RFC 5011.
728 */
729 #define HOUR 3600
730 #define DAY (24*HOUR)
731 #define MONTH (30*DAY)
732 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_hour = HOUR;
733 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_day = DAY;
734 LIBDNS_EXTERNAL_DATA unsigned int dns_zone_mkey_month = MONTH;
735
736 #define SEND_BUFFER_SIZE 2048
737
738 static void zone_settimer(dns_zone_t *, isc_time_t *);
739 static void cancel_refresh(dns_zone_t *);
740 static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel,
741 const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);
742 static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...)
743 ISC_FORMAT_PRINTF(3, 4);
744 static void dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...)
745 ISC_FORMAT_PRINTF(3, 4);
746 static void queue_xfrin(dns_zone_t *zone);
747 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
748 dns_diff_t *diff, dns_diffop_t op,
749 dns_name_t *name, dns_ttl_t ttl,
750 dns_rdata_t *rdata);
751 static void zone_unload(dns_zone_t *zone);
752 static void zone_expire(dns_zone_t *zone);
753 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
754 static void zone_idetach(dns_zone_t **zonep);
755 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
756 bool dump);
757 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
758 static inline void zone_detachdb(dns_zone_t *zone);
759 static isc_result_t default_journal(dns_zone_t *zone);
760 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
761 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
762 isc_time_t loadtime, isc_result_t result);
763 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
764 static void zone_shutdown(isc_task_t *, isc_event_t *);
765 static void zone_loaddone(void *arg, isc_result_t result);
766 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
767 isc_time_t loadtime);
768 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
769 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
770 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
771 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
772 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
773 uint32_t serial);
774 static void refresh_callback(isc_task_t *, isc_event_t *);
775 static void stub_callback(isc_task_t *, isc_event_t *);
776 static void queue_soa_query(dns_zone_t *zone);
777 static void soa_query(isc_task_t *, isc_event_t *);
778 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
779 dns_stub_t *stub);
780 static int message_count(dns_message_t *msg, dns_section_t section,
781 dns_rdatatype_t type);
782 static void notify_cancel(dns_zone_t *zone);
783 static void notify_find_address(dns_notify_t *notify);
784 static void notify_send(dns_notify_t *notify);
785 static isc_result_t notify_createmessage(dns_zone_t *zone,
786 unsigned int flags,
787 dns_message_t **messagep);
788 static void notify_done(isc_task_t *task, isc_event_t *event);
789 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
790 static isc_result_t zone_dump(dns_zone_t *, bool);
791 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
792 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
793 dns_zone_t *zone);
794 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi);
795 static void zonemgr_free(dns_zonemgr_t *zmgr);
796 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
797 isc_task_t *task, isc_taskaction_t action,
798 void *arg, dns_io_t **iop);
799 static void zonemgr_putio(dns_io_t **iop);
800 static void zonemgr_cancelio(dns_io_t *io);
801 static void rss_post(dns_zone_t *, isc_event_t *);
802
803 static isc_result_t
804 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
805 unsigned int *soacount, uint32_t *serial,
806 uint32_t *refresh, uint32_t *retry,
807 uint32_t *expire, uint32_t *minimum,
808 unsigned int *errors);
809
810 static void zone_freedbargs(dns_zone_t *zone);
811 static void forward_callback(isc_task_t *task, isc_event_t *event);
812 static void zone_saveunique(dns_zone_t *zone, const char *path,
813 const char *templat);
814 static void zone_maintenance(dns_zone_t *zone);
815 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
816 static void dump_done(void *arg, isc_result_t result);
817 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
818 uint16_t keyid,
819 bool deleteit);
820 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
821 dns_dbnode_t *node, dns_name_t *name,
822 dns_diff_t *diff);
823 static void zone_rekey(dns_zone_t *zone);
824 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
825 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
826 unsigned int value);
827
828 #define ENTER zone_debuglog(zone, me, 1, "enter")
829
830 static const unsigned int dbargc_default = 1;
831 static const char *dbargv_default[] = { "rbt" };
832
833 #define DNS_ZONE_JITTER_ADD(a, b, c) \
834 do { \
835 isc_interval_t _i; \
836 uint32_t _j; \
837 _j = (b) - isc_random_uniform((b)/4); \
838 isc_interval_set(&_i, _j, 0); \
839 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
840 dns_zone_log(zone, ISC_LOG_WARNING, \
841 "epoch approaching: upgrade required: " \
842 "now + %s failed", #b); \
843 isc_interval_set(&_i, _j/2, 0); \
844 (void)isc_time_add((a), &_i, (c)); \
845 } \
846 } while (/*CONSTCOND*/0)
847
848 #define DNS_ZONE_TIME_ADD(a, b, c) \
849 do { \
850 isc_interval_t _i; \
851 isc_interval_set(&_i, (b), 0); \
852 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
853 dns_zone_log(zone, ISC_LOG_WARNING, \
854 "epoch approaching: upgrade required: " \
855 "now + %s failed", #b); \
856 isc_interval_set(&_i, (b)/2, 0); \
857 (void)isc_time_add((a), &_i, (c)); \
858 } \
859 } while (/*CONSTCOND*/0)
860
861 typedef struct nsec3param nsec3param_t;
862 struct nsec3param {
863 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
864 unsigned int length;
865 bool nsec;
866 bool replace;
867 ISC_LINK(nsec3param_t) link;
868 };
869 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
870 struct np3event {
871 isc_event_t event;
872 nsec3param_t params;
873 };
874
875 struct ssevent {
876 isc_event_t event;
877 uint32_t serial;
878 };
879
880 /*%
881 * Increment resolver-related statistics counters. Zone must be locked.
882 */
883 static inline void
884 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
885 if (zone->stats != NULL)
886 isc_stats_increment(zone->stats, counter);
887 }
888
889 /***
890 *** Public functions.
891 ***/
892
893 isc_result_t
894 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
895 isc_result_t result;
896 dns_zone_t *zone;
897 isc_time_t now;
898
899 REQUIRE(zonep != NULL && *zonep == NULL);
900 REQUIRE(mctx != NULL);
901
902 TIME_NOW(&now);
903 zone = isc_mem_get(mctx, sizeof(*zone));
904 if (zone == NULL) {
905 return (ISC_R_NOMEMORY);
906 }
907
908 zone->mctx = NULL;
909 isc_mem_attach(mctx, &zone->mctx);
910
911 isc_mutex_init(&zone->lock);
912
913 result = ZONEDB_INITLOCK(&zone->dblock);
914 if (result != ISC_R_SUCCESS) {
915 goto free_mutex;
916 }
917
918 /* XXX MPA check that all elements are initialised */
919 #ifdef DNS_ZONE_CHECKLOCK
920 zone->locked = false;
921 #endif
922 zone->db = NULL;
923 zone->zmgr = NULL;
924 ISC_LINK_INIT(zone, link);
925 isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
926 zone->irefs = 0;
927 dns_name_init(&zone->origin, NULL);
928 zone->strnamerd = NULL;
929 zone->strname = NULL;
930 zone->strrdclass = NULL;
931 zone->strviewname = NULL;
932 zone->masterfile = NULL;
933 ISC_LIST_INIT(zone->includes);
934 ISC_LIST_INIT(zone->newincludes);
935 zone->nincludes = 0;
936 zone->masterformat = dns_masterformat_none;
937 zone->masterstyle = NULL;
938 zone->keydirectory = NULL;
939 zone->journalsize = -1;
940 zone->journal = NULL;
941 zone->rdclass = dns_rdataclass_none;
942 zone->type = dns_zone_none;
943 zone->flags = 0;
944 zone->options = 0;
945 zone->keyopts = 0;
946 zone->db_argc = 0;
947 zone->db_argv = NULL;
948 isc_time_settoepoch(&zone->expiretime);
949 isc_time_settoepoch(&zone->refreshtime);
950 isc_time_settoepoch(&zone->dumptime);
951 isc_time_settoepoch(&zone->loadtime);
952 zone->notifytime = now;
953 isc_time_settoepoch(&zone->resigntime);
954 isc_time_settoepoch(&zone->keywarntime);
955 isc_time_settoepoch(&zone->signingtime);
956 isc_time_settoepoch(&zone->nsec3chaintime);
957 isc_time_settoepoch(&zone->refreshkeytime);
958 zone->refreshkeyinterval = 0;
959 zone->refreshkeycount = 0;
960 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
961 zone->retry = DNS_ZONE_DEFAULTRETRY;
962 zone->expire = 0;
963 zone->minimum = 0;
964 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
965 zone->minrefresh = DNS_ZONE_MINREFRESH;
966 zone->maxretry = DNS_ZONE_MAXRETRY;
967 zone->minretry = DNS_ZONE_MINRETRY;
968 zone->masters = NULL;
969 zone->masterdscps = NULL;
970 zone->masterkeynames = NULL;
971 zone->mastersok = NULL;
972 zone->masterscnt = 0;
973 zone->curmaster = 0;
974 zone->maxttl = 0;
975 zone->notify = NULL;
976 zone->notifykeynames = NULL;
977 zone->notifydscp = NULL;
978 zone->notifytype = dns_notifytype_yes;
979 zone->notifycnt = 0;
980 zone->task = NULL;
981 zone->loadtask = NULL;
982 zone->update_acl = NULL;
983 zone->forward_acl = NULL;
984 zone->notify_acl = NULL;
985 zone->query_acl = NULL;
986 zone->queryon_acl = NULL;
987 zone->xfr_acl = NULL;
988 zone->update_disabled = false;
989 zone->zero_no_soa_ttl = true;
990 zone->check_names = dns_severity_ignore;
991 zone->request = NULL;
992 zone->lctx = NULL;
993 zone->readio = NULL;
994 zone->dctx = NULL;
995 zone->writeio = NULL;
996 zone->timer = NULL;
997 zone->idlein = DNS_DEFAULT_IDLEIN;
998 zone->idleout = DNS_DEFAULT_IDLEOUT;
999 zone->log_key_expired_timer = 0;
1000 ISC_LIST_INIT(zone->notifies);
1001 isc_sockaddr_any(&zone->notifysrc4);
1002 isc_sockaddr_any6(&zone->notifysrc6);
1003 isc_sockaddr_any(&zone->xfrsource4);
1004 isc_sockaddr_any6(&zone->xfrsource6);
1005 isc_sockaddr_any(&zone->altxfrsource4);
1006 isc_sockaddr_any6(&zone->altxfrsource6);
1007 zone->notifysrc4dscp = -1;
1008 zone->notifysrc6dscp = -1;
1009 zone->xfrsource4dscp = -1;
1010 zone->xfrsource6dscp = -1;
1011 zone->altxfrsource4dscp = -1;
1012 zone->altxfrsource6dscp = -1;
1013 zone->xfr = NULL;
1014 zone->tsigkey = NULL;
1015 zone->maxxfrin = MAX_XFER_TIME;
1016 zone->maxxfrout = MAX_XFER_TIME;
1017 zone->ssutable = NULL;
1018 zone->sigvalidityinterval = 30 * 24 * 3600;
1019 zone->keyvalidityinterval = 0;
1020 zone->sigresigninginterval = 7 * 24 * 3600;
1021 zone->view = NULL;
1022 zone->prev_view = NULL;
1023 zone->checkmx = NULL;
1024 zone->checksrv = NULL;
1025 zone->checkns = NULL;
1026 ISC_LINK_INIT(zone, statelink);
1027 zone->statelist = NULL;
1028 zone->stats = NULL;
1029 zone->requeststats_on = false;
1030 zone->statlevel = dns_zonestat_none;
1031 zone->requeststats = NULL;
1032 zone->rcvquerystats = NULL;
1033 zone->dnssecsignstats = NULL;
1034 zone->dnssecrefreshstats = NULL;
1035 zone->notifydelay = 5;
1036 zone->isself = NULL;
1037 zone->isselfarg = NULL;
1038 ISC_LIST_INIT(zone->signing);
1039 ISC_LIST_INIT(zone->nsec3chain);
1040 ISC_LIST_INIT(zone->setnsec3param_queue);
1041 zone->signatures = 10;
1042 zone->nodes = 100;
1043 zone->privatetype = (dns_rdatatype_t)0xffffU;
1044 zone->added = false;
1045 zone->automatic = false;
1046 zone->rpzs = NULL;
1047 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1048
1049 zone->catzs = NULL;
1050 zone->parentcatz = NULL;
1051
1052 ISC_LIST_INIT(zone->forwards);
1053 zone->raw = NULL;
1054 zone->secure = NULL;
1055 zone->sourceserial = 0;
1056 zone->sourceserialset = false;
1057 zone->requestixfr = true;
1058 zone->requestexpire = true;
1059 ISC_LIST_INIT(zone->rss_events);
1060 ISC_LIST_INIT(zone->rss_post);
1061 zone->rss_db = NULL;
1062 zone->rss_raw = NULL;
1063 zone->rss_newver = NULL;
1064 zone->rss_oldver = NULL;
1065 zone->rss_event = NULL;
1066 zone->rss_state = NULL;
1067 zone->updatemethod = dns_updatemethod_increment;
1068 zone->maxrecords = 0U;
1069
1070 zone->magic = ZONE_MAGIC;
1071
1072 zone->gluecachestats = NULL;
1073 result = isc_stats_create(mctx, &zone->gluecachestats,
1074 dns_gluecachestatscounter_max);
1075 if (result != ISC_R_SUCCESS) {
1076 goto free_erefs;
1077 }
1078
1079 /* Must be after magic is set. */
1080 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1081 if (result != ISC_R_SUCCESS) {
1082 goto free_stats;
1083 }
1084
1085 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1086 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
1087 NULL, NULL);
1088 *zonep = zone;
1089 return (ISC_R_SUCCESS);
1090
1091 free_stats:
1092 if (zone->gluecachestats != NULL)
1093 isc_stats_detach(&zone->gluecachestats);
1094
1095 free_erefs:
1096 INSIST(isc_refcount_decrement(&zone->erefs) > 0);
1097 isc_refcount_destroy(&zone->erefs);
1098
1099 ZONEDB_DESTROYLOCK(&zone->dblock);
1100
1101 free_mutex:
1102 isc_mutex_destroy(&zone->lock);
1103
1104 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1105 return (result);
1106 }
1107
1108 /*
1109 * Free a zone. Because we require that there be no more
1110 * outstanding events or references, no locking is necessary.
1111 */
1112 static void
1113 zone_free(dns_zone_t *zone) {
1114 isc_mem_t *mctx = NULL;
1115 dns_signing_t *signing;
1116 dns_nsec3chain_t *nsec3chain;
1117 isc_event_t *event;
1118 dns_include_t *include;
1119
1120 REQUIRE(DNS_ZONE_VALID(zone));
1121 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
1122 REQUIRE(zone->irefs == 0);
1123 REQUIRE(!LOCKED_ZONE(zone));
1124 REQUIRE(zone->timer == NULL);
1125 REQUIRE(zone->zmgr == NULL);
1126
1127 /*
1128 * Managed objects. Order is important.
1129 */
1130 if (zone->request != NULL) {
1131 dns_request_destroy(&zone->request); /* XXXMPA */
1132 }
1133 INSIST(zone->readio == NULL);
1134 INSIST(zone->statelist == NULL);
1135 INSIST(zone->writeio == NULL);
1136
1137 if (zone->task != NULL) {
1138 isc_task_detach(&zone->task);
1139 }
1140 if (zone->loadtask != NULL) {
1141 isc_task_detach(&zone->loadtask);
1142 }
1143 if (zone->view != NULL) {
1144 dns_view_weakdetach(&zone->view);
1145 }
1146 if (zone->prev_view != NULL) {
1147 dns_view_weakdetach(&zone->prev_view);
1148 }
1149
1150 /* Unmanaged objects */
1151 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
1152 event = ISC_LIST_HEAD(zone->setnsec3param_queue);
1153 ISC_LIST_UNLINK(zone->setnsec3param_queue, event, ev_link);
1154 isc_event_free(&event);
1155 }
1156 while (!ISC_LIST_EMPTY(zone->rss_post)) {
1157 event = ISC_LIST_HEAD(zone->rss_post);
1158 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
1159 isc_event_free(&event);
1160 }
1161 for (signing = ISC_LIST_HEAD(zone->signing);
1162 signing != NULL;
1163 signing = ISC_LIST_HEAD(zone->signing)) {
1164 ISC_LIST_UNLINK(zone->signing, signing, link);
1165 dns_db_detach(&signing->db);
1166 dns_dbiterator_destroy(&signing->dbiterator);
1167 isc_mem_put(zone->mctx, signing, sizeof *signing);
1168 }
1169 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1170 nsec3chain != NULL;
1171 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1172 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1173 dns_db_detach(&nsec3chain->db);
1174 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1175 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1176 }
1177 for (include = ISC_LIST_HEAD(zone->includes);
1178 include != NULL;
1179 include = ISC_LIST_HEAD(zone->includes)) {
1180 ISC_LIST_UNLINK(zone->includes, include, link);
1181 isc_mem_free(zone->mctx, include->name);
1182 isc_mem_put(zone->mctx, include, sizeof *include);
1183 }
1184 for (include = ISC_LIST_HEAD(zone->newincludes);
1185 include != NULL;
1186 include = ISC_LIST_HEAD(zone->newincludes)) {
1187 ISC_LIST_UNLINK(zone->newincludes, include, link);
1188 isc_mem_free(zone->mctx, include->name);
1189 isc_mem_put(zone->mctx, include, sizeof *include);
1190 }
1191 if (zone->masterfile != NULL) {
1192 isc_mem_free(zone->mctx, zone->masterfile);
1193 }
1194 zone->masterfile = NULL;
1195 if (zone->keydirectory != NULL) {
1196 isc_mem_free(zone->mctx, zone->keydirectory);
1197 }
1198 zone->keydirectory = NULL;
1199 zone->journalsize = -1;
1200 if (zone->journal != NULL) {
1201 isc_mem_free(zone->mctx, zone->journal);
1202 }
1203 zone->journal = NULL;
1204 if (zone->stats != NULL) {
1205 isc_stats_detach(&zone->stats);
1206 }
1207 if (zone->requeststats != NULL) {
1208 isc_stats_detach(&zone->requeststats);
1209 }
1210 if (zone->rcvquerystats != NULL){
1211 dns_stats_detach(&zone->rcvquerystats);
1212 }
1213 if (zone->dnssecsignstats != NULL){
1214 dns_stats_detach(&zone->dnssecsignstats);
1215 }
1216 if (zone->dnssecrefreshstats != NULL){
1217 dns_stats_detach(&zone->dnssecrefreshstats);
1218 }
1219 if (zone->db != NULL) {
1220 zone_detachdb(zone);
1221 }
1222 if (zone->rpzs != NULL) {
1223 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1224 dns_rpz_detach_rpzs(&zone->rpzs);
1225 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1226 }
1227 if (zone->catzs != NULL) {
1228 dns_catz_catzs_detach(&zone->catzs);
1229 }
1230 zone_freedbargs(zone);
1231 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL,
1232 NULL, 0) == ISC_R_SUCCESS);
1233 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1234 zone->check_names = dns_severity_ignore;
1235 if (zone->update_acl != NULL) {
1236 dns_acl_detach(&zone->update_acl);
1237 }
1238 if (zone->forward_acl != NULL) {
1239 dns_acl_detach(&zone->forward_acl);
1240 }
1241 if (zone->notify_acl != NULL) {
1242 dns_acl_detach(&zone->notify_acl);
1243 }
1244 if (zone->query_acl != NULL) {
1245 dns_acl_detach(&zone->query_acl);
1246 }
1247 if (zone->queryon_acl != NULL) {
1248 dns_acl_detach(&zone->queryon_acl);
1249 }
1250 if (zone->xfr_acl != NULL) {
1251 dns_acl_detach(&zone->xfr_acl);
1252 }
1253 if (dns_name_dynamic(&zone->origin)) {
1254 dns_name_free(&zone->origin, zone->mctx);
1255 }
1256 if (zone->strnamerd != NULL) {
1257 isc_mem_free(zone->mctx, zone->strnamerd);
1258 }
1259 if (zone->strname != NULL) {
1260 isc_mem_free(zone->mctx, zone->strname);
1261 }
1262 if (zone->strrdclass != NULL) {
1263 isc_mem_free(zone->mctx, zone->strrdclass);
1264 }
1265 if (zone->strviewname != NULL) {
1266 isc_mem_free(zone->mctx, zone->strviewname);
1267 }
1268 if (zone->ssutable != NULL) {
1269 dns_ssutable_detach(&zone->ssutable);
1270 }
1271 if (zone->gluecachestats != NULL) {
1272 isc_stats_detach(&zone->gluecachestats);
1273 }
1274
1275 /* last stuff */
1276 ZONEDB_DESTROYLOCK(&zone->dblock);
1277 isc_mutex_destroy(&zone->lock);
1278 zone->magic = 0;
1279 mctx = zone->mctx;
1280 isc_mem_put(mctx, zone, sizeof(*zone));
1281 isc_mem_detach(&mctx);
1282 }
1283
1284 /*
1285 * Returns true iff this the signed side of an inline-signing zone.
1286 * Caller should hold zone lock.
1287 */
1288 static inline bool
1289 inline_secure(dns_zone_t *zone) {
1290 REQUIRE(DNS_ZONE_VALID(zone));
1291 if (zone->raw != NULL)
1292 return (true);
1293 return (false);
1294 }
1295
1296 /*
1297 * Returns true iff this the unsigned side of an inline-signing zone
1298 * Caller should hold zone lock.
1299 */
1300 static inline bool
1301 inline_raw(dns_zone_t *zone) {
1302 REQUIRE(DNS_ZONE_VALID(zone));
1303 if (zone->secure != NULL)
1304 return (true);
1305 return (false);
1306 }
1307
1308 /*
1309 * Single shot.
1310 */
1311 void
1312 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1313 char namebuf[1024];
1314
1315 REQUIRE(DNS_ZONE_VALID(zone));
1316 REQUIRE(rdclass != dns_rdataclass_none);
1317
1318 /*
1319 * Test and set.
1320 */
1321 LOCK_ZONE(zone);
1322 INSIST(zone != zone->raw);
1323 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1324 zone->rdclass == rdclass);
1325 zone->rdclass = rdclass;
1326
1327 if (zone->strnamerd != NULL)
1328 isc_mem_free(zone->mctx, zone->strnamerd);
1329 if (zone->strrdclass != NULL)
1330 isc_mem_free(zone->mctx, zone->strrdclass);
1331
1332 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1333 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1334 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1335 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1336
1337 if (inline_secure(zone))
1338 dns_zone_setclass(zone->raw, rdclass);
1339 UNLOCK_ZONE(zone);
1340 }
1341
1342 dns_rdataclass_t
1343 dns_zone_getclass(dns_zone_t *zone) {
1344 REQUIRE(DNS_ZONE_VALID(zone));
1345
1346 return (zone->rdclass);
1347 }
1348
1349 void
1350 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1351 REQUIRE(DNS_ZONE_VALID(zone));
1352
1353 LOCK_ZONE(zone);
1354 zone->notifytype = notifytype;
1355 UNLOCK_ZONE(zone);
1356 }
1357
1358 isc_result_t
1359 dns_zone_getserial(dns_zone_t *zone, uint32_t *serialp) {
1360 isc_result_t result;
1361 unsigned int soacount;
1362
1363 REQUIRE(DNS_ZONE_VALID(zone));
1364 REQUIRE(serialp != NULL);
1365
1366 LOCK_ZONE(zone);
1367 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1368 if (zone->db != NULL) {
1369 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1370 serialp, NULL, NULL, NULL, NULL,
1371 NULL);
1372 if (result == ISC_R_SUCCESS && soacount == 0)
1373 result = ISC_R_FAILURE;
1374 } else
1375 result = DNS_R_NOTLOADED;
1376 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1377 UNLOCK_ZONE(zone);
1378
1379 return (result);
1380 }
1381
1382 /*
1383 * Single shot.
1384 */
1385 void
1386 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1387 char namebuf[1024];
1388
1389 REQUIRE(DNS_ZONE_VALID(zone));
1390 REQUIRE(type != dns_zone_none);
1391
1392 /*
1393 * Test and set.
1394 */
1395 LOCK_ZONE(zone);
1396 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1397 zone->type = type;
1398
1399 if (zone->strnamerd != NULL)
1400 isc_mem_free(zone->mctx, zone->strnamerd);
1401
1402 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1403 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1404 UNLOCK_ZONE(zone);
1405 }
1406
1407 static void
1408 zone_freedbargs(dns_zone_t *zone) {
1409 unsigned int i;
1410
1411 /* Free the old database argument list. */
1412 if (zone->db_argv != NULL) {
1413 for (i = 0; i < zone->db_argc; i++)
1414 isc_mem_free(zone->mctx, zone->db_argv[i]);
1415 isc_mem_put(zone->mctx, zone->db_argv,
1416 zone->db_argc * sizeof(*zone->db_argv));
1417 }
1418 zone->db_argc = 0;
1419 zone->db_argv = NULL;
1420 }
1421
1422 isc_result_t
1423 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1424 size_t size = 0;
1425 unsigned int i;
1426 isc_result_t result = ISC_R_SUCCESS;
1427 void *mem;
1428 char **tmp, *tmp2, *base;
1429
1430 REQUIRE(DNS_ZONE_VALID(zone));
1431 REQUIRE(argv != NULL && *argv == NULL);
1432
1433 LOCK_ZONE(zone);
1434 size = (zone->db_argc + 1) * sizeof(char *);
1435 for (i = 0; i < zone->db_argc; i++)
1436 size += strlen(zone->db_argv[i]) + 1;
1437 mem = isc_mem_allocate(mctx, size);
1438 if (mem != NULL) {
1439 tmp = mem;
1440 tmp2 = mem;
1441 base = mem;
1442 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1443 for (i = 0; i < zone->db_argc; i++) {
1444 *tmp++ = tmp2;
1445 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1446 tmp2 += strlen(tmp2) + 1;
1447 }
1448 *tmp = NULL;
1449 } else
1450 result = ISC_R_NOMEMORY;
1451 UNLOCK_ZONE(zone);
1452 *argv = mem;
1453 return (result);
1454 }
1455
1456 isc_result_t
1457 dns_zone_setdbtype(dns_zone_t *zone,
1458 unsigned int dbargc, const char * const *dbargv)
1459 {
1460 isc_result_t result = ISC_R_SUCCESS;
1461 char **argv = NULL;
1462 unsigned int i;
1463
1464 REQUIRE(DNS_ZONE_VALID(zone));
1465 REQUIRE(dbargc >= 1);
1466 REQUIRE(dbargv != NULL);
1467
1468 LOCK_ZONE(zone);
1469
1470 /* Set up a new database argument list. */
1471 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1472 if (argv == NULL) {
1473 goto nomem;
1474 }
1475 for (i = 0; i < dbargc; i++) {
1476 argv[i] = NULL;
1477 }
1478 for (i = 0; i < dbargc; i++) {
1479 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1480 if (argv[i] == NULL)
1481 goto nomem;
1482 }
1483
1484 /* Free the old list. */
1485 zone_freedbargs(zone);
1486
1487 zone->db_argc = dbargc;
1488 zone->db_argv = argv;
1489 result = ISC_R_SUCCESS;
1490 goto unlock;
1491
1492 nomem:
1493 if (argv != NULL) {
1494 for (i = 0; i < dbargc; i++) {
1495 if (argv[i] != NULL) {
1496 isc_mem_free(zone->mctx, argv[i]);
1497 }
1498 }
1499 isc_mem_put(zone->mctx, argv, dbargc * sizeof(*argv));
1500 }
1501 result = ISC_R_NOMEMORY;
1502
1503 unlock:
1504 UNLOCK_ZONE(zone);
1505 return (result);
1506 }
1507
1508 static void
1509 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1510 char namebuf[1024];
1511
1512 if (zone->prev_view == NULL && zone->view != NULL) {
1513 dns_view_weakattach(zone->view, &zone->prev_view);
1514 }
1515
1516 INSIST(zone != zone->raw);
1517 if (zone->view != NULL) {
1518 dns_view_weakdetach(&zone->view);
1519 }
1520 dns_view_weakattach(view, &zone->view);
1521
1522 if (zone->strviewname != NULL) {
1523 isc_mem_free(zone->mctx, zone->strviewname);
1524 }
1525 if (zone->strnamerd != NULL) {
1526 isc_mem_free(zone->mctx, zone->strnamerd);
1527 }
1528
1529 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1530 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1531 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1532 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1533
1534 if (inline_secure(zone)) {
1535 dns_zone_setview(zone->raw, view);
1536 }
1537 }
1538
1539 void
1540 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1541 REQUIRE(DNS_ZONE_VALID(zone));
1542
1543 LOCK_ZONE(zone);
1544 dns_zone_setview_helper(zone, view);
1545 UNLOCK_ZONE(zone);
1546 }
1547
1548 dns_view_t *
1549 dns_zone_getview(dns_zone_t *zone) {
1550 REQUIRE(DNS_ZONE_VALID(zone));
1551
1552 return (zone->view);
1553 }
1554
1555 void
1556 dns_zone_setviewcommit(dns_zone_t *zone) {
1557 REQUIRE(DNS_ZONE_VALID(zone));
1558
1559 LOCK_ZONE(zone);
1560 if (zone->prev_view != NULL)
1561 dns_view_weakdetach(&zone->prev_view);
1562 UNLOCK_ZONE(zone);
1563 }
1564
1565 void
1566 dns_zone_setviewrevert(dns_zone_t *zone) {
1567 REQUIRE(DNS_ZONE_VALID(zone));
1568
1569 LOCK_ZONE(zone);
1570 if (zone->prev_view != NULL) {
1571 dns_zone_setview_helper(zone, zone->prev_view);
1572 dns_view_weakdetach(&zone->prev_view);
1573 }
1574 UNLOCK_ZONE(zone);
1575 }
1576
1577 isc_result_t
1578 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1579 isc_result_t result;
1580 char namebuf[1024];
1581
1582 REQUIRE(DNS_ZONE_VALID(zone));
1583 REQUIRE(origin != NULL);
1584
1585 LOCK_ZONE(zone);
1586 INSIST(zone != zone->raw);
1587 if (dns_name_dynamic(&zone->origin)) {
1588 dns_name_free(&zone->origin, zone->mctx);
1589 dns_name_init(&zone->origin, NULL);
1590 }
1591 result = dns_name_dup(origin, zone->mctx, &zone->origin);
1592
1593 if (zone->strnamerd != NULL)
1594 isc_mem_free(zone->mctx, zone->strnamerd);
1595 if (zone->strname != NULL)
1596 isc_mem_free(zone->mctx, zone->strname);
1597
1598 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1599 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1600 zone_name_tostr(zone, namebuf, sizeof namebuf);
1601 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1602
1603 if (result == ISC_R_SUCCESS && inline_secure(zone))
1604 result = dns_zone_setorigin(zone->raw, origin);
1605 UNLOCK_ZONE(zone);
1606 return (result);
1607 }
1608
1609 static isc_result_t
1610 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1611 char *copy;
1612
1613 if (value != NULL) {
1614 copy = isc_mem_strdup(zone->mctx, value);
1615 if (copy == NULL)
1616 return (ISC_R_NOMEMORY);
1617 } else {
1618 copy = NULL;
1619 }
1620
1621 if (*field != NULL)
1622 isc_mem_free(zone->mctx, *field);
1623
1624 *field = copy;
1625 return (ISC_R_SUCCESS);
1626 }
1627
1628 isc_result_t
1629 dns_zone_setfile(dns_zone_t *zone, const char *file,
1630 dns_masterformat_t format,
1631 const dns_master_style_t *style)
1632 {
1633 isc_result_t result = ISC_R_SUCCESS;
1634
1635 REQUIRE(DNS_ZONE_VALID(zone));
1636
1637 LOCK_ZONE(zone);
1638 result = dns_zone_setstring(zone, &zone->masterfile, file);
1639 if (result == ISC_R_SUCCESS) {
1640 zone->masterformat = format;
1641 if (format == dns_masterformat_text)
1642 zone->masterstyle = style;
1643 result = default_journal(zone);
1644 }
1645 UNLOCK_ZONE(zone);
1646
1647 return (result);
1648 }
1649
1650 const char *
1651 dns_zone_getfile(dns_zone_t *zone) {
1652 REQUIRE(DNS_ZONE_VALID(zone));
1653
1654 return (zone->masterfile);
1655 }
1656
1657 dns_ttl_t
1658 dns_zone_getmaxttl(dns_zone_t *zone) {
1659 REQUIRE(DNS_ZONE_VALID(zone));
1660
1661 return (zone->maxttl);
1662 }
1663
1664 void
1665 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1666 REQUIRE(DNS_ZONE_VALID(zone));
1667
1668 LOCK_ZONE(zone);
1669 if (maxttl != 0)
1670 zone->options |= DNS_ZONEOPT_CHECKTTL;
1671 else
1672 zone->options &= ~DNS_ZONEOPT_CHECKTTL;
1673 zone->maxttl = maxttl;
1674 UNLOCK_ZONE(zone);
1675
1676 return;
1677 }
1678
1679 static isc_result_t
1680 default_journal(dns_zone_t *zone) {
1681 isc_result_t result;
1682 char *journal;
1683
1684 REQUIRE(DNS_ZONE_VALID(zone));
1685 REQUIRE(LOCKED_ZONE(zone));
1686
1687 if (zone->masterfile != NULL) {
1688 /* Calculate string length including '\0'. */
1689 int len = strlen(zone->masterfile) + sizeof(".jnl");
1690 journal = isc_mem_allocate(zone->mctx, len);
1691 if (journal == NULL)
1692 return (ISC_R_NOMEMORY);
1693 strlcpy(journal, zone->masterfile, len);
1694 strlcat(journal, ".jnl", len);
1695 } else {
1696 journal = NULL;
1697 }
1698 result = dns_zone_setstring(zone, &zone->journal, journal);
1699 if (journal != NULL)
1700 isc_mem_free(zone->mctx, journal);
1701 return (result);
1702 }
1703
1704 isc_result_t
1705 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1706 isc_result_t result = ISC_R_SUCCESS;
1707
1708 REQUIRE(DNS_ZONE_VALID(zone));
1709
1710 LOCK_ZONE(zone);
1711 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1712 UNLOCK_ZONE(zone);
1713
1714 return (result);
1715 }
1716
1717 char *
1718 dns_zone_getjournal(dns_zone_t *zone) {
1719 REQUIRE(DNS_ZONE_VALID(zone));
1720
1721 return (zone->journal);
1722 }
1723
1724 /*
1725 * Return true iff the zone is "dynamic", in the sense that the zone's
1726 * master file (if any) is written by the server, rather than being
1727 * updated manually and read by the server.
1728 *
1729 * This is true for slave zones, mirror zones, stub zones, key zones,
1730 * and zones that allow dynamic updates either by having an update
1731 * policy ("ssutable") or an "allow-update" ACL with a value other than
1732 * exactly "{ none; }".
1733 */
1734 bool
1735 dns_zone_isdynamic(dns_zone_t *zone, bool ignore_freeze) {
1736 REQUIRE(DNS_ZONE_VALID(zone));
1737
1738 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
1739 zone->type == dns_zone_stub || zone->type == dns_zone_key ||
1740 (zone->type == dns_zone_redirect && zone->masters != NULL))
1741 return (true);
1742
1743 /* Inline zones are always dynamic. */
1744 if (zone->type == dns_zone_master && zone->raw != NULL)
1745 return (true);
1746
1747 /* If !ignore_freeze, we need check whether updates are disabled. */
1748 if (zone->type == dns_zone_master &&
1749 (!zone->update_disabled || ignore_freeze) &&
1750 ((zone->ssutable != NULL) ||
1751 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1752 return (true);
1753
1754 return (false);
1755
1756 }
1757
1758 /*
1759 * Set the response policy index and information for a zone.
1760 */
1761 isc_result_t
1762 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1763 dns_rpz_num_t rpz_num)
1764 {
1765 /*
1766 * Only RBTDB zones can be used for response policy zones,
1767 * because only they have the code to create the summary data.
1768 * Only zones that are loaded instead of mmap()ed create the
1769 * summary data and so can be policy zones.
1770 */
1771 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1772 strcmp(zone->db_argv[0], "rbt64") != 0)
1773 return (ISC_R_NOTIMPLEMENTED);
1774 if (zone->masterformat == dns_masterformat_map)
1775 return (ISC_R_NOTIMPLEMENTED);
1776
1777 /*
1778 * This must happen only once or be redundant.
1779 */
1780 LOCK_ZONE(zone);
1781 if (zone->rpzs != NULL) {
1782 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1783 } else {
1784 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1785 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1786 zone->rpz_num = rpz_num;
1787 }
1788 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1789 UNLOCK_ZONE(zone);
1790
1791 return (ISC_R_SUCCESS);
1792 }
1793
1794 dns_rpz_num_t
1795 dns_zone_get_rpz_num(dns_zone_t *zone) {
1796 return (zone->rpz_num);
1797 }
1798
1799 /*
1800 * If a zone is a response policy zone, mark its new database.
1801 */
1802 void
1803 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1804 isc_result_t result;
1805 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1806 return;
1807 }
1808 REQUIRE(zone->rpzs != NULL);
1809 result = dns_db_updatenotify_register(db,
1810 dns_rpz_dbupdate_callback,
1811 zone->rpzs->zones[zone->rpz_num]);
1812 REQUIRE(result == ISC_R_SUCCESS);
1813 }
1814
1815 static void
1816 dns_zone_rpz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1817 if (zone->rpz_num == DNS_RPZ_INVALID_NUM) {
1818 return;
1819 }
1820 REQUIRE(zone->rpzs != NULL);
1821 (void) dns_db_updatenotify_unregister(db,
1822 dns_rpz_dbupdate_callback,
1823 zone->rpzs->zones[zone->rpz_num]);
1824 }
1825
1826 void
1827 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1828 REQUIRE(DNS_ZONE_VALID(zone));
1829 REQUIRE(catzs != NULL);
1830
1831 LOCK_ZONE(zone);
1832 INSIST(zone->catzs == NULL || zone->catzs == catzs);
1833 dns_catz_catzs_set_view(catzs, zone->view);
1834 if (zone->catzs == NULL) {
1835 dns_catz_catzs_attach(catzs, &zone->catzs);
1836 }
1837 UNLOCK_ZONE(zone);
1838 }
1839
1840 /*
1841 * If a zone is a catalog zone, attach it to update notification in database.
1842 */
1843 void
1844 dns_zone_catz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1845 REQUIRE(DNS_ZONE_VALID(zone));
1846 REQUIRE(db != NULL);
1847
1848 if (zone->catzs != NULL) {
1849 dns_db_updatenotify_register(db, dns_catz_dbupdate_callback,
1850 zone->catzs);
1851 }
1852 }
1853
1854 static void
1855 dns_zone_catz_disable_db(dns_zone_t *zone, dns_db_t *db) {
1856 REQUIRE(DNS_ZONE_VALID(zone));
1857 REQUIRE(db != NULL);
1858
1859 if (zone->catzs != NULL) {
1860 dns_db_updatenotify_unregister(db, dns_catz_dbupdate_callback,
1861 zone->catzs);
1862 }
1863 }
1864
1865 /*
1866 * Set catalog zone ownership of the zone
1867 */
1868 void
1869 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
1870 REQUIRE(DNS_ZONE_VALID(zone));
1871 REQUIRE(catz != NULL);
1872 LOCK_ZONE(zone);
1873 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
1874 zone->parentcatz = catz;
1875 UNLOCK_ZONE(zone);
1876 }
1877
1878 dns_catz_zone_t *
1879 dns_zone_get_parentcatz(const dns_zone_t *zone) {
1880 REQUIRE(DNS_ZONE_VALID(zone));
1881 return (zone->parentcatz);
1882 }
1883
1884
1885 static bool
1886 zone_touched(dns_zone_t *zone) {
1887 isc_result_t result;
1888 isc_time_t modtime;
1889 dns_include_t *include;
1890
1891 REQUIRE(DNS_ZONE_VALID(zone));
1892
1893 result = isc_file_getmodtime(zone->masterfile, &modtime);
1894 if (result != ISC_R_SUCCESS ||
1895 isc_time_compare(&modtime, &zone->loadtime) > 0)
1896 return (true);
1897
1898 for (include = ISC_LIST_HEAD(zone->includes);
1899 include != NULL;
1900 include = ISC_LIST_NEXT(include, link))
1901 {
1902 result = isc_file_getmodtime(include->name, &modtime);
1903 if (result != ISC_R_SUCCESS ||
1904 isc_time_compare(&modtime, &include->filetime) > 0)
1905 return (true);
1906 }
1907
1908 return (false);
1909 }
1910
1911 /*
1912 * Note: when dealing with inline-signed zones, external callers will always
1913 * call zone_load() for the secure zone; zone_load() calls itself recursively
1914 * in order to load the raw zone.
1915 */
1916 static isc_result_t
1917 zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
1918 isc_result_t result;
1919 isc_time_t now;
1920 isc_time_t loadtime;
1921 dns_db_t *db = NULL;
1922 bool rbt, hasraw;
1923
1924 REQUIRE(DNS_ZONE_VALID(zone));
1925
1926 if (!locked)
1927 LOCK_ZONE(zone);
1928
1929 INSIST(zone != zone->raw);
1930 hasraw = inline_secure(zone);
1931 if (hasraw) {
1932 /*
1933 * We are trying to load an inline-signed zone. First call
1934 * self recursively to try loading the raw version of the zone.
1935 * Assuming the raw zone file is readable, there are two
1936 * possibilities:
1937 *
1938 * a) the raw zone was not yet loaded and thus it will be
1939 * loaded now, synchronously; if this succeeds, a
1940 * subsequent attempt to load the signed zone file will
1941 * take place and thus zone_postload() will be called
1942 * twice: first for the raw zone and then for the secure
1943 * zone; the latter call will take care of syncing the raw
1944 * version with the secure version,
1945 *
1946 * b) the raw zone was already loaded and we are trying to
1947 * reload it, which will happen asynchronously; this means
1948 * zone_postload() will only be called for the raw zone
1949 * because "result" returned by the zone_load() call below
1950 * will not be ISC_R_SUCCESS but rather DNS_R_CONTINUE;
1951 * zone_postload() called for the raw zone will take care
1952 * of syncing the raw version with the secure version.
1953 */
1954 result = zone_load(zone->raw, flags, false);
1955 if (result != ISC_R_SUCCESS) {
1956 if (!locked)
1957 UNLOCK_ZONE(zone);
1958 return(result);
1959 }
1960 LOCK_ZONE(zone->raw);
1961 }
1962
1963 TIME_NOW(&now);
1964
1965 INSIST(zone->type != dns_zone_none);
1966
1967 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1968 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1969 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1970 result = DNS_R_CONTINUE;
1971 goto cleanup;
1972 }
1973
1974 INSIST(zone->db_argc >= 1);
1975
1976 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1977 strcmp(zone->db_argv[0], "rbt64") == 0;
1978
1979 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1980 /*
1981 * The zone has no master file configured.
1982 */
1983 result = ISC_R_SUCCESS;
1984 goto cleanup;
1985 }
1986
1987 if (zone->db != NULL && dns_zone_isdynamic(zone, false)) {
1988 /*
1989 * This is a slave, stub, or dynamically updated
1990 * zone being reloaded. Do nothing - the database
1991 * we already have is guaranteed to be up-to-date.
1992 */
1993 if (zone->type == dns_zone_master && !hasraw)
1994 result = DNS_R_DYNAMIC;
1995 else
1996 result = ISC_R_SUCCESS;
1997 goto cleanup;
1998 }
1999
2000 /*
2001 * Store the current time before the zone is loaded, so that if the
2002 * file changes between the time of the load and the time that
2003 * zone->loadtime is set, then the file will still be reloaded
2004 * the next time dns_zone_load is called.
2005 */
2006 TIME_NOW(&loadtime);
2007
2008 /*
2009 * Don't do the load if the file that stores the zone is older
2010 * than the last time the zone was loaded. If the zone has not
2011 * been loaded yet, zone->loadtime will be the epoch.
2012 */
2013 if (zone->masterfile != NULL) {
2014 isc_time_t filetime;
2015
2016 /*
2017 * The file is already loaded. If we are just doing a
2018 * "rndc reconfig", we are done.
2019 */
2020 if (!isc_time_isepoch(&zone->loadtime) &&
2021 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
2022 result = ISC_R_SUCCESS;
2023 goto cleanup;
2024 }
2025
2026 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
2027 !zone_touched(zone))
2028 {
2029 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2030 ISC_LOG_DEBUG(1),
2031 "skipping load: master file "
2032 "older than last load");
2033 result = DNS_R_UPTODATE;
2034 goto cleanup;
2035 }
2036
2037 /*
2038 * If the file modification time is in the past
2039 * set loadtime to that value.
2040 */
2041 result = isc_file_getmodtime(zone->masterfile, &filetime);
2042 if (result == ISC_R_SUCCESS &&
2043 isc_time_compare(&loadtime, &filetime) > 0)
2044 loadtime = filetime;
2045 }
2046
2047 /*
2048 * Built in zones (with the exception of empty zones) don't need
2049 * to be reloaded.
2050 */
2051 if (zone->type == dns_zone_master &&
2052 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2053 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2054 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2055 result = ISC_R_SUCCESS;
2056 goto cleanup;
2057 }
2058
2059 /*
2060 * Zones associated with a DLZ don't need to be loaded either,
2061 * but we need to associate the database with the zone object.
2062 */
2063 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2064 dns_dlzdb_t *dlzdb;
2065 dns_dlzfindzone_t findzone;
2066
2067 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2068 dlzdb != NULL;
2069 dlzdb = ISC_LIST_NEXT(dlzdb, link))
2070 {
2071 INSIST(DNS_DLZ_VALID(dlzdb));
2072 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
2073 break;
2074 }
2075
2076 if (dlzdb == NULL) {
2077 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2078 ISC_LOG_ERROR,
2079 "DLZ %s does not exist or is set "
2080 "to 'search yes;'", zone->db_argv[1]);
2081 result = ISC_R_NOTFOUND;
2082 goto cleanup;
2083 }
2084
2085 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2086 /* ask SDLZ driver if the zone is supported */
2087 findzone = dlzdb->implementation->methods->findzone;
2088 result = (*findzone)(dlzdb->implementation->driverarg,
2089 dlzdb->dbdata, dlzdb->mctx,
2090 zone->view->rdclass, &zone->origin,
2091 NULL, NULL, &db);
2092 if (result != ISC_R_NOTFOUND) {
2093 if (zone->db != NULL)
2094 zone_detachdb(zone);
2095 zone_attachdb(zone, db);
2096 dns_db_detach(&db);
2097 result = ISC_R_SUCCESS;
2098 }
2099 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2100
2101 if (result == ISC_R_SUCCESS) {
2102 if (dlzdb->configure_callback == NULL)
2103 goto cleanup;
2104
2105 result = (*dlzdb->configure_callback)(zone->view,
2106 dlzdb, zone);
2107 if (result != ISC_R_SUCCESS)
2108 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2109 ISC_LOG_ERROR,
2110 "DLZ configuration callback: %s",
2111 isc_result_totext(result));
2112 }
2113 goto cleanup;
2114 }
2115
2116 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2117 zone->type == dns_zone_stub ||
2118 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2119 rbt) {
2120 if (zone->masterfile == NULL ||
2121 !isc_file_exists(zone->masterfile)) {
2122 if (zone->masterfile != NULL) {
2123 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2124 ISC_LOG_DEBUG(1),
2125 "no master file");
2126 }
2127 zone->refreshtime = now;
2128 if (zone->task != NULL)
2129 zone_settimer(zone, &now);
2130 result = ISC_R_SUCCESS;
2131 goto cleanup;
2132 }
2133 }
2134
2135 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2136 ISC_LOG_DEBUG(1), "starting load");
2137
2138 result = dns_db_create(zone->mctx, zone->db_argv[0],
2139 &zone->origin, (zone->type == dns_zone_stub) ?
2140 dns_dbtype_stub : dns_dbtype_zone,
2141 zone->rdclass,
2142 zone->db_argc - 1, zone->db_argv + 1,
2143 &db);
2144
2145 if (result != ISC_R_SUCCESS) {
2146 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2147 "loading zone: creating database: %s",
2148 isc_result_totext(result));
2149 goto cleanup;
2150 }
2151 dns_db_settask(db, zone->task);
2152
2153 if (zone->type == dns_zone_master || zone->type == dns_zone_slave ||
2154 zone->type == dns_zone_mirror)
2155 {
2156 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2157 if (result == ISC_R_NOTIMPLEMENTED) {
2158 result = ISC_R_SUCCESS;
2159 }
2160 if (result != ISC_R_SUCCESS) {
2161 goto cleanup;
2162 }
2163 }
2164
2165 if (!dns_db_ispersistent(db)) {
2166 if (zone->masterfile != NULL) {
2167 result = zone_startload(db, zone, loadtime);
2168 } else {
2169 result = DNS_R_NOMASTERFILE;
2170 if (zone->type == dns_zone_master ||
2171 (zone->type == dns_zone_redirect &&
2172 zone->masters == NULL)) {
2173 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2174 ISC_LOG_ERROR,
2175 "loading zone: "
2176 "no master file configured");
2177 goto cleanup;
2178 }
2179 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2180 ISC_LOG_INFO, "loading zone: "
2181 "no master file configured: continuing");
2182 }
2183 }
2184
2185 if (result == DNS_R_CONTINUE) {
2186 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2187 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
2188 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2189 goto cleanup;
2190 }
2191
2192 result = zone_postload(zone, db, loadtime, result);
2193
2194 cleanup:
2195 if (hasraw)
2196 UNLOCK_ZONE(zone->raw);
2197 if (!locked)
2198 UNLOCK_ZONE(zone);
2199 if (db != NULL)
2200 dns_db_detach(&db);
2201 return (result);
2202 }
2203
2204 isc_result_t
2205 dns_zone_load(dns_zone_t *zone, bool newonly) {
2206 return (zone_load(zone, newonly ? DNS_ZONELOADFLAG_NOSTAT : 0, false));
2207 }
2208
2209 static void
2210 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2211 dns_asyncload_t *asl = event->ev_arg;
2212 dns_zone_t *zone = asl->zone;
2213 isc_result_t result;
2214
2215 UNUSED(task);
2216
2217 REQUIRE(DNS_ZONE_VALID(zone));
2218
2219 isc_event_free(&event);
2220
2221 LOCK_ZONE(zone);
2222 result = zone_load(zone, asl->flags, true);
2223 if (result != DNS_R_CONTINUE) {
2224 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2225 }
2226 UNLOCK_ZONE(zone);
2227
2228 /* Inform the zone table we've finished loading */
2229 if (asl->loaded != NULL)
2230 (asl->loaded)(asl->loaded_arg, zone, task);
2231
2232 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2233 dns_zone_idetach(&zone);
2234 }
2235
2236 isc_result_t
2237 dns_zone_asyncload(dns_zone_t *zone, bool newonly,
2238 dns_zt_zoneloaded_t done, void *arg)
2239 {
2240 isc_event_t *e;
2241 dns_asyncload_t *asl = NULL;
2242 isc_result_t result = ISC_R_SUCCESS;
2243
2244 REQUIRE(DNS_ZONE_VALID(zone));
2245
2246 if (zone->zmgr == NULL)
2247 return (ISC_R_FAILURE);
2248
2249 /* If we already have a load pending, stop now */
2250 LOCK_ZONE(zone);
2251 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2252 UNLOCK_ZONE(zone);
2253 return (ISC_R_ALREADYRUNNING);
2254 }
2255
2256 asl = isc_mem_get(zone->mctx, sizeof (*asl));
2257 if (asl == NULL)
2258 CHECK(ISC_R_NOMEMORY);
2259
2260 asl->zone = NULL;
2261 asl->flags = newonly ? DNS_ZONELOADFLAG_NOSTAT : 0;
2262 asl->loaded = done;
2263 asl->loaded_arg = arg;
2264
2265 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
2266 DNS_EVENT_ZONELOAD,
2267 zone_asyncload, asl,
2268 sizeof(isc_event_t));
2269 if (e == NULL)
2270 CHECK(ISC_R_NOMEMORY);
2271
2272 zone_iattach(zone, &asl->zone);
2273 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2274 isc_task_send(zone->loadtask, &e);
2275 UNLOCK_ZONE(zone);
2276
2277 return (ISC_R_SUCCESS);
2278
2279 failure:
2280 if (asl != NULL)
2281 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2282 UNLOCK_ZONE(zone);
2283 return (result);
2284 }
2285
2286 bool
2287 dns__zone_loadpending(dns_zone_t *zone) {
2288 REQUIRE(DNS_ZONE_VALID(zone));
2289
2290 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING));
2291 }
2292
2293 isc_result_t
2294 dns_zone_loadandthaw(dns_zone_t *zone) {
2295 isc_result_t result;
2296
2297 if (inline_raw(zone))
2298 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
2299 false);
2300 else
2301 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, false);
2302
2303 switch (result) {
2304 case DNS_R_CONTINUE:
2305 /* Deferred thaw. */
2306 break;
2307 case DNS_R_UPTODATE:
2308 case ISC_R_SUCCESS:
2309 case DNS_R_SEENINCLUDE:
2310 zone->update_disabled = false;
2311 break;
2312 case DNS_R_NOMASTERFILE:
2313 zone->update_disabled = false;
2314 break;
2315 default:
2316 /* Error, remain in disabled state. */
2317 break;
2318 }
2319 return (result);
2320 }
2321
2322 static unsigned int
2323 get_master_options(dns_zone_t *zone) {
2324 unsigned int options;
2325
2326 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2327 if (zone->type == dns_zone_slave || zone->type == dns_zone_mirror ||
2328 (zone->type == dns_zone_redirect && zone->masters == NULL))
2329 {
2330 options |= DNS_MASTER_SLAVE;
2331 }
2332 if (zone->type == dns_zone_key) {
2333 options |= DNS_MASTER_KEY;
2334 }
2335 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) {
2336 options |= DNS_MASTER_CHECKNS;
2337 }
2338 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) {
2339 options |= DNS_MASTER_FATALNS;
2340 }
2341 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) {
2342 options |= DNS_MASTER_CHECKNAMES;
2343 }
2344 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) {
2345 options |= DNS_MASTER_CHECKNAMESFAIL;
2346 }
2347 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX)) {
2348 options |= DNS_MASTER_CHECKMX;
2349 }
2350 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL)) {
2351 options |= DNS_MASTER_CHECKMXFAIL;
2352 }
2353 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD)) {
2354 options |= DNS_MASTER_CHECKWILDCARD;
2355 }
2356 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKTTL)) {
2357 options |= DNS_MASTER_CHECKTTL;
2358 }
2359
2360 return (options);
2361 }
2362
2363 static void
2364 zone_registerinclude(const char *filename, void *arg) {
2365 isc_result_t result;
2366 dns_zone_t *zone = (dns_zone_t *) arg;
2367 dns_include_t *inc = NULL;
2368
2369 REQUIRE(DNS_ZONE_VALID(zone));
2370
2371 if (filename == NULL)
2372 return;
2373
2374 /*
2375 * Suppress duplicates.
2376 */
2377 for (inc = ISC_LIST_HEAD(zone->newincludes);
2378 inc != NULL;
2379 inc = ISC_LIST_NEXT(inc, link))
2380 if (strcmp(filename, inc->name) == 0)
2381 return;
2382
2383 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2384 if (inc == NULL)
2385 return;
2386 inc->name = isc_mem_strdup(zone->mctx, filename);
2387 if (inc->name == NULL) {
2388 isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
2389 return;
2390 }
2391 ISC_LINK_INIT(inc, link);
2392
2393 result = isc_file_getmodtime(filename, &inc->filetime);
2394 if (result != ISC_R_SUCCESS)
2395 isc_time_settoepoch(&inc->filetime);
2396
2397 ISC_LIST_APPEND(zone->newincludes, inc, link);
2398 }
2399
2400 static void
2401 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2402 dns_load_t *load = event->ev_arg;
2403 isc_result_t result = ISC_R_SUCCESS;
2404 unsigned int options;
2405
2406 REQUIRE(DNS_LOAD_VALID(load));
2407
2408 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2409 result = ISC_R_CANCELED;
2410 isc_event_free(&event);
2411 if (result == ISC_R_CANCELED)
2412 goto fail;
2413
2414 options = get_master_options(load->zone);
2415
2416 result = dns_master_loadfileinc(load->zone->masterfile,
2417 dns_db_origin(load->db),
2418 dns_db_origin(load->db),
2419 load->zone->rdclass, options, 0,
2420 &load->callbacks, task,
2421 zone_loaddone, load,
2422 &load->zone->lctx,
2423 zone_registerinclude,
2424 load->zone, load->zone->mctx,
2425 load->zone->masterformat,
2426 load->zone->maxttl);
2427 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2428 result != DNS_R_SEENINCLUDE)
2429 goto fail;
2430 return;
2431
2432 fail:
2433 zone_loaddone(load, result);
2434 }
2435
2436 static void
2437 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2438 isc_result_t result;
2439 unsigned int soacount;
2440
2441 LOCK(&raw->lock);
2442 if (raw->db != NULL) {
2443 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2444 &rawdata->sourceserial,
2445 NULL, NULL, NULL, NULL,
2446 NULL);
2447 if (result == ISC_R_SUCCESS && soacount > 0U)
2448 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2449 }
2450 UNLOCK(&raw->lock);
2451 }
2452
2453 static void
2454 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2455 const char me[] = "zone_gotwritehandle";
2456 dns_zone_t *zone = event->ev_arg;
2457 isc_result_t result = ISC_R_SUCCESS;
2458 dns_dbversion_t *version = NULL;
2459 dns_masterrawheader_t rawdata;
2460
2461 REQUIRE(DNS_ZONE_VALID(zone));
2462 INSIST(task == zone->task);
2463 ENTER;
2464
2465 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2466 result = ISC_R_CANCELED;
2467 isc_event_free(&event);
2468 if (result == ISC_R_CANCELED)
2469 goto fail;
2470
2471 LOCK_ZONE(zone);
2472 INSIST(zone != zone->raw);
2473 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2474 if (zone->db != NULL) {
2475 const dns_master_style_t *output_style;
2476
2477 dns_db_currentversion(zone->db, &version);
2478 dns_master_initrawheader(&rawdata);
2479 if (inline_secure(zone))
2480 get_raw_serial(zone->raw, &rawdata);
2481 if (zone->type == dns_zone_key)
2482 output_style = &dns_master_style_keyzone;
2483 else if (zone->masterstyle != NULL)
2484 output_style = zone->masterstyle;
2485 else
2486 output_style = &dns_master_style_default;
2487 result = dns_master_dumpinc(zone->mctx, zone->db, version,
2488 output_style, zone->masterfile,
2489 zone->task, dump_done, zone,
2490 &zone->dctx, zone->masterformat,
2491 &rawdata);
2492 dns_db_closeversion(zone->db, &version, false);
2493 } else
2494 result = ISC_R_CANCELED;
2495 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2496 UNLOCK_ZONE(zone);
2497 if (result != DNS_R_CONTINUE)
2498 goto fail;
2499 return;
2500
2501 fail:
2502 dump_done(zone, result);
2503 }
2504
2505 /*
2506 * Save the raw serial number for inline-signing zones.
2507 * (XXX: Other information from the header will be used
2508 * for other purposes in the future, but for now this is
2509 * all we're interested in.)
2510 */
2511 static void
2512 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2513 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2514 return;
2515
2516 zone->sourceserial = header->sourceserial;
2517 zone->sourceserialset = true;
2518 }
2519
2520 void
2521 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2522 if (zone == NULL)
2523 return;
2524
2525 LOCK_ZONE(zone);
2526 zone_setrawdata(zone, header);
2527 UNLOCK_ZONE(zone);
2528 }
2529
2530 static isc_result_t
2531 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2532 const char me[] = "zone_startload";
2533 dns_load_t *load;
2534 isc_result_t result;
2535 isc_result_t tresult;
2536 unsigned int options;
2537
2538 ENTER;
2539
2540 dns_zone_rpz_enable_db(zone, db);
2541 dns_zone_catz_enable_db(zone, db);
2542
2543 options = get_master_options(zone);
2544 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) {
2545 options |= DNS_MASTER_MANYERRORS;
2546 }
2547
2548 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2549 load = isc_mem_get(zone->mctx, sizeof(*load));
2550 if (load == NULL)
2551 return (ISC_R_NOMEMORY);
2552
2553 load->mctx = NULL;
2554 load->zone = NULL;
2555 load->db = NULL;
2556 load->loadtime = loadtime;
2557 load->magic = LOAD_MAGIC;
2558
2559 isc_mem_attach(zone->mctx, &load->mctx);
2560 zone_iattach(zone, &load->zone);
2561 dns_db_attach(db, &load->db);
2562 dns_rdatacallbacks_init(&load->callbacks);
2563 load->callbacks.rawdata = zone_setrawdata;
2564 zone_iattach(zone, &load->callbacks.zone);
2565 result = dns_db_beginload(db, &load->callbacks);
2566 if (result != ISC_R_SUCCESS) {
2567 goto cleanup;
2568 }
2569 result = zonemgr_getio(zone->zmgr, true, zone->loadtask,
2570 zone_gotreadhandle, load,
2571 &zone->readio);
2572 if (result != ISC_R_SUCCESS) {
2573 /*
2574 * We can't report multiple errors so ignore
2575 * the result of dns_db_endload().
2576 */
2577 (void)dns_db_endload(load->db, &load->callbacks);
2578 goto cleanup;
2579 } else {
2580 result = DNS_R_CONTINUE;
2581 }
2582 } else {
2583 dns_rdatacallbacks_t callbacks;
2584
2585 dns_rdatacallbacks_init(&callbacks);
2586 callbacks.rawdata = zone_setrawdata;
2587 zone_iattach(zone, &callbacks.zone);
2588 result = dns_db_beginload(db, &callbacks);
2589 if (result != ISC_R_SUCCESS) {
2590 zone_idetach(&callbacks.zone);
2591 return (result);
2592 }
2593 result = dns_master_loadfile(zone->masterfile,
2594 &zone->origin, &zone->origin,
2595 zone->rdclass, options, 0,
2596 &callbacks,
2597 zone_registerinclude,
2598 zone, zone->mctx,
2599 zone->masterformat,
2600 zone->maxttl);
2601 tresult = dns_db_endload(db, &callbacks);
2602 if (result == ISC_R_SUCCESS) {
2603 result = tresult;
2604 }
2605 zone_idetach(&callbacks.zone);
2606 }
2607
2608 return (result);
2609
2610 cleanup:
2611 load->magic = 0;
2612 dns_db_detach(&load->db);
2613 zone_idetach(&load->zone);
2614 zone_idetach(&load->callbacks.zone);
2615 isc_mem_detach(&load->mctx);
2616 isc_mem_put(zone->mctx, load, sizeof(*load));
2617 return (result);
2618 }
2619
2620 static bool
2621 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2622 dns_name_t *owner)
2623 {
2624 isc_result_t result;
2625 char ownerbuf[DNS_NAME_FORMATSIZE];
2626 char namebuf[DNS_NAME_FORMATSIZE];
2627 char altbuf[DNS_NAME_FORMATSIZE];
2628 dns_fixedname_t fixed;
2629 dns_name_t *foundname;
2630 int level;
2631
2632 /*
2633 * "." means the services does not exist.
2634 */
2635 if (dns_name_equal(name, dns_rootname))
2636 return (true);
2637
2638 /*
2639 * Outside of zone.
2640 */
2641 if (!dns_name_issubdomain(name, &zone->origin)) {
2642 if (zone->checkmx != NULL)
2643 return ((zone->checkmx)(zone, name, owner));
2644 return (true);
2645 }
2646
2647 if (zone->type == dns_zone_master)
2648 level = ISC_LOG_ERROR;
2649 else
2650 level = ISC_LOG_WARNING;
2651
2652 foundname = dns_fixedname_initname(&fixed);
2653
2654 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2655 0, 0, NULL, foundname, NULL, NULL);
2656 if (result == ISC_R_SUCCESS)
2657 return (true);
2658
2659 if (result == DNS_R_NXRRSET) {
2660 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2661 0, 0, NULL, foundname, NULL, NULL);
2662 if (result == ISC_R_SUCCESS)
2663 return (true);
2664 }
2665
2666 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2667 dns_name_format(name, namebuf, sizeof namebuf);
2668 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2669 result == DNS_R_EMPTYNAME) {
2670 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2671 level = ISC_LOG_WARNING;
2672 dns_zone_log(zone, level,
2673 "%s/MX '%s' has no address records (A or AAAA)",
2674 ownerbuf, namebuf);
2675 return ((level == ISC_LOG_WARNING) ? true : false);
2676 }
2677
2678 if (result == DNS_R_CNAME) {
2679 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2680 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2681 level = ISC_LOG_WARNING;
2682 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2683 dns_zone_log(zone, level,
2684 "%s/MX '%s' is a CNAME (illegal)",
2685 ownerbuf, namebuf);
2686 return ((level == ISC_LOG_WARNING) ? true : false);
2687 }
2688
2689 if (result == DNS_R_DNAME) {
2690 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2691 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2692 level = ISC_LOG_WARNING;
2693 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2694 dns_name_format(foundname, altbuf, sizeof altbuf);
2695 dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2696 " '%s' (illegal)", ownerbuf, namebuf,
2697 altbuf);
2698 }
2699 return ((level == ISC_LOG_WARNING) ? true : false);
2700 }
2701
2702 if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2703 return ((zone->checkmx)(zone, name, owner));
2704
2705 return (true);
2706 }
2707
2708 static bool
2709 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2710 dns_name_t *owner)
2711 {
2712 isc_result_t result;
2713 char ownerbuf[DNS_NAME_FORMATSIZE];
2714 char namebuf[DNS_NAME_FORMATSIZE];
2715 char altbuf[DNS_NAME_FORMATSIZE];
2716 dns_fixedname_t fixed;
2717 dns_name_t *foundname;
2718 int level;
2719
2720 /*
2721 * "." means the services does not exist.
2722 */
2723 if (dns_name_equal(name, dns_rootname))
2724 return (true);
2725
2726 /*
2727 * Outside of zone.
2728 */
2729 if (!dns_name_issubdomain(name, &zone->origin)) {
2730 if (zone->checksrv != NULL)
2731 return ((zone->checksrv)(zone, name, owner));
2732 return (true);
2733 }
2734
2735 if (zone->type == dns_zone_master)
2736 level = ISC_LOG_ERROR;
2737 else
2738 level = ISC_LOG_WARNING;
2739
2740 foundname = dns_fixedname_initname(&fixed);
2741
2742 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2743 0, 0, NULL, foundname, NULL, NULL);
2744 if (result == ISC_R_SUCCESS)
2745 return (true);
2746
2747 if (result == DNS_R_NXRRSET) {
2748 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2749 0, 0, NULL, foundname, NULL, NULL);
2750 if (result == ISC_R_SUCCESS)
2751 return (true);
2752 }
2753
2754 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2755 dns_name_format(name, namebuf, sizeof namebuf);
2756 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2757 result == DNS_R_EMPTYNAME) {
2758 dns_zone_log(zone, level,
2759 "%s/SRV '%s' has no address records (A or AAAA)",
2760 ownerbuf, namebuf);
2761 /* XXX950 make fatal for 9.5.0. */
2762 return (true);
2763 }
2764
2765 if (result == DNS_R_CNAME) {
2766 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2767 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2768 level = ISC_LOG_WARNING;
2769 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2770 dns_zone_log(zone, level,
2771 "%s/SRV '%s' is a CNAME (illegal)",
2772 ownerbuf, namebuf);
2773 return ((level == ISC_LOG_WARNING) ? true : false);
2774 }
2775
2776 if (result == DNS_R_DNAME) {
2777 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2778 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2779 level = ISC_LOG_WARNING;
2780 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2781 dns_name_format(foundname, altbuf, sizeof altbuf);
2782 dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2783 "DNAME '%s' (illegal)", ownerbuf, namebuf,
2784 altbuf);
2785 }
2786 return ((level == ISC_LOG_WARNING) ? true : false);
2787 }
2788
2789 if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2790 return ((zone->checksrv)(zone, name, owner));
2791
2792 return (true);
2793 }
2794
2795 static bool
2796 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2797 dns_name_t *owner)
2798 {
2799 bool answer = true;
2800 isc_result_t result, tresult;
2801 char ownerbuf[DNS_NAME_FORMATSIZE];
2802 char namebuf[DNS_NAME_FORMATSIZE];
2803 char altbuf[DNS_NAME_FORMATSIZE];
2804 dns_fixedname_t fixed;
2805 dns_name_t *foundname;
2806 dns_rdataset_t a;
2807 dns_rdataset_t aaaa;
2808 int level;
2809
2810 /*
2811 * Outside of zone.
2812 */
2813 if (!dns_name_issubdomain(name, &zone->origin)) {
2814 if (zone->checkns != NULL)
2815 return ((zone->checkns)(zone, name, owner, NULL, NULL));
2816 return (true);
2817 }
2818
2819 if (zone->type == dns_zone_master)
2820 level = ISC_LOG_ERROR;
2821 else
2822 level = ISC_LOG_WARNING;
2823
2824 foundname = dns_fixedname_initname(&fixed);
2825 dns_rdataset_init(&a);
2826 dns_rdataset_init(&aaaa);
2827
2828 /*
2829 * Perform a regular lookup to catch DNAME records then look
2830 * for glue.
2831 */
2832 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2833 0, 0, NULL, foundname, &a, NULL);
2834 switch (result) {
2835 case ISC_R_SUCCESS:
2836 case DNS_R_DNAME:
2837 case DNS_R_CNAME:
2838 break;
2839 default:
2840 if (dns_rdataset_isassociated(&a))
2841 dns_rdataset_disassociate(&a);
2842 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2843 DNS_DBFIND_GLUEOK, 0, NULL,
2844 foundname, &a, NULL);
2845 }
2846 if (result == ISC_R_SUCCESS) {
2847 dns_rdataset_disassociate(&a);
2848 return (true);
2849 } else if (result == DNS_R_DELEGATION)
2850 dns_rdataset_disassociate(&a);
2851
2852 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2853 result == DNS_R_GLUE) {
2854 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2855 DNS_DBFIND_GLUEOK, 0, NULL,
2856 foundname, &aaaa, NULL);
2857 if (tresult == ISC_R_SUCCESS) {
2858 if (dns_rdataset_isassociated(&a))
2859 dns_rdataset_disassociate(&a);
2860 dns_rdataset_disassociate(&aaaa);
2861 return (true);
2862 }
2863 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME)
2864 dns_rdataset_disassociate(&aaaa);
2865 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2866 /*
2867 * Check glue against child zone.
2868 */
2869 if (zone->checkns != NULL)
2870 answer = (zone->checkns)(zone, name, owner,
2871 &a, &aaaa);
2872 if (dns_rdataset_isassociated(&a))
2873 dns_rdataset_disassociate(&a);
2874 if (dns_rdataset_isassociated(&aaaa))
2875 dns_rdataset_disassociate(&aaaa);
2876 return (answer);
2877 }
2878 }
2879
2880 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2881 dns_name_format(name, namebuf, sizeof namebuf);
2882 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2883 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2884 const char *what;
2885 bool required = false;
2886 if (dns_name_issubdomain(name, owner)) {
2887 what = "REQUIRED GLUE ";
2888 required = true;
2889 } else if (result == DNS_R_DELEGATION)
2890 what = "SIBLING GLUE ";
2891 else
2892 what = "";
2893
2894 if (result != DNS_R_DELEGATION || required ||
2895 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2896 dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2897 "address records (A or AAAA)",
2898 ownerbuf, namebuf, what);
2899 /*
2900 * Log missing address record.
2901 */
2902 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2903 (void)(zone->checkns)(zone, name, owner,
2904 &a, &aaaa);
2905 /* XXX950 make fatal for 9.5.0. */
2906 /* answer = false; */
2907 }
2908 } else if (result == DNS_R_CNAME) {
2909 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2910 ownerbuf, namebuf);
2911 /* XXX950 make fatal for 9.5.0. */
2912 /* answer = false; */
2913 } else if (result == DNS_R_DNAME) {
2914 dns_name_format(foundname, altbuf, sizeof altbuf);
2915 dns_zone_log(zone, level,
2916 "%s/NS '%s' is below a DNAME '%s' (illegal)",
2917 ownerbuf, namebuf, altbuf);
2918 /* XXX950 make fatal for 9.5.0. */
2919 /* answer = false; */
2920 }
2921
2922 if (dns_rdataset_isassociated(&a))
2923 dns_rdataset_disassociate(&a);
2924 if (dns_rdataset_isassociated(&aaaa))
2925 dns_rdataset_disassociate(&aaaa);
2926 return (answer);
2927 }
2928
2929 static bool
2930 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2931 dns_rdataset_t *rdataset)
2932 {
2933 dns_rdataset_t tmprdataset;
2934 isc_result_t result;
2935 bool answer = true;
2936 bool format = true;
2937 int level = ISC_LOG_WARNING;
2938 char ownerbuf[DNS_NAME_FORMATSIZE];
2939 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2940 unsigned int count1 = 0;
2941
2942 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2943 level = ISC_LOG_ERROR;
2944
2945 dns_rdataset_init(&tmprdataset);
2946 for (result = dns_rdataset_first(rdataset);
2947 result == ISC_R_SUCCESS;
2948 result = dns_rdataset_next(rdataset)) {
2949 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2950 unsigned int count2 = 0;
2951
2952 count1++;
2953 dns_rdataset_current(rdataset, &rdata1);
2954 dns_rdataset_clone(rdataset, &tmprdataset);
2955 for (result = dns_rdataset_first(&tmprdataset);
2956 result == ISC_R_SUCCESS;
2957 result = dns_rdataset_next(&tmprdataset)) {
2958 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2959 count2++;
2960 if (count1 >= count2)
2961 continue;
2962 dns_rdataset_current(&tmprdataset, &rdata2);
2963 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2964 if (format) {
2965 dns_name_format(owner, ownerbuf,
2966 sizeof ownerbuf);
2967 dns_rdatatype_format(rdata1.type,
2968 typebuf,
2969 sizeof(typebuf));
2970 format = false;
2971 }
2972 dns_zone_log(zone, level, "%s/%s has "
2973 "semantically identical records",
2974 ownerbuf, typebuf);
2975 if (level == ISC_LOG_ERROR)
2976 answer = false;
2977 break;
2978 }
2979 }
2980 dns_rdataset_disassociate(&tmprdataset);
2981 if (!format)
2982 break;
2983 }
2984 return (answer);
2985 }
2986
2987 static bool
2988 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2989 dns_dbiterator_t *dbiterator = NULL;
2990 dns_dbnode_t *node = NULL;
2991 dns_fixedname_t fixed;
2992 dns_name_t *name;
2993 dns_rdataset_t rdataset;
2994 dns_rdatasetiter_t *rdsit = NULL;
2995 bool ok = true;
2996 isc_result_t result;
2997
2998 name = dns_fixedname_initname(&fixed);
2999 dns_rdataset_init(&rdataset);
3000
3001 result = dns_db_createiterator(db, 0, &dbiterator);
3002 if (result != ISC_R_SUCCESS)
3003 return (true);
3004
3005 for (result = dns_dbiterator_first(dbiterator);
3006 result == ISC_R_SUCCESS;
3007 result = dns_dbiterator_next(dbiterator)) {
3008 result = dns_dbiterator_current(dbiterator, &node, name);
3009 if (result != ISC_R_SUCCESS)
3010 continue;
3011
3012 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
3013 if (result != ISC_R_SUCCESS)
3014 continue;
3015
3016 for (result = dns_rdatasetiter_first(rdsit);
3017 result == ISC_R_SUCCESS;
3018 result = dns_rdatasetiter_next(rdsit)) {
3019 dns_rdatasetiter_current(rdsit, &rdataset);
3020 if (!zone_rrset_check_dup(zone, name, &rdataset))
3021 ok = false;
3022 dns_rdataset_disassociate(&rdataset);
3023 }
3024 dns_rdatasetiter_destroy(&rdsit);
3025 dns_db_detachnode(db, &node);
3026 }
3027
3028 if (node != NULL)
3029 dns_db_detachnode(db, &node);
3030 dns_dbiterator_destroy(&dbiterator);
3031
3032 return (ok);
3033 }
3034
3035 static bool
3036 isspf(const dns_rdata_t *rdata) {
3037 char buf[1024];
3038 const unsigned char *data = rdata->data;
3039 unsigned int rdl = rdata->length, i = 0, tl, len;
3040
3041 while (rdl > 0U) {
3042 len = tl = *data;
3043 ++data;
3044 --rdl;
3045 INSIST(tl <= rdl);
3046 if (len > sizeof(buf) - i - 1)
3047 len = sizeof(buf) - i - 1;
3048 memmove(buf + i, data, len);
3049 i += len;
3050 data += tl;
3051 rdl -= tl;
3052 }
3053
3054 if (i < 6U)
3055 return(false);
3056
3057 buf[i] = 0;
3058 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
3059 return (true);
3060 return (false);
3061 }
3062
3063 static bool
3064 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3065 dns_dbiterator_t *dbiterator = NULL;
3066 dns_dbnode_t *node = NULL;
3067 dns_rdataset_t rdataset;
3068 dns_fixedname_t fixed;
3069 dns_fixedname_t fixedbottom;
3070 dns_rdata_mx_t mx;
3071 dns_rdata_ns_t ns;
3072 dns_rdata_in_srv_t srv;
3073 dns_rdata_t rdata;
3074 dns_name_t *name;
3075 dns_name_t *bottom;
3076 isc_result_t result;
3077 bool ok = true, have_spf, have_txt;
3078
3079 name = dns_fixedname_initname(&fixed);
3080 bottom = dns_fixedname_initname(&fixedbottom);
3081 dns_rdataset_init(&rdataset);
3082 dns_rdata_init(&rdata);
3083
3084 result = dns_db_createiterator(db, 0, &dbiterator);
3085 if (result != ISC_R_SUCCESS)
3086 return (true);
3087
3088 result = dns_dbiterator_first(dbiterator);
3089 while (result == ISC_R_SUCCESS) {
3090 result = dns_dbiterator_current(dbiterator, &node, name);
3091 if (result != ISC_R_SUCCESS)
3092 goto cleanup;
3093
3094 /*
3095 * Is this name visible in the zone?
3096 */
3097 if (!dns_name_issubdomain(name, &zone->origin) ||
3098 (dns_name_countlabels(bottom) > 0 &&
3099 dns_name_issubdomain(name, bottom)))
3100 goto next;
3101
3102 /*
3103 * Don't check the NS records at the origin.
3104 */
3105 if (dns_name_equal(name, &zone->origin))
3106 goto checkfordname;
3107
3108 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3109 0, 0, &rdataset, NULL);
3110 if (result != ISC_R_SUCCESS)
3111 goto checkfordname;
3112 /*
3113 * Remember bottom of zone due to NS.
3114 */
3115 dns_name_copynf(name, bottom);
3116
3117 result = dns_rdataset_first(&rdataset);
3118 while (result == ISC_R_SUCCESS) {
3119 dns_rdataset_current(&rdataset, &rdata);
3120 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3121 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3122 if (!zone_check_glue(zone, db, &ns.name, name))
3123 ok = false;
3124 dns_rdata_reset(&rdata);
3125 result = dns_rdataset_next(&rdataset);
3126 }
3127 dns_rdataset_disassociate(&rdataset);
3128 goto next;
3129
3130 checkfordname:
3131 result = dns_db_findrdataset(db, node, NULL,
3132 dns_rdatatype_dname, 0, 0,
3133 &rdataset, NULL);
3134 if (result == ISC_R_SUCCESS) {
3135 /*
3136 * Remember bottom of zone due to DNAME.
3137 */
3138 dns_name_copynf(name, bottom);
3139 dns_rdataset_disassociate(&rdataset);
3140 }
3141
3142 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3143 0, 0, &rdataset, NULL);
3144 if (result != ISC_R_SUCCESS)
3145 goto checksrv;
3146 result = dns_rdataset_first(&rdataset);
3147 while (result == ISC_R_SUCCESS) {
3148 dns_rdataset_current(&rdataset, &rdata);
3149 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3150 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3151 if (!zone_check_mx(zone, db, &mx.mx, name))
3152 ok = false;
3153 dns_rdata_reset(&rdata);
3154 result = dns_rdataset_next(&rdataset);
3155 }
3156 dns_rdataset_disassociate(&rdataset);
3157
3158 checksrv:
3159 if (zone->rdclass != dns_rdataclass_in)
3160 goto next;
3161 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3162 0, 0, &rdataset, NULL);
3163 if (result != ISC_R_SUCCESS)
3164 goto checkspf;
3165 result = dns_rdataset_first(&rdataset);
3166 while (result == ISC_R_SUCCESS) {
3167 dns_rdataset_current(&rdataset, &rdata);
3168 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3169 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3170 if (!zone_check_srv(zone, db, &srv.target, name))
3171 ok = false;
3172 dns_rdata_reset(&rdata);
3173 result = dns_rdataset_next(&rdataset);
3174 }
3175 dns_rdataset_disassociate(&rdataset);
3176
3177 checkspf:
3178 /*
3179 * Check if there is a type SPF record without an
3180 * SPF-formatted type TXT record also being present.
3181 */
3182 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
3183 goto next;
3184 if (zone->rdclass != dns_rdataclass_in)
3185 goto next;
3186 have_spf = have_txt = false;
3187 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3188 0, 0, &rdataset, NULL);
3189 if (result == ISC_R_SUCCESS) {
3190 dns_rdataset_disassociate(&rdataset);
3191 have_spf = true;
3192 }
3193 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3194 0, 0, &rdataset, NULL);
3195 if (result != ISC_R_SUCCESS)
3196 goto notxt;
3197 result = dns_rdataset_first(&rdataset);
3198 while (result == ISC_R_SUCCESS) {
3199 dns_rdataset_current(&rdataset, &rdata);
3200 have_txt = isspf(&rdata);
3201 dns_rdata_reset(&rdata);
3202 if (have_txt)
3203 break;
3204 result = dns_rdataset_next(&rdataset);
3205 }
3206 dns_rdataset_disassociate(&rdataset);
3207
3208 notxt:
3209 if (have_spf && !have_txt) {
3210 char namebuf[DNS_NAME_FORMATSIZE];
3211
3212 dns_name_format(name, namebuf, sizeof(namebuf));
3213 dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
3214 "SPF record but no SPF TXT record found, "
3215 "add matching type TXT record", namebuf);
3216 }
3217
3218 next:
3219 dns_db_detachnode(db, &node);
3220 result = dns_dbiterator_next(dbiterator);
3221 }
3222
3223 cleanup:
3224 if (node != NULL)
3225 dns_db_detachnode(db, &node);
3226 dns_dbiterator_destroy(&dbiterator);
3227
3228 return (ok);
3229 }
3230
3231 /*
3232 * OpenSSL verification of RSA keys with exponent 3 is known to be
3233 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3234 * if they are in use.
3235 */
3236 static void
3237 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3238 dns_dbnode_t *node = NULL;
3239 dns_dbversion_t *version = NULL;
3240 dns_rdata_dnskey_t dnskey;
3241 dns_rdata_t rdata = DNS_RDATA_INIT;
3242 dns_rdataset_t rdataset;
3243 isc_result_t result;
3244 bool logit, foundrsa = false;
3245 const char *algorithm;
3246
3247 result = dns_db_findnode(db, &zone->origin, false, &node);
3248 if (result != ISC_R_SUCCESS) {
3249 goto cleanup;
3250 }
3251
3252 dns_db_currentversion(db, &version);
3253 dns_rdataset_init(&rdataset);
3254 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3255 dns_rdatatype_none, 0, &rdataset, NULL);
3256 if (result != ISC_R_SUCCESS) {
3257 goto cleanup;
3258 }
3259
3260 for (result = dns_rdataset_first(&rdataset);
3261 result == ISC_R_SUCCESS;
3262 result = dns_rdataset_next(&rdataset))
3263 {
3264 dns_rdataset_current(&rdataset, &rdata);
3265 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3266 INSIST(result == ISC_R_SUCCESS);
3267
3268 /* RFC 3110, section 4: Performance Considerations:
3269 *
3270 * A public exponent of 3 minimizes the effort needed to verify
3271 * a signature. Use of 3 as the public exponent is weak for
3272 * confidentiality uses since, if the same data can be collected
3273 * encrypted under three different keys with an exponent of 3
3274 * then, using the Chinese Remainder Theorem [NETSEC], the
3275 * original plain text can be easily recovered. If a key is
3276 * known to be used only for authentication, as is the case with
3277 * DNSSEC, then an exponent of 3 is acceptable. However other
3278 * applications in the future may wish to leverage DNS
3279 * distributed keys for applications that do require
3280 * confidentiality. For keys which might have such other uses,
3281 * a more conservative choice would be 65537 (F4, the fourth
3282 * fermat number).
3283 */
3284 if (dnskey.algorithm == DST_ALG_RSASHA1 &&
3285 dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3286 dnskey.data[1] == 3)
3287 {
3288 if (dnskey.algorithm == DST_ALG_RSASHA1) {
3289 logit = !foundrsa;
3290 foundrsa = true;
3291 algorithm = "RSASHA1";
3292 }
3293 if (logit) {
3294 dnssec_log(zone, ISC_LOG_WARNING,
3295 "weak %s (%u) key found "
3296 "(exponent=3)", algorithm,
3297 dnskey.algorithm);
3298 }
3299 }
3300 dns_rdata_reset(&rdata);
3301 }
3302 dns_rdataset_disassociate(&rdataset);
3303
3304 cleanup:
3305 if (node != NULL) {
3306 dns_db_detachnode(db, &node);
3307 }
3308 if (version != NULL) {
3309 dns_db_closeversion(db, &version, false);
3310 }
3311 }
3312
3313 static void
3314 resume_signingwithkey(dns_zone_t *zone) {
3315 dns_dbnode_t *node = NULL;
3316 dns_dbversion_t *version = NULL;
3317 dns_rdata_t rdata = DNS_RDATA_INIT;
3318 dns_rdataset_t rdataset;
3319 isc_result_t result;
3320 dns_db_t *db = NULL;
3321
3322 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3323 if (zone->db != NULL) {
3324 dns_db_attach(zone->db, &db);
3325 }
3326 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3327 if (db == NULL) {
3328 goto cleanup;
3329 }
3330
3331 result = dns_db_findnode(db, &zone->origin, false, &node);
3332 if (result != ISC_R_SUCCESS) {
3333 goto cleanup;
3334 }
3335
3336 dns_db_currentversion(db, &version);
3337 dns_rdataset_init(&rdataset);
3338 result = dns_db_findrdataset(db, node, version,
3339 zone->privatetype,
3340 dns_rdatatype_none, 0,
3341 &rdataset, NULL);
3342 if (result != ISC_R_SUCCESS) {
3343 INSIST(!dns_rdataset_isassociated(&rdataset));
3344 goto cleanup;
3345 }
3346
3347 for (result = dns_rdataset_first(&rdataset);
3348 result == ISC_R_SUCCESS;
3349 result = dns_rdataset_next(&rdataset))
3350 {
3351 dns_rdataset_current(&rdataset, &rdata);
3352 if (rdata.length != 5 ||
3353 rdata.data[0] == 0 || rdata.data[4] != 0)
3354 {
3355 dns_rdata_reset(&rdata);
3356 continue;
3357 }
3358
3359 result = zone_signwithkey(zone, rdata.data[0],
3360 (rdata.data[1] << 8) | rdata.data[2],
3361 rdata.data[3]);
3362 if (result != ISC_R_SUCCESS) {
3363 dnssec_log(zone, ISC_LOG_ERROR,
3364 "zone_signwithkey failed: %s",
3365 dns_result_totext(result));
3366 }
3367 dns_rdata_reset(&rdata);
3368 }
3369 dns_rdataset_disassociate(&rdataset);
3370
3371 cleanup:
3372 if (db != NULL) {
3373 if (node != NULL) {
3374 dns_db_detachnode(db, &node);
3375 }
3376 if (version != NULL) {
3377 dns_db_closeversion(db, &version, false);
3378 }
3379 dns_db_detach(&db);
3380 }
3381 }
3382
3383 /*
3384 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3385 * supplied NSEC3PARAM RDATA.
3386 *
3387 * Zone must be locked by caller.
3388 */
3389 static isc_result_t
3390 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3391 dns_nsec3chain_t *nsec3chain, *current;
3392 dns_dbversion_t *version = NULL;
3393 bool nseconly = false, nsec3ok = false;
3394 isc_result_t result;
3395 isc_time_t now;
3396 unsigned int options = 0;
3397 char saltbuf[255*2+1];
3398 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
3399 dns_db_t *db = NULL;
3400
3401 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3402 if (zone->db != NULL) {
3403 dns_db_attach(zone->db, &db);
3404 }
3405 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3406
3407 if (db == NULL) {
3408 result = ISC_R_SUCCESS;
3409 goto cleanup;
3410 }
3411
3412 /*
3413 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3414 * chain from it is pointless as it would not be possible for the
3415 * latter to exist in the first place.
3416 */
3417 dns_db_currentversion(db, &version);
3418 result = dns_nsec_nseconly(db, version, &nseconly);
3419 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3420 dns_db_closeversion(db, &version, false);
3421 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3422 result = ISC_R_SUCCESS;
3423 goto cleanup;
3424 }
3425
3426 /*
3427 * Allocate and initialize structure preserving state of
3428 * adding/removing records belonging to this NSEC3 chain between
3429 * separate zone_nsec3chain() calls.
3430 */
3431 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3432 if (nsec3chain == NULL) {
3433 result = ISC_R_NOMEMORY;
3434 goto cleanup;
3435 }
3436
3437 nsec3chain->magic = 0;
3438 nsec3chain->done = false;
3439 nsec3chain->db = NULL;
3440 nsec3chain->dbiterator = NULL;
3441 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3442 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3443 nsec3chain->nsec3param.hash = nsec3param->hash;
3444 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3445 nsec3chain->nsec3param.flags = nsec3param->flags;
3446 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3447 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3448 nsec3chain->nsec3param.salt = nsec3chain->salt;
3449 nsec3chain->seen_nsec = false;
3450 nsec3chain->delete_nsec = false;
3451 nsec3chain->save_delete_nsec = false;
3452
3453 /*
3454 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3455 */
3456 if (nsec3param->flags == 0) {
3457 strlcpy(flags, "NONE", sizeof(flags));
3458 } else {
3459 flags[0] = '\0';
3460 if ((nsec3param->flags & DNS_NSEC3FLAG_REMOVE) != 0) {
3461 strlcat(flags, "REMOVE", sizeof(flags));
3462 }
3463 if ((nsec3param->flags & DNS_NSEC3FLAG_INITIAL) != 0) {
3464 if (flags[0] == '\0') {
3465 strlcpy(flags, "INITIAL", sizeof(flags));
3466 } else {
3467 strlcat(flags, "|INITIAL", sizeof(flags));
3468 }
3469 }
3470 if ((nsec3param->flags & DNS_NSEC3FLAG_CREATE) != 0) {
3471 if (flags[0] == '\0') {
3472 strlcpy(flags, "CREATE", sizeof(flags));
3473 } else {
3474 strlcat(flags, "|CREATE", sizeof(flags));
3475 }
3476 }
3477 if ((nsec3param->flags & DNS_NSEC3FLAG_NONSEC) != 0) {
3478 if (flags[0] == '\0') {
3479 strlcpy(flags, "NONSEC", sizeof(flags));
3480 } else {
3481 strlcat(flags, "|NONSEC", sizeof(flags));
3482 }
3483 }
3484 if ((nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) != 0) {
3485 if (flags[0] == '\0') {
3486 strlcpy(flags, "OPTOUT", sizeof(flags));
3487 } else {
3488 strlcat(flags, "|OPTOUT", sizeof(flags));
3489 }
3490 }
3491 }
3492 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3493 sizeof(saltbuf));
3494 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3495 dnssec_log(zone, ISC_LOG_INFO, "zone_addnsec3chain(%u,%s,%u,%s)",
3496 nsec3param->hash, flags, nsec3param->iterations, saltbuf);
3497
3498 /*
3499 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3500 * currently being processed, interrupt its processing to avoid
3501 * simultaneously adding and removing records for the same NSEC3 chain.
3502 */
3503 for (current = ISC_LIST_HEAD(zone->nsec3chain);
3504 current != NULL;
3505 current = ISC_LIST_NEXT(current, link))
3506 {
3507 if ((current->db == db) &&
3508 (current->nsec3param.hash == nsec3param->hash) &&
3509 (current->nsec3param.iterations ==
3510 nsec3param->iterations) &&
3511 (current->nsec3param.salt_length ==
3512 nsec3param->salt_length) &&
3513 memcmp(current->nsec3param.salt, nsec3param->salt,
3514 nsec3param->salt_length) == 0)
3515 {
3516 current->done = true;
3517 }
3518 }
3519
3520 /*
3521 * Attach zone database to the structure initialized above and create
3522 * an iterator for it with appropriate options in order to avoid
3523 * creating NSEC3 records for NSEC3 records.
3524 */
3525 dns_db_attach(db, &nsec3chain->db);
3526 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0) {
3527 options = DNS_DB_NONSEC3;
3528 }
3529 result = dns_db_createiterator(nsec3chain->db, options,
3530 &nsec3chain->dbiterator);
3531 if (result == ISC_R_SUCCESS) {
3532 result = dns_dbiterator_first(nsec3chain->dbiterator);
3533 }
3534 if (result == ISC_R_SUCCESS) {
3535 /*
3536 * Database iterator initialization succeeded. We are now
3537 * ready to kick off adding/removing records belonging to this
3538 * NSEC3 chain. Append the structure initialized above to the
3539 * "nsec3chain" list for the zone and set the appropriate zone
3540 * timer so that zone_nsec3chain() is called as soon as
3541 * possible.
3542 */
3543 dns_dbiterator_pause(nsec3chain->dbiterator);
3544 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
3545 nsec3chain, link);
3546 nsec3chain = NULL;
3547 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3548 TIME_NOW(&now);
3549 zone->nsec3chaintime = now;
3550 if (zone->task != NULL) {
3551 zone_settimer(zone, &now);
3552 }
3553 }
3554 }
3555
3556 if (nsec3chain != NULL) {
3557 if (nsec3chain->db != NULL) {
3558 dns_db_detach(&nsec3chain->db);
3559 }
3560 if (nsec3chain->dbiterator != NULL) {
3561 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3562 }
3563 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3564 }
3565
3566 cleanup:
3567 if (db != NULL) {
3568 dns_db_detach(&db);
3569 }
3570 return (result);
3571 }
3572
3573 /*
3574 * Find private-type records at the zone apex which signal that an NSEC3 chain
3575 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3576 * and pass it to zone_addnsec3chain().
3577 *
3578 * Zone must be locked by caller.
3579 */
3580 static void
3581 resume_addnsec3chain(dns_zone_t *zone) {
3582 dns_dbnode_t *node = NULL;
3583 dns_dbversion_t *version = NULL;
3584 dns_rdataset_t rdataset;
3585 isc_result_t result;
3586 dns_rdata_nsec3param_t nsec3param;
3587 bool nseconly = false, nsec3ok = false;
3588 dns_db_t *db = NULL;
3589
3590 INSIST(LOCKED_ZONE(zone));
3591
3592 if (zone->privatetype == 0)
3593 return;
3594
3595 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3596 if (zone->db != NULL) {
3597 dns_db_attach(zone->db, &db);
3598 }
3599 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3600 if (db == NULL) {
3601 goto cleanup;
3602 }
3603
3604 result = dns_db_findnode(db, &zone->origin, false, &node);
3605 if (result != ISC_R_SUCCESS) {
3606 goto cleanup;
3607 }
3608
3609 dns_db_currentversion(db, &version);
3610
3611 /*
3612 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3613 * apex to exist and contain no keys using NSEC-only algorithms.
3614 */
3615 result = dns_nsec_nseconly(db, version, &nseconly);
3616 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3617
3618 /*
3619 * Get the RRset containing all private-type records at the zone apex.
3620 */
3621 dns_rdataset_init(&rdataset);
3622 result = dns_db_findrdataset(db, node, version,
3623 zone->privatetype, dns_rdatatype_none,
3624 0, &rdataset, NULL);
3625 if (result != ISC_R_SUCCESS) {
3626 INSIST(!dns_rdataset_isassociated(&rdataset));
3627 goto cleanup;
3628 }
3629
3630 for (result = dns_rdataset_first(&rdataset);
3631 result == ISC_R_SUCCESS;
3632 result = dns_rdataset_next(&rdataset))
3633 {
3634 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3635 dns_rdata_t rdata = DNS_RDATA_INIT;
3636 dns_rdata_t private = DNS_RDATA_INIT;
3637
3638 dns_rdataset_current(&rdataset, &private);
3639 /*
3640 * Try extracting NSEC3PARAM RDATA from this private-type
3641 * record. Failure means this private-type record does not
3642 * represent an NSEC3PARAM record, so skip it.
3643 */
3644 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3645 sizeof(buf)))
3646 {
3647 continue;
3648 }
3649 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3650 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3651 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3652 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3653 {
3654 /*
3655 * Pass the NSEC3PARAM RDATA contained in this
3656 * private-type record to zone_addnsec3chain() so that
3657 * it can kick off adding or removing NSEC3 records.
3658 */
3659 result = zone_addnsec3chain(zone, &nsec3param);
3660 if (result != ISC_R_SUCCESS) {
3661 dnssec_log(zone, ISC_LOG_ERROR,
3662 "zone_addnsec3chain failed: %s",
3663 dns_result_totext(result));
3664 }
3665 }
3666 }
3667 dns_rdataset_disassociate(&rdataset);
3668
3669 cleanup:
3670 if (db != NULL) {
3671 if (node != NULL) {
3672 dns_db_detachnode(db, &node);
3673 }
3674 if (version != NULL) {
3675 dns_db_closeversion(db, &version, false);
3676 }
3677 dns_db_detach(&db);
3678 }
3679 }
3680
3681 static void
3682 set_resigntime(dns_zone_t *zone) {
3683 dns_rdataset_t rdataset;
3684 dns_fixedname_t fixed;
3685 unsigned int resign;
3686 isc_result_t result;
3687 uint32_t nanosecs;
3688 dns_db_t *db = NULL;
3689
3690 /* We only re-sign zones that can be dynamically updated */
3691 if (zone->update_disabled)
3692 return;
3693
3694 if (!inline_secure(zone) && (zone->type != dns_zone_master ||
3695 (zone->ssutable == NULL &&
3696 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3697 return;
3698
3699 dns_rdataset_init(&rdataset);
3700 dns_fixedname_init(&fixed);
3701
3702 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3703 if (zone->db != NULL)
3704 dns_db_attach(zone->db, &db);
3705 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3706 if (db == NULL) {
3707 isc_time_settoepoch(&zone->resigntime);
3708 return;
3709 }
3710
3711 result = dns_db_getsigningtime(db, &rdataset,
3712 dns_fixedname_name(&fixed));
3713 if (result != ISC_R_SUCCESS) {
3714 isc_time_settoepoch(&zone->resigntime);
3715 goto cleanup;
3716 }
3717
3718 resign = rdataset.resign - zone->sigresigninginterval;
3719 dns_rdataset_disassociate(&rdataset);
3720 nanosecs = isc_random_uniform(1000000000);
3721 isc_time_set(&zone->resigntime, resign, nanosecs);
3722 cleanup:
3723 dns_db_detach(&db);
3724 return;
3725 }
3726
3727 static isc_result_t
3728 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3729 dns_dbnode_t *node = NULL;
3730 dns_rdataset_t rdataset;
3731 dns_dbversion_t *version = NULL;
3732 dns_rdata_nsec3param_t nsec3param;
3733 bool ok = false;
3734 isc_result_t result;
3735 dns_rdata_t rdata = DNS_RDATA_INIT;
3736 bool dynamic = (zone->type == dns_zone_master)
3737 ? dns_zone_isdynamic(zone, false) : false;
3738
3739 dns_rdataset_init(&rdataset);
3740 result = dns_db_findnode(db, &zone->origin, false, &node);
3741 if (result != ISC_R_SUCCESS) {
3742 dns_zone_log(zone, ISC_LOG_ERROR,
3743 "nsec3param lookup failure: %s",
3744 dns_result_totext(result));
3745 return (result);
3746 }
3747 dns_db_currentversion(db, &version);
3748
3749 result = dns_db_findrdataset(db, node, version,
3750 dns_rdatatype_nsec3param,
3751 dns_rdatatype_none, 0, &rdataset, NULL);
3752 if (result == ISC_R_NOTFOUND) {
3753 INSIST(!dns_rdataset_isassociated(&rdataset));
3754 result = ISC_R_SUCCESS;
3755 goto cleanup;
3756 }
3757 if (result != ISC_R_SUCCESS) {
3758 INSIST(!dns_rdataset_isassociated(&rdataset));
3759 dns_zone_log(zone, ISC_LOG_ERROR,
3760 "nsec3param lookup failure: %s",
3761 dns_result_totext(result));
3762 goto cleanup;
3763 }
3764
3765 /*
3766 * For dynamic zones we must support every algorithm so we can
3767 * regenerate all the NSEC3 chains.
3768 * For non-dynamic zones we only need to find a supported algorithm.
3769 */
3770 for (result = dns_rdataset_first(&rdataset);
3771 result == ISC_R_SUCCESS;
3772 result = dns_rdataset_next(&rdataset))
3773 {
3774 dns_rdataset_current(&rdataset, &rdata);
3775 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3776 dns_rdata_reset(&rdata);
3777 INSIST(result == ISC_R_SUCCESS);
3778 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3779 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3780 {
3781 dns_zone_log(zone, ISC_LOG_WARNING,
3782 "nsec3 test \"unknown\" hash algorithm found: %u",
3783 nsec3param.hash);
3784 ok = true;
3785 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3786 if (dynamic) {
3787 dns_zone_log(zone, ISC_LOG_ERROR,
3788 "unsupported nsec3 hash algorithm"
3789 " in dynamic zone: %u",
3790 nsec3param.hash);
3791 result = DNS_R_BADZONE;
3792 /* Stop second error message. */
3793 ok = true;
3794 break;
3795 } else
3796 dns_zone_log(zone, ISC_LOG_WARNING,
3797 "unsupported nsec3 hash algorithm: %u",
3798 nsec3param.hash);
3799 } else {
3800 ok = true;
3801 }
3802 }
3803 if (result == ISC_R_NOMORE) {
3804 result = ISC_R_SUCCESS;
3805 }
3806
3807 if (!ok) {
3808 result = DNS_R_BADZONE;
3809 dns_zone_log(zone, ISC_LOG_ERROR,
3810 "no supported nsec3 hash algorithm");
3811 }
3812
3813 cleanup:
3814 if (dns_rdataset_isassociated(&rdataset)) {
3815 dns_rdataset_disassociate(&rdataset);
3816 }
3817 dns_db_closeversion(db, &version, false);
3818 dns_db_detachnode(db, &node);
3819 return (result);
3820 }
3821
3822 /*
3823 * Set the timer for refreshing the key zone to the soonest future time
3824 * of the set (current timer, keydata->refresh, keydata->addhd,
3825 * keydata->removehd).
3826 */
3827 static void
3828 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3829 isc_stdtime_t now, bool force)
3830 {
3831 const char me[] = "set_refreshkeytimer";
3832 isc_stdtime_t then;
3833 isc_time_t timenow, timethen;
3834 char timebuf[80];
3835
3836 ENTER;
3837 then = key->refresh;
3838 if (force)
3839 then = now;
3840 if (key->addhd > now && key->addhd < then)
3841 then = key->addhd;
3842 if (key->removehd > now && key->removehd < then)
3843 then = key->removehd;
3844
3845 TIME_NOW(&timenow);
3846 if (then > now)
3847 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3848 else
3849 timethen = timenow;
3850 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3851 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3852 zone->refreshkeytime = timethen;
3853
3854 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3855 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3856 zone_settimer(zone, &timenow);
3857 }
3858
3859 /*
3860 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3861 * If the key zone is changed, set '*changed' to true.
3862 */
3863 static isc_result_t
3864 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3865 dns_diff_t *diff, dns_keytable_t *keytable,
3866 dns_keynode_t **keynodep, bool *changed)
3867 {
3868 const char me[] = "create_keydata";
3869 isc_result_t result = ISC_R_SUCCESS;
3870 isc_buffer_t keyb, dstb;
3871 unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3872 dns_rdata_keydata_t keydata;
3873 dns_rdata_dnskey_t dnskey;
3874 dns_rdata_t rdata = DNS_RDATA_INIT;
3875 dns_keynode_t *keynode;
3876 isc_stdtime_t now;
3877 isc_region_t r;
3878 dst_key_t *key;
3879
3880 REQUIRE(keynodep != NULL);
3881 keynode = *keynodep;
3882
3883 ENTER;
3884 isc_stdtime_get(&now);
3885
3886 /* Loop in case there's more than one key. */
3887 while (result == ISC_R_SUCCESS) {
3888 dns_keynode_t *nextnode = NULL;
3889
3890 key = dns_keynode_key(keynode);
3891 if (key == NULL)
3892 goto skip;
3893
3894 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3895 CHECK(dst_key_todns(key, &dstb));
3896
3897 /* Convert DST key to DNSKEY. */
3898 dns_rdata_reset(&rdata);
3899 isc_buffer_usedregion(&dstb, &r);
3900 dns_rdata_fromregion(&rdata, dst_key_class(key),
3901 dns_rdatatype_dnskey, &r);
3902
3903 /* DSTKEY to KEYDATA. */
3904 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3905 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3906 NULL));
3907
3908 /* KEYDATA to rdata. */
3909 dns_rdata_reset(&rdata);
3910 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3911 CHECK(dns_rdata_fromstruct(&rdata,
3912 zone->rdclass, dns_rdatatype_keydata,
3913 &keydata, &keyb));
3914
3915 /* Add rdata to zone. */
3916 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3917 dst_key_name(key), 0, &rdata));
3918 *changed = true;
3919
3920 /* Refresh new keys from the zone apex as soon as possible. */
3921 set_refreshkeytimer(zone, &keydata, now, true);
3922
3923 skip:
3924 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3925 if (result != ISC_R_NOTFOUND) {
3926 dns_keytable_detachkeynode(keytable, &keynode);
3927 keynode = nextnode;
3928 }
3929 }
3930
3931 if (keynode != NULL)
3932 dns_keytable_detachkeynode(keytable, &keynode);
3933 *keynodep = NULL;
3934
3935 return (ISC_R_SUCCESS);
3936
3937 failure:
3938 return (result);
3939 }
3940
3941 /*
3942 * Remove from the key zone all the KEYDATA records found in rdataset.
3943 */
3944 static isc_result_t
3945 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3946 dns_name_t *name, dns_rdataset_t *rdataset)
3947 {
3948 dns_rdata_t rdata = DNS_RDATA_INIT;
3949 isc_result_t result, uresult;
3950
3951 for (result = dns_rdataset_first(rdataset);
3952 result == ISC_R_SUCCESS;
3953 result = dns_rdataset_next(rdataset)) {
3954 dns_rdata_reset(&rdata);
3955 dns_rdataset_current(rdataset, &rdata);
3956 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3957 name, 0, &rdata);
3958 if (uresult != ISC_R_SUCCESS)
3959 return (uresult);
3960 }
3961 if (result == ISC_R_NOMORE)
3962 result = ISC_R_SUCCESS;
3963 return (result);
3964 }
3965
3966 /*
3967 * Compute the DNSSEC key ID for a DNSKEY record.
3968 */
3969 static isc_result_t
3970 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3971 dns_keytag_t *tag)
3972 {
3973 isc_result_t result;
3974 dns_rdata_t rdata = DNS_RDATA_INIT;
3975 unsigned char data[4096];
3976 isc_buffer_t buffer;
3977 dst_key_t *dstkey = NULL;
3978
3979 isc_buffer_init(&buffer, data, sizeof(data));
3980 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3981 dns_rdatatype_dnskey, dnskey, &buffer);
3982
3983 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3984 if (result == ISC_R_SUCCESS) {
3985 *tag = dst_key_id(dstkey);
3986 dst_key_free(&dstkey);
3987 }
3988
3989 return (result);
3990 }
3991
3992 /*
3993 * Add key to the security roots.
3994 */
3995 static void
3996 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3997 dns_rdata_dnskey_t *dnskey, bool initial,
3998 isc_mem_t *mctx)
3999 {
4000 isc_result_t result;
4001 dns_rdata_t rdata = DNS_RDATA_INIT;
4002 unsigned char data[4096];
4003 isc_buffer_t buffer;
4004 dns_keytable_t *sr = NULL;
4005 dst_key_t *dstkey = NULL;
4006
4007 /* Convert dnskey to DST key. */
4008 isc_buffer_init(&buffer, data, sizeof(data));
4009 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
4010 dns_rdatatype_dnskey, dnskey, &buffer);
4011
4012 result = dns_view_getsecroots(zone->view, &sr);
4013 if (result != ISC_R_SUCCESS)
4014 goto failure;
4015
4016 CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
4017 CHECK(dns_keytable_add(sr, true, initial, &dstkey));
4018 dns_keytable_detach(&sr);
4019
4020 failure:
4021 if (dstkey != NULL)
4022 dst_key_free(&dstkey);
4023 if (sr != NULL)
4024 dns_keytable_detach(&sr);
4025 return;
4026 }
4027
4028 /*
4029 * Add a null key to the security roots for so that all queries
4030 * to the zone will fail.
4031 */
4032 static void
4033 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
4034 isc_result_t result;
4035 dns_keytable_t *sr = NULL;
4036
4037 result = dns_view_getsecroots(zone->view, &sr);
4038 if (result == ISC_R_SUCCESS) {
4039 dns_keytable_marksecure(sr, keyname);
4040 dns_keytable_detach(&sr);
4041 }
4042 }
4043
4044 /*
4045 * Scan a set of KEYDATA records from the key zone. The ones that are
4046 * valid (i.e., the add holddown timer has expired) become trusted keys.
4047 */
4048 static void
4049 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
4050 isc_result_t result;
4051 dns_rdata_t rdata = DNS_RDATA_INIT;
4052 dns_rdata_keydata_t keydata;
4053 dns_rdata_dnskey_t dnskey;
4054 isc_mem_t *mctx = zone->mctx;
4055 int trusted = 0, revoked = 0, pending = 0;
4056 isc_stdtime_t now;
4057 dns_keytable_t *sr = NULL;
4058
4059 isc_stdtime_get(&now);
4060
4061 result = dns_view_getsecroots(zone->view, &sr);
4062 if (result == ISC_R_SUCCESS) {
4063 dns_keytable_delete(sr, name);
4064 dns_keytable_detach(&sr);
4065 }
4066
4067 /* Now insert all the accepted trust anchors from this keydata set. */
4068 for (result = dns_rdataset_first(rdataset);
4069 result == ISC_R_SUCCESS;
4070 result = dns_rdataset_next(rdataset))
4071 {
4072 dns_rdata_reset(&rdata);
4073 dns_rdataset_current(rdataset, &rdata);
4074
4075 /* Convert rdata to keydata. */
4076 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
4077 if (result == ISC_R_UNEXPECTEDEND) {
4078 continue;
4079 }
4080 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4081
4082 /* Set the key refresh timer to force a fast refresh. */
4083 set_refreshkeytimer(zone, &keydata, now, true);
4084
4085 /* If the removal timer is nonzero, this key was revoked. */
4086 if (keydata.removehd != 0) {
4087 revoked++;
4088 continue;
4089 }
4090
4091 /*
4092 * If the add timer is still pending, this key is not
4093 * trusted yet.
4094 */
4095 if (now < keydata.addhd) {
4096 pending++;
4097 continue;
4098 }
4099
4100 /* Convert keydata to dnskey. */
4101 dns_keydata_todnskey(&keydata, &dnskey, NULL);
4102
4103 /* Add to keytables. */
4104 trusted++;
4105 trust_key(zone, name, &dnskey, (keydata.addhd == 0), mctx);
4106 }
4107
4108 if (trusted == 0 && pending != 0) {
4109 char namebuf[DNS_NAME_FORMATSIZE];
4110 dns_name_format(name, namebuf, sizeof namebuf);
4111 dnssec_log(zone, ISC_LOG_ERROR,
4112 "No valid trust anchors for '%s'!", namebuf);
4113 dnssec_log(zone, ISC_LOG_ERROR,
4114 "%d key(s) revoked, %d still pending",
4115 revoked, pending);
4116 dnssec_log(zone, ISC_LOG_ERROR,
4117 "All queries to '%s' will fail", namebuf);
4118 fail_secure(zone, name);
4119 }
4120 }
4121
4122 static isc_result_t
4123 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4124 dns_diff_t *diff)
4125 {
4126 dns_diff_t temp_diff;
4127 isc_result_t result;
4128
4129 /*
4130 * Create a singleton diff.
4131 */
4132 dns_diff_init(diff->mctx, &temp_diff);
4133 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4134
4135 /*
4136 * Apply it to the database.
4137 */
4138 result = dns_diff_apply(&temp_diff, db, ver);
4139 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4140 if (result != ISC_R_SUCCESS) {
4141 dns_difftuple_free(tuple);
4142 return (result);
4143 }
4144
4145 /*
4146 * Merge it into the current pending journal entry.
4147 */
4148 dns_diff_appendminimal(diff, tuple);
4149
4150 /*
4151 * Do not clear temp_diff.
4152 */
4153 return (ISC_R_SUCCESS);
4154 }
4155
4156 static isc_result_t
4157 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4158 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4159 dns_rdata_t *rdata)
4160 {
4161 dns_difftuple_t *tuple = NULL;
4162 isc_result_t result;
4163 result = dns_difftuple_create(diff->mctx, op,
4164 name, ttl, rdata, &tuple);
4165 if (result != ISC_R_SUCCESS)
4166 return (result);
4167 return (do_one_tuple(&tuple, db, ver, diff));
4168 }
4169
4170 static isc_result_t
4171 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4172 isc_mem_t *mctx, dns_updatemethod_t method) {
4173 dns_difftuple_t *deltuple = NULL;
4174 dns_difftuple_t *addtuple = NULL;
4175 uint32_t serial;
4176 isc_result_t result;
4177
4178 INSIST(method != dns_updatemethod_none);
4179
4180 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4181 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4182 addtuple->op = DNS_DIFFOP_ADD;
4183
4184 serial = dns_soa_getserial(&addtuple->rdata);
4185 serial = dns_update_soaserial(serial, method);
4186 dns_soa_setserial(serial, &addtuple->rdata);
4187 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4188 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4189 result = ISC_R_SUCCESS;
4190
4191 failure:
4192 if (addtuple != NULL)
4193 dns_difftuple_free(&addtuple);
4194 if (deltuple != NULL)
4195 dns_difftuple_free(&deltuple);
4196 return (result);
4197 }
4198
4199 /*
4200 * Write all transactions in 'diff' to the zone journal file.
4201 */
4202 static isc_result_t
4203 zone_journal(dns_zone_t *zone, dns_diff_t *diff, uint32_t *sourceserial,
4204 const char *caller)
4205 {
4206 const char me[] = "zone_journal";
4207 const char *journalfile;
4208 isc_result_t result = ISC_R_SUCCESS;
4209 dns_journal_t *journal = NULL;
4210 unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
4211
4212 ENTER;
4213 journalfile = dns_zone_getjournal(zone);
4214 if (journalfile != NULL) {
4215 result = dns_journal_open(zone->mctx, journalfile, mode,
4216 &journal);
4217 if (result != ISC_R_SUCCESS) {
4218 dns_zone_log(zone, ISC_LOG_ERROR,
4219 "%s:dns_journal_open -> %s",
4220 caller, dns_result_totext(result));
4221 return (result);
4222 }
4223
4224 if (sourceserial != NULL)
4225 dns_journal_set_sourceserial(journal, *sourceserial);
4226
4227 result = dns_journal_write_transaction(journal, diff);
4228 if (result != ISC_R_SUCCESS) {
4229 dns_zone_log(zone, ISC_LOG_ERROR,
4230 "%s:dns_journal_write_transaction -> %s",
4231 caller, dns_result_totext(result));
4232 }
4233 dns_journal_destroy(&journal);
4234 }
4235
4236 return (result);
4237 }
4238
4239 /*
4240 * Create an SOA record for a newly-created zone
4241 */
4242 static isc_result_t
4243 add_soa(dns_zone_t *zone, dns_db_t *db) {
4244 isc_result_t result;
4245 dns_rdata_t rdata = DNS_RDATA_INIT;
4246 unsigned char buf[DNS_SOA_BUFFERSIZE];
4247 dns_dbversion_t *ver = NULL;
4248 dns_diff_t diff;
4249
4250 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4251
4252 dns_diff_init(zone->mctx, &diff);
4253 result = dns_db_newversion(db, &ver);
4254 if (result != ISC_R_SUCCESS) {
4255 dns_zone_log(zone, ISC_LOG_ERROR,
4256 "add_soa:dns_db_newversion -> %s",
4257 dns_result_totext(result));
4258 goto failure;
4259 }
4260
4261 /* Build SOA record */
4262 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4263 0, 0, 0, 0, 0, buf, &rdata);
4264 if (result != ISC_R_SUCCESS) {
4265 dns_zone_log(zone, ISC_LOG_ERROR,
4266 "add_soa:dns_soa_buildrdata -> %s",
4267 dns_result_totext(result));
4268 goto failure;
4269 }
4270
4271 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
4272 &zone->origin, 0, &rdata);
4273
4274 failure:
4275 dns_diff_clear(&diff);
4276 if (ver != NULL)
4277 dns_db_closeversion(db, &ver, (result == ISC_R_SUCCESS));
4278
4279 INSIST(ver == NULL);
4280
4281 return (result);
4282 }
4283
4284 struct addifmissing_arg {
4285 dns_db_t *db;
4286 dns_dbversion_t *ver;
4287 dns_diff_t *diff;
4288 dns_zone_t *zone;
4289 bool *changed;
4290 isc_result_t result;
4291 };
4292
4293 static void
4294 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
4295 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4296 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4297 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4298 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4299 bool *changed = ((struct addifmissing_arg *)arg)->changed;
4300 isc_result_t result;
4301 dns_keynode_t *dummy = NULL;
4302
4303 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS)
4304 return;
4305
4306 if (dns_keynode_managed(keynode)) {
4307 dns_fixedname_t fname;
4308 dns_name_t *keyname;
4309 dst_key_t *key;
4310
4311 key = dns_keynode_key(keynode);
4312 if (key == NULL)
4313 return;
4314 dns_fixedname_init(&fname);
4315
4316 keyname = dst_key_name(key);
4317 result = dns_db_find(db, keyname, ver,
4318 dns_rdatatype_keydata,
4319 DNS_DBFIND_NOWILD, 0, NULL,
4320 dns_fixedname_name(&fname),
4321 NULL, NULL);
4322 if (result == ISC_R_SUCCESS)
4323 return;
4324 dns_keytable_attachkeynode(keytable, keynode, &dummy);
4325 result = create_keydata(zone, db, ver, diff, keytable,
4326 &dummy, changed);
4327 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
4328 ((struct addifmissing_arg *)arg)->result = result;
4329 }
4330 };
4331
4332 /*
4333 * Synchronize the set of initializing keys found in managed-keys {}
4334 * statements with the set of trust anchors found in the managed-keys.bind
4335 * zone. If a domain is no longer named in managed-keys, delete all keys
4336 * from that domain from the key zone. If a domain is mentioned in in
4337 * managed-keys but there are no references to it in the key zone, load
4338 * the key zone with the initializing key(s) for that domain.
4339 */
4340 static isc_result_t
4341 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4342 isc_result_t result = ISC_R_SUCCESS;
4343 bool changed = false;
4344 bool commit = false;
4345 dns_keynode_t *keynode = NULL;
4346 dns_view_t *view = zone->view;
4347 dns_keytable_t *sr = NULL;
4348 dns_dbversion_t *ver = NULL;
4349 dns_diff_t diff;
4350 dns_rriterator_t rrit;
4351 struct addifmissing_arg arg;
4352
4353 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4354
4355 dns_diff_init(zone->mctx, &diff);
4356
4357 CHECK(dns_view_getsecroots(view, &sr));
4358
4359 result = dns_db_newversion(db, &ver);
4360 if (result != ISC_R_SUCCESS) {
4361 dnssec_log(zone, ISC_LOG_ERROR,
4362 "sync_keyzone:dns_db_newversion -> %s",
4363 dns_result_totext(result));
4364 goto failure;
4365 }
4366
4367 /*
4368 * Walk the zone DB. If we find any keys whose names are no longer
4369 * in managed-keys (or *are* in trusted-keys, meaning they are
4370 * permanent and not RFC5011-maintained), delete them from the
4371 * zone. Otherwise call load_secroots(), which loads keys into
4372 * secroots as appropriate.
4373 */
4374 dns_rriterator_init(&rrit, db, ver, 0);
4375 for (result = dns_rriterator_first(&rrit);
4376 result == ISC_R_SUCCESS;
4377 result = dns_rriterator_nextrrset(&rrit))
4378 {
4379 dns_rdataset_t *rdataset = NULL;
4380 dns_name_t *rrname = NULL;
4381 uint32_t ttl;
4382
4383 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4384 if (!dns_rdataset_isassociated(rdataset)) {
4385 dns_rriterator_destroy(&rrit);
4386 goto failure;
4387 }
4388
4389 if (rdataset->type != dns_rdatatype_keydata) {
4390 continue;
4391 }
4392
4393 result = dns_keytable_find(sr, rrname, &keynode);
4394 if ((result != ISC_R_SUCCESS &&
4395 result != DNS_R_PARTIALMATCH) ||
4396 dns_keynode_managed(keynode) == false)
4397 {
4398 CHECK(delete_keydata(db, ver, &diff,
4399 rrname, rdataset));
4400 changed = true;
4401 } else {
4402 load_secroots(zone, rrname, rdataset);
4403 }
4404
4405 if (keynode != NULL) {
4406 dns_keytable_detachkeynode(sr, &keynode);
4407 }
4408 }
4409 dns_rriterator_destroy(&rrit);
4410
4411 /*
4412 * Now walk secroots to find any managed keys that aren't
4413 * in the zone. If we find any, we add them to the zone.
4414 */
4415 arg.db = db;
4416 arg.ver = ver;
4417 arg.result = ISC_R_SUCCESS;
4418 arg.diff = &diff;
4419 arg.zone = zone;
4420 arg.changed = &changed;
4421 dns_keytable_forall(sr, addifmissing, &arg);
4422 result = arg.result;
4423 if (changed) {
4424 /* Write changes to journal file. */
4425 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
4426 zone->updatemethod));
4427 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4428
4429 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4430 zone_needdump(zone, 30);
4431 commit = true;
4432 }
4433
4434 failure:
4435 if (result != ISC_R_SUCCESS &&
4436 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4437 {
4438 dnssec_log(zone, ISC_LOG_ERROR,
4439 "unable to synchronize managed keys: %s",
4440 dns_result_totext(result));
4441 isc_time_settoepoch(&zone->refreshkeytime);
4442 }
4443 if (keynode != NULL) {
4444 dns_keytable_detachkeynode(sr, &keynode);
4445 }
4446 if (sr != NULL) {
4447 dns_keytable_detach(&sr);
4448 }
4449 if (ver != NULL) {
4450 dns_db_closeversion(db, &ver, commit);
4451 }
4452 dns_diff_clear(&diff);
4453
4454 INSIST(ver == NULL);
4455
4456 return (result);
4457 }
4458
4459 isc_result_t
4460 dns_zone_synckeyzone(dns_zone_t *zone) {
4461 isc_result_t result;
4462 dns_db_t *db = NULL;
4463
4464 if (zone->type != dns_zone_key) {
4465 return (DNS_R_BADZONE);
4466 }
4467
4468 CHECK(dns_zone_getdb(zone, &db));
4469
4470 LOCK_ZONE(zone);
4471 result = sync_keyzone(zone, db);
4472 UNLOCK_ZONE(zone);
4473
4474 failure:
4475 if (db != NULL) {
4476 dns_db_detach(&db);
4477 }
4478 return (result);
4479 }
4480
4481 static void
4482 maybe_send_secure(dns_zone_t *zone) {
4483 isc_result_t result;
4484
4485 /*
4486 * We've finished loading, or else failed to load, an inline-signing
4487 * 'secure' zone. We now need information about the status of the
4488 * 'raw' zone. If we failed to load, then we need it to send a
4489 * copy of its database; if we succeeded, we need it to send its
4490 * serial number so that we can sync with it. If it has not yet
4491 * loaded, we set a flag so that it will send the necessary
4492 * information when it has finished loading.
4493 */
4494 if (zone->raw->db != NULL) {
4495 if (zone->db != NULL) {
4496 uint32_t serial;
4497 unsigned int soacount;
4498
4499 result = zone_get_from_db(zone->raw, zone->raw->db,
4500 NULL, &soacount, &serial,
4501 NULL, NULL, NULL, NULL, NULL);
4502 if (result == ISC_R_SUCCESS && soacount > 0U)
4503 zone_send_secureserial(zone->raw, serial);
4504 } else
4505 zone_send_securedb(zone->raw, zone->raw->db);
4506
4507 } else
4508 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4509 }
4510
4511 static bool
4512 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4513 isc_result_t result;
4514 bool answer = false;
4515 dns_diff_t diff;
4516
4517 dns_diff_init(mctx, &diff);
4518 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4519 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
4520 answer = true;
4521 dns_diff_clear(&diff);
4522 return (answer);
4523 }
4524
4525 /*
4526 * The zone is presumed to be locked.
4527 * If this is a inline_raw zone the secure version is also locked.
4528 */
4529 static isc_result_t
4530 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4531 isc_result_t result)
4532 {
4533 unsigned int soacount = 0;
4534 unsigned int nscount = 0;
4535 unsigned int errors = 0;
4536 uint32_t serial, oldserial, refresh, retry, expire, minimum;
4537 isc_time_t now;
4538 bool needdump = false;
4539 bool hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4540 bool nomaster = false;
4541 bool had_db = false;
4542 unsigned int options;
4543 dns_include_t *inc;
4544
4545 INSIST(LOCKED_ZONE(zone));
4546 if (inline_raw(zone)) {
4547 INSIST(LOCKED_ZONE(zone->secure));
4548 }
4549
4550 TIME_NOW(&now);
4551
4552 /*
4553 * Initiate zone transfer? We may need a error code that
4554 * indicates that the "permanent" form does not exist.
4555 * XXX better error feedback to log.
4556 */
4557 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4558 if (zone->type == dns_zone_slave ||
4559 zone->type == dns_zone_mirror ||
4560 zone->type == dns_zone_stub ||
4561 (zone->type == dns_zone_redirect &&
4562 zone->masters == NULL))
4563 {
4564 if (result == ISC_R_FILENOTFOUND) {
4565 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4566 ISC_LOG_DEBUG(1),
4567 "no master file");
4568 } else if (result != DNS_R_NOMASTERFILE) {
4569 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4570 ISC_LOG_ERROR,
4571 "loading from master file %s "
4572 "failed: %s",
4573 zone->masterfile,
4574 dns_result_totext(result));
4575 }
4576 } else if (zone->type == dns_zone_master &&
4577 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4578 {
4579 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4580 ISC_LOG_DEBUG(1),
4581 "no master file, requesting db");
4582 maybe_send_secure(zone);
4583 } else {
4584 int level = ISC_LOG_ERROR;
4585 if (zone->type == dns_zone_key &&
4586 result == ISC_R_FILENOTFOUND)
4587 level = ISC_LOG_DEBUG(1);
4588 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4589 "loading from master file %s failed: %s",
4590 zone->masterfile,
4591 dns_result_totext(result));
4592 nomaster = true;
4593 }
4594
4595 if (zone->type != dns_zone_key) {
4596 goto cleanup;
4597 }
4598 }
4599
4600 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4601 "number of nodes in database: %u",
4602 dns_db_nodecount(db));
4603
4604 if (result == DNS_R_SEENINCLUDE) {
4605 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4606 } else {
4607 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4608 }
4609
4610 /*
4611 * If there's no master file for a key zone, then the zone is new:
4612 * create an SOA record. (We do this now, instead of later, so that
4613 * if there happens to be a journal file, we can roll forward from
4614 * a sane starting point.)
4615 */
4616 if (nomaster && zone->type == dns_zone_key) {
4617 result = add_soa(zone, db);
4618 if (result != ISC_R_SUCCESS) {
4619 goto cleanup;
4620 }
4621 }
4622
4623 /*
4624 * Apply update log, if any, on initial load.
4625 */
4626 if (zone->journal != NULL &&
4627 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4628 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4629 {
4630 if (zone->type == dns_zone_master && (inline_secure(zone) ||
4631 (zone->update_acl != NULL || zone->ssutable != NULL)))
4632 {
4633 options = DNS_JOURNALOPT_RESIGN;
4634 } else {
4635 options = 0;
4636 }
4637 result = dns_journal_rollforward(zone->mctx, db, options,
4638 zone->journal);
4639 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4640 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4641 result != ISC_R_RANGE)
4642 {
4643 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4644 ISC_LOG_ERROR,
4645 "journal rollforward failed: %s",
4646 dns_result_totext(result));
4647 goto cleanup;
4648
4649
4650 }
4651 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4652 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4653 ISC_LOG_ERROR,
4654 "journal rollforward failed: "
4655 "journal out of sync with zone");
4656 goto cleanup;
4657 }
4658 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4659 "journal rollforward completed "
4660 "successfully: %s",
4661 dns_result_totext(result));
4662 if (result == ISC_R_SUCCESS) {
4663 needdump = true;
4664 }
4665 }
4666
4667 /*
4668 * Obtain ns, soa and cname counts for top of zone.
4669 */
4670 INSIST(db != NULL);
4671 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4672 &refresh, &retry, &expire, &minimum,
4673 &errors);
4674 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4675 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4676 "could not find NS and/or SOA records");
4677 }
4678
4679 /*
4680 * Check to make sure the journal is up to date, and remove the
4681 * journal file if it isn't, as we wouldn't be able to apply
4682 * updates otherwise.
4683 */
4684 if (zone->journal != NULL && dns_zone_isdynamic(zone, true) &&
4685 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS))
4686 {
4687 uint32_t jserial;
4688 dns_journal_t *journal = NULL;
4689 bool empty = false;
4690
4691 result = dns_journal_open(zone->mctx, zone->journal,
4692 DNS_JOURNAL_READ, &journal);
4693 if (result == ISC_R_SUCCESS) {
4694 jserial = dns_journal_last_serial(journal);
4695 empty = dns_journal_empty(journal);
4696 dns_journal_destroy(&journal);
4697 } else {
4698 jserial = serial;
4699 result = ISC_R_SUCCESS;
4700 }
4701
4702 if (jserial != serial) {
4703 if (!empty) {
4704 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4705 ISC_LOG_INFO,
4706 "journal file is out of date: "
4707 "removing journal file");
4708 }
4709 if (remove(zone->journal) < 0 && errno != ENOENT) {
4710 char strbuf[ISC_STRERRORSIZE];
4711 strerror_r(errno, strbuf, sizeof(strbuf));
4712 isc_log_write(dns_lctx,
4713 DNS_LOGCATEGORY_GENERAL,
4714 DNS_LOGMODULE_ZONE,
4715 ISC_LOG_WARNING,
4716 "unable to remove journal "
4717 "'%s': '%s'",
4718 zone->journal, strbuf);
4719 }
4720 }
4721 }
4722
4723 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4724 "loaded; checking validity");
4725
4726 /*
4727 * Master / Slave / Mirror / Stub zones require both NS and SOA records
4728 * at the top of the zone.
4729 */
4730
4731 switch (zone->type) {
4732 case dns_zone_dlz:
4733 case dns_zone_master:
4734 case dns_zone_slave:
4735 case dns_zone_mirror:
4736 case dns_zone_stub:
4737 case dns_zone_redirect:
4738 if (soacount != 1) {
4739 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4740 ISC_LOG_ERROR,
4741 "has %d SOA records", soacount);
4742 result = DNS_R_BADZONE;
4743 }
4744 if (nscount == 0) {
4745 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4746 ISC_LOG_ERROR,
4747 "has no NS records");
4748 result = DNS_R_BADZONE;
4749 }
4750 if (result != ISC_R_SUCCESS) {
4751 goto cleanup;
4752 }
4753 if (zone->type == dns_zone_master && errors != 0) {
4754 result = DNS_R_BADZONE;
4755 goto cleanup;
4756 }
4757 if (zone->type != dns_zone_stub &&
4758 zone->type != dns_zone_redirect)
4759 {
4760 result = check_nsec3param(zone, db);
4761 if (result != ISC_R_SUCCESS)
4762 goto cleanup;
4763 }
4764 if (zone->type == dns_zone_master &&
4765 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4766 !integrity_checks(zone, db))
4767 {
4768 result = DNS_R_BADZONE;
4769 goto cleanup;
4770 }
4771 if (zone->type == dns_zone_master &&
4772 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4773 !zone_check_dup(zone, db))
4774 {
4775 result = DNS_R_BADZONE;
4776 goto cleanup;
4777 }
4778
4779 if (zone->type == dns_zone_master) {
4780 result = dns_zone_cdscheck(zone, db, NULL);
4781 if (result != ISC_R_SUCCESS) {
4782 dns_zone_log(zone, ISC_LOG_ERROR,
4783 "CDS/CDNSKEY consistency checks "
4784 "failed");
4785 goto cleanup;
4786 }
4787 }
4788
4789 result = dns_zone_verifydb(zone, db, NULL);
4790 if (result != ISC_R_SUCCESS) {
4791 goto cleanup;
4792 }
4793
4794 if (zone->db != NULL) {
4795 unsigned int oldsoacount;
4796
4797 /*
4798 * This is checked in zone_replacedb() for slave zones
4799 * as they don't reload from disk.
4800 */
4801 result = zone_get_from_db(zone, zone->db, NULL,
4802 &oldsoacount, &oldserial,
4803 NULL, NULL, NULL, NULL,
4804 NULL);
4805 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4806 RUNTIME_CHECK(soacount > 0U);
4807 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4808 !isc_serial_gt(serial, oldserial)) {
4809 uint32_t serialmin, serialmax;
4810
4811 INSIST(zone->type == dns_zone_master);
4812 INSIST(zone->raw == NULL);
4813
4814 if (serial == oldserial &&
4815 zone_unchanged(zone->db, db, zone->mctx)) {
4816 dns_zone_logc(zone,
4817 DNS_LOGCATEGORY_ZONELOAD,
4818 ISC_LOG_INFO,
4819 "ixfr-from-differences: "
4820 "unchanged");
4821 goto done;
4822 }
4823
4824 serialmin = (oldserial + 1) & 0xffffffffU;
4825 serialmax = (oldserial + 0x7fffffffU) &
4826 0xffffffffU;
4827 dns_zone_logc(zone,
4828 DNS_LOGCATEGORY_ZONELOAD,
4829 ISC_LOG_ERROR,
4830 "ixfr-from-differences: "
4831 "new serial (%u) out of range "
4832 "[%u - %u]", serial, serialmin,
4833 serialmax);
4834 result = DNS_R_BADZONE;
4835 goto cleanup;
4836 } else if (!isc_serial_ge(serial, oldserial)) {
4837 dns_zone_logc(zone,
4838 DNS_LOGCATEGORY_ZONELOAD,
4839 ISC_LOG_ERROR,
4840 "zone serial (%u/%u) has gone "
4841 "backwards", serial, oldserial);
4842 } else if (serial == oldserial && !hasinclude &&
4843 strcmp(zone->db_argv[0], "_builtin") != 0)
4844 {
4845 dns_zone_logc(zone,
4846 DNS_LOGCATEGORY_ZONELOAD,
4847 ISC_LOG_ERROR,
4848 "zone serial (%u) unchanged. "
4849 "zone may fail to transfer "
4850 "to slaves.", serial);
4851 }
4852 }
4853
4854 if (zone->type == dns_zone_master &&
4855 (zone->update_acl != NULL || zone->ssutable != NULL) &&
4856 zone->sigresigninginterval < (3 * refresh) &&
4857 dns_db_issecure(db))
4858 {
4859 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4860 ISC_LOG_WARNING,
4861 "sig-re-signing-interval less than "
4862 "3 * refresh.");
4863 }
4864
4865 zone->refresh = RANGE(refresh,
4866 zone->minrefresh, zone->maxrefresh);
4867 zone->retry = RANGE(retry,
4868 zone->minretry, zone->maxretry);
4869 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4870 DNS_MAX_EXPIRE);
4871 zone->minimum = minimum;
4872 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4873
4874 if (zone->type == dns_zone_slave ||
4875 zone->type == dns_zone_mirror ||
4876 zone->type == dns_zone_stub ||
4877 (zone->type == dns_zone_redirect &&
4878 zone->masters != NULL))
4879 {
4880 isc_time_t t;
4881 uint32_t delay;
4882
4883 result = isc_file_getmodtime(zone->journal, &t);
4884 if (result != ISC_R_SUCCESS) {
4885 result = isc_file_getmodtime(zone->masterfile,
4886 &t);
4887 }
4888 if (result == ISC_R_SUCCESS) {
4889 DNS_ZONE_TIME_ADD(&t, zone->expire,
4890 &zone->expiretime);
4891 } else {
4892 DNS_ZONE_TIME_ADD(&now, zone->retry,
4893 &zone->expiretime);
4894 }
4895
4896 delay = (zone->retry -
4897 isc_random_uniform((zone->retry * 3) / 4));
4898 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4899 if (isc_time_compare(&zone->refreshtime,
4900 &zone->expiretime) >= 0)
4901 {
4902 zone->refreshtime = now;
4903 }
4904 }
4905
4906 break;
4907
4908 case dns_zone_key:
4909 result = sync_keyzone(zone, db);
4910 if (result != ISC_R_SUCCESS) {
4911 goto cleanup;
4912 }
4913 break;
4914
4915 default:
4916 UNEXPECTED_ERROR(__FILE__, __LINE__,
4917 "unexpected zone type %d", zone->type);
4918 result = ISC_R_UNEXPECTED;
4919 goto cleanup;
4920 }
4921
4922 /*
4923 * Check for weak DNSKEY's.
4924 */
4925 if (zone->type == dns_zone_master) {
4926 zone_check_dnskeys(zone, db);
4927 }
4928
4929 /*
4930 * Schedule DNSSEC key refresh.
4931 */
4932 if (zone->type == dns_zone_master &&
4933 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4934 {
4935 zone->refreshkeytime = now;
4936 }
4937
4938 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4939 if (zone->db != NULL) {
4940 had_db = true;
4941 result = zone_replacedb(zone, db, false);
4942 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4943 if (result != ISC_R_SUCCESS) {
4944 goto cleanup;
4945 }
4946 } else {
4947 zone_attachdb(zone, db);
4948 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4949 DNS_ZONE_SETFLAG(zone,
4950 DNS_ZONEFLG_LOADED|
4951 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
4952 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4953 inline_raw(zone))
4954 {
4955 if (zone->secure->db == NULL) {
4956 zone_send_securedb(zone, db);
4957 } else {
4958 zone_send_secureserial(zone, serial);
4959 }
4960 }
4961 }
4962
4963 /*
4964 * Finished loading inline-signing zone; need to get status
4965 * from the raw side now.
4966 */
4967 if (zone->type == dns_zone_master && inline_secure(zone)) {
4968 maybe_send_secure(zone);
4969 }
4970
4971 result = ISC_R_SUCCESS;
4972
4973 if (needdump) {
4974 if (zone->type == dns_zone_key) {
4975 zone_needdump(zone, 30);
4976 } else {
4977 zone_needdump(zone, DNS_DUMP_DELAY);
4978 }
4979 }
4980
4981 if (zone->task != NULL) {
4982 if (zone->type == dns_zone_master) {
4983 set_resigntime(zone);
4984 resume_signingwithkey(zone);
4985 resume_addnsec3chain(zone);
4986 }
4987
4988 if (zone->type == dns_zone_master &&
4989 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4990 dns_zone_isdynamic(zone, false) &&
4991 dns_db_issecure(db))
4992 {
4993 dns_name_t *name;
4994 dns_fixedname_t fixed;
4995 dns_rdataset_t next;
4996
4997 dns_rdataset_init(&next);
4998 name = dns_fixedname_initname(&fixed);
4999
5000 result = dns_db_getsigningtime(db, &next, name);
5001 if (result == ISC_R_SUCCESS) {
5002 isc_stdtime_t timenow;
5003 char namebuf[DNS_NAME_FORMATSIZE];
5004 char typebuf[DNS_RDATATYPE_FORMATSIZE];
5005
5006 isc_stdtime_get(&timenow);
5007 dns_name_format(name, namebuf, sizeof(namebuf));
5008 dns_rdatatype_format(next.covers,
5009 typebuf, sizeof(typebuf));
5010 dnssec_log(zone, ISC_LOG_DEBUG(3),
5011 "next resign: %s/%s "
5012 "in %d seconds", namebuf, typebuf,
5013 next.resign - timenow -
5014 zone->sigresigninginterval);
5015 dns_rdataset_disassociate(&next);
5016 } else {
5017 dnssec_log(zone, ISC_LOG_WARNING,
5018 "signed dynamic zone has no "
5019 "resign event scheduled");
5020 }
5021 }
5022
5023 zone_settimer(zone, &now);
5024 }
5025
5026 /*
5027 * Clear old include list.
5028 */
5029 for (inc = ISC_LIST_HEAD(zone->includes);
5030 inc != NULL;
5031 inc = ISC_LIST_HEAD(zone->includes))
5032 {
5033 ISC_LIST_UNLINK(zone->includes, inc, link);
5034 isc_mem_free(zone->mctx, inc->name);
5035 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5036 }
5037 zone->nincludes = 0;
5038
5039 /*
5040 * Transfer new include list.
5041 */
5042 for (inc = ISC_LIST_HEAD(zone->newincludes);
5043 inc != NULL;
5044 inc = ISC_LIST_HEAD(zone->newincludes))
5045 {
5046 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5047 ISC_LIST_APPEND(zone->includes, inc, link);
5048 zone->nincludes++;
5049 }
5050
5051 if (! dns_db_ispersistent(db)) {
5052 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5053 ISC_LOG_INFO, "loaded serial %u%s", serial,
5054 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
5055 }
5056
5057 if (!had_db && zone->type == dns_zone_mirror) {
5058 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
5059 "mirror zone is now in use");
5060 }
5061
5062 zone->loadtime = loadtime;
5063 goto done;
5064
5065 cleanup:
5066 if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
5067 dnssec_log(zone, ISC_LOG_ERROR,
5068 "failed to initialize managed-keys (%s): "
5069 "DNSSEC validation is at risk",
5070 isc_result_totext(result));
5071 }
5072
5073 for (inc = ISC_LIST_HEAD(zone->newincludes);
5074 inc != NULL;
5075 inc = ISC_LIST_HEAD(zone->newincludes))
5076 {
5077 ISC_LIST_UNLINK(zone->newincludes, inc, link);
5078 isc_mem_free(zone->mctx, inc->name);
5079 isc_mem_put(zone->mctx, inc, sizeof(*inc));
5080 }
5081 if (zone->type == dns_zone_slave ||
5082 zone->type == dns_zone_mirror ||
5083 zone->type == dns_zone_stub ||
5084 zone->type == dns_zone_key ||
5085 (zone->type == dns_zone_redirect && zone->masters != NULL))
5086 {
5087 if (result != ISC_R_NOMEMORY) {
5088 if (zone->journal != NULL) {
5089 zone_saveunique(zone, zone->journal,
5090 "jn-XXXXXXXX");
5091 }
5092 if (zone->masterfile != NULL) {
5093 zone_saveunique(zone, zone->masterfile,
5094 "db-XXXXXXXX");
5095 }
5096 }
5097
5098 /* Mark the zone for immediate refresh. */
5099 zone->refreshtime = now;
5100 if (zone->task != NULL) {
5101 zone_settimer(zone, &now);
5102 }
5103 result = ISC_R_SUCCESS;
5104 } else if (zone->type == dns_zone_master ||
5105 zone->type == dns_zone_redirect)
5106 {
5107 if (! (inline_secure(zone) && result == ISC_R_FILENOTFOUND)) {
5108 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
5109 ISC_LOG_ERROR,
5110 "not loaded due to errors.");
5111 } else if (zone->type == dns_zone_master) {
5112 result = ISC_R_SUCCESS;
5113 }
5114 }
5115
5116 done:
5117 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
5118 /*
5119 * If this is an inline-signed zone and we were called for the raw
5120 * zone, we need to clear DNS_ZONEFLG_LOADPENDING for the secure zone
5121 * as well, but only if this is a reload, not an initial zone load: in
5122 * the former case, zone_postload() will not be run for the secure
5123 * zone; in the latter case, it will be. Check which case we are
5124 * dealing with by consulting the DNS_ZONEFLG_LOADED flag for the
5125 * secure zone: if it is set, this must be a reload.
5126 */
5127 if (inline_raw(zone) &&
5128 DNS_ZONE_FLAG(zone->secure, DNS_ZONEFLG_LOADED))
5129 {
5130 DNS_ZONE_CLRFLAG(zone->secure, DNS_ZONEFLG_LOADPENDING);
5131 }
5132
5133 zone_debuglog(zone, "zone_postload", 99, "done");
5134
5135 return (result);
5136 }
5137
5138 static bool
5139 exit_check(dns_zone_t *zone) {
5140 REQUIRE(LOCKED_ZONE(zone));
5141
5142 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
5143 /*
5144 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
5145 */
5146 INSIST(isc_refcount_current(&zone->erefs) == 0);
5147 return (true);
5148 }
5149 return (false);
5150 }
5151
5152 static bool
5153 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
5154 dns_name_t *name, bool logit)
5155 {
5156 isc_result_t result;
5157 char namebuf[DNS_NAME_FORMATSIZE];
5158 char altbuf[DNS_NAME_FORMATSIZE];
5159 dns_fixedname_t fixed;
5160 dns_name_t *foundname;
5161 int level;
5162
5163 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
5164 return (true);
5165
5166 if (zone->type == dns_zone_master)
5167 level = ISC_LOG_ERROR;
5168 else
5169 level = ISC_LOG_WARNING;
5170
5171 foundname = dns_fixedname_initname(&fixed);
5172
5173 result = dns_db_find(db, name, version, dns_rdatatype_a,
5174 0, 0, NULL, foundname, NULL, NULL);
5175 if (result == ISC_R_SUCCESS)
5176 return (true);
5177
5178 if (result == DNS_R_NXRRSET) {
5179 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
5180 0, 0, NULL, foundname, NULL, NULL);
5181 if (result == ISC_R_SUCCESS)
5182 return (true);
5183 }
5184
5185 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5186 result == DNS_R_EMPTYNAME) {
5187 if (logit) {
5188 dns_name_format(name, namebuf, sizeof namebuf);
5189 dns_zone_log(zone, level, "NS '%s' has no address "
5190 "records (A or AAAA)", namebuf);
5191 }
5192 return (false);
5193 }
5194
5195 if (result == DNS_R_CNAME) {
5196 if (logit) {
5197 dns_name_format(name, namebuf, sizeof namebuf);
5198 dns_zone_log(zone, level, "NS '%s' is a CNAME "
5199 "(illegal)", namebuf);
5200 }
5201 return (false);
5202 }
5203
5204 if (result == DNS_R_DNAME) {
5205 if (logit) {
5206 dns_name_format(name, namebuf, sizeof namebuf);
5207 dns_name_format(foundname, altbuf, sizeof altbuf);
5208 dns_zone_log(zone, level, "NS '%s' is below a DNAME "
5209 "'%s' (illegal)", namebuf, altbuf);
5210 }
5211 return (false);
5212 }
5213
5214 return (true);
5215 }
5216
5217 static isc_result_t
5218 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5219 dns_dbversion_t *version, unsigned int *nscount,
5220 unsigned int *errors, bool logit)
5221 {
5222 isc_result_t result;
5223 unsigned int count = 0;
5224 unsigned int ecount = 0;
5225 dns_rdataset_t rdataset;
5226 dns_rdata_t rdata;
5227 dns_rdata_ns_t ns;
5228
5229 dns_rdataset_init(&rdataset);
5230 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5231 dns_rdatatype_none, 0, &rdataset, NULL);
5232 if (result == ISC_R_NOTFOUND) {
5233 INSIST(!dns_rdataset_isassociated(&rdataset));
5234 goto success;
5235 }
5236 if (result != ISC_R_SUCCESS) {
5237 INSIST(!dns_rdataset_isassociated(&rdataset));
5238 goto invalidate_rdataset;
5239 }
5240
5241 result = dns_rdataset_first(&rdataset);
5242 while (result == ISC_R_SUCCESS) {
5243 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5244 (zone->type == dns_zone_master ||
5245 zone->type == dns_zone_slave ||
5246 zone->type == dns_zone_mirror))
5247 {
5248 dns_rdata_init(&rdata);
5249 dns_rdataset_current(&rdataset, &rdata);
5250 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5251 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5252 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5253 !zone_check_ns(zone, db, version, &ns.name, logit))
5254 ecount++;
5255 }
5256 count++;
5257 result = dns_rdataset_next(&rdataset);
5258 }
5259 dns_rdataset_disassociate(&rdataset);
5260
5261 success:
5262 if (nscount != NULL)
5263 *nscount = count;
5264 if (errors != NULL)
5265 *errors = ecount;
5266
5267 result = ISC_R_SUCCESS;
5268
5269 invalidate_rdataset:
5270 dns_rdataset_invalidate(&rdataset);
5271
5272 return (result);
5273 }
5274
5275 static isc_result_t
5276 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5277 unsigned int *soacount,
5278 uint32_t *serial, uint32_t *refresh,
5279 uint32_t *retry, uint32_t *expire,
5280 uint32_t *minimum)
5281 {
5282 isc_result_t result;
5283 unsigned int count;
5284 dns_rdataset_t rdataset;
5285 dns_rdata_t rdata = DNS_RDATA_INIT;
5286 dns_rdata_soa_t soa;
5287
5288 dns_rdataset_init(&rdataset);
5289 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5290 dns_rdatatype_none, 0, &rdataset, NULL);
5291 if (result == ISC_R_NOTFOUND) {
5292 INSIST(!dns_rdataset_isassociated(&rdataset));
5293 if (soacount != NULL)
5294 *soacount = 0;
5295 if (serial != NULL)
5296 *serial = 0;
5297 if (refresh != NULL)
5298 *refresh = 0;
5299 if (retry != NULL)
5300 *retry = 0;
5301 if (expire != NULL)
5302 *expire = 0;
5303 if (minimum != NULL)
5304 *minimum = 0;
5305 result = ISC_R_SUCCESS;
5306 goto invalidate_rdataset;
5307 }
5308 if (result != ISC_R_SUCCESS) {
5309 INSIST(!dns_rdataset_isassociated(&rdataset));
5310 goto invalidate_rdataset;
5311 }
5312
5313 count = 0;
5314 result = dns_rdataset_first(&rdataset);
5315 while (result == ISC_R_SUCCESS) {
5316 dns_rdata_init(&rdata);
5317 dns_rdataset_current(&rdataset, &rdata);
5318 count++;
5319 if (count == 1) {
5320 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5321 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5322 }
5323
5324 result = dns_rdataset_next(&rdataset);
5325 dns_rdata_reset(&rdata);
5326 }
5327 dns_rdataset_disassociate(&rdataset);
5328
5329 if (soacount != NULL)
5330 *soacount = count;
5331
5332 if (count > 0) {
5333 if (serial != NULL)
5334 *serial = soa.serial;
5335 if (refresh != NULL)
5336 *refresh = soa.refresh;
5337 if (retry != NULL)
5338 *retry = soa.retry;
5339 if (expire != NULL)
5340 *expire = soa.expire;
5341 if (minimum != NULL)
5342 *minimum = soa.minimum;
5343 } else {
5344 if (soacount != NULL)
5345 *soacount = 0;
5346 if (serial != NULL)
5347 *serial = 0;
5348 if (refresh != NULL)
5349 *refresh = 0;
5350 if (retry != NULL)
5351 *retry = 0;
5352 if (expire != NULL)
5353 *expire = 0;
5354 if (minimum != NULL)
5355 *minimum = 0;
5356 }
5357
5358 result = ISC_R_SUCCESS;
5359
5360 invalidate_rdataset:
5361 dns_rdataset_invalidate(&rdataset);
5362
5363 return (result);
5364 }
5365
5366 /*
5367 * zone must be locked.
5368 */
5369 static isc_result_t
5370 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5371 unsigned int *soacount, uint32_t *serial,
5372 uint32_t *refresh, uint32_t *retry,
5373 uint32_t *expire, uint32_t *minimum,
5374 unsigned int *errors)
5375 {
5376 isc_result_t result;
5377 isc_result_t answer = ISC_R_SUCCESS;
5378 dns_dbversion_t *version = NULL;
5379 dns_dbnode_t *node;
5380
5381 REQUIRE(db != NULL);
5382 REQUIRE(zone != NULL);
5383
5384 dns_db_currentversion(db, &version);
5385
5386 if (nscount != NULL)
5387 *nscount = 0;
5388 if (soacount != NULL)
5389 *soacount = 0;
5390 if (serial != NULL)
5391 *serial = 0;
5392 if (refresh != NULL)
5393 *refresh = 0;
5394 if (retry != NULL)
5395 *retry = 0;
5396 if (expire != NULL)
5397 *expire = 0;
5398 if (errors != NULL)
5399 *errors = 0;
5400
5401 node = NULL;
5402 result = dns_db_findnode(db, &zone->origin, false, &node);
5403 if (result != ISC_R_SUCCESS) {
5404 answer = result;
5405 goto closeversion;
5406 }
5407
5408 if (nscount != NULL || errors != NULL) {
5409 result = zone_count_ns_rr(zone, db, node, version,
5410 nscount, errors, true);
5411 if (result != ISC_R_SUCCESS)
5412 answer = result;
5413 }
5414
5415 if (soacount != NULL || serial != NULL || refresh != NULL
5416 || retry != NULL || expire != NULL || minimum != NULL) {
5417 result = zone_load_soa_rr(db, node, version, soacount,
5418 serial, refresh, retry, expire,
5419 minimum);
5420 if (result != ISC_R_SUCCESS)
5421 answer = result;
5422 }
5423
5424 dns_db_detachnode(db, &node);
5425 closeversion:
5426 dns_db_closeversion(db, &version, false);
5427
5428 return (answer);
5429 }
5430
5431 void
5432 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5433 REQUIRE(DNS_ZONE_VALID(source));
5434 REQUIRE(target != NULL && *target == NULL);
5435 isc_refcount_increment(&source->erefs);
5436 *target = source;
5437 }
5438
5439 void
5440 dns_zone_detach(dns_zone_t **zonep) {
5441 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5442 dns_zone_t *zone = *zonep;
5443 *zonep = NULL;
5444
5445 bool free_now = false;
5446 dns_zone_t *raw = NULL;
5447 dns_zone_t *secure = NULL;
5448 if (isc_refcount_decrement(&zone->erefs) == 1) {
5449 isc_refcount_destroy(&zone->erefs);
5450
5451 LOCK_ZONE(zone);
5452 INSIST(zone != zone->raw);
5453 /*
5454 * We just detached the last external reference.
5455 */
5456 if (zone->task != NULL) {
5457 /*
5458 * This zone is being managed. Post
5459 * its control event and let it clean
5460 * up synchronously in the context of
5461 * its task.
5462 */
5463 isc_event_t *ev = &zone->ctlevent;
5464 isc_task_send(zone->task, &ev);
5465 } else {
5466 /*
5467 * This zone is not being managed; it has
5468 * no task and can have no outstanding
5469 * events. Free it immediately.
5470 */
5471 /*
5472 * Unmanaged zones should not have non-null views;
5473 * we have no way of detaching from the view here
5474 * without causing deadlock because this code is called
5475 * with the view already locked.
5476 */
5477 INSIST(zone->view == NULL);
5478 free_now = true;
5479 raw = zone->raw;
5480 zone->raw = NULL;
5481 secure = zone->secure;
5482 zone->secure = NULL;
5483 }
5484 UNLOCK_ZONE(zone);
5485 }
5486 if (free_now) {
5487 if (raw != NULL) {
5488 dns_zone_detach(&raw);
5489 }
5490 if (secure != NULL) {
5491 dns_zone_idetach(&secure);
5492 }
5493 zone_free(zone);
5494 }
5495 }
5496
5497 void
5498 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5499 REQUIRE(DNS_ZONE_VALID(source));
5500 REQUIRE(target != NULL && *target == NULL);
5501 LOCK_ZONE(source);
5502 zone_iattach(source, target);
5503 UNLOCK_ZONE(source);
5504 }
5505
5506 static void
5507 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5508
5509 /*
5510 * 'source' locked by caller.
5511 */
5512 REQUIRE(DNS_ZONE_VALID(source));
5513 REQUIRE(LOCKED_ZONE(source));
5514 REQUIRE(target != NULL && *target == NULL);
5515 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
5516 source->irefs++;
5517 INSIST(source->irefs != 0);
5518 *target = source;
5519 }
5520
5521 static void
5522 zone_idetach(dns_zone_t **zonep) {
5523 dns_zone_t *zone;
5524
5525 /*
5526 * 'zone' locked by caller.
5527 */
5528 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5529 zone = *zonep;
5530 REQUIRE(LOCKED_ZONE(*zonep));
5531 *zonep = NULL;
5532
5533 INSIST(zone->irefs > 0);
5534 zone->irefs--;
5535 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
5536 }
5537
5538 void
5539 dns_zone_idetach(dns_zone_t **zonep) {
5540 dns_zone_t *zone;
5541 bool free_needed;
5542
5543 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5544 zone = *zonep;
5545 *zonep = NULL;
5546
5547 LOCK_ZONE(zone);
5548 INSIST(zone->irefs > 0);
5549 zone->irefs--;
5550 free_needed = exit_check(zone);
5551 UNLOCK_ZONE(zone);
5552 if (free_needed)
5553 zone_free(zone);
5554 }
5555
5556 isc_mem_t *
5557 dns_zone_getmctx(dns_zone_t *zone) {
5558 REQUIRE(DNS_ZONE_VALID(zone));
5559
5560 return (zone->mctx);
5561 }
5562
5563 dns_zonemgr_t *
5564 dns_zone_getmgr(dns_zone_t *zone) {
5565 REQUIRE(DNS_ZONE_VALID(zone));
5566
5567 return (zone->zmgr);
5568 }
5569
5570 void
5571 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, bool value) {
5572 REQUIRE(DNS_ZONE_VALID(zone));
5573
5574 LOCK_ZONE(zone);
5575 if (value)
5576 DNS_ZONE_SETFLAG(zone, flags);
5577 else
5578 DNS_ZONE_CLRFLAG(zone, flags);
5579 UNLOCK_ZONE(zone);
5580 }
5581
5582 void
5583 dns_zone_setoption(dns_zone_t *zone, dns_zoneopt_t option,
5584 bool value)
5585 {
5586 REQUIRE(DNS_ZONE_VALID(zone));
5587
5588 LOCK_ZONE(zone);
5589 if (value)
5590 zone->options |= option;
5591 else
5592 zone->options &= ~option;
5593 UNLOCK_ZONE(zone);
5594 }
5595
5596 dns_zoneopt_t
5597 dns_zone_getoptions(dns_zone_t *zone) {
5598 REQUIRE(DNS_ZONE_VALID(zone));
5599
5600 return (zone->options);
5601 }
5602
5603 void
5604 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, bool value)
5605 {
5606 REQUIRE(DNS_ZONE_VALID(zone));
5607
5608 LOCK_ZONE(zone);
5609 if (value)
5610 zone->keyopts |= keyopt;
5611 else
5612 zone->keyopts &= ~keyopt;
5613 UNLOCK_ZONE(zone);
5614 }
5615
5616 unsigned int
5617 dns_zone_getkeyopts(dns_zone_t *zone) {
5618
5619 REQUIRE(DNS_ZONE_VALID(zone));
5620
5621 return (zone->keyopts);
5622 }
5623
5624 isc_result_t
5625 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5626 REQUIRE(DNS_ZONE_VALID(zone));
5627
5628 LOCK_ZONE(zone);
5629 zone->xfrsource4 = *xfrsource;
5630 UNLOCK_ZONE(zone);
5631
5632 return (ISC_R_SUCCESS);
5633 }
5634
5635 isc_sockaddr_t *
5636 dns_zone_getxfrsource4(dns_zone_t *zone) {
5637 REQUIRE(DNS_ZONE_VALID(zone));
5638 return (&zone->xfrsource4);
5639 }
5640
5641 isc_result_t
5642 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5643 REQUIRE(DNS_ZONE_VALID(zone));
5644
5645 LOCK_ZONE(zone);
5646 zone->xfrsource4dscp = dscp;
5647 UNLOCK_ZONE(zone);
5648
5649 return (ISC_R_SUCCESS);
5650 }
5651
5652 isc_dscp_t
5653 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5654 REQUIRE(DNS_ZONE_VALID(zone));
5655 return (zone->xfrsource4dscp);
5656 }
5657
5658 isc_result_t
5659 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5660 REQUIRE(DNS_ZONE_VALID(zone));
5661
5662 LOCK_ZONE(zone);
5663 zone->xfrsource6 = *xfrsource;
5664 UNLOCK_ZONE(zone);
5665
5666 return (ISC_R_SUCCESS);
5667 }
5668
5669 isc_sockaddr_t *
5670 dns_zone_getxfrsource6(dns_zone_t *zone) {
5671 REQUIRE(DNS_ZONE_VALID(zone));
5672 return (&zone->xfrsource6);
5673 }
5674
5675 isc_dscp_t
5676 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5677 REQUIRE(DNS_ZONE_VALID(zone));
5678 return (zone->xfrsource6dscp);
5679 }
5680
5681 isc_result_t
5682 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5683 REQUIRE(DNS_ZONE_VALID(zone));
5684
5685 LOCK_ZONE(zone);
5686 zone->xfrsource6dscp = dscp;
5687 UNLOCK_ZONE(zone);
5688
5689 return (ISC_R_SUCCESS);
5690 }
5691
5692 isc_result_t
5693 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5694 const isc_sockaddr_t *altxfrsource)
5695 {
5696 REQUIRE(DNS_ZONE_VALID(zone));
5697
5698 LOCK_ZONE(zone);
5699 zone->altxfrsource4 = *altxfrsource;
5700 UNLOCK_ZONE(zone);
5701
5702 return (ISC_R_SUCCESS);
5703 }
5704
5705 isc_sockaddr_t *
5706 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
5707 REQUIRE(DNS_ZONE_VALID(zone));
5708 return (&zone->altxfrsource4);
5709 }
5710
5711 isc_result_t
5712 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5713 REQUIRE(DNS_ZONE_VALID(zone));
5714
5715 LOCK_ZONE(zone);
5716 zone->altxfrsource4dscp = dscp;
5717 UNLOCK_ZONE(zone);
5718
5719 return (ISC_R_SUCCESS);
5720 }
5721
5722 isc_dscp_t
5723 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
5724 REQUIRE(DNS_ZONE_VALID(zone));
5725 return (zone->altxfrsource4dscp);
5726 }
5727
5728 isc_result_t
5729 dns_zone_setaltxfrsource6(dns_zone_t *zone,
5730 const isc_sockaddr_t *altxfrsource)
5731 {
5732 REQUIRE(DNS_ZONE_VALID(zone));
5733
5734 LOCK_ZONE(zone);
5735 zone->altxfrsource6 = *altxfrsource;
5736 UNLOCK_ZONE(zone);
5737
5738 return (ISC_R_SUCCESS);
5739 }
5740
5741 isc_sockaddr_t *
5742 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
5743 REQUIRE(DNS_ZONE_VALID(zone));
5744 return (&zone->altxfrsource6);
5745 }
5746
5747 isc_result_t
5748 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5749 REQUIRE(DNS_ZONE_VALID(zone));
5750
5751 LOCK_ZONE(zone);
5752 zone->altxfrsource6dscp = dscp;
5753 UNLOCK_ZONE(zone);
5754
5755 return (ISC_R_SUCCESS);
5756 }
5757
5758 isc_dscp_t
5759 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
5760 REQUIRE(DNS_ZONE_VALID(zone));
5761 return (zone->altxfrsource6dscp);
5762 }
5763
5764 isc_result_t
5765 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5766 REQUIRE(DNS_ZONE_VALID(zone));
5767
5768 LOCK_ZONE(zone);
5769 zone->notifysrc4 = *notifysrc;
5770 UNLOCK_ZONE(zone);
5771
5772 return (ISC_R_SUCCESS);
5773 }
5774
5775 isc_sockaddr_t *
5776 dns_zone_getnotifysrc4(dns_zone_t *zone) {
5777 REQUIRE(DNS_ZONE_VALID(zone));
5778 return (&zone->notifysrc4);
5779 }
5780
5781 isc_result_t
5782 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5783 REQUIRE(DNS_ZONE_VALID(zone));
5784
5785 LOCK_ZONE(zone);
5786 zone->notifysrc4dscp = dscp;
5787 UNLOCK_ZONE(zone);
5788
5789 return (ISC_R_SUCCESS);
5790 }
5791
5792 isc_dscp_t
5793 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
5794 REQUIRE(DNS_ZONE_VALID(zone));
5795 return (zone->notifysrc4dscp);
5796 }
5797
5798 isc_result_t
5799 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5800 REQUIRE(DNS_ZONE_VALID(zone));
5801
5802 LOCK_ZONE(zone);
5803 zone->notifysrc6 = *notifysrc;
5804 UNLOCK_ZONE(zone);
5805
5806 return (ISC_R_SUCCESS);
5807 }
5808
5809 isc_sockaddr_t *
5810 dns_zone_getnotifysrc6(dns_zone_t *zone) {
5811 REQUIRE(DNS_ZONE_VALID(zone));
5812 return (&zone->notifysrc6);
5813 }
5814
5815 static bool
5816 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
5817 uint32_t count)
5818 {
5819 unsigned int i;
5820
5821 for (i = 0; i < count; i++)
5822 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i]))
5823 return (false);
5824 return (true);
5825 }
5826
5827 static bool
5828 same_keynames(dns_name_t * const *oldlist, dns_name_t * const *newlist,
5829 uint32_t count)
5830 {
5831 unsigned int i;
5832
5833 if (oldlist == NULL && newlist == NULL)
5834 return (true);
5835 if (oldlist == NULL || newlist == NULL)
5836 return (false);
5837
5838 for (i = 0; i < count; i++) {
5839 if (oldlist[i] == NULL && newlist[i] == NULL)
5840 continue;
5841 if (oldlist[i] == NULL || newlist[i] == NULL ||
5842 !dns_name_equal(oldlist[i], newlist[i]))
5843 return (false);
5844 }
5845 return (true);
5846 }
5847
5848 static void
5849 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
5850 dns_name_t ***keynamesp, unsigned int *countp,
5851 isc_mem_t *mctx)
5852 {
5853 unsigned int count;
5854 isc_sockaddr_t *addrs;
5855 isc_dscp_t *dscps;
5856 dns_name_t **keynames;
5857
5858 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
5859 keynamesp != NULL);
5860
5861 count = *countp;
5862 *countp = 0;
5863 addrs = *addrsp;
5864 *addrsp = NULL;
5865 dscps = *dscpsp;
5866 *dscpsp = NULL;
5867 keynames = *keynamesp;
5868 *keynamesp = NULL;
5869
5870 if (addrs != NULL)
5871 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
5872
5873 if (dscps != NULL)
5874 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
5875
5876 if (keynames != NULL) {
5877 unsigned int i;
5878 for (i = 0; i < count; i++) {
5879 if (keynames[i] != NULL) {
5880 dns_name_free(keynames[i], mctx);
5881 isc_mem_put(mctx, keynames[i],
5882 sizeof(dns_name_t));
5883 keynames[i] = NULL;
5884 }
5885 }
5886 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
5887 }
5888 }
5889
5890 static isc_result_t
5891 set_addrkeylist(unsigned int count,
5892 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
5893 const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
5894 dns_name_t **names, dns_name_t ***newnamesp,
5895 isc_mem_t *mctx)
5896 {
5897 isc_result_t result;
5898 isc_sockaddr_t *newaddrs = NULL;
5899 isc_dscp_t *newdscp = NULL;
5900 dns_name_t **newnames = NULL;
5901 unsigned int i;
5902
5903 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
5904 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
5905 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
5906
5907 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
5908 if (newaddrs == NULL)
5909 return (ISC_R_NOMEMORY);
5910 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
5911
5912 if (dscp != NULL) {
5913 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
5914 if (newdscp == NULL) {
5915 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5916 return (ISC_R_NOMEMORY);
5917 }
5918 memmove(newdscp, dscp, count * sizeof(*newdscp));
5919 } else
5920 newdscp = NULL;
5921
5922 if (names != NULL) {
5923 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
5924 if (newnames == NULL) {
5925 if (newdscp != NULL)
5926 isc_mem_put(mctx, newdscp,
5927 count * sizeof(*newdscp));
5928 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5929 return (ISC_R_NOMEMORY);
5930 }
5931 for (i = 0; i < count; i++)
5932 newnames[i] = NULL;
5933 for (i = 0; i < count; i++) {
5934 if (names[i] != NULL) {
5935 newnames[i] = isc_mem_get(mctx,
5936 sizeof(dns_name_t));
5937 if (newnames[i] == NULL)
5938 goto allocfail;
5939 dns_name_init(newnames[i], NULL);
5940 result = dns_name_dup(names[i], mctx,
5941 newnames[i]);
5942 if (result != ISC_R_SUCCESS) {
5943 allocfail:
5944 for (i = 0; i < count; i++)
5945 if (newnames[i] != NULL)
5946 dns_name_free(
5947 newnames[i],
5948 mctx);
5949 isc_mem_put(mctx, newaddrs,
5950 count * sizeof(*newaddrs));
5951 isc_mem_put(mctx, newdscp,
5952 count * sizeof(*newdscp));
5953 isc_mem_put(mctx, newnames,
5954 count * sizeof(*newnames));
5955 return (ISC_R_NOMEMORY);
5956 }
5957 }
5958 }
5959 } else
5960 newnames = NULL;
5961
5962 *newdscpp = newdscp;
5963 *newaddrsp = newaddrs;
5964 *newnamesp = newnames;
5965 return (ISC_R_SUCCESS);
5966 }
5967
5968 isc_result_t
5969 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5970 REQUIRE(DNS_ZONE_VALID(zone));
5971
5972 LOCK_ZONE(zone);
5973 zone->notifysrc6dscp = dscp;
5974 UNLOCK_ZONE(zone);
5975
5976 return (ISC_R_SUCCESS);
5977 }
5978
5979 isc_dscp_t
5980 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
5981 REQUIRE(DNS_ZONE_VALID(zone));
5982 return (zone->notifysrc6dscp);
5983 }
5984
5985 isc_result_t
5986 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5987 uint32_t count)
5988 {
5989 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
5990 count));
5991 }
5992
5993 isc_result_t
5994 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5995 dns_name_t **keynames, uint32_t count)
5996 {
5997 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
5998 count));
5999 }
6000
6001 isc_result_t
6002 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
6003 const isc_dscp_t *dscps, dns_name_t **keynames,
6004 uint32_t count)
6005 {
6006 isc_result_t result;
6007 isc_sockaddr_t *newaddrs = NULL;
6008 isc_dscp_t *newdscps = NULL;
6009 dns_name_t **newnames = NULL;
6010
6011 REQUIRE(DNS_ZONE_VALID(zone));
6012 REQUIRE(count == 0 || notify != NULL);
6013 if (keynames != NULL)
6014 REQUIRE(count != 0);
6015
6016 LOCK_ZONE(zone);
6017
6018 if (count == zone->notifycnt &&
6019 same_addrs(zone->notify, notify, count) &&
6020 same_keynames(zone->notifykeynames, keynames, count))
6021 goto unlock;
6022
6023 clear_addresskeylist(&zone->notify, &zone->notifydscp,
6024 &zone->notifykeynames, &zone->notifycnt,
6025 zone->mctx);
6026
6027 if (count == 0)
6028 goto unlock;
6029
6030 /*
6031 * Set up the notify and notifykey lists
6032 */
6033 result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
6034 keynames, &newnames, zone->mctx);
6035 if (result != ISC_R_SUCCESS)
6036 goto unlock;
6037
6038 /*
6039 * Everything is ok so attach to the zone.
6040 */
6041 zone->notify = newaddrs;
6042 zone->notifydscp = newdscps;
6043 zone->notifykeynames = newnames;
6044 zone->notifycnt = count;
6045 unlock:
6046 UNLOCK_ZONE(zone);
6047 return (ISC_R_SUCCESS);
6048 }
6049
6050 isc_result_t
6051 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
6052 uint32_t count)
6053 {
6054 isc_result_t result;
6055
6056 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
6057 return (result);
6058 }
6059
6060 isc_result_t
6061 dns_zone_setmasterswithkeys(dns_zone_t *zone,
6062 const isc_sockaddr_t *masters,
6063 dns_name_t **keynames,
6064 uint32_t count)
6065 {
6066 isc_result_t result = ISC_R_SUCCESS;
6067 isc_sockaddr_t *newaddrs = NULL;
6068 isc_dscp_t *newdscps = NULL;
6069 dns_name_t **newnames = NULL;
6070 bool *newok;
6071 unsigned int i;
6072
6073 REQUIRE(DNS_ZONE_VALID(zone));
6074 REQUIRE(count == 0 || masters != NULL);
6075 if (keynames != NULL) {
6076 REQUIRE(count != 0);
6077 }
6078
6079 LOCK_ZONE(zone);
6080 /*
6081 * The refresh code assumes that 'masters' wouldn't change under it.
6082 * If it will change then kill off any current refresh in progress
6083 * and update the masters info. If it won't change then we can just
6084 * unlock and exit.
6085 */
6086 if (count != zone->masterscnt ||
6087 !same_addrs(zone->masters, masters, count) ||
6088 !same_keynames(zone->masterkeynames, keynames, count)) {
6089 if (zone->request != NULL)
6090 dns_request_cancel(zone->request);
6091 } else
6092 goto unlock;
6093
6094 /*
6095 * This needs to happen before clear_addresskeylist() sets
6096 * zone->masterscnt to 0:
6097 */
6098 if (zone->mastersok != NULL) {
6099 isc_mem_put(zone->mctx, zone->mastersok,
6100 zone->masterscnt * sizeof(bool));
6101 zone->mastersok = NULL;
6102 }
6103 clear_addresskeylist(&zone->masters, &zone->masterdscps,
6104 &zone->masterkeynames, &zone->masterscnt,
6105 zone->mctx);
6106 /*
6107 * If count == 0, don't allocate any space for masters, mastersok or
6108 * keynames so internally, those pointers are NULL if count == 0
6109 */
6110 if (count == 0)
6111 goto unlock;
6112
6113 /*
6114 * mastersok must contain count elements
6115 */
6116 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
6117 if (newok == NULL) {
6118 result = ISC_R_NOMEMORY;
6119 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
6120 goto unlock;
6121 };
6122 for (i = 0; i < count; i++)
6123 newok[i] = false;
6124
6125 /*
6126 * Now set up the masters and masterkey lists
6127 */
6128 result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
6129 keynames, &newnames, zone->mctx);
6130 INSIST(newdscps == NULL);
6131 if (result != ISC_R_SUCCESS) {
6132 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
6133 goto unlock;
6134 }
6135
6136 /*
6137 * Everything is ok so attach to the zone.
6138 */
6139 zone->curmaster = 0;
6140 zone->mastersok = newok;
6141 zone->masters = newaddrs;
6142 zone->masterdscps = newdscps;
6143 zone->masterkeynames = newnames;
6144 zone->masterscnt = count;
6145 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
6146
6147 unlock:
6148 UNLOCK_ZONE(zone);
6149 return (result);
6150 }
6151
6152 isc_result_t
6153 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
6154 isc_result_t result = ISC_R_SUCCESS;
6155
6156 REQUIRE(DNS_ZONE_VALID(zone));
6157
6158 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6159 if (zone->db == NULL)
6160 result = DNS_R_NOTLOADED;
6161 else
6162 dns_db_attach(zone->db, dpb);
6163 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6164
6165 return (result);
6166 }
6167
6168 void
6169 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6170 REQUIRE(DNS_ZONE_VALID(zone));
6171 REQUIRE(zone->type == dns_zone_staticstub);
6172
6173 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6174 REQUIRE(zone->db == NULL);
6175 dns_db_attach(db, &zone->db);
6176 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6177 }
6178
6179 /*
6180 * Co-ordinates the starting of routine jobs.
6181 */
6182 void
6183 dns_zone_maintenance(dns_zone_t *zone) {
6184 const char me[] = "dns_zone_maintenance";
6185 isc_time_t now;
6186
6187 REQUIRE(DNS_ZONE_VALID(zone));
6188 ENTER;
6189
6190 LOCK_ZONE(zone);
6191 TIME_NOW(&now);
6192 zone_settimer(zone, &now);
6193 UNLOCK_ZONE(zone);
6194 }
6195
6196 static inline bool
6197 was_dumping(dns_zone_t *zone) {
6198
6199 REQUIRE(LOCKED_ZONE(zone));
6200
6201 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
6202 return (true);
6203 }
6204
6205 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6206 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6207 isc_time_settoepoch(&zone->dumptime);
6208 return (false);
6209 }
6210
6211 /*%
6212 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6213 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6214 * Only load the public part of a given key if it is not active at timestamp
6215 * 'now'. Store the number of keys found in 'nkeys'.
6216 */
6217 isc_result_t
6218 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6219 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6220 dst_key_t **keys, unsigned int *nkeys)
6221 {
6222 isc_result_t result;
6223 dns_dbnode_t *node = NULL;
6224 const char *directory = dns_zone_getkeydirectory(zone);
6225
6226 CHECK(dns_db_findnode(db, dns_db_origin(db), false, &node));
6227 memset(keys, 0, sizeof(*keys) * maxkeys);
6228 result = dns_dnssec_findzonekeys(db, ver, node, dns_db_origin(db),
6229 directory, now, mctx, maxkeys, keys,
6230 nkeys);
6231 if (result == ISC_R_NOTFOUND)
6232 result = ISC_R_SUCCESS;
6233 failure:
6234 if (node != NULL)
6235 dns_db_detachnode(db, &node);
6236 return (result);
6237 }
6238
6239 static isc_result_t
6240 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6241 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
6242 {
6243 isc_result_t result;
6244
6245 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
6246 return (ISC_R_SUCCESS);
6247 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6248 name, ttl, rdata);
6249 if (result != ISC_R_SUCCESS)
6250 return (result);
6251 rdata->flags |= DNS_RDATA_OFFLINE;
6252 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6253 name, ttl, rdata);
6254 zonediff->offline = true;
6255 return (result);
6256 }
6257
6258 static void
6259 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
6260 {
6261 unsigned int delta;
6262 char timebuf[80];
6263
6264 zone->key_expiry = when;
6265 if (when <= now) {
6266 dns_zone_log(zone, ISC_LOG_ERROR,
6267 "DNSKEY RRSIG(s) have expired");
6268 isc_time_settoepoch(&zone->keywarntime);
6269 } else if (when < now + 7 * 24 * 3600) {
6270 isc_time_t t;
6271 isc_time_set(&t, when, 0);
6272 isc_time_formattimestamp(&t, timebuf, 80);
6273 dns_zone_log(zone, ISC_LOG_WARNING,
6274 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6275 timebuf);
6276 delta = when - now;
6277 delta--; /* loop prevention */
6278 delta /= 24 * 3600; /* to whole days */
6279 delta *= 24 * 3600; /* to seconds */
6280 isc_time_set(&zone->keywarntime, when - delta, 0);
6281 } else {
6282 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6283 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6284 dns_zone_log(zone, ISC_LOG_NOTICE,
6285 "setting keywarntime to %s", timebuf);
6286 }
6287 }
6288
6289 /*
6290 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6291 * have no new key.
6292 */
6293 static bool
6294 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6295 bool *warn)
6296 {
6297 unsigned int i = 0;
6298 bool have_ksk = false, have_zsk = false;
6299 bool have_pksk = false, have_pzsk = false;
6300
6301 for (i = 0; i < nkeys; i++) {
6302 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
6303 continue;
6304 if (dst_key_isprivate(keys[i])) {
6305 if (KSK(keys[i]))
6306 have_ksk = have_pksk = true;
6307 else
6308 have_zsk = have_pzsk = true;
6309 } else {
6310 if (KSK(keys[i]))
6311 have_ksk = true;
6312 else
6313 have_zsk = true;
6314 }
6315 }
6316
6317 if (have_zsk && have_ksk && !have_pzsk)
6318 *warn = true;
6319
6320 /*
6321 * It's okay to delete a signature if there is an active key
6322 * with the same algorithm to replace it.
6323 */
6324 if (have_pksk || have_pzsk)
6325 return (true);
6326
6327 /*
6328 * Failing that, it is *not* okay to delete a signature
6329 * if the associated public key is still in the DNSKEY RRset
6330 */
6331 for (i = 0; i < nkeys; i++) {
6332 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6333 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6334 return (false);
6335 }
6336
6337 /*
6338 * But if the key is gone, then go ahead.
6339 */
6340 return (true);
6341 }
6342
6343 /*
6344 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6345 * See also update.c:del_keysigs().
6346 */
6347 static isc_result_t
6348 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6349 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6350 unsigned int nkeys, isc_stdtime_t now, bool incremental)
6351 {
6352 isc_result_t result;
6353 dns_dbnode_t *node = NULL;
6354 dns_rdataset_t rdataset;
6355 unsigned int i;
6356 dns_rdata_rrsig_t rrsig;
6357 bool found;
6358 int64_t timewarn = 0, timemaybe = 0;
6359
6360 dns_rdataset_init(&rdataset);
6361
6362 if (type == dns_rdatatype_nsec3)
6363 result = dns_db_findnsec3node(db, name, false, &node);
6364 else
6365 result = dns_db_findnode(db, name, false, &node);
6366 if (result == ISC_R_NOTFOUND)
6367 return (ISC_R_SUCCESS);
6368 if (result != ISC_R_SUCCESS)
6369 goto failure;
6370 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6371 (isc_stdtime_t) 0, &rdataset, NULL);
6372 dns_db_detachnode(db, &node);
6373
6374 if (result == ISC_R_NOTFOUND) {
6375 INSIST(!dns_rdataset_isassociated(&rdataset));
6376 return (ISC_R_SUCCESS);
6377 }
6378 if (result != ISC_R_SUCCESS) {
6379 INSIST(!dns_rdataset_isassociated(&rdataset));
6380 goto failure;
6381 }
6382
6383 for (result = dns_rdataset_first(&rdataset);
6384 result == ISC_R_SUCCESS;
6385 result = dns_rdataset_next(&rdataset)) {
6386 dns_rdata_t rdata = DNS_RDATA_INIT;
6387
6388 dns_rdataset_current(&rdataset, &rdata);
6389 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6390 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6391
6392 if (type != dns_rdatatype_dnskey) {
6393 bool warn = false, deleted = false;
6394 if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
6395 result = update_one_rr(db, ver, zonediff->diff,
6396 DNS_DIFFOP_DELRESIGN, name,
6397 rdataset.ttl, &rdata);
6398 if (result != ISC_R_SUCCESS)
6399 break;
6400 deleted = true;
6401 }
6402 if (warn) {
6403 /*
6404 * At this point, we've got an RRSIG,
6405 * which is signed by an inactive key.
6406 * An administrator needs to provide a new
6407 * key/alg, but until that time, we want to
6408 * keep the old RRSIG. Marking the key as
6409 * offline will prevent us spinning waiting
6410 * for the private part.
6411 */
6412 if (incremental && !deleted) {
6413 result = offline(db, ver, zonediff,
6414 name, rdataset.ttl,
6415 &rdata);
6416 if (result != ISC_R_SUCCESS)
6417 break;
6418 }
6419
6420 /*
6421 * Log the key id and algorithm of
6422 * the inactive key with no replacement
6423 */
6424 if (zone->log_key_expired_timer <= now) {
6425 char origin[DNS_NAME_FORMATSIZE];
6426 char algbuf[DNS_NAME_FORMATSIZE];
6427 dns_name_format(&zone->origin, origin,
6428 sizeof(origin));
6429 dns_secalg_format(rrsig.algorithm,
6430 algbuf,
6431 sizeof(algbuf));
6432 dns_zone_log(zone, ISC_LOG_WARNING,
6433 "Key %s/%s/%d "
6434 "missing or inactive "
6435 "and has no replacement: "
6436 "retaining signatures.",
6437 origin, algbuf,
6438 rrsig.keyid);
6439 zone->log_key_expired_timer = now +
6440 3600;
6441 }
6442 }
6443 continue;
6444 }
6445
6446 /*
6447 * RRSIG(DNSKEY) requires special processing.
6448 */
6449 found = false;
6450 for (i = 0; i < nkeys; i++) {
6451 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6452 rrsig.keyid == dst_key_id(keys[i])) {
6453 found = true;
6454 /*
6455 * Mark offline RRSIG(DNSKEY).
6456 * We want the earliest offline expire time
6457 * iff there is a new offline signature.
6458 */
6459 if (!dst_key_inactive(keys[i]) &&
6460 !dst_key_isprivate(keys[i]))
6461 {
6462 int64_t timeexpire =
6463 dns_time64_from32(rrsig.timeexpire);
6464 if (timewarn != 0 &&
6465 timewarn > timeexpire)
6466 timewarn = timeexpire;
6467 if (rdata.flags & DNS_RDATA_OFFLINE) {
6468 if (timemaybe == 0 ||
6469 timemaybe > timeexpire)
6470 timemaybe = timeexpire;
6471 break;
6472 }
6473 if (timewarn == 0)
6474 timewarn = timemaybe;
6475 if (timewarn == 0 ||
6476 timewarn > timeexpire)
6477 timewarn = timeexpire;
6478 result = offline(db, ver, zonediff,
6479 name, rdataset.ttl,
6480 &rdata);
6481 break;
6482 }
6483 result = update_one_rr(db, ver, zonediff->diff,
6484 DNS_DIFFOP_DELRESIGN,
6485 name, rdataset.ttl,
6486 &rdata);
6487 break;
6488 }
6489 }
6490
6491 /*
6492 * If there is not a matching DNSKEY then
6493 * delete the RRSIG.
6494 */
6495 if (!found) {
6496 result = update_one_rr(db, ver, zonediff->diff,
6497 DNS_DIFFOP_DELRESIGN, name,
6498 rdataset.ttl, &rdata);
6499 }
6500 if (result != ISC_R_SUCCESS)
6501 break;
6502 }
6503
6504 dns_rdataset_disassociate(&rdataset);
6505 if (result == ISC_R_NOMORE)
6506 result = ISC_R_SUCCESS;
6507 if (timewarn > 0) {
6508 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6509 if (timewarn == stdwarn) {
6510 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6511 now);
6512 } else {
6513 dns_zone_log(zone, ISC_LOG_ERROR,
6514 "key expiry warning time out of range");
6515 }
6516 }
6517 failure:
6518 if (node != NULL)
6519 dns_db_detachnode(db, &node);
6520 return (result);
6521 }
6522
6523 static isc_result_t
6524 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6525 dns_zone_t* zone, dns_rdatatype_t type, dns_diff_t *diff,
6526 dst_key_t **keys, unsigned int nkeys, isc_mem_t *mctx,
6527 isc_stdtime_t inception, isc_stdtime_t expire,
6528 bool check_ksk, bool keyset_kskonly)
6529 {
6530 isc_result_t result;
6531 dns_dbnode_t *node = NULL;
6532 dns_stats_t* dnssecsignstats;
6533 dns_stats_t* dnssecrefreshstats;
6534 dns_rdataset_t rdataset;
6535 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6536 unsigned char data[1024]; /* XXX */
6537 isc_buffer_t buffer;
6538 unsigned int i, j;
6539
6540 dns_rdataset_init(&rdataset);
6541 isc_buffer_init(&buffer, data, sizeof(data));
6542
6543 if (type == dns_rdatatype_nsec3)
6544 result = dns_db_findnsec3node(db, name, false, &node);
6545 else
6546 result = dns_db_findnode(db, name, false, &node);
6547 if (result == ISC_R_NOTFOUND)
6548 return (ISC_R_SUCCESS);
6549 if (result != ISC_R_SUCCESS)
6550 goto failure;
6551 result = dns_db_findrdataset(db, node, ver, type, 0,
6552 (isc_stdtime_t) 0, &rdataset, NULL);
6553 dns_db_detachnode(db, &node);
6554 if (result == ISC_R_NOTFOUND) {
6555 INSIST(!dns_rdataset_isassociated(&rdataset));
6556 return (ISC_R_SUCCESS);
6557 }
6558 if (result != ISC_R_SUCCESS) {
6559 INSIST(!dns_rdataset_isassociated(&rdataset));
6560 goto failure;
6561 }
6562
6563 for (i = 0; i < nkeys; i++) {
6564 bool both = false;
6565
6566 /* Don't add signatures for offline or inactive keys */
6567 if (!dst_key_isprivate(keys[i])) {
6568 continue;
6569 }
6570 if (dst_key_inactive(keys[i])) {
6571 continue;
6572 }
6573
6574 if (check_ksk && !REVOKE(keys[i])) {
6575 bool have_ksk, have_nonksk;
6576 if (KSK(keys[i])) {
6577 have_ksk = true;
6578 have_nonksk = false;
6579 } else {
6580 have_ksk = false;
6581 have_nonksk = true;
6582 }
6583
6584 for (j = 0; j < nkeys; j++) {
6585 if (j == i || ALG(keys[i]) != ALG(keys[j])) {
6586 continue;
6587 }
6588
6589 /* Don't consider inactive keys, however
6590 * the key may be temporary offline, so do
6591 * consider keys which private key files are
6592 * unavailable.
6593 */
6594 if (dst_key_inactive(keys[j])) {
6595 continue;
6596 }
6597
6598 if (REVOKE(keys[j])) {
6599 continue;
6600 }
6601 if (KSK(keys[j])) {
6602 have_ksk = true;
6603 } else {
6604 have_nonksk = true;
6605 }
6606 both = have_ksk && have_nonksk;
6607 if (both) {
6608 break;
6609 }
6610 }
6611 }
6612
6613 if (both) {
6614 /*
6615 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6616 */
6617 if (type == dns_rdatatype_dnskey ||
6618 type == dns_rdatatype_cdnskey ||
6619 type == dns_rdatatype_cds)
6620 {
6621 if (!KSK(keys[i]) && keyset_kskonly)
6622 continue;
6623 } else if (KSK(keys[i])) {
6624 continue;
6625 }
6626 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
6627 continue;
6628 }
6629
6630 /* Calculate the signature, creating a RRSIG RDATA. */
6631 isc_buffer_clear(&buffer);
6632 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
6633 &inception, &expire,
6634 mctx, &buffer, &sig_rdata));
6635
6636 /* Update the database and journal with the RRSIG. */
6637 /* XXX inefficient - will cause dataset merging */
6638 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
6639 name, rdataset.ttl, &sig_rdata));
6640 dns_rdata_reset(&sig_rdata);
6641 isc_buffer_init(&buffer, data, sizeof(data));
6642
6643 /* Update DNSSEC sign statistics. */
6644 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
6645 dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
6646 if (dnssecsignstats != NULL) {
6647 dns_dnssecsignstats_increment(
6648 dns_zone_getdnssecsignstats(zone),
6649 dst_key_id(keys[i]));
6650 }
6651 if (dnssecrefreshstats != NULL) {
6652 dns_dnssecsignstats_increment(
6653 dns_zone_getdnssecrefreshstats(zone),
6654 dst_key_id(keys[i]));
6655 }
6656 }
6657
6658 failure:
6659 if (dns_rdataset_isassociated(&rdataset))
6660 dns_rdataset_disassociate(&rdataset);
6661 if (node != NULL)
6662 dns_db_detachnode(db, &node);
6663 return (result);
6664 }
6665
6666 static void
6667 zone_resigninc(dns_zone_t *zone) {
6668 const char *me = "zone_resigninc";
6669 dns_db_t *db = NULL;
6670 dns_dbversion_t *version = NULL;
6671 dns_diff_t _sig_diff;
6672 dns__zonediff_t zonediff;
6673 dns_fixedname_t fixed;
6674 dns_name_t *name;
6675 dns_rdataset_t rdataset;
6676 dns_rdatatype_t covers;
6677 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6678 bool check_ksk, keyset_kskonly = false;
6679 isc_result_t result;
6680 isc_stdtime_t now, inception, soaexpire, expire, fullexpire, stop;
6681 uint32_t sigvalidityinterval, expiryinterval;
6682 unsigned int i;
6683 unsigned int nkeys = 0;
6684 unsigned int resign;
6685
6686 ENTER;
6687
6688 dns_rdataset_init(&rdataset);
6689 dns_diff_init(zone->mctx, &_sig_diff);
6690 zonediff_init(&zonediff, &_sig_diff);
6691
6692 /*
6693 * Zone is frozen or automatic resigning is disabled.
6694 * Pause for 5 minutes.
6695 */
6696 if (zone->update_disabled ||
6697 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
6698 {
6699 result = ISC_R_FAILURE;
6700 goto failure;
6701 }
6702
6703 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6704 dns_db_attach(zone->db, &db);
6705 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6706
6707 result = dns_db_newversion(db, &version);
6708 if (result != ISC_R_SUCCESS) {
6709 dns_zone_log(zone, ISC_LOG_ERROR,
6710 "zone_resigninc:dns_db_newversion -> %s",
6711 dns_result_totext(result));
6712 goto failure;
6713 }
6714
6715 isc_stdtime_get(&now);
6716
6717 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
6718 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6719 if (result != ISC_R_SUCCESS) {
6720 dns_zone_log(zone, ISC_LOG_ERROR,
6721 "zone_resigninc:dns__zone_findkeys -> %s",
6722 dns_result_totext(result));
6723 goto failure;
6724 }
6725
6726 sigvalidityinterval = zone->sigvalidityinterval;
6727 inception = now - 3600; /* Allow for clock skew. */
6728 soaexpire = now + sigvalidityinterval;
6729 expiryinterval = dns_zone_getsigresigninginterval(zone);
6730 if (expiryinterval > sigvalidityinterval) {
6731 expiryinterval = sigvalidityinterval;
6732 } else {
6733 expiryinterval = sigvalidityinterval - expiryinterval;
6734 }
6735
6736 /*
6737 * Spread out signatures over time if they happen to be
6738 * clumped. We don't do this for each add_sigs() call as
6739 * we still want some clustering to occur. In normal operations
6740 * the records should be re-signed as they fall due and they should
6741 * already be spread out. However if the server is off for a
6742 * period we need to ensure that the clusters don't become
6743 * synchronised by using the full jitter range.
6744 */
6745 if (sigvalidityinterval >= 3600U) {
6746 uint32_t normaljitter, fulljitter;
6747 if (sigvalidityinterval > 7200U) {
6748 normaljitter = isc_random_uniform(3600);
6749 fulljitter = isc_random_uniform(expiryinterval);
6750 } else {
6751 normaljitter = fulljitter = isc_random_uniform(1200);
6752 }
6753 expire = soaexpire - normaljitter - 1;
6754 fullexpire = soaexpire - fulljitter - 1;
6755 } else {
6756 expire = fullexpire = soaexpire - 1;
6757 }
6758 stop = now + 5;
6759
6760 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6761 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6762
6763 name = dns_fixedname_initname(&fixed);
6764 result = dns_db_getsigningtime(db, &rdataset, name);
6765 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6766 dns_zone_log(zone, ISC_LOG_ERROR,
6767 "zone_resigninc:dns_db_getsigningtime -> %s",
6768 dns_result_totext(result));
6769 }
6770
6771 i = 0;
6772 while (result == ISC_R_SUCCESS) {
6773 resign = rdataset.resign - zone->sigresigninginterval;
6774 covers = rdataset.covers;
6775 dns_rdataset_disassociate(&rdataset);
6776
6777 /*
6778 * Stop if we hit the SOA as that means we have walked the
6779 * entire zone. The SOA record should always be the most
6780 * recent signature.
6781 */
6782 /* XXXMPA increase number of RRsets signed pre call */
6783 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
6784 resign > stop)
6785 break;
6786
6787 result = del_sigs(zone, db, version, name, covers, &zonediff,
6788 zone_keys, nkeys, now, true);
6789 if (result != ISC_R_SUCCESS) {
6790 dns_zone_log(zone, ISC_LOG_ERROR,
6791 "zone_resigninc:del_sigs -> %s",
6792 dns_result_totext(result));
6793 break;
6794 }
6795
6796 /*
6797 * If re-signing is over 5 minutes late use 'fullexpire'
6798 * to redistribute the signature over the complete
6799 * re-signing window, otherwise only add a small amount
6800 * of jitter.
6801 */
6802 result = add_sigs(db, version, name, zone, covers,
6803 zonediff.diff, zone_keys, nkeys, zone->mctx,
6804 inception,
6805 resign > (now - 300) ? expire : fullexpire,
6806 check_ksk, keyset_kskonly);
6807 if (result != ISC_R_SUCCESS) {
6808 dns_zone_log(zone, ISC_LOG_ERROR,
6809 "zone_resigninc:add_sigs -> %s",
6810 dns_result_totext(result));
6811 break;
6812 }
6813 result = dns_db_getsigningtime(db, &rdataset, name);
6814 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
6815 result = ISC_R_SUCCESS;
6816 break;
6817 }
6818 if (result != ISC_R_SUCCESS)
6819 dns_zone_log(zone, ISC_LOG_ERROR,
6820 "zone_resigninc:dns_db_getsigningtime -> %s",
6821 dns_result_totext(result));
6822 }
6823
6824 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
6825 goto failure;
6826
6827 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6828 &zonediff, zone_keys, nkeys, now, true);
6829 if (result != ISC_R_SUCCESS) {
6830 dns_zone_log(zone, ISC_LOG_ERROR,
6831 "zone_resigninc:del_sigs -> %s",
6832 dns_result_totext(result));
6833 goto failure;
6834 }
6835
6836 /*
6837 * Did we change anything in the zone?
6838 */
6839 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
6840 /*
6841 * Commit the changes if any key has been marked as offline.
6842 */
6843 if (zonediff.offline)
6844 dns_db_closeversion(db, &version, true);
6845 goto failure;
6846 }
6847
6848 /* Increment SOA serial if we have made changes */
6849 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
6850 zone->updatemethod);
6851 if (result != ISC_R_SUCCESS) {
6852 dns_zone_log(zone, ISC_LOG_ERROR,
6853 "zone_resigninc:update_soa_serial -> %s",
6854 dns_result_totext(result));
6855 goto failure;
6856 }
6857
6858 /*
6859 * Generate maximum life time signatures so that the above loop
6860 * termination is sensible.
6861 */
6862 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
6863 zonediff.diff, zone_keys, nkeys, zone->mctx,
6864 inception, soaexpire, check_ksk, keyset_kskonly);
6865 if (result != ISC_R_SUCCESS) {
6866 dns_zone_log(zone, ISC_LOG_ERROR,
6867 "zone_resigninc:add_sigs -> %s",
6868 dns_result_totext(result));
6869 goto failure;
6870 }
6871
6872 /* Write changes to journal file. */
6873 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
6874
6875 /* Everything has succeeded. Commit the changes. */
6876 dns_db_closeversion(db, &version, true);
6877
6878 failure:
6879 dns_diff_clear(&_sig_diff);
6880 for (i = 0; i < nkeys; i++)
6881 dst_key_free(&zone_keys[i]);
6882 if (version != NULL) {
6883 dns_db_closeversion(db, &version, false);
6884 dns_db_detach(&db);
6885 } else if (db != NULL)
6886 dns_db_detach(&db);
6887 if (result == ISC_R_SUCCESS) {
6888 set_resigntime(zone);
6889 LOCK_ZONE(zone);
6890 zone_needdump(zone, DNS_DUMP_DELAY);
6891 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6892 UNLOCK_ZONE(zone);
6893 } else {
6894 /*
6895 * Something failed. Retry in 5 minutes.
6896 */
6897 isc_interval_t ival;
6898 isc_interval_set(&ival, 300, 0);
6899 isc_time_nowplusinterval(&zone->resigntime, &ival);
6900 }
6901
6902 INSIST(version == NULL);
6903 }
6904
6905 static isc_result_t
6906 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
6907 dns_name_t *newname, bool bottom)
6908 {
6909 isc_result_t result;
6910 dns_dbiterator_t *dbit = NULL;
6911 dns_rdatasetiter_t *rdsit = NULL;
6912 dns_dbnode_t *node = NULL;
6913
6914 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
6915 CHECK(dns_dbiterator_seek(dbit, oldname));
6916 do {
6917 result = dns_dbiterator_next(dbit);
6918 if (result == ISC_R_NOMORE)
6919 CHECK(dns_dbiterator_first(dbit));
6920 CHECK(dns_dbiterator_current(dbit, &node, newname));
6921 if (bottom && dns_name_issubdomain(newname, oldname) &&
6922 !dns_name_equal(newname, oldname)) {
6923 dns_db_detachnode(db, &node);
6924 continue;
6925 }
6926 /*
6927 * Is this node empty?
6928 */
6929 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
6930 result = dns_rdatasetiter_first(rdsit);
6931 dns_db_detachnode(db, &node);
6932 dns_rdatasetiter_destroy(&rdsit);
6933 if (result != ISC_R_NOMORE)
6934 break;
6935 } while (1);
6936 failure:
6937 if (node != NULL)
6938 dns_db_detachnode(db, &node);
6939 if (dbit != NULL)
6940 dns_dbiterator_destroy(&dbit);
6941 return (result);
6942 }
6943
6944 static bool
6945 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
6946 dns_rdatatype_t type, dst_key_t *key)
6947 {
6948 isc_result_t result;
6949 dns_rdataset_t rdataset;
6950 dns_rdata_t rdata = DNS_RDATA_INIT;
6951 dns_rdata_rrsig_t rrsig;
6952
6953 dns_rdataset_init(&rdataset);
6954 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
6955 type, 0, &rdataset, NULL);
6956 if (result != ISC_R_SUCCESS) {
6957 INSIST(!dns_rdataset_isassociated(&rdataset));
6958 return (false);
6959 }
6960 for (result = dns_rdataset_first(&rdataset);
6961 result == ISC_R_SUCCESS;
6962 result = dns_rdataset_next(&rdataset)) {
6963 dns_rdataset_current(&rdataset, &rdata);
6964 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6965 INSIST(result == ISC_R_SUCCESS);
6966 if (rrsig.algorithm == dst_key_alg(key) &&
6967 rrsig.keyid == dst_key_id(key)) {
6968 dns_rdataset_disassociate(&rdataset);
6969 return (true);
6970 }
6971 dns_rdata_reset(&rdata);
6972 }
6973 dns_rdataset_disassociate(&rdataset);
6974 return (false);
6975 }
6976
6977 static isc_result_t
6978 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6979 dns_dbnode_t *node, dns_ttl_t ttl, bool bottom,
6980 dns_diff_t *diff)
6981 {
6982 dns_fixedname_t fixed;
6983 dns_name_t *next;
6984 dns_rdata_t rdata = DNS_RDATA_INIT;
6985 isc_result_t result;
6986 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
6987
6988 next = dns_fixedname_initname(&fixed);
6989
6990 CHECK(next_active(db, version, name, next, bottom));
6991 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
6992 &rdata));
6993 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
6994 &rdata));
6995 failure:
6996 return (result);
6997 }
6998
6999 static isc_result_t
7000 check_if_bottom_of_zone(dns_db_t *db, dns_dbnode_t *node,
7001 dns_dbversion_t *version, bool *is_bottom_of_zone)
7002 {
7003 isc_result_t result;
7004 dns_rdatasetiter_t *iterator = NULL;
7005 dns_rdataset_t rdataset;
7006 bool seen_soa = false, seen_ns = false, seen_dname = false;
7007
7008 REQUIRE(is_bottom_of_zone != NULL);
7009
7010 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7011 if (result != ISC_R_SUCCESS) {
7012 if (result == ISC_R_NOTFOUND) {
7013 result = ISC_R_SUCCESS;
7014 }
7015 return (result);
7016 }
7017
7018 dns_rdataset_init(&rdataset);
7019 for (result = dns_rdatasetiter_first(iterator);
7020 result == ISC_R_SUCCESS;
7021 result = dns_rdatasetiter_next(iterator)) {
7022 dns_rdatasetiter_current(iterator, &rdataset);
7023 switch (rdataset.type) {
7024 case dns_rdatatype_soa:
7025 seen_soa = true;
7026 break;
7027 case dns_rdatatype_ns:
7028 seen_ns = true;
7029 break;
7030 case dns_rdatatype_dname:
7031 seen_dname = true;
7032 break;
7033 }
7034 dns_rdataset_disassociate(&rdataset);
7035 }
7036 if (result != ISC_R_NOMORE) {
7037 goto failure;
7038 }
7039 if ((seen_ns && !seen_soa) || seen_dname) {
7040 *is_bottom_of_zone = true;
7041 }
7042 result = ISC_R_SUCCESS;
7043
7044 failure:
7045 dns_rdatasetiter_destroy(&iterator);
7046
7047 return (result);
7048 }
7049
7050 static isc_result_t
7051 sign_a_node(dns_db_t *db, dns_zone_t *zone, dns_name_t *name,
7052 dns_dbnode_t *node, dns_dbversion_t *version,
7053 bool build_nsec3, bool build_nsec, dst_key_t *key,
7054 isc_stdtime_t inception, isc_stdtime_t expire,
7055 unsigned int minimum, bool is_ksk,
7056 bool keyset_kskonly, bool is_bottom_of_zone,
7057 dns_diff_t *diff, int32_t *signatures, isc_mem_t *mctx)
7058 {
7059 isc_result_t result;
7060 dns_rdatasetiter_t *iterator = NULL;
7061 dns_rdataset_t rdataset;
7062 dns_rdata_t rdata = DNS_RDATA_INIT;
7063 dns_stats_t* dnssecsignstats;
7064 dns_stats_t* dnssecrefreshstats;
7065
7066 isc_buffer_t buffer;
7067 unsigned char data[1024];
7068 bool seen_soa, seen_ns, seen_rr, seen_nsec, seen_nsec3, seen_ds;
7069
7070 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7071 if (result != ISC_R_SUCCESS) {
7072 if (result == ISC_R_NOTFOUND)
7073 result = ISC_R_SUCCESS;
7074 return (result);
7075 }
7076
7077 dns_rdataset_init(&rdataset);
7078 isc_buffer_init(&buffer, data, sizeof(data));
7079 seen_rr = seen_soa = seen_ns = seen_nsec = seen_nsec3 = seen_ds = false;
7080 for (result = dns_rdatasetiter_first(iterator);
7081 result == ISC_R_SUCCESS;
7082 result = dns_rdatasetiter_next(iterator)) {
7083 dns_rdatasetiter_current(iterator, &rdataset);
7084 if (rdataset.type == dns_rdatatype_soa)
7085 seen_soa = true;
7086 else if (rdataset.type == dns_rdatatype_ns)
7087 seen_ns = true;
7088 else if (rdataset.type == dns_rdatatype_ds)
7089 seen_ds = true;
7090 else if (rdataset.type == dns_rdatatype_nsec)
7091 seen_nsec = true;
7092 else if (rdataset.type == dns_rdatatype_nsec3)
7093 seen_nsec3 = true;
7094 if (rdataset.type != dns_rdatatype_rrsig)
7095 seen_rr = true;
7096 dns_rdataset_disassociate(&rdataset);
7097 }
7098 if (result != ISC_R_NOMORE)
7099 goto failure;
7100 /*
7101 * Going from insecure to NSEC3.
7102 * Don't generate NSEC3 records for NSEC3 records.
7103 */
7104 if (build_nsec3 && !seen_nsec3 && seen_rr) {
7105 bool unsecure = !seen_ds && seen_ns && !seen_soa;
7106 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
7107 unsecure, diff));
7108 (*signatures)--;
7109 }
7110 /*
7111 * Going from insecure to NSEC.
7112 * Don't generate NSEC records for NSEC3 records.
7113 */
7114 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
7115 /*
7116 * Build a NSEC record except at the origin.
7117 */
7118 if (!dns_name_equal(name, dns_db_origin(db))) {
7119 CHECK(add_nsec(db, version, name, node, minimum,
7120 is_bottom_of_zone, diff));
7121 /* Count a NSEC generation as a signature generation. */
7122 (*signatures)--;
7123 }
7124 }
7125 result = dns_rdatasetiter_first(iterator);
7126 while (result == ISC_R_SUCCESS) {
7127 dns_rdatasetiter_current(iterator, &rdataset);
7128 if (rdataset.type == dns_rdatatype_soa ||
7129 rdataset.type == dns_rdatatype_rrsig)
7130 {
7131 goto next_rdataset;
7132 }
7133 if (rdataset.type == dns_rdatatype_dnskey ||
7134 rdataset.type == dns_rdatatype_cdnskey ||
7135 rdataset.type == dns_rdatatype_cds)
7136 {
7137 /*
7138 * CDS and CDNSKEY are signed with KSK like DNSKEY.
7139 * (RFC 7344, section 4.1 specifies that they must
7140 * be signed with a key in the current DS RRset,
7141 * which would only include KSK's.)
7142 */
7143 if (!is_ksk && keyset_kskonly) {
7144 goto next_rdataset;
7145 }
7146 } else if (is_ksk) {
7147 goto next_rdataset;
7148 }
7149 if (seen_ns && !seen_soa &&
7150 rdataset.type != dns_rdatatype_ds &&
7151 rdataset.type != dns_rdatatype_nsec)
7152 {
7153 goto next_rdataset;
7154 }
7155 if (signed_with_key(db, node, version, rdataset.type, key)) {
7156 goto next_rdataset;
7157 }
7158 /* Calculate the signature, creating a RRSIG RDATA. */
7159 isc_buffer_clear(&buffer);
7160 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
7161 &expire, mctx, &buffer, &rdata));
7162 /* Update the database and journal with the RRSIG. */
7163 /* XXX inefficient - will cause dataset merging */
7164 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
7165 name, rdataset.ttl, &rdata));
7166 dns_rdata_reset(&rdata);
7167
7168 /* Update DNSSEC sign statistics. */
7169 dnssecsignstats = dns_zone_getdnssecsignstats(zone);
7170 dnssecrefreshstats = dns_zone_getdnssecrefreshstats(zone);
7171 if (dnssecsignstats != NULL) {
7172 dns_dnssecsignstats_increment(
7173 dns_zone_getdnssecsignstats(zone),
7174 dst_key_id(key));
7175 }
7176 if (dnssecrefreshstats != NULL) {
7177 dns_dnssecsignstats_increment(
7178 dns_zone_getdnssecrefreshstats(zone),
7179 dst_key_id(key));
7180 }
7181
7182 (*signatures)--;
7183 next_rdataset:
7184 dns_rdataset_disassociate(&rdataset);
7185 result = dns_rdatasetiter_next(iterator);
7186 }
7187 if (result == ISC_R_NOMORE)
7188 result = ISC_R_SUCCESS;
7189 failure:
7190 if (dns_rdataset_isassociated(&rdataset))
7191 dns_rdataset_disassociate(&rdataset);
7192 if (iterator != NULL)
7193 dns_rdatasetiter_destroy(&iterator);
7194 return (result);
7195 }
7196
7197 /*
7198 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
7199 */
7200 static isc_result_t
7201 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
7202 dns_ttl_t minimum, bool update_only, dns_diff_t *diff)
7203 {
7204 isc_result_t result;
7205 dns_rdataset_t rdataset;
7206 dns_dbnode_t *node = NULL;
7207
7208 CHECK(dns_db_getoriginnode(db, &node));
7209 if (update_only) {
7210 dns_rdataset_init(&rdataset);
7211 result = dns_db_findrdataset(db, node, version,
7212 dns_rdatatype_nsec,
7213 dns_rdatatype_none,
7214 0, &rdataset, NULL);
7215 if (dns_rdataset_isassociated(&rdataset))
7216 dns_rdataset_disassociate(&rdataset);
7217 if (result == ISC_R_NOTFOUND)
7218 goto success;
7219 if (result != ISC_R_SUCCESS)
7220 goto failure;
7221 }
7222 CHECK(delete_nsec(db, version, node, name, diff));
7223 CHECK(add_nsec(db, version, name, node, minimum, false, diff));
7224 success:
7225 result = ISC_R_SUCCESS;
7226 failure:
7227 if (node != NULL)
7228 dns_db_detachnode(db, &node);
7229 return (result);
7230 }
7231
7232 static isc_result_t
7233 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
7234 dns_dbversion_t *version, bool build_nsec3,
7235 dns_ttl_t minimum, dns_diff_t *diff)
7236 {
7237 isc_result_t result;
7238 dns_dbnode_t *node = NULL;
7239 dns_rdataset_t rdataset;
7240 dns_rdata_t rdata = DNS_RDATA_INIT;
7241 unsigned char data[5];
7242 bool seen_done = false;
7243 bool have_rr = false;
7244
7245 dns_rdataset_init(&rdataset);
7246 result = dns_db_getoriginnode(signing->db, &node);
7247 if (result != ISC_R_SUCCESS)
7248 goto failure;
7249
7250 result = dns_db_findrdataset(signing->db, node, version,
7251 zone->privatetype, dns_rdatatype_none,
7252 0, &rdataset, NULL);
7253 if (result == ISC_R_NOTFOUND) {
7254 INSIST(!dns_rdataset_isassociated(&rdataset));
7255 result = ISC_R_SUCCESS;
7256 goto failure;
7257 }
7258 if (result != ISC_R_SUCCESS) {
7259 INSIST(!dns_rdataset_isassociated(&rdataset));
7260 goto failure;
7261 }
7262 for (result = dns_rdataset_first(&rdataset);
7263 result == ISC_R_SUCCESS;
7264 result = dns_rdataset_next(&rdataset)) {
7265 dns_rdataset_current(&rdataset, &rdata);
7266 /*
7267 * If we don't match the algorithm or keyid skip the record.
7268 */
7269 if (rdata.length != 5 ||
7270 rdata.data[0] != signing->algorithm ||
7271 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7272 rdata.data[2] != (signing->keyid & 0xff)) {
7273 have_rr = true;
7274 dns_rdata_reset(&rdata);
7275 continue;
7276 }
7277 /*
7278 * We have a match. If we were signing (!signing->deleteit)
7279 * and we already have a record indicating that we have
7280 * finished signing (rdata.data[4] != 0) then keep it.
7281 * Otherwise it needs to be deleted as we have removed all
7282 * the signatures (signing->deleteit), so any record indicating
7283 * completion is now out of date, or we have finished signing
7284 * with the new record so we no longer need to remember that
7285 * we need to sign the zone with the matching key across a
7286 * nameserver re-start.
7287 */
7288 if (!signing->deleteit && rdata.data[4] != 0) {
7289 seen_done = true;
7290 have_rr = true;
7291 } else
7292 CHECK(update_one_rr(signing->db, version, diff,
7293 DNS_DIFFOP_DEL, &zone->origin,
7294 rdataset.ttl, &rdata));
7295 dns_rdata_reset(&rdata);
7296 }
7297 if (result == ISC_R_NOMORE)
7298 result = ISC_R_SUCCESS;
7299 if (!signing->deleteit && !seen_done) {
7300 /*
7301 * If we were signing then we need to indicate that we have
7302 * finished signing the zone with this key. If it is already
7303 * there we don't need to add it a second time.
7304 */
7305 data[0] = signing->algorithm;
7306 data[1] = (signing->keyid >> 8) & 0xff;
7307 data[2] = signing->keyid & 0xff;
7308 data[3] = 0;
7309 data[4] = 1;
7310 rdata.length = sizeof(data);
7311 rdata.data = data;
7312 rdata.type = zone->privatetype;
7313 rdata.rdclass = dns_db_class(signing->db);
7314 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7315 &zone->origin, rdataset.ttl, &rdata));
7316 } else if (!have_rr) {
7317 dns_name_t *origin = dns_db_origin(signing->db);
7318 /*
7319 * Rebuild the NSEC/NSEC3 record for the origin as we no
7320 * longer have any private records.
7321 */
7322 if (build_nsec3)
7323 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7324 minimum, false, diff));
7325 CHECK(updatesecure(signing->db, version, origin, minimum,
7326 true, diff));
7327 }
7328
7329 failure:
7330 if (dns_rdataset_isassociated(&rdataset))
7331 dns_rdataset_disassociate(&rdataset);
7332 if (node != NULL)
7333 dns_db_detachnode(signing->db, &node);
7334 return (result);
7335 }
7336
7337 /*
7338 * Called from zone_nsec3chain() in order to update zone records indicating
7339 * processing status of given NSEC3 chain:
7340 *
7341 * - If the supplied dns_nsec3chain_t structure has been fully processed
7342 * (which is indicated by "active" being set to false):
7343 *
7344 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7345 *
7346 * - remove all private-type records containing NSEC3PARAM RDATA matching
7347 * the relevant NSEC3 chain.
7348 *
7349 * - If the supplied dns_nsec3chain_t structure has not been fully processed
7350 * (which is indicated by "active" being set to true), only remove the
7351 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7352 * "flags" field set to 0.
7353 *
7354 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7355 * in the relevant private-type record, but with the "flags" field set to
7356 * 0, indicating that this NSEC3 chain is now complete for this zone.
7357 *
7358 * Note that this function is called at different processing stages for NSEC3
7359 * chain additions vs. removals and needs to handle all cases properly.
7360 */
7361 static isc_result_t
7362 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7363 bool active, dns_rdatatype_t privatetype,
7364 dns_diff_t *diff)
7365 {
7366 dns_dbnode_t *node = NULL;
7367 dns_name_t *name = dns_db_origin(db);
7368 dns_rdata_t rdata = DNS_RDATA_INIT;
7369 dns_rdataset_t rdataset;
7370 dns_rdata_nsec3param_t nsec3param;
7371 isc_result_t result;
7372 isc_buffer_t buffer;
7373 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7374 dns_ttl_t ttl = 0;
7375 bool nseconly = false, nsec3ok = false;
7376
7377 dns_rdataset_init(&rdataset);
7378
7379 result = dns_db_getoriginnode(db, &node);
7380 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7381 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7382 0, 0, &rdataset, NULL);
7383 if (result == ISC_R_NOTFOUND)
7384 goto try_private;
7385 if (result != ISC_R_SUCCESS)
7386 goto failure;
7387
7388 /*
7389 * Preserve the existing ttl.
7390 */
7391 ttl = rdataset.ttl;
7392
7393 /*
7394 * Delete all NSEC3PARAM records which match that in nsec3chain.
7395 */
7396 for (result = dns_rdataset_first(&rdataset);
7397 result == ISC_R_SUCCESS;
7398 result = dns_rdataset_next(&rdataset)) {
7399
7400 dns_rdataset_current(&rdataset, &rdata);
7401 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7402
7403 if (nsec3param.hash != chain->nsec3param.hash ||
7404 (active && nsec3param.flags != 0) ||
7405 nsec3param.iterations != chain->nsec3param.iterations ||
7406 nsec3param.salt_length != chain->nsec3param.salt_length ||
7407 memcmp(nsec3param.salt, chain->nsec3param.salt,
7408 nsec3param.salt_length)) {
7409 dns_rdata_reset(&rdata);
7410 continue;
7411 }
7412
7413 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7414 name, rdataset.ttl, &rdata));
7415 dns_rdata_reset(&rdata);
7416 }
7417 if (result != ISC_R_NOMORE)
7418 goto failure;
7419
7420 dns_rdataset_disassociate(&rdataset);
7421
7422 try_private:
7423
7424 if (active)
7425 goto add;
7426
7427 result = dns_nsec_nseconly(db, ver, &nseconly);
7428 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
7429
7430 /*
7431 * Delete all private records which match that in nsec3chain.
7432 */
7433 result = dns_db_findrdataset(db, node, ver, privatetype,
7434 0, 0, &rdataset, NULL);
7435 if (result == ISC_R_NOTFOUND)
7436 goto add;
7437 if (result != ISC_R_SUCCESS)
7438 goto failure;
7439
7440 for (result = dns_rdataset_first(&rdataset);
7441 result == ISC_R_SUCCESS;
7442 result = dns_rdataset_next(&rdataset)) {
7443 dns_rdata_t private = DNS_RDATA_INIT;
7444 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
7445
7446 dns_rdataset_current(&rdataset, &private);
7447 if (!dns_nsec3param_fromprivate(&private, &rdata,
7448 buf, sizeof(buf)))
7449 continue;
7450 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7451
7452 if ((!nsec3ok &&
7453 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
7454 nsec3param.hash != chain->nsec3param.hash ||
7455 nsec3param.iterations != chain->nsec3param.iterations ||
7456 nsec3param.salt_length != chain->nsec3param.salt_length ||
7457 memcmp(nsec3param.salt, chain->nsec3param.salt,
7458 nsec3param.salt_length)) {
7459 dns_rdata_reset(&rdata);
7460 continue;
7461 }
7462
7463 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7464 name, rdataset.ttl, &private));
7465 dns_rdata_reset(&rdata);
7466 }
7467 if (result != ISC_R_NOMORE)
7468 goto failure;
7469
7470 add:
7471 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
7472 result = ISC_R_SUCCESS;
7473 goto failure;
7474 }
7475
7476 /*
7477 * Add a NSEC3PARAM record which matches that in nsec3chain but
7478 * with all flags bits cleared.
7479 *
7480 * Note: we do not clear chain->nsec3param.flags as this change
7481 * may be reversed.
7482 */
7483 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
7484 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
7485 dns_rdatatype_nsec3param,
7486 &chain->nsec3param, &buffer));
7487 rdata.data[1] = 0; /* Clear flag bits. */
7488 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
7489
7490 failure:
7491 dns_db_detachnode(db, &node);
7492 if (dns_rdataset_isassociated(&rdataset))
7493 dns_rdataset_disassociate(&rdataset);
7494 return (result);
7495 }
7496
7497 static isc_result_t
7498 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7499 dns_name_t *name, dns_diff_t *diff)
7500 {
7501 dns_rdataset_t rdataset;
7502 isc_result_t result;
7503
7504 dns_rdataset_init(&rdataset);
7505
7506 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7507 0, 0, &rdataset, NULL);
7508 if (result == ISC_R_NOTFOUND)
7509 return (ISC_R_SUCCESS);
7510 if (result != ISC_R_SUCCESS)
7511 return (result);
7512 for (result = dns_rdataset_first(&rdataset);
7513 result == ISC_R_SUCCESS;
7514 result = dns_rdataset_next(&rdataset)) {
7515 dns_rdata_t rdata = DNS_RDATA_INIT;
7516
7517 dns_rdataset_current(&rdataset, &rdata);
7518 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7519 rdataset.ttl, &rdata));
7520 }
7521 if (result == ISC_R_NOMORE)
7522 result = ISC_R_SUCCESS;
7523 failure:
7524 dns_rdataset_disassociate(&rdataset);
7525 return (result);
7526 }
7527
7528 static isc_result_t
7529 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7530 dns_name_t *name, const dns_rdata_nsec3param_t *param,
7531 dns_diff_t *diff)
7532 {
7533 dns_rdataset_t rdataset;
7534 dns_rdata_nsec3_t nsec3;
7535 isc_result_t result;
7536
7537 dns_rdataset_init(&rdataset);
7538 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
7539 0, 0, &rdataset, NULL);
7540 if (result == ISC_R_NOTFOUND)
7541 return (ISC_R_SUCCESS);
7542 if (result != ISC_R_SUCCESS)
7543 return (result);
7544
7545 for (result = dns_rdataset_first(&rdataset);
7546 result == ISC_R_SUCCESS;
7547 result = dns_rdataset_next(&rdataset)) {
7548 dns_rdata_t rdata = DNS_RDATA_INIT;
7549
7550 dns_rdataset_current(&rdataset, &rdata);
7551 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
7552 if (nsec3.hash != param->hash ||
7553 nsec3.iterations != param->iterations ||
7554 nsec3.salt_length != param->salt_length ||
7555 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
7556 continue;
7557 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7558 rdataset.ttl, &rdata));
7559 }
7560 if (result == ISC_R_NOMORE)
7561 result = ISC_R_SUCCESS;
7562 failure:
7563 dns_rdataset_disassociate(&rdataset);
7564 return (result);
7565 }
7566
7567 static isc_result_t
7568 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
7569 const dns_rdata_nsec3param_t *param,
7570 bool *answer)
7571 {
7572 dns_dbnode_t *node = NULL;
7573 dns_rdata_t rdata = DNS_RDATA_INIT;
7574 dns_rdata_nsec3param_t myparam;
7575 dns_rdataset_t rdataset;
7576 isc_result_t result;
7577
7578 *answer = false;
7579
7580 result = dns_db_getoriginnode(db, &node);
7581 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7582
7583 dns_rdataset_init(&rdataset);
7584
7585 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7586 0, 0, &rdataset, NULL);
7587 if (result == ISC_R_SUCCESS) {
7588 dns_rdataset_disassociate(&rdataset);
7589 dns_db_detachnode(db, &node);
7590 return (result);
7591 }
7592 if (result != ISC_R_NOTFOUND) {
7593 dns_db_detachnode(db, &node);
7594 return (result);
7595 }
7596
7597 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7598 0, 0, &rdataset, NULL);
7599 if (result == ISC_R_NOTFOUND) {
7600 *answer = true;
7601 dns_db_detachnode(db, &node);
7602 return (ISC_R_SUCCESS);
7603 }
7604 if (result != ISC_R_SUCCESS) {
7605 dns_db_detachnode(db, &node);
7606 return (result);
7607 }
7608
7609 for (result = dns_rdataset_first(&rdataset);
7610 result == ISC_R_SUCCESS;
7611 result = dns_rdataset_next(&rdataset)) {
7612 dns_rdataset_current(&rdataset, &rdata);
7613 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
7614 dns_rdata_reset(&rdata);
7615 /*
7616 * Ignore any NSEC3PARAM removals.
7617 */
7618 if (NSEC3REMOVE(myparam.flags))
7619 continue;
7620 /*
7621 * Ignore the chain that we are in the process of deleting.
7622 */
7623 if (myparam.hash == param->hash &&
7624 myparam.iterations == param->iterations &&
7625 myparam.salt_length == param->salt_length &&
7626 !memcmp(myparam.salt, param->salt, myparam.salt_length))
7627 continue;
7628 /*
7629 * Found an active NSEC3 chain.
7630 */
7631 break;
7632 }
7633 if (result == ISC_R_NOMORE) {
7634 *answer = true;
7635 result = ISC_R_SUCCESS;
7636 }
7637
7638 failure:
7639 if (dns_rdataset_isassociated(&rdataset))
7640 dns_rdataset_disassociate(&rdataset);
7641 dns_db_detachnode(db, &node);
7642 return (result);
7643 }
7644
7645 /*%
7646 * Given a tuple which is part of a diff, return a pointer to the next tuple in
7647 * that diff which has the same name and type (or NULL if no such tuple is
7648 * found).
7649 */
7650 static dns_difftuple_t *
7651 find_next_matching_tuple(dns_difftuple_t *cur) {
7652 dns_difftuple_t *next = cur;
7653
7654 while ((next = ISC_LIST_NEXT(next, link)) != NULL) {
7655 if (cur->rdata.type == next->rdata.type &&
7656 dns_name_equal(&cur->name, &next->name))
7657 {
7658 return (next);
7659 }
7660 }
7661
7662 return (NULL);
7663 }
7664
7665 /*%
7666 * Remove all tuples with the same name and type as 'cur' from 'src' and append
7667 * them to 'dst'.
7668 */
7669 static void
7670 move_matching_tuples(dns_difftuple_t *cur, dns_diff_t *src, dns_diff_t *dst) {
7671 do {
7672 dns_difftuple_t *next = find_next_matching_tuple(cur);
7673 ISC_LIST_UNLINK(src->tuples, cur, link);
7674 dns_diff_appendminimal(dst, &cur);
7675 cur = next;
7676 } while (cur != NULL);
7677 }
7678
7679 /*%
7680 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
7681 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
7682 * along with tuples representing relevant signature changes.
7683 */
7684 isc_result_t
7685 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
7686 dst_key_t *zone_keys[], unsigned int nkeys,
7687 dns_zone_t *zone, isc_stdtime_t inception,
7688 isc_stdtime_t expire, isc_stdtime_t keyexpire,
7689 isc_stdtime_t now, bool check_ksk,
7690 bool keyset_kskonly, dns__zonediff_t *zonediff)
7691 {
7692 dns_difftuple_t *tuple;
7693 isc_result_t result;
7694
7695 while ((tuple = ISC_LIST_HEAD(diff->tuples)) != NULL) {
7696 isc_stdtime_t exp = expire;
7697
7698 if (keyexpire != 0 &&
7699 (tuple->rdata.type == dns_rdatatype_dnskey ||
7700 tuple->rdata.type == dns_rdatatype_cdnskey ||
7701 tuple->rdata.type == dns_rdatatype_cds))
7702 {
7703 exp = keyexpire;
7704 }
7705
7706 result = del_sigs(zone, db, version, &tuple->name,
7707 tuple->rdata.type, zonediff,
7708 zone_keys, nkeys, now, false);
7709 if (result != ISC_R_SUCCESS) {
7710 dns_zone_log(zone, ISC_LOG_ERROR,
7711 "dns__zone_updatesigs:del_sigs -> %s",
7712 dns_result_totext(result));
7713 return (result);
7714 }
7715 result = add_sigs(db, version, &tuple->name, zone,
7716 tuple->rdata.type, zonediff->diff,
7717 zone_keys, nkeys, zone->mctx, inception,
7718 exp, check_ksk, keyset_kskonly);
7719 if (result != ISC_R_SUCCESS) {
7720 dns_zone_log(zone, ISC_LOG_ERROR,
7721 "dns__zone_updatesigs:add_sigs -> %s",
7722 dns_result_totext(result));
7723 return (result);
7724 }
7725
7726 /*
7727 * Signature changes for all RRs with name tuple->name and type
7728 * tuple->rdata.type were appended to zonediff->diff. Now we
7729 * remove all the "raw" changes with the same name and type
7730 * from diff (so that they are not processed by this loop
7731 * again) and append them to zonediff so that they get applied.
7732 */
7733 move_matching_tuples(tuple, diff, zonediff->diff);
7734 }
7735 return (ISC_R_SUCCESS);
7736 }
7737
7738 /*
7739 * Incrementally build and sign a new NSEC3 chain using the parameters
7740 * requested.
7741 */
7742 static void
7743 zone_nsec3chain(dns_zone_t *zone) {
7744 const char *me = "zone_nsec3chain";
7745 dns_db_t *db = NULL;
7746 dns_dbnode_t *node = NULL;
7747 dns_dbversion_t *version = NULL;
7748 dns_diff_t _sig_diff;
7749 dns_diff_t nsec_diff;
7750 dns_diff_t nsec3_diff;
7751 dns_diff_t param_diff;
7752 dns__zonediff_t zonediff;
7753 dns_fixedname_t fixed;
7754 dns_fixedname_t nextfixed;
7755 dns_name_t *name, *nextname;
7756 dns_rdataset_t rdataset;
7757 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
7758 dns_nsec3chainlist_t cleanup;
7759 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7760 int32_t signatures;
7761 bool check_ksk, keyset_kskonly;
7762 bool delegation;
7763 bool first;
7764 isc_result_t result;
7765 isc_stdtime_t now, inception, soaexpire, expire;
7766 uint32_t jitter, sigvalidityinterval, expiryinterval;
7767 unsigned int i;
7768 unsigned int nkeys = 0;
7769 uint32_t nodes;
7770 bool unsecure = false;
7771 bool seen_soa, seen_ns, seen_dname, seen_ds;
7772 bool seen_nsec, seen_nsec3, seen_rr;
7773 dns_rdatasetiter_t *iterator = NULL;
7774 bool buildnsecchain;
7775 bool updatensec = false;
7776 dns_rdatatype_t privatetype = zone->privatetype;
7777
7778 ENTER;
7779
7780 dns_rdataset_init(&rdataset);
7781 name = dns_fixedname_initname(&fixed);
7782 nextname = dns_fixedname_initname(&nextfixed);
7783 dns_diff_init(zone->mctx, ¶m_diff);
7784 dns_diff_init(zone->mctx, &nsec3_diff);
7785 dns_diff_init(zone->mctx, &nsec_diff);
7786 dns_diff_init(zone->mctx, &_sig_diff);
7787 zonediff_init(&zonediff, &_sig_diff);
7788 ISC_LIST_INIT(cleanup);
7789
7790 /*
7791 * Updates are disabled. Pause for 5 minutes.
7792 */
7793 if (zone->update_disabled) {
7794 result = ISC_R_FAILURE;
7795 goto failure;
7796 }
7797
7798 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7799 /*
7800 * This function is called when zone timer fires, after the latter gets
7801 * set by zone_addnsec3chain(). If the action triggering the call to
7802 * zone_addnsec3chain() is closely followed by a zone deletion request,
7803 * it might turn out that the timer thread will not be woken up until
7804 * after the zone is deleted by rmzone(), which calls dns_db_detach()
7805 * for zone->db, causing the latter to become NULL. Return immediately
7806 * if that happens.
7807 */
7808 if (zone->db != NULL) {
7809 dns_db_attach(zone->db, &db);
7810 }
7811 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7812 if (db == NULL) {
7813 return;
7814 }
7815
7816 result = dns_db_newversion(db, &version);
7817 if (result != ISC_R_SUCCESS) {
7818 dnssec_log(zone, ISC_LOG_ERROR,
7819 "zone_nsec3chain:dns_db_newversion -> %s",
7820 dns_result_totext(result));
7821 goto failure;
7822 }
7823
7824 isc_stdtime_get(&now);
7825
7826 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7827 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7828 if (result != ISC_R_SUCCESS) {
7829 dnssec_log(zone, ISC_LOG_ERROR,
7830 "zone_nsec3chain:dns__zone_findkeys -> %s",
7831 dns_result_totext(result));
7832 goto failure;
7833 }
7834
7835 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7836 inception = now - 3600; /* Allow for clock skew. */
7837 soaexpire = now + sigvalidityinterval;
7838 expiryinterval = dns_zone_getsigresigninginterval(zone);
7839 if (expiryinterval > sigvalidityinterval) {
7840 expiryinterval = sigvalidityinterval;
7841 } else {
7842 expiryinterval = sigvalidityinterval - expiryinterval;
7843 }
7844
7845 /*
7846 * Spread out signatures over time if they happen to be
7847 * clumped. We don't do this for each add_sigs() call as
7848 * we still want some clustering to occur.
7849 */
7850 if (sigvalidityinterval >= 3600U) {
7851 if (sigvalidityinterval > 7200U) {
7852 jitter = isc_random_uniform(expiryinterval);
7853 } else {
7854 jitter = isc_random_uniform(1200);
7855 }
7856 expire = soaexpire - jitter - 1;
7857 } else {
7858 expire = soaexpire - 1;
7859 }
7860
7861 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7862 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7863
7864 /*
7865 * We keep pulling nodes off each iterator in turn until
7866 * we have no more nodes to pull off or we reach the limits
7867 * for this quantum.
7868 */
7869 nodes = zone->nodes;
7870 signatures = zone->signatures;
7871 LOCK_ZONE(zone);
7872 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7873 UNLOCK_ZONE(zone);
7874 first = true;
7875
7876 if (nsec3chain != NULL) {
7877 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7878 }
7879 /*
7880 * Generate new NSEC3 chains first.
7881 *
7882 * The following while loop iterates over nodes in the zone database,
7883 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
7884 * them. Once all nodes are processed, the "delete_nsec" field is
7885 * consulted to check whether we are supposed to remove NSEC records
7886 * from the zone database; if so, the database iterator is reset to
7887 * point to the first node and the loop traverses all of them again,
7888 * this time removing NSEC records. If we hit a node which is obscured
7889 * by a delegation or a DNAME, nodes are skipped over until we find one
7890 * that is not obscured by the same obscuring name and then normal
7891 * processing is resumed.
7892 *
7893 * The above is repeated until all requested NSEC3 chain changes are
7894 * applied or when we reach the limits for this quantum, whichever
7895 * happens first.
7896 *
7897 * Note that the "signatures" variable is only used here to limit the
7898 * amount of work performed. Actual DNSSEC signatures are only
7899 * generated by dns__zone_updatesigs() calls later in this function.
7900 */
7901 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7902 LOCK_ZONE(zone);
7903 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7904
7905 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7906 if (nsec3chain->done || nsec3chain->db != zone->db) {
7907 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
7908 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7909 }
7910 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7911 UNLOCK_ZONE(zone);
7912 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
7913 goto next_addchain;
7914
7915 /*
7916 * Possible future db.
7917 */
7918 if (nsec3chain->db != db) {
7919 goto next_addchain;
7920 }
7921
7922 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
7923 goto next_addchain;
7924
7925 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
7926
7927 if (nsec3chain->delete_nsec) {
7928 delegation = false;
7929 dns_dbiterator_pause(nsec3chain->dbiterator);
7930 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
7931 goto next_addnode;
7932 }
7933 /*
7934 * On the first pass we need to check if the current node
7935 * has not been obscured.
7936 */
7937 delegation = false;
7938 unsecure = false;
7939 if (first) {
7940 dns_fixedname_t ffound;
7941 dns_name_t *found;
7942 found = dns_fixedname_initname(&ffound);
7943 result = dns_db_find(db, name, version,
7944 dns_rdatatype_soa,
7945 DNS_DBFIND_NOWILD, 0, NULL, found,
7946 NULL, NULL);
7947 if ((result == DNS_R_DELEGATION ||
7948 result == DNS_R_DNAME) &&
7949 !dns_name_equal(name, found)) {
7950 /*
7951 * Remember the obscuring name so that
7952 * we skip all obscured names.
7953 */
7954 dns_name_copynf(found, name);
7955 delegation = true;
7956 goto next_addnode;
7957 }
7958 }
7959
7960 /*
7961 * Check to see if this is a bottom of zone node.
7962 */
7963 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7964 if (result == ISC_R_NOTFOUND) {
7965 /* Empty node? */
7966 goto next_addnode;
7967 }
7968 if (result != ISC_R_SUCCESS) {
7969 goto failure;
7970 }
7971
7972 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec = false;
7973 for (result = dns_rdatasetiter_first(iterator);
7974 result == ISC_R_SUCCESS;
7975 result = dns_rdatasetiter_next(iterator))
7976 {
7977 dns_rdatasetiter_current(iterator, &rdataset);
7978 INSIST(rdataset.type != dns_rdatatype_nsec3);
7979 if (rdataset.type == dns_rdatatype_soa) {
7980 seen_soa = true;
7981 } else if (rdataset.type == dns_rdatatype_ns) {
7982 seen_ns = true;
7983 } else if (rdataset.type == dns_rdatatype_dname) {
7984 seen_dname = true;
7985 } else if (rdataset.type == dns_rdatatype_ds) {
7986 seen_ds = true;
7987 } else if (rdataset.type == dns_rdatatype_nsec) {
7988 seen_nsec = true;
7989 }
7990 dns_rdataset_disassociate(&rdataset);
7991 }
7992 dns_rdatasetiter_destroy(&iterator);
7993 /*
7994 * Is there a NSEC chain than needs to be cleaned up?
7995 */
7996 if (seen_nsec) {
7997 nsec3chain->seen_nsec = true;
7998 }
7999 if (seen_ns && !seen_soa && !seen_ds) {
8000 unsecure = true;
8001 }
8002 if ((seen_ns && !seen_soa) || seen_dname) {
8003 delegation = true;
8004 }
8005
8006 /*
8007 * Process one node.
8008 */
8009 dns_dbiterator_pause(nsec3chain->dbiterator);
8010 result = dns_nsec3_addnsec3(db, version, name,
8011 &nsec3chain->nsec3param,
8012 zone->minimum, unsecure,
8013 &nsec3_diff);
8014 if (result != ISC_R_SUCCESS) {
8015 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8016 "dns_nsec3_addnsec3 -> %s",
8017 dns_result_totext(result));
8018 goto failure;
8019 }
8020
8021 /*
8022 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
8023 * two signatures. Additionally there will, in general, be
8024 * two signature generated below.
8025 *
8026 * If we are only changing the optout flag the cost is half
8027 * that of the cost of generating a completely new chain.
8028 */
8029 signatures -= 4;
8030
8031 /*
8032 * Go onto next node.
8033 */
8034 next_addnode:
8035 first = false;
8036 dns_db_detachnode(db, &node);
8037 do {
8038 result = dns_dbiterator_next(nsec3chain->dbiterator);
8039
8040 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
8041 dns_dbiterator_pause(nsec3chain->dbiterator);
8042 CHECK(fixup_nsec3param(db, version, nsec3chain,
8043 false, privatetype,
8044 ¶m_diff));
8045 LOCK_ZONE(zone);
8046 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8047 link);
8048 UNLOCK_ZONE(zone);
8049 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8050 goto next_addchain;
8051 }
8052 if (result == ISC_R_NOMORE) {
8053 dns_dbiterator_pause(nsec3chain->dbiterator);
8054 if (nsec3chain->seen_nsec) {
8055 CHECK(fixup_nsec3param(db, version,
8056 nsec3chain,
8057 true,
8058 privatetype,
8059 ¶m_diff));
8060 nsec3chain->delete_nsec = true;
8061 goto same_addchain;
8062 }
8063 CHECK(fixup_nsec3param(db, version, nsec3chain,
8064 false, privatetype,
8065 ¶m_diff));
8066 LOCK_ZONE(zone);
8067 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8068 link);
8069 UNLOCK_ZONE(zone);
8070 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8071 goto next_addchain;
8072 } else if (result != ISC_R_SUCCESS) {
8073 dnssec_log(zone, ISC_LOG_ERROR,
8074 "zone_nsec3chain:"
8075 "dns_dbiterator_next -> %s",
8076 dns_result_totext(result));
8077 goto failure;
8078 } else if (delegation) {
8079 dns_dbiterator_current(nsec3chain->dbiterator,
8080 &node, nextname);
8081 dns_db_detachnode(db, &node);
8082 if (!dns_name_issubdomain(nextname, name))
8083 break;
8084 } else {
8085 break;
8086 }
8087 } while (1);
8088 continue;
8089
8090 same_addchain:
8091 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8092 first = true;
8093 continue;
8094
8095 next_addchain:
8096 dns_dbiterator_pause(nsec3chain->dbiterator);
8097 nsec3chain = nextnsec3chain;
8098 first = true;
8099 if (nsec3chain != NULL) {
8100 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
8101 }
8102 }
8103
8104 if (nsec3chain != NULL) {
8105 goto skip_removals;
8106 }
8107
8108 /*
8109 * Process removals.
8110 *
8111 * This is a counterpart of the above while loop which takes care of
8112 * removing an NSEC3 chain. It starts with determining whether the
8113 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
8114 * NSEC chain by iterating over all nodes in the zone database and only
8115 * then goes on to remove NSEC3 records be iterating over all nodes
8116 * again and calling deletematchingnsec3() for each of them; otherwise,
8117 * it starts removing NSEC3 records immediately. Rules for processing
8118 * obscured nodes and interrupting work are the same as for the while
8119 * loop above.
8120 */
8121 LOCK_ZONE(zone);
8122 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8123 UNLOCK_ZONE(zone);
8124 first = true;
8125 buildnsecchain = false;
8126 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
8127 LOCK_ZONE(zone);
8128 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
8129 UNLOCK_ZONE(zone);
8130
8131 if (nsec3chain->db != db) {
8132 goto next_removechain;
8133 }
8134
8135 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags)) {
8136 goto next_removechain;
8137 }
8138
8139 /*
8140 * Work out if we need to build a NSEC chain as a consequence
8141 * of removing this NSEC3 chain.
8142 */
8143 if (first && !updatensec &&
8144 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
8145 {
8146 result = need_nsec_chain(db, version,
8147 &nsec3chain->nsec3param,
8148 &buildnsecchain);
8149 if (result != ISC_R_SUCCESS) {
8150 dnssec_log(zone, ISC_LOG_ERROR,
8151 "zone_nsec3chain:"
8152 "need_nsec_chain -> %s",
8153 dns_result_totext(result));
8154 goto failure;
8155 }
8156 }
8157
8158 if (first) {
8159 dnssec_log(zone, ISC_LOG_DEBUG(3),
8160 "zone_nsec3chain:buildnsecchain = %u\n",
8161 buildnsecchain);
8162 }
8163
8164 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
8165 delegation = false;
8166
8167 if (!buildnsecchain) {
8168 /*
8169 * Delete the NSEC3PARAM record matching this chain.
8170 */
8171 if (first) {
8172 result = fixup_nsec3param(db, version,
8173 nsec3chain,
8174 true, privatetype,
8175 ¶m_diff);
8176 if (result != ISC_R_SUCCESS) {
8177 dnssec_log(zone, ISC_LOG_ERROR,
8178 "zone_nsec3chain:"
8179 "fixup_nsec3param -> %s",
8180 dns_result_totext(result));
8181 goto failure;
8182 }
8183 }
8184
8185 /*
8186 * Delete the NSEC3 records.
8187 */
8188 result = deletematchingnsec3(db, version, node, name,
8189 &nsec3chain->nsec3param,
8190 &nsec3_diff);
8191 if (result != ISC_R_SUCCESS) {
8192 dnssec_log(zone, ISC_LOG_ERROR,
8193 "zone_nsec3chain:"
8194 "deletematchingnsec3 -> %s",
8195 dns_result_totext(result));
8196 goto failure;
8197 }
8198 goto next_removenode;
8199 }
8200
8201 if (first) {
8202 dns_fixedname_t ffound;
8203 dns_name_t *found;
8204 found = dns_fixedname_initname(&ffound);
8205 result = dns_db_find(db, name, version,
8206 dns_rdatatype_soa,
8207 DNS_DBFIND_NOWILD, 0, NULL, found,
8208 NULL, NULL);
8209 if ((result == DNS_R_DELEGATION ||
8210 result == DNS_R_DNAME) &&
8211 !dns_name_equal(name, found))
8212 {
8213 /*
8214 * Remember the obscuring name so that
8215 * we skip all obscured names.
8216 */
8217 dns_name_copynf(found, name);
8218 delegation = true;
8219 goto next_removenode;
8220 }
8221 }
8222
8223 /*
8224 * Check to see if this is a bottom of zone node.
8225 */
8226 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8227 if (result == ISC_R_NOTFOUND) {
8228 /* Empty node? */
8229 goto next_removenode;
8230 }
8231 if (result != ISC_R_SUCCESS) {
8232 goto failure;
8233 }
8234
8235 seen_soa = seen_ns = seen_dname = seen_nsec3 =
8236 seen_nsec = seen_rr = false;
8237 for (result = dns_rdatasetiter_first(iterator);
8238 result == ISC_R_SUCCESS;
8239 result = dns_rdatasetiter_next(iterator))
8240 {
8241 dns_rdatasetiter_current(iterator, &rdataset);
8242 if (rdataset.type == dns_rdatatype_soa) {
8243 seen_soa = true;
8244 } else if (rdataset.type == dns_rdatatype_ns) {
8245 seen_ns = true;
8246 } else if (rdataset.type == dns_rdatatype_dname) {
8247 seen_dname = true;
8248 } else if (rdataset.type == dns_rdatatype_nsec) {
8249 seen_nsec = true;
8250 } else if (rdataset.type == dns_rdatatype_nsec3) {
8251 seen_nsec3 = true;
8252 } else if (rdataset.type != dns_rdatatype_rrsig) {
8253 seen_rr = true;
8254 }
8255 dns_rdataset_disassociate(&rdataset);
8256 }
8257 dns_rdatasetiter_destroy(&iterator);
8258
8259 if (!seen_rr || seen_nsec3 || seen_nsec) {
8260 goto next_removenode;
8261 }
8262 if ((seen_ns && !seen_soa) || seen_dname) {
8263 delegation = true;
8264 }
8265
8266 /*
8267 * Add a NSEC record except at the origin.
8268 */
8269 if (!dns_name_equal(name, dns_db_origin(db))) {
8270 dns_dbiterator_pause(nsec3chain->dbiterator);
8271 CHECK(add_nsec(db, version, name, node, zone->minimum,
8272 delegation, &nsec_diff));
8273 signatures--;
8274 }
8275
8276 next_removenode:
8277 first = false;
8278 dns_db_detachnode(db, &node);
8279 do {
8280 result = dns_dbiterator_next(nsec3chain->dbiterator);
8281 if (result == ISC_R_NOMORE && buildnsecchain) {
8282 /*
8283 * The NSEC chain should now be built.
8284 * We can now remove the NSEC3 chain.
8285 */
8286 updatensec = true;
8287 goto same_removechain;
8288 }
8289 if (result == ISC_R_NOMORE) {
8290 LOCK_ZONE(zone);
8291 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
8292 link);
8293 UNLOCK_ZONE(zone);
8294 ISC_LIST_APPEND(cleanup, nsec3chain, link);
8295 dns_dbiterator_pause(nsec3chain->dbiterator);
8296 result = fixup_nsec3param(db, version,
8297 nsec3chain, false,
8298 privatetype,
8299 ¶m_diff);
8300 if (result != ISC_R_SUCCESS) {
8301 dnssec_log(zone, ISC_LOG_ERROR,
8302 "zone_nsec3chain:"
8303 "fixup_nsec3param -> %s",
8304 dns_result_totext(result));
8305 goto failure;
8306 }
8307 goto next_removechain;
8308 } else if (result != ISC_R_SUCCESS) {
8309 dnssec_log(zone, ISC_LOG_ERROR,
8310 "zone_nsec3chain:"
8311 "dns_dbiterator_next -> %s",
8312 dns_result_totext(result));
8313 goto failure;
8314 } else if (delegation) {
8315 dns_dbiterator_current(nsec3chain->dbiterator,
8316 &node, nextname);
8317 dns_db_detachnode(db, &node);
8318 if (!dns_name_issubdomain(nextname, name)) {
8319 break;
8320 }
8321 } else {
8322 break;
8323 }
8324 } while (1);
8325 continue;
8326
8327 same_removechain:
8328 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
8329 buildnsecchain = false;
8330 first = true;
8331 continue;
8332
8333 next_removechain:
8334 dns_dbiterator_pause(nsec3chain->dbiterator);
8335 nsec3chain = nextnsec3chain;
8336 first = true;
8337 }
8338
8339 skip_removals:
8340 /*
8341 * We may need to update the NSEC/NSEC3 records for the zone apex.
8342 */
8343 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8344 bool rebuild_nsec = false,
8345 rebuild_nsec3 = false;
8346 result = dns_db_getoriginnode(db, &node);
8347 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8348 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8349 if (result != ISC_R_SUCCESS) {
8350 dnssec_log(zone, ISC_LOG_ERROR,
8351 "zone_nsec3chain:dns_db_allrdatasets -> %s",
8352 dns_result_totext(result));
8353 goto failure;
8354 }
8355 for (result = dns_rdatasetiter_first(iterator);
8356 result == ISC_R_SUCCESS;
8357 result = dns_rdatasetiter_next(iterator))
8358 {
8359 dns_rdatasetiter_current(iterator, &rdataset);
8360 if (rdataset.type == dns_rdatatype_nsec) {
8361 rebuild_nsec = true;
8362 } else if (rdataset.type == dns_rdatatype_nsec3param) {
8363 rebuild_nsec3 = true;
8364 }
8365 dns_rdataset_disassociate(&rdataset);
8366 }
8367 dns_rdatasetiter_destroy(&iterator);
8368 dns_db_detachnode(db, &node);
8369
8370 if (rebuild_nsec) {
8371 if (nsec3chain != NULL) {
8372 dns_dbiterator_pause(nsec3chain->dbiterator);
8373 }
8374
8375 result = updatesecure(db, version, &zone->origin,
8376 zone->minimum, true,
8377 &nsec_diff);
8378 if (result != ISC_R_SUCCESS) {
8379 dnssec_log(zone, ISC_LOG_ERROR,
8380 "zone_nsec3chain:updatesecure -> %s",
8381 dns_result_totext(result));
8382 goto failure;
8383 }
8384 }
8385
8386 if (rebuild_nsec3) {
8387 if (nsec3chain != NULL) {
8388 dns_dbiterator_pause(nsec3chain->dbiterator);
8389 }
8390
8391 result = dns_nsec3_addnsec3s(db, version,
8392 dns_db_origin(db),
8393 zone->minimum, false,
8394 &nsec3_diff);
8395 if (result != ISC_R_SUCCESS) {
8396 dnssec_log(zone, ISC_LOG_ERROR,
8397 "zone_nsec3chain:"
8398 "dns_nsec3_addnsec3s -> %s",
8399 dns_result_totext(result));
8400 goto failure;
8401 }
8402 }
8403 }
8404
8405 /*
8406 * Add / update signatures for the NSEC3 records.
8407 */
8408 if (nsec3chain != NULL) {
8409 dns_dbiterator_pause(nsec3chain->dbiterator);
8410 }
8411 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
8412 nkeys, zone, inception, expire, 0, now,
8413 check_ksk, keyset_kskonly, &zonediff);
8414 if (result != ISC_R_SUCCESS) {
8415 dnssec_log(zone, ISC_LOG_ERROR,
8416 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8417 dns_result_totext(result));
8418 goto failure;
8419 }
8420
8421 /*
8422 * We have changed the NSEC3PARAM or private RRsets
8423 * above so we need to update the signatures.
8424 */
8425 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
8426 nkeys, zone, inception, expire, 0, now,
8427 check_ksk, keyset_kskonly, &zonediff);
8428 if (result != ISC_R_SUCCESS) {
8429 dnssec_log(zone, ISC_LOG_ERROR,
8430 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8431 dns_result_totext(result));
8432 goto failure;
8433 }
8434
8435 if (updatensec) {
8436 result = updatesecure(db, version, &zone->origin,
8437 zone->minimum, false, &nsec_diff);
8438 if (result != ISC_R_SUCCESS) {
8439 dnssec_log(zone, ISC_LOG_ERROR,
8440 "zone_nsec3chain:updatesecure -> %s",
8441 dns_result_totext(result));
8442 goto failure;
8443 }
8444 }
8445
8446 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys,
8447 nkeys, zone, inception, expire, 0, now,
8448 check_ksk, keyset_kskonly, &zonediff);
8449 if (result != ISC_R_SUCCESS) {
8450 dnssec_log(zone, ISC_LOG_ERROR,
8451 "zone_nsec3chain:dns__zone_updatesigs -> %s",
8452 dns_result_totext(result));
8453 goto failure;
8454 }
8455
8456 /*
8457 * If we made no effective changes to the zone then we can just
8458 * cleanup otherwise we need to increment the serial.
8459 */
8460 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8461 /*
8462 * No need to call dns_db_closeversion() here as it is
8463 * called with commit = true below.
8464 */
8465 goto done;
8466 }
8467
8468 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8469 &zonediff, zone_keys, nkeys, now, false);
8470 if (result != ISC_R_SUCCESS) {
8471 dnssec_log(zone, ISC_LOG_ERROR,
8472 "zone_nsec3chain:del_sigs -> %s",
8473 dns_result_totext(result));
8474 goto failure;
8475 }
8476
8477 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
8478 zone->updatemethod);
8479 if (result != ISC_R_SUCCESS) {
8480 dnssec_log(zone, ISC_LOG_ERROR,
8481 "zone_nsec3chain:update_soa_serial -> %s",
8482 dns_result_totext(result));
8483 goto failure;
8484 }
8485
8486 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
8487 zonediff.diff, zone_keys, nkeys, zone->mctx,
8488 inception, soaexpire, check_ksk, keyset_kskonly);
8489 if (result != ISC_R_SUCCESS) {
8490 dnssec_log(zone, ISC_LOG_ERROR,
8491 "zone_nsec3chain:add_sigs -> %s",
8492 dns_result_totext(result));
8493 goto failure;
8494 }
8495
8496 /* Write changes to journal file. */
8497 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
8498
8499 LOCK_ZONE(zone);
8500 zone_needdump(zone, DNS_DUMP_DELAY);
8501 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8502 UNLOCK_ZONE(zone);
8503
8504 done:
8505 /*
8506 * Pause all iterators so that dns_db_closeversion() can succeed.
8507 */
8508 LOCK_ZONE(zone);
8509 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8510 nsec3chain != NULL;
8511 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8512 {
8513 dns_dbiterator_pause(nsec3chain->dbiterator);
8514 }
8515 UNLOCK_ZONE(zone);
8516
8517 /*
8518 * Everything has succeeded. Commit the changes.
8519 * Unconditionally commit as zonediff.offline not checked above.
8520 */
8521 dns_db_closeversion(db, &version, true);
8522
8523 /*
8524 * Everything succeeded so we can clean these up now.
8525 */
8526 nsec3chain = ISC_LIST_HEAD(cleanup);
8527 while (nsec3chain != NULL) {
8528 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8529 dns_db_detach(&nsec3chain->db);
8530 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8531 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8532 nsec3chain = ISC_LIST_HEAD(cleanup);
8533 }
8534
8535 set_resigntime(zone);
8536
8537 failure:
8538 if (result != ISC_R_SUCCESS) {
8539 dnssec_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
8540 dns_result_totext(result));
8541 }
8542
8543 /*
8544 * On error roll back the current nsec3chain.
8545 */
8546 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
8547 if (nsec3chain->done) {
8548 dns_db_detach(&nsec3chain->db);
8549 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8550 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8551 } else {
8552 result = dns_dbiterator_first(nsec3chain->dbiterator);
8553 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8554 dns_dbiterator_pause(nsec3chain->dbiterator);
8555 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8556 }
8557 }
8558
8559 /*
8560 * Rollback the cleanup list.
8561 */
8562 nsec3chain = ISC_LIST_TAIL(cleanup);
8563 while (nsec3chain != NULL) {
8564 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8565 if (nsec3chain->done) {
8566 dns_db_detach(&nsec3chain->db);
8567 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8568 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8569 } else {
8570 LOCK_ZONE(zone);
8571 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
8572 UNLOCK_ZONE(zone);
8573 result = dns_dbiterator_first(nsec3chain->dbiterator);
8574 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8575 dns_dbiterator_pause(nsec3chain->dbiterator);
8576 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8577 }
8578 nsec3chain = ISC_LIST_TAIL(cleanup);
8579 }
8580
8581 LOCK_ZONE(zone);
8582 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8583 nsec3chain != NULL;
8584 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8585 {
8586 dns_dbiterator_pause(nsec3chain->dbiterator);
8587 }
8588 UNLOCK_ZONE(zone);
8589
8590 dns_diff_clear(¶m_diff);
8591 dns_diff_clear(&nsec3_diff);
8592 dns_diff_clear(&nsec_diff);
8593 dns_diff_clear(&_sig_diff);
8594
8595 if (iterator != NULL) {
8596 dns_rdatasetiter_destroy(&iterator);
8597 }
8598
8599 for (i = 0; i < nkeys; i++) {
8600 dst_key_free(&zone_keys[i]);
8601 }
8602
8603 if (node != NULL) {
8604 dns_db_detachnode(db, &node);
8605 }
8606 if (version != NULL) {
8607 dns_db_closeversion(db, &version, false);
8608 dns_db_detach(&db);
8609 } else if (db != NULL) {
8610 dns_db_detach(&db);
8611 }
8612
8613 LOCK_ZONE(zone);
8614 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
8615 isc_interval_t interval;
8616 if (zone->update_disabled || result != ISC_R_SUCCESS) {
8617 isc_interval_set(&interval, 60, 0); /* 1 minute */
8618 } else {
8619 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
8620 }
8621 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
8622 } else {
8623 isc_time_settoepoch(&zone->nsec3chaintime);
8624 }
8625 UNLOCK_ZONE(zone);
8626
8627 INSIST(version == NULL);
8628 }
8629
8630 /*%
8631 * Delete all RRSIG records with the given algorithm and keyid.
8632 * Remove the NSEC record and RRSIGs if nkeys is zero.
8633 * If all remaining RRsets are signed with the given algorithm
8634 * set *has_algp to true.
8635 */
8636 static isc_result_t
8637 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
8638 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
8639 uint16_t keyid, bool *has_algp, dns_diff_t *diff)
8640 {
8641 dns_rdata_rrsig_t rrsig;
8642 dns_rdataset_t rdataset;
8643 dns_rdatasetiter_t *iterator = NULL;
8644 isc_result_t result;
8645 bool alg_missed = false;
8646 bool alg_found = false;
8647
8648 char namebuf[DNS_NAME_FORMATSIZE];
8649 dns_name_format(name, namebuf, sizeof(namebuf));
8650
8651 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8652 if (result != ISC_R_SUCCESS) {
8653 if (result == ISC_R_NOTFOUND)
8654 result = ISC_R_SUCCESS;
8655 return (result);
8656 }
8657
8658 dns_rdataset_init(&rdataset);
8659 for (result = dns_rdatasetiter_first(iterator);
8660 result == ISC_R_SUCCESS;
8661 result = dns_rdatasetiter_next(iterator)) {
8662 bool has_alg = false;
8663 dns_rdatasetiter_current(iterator, &rdataset);
8664 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
8665 for (result = dns_rdataset_first(&rdataset);
8666 result == ISC_R_SUCCESS;
8667 result = dns_rdataset_next(&rdataset)) {
8668 dns_rdata_t rdata = DNS_RDATA_INIT;
8669 dns_rdataset_current(&rdataset, &rdata);
8670 CHECK(update_one_rr(db, version, diff,
8671 DNS_DIFFOP_DEL, name,
8672 rdataset.ttl, &rdata));
8673 }
8674 if (result != ISC_R_NOMORE)
8675 goto failure;
8676 dns_rdataset_disassociate(&rdataset);
8677 continue;
8678 }
8679 if (rdataset.type != dns_rdatatype_rrsig) {
8680 dns_rdataset_disassociate(&rdataset);
8681 continue;
8682 }
8683 for (result = dns_rdataset_first(&rdataset);
8684 result == ISC_R_SUCCESS;
8685 result = dns_rdataset_next(&rdataset))
8686 {
8687 dns_rdata_t rdata = DNS_RDATA_INIT;
8688 dns_rdataset_current(&rdataset, &rdata);
8689 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
8690 if (nkeys != 0 &&
8691 (rrsig.algorithm != algorithm ||
8692 rrsig.keyid != keyid))
8693 {
8694 if (rrsig.algorithm == algorithm) {
8695 has_alg = true;
8696 }
8697 continue;
8698 }
8699 CHECK(update_one_rr(db, version, diff,
8700 DNS_DIFFOP_DELRESIGN, name,
8701 rdataset.ttl, &rdata));
8702 }
8703 dns_rdataset_disassociate(&rdataset);
8704 if (result != ISC_R_NOMORE)
8705 break;
8706
8707 /*
8708 * After deleting, if there's still a signature for
8709 * 'algorithm', set alg_found; if not, set alg_missed.
8710 */
8711 if (has_alg) {
8712 alg_found = true;
8713 } else {
8714 alg_missed = true;
8715 }
8716 }
8717 if (result == ISC_R_NOMORE)
8718 result = ISC_R_SUCCESS;
8719
8720 /*
8721 * Set `has_algp` if the algorithm was found in every RRset:
8722 * i.e., found in at least one, and not missing from any.
8723 */
8724 *has_algp = (alg_found && !alg_missed);
8725 failure:
8726 if (dns_rdataset_isassociated(&rdataset))
8727 dns_rdataset_disassociate(&rdataset);
8728 dns_rdatasetiter_destroy(&iterator);
8729 return (result);
8730 }
8731
8732 /*
8733 * Incrementally sign the zone using the keys requested.
8734 * Builds the NSEC chain if required.
8735 */
8736 static void
8737 zone_sign(dns_zone_t *zone) {
8738 const char *me = "zone_sign";
8739 dns_db_t *db = NULL;
8740 dns_dbnode_t *node = NULL;
8741 dns_dbversion_t *version = NULL;
8742 dns_diff_t _sig_diff;
8743 dns_diff_t post_diff;
8744 dns__zonediff_t zonediff;
8745 dns_fixedname_t fixed;
8746 dns_fixedname_t nextfixed;
8747 dns_name_t *name, *nextname;
8748 dns_rdataset_t rdataset;
8749 dns_signing_t *signing, *nextsigning;
8750 dns_signinglist_t cleanup;
8751 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8752 int32_t signatures;
8753 bool check_ksk, keyset_kskonly, is_ksk;
8754 bool with_ksk, with_zsk;
8755 bool commit = false;
8756 bool is_bottom_of_zone;
8757 bool build_nsec = false;
8758 bool build_nsec3 = false;
8759 bool first;
8760 isc_result_t result;
8761 isc_stdtime_t now, inception, soaexpire, expire;
8762 uint32_t jitter, sigvalidityinterval, expiryinterval;
8763 unsigned int i, j;
8764 unsigned int nkeys = 0;
8765 uint32_t nodes;
8766
8767 ENTER;
8768
8769 dns_rdataset_init(&rdataset);
8770 name = dns_fixedname_initname(&fixed);
8771 nextname = dns_fixedname_initname(&nextfixed);
8772 dns_diff_init(zone->mctx, &_sig_diff);
8773 dns_diff_init(zone->mctx, &post_diff);
8774 zonediff_init(&zonediff, &_sig_diff);
8775 ISC_LIST_INIT(cleanup);
8776
8777 /*
8778 * Updates are disabled. Pause for 1 minute.
8779 */
8780 if (zone->update_disabled) {
8781 result = ISC_R_FAILURE;
8782 goto cleanup;
8783 }
8784
8785 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8786 if (zone->db != NULL) {
8787 dns_db_attach(zone->db, &db);
8788 }
8789 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8790 if (db == NULL) {
8791 result = ISC_R_FAILURE;
8792 goto cleanup;
8793 }
8794
8795 result = dns_db_newversion(db, &version);
8796 if (result != ISC_R_SUCCESS) {
8797 dnssec_log(zone, ISC_LOG_ERROR,
8798 "zone_sign:dns_db_newversion -> %s",
8799 dns_result_totext(result));
8800 goto cleanup;
8801 }
8802
8803 isc_stdtime_get(&now);
8804
8805 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8806 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8807 if (result != ISC_R_SUCCESS) {
8808 dnssec_log(zone, ISC_LOG_ERROR,
8809 "zone_sign:dns__zone_findkeys -> %s",
8810 dns_result_totext(result));
8811 goto cleanup;
8812 }
8813
8814 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8815 inception = now - 3600; /* Allow for clock skew. */
8816 soaexpire = now + sigvalidityinterval;
8817 expiryinterval = dns_zone_getsigresigninginterval(zone);
8818 if (expiryinterval > sigvalidityinterval) {
8819 expiryinterval = sigvalidityinterval;
8820 } else {
8821 expiryinterval = sigvalidityinterval - expiryinterval;
8822 }
8823
8824 /*
8825 * Spread out signatures over time if they happen to be
8826 * clumped. We don't do this for each add_sigs() call as
8827 * we still want some clustering to occur.
8828 */
8829 if (sigvalidityinterval >= 3600U) {
8830 if (sigvalidityinterval > 7200U) {
8831 jitter = isc_random_uniform(expiryinterval);
8832 } else {
8833 jitter = isc_random_uniform(1200);
8834 }
8835 expire = soaexpire - jitter - 1;
8836 } else {
8837 expire = soaexpire - 1;
8838 }
8839
8840 /*
8841 * We keep pulling nodes off each iterator in turn until
8842 * we have no more nodes to pull off or we reach the limits
8843 * for this quantum.
8844 */
8845 nodes = zone->nodes;
8846 signatures = zone->signatures;
8847 signing = ISC_LIST_HEAD(zone->signing);
8848 first = true;
8849
8850 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8851 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8852
8853 /* Determine which type of chain to build */
8854 CHECK(dns_private_chains(db, version, zone->privatetype,
8855 &build_nsec, &build_nsec3));
8856
8857 /* If neither chain is found, default to NSEC */
8858 if (!build_nsec && !build_nsec3) {
8859 build_nsec = true;
8860 }
8861
8862 while (signing != NULL && nodes-- > 0 && signatures > 0) {
8863 bool has_alg = false;
8864 nextsigning = ISC_LIST_NEXT(signing, link);
8865
8866 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8867 if (signing->done || signing->db != zone->db) {
8868 /*
8869 * The zone has been reloaded. We will have
8870 * created new signings as part of the reload
8871 * process so we can destroy this one.
8872 */
8873 ISC_LIST_UNLINK(zone->signing, signing, link);
8874 ISC_LIST_APPEND(cleanup, signing, link);
8875 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8876 goto next_signing;
8877 }
8878 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8879
8880 if (signing->db != db) {
8881 goto next_signing;
8882 }
8883
8884 is_bottom_of_zone = false;
8885
8886 if (first && signing->deleteit) {
8887 /*
8888 * Remove the key we are deleting from consideration.
8889 */
8890 for (i = 0, j = 0; i < nkeys; i++) {
8891 /*
8892 * Find the key we want to remove.
8893 */
8894 if (ALG(zone_keys[i]) == signing->algorithm &&
8895 dst_key_id(zone_keys[i]) == signing->keyid)
8896 {
8897 if (KSK(zone_keys[i]))
8898 dst_key_free(&zone_keys[i]);
8899 continue;
8900 }
8901 zone_keys[j] = zone_keys[i];
8902 j++;
8903 }
8904 for (i = j; i < nkeys; i++) {
8905 zone_keys[i] = NULL;
8906 }
8907 nkeys = j;
8908 }
8909
8910 dns_dbiterator_current(signing->dbiterator, &node, name);
8911
8912 if (signing->deleteit) {
8913 dns_dbiterator_pause(signing->dbiterator);
8914 CHECK(del_sig(db, version, name, node, nkeys,
8915 signing->algorithm, signing->keyid,
8916 &has_alg, zonediff.diff));
8917 }
8918
8919 /*
8920 * On the first pass we need to check if the current node
8921 * has not been obscured.
8922 */
8923 if (first) {
8924 dns_fixedname_t ffound;
8925 dns_name_t *found;
8926 found = dns_fixedname_initname(&ffound);
8927 result = dns_db_find(db, name, version,
8928 dns_rdatatype_soa,
8929 DNS_DBFIND_NOWILD, 0, NULL, found,
8930 NULL, NULL);
8931 if ((result == DNS_R_DELEGATION ||
8932 result == DNS_R_DNAME) &&
8933 !dns_name_equal(name, found))
8934 {
8935 /*
8936 * Remember the obscuring name so that
8937 * we skip all obscured names.
8938 */
8939 dns_name_copynf(found, name);
8940 is_bottom_of_zone = true;
8941 goto next_node;
8942 }
8943 }
8944
8945 /*
8946 * Process one node.
8947 */
8948 with_ksk = false;
8949 with_zsk = false;
8950 dns_dbiterator_pause(signing->dbiterator);
8951
8952 CHECK(check_if_bottom_of_zone(db, node, version,
8953 &is_bottom_of_zone));
8954
8955 for (i = 0; !has_alg && i < nkeys; i++) {
8956 bool both = false;
8957
8958 /*
8959 * Find the keys we want to sign with.
8960 */
8961 if (!dst_key_isprivate(zone_keys[i])) {
8962 continue;
8963 }
8964 if (dst_key_inactive(zone_keys[i])) {
8965 continue;
8966 }
8967
8968 /*
8969 * When adding look for the specific key.
8970 */
8971 if (!signing->deleteit &&
8972 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
8973 dst_key_id(zone_keys[i]) != signing->keyid))
8974 {
8975 continue;
8976 }
8977
8978 /*
8979 * When deleting make sure we are properly signed
8980 * with the algorithm that was being removed.
8981 */
8982 if (signing->deleteit &&
8983 ALG(zone_keys[i]) != signing->algorithm)
8984 {
8985 continue;
8986 }
8987
8988 /*
8989 * Do we do KSK processing?
8990 */
8991 if (check_ksk && !REVOKE(zone_keys[i])) {
8992 bool have_ksk, have_nonksk;
8993 if (KSK(zone_keys[i])) {
8994 have_ksk = true;
8995 have_nonksk = false;
8996 } else {
8997 have_ksk = false;
8998 have_nonksk = true;
8999 }
9000 for (j = 0; j < nkeys; j++) {
9001 if (j == i ||
9002 (ALG(zone_keys[i]) !=
9003 ALG(zone_keys[j])))
9004 {
9005 continue;
9006 }
9007 /* Don't consider inactive keys, however
9008 * the key may be temporary offline, so do
9009 * consider keys which private key files are
9010 * unavailable.
9011 */
9012 if (dst_key_inactive(zone_keys[j])) {
9013 continue;
9014 }
9015 if (REVOKE(zone_keys[j])) {
9016 continue;
9017 }
9018 if (KSK(zone_keys[j])) {
9019 have_ksk = true;
9020 } else {
9021 have_nonksk = true;
9022 }
9023 both = have_ksk && have_nonksk;
9024 if (both) {
9025 break;
9026 }
9027 }
9028 }
9029 if (both || REVOKE(zone_keys[i])) {
9030 is_ksk = KSK(zone_keys[i]);
9031 } else {
9032 is_ksk = false;
9033 }
9034
9035 /*
9036 * If deleting signatures, we need to ensure that
9037 * the RRset is still signed at least once by a
9038 * KSK and a ZSK.
9039 */
9040 if (signing->deleteit && !is_ksk && with_zsk) {
9041 continue;
9042 }
9043
9044 if (signing->deleteit && is_ksk && with_ksk) {
9045 continue;
9046 }
9047
9048 CHECK(sign_a_node(db, zone, name, node, version,
9049 build_nsec3, build_nsec,
9050 zone_keys[i], inception, expire,
9051 zone->minimum, is_ksk,
9052 (both && keyset_kskonly),
9053 is_bottom_of_zone, zonediff.diff,
9054 &signatures, zone->mctx));
9055 /*
9056 * If we are adding we are done. Look for other keys
9057 * of the same algorithm if deleting.
9058 */
9059 if (!signing->deleteit) {
9060 break;
9061 }
9062 if (!is_ksk) {
9063 with_zsk = true;
9064 }
9065 if (KSK(zone_keys[i])) {
9066 with_ksk = true;
9067 }
9068 }
9069
9070 /*
9071 * Go onto next node.
9072 */
9073 next_node:
9074 first = false;
9075 dns_db_detachnode(db, &node);
9076 do {
9077 result = dns_dbiterator_next(signing->dbiterator);
9078 if (result == ISC_R_NOMORE) {
9079 ISC_LIST_UNLINK(zone->signing, signing, link);
9080 ISC_LIST_APPEND(cleanup, signing, link);
9081 dns_dbiterator_pause(signing->dbiterator);
9082 if (nkeys != 0 && build_nsec) {
9083 /*
9084 * We have finished regenerating the
9085 * zone with a zone signing key.
9086 * The NSEC chain is now complete and
9087 * there is a full set of signatures
9088 * for the zone. We can now clear the
9089 * OPT bit from the NSEC record.
9090 */
9091 result = updatesecure(db, version,
9092 &zone->origin,
9093 zone->minimum,
9094 false,
9095 &post_diff);
9096 if (result != ISC_R_SUCCESS) {
9097 dnssec_log(zone, ISC_LOG_ERROR,
9098 "updatesecure -> %s",
9099 dns_result_totext(result));
9100 goto cleanup;
9101 }
9102 }
9103 result = updatesignwithkey(zone, signing,
9104 version,
9105 build_nsec3,
9106 zone->minimum,
9107 &post_diff);
9108 if (result != ISC_R_SUCCESS) {
9109 dnssec_log(zone, ISC_LOG_ERROR,
9110 "updatesignwithkey -> %s",
9111 dns_result_totext(result));
9112 goto cleanup;
9113 }
9114 build_nsec = false;
9115 goto next_signing;
9116 } else if (result != ISC_R_SUCCESS) {
9117 dnssec_log(zone, ISC_LOG_ERROR,
9118 "zone_sign:"
9119 "dns_dbiterator_next -> %s",
9120 dns_result_totext(result));
9121 goto cleanup;
9122 } else if (is_bottom_of_zone) {
9123 dns_dbiterator_current(signing->dbiterator,
9124 &node, nextname);
9125 dns_db_detachnode(db, &node);
9126 if (!dns_name_issubdomain(nextname, name)) {
9127 break;
9128 }
9129 } else {
9130 break;
9131 }
9132 } while (1);
9133 continue;
9134
9135 next_signing:
9136 dns_dbiterator_pause(signing->dbiterator);
9137 signing = nextsigning;
9138 first = true;
9139 }
9140
9141 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
9142 result = dns__zone_updatesigs(&post_diff, db, version,
9143 zone_keys, nkeys, zone,
9144 inception, expire, 0, now,
9145 check_ksk, keyset_kskonly,
9146 &zonediff);
9147 if (result != ISC_R_SUCCESS) {
9148 dnssec_log(zone, ISC_LOG_ERROR,
9149 "zone_sign:dns__zone_updatesigs -> %s",
9150 dns_result_totext(result));
9151 goto cleanup;
9152 }
9153 }
9154
9155 /*
9156 * Have we changed anything?
9157 */
9158 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
9159 if (zonediff.offline) {
9160 commit = true;
9161 }
9162 result = ISC_R_SUCCESS;
9163 goto pauseall;
9164 }
9165
9166 commit = true;
9167
9168 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
9169 &zonediff, zone_keys, nkeys, now, false);
9170 if (result != ISC_R_SUCCESS) {
9171 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:del_sigs -> %s",
9172 dns_result_totext(result));
9173 goto cleanup;
9174 }
9175
9176 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
9177 zone->updatemethod);
9178 if (result != ISC_R_SUCCESS) {
9179 dnssec_log(zone, ISC_LOG_ERROR,
9180 "zone_sign:update_soa_serial -> %s",
9181 dns_result_totext(result));
9182 goto cleanup;
9183 }
9184
9185 /*
9186 * Generate maximum life time signatures so that the above loop
9187 * termination is sensible.
9188 */
9189 result = add_sigs(db, version, &zone->origin, zone, dns_rdatatype_soa,
9190 zonediff.diff, zone_keys, nkeys, zone->mctx,
9191 inception, soaexpire, check_ksk, keyset_kskonly);
9192 if (result != ISC_R_SUCCESS) {
9193 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign:add_sigs -> %s",
9194 dns_result_totext(result));
9195 goto cleanup;
9196 }
9197
9198 /*
9199 * Write changes to journal file.
9200 */
9201 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
9202
9203 pauseall:
9204 /*
9205 * Pause all iterators so that dns_db_closeversion() can succeed.
9206 */
9207 for (signing = ISC_LIST_HEAD(zone->signing);
9208 signing != NULL;
9209 signing = ISC_LIST_NEXT(signing, link))
9210 {
9211 dns_dbiterator_pause(signing->dbiterator);
9212 }
9213
9214 for (signing = ISC_LIST_HEAD(cleanup);
9215 signing != NULL;
9216 signing = ISC_LIST_NEXT(signing, link))
9217 {
9218 dns_dbiterator_pause(signing->dbiterator);
9219 }
9220
9221 /*
9222 * Everything has succeeded. Commit the changes.
9223 */
9224 dns_db_closeversion(db, &version, commit);
9225
9226 /*
9227 * Everything succeeded so we can clean these up now.
9228 */
9229 signing = ISC_LIST_HEAD(cleanup);
9230 while (signing != NULL) {
9231 ISC_LIST_UNLINK(cleanup, signing, link);
9232 dns_db_detach(&signing->db);
9233 dns_dbiterator_destroy(&signing->dbiterator);
9234 isc_mem_put(zone->mctx, signing, sizeof *signing);
9235 signing = ISC_LIST_HEAD(cleanup);
9236 }
9237
9238 set_resigntime(zone);
9239
9240 if (commit) {
9241 LOCK_ZONE(zone);
9242 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
9243 zone_needdump(zone, DNS_DUMP_DELAY);
9244 UNLOCK_ZONE(zone);
9245 }
9246
9247 failure:
9248 if (result != ISC_R_SUCCESS) {
9249 dnssec_log(zone, ISC_LOG_ERROR, "zone_sign: failed: %s",
9250 dns_result_totext(result));
9251 }
9252
9253 cleanup:
9254 /*
9255 * Pause all dbiterators.
9256 */
9257 for (signing = ISC_LIST_HEAD(zone->signing);
9258 signing != NULL;
9259 signing = ISC_LIST_NEXT(signing, link))
9260 {
9261 dns_dbiterator_pause(signing->dbiterator);
9262 }
9263
9264 /*
9265 * Rollback the cleanup list.
9266 */
9267 signing = ISC_LIST_HEAD(cleanup);
9268 while (signing != NULL) {
9269 ISC_LIST_UNLINK(cleanup, signing, link);
9270 ISC_LIST_PREPEND(zone->signing, signing, link);
9271 dns_dbiterator_first(signing->dbiterator);
9272 dns_dbiterator_pause(signing->dbiterator);
9273 signing = ISC_LIST_HEAD(cleanup);
9274 }
9275
9276 dns_diff_clear(&_sig_diff);
9277
9278 for (i = 0; i < nkeys; i++) {
9279 dst_key_free(&zone_keys[i]);
9280 }
9281
9282 if (node != NULL) {
9283 dns_db_detachnode(db, &node);
9284 }
9285
9286 if (version != NULL) {
9287 dns_db_closeversion(db, &version, false);
9288 dns_db_detach(&db);
9289 } else if (db != NULL) {
9290 dns_db_detach(&db);
9291 }
9292
9293 if (ISC_LIST_HEAD(zone->signing) != NULL) {
9294 isc_interval_t interval;
9295 if (zone->update_disabled || result != ISC_R_SUCCESS) {
9296 isc_interval_set(&interval, 60, 0); /* 1 minute */
9297 } else {
9298 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
9299 }
9300 isc_time_nowplusinterval(&zone->signingtime, &interval);
9301 } else {
9302 isc_time_settoepoch(&zone->signingtime);
9303 }
9304
9305 INSIST(version == NULL);
9306 }
9307
9308 static isc_result_t
9309 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
9310 unsigned char *data, int size)
9311 {
9312 dns_rdata_dnskey_t dnskey;
9313 dns_rdata_keydata_t keydata;
9314 isc_buffer_t buf;
9315 isc_result_t result;
9316
9317 dns_rdata_reset(target);
9318 isc_buffer_init(&buf, data, size);
9319
9320 switch (rr->type) {
9321 case dns_rdatatype_dnskey:
9322 result = dns_rdata_tostruct(rr, &dnskey, NULL);
9323 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9324 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
9325 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9326 &dnskey, &buf);
9327 break;
9328 case dns_rdatatype_keydata:
9329 result = dns_rdata_tostruct(rr, &keydata, NULL);
9330 if (result == ISC_R_UNEXPECTEDEND)
9331 return (result);
9332 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9333 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9334 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
9335 &dnskey, &buf);
9336 break;
9337 default:
9338 INSIST(0);
9339 ISC_UNREACHABLE();
9340 }
9341 return (ISC_R_SUCCESS);
9342 }
9343
9344 /*
9345 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
9346 * a KEYDATA rdataset from the key zone.
9347 *
9348 * 'rr' contains either a DNSKEY record, or a KEYDATA record
9349 *
9350 * After normalizing keys to the same format (DNSKEY, with revoke bit
9351 * cleared), return true if a key that matches 'rr' is found in
9352 * 'rdset', or false if not.
9353 */
9354
9355 static bool
9356 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
9357 unsigned char data1[4096], data2[4096];
9358 dns_rdata_t rdata, rdata1, rdata2;
9359 isc_result_t result;
9360
9361 dns_rdata_init(&rdata);
9362 dns_rdata_init(&rdata1);
9363 dns_rdata_init(&rdata2);
9364
9365 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
9366 if (result != ISC_R_SUCCESS)
9367 return (false);
9368
9369 for (result = dns_rdataset_first(rdset);
9370 result == ISC_R_SUCCESS;
9371 result = dns_rdataset_next(rdset)) {
9372 dns_rdata_reset(&rdata);
9373 dns_rdataset_current(rdset, &rdata);
9374 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
9375 if (result != ISC_R_SUCCESS)
9376 continue;
9377 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
9378 return (true);
9379 }
9380
9381 return (false);
9382 }
9383
9384 /*
9385 * Calculate the refresh interval for a keydata zone, per
9386 * RFC5011: MAX(1 hr,
9387 * MIN(15 days,
9388 * 1/2 * OrigTTL,
9389 * 1/2 * RRSigExpirationInterval))
9390 * or for retries: MAX(1 hr,
9391 * MIN(1 day,
9392 * 1/10 * OrigTTL,
9393 * 1/10 * RRSigExpirationInterval))
9394 */
9395 static inline isc_stdtime_t
9396 refresh_time(dns_keyfetch_t *kfetch, bool retry) {
9397 isc_result_t result;
9398 uint32_t t;
9399 dns_rdataset_t *rdset;
9400 dns_rdata_t sigrr = DNS_RDATA_INIT;
9401 dns_rdata_sig_t sig;
9402 isc_stdtime_t now;
9403
9404 isc_stdtime_get(&now);
9405
9406 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
9407 rdset = &kfetch->dnskeysigset;
9408 else
9409 return (now + dns_zone_mkey_hour);
9410
9411 result = dns_rdataset_first(rdset);
9412 if (result != ISC_R_SUCCESS)
9413 return (now + dns_zone_mkey_hour);
9414
9415 dns_rdataset_current(rdset, &sigrr);
9416 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9417 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9418
9419 if (!retry) {
9420 t = sig.originalttl / 2;
9421
9422 if (isc_serial_gt(sig.timeexpire, now)) {
9423 uint32_t exp = (sig.timeexpire - now) / 2;
9424 if (t > exp)
9425 t = exp;
9426 }
9427
9428 if (t > (15 * dns_zone_mkey_day))
9429 t = (15 * dns_zone_mkey_day);
9430
9431 if (t < dns_zone_mkey_hour)
9432 t = dns_zone_mkey_hour;
9433 } else {
9434 t = sig.originalttl / 10;
9435
9436 if (isc_serial_gt(sig.timeexpire, now)) {
9437 uint32_t exp = (sig.timeexpire - now) / 10;
9438 if (t > exp)
9439 t = exp;
9440 }
9441
9442 if (t > dns_zone_mkey_day)
9443 t = dns_zone_mkey_day;
9444
9445 if (t < dns_zone_mkey_hour)
9446 t = dns_zone_mkey_hour;
9447 }
9448
9449 return (now + t);
9450 }
9451
9452 /*
9453 * This routine is called when no changes are needed in a KEYDATA
9454 * record except to simply update the refresh timer. Caller should
9455 * hold zone lock.
9456 */
9457 static isc_result_t
9458 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
9459 {
9460 isc_result_t result;
9461 isc_buffer_t keyb;
9462 unsigned char key_buf[4096];
9463 dns_rdata_t rdata = DNS_RDATA_INIT;
9464 dns_rdata_keydata_t keydata;
9465 dns_name_t *name;
9466 dns_zone_t *zone = kfetch->zone;
9467 isc_stdtime_t now;
9468
9469 name = dns_fixedname_name(&kfetch->name);
9470 isc_stdtime_get(&now);
9471
9472 for (result = dns_rdataset_first(&kfetch->keydataset);
9473 result == ISC_R_SUCCESS;
9474 result = dns_rdataset_next(&kfetch->keydataset)) {
9475 dns_rdata_reset(&rdata);
9476 dns_rdataset_current(&kfetch->keydataset, &rdata);
9477
9478 /* Delete old version */
9479 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
9480 name, 0, &rdata));
9481
9482 /* Update refresh timer */
9483 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
9484 if (result == ISC_R_UNEXPECTEDEND)
9485 continue;
9486 if (result != ISC_R_SUCCESS)
9487 goto failure;
9488 keydata.refresh = refresh_time(kfetch, true);
9489 set_refreshkeytimer(zone, &keydata, now, false);
9490
9491 dns_rdata_reset(&rdata);
9492 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9493 CHECK(dns_rdata_fromstruct(&rdata,
9494 zone->rdclass, dns_rdatatype_keydata,
9495 &keydata, &keyb));
9496
9497 /* Insert updated version */
9498 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
9499 name, 0, &rdata));
9500 }
9501 result = ISC_R_SUCCESS;
9502 failure:
9503 return (result);
9504 }
9505
9506 /*
9507 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
9508 */
9509 static bool
9510 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
9511 isc_result_t result;
9512 dns_name_t *keyname;
9513 isc_mem_t *mctx;
9514 dns_rdata_t sigrr = DNS_RDATA_INIT;
9515 dns_rdata_t rr = DNS_RDATA_INIT;
9516 dns_rdata_rrsig_t sig;
9517 dns_rdata_dnskey_t dnskey;
9518 dst_key_t *dstkey = NULL;
9519 unsigned char key_buf[4096];
9520 isc_buffer_t keyb;
9521 bool answer = false;
9522
9523 REQUIRE(kfetch != NULL && keydata != NULL);
9524 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
9525
9526 keyname = dns_fixedname_name(&kfetch->name);
9527 mctx = kfetch->zone->view->mctx;
9528
9529 /* Generate a key from keydata */
9530 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9531 dns_keydata_todnskey(keydata, &dnskey, NULL);
9532 dns_rdata_fromstruct(&rr, keydata->common.rdclass,
9533 dns_rdatatype_dnskey, &dnskey, &keyb);
9534 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
9535 if (result != ISC_R_SUCCESS) {
9536 return (false);
9537 }
9538
9539 /* See if that key generated any of the signatures */
9540 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9541 result == ISC_R_SUCCESS;
9542 result = dns_rdataset_next(&kfetch->dnskeysigset))
9543 {
9544 dns_fixedname_t fixed;
9545 dns_fixedname_init(&fixed);
9546
9547 dns_rdata_reset(&sigrr);
9548 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9549 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9550 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9551
9552 if (dst_key_alg(dstkey) == sig.algorithm &&
9553 dst_key_rid(dstkey) == sig.keyid)
9554 {
9555 result = dns_dnssec_verify(keyname,
9556 &kfetch->dnskeyset,
9557 dstkey, false, 0, mctx,
9558 &sigrr,
9559 dns_fixedname_name(&fixed));
9560
9561 dnssec_log(kfetch->zone, ISC_LOG_DEBUG(3),
9562 "Confirm revoked DNSKEY is self-signed: %s",
9563 dns_result_totext(result));
9564
9565 if (result == ISC_R_SUCCESS) {
9566 answer = true;
9567 break;
9568 }
9569 }
9570 }
9571
9572 dst_key_free(&dstkey);
9573 return (answer);
9574 }
9575
9576 /*
9577 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
9578 * anchors are being managed; scan the keyset, and update the key zone and the
9579 * local trust anchors according to RFC5011.
9580 */
9581 static void
9582 keyfetch_done(isc_task_t *task, isc_event_t *event) {
9583 isc_result_t result, eresult;
9584 dns_fetchevent_t *devent;
9585 dns_keyfetch_t *kfetch;
9586 dns_zone_t *zone;
9587 isc_mem_t *mctx = NULL;
9588 dns_keytable_t *secroots = NULL;
9589 dns_dbversion_t *ver = NULL;
9590 dns_diff_t diff;
9591 bool alldone = false;
9592 bool commit = false;
9593 dns_name_t *keyname;
9594 dns_rdata_t sigrr = DNS_RDATA_INIT;
9595 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
9596 dns_rdata_t keydatarr = DNS_RDATA_INIT;
9597 dns_rdata_rrsig_t sig;
9598 dns_rdata_dnskey_t dnskey;
9599 dns_rdata_keydata_t keydata;
9600 bool initializing;
9601 char namebuf[DNS_NAME_FORMATSIZE];
9602 unsigned char key_buf[4096];
9603 isc_buffer_t keyb;
9604 dst_key_t *dstkey;
9605 isc_stdtime_t now;
9606 int pending = 0;
9607 bool secure = false, initial = false;
9608 bool free_needed;
9609
9610 UNUSED(task);
9611 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
9612 INSIST(event->ev_arg != NULL);
9613
9614 kfetch = event->ev_arg;
9615 zone = kfetch->zone;
9616 isc_mem_attach(zone->mctx, &mctx);
9617 keyname = dns_fixedname_name(&kfetch->name);
9618
9619 devent = (dns_fetchevent_t *) event;
9620 eresult = devent->result;
9621
9622 /* Free resources which are not of interest */
9623 if (devent->node != NULL) {
9624 dns_db_detachnode(devent->db, &devent->node);
9625 }
9626 if (devent->db != NULL) {
9627 dns_db_detach(&devent->db);
9628 }
9629 isc_event_free(&event);
9630 dns_resolver_destroyfetch(&kfetch->fetch);
9631
9632 LOCK_ZONE(zone);
9633 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL) {
9634 goto cleanup;
9635 }
9636
9637 isc_stdtime_get(&now);
9638 dns_name_format(keyname, namebuf, sizeof(namebuf));
9639
9640 result = dns_view_getsecroots(zone->view, &secroots);
9641 INSIST(result == ISC_R_SUCCESS);
9642
9643 dns_diff_init(mctx, &diff);
9644
9645 CHECK(dns_db_newversion(kfetch->db, &ver));
9646
9647 zone->refreshkeycount--;
9648 alldone = (zone->refreshkeycount == 0);
9649
9650 if (alldone) {
9651 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
9652 }
9653
9654 dnssec_log(zone, ISC_LOG_DEBUG(3),
9655 "Returned from key fetch in keyfetch_done() for '%s': %s",
9656 namebuf, dns_result_totext(eresult));
9657
9658 /* Fetch failed */
9659 if (eresult != ISC_R_SUCCESS ||
9660 !dns_rdataset_isassociated(&kfetch->dnskeyset))
9661 {
9662 dnssec_log(zone, ISC_LOG_WARNING,
9663 "Unable to fetch DNSKEY set '%s': %s",
9664 namebuf, dns_result_totext(eresult));
9665 CHECK(minimal_update(kfetch, ver, &diff));
9666 goto done;
9667 }
9668
9669 /* No RRSIGs found */
9670 if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
9671 dnssec_log(zone, ISC_LOG_WARNING,
9672 "No DNSKEY RRSIGs found for '%s': %s",
9673 namebuf, dns_result_totext(eresult));
9674 CHECK(minimal_update(kfetch, ver, &diff));
9675 goto done;
9676 }
9677
9678 /*
9679 * Clear any cached trust level, as we need to run validation
9680 * over again; trusted keys might have changed.
9681 */
9682 kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
9683
9684 /*
9685 * Validate the dnskeyset against the current trusted keys.
9686 */
9687 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9688 result == ISC_R_SUCCESS;
9689 result = dns_rdataset_next(&kfetch->dnskeysigset))
9690 {
9691 dns_keynode_t *keynode = NULL;
9692
9693 dns_rdata_reset(&sigrr);
9694 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9695 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9696 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9697
9698 result = dns_keytable_find(secroots, keyname, &keynode);
9699 while (result == ISC_R_SUCCESS) {
9700 dns_keynode_t *nextnode = NULL;
9701 dns_fixedname_t fixed;
9702 dns_fixedname_init(&fixed);
9703
9704 dstkey = dns_keynode_key(keynode);
9705 if (dstkey == NULL) {
9706 /* fail_secure() was called */
9707 break;
9708 }
9709
9710 if (dst_key_alg(dstkey) == sig.algorithm &&
9711 dst_key_id(dstkey) == sig.keyid)
9712 {
9713 result = dns_dnssec_verify(keyname,
9714 &kfetch->dnskeyset,
9715 dstkey, false,
9716 0,
9717 zone->view->mctx,
9718 &sigrr,
9719 dns_fixedname_name(
9720 &fixed));
9721
9722 dnssec_log(zone, ISC_LOG_DEBUG(3),
9723 "Verifying DNSKEY set for zone "
9724 "'%s' using key %d/%d: %s",
9725 namebuf, sig.keyid, sig.algorithm,
9726 dns_result_totext(result));
9727
9728 if (result == ISC_R_SUCCESS) {
9729 kfetch->dnskeyset.trust =
9730 dns_trust_secure;
9731 kfetch->dnskeysigset.trust =
9732 dns_trust_secure;
9733 secure = true;
9734 initial = dns_keynode_initial(keynode);
9735 dns_keynode_trust(keynode);
9736 break;
9737 }
9738 }
9739
9740 result = dns_keytable_nextkeynode(secroots,
9741 keynode, &nextnode);
9742 dns_keytable_detachkeynode(secroots, &keynode);
9743 keynode = nextnode;
9744 }
9745
9746 if (keynode != NULL) {
9747 dns_keytable_detachkeynode(secroots, &keynode);
9748 }
9749
9750 if (secure) {
9751 break;
9752 }
9753 }
9754
9755 /*
9756 * If we were not able to verify the answer using the current
9757 * trusted keys then all we can do is look at any revoked keys.
9758 */
9759 if (!secure) {
9760 dnssec_log(zone, ISC_LOG_INFO,
9761 "DNSKEY set for zone '%s' could not be verified "
9762 "with current keys", namebuf);
9763 }
9764
9765 /*
9766 * First scan keydataset to find keys that are not in dnskeyset
9767 * - Missing keys which are not scheduled for removal,
9768 * log a warning
9769 * - Missing keys which are scheduled for removal and
9770 * the remove hold-down timer has completed should
9771 * be removed from the key zone
9772 * - Missing keys whose acceptance timers have not yet
9773 * completed, log a warning and reset the acceptance
9774 * timer to 30 days in the future
9775 * - All keys not being removed have their refresh timers
9776 * updated
9777 */
9778 initializing = true;
9779 for (result = dns_rdataset_first(&kfetch->keydataset);
9780 result == ISC_R_SUCCESS;
9781 result = dns_rdataset_next(&kfetch->keydataset))
9782 {
9783 dns_keytag_t keytag;
9784
9785 dns_rdata_reset(&keydatarr);
9786 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9787 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9788 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9789
9790 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9791 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9792 if (result != ISC_R_SUCCESS) {
9793 /*
9794 * Skip if we cannot compute the key tag.
9795 * This may happen if the algorithm is unsupported
9796 */
9797 dns_zone_log(zone, ISC_LOG_ERROR,
9798 "Cannot compute tag for key in zone %s: %s "
9799 "(skipping)",
9800 namebuf, dns_result_totext(result));
9801 continue;
9802 }
9803 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9804
9805 /*
9806 * If any keydata record has a nonzero add holddown, then
9807 * there was a pre-existing trust anchor for this domain;
9808 * that means we are *not* initializing it and shouldn't
9809 * automatically trust all the keys we find at the zone apex.
9810 */
9811 initializing = initializing && (keydata.addhd == 0);
9812
9813 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
9814 bool deletekey = false;
9815
9816 if (!secure) {
9817 if (keydata.removehd != 0 &&
9818 keydata.removehd <= now)
9819 {
9820 deletekey = true;
9821 }
9822 } else if (keydata.addhd == 0) {
9823 deletekey = true;
9824 } else if (keydata.addhd > now) {
9825 dnssec_log(zone, ISC_LOG_INFO,
9826 "Pending key %d for zone %s "
9827 "unexpectedly missing "
9828 "restarting 30-day acceptance "
9829 "timer", keytag, namebuf);
9830 if (keydata.addhd < now + dns_zone_mkey_month) {
9831 keydata.addhd =
9832 now + dns_zone_mkey_month;
9833 }
9834 keydata.refresh = refresh_time(kfetch, false);
9835 } else if (keydata.removehd == 0) {
9836 dnssec_log(zone, ISC_LOG_INFO,
9837 "Active key %d for zone %s "
9838 "unexpectedly missing",
9839 keytag, namebuf);
9840 keydata.refresh = now + dns_zone_mkey_hour;
9841 } else if (keydata.removehd <= now) {
9842 deletekey = true;
9843 dnssec_log(zone, ISC_LOG_INFO,
9844 "Revoked key %d for zone %s "
9845 "missing: deleting from "
9846 "managed keys database",
9847 keytag, namebuf);
9848 } else {
9849 keydata.refresh = refresh_time(kfetch, false);
9850 }
9851
9852 if (secure || deletekey) {
9853 /* Delete old version */
9854 CHECK(update_one_rr(kfetch->db, ver, &diff,
9855 DNS_DIFFOP_DEL, keyname, 0,
9856 &keydatarr));
9857 }
9858
9859 if (!secure || deletekey) {
9860 continue;
9861 }
9862
9863 dns_rdata_reset(&keydatarr);
9864 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9865 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9866 dns_rdatatype_keydata,
9867 &keydata, &keyb);
9868
9869 /* Insert updated version */
9870 CHECK(update_one_rr(kfetch->db, ver, &diff,
9871 DNS_DIFFOP_ADD, keyname, 0,
9872 &keydatarr));
9873
9874 set_refreshkeytimer(zone, &keydata, now, false);
9875 }
9876 }
9877
9878 /*
9879 * Next scan dnskeyset:
9880 * - If new keys are found (i.e., lacking a match in keydataset)
9881 * add them to the key zone and set the acceptance timer
9882 * to 30 days in the future (or to immediately if we've
9883 * determined that we're initializing the zone for the
9884 * first time)
9885 * - Previously-known keys that have been revoked
9886 * must be scheduled for removal from the key zone (or,
9887 * if they hadn't been accepted as trust anchors yet
9888 * anyway, removed at once)
9889 * - Previously-known unrevoked keys whose acceptance timers
9890 * have completed are promoted to trust anchors
9891 * - All keys not being removed have their refresh
9892 * timers updated
9893 */
9894 for (result = dns_rdataset_first(&kfetch->dnskeyset);
9895 result == ISC_R_SUCCESS;
9896 result = dns_rdataset_next(&kfetch->dnskeyset))
9897 {
9898 bool revoked = false;
9899 bool newkey = false;
9900 bool updatekey = false;
9901 bool deletekey = false;
9902 bool trustkey = false;
9903 dns_keytag_t keytag;
9904
9905 dns_rdata_reset(&dnskeyrr);
9906 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
9907 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9908 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9909
9910 /* Skip ZSK's */
9911 if ((dnskey.flags & DNS_KEYFLAG_KSK) == 0) {
9912 continue;
9913 }
9914
9915 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9916 if (result != ISC_R_SUCCESS) {
9917 /*
9918 * Skip if we cannot compute the key tag.
9919 * This may happen if the algorithm is unsupported
9920 */
9921 dns_zone_log(zone, ISC_LOG_ERROR,
9922 "Cannot compute tag for key in zone %s: %s "
9923 "(skipping)",
9924 namebuf, dns_result_totext(result));
9925 continue;
9926 }
9927 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9928
9929 revoked = ((dnskey.flags & DNS_KEYFLAG_REVOKE) != 0);
9930
9931 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
9932 dns_rdata_reset(&keydatarr);
9933 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9934 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9935 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9936
9937 if (revoked && revocable(kfetch, &keydata)) {
9938 if (keydata.addhd > now) {
9939 /*
9940 * Key wasn't trusted yet, and now
9941 * it's been revoked? Just remove it
9942 */
9943 deletekey = true;
9944 dnssec_log(zone, ISC_LOG_INFO,
9945 "Pending key %d for "
9946 "zone %s is now revoked: "
9947 "deleting from the "
9948 "managed keys database",
9949 keytag, namebuf);
9950 } else if (keydata.removehd == 0) {
9951 /*
9952 * Remove key from secroots.
9953 */
9954 dns_view_untrust(zone->view, keyname,
9955 &dnskey, mctx);
9956
9957 /* If initializing, delete now */
9958 if (keydata.addhd == 0) {
9959 deletekey = true;
9960 } else {
9961 keydata.removehd = now +
9962 dns_zone_mkey_month;
9963 keydata.flags |=
9964 DNS_KEYFLAG_REVOKE;
9965 }
9966
9967 dnssec_log(zone, ISC_LOG_INFO,
9968 "Trusted key %d for "
9969 "zone %s is now revoked",
9970 keytag, namebuf);
9971 } else if (keydata.removehd < now) {
9972 /* Scheduled for removal */
9973 deletekey = true;
9974
9975 dnssec_log(zone, ISC_LOG_INFO,
9976 "Revoked key %d for "
9977 "zone %s removal timer "
9978 "complete: deleting from "
9979 "the managed keys database",
9980 keytag, namebuf);
9981 }
9982 } else if (revoked && keydata.removehd == 0) {
9983 dnssec_log(zone, ISC_LOG_WARNING,
9984 "Active key %d for zone "
9985 "%s is revoked but "
9986 "did not self-sign; "
9987 "ignoring", keytag, namebuf);
9988 continue;
9989 } else if (secure) {
9990 if (keydata.removehd != 0) {
9991 /*
9992 * Key isn't revoked--but it
9993 * seems it used to be.
9994 * Remove it now and add it
9995 * back as if it were a fresh key,
9996 * with a 30-day acceptance timer.
9997 */
9998 deletekey = true;
9999 newkey = true;
10000 keydata.removehd = 0;
10001 keydata.addhd =
10002 now + dns_zone_mkey_month;
10003
10004 dnssec_log(zone, ISC_LOG_INFO,
10005 "Revoked key %d for "
10006 "zone %s has returned: "
10007 "starting 30-day "
10008 "acceptance timer",
10009 keytag, namebuf);
10010 } else if (keydata.addhd > now) {
10011 pending++;
10012 } else if (keydata.addhd == 0) {
10013 keydata.addhd = now;
10014 }
10015
10016 if (keydata.addhd <= now) {
10017 trustkey = true;
10018 dnssec_log(zone, ISC_LOG_INFO,
10019 "Key %d for zone %s "
10020 "is now trusted (%s)",
10021 keytag, namebuf,
10022 initial
10023 ? "initializing key "
10024 "verified"
10025 : "acceptance timer "
10026 "complete");
10027 }
10028 } else if (keydata.addhd > now) {
10029 /*
10030 * Not secure, and key is pending:
10031 * reset the acceptance timer
10032 */
10033 pending++;
10034 keydata.addhd = now + dns_zone_mkey_month;
10035 dnssec_log(zone, ISC_LOG_INFO,
10036 "Pending key %d "
10037 "for zone %s was "
10038 "not validated: restarting "
10039 "30-day acceptance timer",
10040 keytag, namebuf);
10041 }
10042
10043 if (!deletekey && !newkey) {
10044 updatekey = true;
10045 }
10046 } else if (secure) {
10047 /*
10048 * Key wasn't in the key zone but it's
10049 * revoked now anyway, so just skip it
10050 */
10051 if (revoked) {
10052 continue;
10053 }
10054
10055 /* Key wasn't in the key zone: add it */
10056 newkey = true;
10057
10058 if (initializing) {
10059 dnssec_log(zone, ISC_LOG_WARNING,
10060 "Initializing automatic trust "
10061 "anchor management for zone '%s'; "
10062 "DNSKEY ID %d is now trusted, "
10063 "waiving the normal 30-day "
10064 "waiting period.",
10065 namebuf, keytag);
10066 trustkey = true;
10067 } else {
10068 dnssec_log(zone, ISC_LOG_INFO,
10069 "New key %d observed "
10070 "for zone '%s': "
10071 "starting 30-day "
10072 "acceptance timer",
10073 keytag, namebuf);
10074 }
10075 } else {
10076 /*
10077 * No previously known key, and the key is not
10078 * secure, so skip it.
10079 */
10080 continue;
10081 }
10082
10083 /* Delete old version */
10084 if (deletekey || !newkey) {
10085 CHECK(update_one_rr(kfetch->db, ver, &diff,
10086 DNS_DIFFOP_DEL, keyname, 0,
10087 &keydatarr));
10088 }
10089
10090 if (updatekey) {
10091 /* Set refresh timer */
10092 keydata.refresh = refresh_time(kfetch, false);
10093 dns_rdata_reset(&keydatarr);
10094 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10095 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10096 dns_rdatatype_keydata,
10097 &keydata, &keyb);
10098
10099 /* Insert updated version */
10100 CHECK(update_one_rr(kfetch->db, ver, &diff,
10101 DNS_DIFFOP_ADD, keyname, 0,
10102 &keydatarr));
10103 } else if (newkey) {
10104 /* Convert DNSKEY to KEYDATA */
10105 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10106 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10107 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
10108 NULL);
10109 keydata.addhd = initializing
10110 ? now : now + dns_zone_mkey_month;
10111 keydata.refresh = refresh_time(kfetch, false);
10112 dns_rdata_reset(&keydatarr);
10113 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
10114 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
10115 dns_rdatatype_keydata,
10116 &keydata, &keyb);
10117
10118 /* Insert into key zone */
10119 CHECK(update_one_rr(kfetch->db, ver, &diff,
10120 DNS_DIFFOP_ADD, keyname, 0,
10121 &keydatarr));
10122 }
10123
10124 if (trustkey) {
10125 /* Trust this key. */
10126 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
10127 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10128 trust_key(zone, keyname, &dnskey, false, mctx);
10129 }
10130
10131 if (secure && !deletekey) {
10132 INSIST(newkey || updatekey);
10133 set_refreshkeytimer(zone, &keydata, now, false);
10134 }
10135 }
10136
10137 /*
10138 * RFC5011 says, "A trust point that has all of its trust anchors
10139 * revoked is considered deleted and is treated as if the trust
10140 * point was never configured." But if someone revoked their
10141 * active key before the standby was trusted, that would mean the
10142 * zone would suddenly be nonsecured. We avoid this by checking to
10143 * see if there's pending keydata. If so, we put a null key in
10144 * the security roots; then all queries to the zone will fail.
10145 */
10146 if (pending != 0) {
10147 fail_secure(zone, keyname);
10148 }
10149
10150 done:
10151 if (!ISC_LIST_EMPTY(diff.tuples)) {
10152 /* Write changes to journal file. */
10153 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
10154 zone->updatemethod));
10155 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
10156 commit = true;
10157
10158 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10159 zone_needdump(zone, 30);
10160 } else if (result == ISC_R_NOMORE) {
10161 /*
10162 * If "updatekey" was true for all keys found in the DNSKEY
10163 * response and the previous update of those keys happened
10164 * during the same second (only possible if a key refresh was
10165 * externally triggered), it may happen that all relevant
10166 * update_one_rr() calls will return ISC_R_SUCCESS, but
10167 * diff.tuples will remain empty. Reset result to
10168 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
10169 */
10170 result = ISC_R_SUCCESS;
10171 }
10172
10173 failure:
10174 if (result != ISC_R_SUCCESS) {
10175 dnssec_log(zone, ISC_LOG_ERROR,
10176 "error during managed-keys processing (%s): "
10177 "DNSSEC validation may be at risk",
10178 isc_result_totext(result));
10179 }
10180 dns_diff_clear(&diff);
10181 if (ver != NULL) {
10182 dns_db_closeversion(kfetch->db, &ver, commit);
10183 }
10184
10185 cleanup:
10186 dns_db_detach(&kfetch->db);
10187
10188 INSIST(zone->irefs > 0);
10189 zone->irefs--;
10190 kfetch->zone = NULL;
10191
10192 if (dns_rdataset_isassociated(&kfetch->keydataset)) {
10193 dns_rdataset_disassociate(&kfetch->keydataset);
10194 }
10195 if (dns_rdataset_isassociated(&kfetch->dnskeyset)) {
10196 dns_rdataset_disassociate(&kfetch->dnskeyset);
10197 }
10198 if (dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
10199 dns_rdataset_disassociate(&kfetch->dnskeysigset);
10200 }
10201
10202 dns_name_free(keyname, mctx);
10203 isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
10204 isc_mem_detach(&mctx);
10205
10206 if (secroots != NULL) {
10207 dns_keytable_detach(&secroots);
10208 }
10209
10210 free_needed = exit_check(zone);
10211 UNLOCK_ZONE(zone);
10212 if (free_needed) {
10213 zone_free(zone);
10214 }
10215
10216 INSIST(ver == NULL);
10217 }
10218
10219 /*
10220 * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
10221 * records from the zone apex.
10222 */
10223 static void
10224 zone_refreshkeys(dns_zone_t *zone) {
10225 const char me[] = "zone_refreshkeys";
10226 isc_result_t result;
10227 dns_rriterator_t rrit;
10228 dns_db_t *db = NULL;
10229 dns_dbversion_t *ver = NULL;
10230 dns_diff_t diff;
10231 dns_rdata_t rdata = DNS_RDATA_INIT;
10232 dns_rdata_keydata_t kd;
10233 isc_stdtime_t now;
10234 bool commit = false;
10235 bool fetching = false, fetch_err = false;
10236 bool timerset = false;
10237
10238 ENTER;
10239 REQUIRE(zone->db != NULL);
10240
10241 isc_stdtime_get(&now);
10242
10243 LOCK_ZONE(zone);
10244 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
10245 isc_time_settoepoch(&zone->refreshkeytime);
10246 UNLOCK_ZONE(zone);
10247 return;
10248 }
10249
10250 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10251 dns_db_attach(zone->db, &db);
10252 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10253
10254 dns_diff_init(zone->mctx, &diff);
10255
10256 CHECK(dns_db_newversion(db, &ver));
10257
10258 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
10259
10260 dns_rriterator_init(&rrit, db, ver, 0);
10261 for (result = dns_rriterator_first(&rrit);
10262 result == ISC_R_SUCCESS;
10263 result = dns_rriterator_nextrrset(&rrit))
10264 {
10265 isc_stdtime_t timer = 0xffffffff;
10266 dns_name_t *name = NULL, *kname = NULL;
10267 dns_rdataset_t *kdset = NULL;
10268 dns_keyfetch_t *kfetch;
10269 uint32_t ttl;
10270
10271 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
10272 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
10273 !dns_rdataset_isassociated(kdset))
10274 {
10275 continue;
10276 }
10277
10278 /*
10279 * Scan the stored keys looking for ones that need
10280 * removal or refreshing
10281 */
10282 for (result = dns_rdataset_first(kdset);
10283 result == ISC_R_SUCCESS;
10284 result = dns_rdataset_next(kdset))
10285 {
10286 dns_rdata_reset(&rdata);
10287 dns_rdataset_current(kdset, &rdata);
10288 result = dns_rdata_tostruct(&rdata, &kd, NULL);
10289 RUNTIME_CHECK(result == ISC_R_SUCCESS);
10290
10291 /* Removal timer expired? */
10292 if (kd.removehd != 0 && kd.removehd < now) {
10293 CHECK(update_one_rr(db, ver, &diff,
10294 DNS_DIFFOP_DEL, name, ttl,
10295 &rdata));
10296 continue;
10297 }
10298
10299 /* Acceptance timer expired? */
10300 if (kd.addhd <= now) {
10301 timer = kd.addhd;
10302 }
10303
10304 /* Or do we just need to refresh the keyset? */
10305 if (timer > kd.refresh) {
10306 timer = kd.refresh;
10307 }
10308
10309 set_refreshkeytimer(zone, &kd, now, false);
10310 timerset = true;
10311 }
10312
10313 if (timer > now) {
10314 continue;
10315 }
10316
10317 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
10318 if (kfetch == NULL) {
10319 fetch_err = true;
10320 goto failure;
10321 }
10322
10323 zone->refreshkeycount++;
10324 kfetch->zone = zone;
10325 zone->irefs++;
10326 INSIST(zone->irefs != 0);
10327 kname = dns_fixedname_initname(&kfetch->name);
10328 dns_name_dup(name, zone->mctx, kname);
10329 dns_rdataset_init(&kfetch->dnskeyset);
10330 dns_rdataset_init(&kfetch->dnskeysigset);
10331 dns_rdataset_init(&kfetch->keydataset);
10332 dns_rdataset_clone(kdset, &kfetch->keydataset);
10333 kfetch->db = NULL;
10334 dns_db_attach(db, &kfetch->db);
10335 kfetch->fetch = NULL;
10336
10337 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
10338 char namebuf[DNS_NAME_FORMATSIZE];
10339 dns_name_format(kname, namebuf,
10340 sizeof(namebuf));
10341 dnssec_log(zone, ISC_LOG_DEBUG(3),
10342 "Creating key fetch in "
10343 "zone_refreshkeys() for '%s'",
10344 namebuf);
10345 }
10346
10347 /*
10348 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is
10349 * not set and the cache still holds a non-expired, validated
10350 * version of the RRset being queried for by the time the
10351 * response is received, the cached RRset will be passed to
10352 * keyfetch_done() instead of the one received in the response
10353 * as the latter will have a lower trust level due to not being
10354 * validated until keyfetch_done() is called.
10355 */
10356
10357 #ifdef ENABLE_AFL
10358 if (dns_fuzzing_resolver == false) {
10359 #endif
10360 result = dns_resolver_createfetch(zone->view->resolver,
10361 kname, dns_rdatatype_dnskey,
10362 NULL, NULL, NULL, NULL, 0,
10363 DNS_FETCHOPT_NOVALIDATE |
10364 DNS_FETCHOPT_UNSHARED |
10365 DNS_FETCHOPT_NOCACHED,
10366 0, NULL, zone->task,
10367 keyfetch_done, kfetch,
10368 &kfetch->dnskeyset,
10369 &kfetch->dnskeysigset,
10370 &kfetch->fetch);
10371 #ifdef ENABLE_AFL
10372 } else {
10373 result = ISC_R_FAILURE;
10374 }
10375 #endif
10376 if (result == ISC_R_SUCCESS) {
10377 fetching = true;
10378 } else {
10379 zone->refreshkeycount--;
10380 zone->irefs--;
10381 dns_db_detach(&kfetch->db);
10382 dns_rdataset_disassociate(&kfetch->keydataset);
10383 dns_name_free(kname, zone->mctx);
10384 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
10385 dnssec_log(zone, ISC_LOG_WARNING,
10386 "Failed to create fetch for DNSKEY update");
10387 fetch_err = true;
10388 }
10389 }
10390 if (!ISC_LIST_EMPTY(diff.tuples)) {
10391 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
10392 zone->updatemethod));
10393 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
10394 commit = true;
10395 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
10396 zone_needdump(zone, 30);
10397 }
10398
10399 failure:
10400 if (fetch_err) {
10401 /*
10402 * Error during a key fetch; retry in an hour.
10403 */
10404 isc_time_t timenow, timethen;
10405 char timebuf[80];
10406
10407 TIME_NOW(&timenow);
10408 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
10409 zone->refreshkeytime = timethen;
10410 zone_settimer(zone, &timenow);
10411
10412 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
10413 dnssec_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
10414 timebuf);
10415 } else if (!timerset) {
10416 isc_time_settoepoch(&zone->refreshkeytime);
10417 }
10418
10419 if (!fetching) {
10420 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
10421 }
10422
10423 dns_diff_clear(&diff);
10424 if (ver != NULL) {
10425 dns_rriterator_destroy(&rrit);
10426 dns_db_closeversion(db, &ver, commit);
10427 }
10428 dns_db_detach(&db);
10429
10430 UNLOCK_ZONE(zone);
10431
10432 INSIST(ver == NULL);
10433 }
10434
10435 static void
10436 zone_maintenance(dns_zone_t *zone) {
10437 const char me[] = "zone_maintenance";
10438 isc_time_t now;
10439 isc_result_t result;
10440 bool dumping, load_pending;
10441
10442 REQUIRE(DNS_ZONE_VALID(zone));
10443 ENTER;
10444
10445 /*
10446 * Are we pending load/reload?
10447 */
10448 LOCK_ZONE(zone);
10449 load_pending = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING);
10450 UNLOCK_ZONE(zone);
10451
10452 if (load_pending) {
10453 return;
10454 }
10455
10456 /*
10457 * Configuring the view of this zone may have
10458 * failed, for example because the config file
10459 * had a syntax error. In that case, the view
10460 * adb or resolver will be NULL, and we had better not try
10461 * to do further maintenance on it.
10462 */
10463 if (zone->view == NULL || zone->view->adb == NULL)
10464 return;
10465
10466 TIME_NOW(&now);
10467
10468 /*
10469 * Expire check.
10470 */
10471 switch (zone->type) {
10472 case dns_zone_redirect:
10473 if (zone->masters == NULL)
10474 break;
10475 /* FALLTHROUGH */
10476 case dns_zone_slave:
10477 case dns_zone_mirror:
10478 case dns_zone_stub:
10479 LOCK_ZONE(zone);
10480 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
10481 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10482 zone_expire(zone);
10483 zone->refreshtime = now;
10484 }
10485 UNLOCK_ZONE(zone);
10486 break;
10487 default:
10488 break;
10489 }
10490
10491 /*
10492 * Up to date check.
10493 */
10494 switch (zone->type) {
10495 case dns_zone_redirect:
10496 if (zone->masters == NULL)
10497 break;
10498 /* FALLTHROUGH */
10499 case dns_zone_slave:
10500 case dns_zone_mirror:
10501 case dns_zone_stub:
10502 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
10503 isc_time_compare(&now, &zone->refreshtime) >= 0)
10504 dns_zone_refresh(zone);
10505 break;
10506 default:
10507 break;
10508 }
10509
10510 /*
10511 * Slaves send notifies before backing up to disk, masters after.
10512 */
10513 if ((zone->type == dns_zone_slave || zone->type == dns_zone_mirror) &&
10514 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10515 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
10516 isc_time_compare(&now, &zone->notifytime) >= 0)
10517 zone_notify(zone, &now);
10518
10519 /*
10520 * Do we need to consolidate the backing store?
10521 */
10522 switch (zone->type) {
10523 case dns_zone_master:
10524 case dns_zone_slave:
10525 case dns_zone_mirror:
10526 case dns_zone_key:
10527 case dns_zone_redirect:
10528 case dns_zone_stub:
10529 LOCK_ZONE(zone);
10530 if (zone->masterfile != NULL &&
10531 isc_time_compare(&now, &zone->dumptime) >= 0 &&
10532 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10533 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
10534 dumping = was_dumping(zone);
10535 } else
10536 dumping = true;
10537 UNLOCK_ZONE(zone);
10538 if (!dumping) {
10539 result = zone_dump(zone, true); /* task locked */
10540 if (result != ISC_R_SUCCESS)
10541 dns_zone_log(zone, ISC_LOG_WARNING,
10542 "dump failed: %s",
10543 dns_result_totext(result));
10544 }
10545 break;
10546 default:
10547 break;
10548 }
10549
10550 /*
10551 * Master/redirect zones send notifies now, if needed
10552 */
10553 switch (zone->type) {
10554 case dns_zone_master:
10555 case dns_zone_redirect:
10556 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10557 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
10558 isc_time_compare(&now, &zone->notifytime) >= 0)
10559 zone_notify(zone, &now);
10560 default:
10561 break;
10562 }
10563
10564 /*
10565 * Do we need to refresh keys?
10566 */
10567 switch (zone->type) {
10568 case dns_zone_key:
10569 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
10570 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10571 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10572 zone_refreshkeys(zone);
10573 }
10574 }
10575 break;
10576 case dns_zone_master:
10577 if (!isc_time_isepoch(&zone->refreshkeytime) &&
10578 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
10579 zone->rss_event == NULL)
10580 zone_rekey(zone);
10581 default:
10582 break;
10583 }
10584
10585 switch (zone->type) {
10586 case dns_zone_master:
10587 case dns_zone_redirect:
10588 case dns_zone_slave:
10589 /*
10590 * Do we need to sign/resign some RRsets?
10591 */
10592 if (zone->rss_event != NULL)
10593 break;
10594 if (!isc_time_isepoch(&zone->signingtime) &&
10595 isc_time_compare(&now, &zone->signingtime) >= 0) {
10596 zone_sign(zone);
10597 }
10598 else if (!isc_time_isepoch(&zone->resigntime) &&
10599 isc_time_compare(&now, &zone->resigntime) >= 0) {
10600 zone_resigninc(zone);
10601 }
10602 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
10603 isc_time_compare(&now, &zone->nsec3chaintime) >= 0) {
10604 zone_nsec3chain(zone);
10605 }
10606 /*
10607 * Do we need to issue a key expiry warning?
10608 */
10609 if (!isc_time_isepoch(&zone->keywarntime) &&
10610 isc_time_compare(&now, &zone->keywarntime) >= 0)
10611 set_key_expiry_warning(zone, zone->key_expiry,
10612 isc_time_seconds(&now));
10613 break;
10614
10615 default:
10616 break;
10617 }
10618 zone_settimer(zone, &now);
10619 }
10620
10621 void
10622 dns_zone_markdirty(dns_zone_t *zone) {
10623 uint32_t serial;
10624 isc_result_t result = ISC_R_SUCCESS;
10625 dns_zone_t *secure = NULL;
10626
10627 /*
10628 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
10629 * could result in a deadlock due to a LOR so we will spin if we
10630 * can't obtain the both locks.
10631 */
10632 again:
10633 LOCK_ZONE(zone);
10634 if (zone->type == dns_zone_master) {
10635 if (inline_raw(zone)) {
10636 unsigned int soacount;
10637 secure = zone->secure;
10638 INSIST(secure != zone);
10639 TRYLOCK_ZONE(result, secure);
10640 if (result != ISC_R_SUCCESS) {
10641 UNLOCK_ZONE(zone);
10642 secure = NULL;
10643 isc_thread_yield();
10644 goto again;
10645 }
10646
10647 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10648 if (zone->db != NULL) {
10649 result = zone_get_from_db(zone, zone->db, NULL,
10650 &soacount, &serial,
10651 NULL, NULL, NULL,
10652 NULL, NULL);
10653 } else
10654 result = DNS_R_NOTLOADED;
10655 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10656 if (result == ISC_R_SUCCESS && soacount > 0U)
10657 zone_send_secureserial(zone, serial);
10658 }
10659
10660 /* XXXMPA make separate call back */
10661 if (result == ISC_R_SUCCESS)
10662 set_resigntime(zone);
10663 }
10664 if (secure != NULL)
10665 UNLOCK_ZONE(secure);
10666 zone_needdump(zone, DNS_DUMP_DELAY);
10667 UNLOCK_ZONE(zone);
10668 }
10669
10670 void
10671 dns_zone_expire(dns_zone_t *zone) {
10672 REQUIRE(DNS_ZONE_VALID(zone));
10673
10674 LOCK_ZONE(zone);
10675 zone_expire(zone);
10676 UNLOCK_ZONE(zone);
10677 }
10678
10679 static void
10680 zone_expire(dns_zone_t *zone) {
10681 dns_db_t *db = NULL;
10682
10683 /*
10684 * 'zone' locked by caller.
10685 */
10686
10687 REQUIRE(LOCKED_ZONE(zone));
10688
10689 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
10690
10691 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
10692 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
10693 zone->retry = DNS_ZONE_DEFAULTRETRY;
10694 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10695
10696 /*
10697 * An RPZ zone has expired; before unloading it, we must
10698 * first remove it from the RPZ summary database. The
10699 * easiest way to do this is "update" it with an empty
10700 * database so that the update callback synchonizes
10701 * the diff automatically.
10702 */
10703 if (zone->rpzs != NULL && zone->rpz_num != DNS_RPZ_INVALID_NUM) {
10704 isc_result_t result;
10705 dns_rpz_zone_t *rpz = zone->rpzs->zones[zone->rpz_num];
10706
10707 CHECK(dns_db_create(zone->mctx, "rbt", &zone->origin,
10708 dns_dbtype_zone, zone->rdclass,
10709 0, NULL, &db));
10710 CHECK(dns_rpz_dbupdate_callback(db, rpz));
10711 dns_zone_log(zone, ISC_LOG_WARNING,
10712 "response-policy zone expired; "
10713 "policies unloaded");
10714 }
10715
10716 failure:
10717 if (db != NULL) {
10718 dns_db_detach(&db);
10719 }
10720
10721 zone_unload(zone);
10722 }
10723
10724 void
10725 dns_zone_refresh(dns_zone_t *zone) {
10726 isc_interval_t i;
10727 uint32_t oldflags;
10728 unsigned int j;
10729 isc_result_t result;
10730
10731 REQUIRE(DNS_ZONE_VALID(zone));
10732
10733 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10734 return;
10735
10736 /*
10737 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
10738 * in progress at a time.
10739 */
10740
10741 LOCK_ZONE(zone);
10742 oldflags = zone->flags;
10743 if (zone->masterscnt == 0) {
10744 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
10745 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
10746 dns_zone_log(zone, ISC_LOG_ERROR,
10747 "cannot refresh: no masters");
10748 goto unlock;
10749 }
10750 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
10751 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10752 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10753 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
10754 goto unlock;
10755
10756 /*
10757 * Set the next refresh time as if refresh check has failed.
10758 * Setting this to the retry time will do that. XXXMLG
10759 * If we are successful it will be reset using zone->refresh.
10760 */
10761 isc_interval_set(&i, zone->retry - isc_random_uniform(zone->retry / 4),
10762 0);
10763 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
10764 if (result != ISC_R_SUCCESS)
10765 dns_zone_log(zone, ISC_LOG_WARNING,
10766 "isc_time_nowplusinterval() failed: %s",
10767 dns_result_totext(result));
10768
10769 /*
10770 * When lacking user-specified timer values from the SOA,
10771 * do exponential backoff of the retry time up to a
10772 * maximum of six hours.
10773 */
10774 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
10775 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
10776
10777 zone->curmaster = 0;
10778 for (j = 0; j < zone->masterscnt; j++)
10779 zone->mastersok[j] = false;
10780 /* initiate soa query */
10781 queue_soa_query(zone);
10782 unlock:
10783 UNLOCK_ZONE(zone);
10784 }
10785
10786 static void
10787 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, uint32_t serial) {
10788 isc_result_t result;
10789 int32_t journalsize;
10790 dns_dbversion_t *ver = NULL;
10791 uint64_t dbsize;
10792
10793 INSIST(LOCKED_ZONE(zone));
10794 if (inline_raw(zone))
10795 INSIST(LOCKED_ZONE(zone->secure));
10796
10797 journalsize = zone->journalsize;
10798 if (journalsize == -1) {
10799 journalsize = DNS_JOURNAL_SIZE_MAX;
10800 dns_db_currentversion(db, &ver);
10801 result = dns_db_getsize(db, ver, NULL, &dbsize);
10802 dns_db_closeversion(db, &ver, false);
10803 if (result != ISC_R_SUCCESS) {
10804 dns_zone_log(zone, ISC_LOG_ERROR,
10805 "zone_journal_compact: "
10806 "could not get zone size: %s",
10807 isc_result_totext(result));
10808 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
10809 journalsize = (int32_t)dbsize * 2;
10810 }
10811 }
10812 zone_debuglog(zone, "zone_journal_compact", 1,
10813 "target journal size %d", journalsize);
10814 result = dns_journal_compact(zone->mctx, zone->journal,
10815 serial, journalsize);
10816 switch (result) {
10817 case ISC_R_SUCCESS:
10818 case ISC_R_NOSPACE:
10819 case ISC_R_NOTFOUND:
10820 dns_zone_log(zone, ISC_LOG_DEBUG(3),
10821 "dns_journal_compact: %s",
10822 dns_result_totext(result));
10823 break;
10824 default:
10825 dns_zone_log(zone, ISC_LOG_ERROR,
10826 "dns_journal_compact failed: %s",
10827 dns_result_totext(result));
10828 break;
10829 }
10830 }
10831
10832 isc_result_t
10833 dns_zone_flush(dns_zone_t *zone) {
10834 isc_result_t result = ISC_R_SUCCESS;
10835 bool dumping;
10836
10837 REQUIRE(DNS_ZONE_VALID(zone));
10838
10839 LOCK_ZONE(zone);
10840 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
10841 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10842 zone->masterfile != NULL) {
10843 result = ISC_R_ALREADYRUNNING;
10844 dumping = was_dumping(zone);
10845 } else
10846 dumping = true;
10847 UNLOCK_ZONE(zone);
10848 if (!dumping)
10849 result = zone_dump(zone, true); /* Unknown task. */
10850 return (result);
10851 }
10852
10853 isc_result_t
10854 dns_zone_dump(dns_zone_t *zone) {
10855 isc_result_t result = ISC_R_ALREADYRUNNING;
10856 bool dumping;
10857
10858 REQUIRE(DNS_ZONE_VALID(zone));
10859
10860 LOCK_ZONE(zone);
10861 dumping = was_dumping(zone);
10862 UNLOCK_ZONE(zone);
10863 if (!dumping)
10864 result = zone_dump(zone, false); /* Unknown task. */
10865 return (result);
10866 }
10867
10868 static void
10869 zone_needdump(dns_zone_t *zone, unsigned int delay) {
10870 const char me[] = "zone_needdump";
10871 isc_time_t dumptime;
10872 isc_time_t now;
10873
10874 /*
10875 * 'zone' locked by caller
10876 */
10877
10878 REQUIRE(DNS_ZONE_VALID(zone));
10879 REQUIRE(LOCKED_ZONE(zone));
10880 ENTER;
10881
10882 /*
10883 * Do we have a place to dump to and are we loaded?
10884 */
10885 if (zone->masterfile == NULL ||
10886 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
10887 return;
10888
10889 TIME_NOW(&now);
10890 /* add some noise */
10891 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
10892
10893 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10894 if (isc_time_isepoch(&zone->dumptime) ||
10895 isc_time_compare(&zone->dumptime, &dumptime) > 0)
10896 zone->dumptime = dumptime;
10897 if (zone->task != NULL)
10898 zone_settimer(zone, &now);
10899 }
10900
10901 static void
10902 dump_done(void *arg, isc_result_t result) {
10903 const char me[] = "dump_done";
10904 dns_zone_t *zone = arg;
10905 dns_zone_t *secure = NULL;
10906 dns_db_t *db;
10907 dns_dbversion_t *version;
10908 bool again = false;
10909 bool compact = false;
10910 uint32_t serial;
10911 isc_result_t tresult;
10912
10913 REQUIRE(DNS_ZONE_VALID(zone));
10914
10915 ENTER;
10916
10917 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
10918 /*
10919 * We don't own these, zone->dctx must stay valid.
10920 */
10921 db = dns_dumpctx_db(zone->dctx);
10922 version = dns_dumpctx_version(zone->dctx);
10923 tresult = dns_db_getsoaserial(db, version, &serial);
10924
10925 /*
10926 * Handle lock order inversion.
10927 */
10928 again:
10929 LOCK_ZONE(zone);
10930 if (inline_raw(zone)) {
10931 secure = zone->secure;
10932 INSIST(secure != zone);
10933 TRYLOCK_ZONE(result, secure);
10934 if (result != ISC_R_SUCCESS) {
10935 UNLOCK_ZONE(zone);
10936 secure = NULL;
10937 isc_thread_yield();
10938 goto again;
10939 }
10940 }
10941
10942 /*
10943 * If there is a secure version of this zone
10944 * use its serial if it is less than ours.
10945 */
10946 if (tresult == ISC_R_SUCCESS && secure != NULL) {
10947 uint32_t sserial;
10948 isc_result_t mresult;
10949
10950 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
10951 if (secure->db != NULL) {
10952 mresult = dns_db_getsoaserial(zone->secure->db,
10953 NULL, &sserial);
10954 if (mresult == ISC_R_SUCCESS &&
10955 isc_serial_lt(sserial, serial))
10956 serial = sserial;
10957 }
10958 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
10959 }
10960 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
10961 dns_db_t *zdb = NULL;
10962 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
10963 zone_journal_compact(zone, zdb, serial);
10964 dns_db_detach(&zdb);
10965 }
10966 } else if (tresult == ISC_R_SUCCESS) {
10967 compact = true;
10968 zone->compact_serial = serial;
10969 }
10970 if (secure != NULL)
10971 UNLOCK_ZONE(secure);
10972 UNLOCK_ZONE(zone);
10973 }
10974
10975 LOCK_ZONE(zone);
10976 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
10977 if (compact)
10978 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
10979 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
10980 /*
10981 * Try again in a short while.
10982 */
10983 zone_needdump(zone, DNS_DUMP_DELAY);
10984 } else if (result == ISC_R_SUCCESS &&
10985 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
10986 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10987 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10988 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10989 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
10990 isc_time_settoepoch(&zone->dumptime);
10991 again = true;
10992 } else if (result == ISC_R_SUCCESS)
10993 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
10994
10995 if (zone->dctx != NULL)
10996 dns_dumpctx_detach(&zone->dctx);
10997 zonemgr_putio(&zone->writeio);
10998 UNLOCK_ZONE(zone);
10999 if (again)
11000 (void)zone_dump(zone, false);
11001 dns_zone_idetach(&zone);
11002 }
11003
11004 static isc_result_t
11005 zone_dump(dns_zone_t *zone, bool compact) {
11006 const char me[] = "zone_dump";
11007 isc_result_t result;
11008 dns_dbversion_t *version = NULL;
11009 bool again;
11010 dns_db_t *db = NULL;
11011 char *masterfile = NULL;
11012 dns_masterformat_t masterformat = dns_masterformat_none;
11013
11014 /*
11015 * 'compact' MUST only be set if we are task locked.
11016 */
11017
11018 REQUIRE(DNS_ZONE_VALID(zone));
11019 ENTER;
11020
11021 redo:
11022 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11023 if (zone->db != NULL)
11024 dns_db_attach(zone->db, &db);
11025 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11026 LOCK_ZONE(zone);
11027 if (zone->masterfile != NULL) {
11028 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
11029 masterformat = zone->masterformat;
11030 }
11031 UNLOCK_ZONE(zone);
11032 if (db == NULL) {
11033 result = DNS_R_NOTLOADED;
11034 goto fail;
11035 }
11036 if (masterfile == NULL) {
11037 result = DNS_R_NOMASTERFILE;
11038 goto fail;
11039 }
11040
11041 if (compact && zone->type != dns_zone_stub) {
11042 dns_zone_t *dummy = NULL;
11043 LOCK_ZONE(zone);
11044 zone_iattach(zone, &dummy);
11045 result = zonemgr_getio(zone->zmgr, false, zone->task,
11046 zone_gotwritehandle, zone,
11047 &zone->writeio);
11048 if (result != ISC_R_SUCCESS)
11049 zone_idetach(&dummy);
11050 else
11051 result = DNS_R_CONTINUE;
11052 UNLOCK_ZONE(zone);
11053 } else {
11054 const dns_master_style_t *output_style;
11055
11056 dns_masterrawheader_t rawdata;
11057 dns_db_currentversion(db, &version);
11058 dns_master_initrawheader(&rawdata);
11059 if (inline_secure(zone))
11060 get_raw_serial(zone->raw, &rawdata);
11061 if (zone->type == dns_zone_key)
11062 output_style = &dns_master_style_keyzone;
11063 else
11064 output_style = &dns_master_style_default;
11065 result = dns_master_dump(zone->mctx, db, version,
11066 output_style, masterfile,
11067 masterformat, &rawdata);
11068 dns_db_closeversion(db, &version, false);
11069 }
11070 fail:
11071 if (db != NULL)
11072 dns_db_detach(&db);
11073 if (masterfile != NULL)
11074 isc_mem_free(zone->mctx, masterfile);
11075 masterfile = NULL;
11076
11077 if (result == DNS_R_CONTINUE)
11078 return (ISC_R_SUCCESS); /* XXXMPA */
11079
11080 again = false;
11081 LOCK_ZONE(zone);
11082 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
11083 if (result != ISC_R_SUCCESS) {
11084 /*
11085 * Try again in a short while.
11086 */
11087 zone_needdump(zone, DNS_DUMP_DELAY);
11088 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
11089 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11090 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
11091 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11092 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
11093 isc_time_settoepoch(&zone->dumptime);
11094 again = true;
11095 } else
11096 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
11097 UNLOCK_ZONE(zone);
11098 if (again)
11099 goto redo;
11100
11101 return (result);
11102 }
11103
11104 static isc_result_t
11105 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
11106 dns_masterformat_t format, const uint32_t rawversion)
11107 {
11108 isc_result_t result;
11109 dns_dbversion_t *version = NULL;
11110 dns_db_t *db = NULL;
11111 dns_masterrawheader_t rawdata;
11112
11113 REQUIRE(DNS_ZONE_VALID(zone));
11114
11115 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11116 if (zone->db != NULL)
11117 dns_db_attach(zone->db, &db);
11118 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11119 if (db == NULL)
11120 return (DNS_R_NOTLOADED);
11121
11122 dns_db_currentversion(db, &version);
11123 dns_master_initrawheader(&rawdata);
11124 if (rawversion == 0)
11125 rawdata.flags |= DNS_MASTERRAW_COMPAT;
11126 else if (inline_secure(zone))
11127 get_raw_serial(zone->raw, &rawdata);
11128 else if (zone->sourceserialset) {
11129 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
11130 rawdata.sourceserial = zone->sourceserial;
11131 }
11132 result = dns_master_dumptostream(zone->mctx, db, version, style,
11133 format, &rawdata, fd);
11134 dns_db_closeversion(db, &version, false);
11135 dns_db_detach(&db);
11136 return (result);
11137 }
11138
11139 isc_result_t
11140 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
11141 const dns_master_style_t *style,
11142 const uint32_t rawversion)
11143 {
11144 return (dumptostream(zone, fd, style, format, rawversion));
11145 }
11146
11147 void
11148 dns_zone_unload(dns_zone_t *zone) {
11149 REQUIRE(DNS_ZONE_VALID(zone));
11150
11151 LOCK_ZONE(zone);
11152 zone_unload(zone);
11153 UNLOCK_ZONE(zone);
11154 }
11155
11156 static void
11157 notify_cancel(dns_zone_t *zone) {
11158 dns_notify_t *notify;
11159
11160 /*
11161 * 'zone' locked by caller.
11162 */
11163
11164 REQUIRE(LOCKED_ZONE(zone));
11165
11166 for (notify = ISC_LIST_HEAD(zone->notifies);
11167 notify != NULL;
11168 notify = ISC_LIST_NEXT(notify, link)) {
11169 if (notify->find != NULL)
11170 dns_adb_cancelfind(notify->find);
11171 if (notify->request != NULL)
11172 dns_request_cancel(notify->request);
11173 }
11174 }
11175
11176 static void
11177 forward_cancel(dns_zone_t *zone) {
11178 dns_forward_t *forward;
11179
11180 /*
11181 * 'zone' locked by caller.
11182 */
11183
11184 REQUIRE(LOCKED_ZONE(zone));
11185
11186 for (forward = ISC_LIST_HEAD(zone->forwards);
11187 forward != NULL;
11188 forward = ISC_LIST_NEXT(forward, link)) {
11189 if (forward->request != NULL)
11190 dns_request_cancel(forward->request);
11191 }
11192 }
11193
11194 static void
11195 zone_unload(dns_zone_t *zone) {
11196 /*
11197 * 'zone' locked by caller.
11198 */
11199
11200 REQUIRE(LOCKED_ZONE(zone));
11201
11202 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
11203 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
11204 if (zone->writeio != NULL)
11205 zonemgr_cancelio(zone->writeio);
11206
11207 if (zone->dctx != NULL)
11208 dns_dumpctx_cancel(zone->dctx);
11209 }
11210 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11211 zone_detachdb(zone);
11212 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11213 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
11214 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
11215
11216 if (zone->type == dns_zone_mirror) {
11217 dns_zone_log(zone, ISC_LOG_INFO,
11218 "mirror zone is no longer in use; "
11219 "reverting to normal recursion");
11220 }
11221 }
11222
11223 void
11224 dns_zone_setminrefreshtime(dns_zone_t *zone, uint32_t val) {
11225 REQUIRE(DNS_ZONE_VALID(zone));
11226 REQUIRE(val > 0);
11227
11228 zone->minrefresh = val;
11229 }
11230
11231 void
11232 dns_zone_setmaxrefreshtime(dns_zone_t *zone, uint32_t val) {
11233 REQUIRE(DNS_ZONE_VALID(zone));
11234 REQUIRE(val > 0);
11235
11236 zone->maxrefresh = val;
11237 }
11238
11239 void
11240 dns_zone_setminretrytime(dns_zone_t *zone, uint32_t val) {
11241 REQUIRE(DNS_ZONE_VALID(zone));
11242 REQUIRE(val > 0);
11243
11244 zone->minretry = val;
11245 }
11246
11247 void
11248 dns_zone_setmaxretrytime(dns_zone_t *zone, uint32_t val) {
11249 REQUIRE(DNS_ZONE_VALID(zone));
11250 REQUIRE(val > 0);
11251
11252 zone->maxretry = val;
11253 }
11254
11255 uint32_t
11256 dns_zone_getmaxrecords(dns_zone_t *zone) {
11257 REQUIRE(DNS_ZONE_VALID(zone));
11258
11259 return (zone->maxrecords);
11260 }
11261
11262 void
11263 dns_zone_setmaxrecords(dns_zone_t *zone, uint32_t val) {
11264 REQUIRE(DNS_ZONE_VALID(zone));
11265
11266 zone->maxrecords = val;
11267 }
11268
11269 static bool
11270 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
11271 isc_sockaddr_t *addr, dns_tsigkey_t *key)
11272 {
11273 dns_notify_t *notify;
11274 dns_zonemgr_t *zmgr;
11275 isc_result_t result;
11276
11277 for (notify = ISC_LIST_HEAD(zone->notifies);
11278 notify != NULL;
11279 notify = ISC_LIST_NEXT(notify, link)) {
11280 if (notify->request != NULL)
11281 continue;
11282 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
11283 dns_name_equal(name, ¬ify->ns))
11284 goto requeue;
11285 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
11286 notify->key == key)
11287 goto requeue;
11288 }
11289 return (false);
11290
11291 requeue:
11292 /*
11293 * If we are enqueued on the startup ratelimiter and this is
11294 * not a startup notify, re-enqueue on the normal notify
11295 * ratelimiter.
11296 */
11297 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
11298 (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
11299 zmgr = notify->zone->zmgr;
11300 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
11301 notify->event);
11302 if (result != ISC_R_SUCCESS)
11303 return (true);
11304
11305 notify->flags &= ~DNS_NOTIFY_STARTUP;
11306 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
11307 notify->zone->task,
11308 ¬ify->event);
11309 if (result != ISC_R_SUCCESS) {
11310 isc_event_free(¬ify->event);
11311 return (false);
11312 }
11313 }
11314
11315 return (true);
11316 }
11317
11318 static bool
11319 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
11320 dns_tsigkey_t *key = NULL;
11321 isc_sockaddr_t src;
11322 isc_sockaddr_t any;
11323 bool isself;
11324 isc_netaddr_t dstaddr;
11325 isc_result_t result;
11326
11327 if (zone->view == NULL || zone->isself == NULL)
11328 return (false);
11329
11330 switch (isc_sockaddr_pf(dst)) {
11331 case PF_INET:
11332 src = zone->notifysrc4;
11333 isc_sockaddr_any(&any);
11334 break;
11335 case PF_INET6:
11336 src = zone->notifysrc6;
11337 isc_sockaddr_any6(&any);
11338 break;
11339 default:
11340 return (false);
11341 }
11342
11343 /*
11344 * When sending from any the kernel will assign a source address
11345 * that matches the destination address.
11346 */
11347 if (isc_sockaddr_eqaddr(&any, &src))
11348 src = *dst;
11349
11350 isc_netaddr_fromsockaddr(&dstaddr, dst);
11351 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
11352 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
11353 return (false);
11354 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
11355 zone->isselfarg);
11356 if (key != NULL)
11357 dns_tsigkey_detach(&key);
11358 return (isself);
11359 }
11360
11361 static void
11362 notify_destroy(dns_notify_t *notify, bool locked) {
11363 isc_mem_t *mctx;
11364
11365 REQUIRE(DNS_NOTIFY_VALID(notify));
11366
11367 if (notify->zone != NULL) {
11368 if (!locked)
11369 LOCK_ZONE(notify->zone);
11370 REQUIRE(LOCKED_ZONE(notify->zone));
11371 if (ISC_LINK_LINKED(notify, link))
11372 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
11373 if (!locked)
11374 UNLOCK_ZONE(notify->zone);
11375 if (locked)
11376 zone_idetach(¬ify->zone);
11377 else
11378 dns_zone_idetach(¬ify->zone);
11379 }
11380 if (notify->find != NULL)
11381 dns_adb_destroyfind(¬ify->find);
11382 if (notify->request != NULL)
11383 dns_request_destroy(¬ify->request);
11384 if (dns_name_dynamic(¬ify->ns))
11385 dns_name_free(¬ify->ns, notify->mctx);
11386 if (notify->key != NULL)
11387 dns_tsigkey_detach(¬ify->key);
11388 mctx = notify->mctx;
11389 isc_mem_put(notify->mctx, notify, sizeof(*notify));
11390 isc_mem_detach(&mctx);
11391 }
11392
11393 static isc_result_t
11394 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
11395 dns_notify_t *notify;
11396
11397 REQUIRE(notifyp != NULL && *notifyp == NULL);
11398
11399 notify = isc_mem_get(mctx, sizeof(*notify));
11400 if (notify == NULL)
11401 return (ISC_R_NOMEMORY);
11402
11403 notify->mctx = NULL;
11404 isc_mem_attach(mctx, ¬ify->mctx);
11405 notify->flags = flags;
11406 notify->zone = NULL;
11407 notify->find = NULL;
11408 notify->request = NULL;
11409 notify->key = NULL;
11410 notify->event = NULL;
11411 isc_sockaddr_any(¬ify->dst);
11412 dns_name_init(¬ify->ns, NULL);
11413 ISC_LINK_INIT(notify, link);
11414 notify->magic = NOTIFY_MAGIC;
11415 *notifyp = notify;
11416 return (ISC_R_SUCCESS);
11417 }
11418
11419 /*
11420 * XXXAG should check for DNS_ZONEFLG_EXITING
11421 */
11422 static void
11423 process_adb_event(isc_task_t *task, isc_event_t *ev) {
11424 dns_notify_t *notify;
11425 isc_eventtype_t result;
11426
11427 UNUSED(task);
11428
11429 notify = ev->ev_arg;
11430 REQUIRE(DNS_NOTIFY_VALID(notify));
11431 INSIST(task == notify->zone->task);
11432 result = ev->ev_type;
11433 isc_event_free(&ev);
11434 if (result == DNS_EVENT_ADBMOREADDRESSES) {
11435 dns_adb_destroyfind(¬ify->find);
11436 notify_find_address(notify);
11437 return;
11438 }
11439 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
11440 LOCK_ZONE(notify->zone);
11441 notify_send(notify);
11442 UNLOCK_ZONE(notify->zone);
11443 }
11444 notify_destroy(notify, false);
11445 }
11446
11447 static void
11448 notify_find_address(dns_notify_t *notify) {
11449 isc_result_t result;
11450 unsigned int options;
11451
11452 REQUIRE(DNS_NOTIFY_VALID(notify));
11453 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
11454 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
11455
11456 if (notify->zone->view->adb == NULL)
11457 goto destroy;
11458
11459 result = dns_adb_createfind(notify->zone->view->adb,
11460 notify->zone->task,
11461 process_adb_event, notify,
11462 ¬ify->ns, dns_rootname, 0,
11463 options, 0, NULL,
11464 notify->zone->view->dstport,
11465 0, NULL, ¬ify->find);
11466
11467 /* Something failed? */
11468 if (result != ISC_R_SUCCESS)
11469 goto destroy;
11470
11471 /* More addresses pending? */
11472 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
11473 return;
11474
11475 /* We have as many addresses as we can get. */
11476 LOCK_ZONE(notify->zone);
11477 notify_send(notify);
11478 UNLOCK_ZONE(notify->zone);
11479
11480 destroy:
11481 notify_destroy(notify, false);
11482 }
11483
11484
11485 static isc_result_t
11486 notify_send_queue(dns_notify_t *notify, bool startup) {
11487 isc_event_t *e;
11488 isc_result_t result;
11489
11490 INSIST(notify->event == NULL);
11491 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
11492 notify_send_toaddr, notify, sizeof(isc_event_t));
11493 if (e == NULL)
11494 return (ISC_R_NOMEMORY);
11495 if (startup)
11496 notify->event = e;
11497 e->ev_arg = notify;
11498 e->ev_sender = NULL;
11499 result = isc_ratelimiter_enqueue(startup
11500 ? notify->zone->zmgr->startupnotifyrl
11501 : notify->zone->zmgr->notifyrl,
11502 notify->zone->task, &e);
11503 if (result != ISC_R_SUCCESS) {
11504 isc_event_free(&e);
11505 notify->event = NULL;
11506 }
11507 return (result);
11508 }
11509
11510 static void
11511 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
11512 dns_notify_t *notify;
11513 isc_result_t result;
11514 dns_message_t *message = NULL;
11515 isc_netaddr_t dstip;
11516 dns_tsigkey_t *key = NULL;
11517 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11518 isc_sockaddr_t src;
11519 unsigned int options, timeout;
11520 bool have_notifysource = false;
11521 bool have_notifydscp = false;
11522 isc_dscp_t dscp = -1;
11523
11524 notify = event->ev_arg;
11525 REQUIRE(DNS_NOTIFY_VALID(notify));
11526
11527 UNUSED(task);
11528
11529 LOCK_ZONE(notify->zone);
11530
11531 notify->event = NULL;
11532
11533 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
11534 result = ISC_R_CANCELED;
11535 goto cleanup;
11536 }
11537
11538 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
11539 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
11540 notify->zone->view->requestmgr == NULL ||
11541 notify->zone->db == NULL) {
11542 result = ISC_R_CANCELED;
11543 goto cleanup;
11544 }
11545
11546 /*
11547 * The raw IPv4 address should also exist. Don't send to the
11548 * mapped form.
11549 */
11550 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
11551 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr)) {
11552 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
11553 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11554 "notify: ignoring IPv6 mapped IPV4 address: %s",
11555 addrbuf);
11556 result = ISC_R_CANCELED;
11557 goto cleanup;
11558 }
11559
11560 result = notify_createmessage(notify->zone, notify->flags, &message);
11561 if (result != ISC_R_SUCCESS)
11562 goto cleanup;
11563
11564 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
11565 if (notify->key != NULL) {
11566 /* Transfer ownership of key */
11567 key = notify->key;
11568 notify->key = NULL;
11569 } else {
11570 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
11571 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
11572 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11573 notify_log(notify->zone, ISC_LOG_ERROR,
11574 "NOTIFY to %s not sent. "
11575 "Peer TSIG key lookup failure.", addrbuf);
11576 goto cleanup_message;
11577 }
11578 }
11579
11580 /* XXX: should we log the tsig key too? */
11581 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
11582 addrbuf);
11583 options = 0;
11584 if (notify->zone->view->peers != NULL) {
11585 dns_peer_t *peer = NULL;
11586 bool usetcp = false;
11587 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
11588 &dstip, &peer);
11589 if (result == ISC_R_SUCCESS) {
11590 result = dns_peer_getnotifysource(peer, &src);
11591 if (result == ISC_R_SUCCESS)
11592 have_notifysource = true;
11593 dns_peer_getnotifydscp(peer, &dscp);
11594 if (dscp != -1)
11595 have_notifydscp = true;
11596 result = dns_peer_getforcetcp(peer, &usetcp);
11597 if (result == ISC_R_SUCCESS && usetcp)
11598 options |= DNS_FETCHOPT_TCP;
11599 }
11600 }
11601 switch (isc_sockaddr_pf(¬ify->dst)) {
11602 case PF_INET:
11603 if (!have_notifysource)
11604 src = notify->zone->notifysrc4;
11605 if (!have_notifydscp)
11606 dscp = notify->zone->notifysrc4dscp;
11607 break;
11608 case PF_INET6:
11609 if (!have_notifysource)
11610 src = notify->zone->notifysrc6;
11611 if (!have_notifydscp)
11612 dscp = notify->zone->notifysrc6dscp;
11613 break;
11614 default:
11615 result = ISC_R_NOTIMPLEMENTED;
11616 goto cleanup_key;
11617 }
11618 timeout = 15;
11619 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
11620 timeout = 30;
11621 result = dns_request_createvia(notify->zone->view->requestmgr,
11622 message, &src, ¬ify->dst, dscp,
11623 options, key, timeout * 3, timeout,
11624 0, notify->zone->task, notify_done,
11625 notify, ¬ify->request);
11626 if (result == ISC_R_SUCCESS) {
11627 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
11628 inc_stats(notify->zone,
11629 dns_zonestatscounter_notifyoutv4);
11630 } else {
11631 inc_stats(notify->zone,
11632 dns_zonestatscounter_notifyoutv6);
11633 }
11634 }
11635
11636 cleanup_key:
11637 if (key != NULL)
11638 dns_tsigkey_detach(&key);
11639 cleanup_message:
11640 dns_message_destroy(&message);
11641 cleanup:
11642 UNLOCK_ZONE(notify->zone);
11643 isc_event_free(&event);
11644 if (result != ISC_R_SUCCESS)
11645 notify_destroy(notify, false);
11646 }
11647
11648 static void
11649 notify_send(dns_notify_t *notify) {
11650 dns_adbaddrinfo_t *ai;
11651 isc_sockaddr_t dst;
11652 isc_result_t result;
11653 dns_notify_t *newnotify = NULL;
11654 unsigned int flags;
11655 bool startup;
11656
11657 /*
11658 * Zone lock held by caller.
11659 */
11660 REQUIRE(DNS_NOTIFY_VALID(notify));
11661 REQUIRE(LOCKED_ZONE(notify->zone));
11662
11663 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING))
11664 return;
11665
11666 for (ai = ISC_LIST_HEAD(notify->find->list);
11667 ai != NULL;
11668 ai = ISC_LIST_NEXT(ai, publink)) {
11669 dst = ai->sockaddr;
11670 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
11671 NULL))
11672 continue;
11673 if (notify_isself(notify->zone, &dst))
11674 continue;
11675 newnotify = NULL;
11676 flags = notify->flags & DNS_NOTIFY_NOSOA;
11677 result = notify_create(notify->mctx, flags, &newnotify);
11678 if (result != ISC_R_SUCCESS)
11679 goto cleanup;
11680 zone_iattach(notify->zone, &newnotify->zone);
11681 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
11682 newnotify->dst = dst;
11683 startup = ((notify->flags & DNS_NOTIFY_STARTUP) != 0);
11684 result = notify_send_queue(newnotify, startup);
11685 if (result != ISC_R_SUCCESS)
11686 goto cleanup;
11687 newnotify = NULL;
11688 }
11689
11690 cleanup:
11691 if (newnotify != NULL)
11692 notify_destroy(newnotify, true);
11693 }
11694
11695 void
11696 dns_zone_notify(dns_zone_t *zone) {
11697 isc_time_t now;
11698
11699 REQUIRE(DNS_ZONE_VALID(zone));
11700
11701 LOCK_ZONE(zone);
11702 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11703
11704 TIME_NOW(&now);
11705 zone_settimer(zone, &now);
11706 UNLOCK_ZONE(zone);
11707 }
11708
11709 static void
11710 zone_notify(dns_zone_t *zone, isc_time_t *now) {
11711 dns_dbnode_t *node = NULL;
11712 dns_db_t *zonedb = NULL;
11713 dns_dbversion_t *version = NULL;
11714 dns_name_t *origin = NULL;
11715 dns_name_t master;
11716 dns_rdata_ns_t ns;
11717 dns_rdata_soa_t soa;
11718 uint32_t serial;
11719 dns_rdata_t rdata = DNS_RDATA_INIT;
11720 dns_rdataset_t nsrdset;
11721 dns_rdataset_t soardset;
11722 isc_result_t result;
11723 unsigned int i;
11724 isc_sockaddr_t dst;
11725 bool isqueued;
11726 dns_notifytype_t notifytype;
11727 unsigned int flags = 0;
11728 bool loggednotify = false;
11729 bool startup;
11730
11731 REQUIRE(DNS_ZONE_VALID(zone));
11732
11733 LOCK_ZONE(zone);
11734 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11735 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11736 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
11737 notifytype = zone->notifytype;
11738 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
11739 UNLOCK_ZONE(zone);
11740
11741 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11742 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11743 return;
11744
11745 if (notifytype == dns_notifytype_no)
11746 return;
11747
11748 if (notifytype == dns_notifytype_masteronly &&
11749 zone->type != dns_zone_master)
11750 return;
11751
11752 origin = &zone->origin;
11753
11754 /*
11755 * If the zone is dialup we are done as we don't want to send
11756 * the current soa so as to force a refresh query.
11757 */
11758 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
11759 flags |= DNS_NOTIFY_NOSOA;
11760
11761 /*
11762 * Record that this was a notify due to starting up.
11763 */
11764 if (startup)
11765 flags |= DNS_NOTIFY_STARTUP;
11766
11767 /*
11768 * Get SOA RRset.
11769 */
11770 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11771 if (zone->db != NULL)
11772 dns_db_attach(zone->db, &zonedb);
11773 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11774 if (zonedb == NULL)
11775 return;
11776 dns_db_currentversion(zonedb, &version);
11777 result = dns_db_findnode(zonedb, origin, false, &node);
11778 if (result != ISC_R_SUCCESS)
11779 goto cleanup1;
11780
11781 dns_rdataset_init(&soardset);
11782 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
11783 dns_rdatatype_none, 0, &soardset, NULL);
11784 if (result != ISC_R_SUCCESS)
11785 goto cleanup2;
11786
11787 /*
11788 * Find serial and master server's name.
11789 */
11790 dns_name_init(&master, NULL);
11791 result = dns_rdataset_first(&soardset);
11792 if (result != ISC_R_SUCCESS)
11793 goto cleanup3;
11794 dns_rdataset_current(&soardset, &rdata);
11795 result = dns_rdata_tostruct(&rdata, &soa, NULL);
11796 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11797 dns_rdata_reset(&rdata);
11798 result = dns_name_dup(&soa.origin, zone->mctx, &master);
11799 serial = soa.serial;
11800 dns_rdataset_disassociate(&soardset);
11801 if (result != ISC_R_SUCCESS)
11802 goto cleanup3;
11803
11804 /*
11805 * Enqueue notify requests for 'also-notify' servers.
11806 */
11807 LOCK_ZONE(zone);
11808 for (i = 0; i < zone->notifycnt; i++) {
11809 dns_tsigkey_t *key = NULL;
11810 dns_notify_t *notify = NULL;
11811
11812 if ((zone->notifykeynames != NULL) &&
11813 (zone->notifykeynames[i] != NULL)) {
11814 dns_view_t *view = dns_zone_getview(zone);
11815 dns_name_t *keyname = zone->notifykeynames[i];
11816 (void)dns_view_gettsig(view, keyname, &key);
11817 }
11818
11819 dst = zone->notify[i];
11820 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
11821 if (key != NULL)
11822 dns_tsigkey_detach(&key);
11823 continue;
11824 }
11825
11826 result = notify_create(zone->mctx, flags, ¬ify);
11827 if (result != ISC_R_SUCCESS) {
11828 if (key != NULL)
11829 dns_tsigkey_detach(&key);
11830 continue;
11831 }
11832
11833 zone_iattach(zone, ¬ify->zone);
11834 notify->dst = dst;
11835
11836 INSIST(notify->key == NULL);
11837
11838 if (key != NULL) {
11839 notify->key = key;
11840 key = NULL;
11841 }
11842
11843 ISC_LIST_APPEND(zone->notifies, notify, link);
11844 result = notify_send_queue(notify, startup);
11845 if (result != ISC_R_SUCCESS)
11846 notify_destroy(notify, true);
11847 if (!loggednotify) {
11848 notify_log(zone, ISC_LOG_INFO,
11849 "sending notifies (serial %u)",
11850 serial);
11851 loggednotify = true;
11852 }
11853 }
11854 UNLOCK_ZONE(zone);
11855
11856 if (notifytype == dns_notifytype_explicit)
11857 goto cleanup3;
11858
11859 /*
11860 * Process NS RRset to generate notifies.
11861 */
11862
11863 dns_rdataset_init(&nsrdset);
11864 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
11865 dns_rdatatype_none, 0, &nsrdset, NULL);
11866 if (result != ISC_R_SUCCESS)
11867 goto cleanup3;
11868
11869 result = dns_rdataset_first(&nsrdset);
11870 while (result == ISC_R_SUCCESS) {
11871 dns_notify_t *notify = NULL;
11872
11873 dns_rdataset_current(&nsrdset, &rdata);
11874 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11875 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11876 dns_rdata_reset(&rdata);
11877 /*
11878 * Don't notify the master server unless explicitly
11879 * configured to do so.
11880 */
11881 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
11882 dns_name_compare(&master, &ns.name) == 0) {
11883 result = dns_rdataset_next(&nsrdset);
11884 continue;
11885 }
11886
11887 if (!loggednotify) {
11888 notify_log(zone, ISC_LOG_INFO,
11889 "sending notifies (serial %u)",
11890 serial);
11891 loggednotify = true;
11892 }
11893
11894 LOCK_ZONE(zone);
11895 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
11896 UNLOCK_ZONE(zone);
11897 if (isqueued) {
11898 result = dns_rdataset_next(&nsrdset);
11899 continue;
11900 }
11901 result = notify_create(zone->mctx, flags, ¬ify);
11902 if (result != ISC_R_SUCCESS)
11903 continue;
11904 dns_zone_iattach(zone, ¬ify->zone);
11905 result = dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
11906 if (result != ISC_R_SUCCESS) {
11907 LOCK_ZONE(zone);
11908 notify_destroy(notify, true);
11909 UNLOCK_ZONE(zone);
11910 continue;
11911 }
11912 LOCK_ZONE(zone);
11913 ISC_LIST_APPEND(zone->notifies, notify, link);
11914 UNLOCK_ZONE(zone);
11915 notify_find_address(notify);
11916 result = dns_rdataset_next(&nsrdset);
11917 }
11918 dns_rdataset_disassociate(&nsrdset);
11919
11920 cleanup3:
11921 if (dns_name_dynamic(&master))
11922 dns_name_free(&master, zone->mctx);
11923 cleanup2:
11924 dns_db_detachnode(zonedb, &node);
11925 cleanup1:
11926 dns_db_closeversion(zonedb, &version, false);
11927 dns_db_detach(&zonedb);
11928 }
11929
11930 /***
11931 *** Private
11932 ***/
11933
11934 static inline isc_result_t
11935 save_nsrrset(dns_message_t *message, dns_name_t *name,
11936 dns_db_t *db, dns_dbversion_t *version)
11937 {
11938 dns_rdataset_t *nsrdataset = NULL;
11939 dns_rdataset_t *rdataset = NULL;
11940 dns_dbnode_t *node = NULL;
11941 dns_rdata_ns_t ns;
11942 isc_result_t result;
11943 dns_rdata_t rdata = DNS_RDATA_INIT;
11944
11945 /*
11946 * Extract NS RRset from message.
11947 */
11948 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
11949 dns_rdatatype_ns, dns_rdatatype_none,
11950 NULL, &nsrdataset);
11951 if (result != ISC_R_SUCCESS)
11952 goto fail;
11953
11954 /*
11955 * Add NS rdataset.
11956 */
11957 result = dns_db_findnode(db, name, true, &node);
11958 if (result != ISC_R_SUCCESS)
11959 goto fail;
11960 result = dns_db_addrdataset(db, node, version, 0,
11961 nsrdataset, 0, NULL);
11962 dns_db_detachnode(db, &node);
11963 if (result != ISC_R_SUCCESS)
11964 goto fail;
11965 /*
11966 * Add glue rdatasets.
11967 */
11968 for (result = dns_rdataset_first(nsrdataset);
11969 result == ISC_R_SUCCESS;
11970 result = dns_rdataset_next(nsrdataset)) {
11971 dns_rdataset_current(nsrdataset, &rdata);
11972 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11973 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11974 dns_rdata_reset(&rdata);
11975 if (!dns_name_issubdomain(&ns.name, name))
11976 continue;
11977 rdataset = NULL;
11978 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11979 &ns.name, dns_rdatatype_aaaa,
11980 dns_rdatatype_none, NULL,
11981 &rdataset);
11982 if (result == ISC_R_SUCCESS) {
11983 result = dns_db_findnode(db, &ns.name,
11984 true, &node);
11985 if (result != ISC_R_SUCCESS)
11986 goto fail;
11987 result = dns_db_addrdataset(db, node, version, 0,
11988 rdataset, 0, NULL);
11989 dns_db_detachnode(db, &node);
11990 if (result != ISC_R_SUCCESS)
11991 goto fail;
11992 }
11993 rdataset = NULL;
11994 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11995 &ns.name, dns_rdatatype_a,
11996 dns_rdatatype_none, NULL,
11997 &rdataset);
11998 if (result == ISC_R_SUCCESS) {
11999 result = dns_db_findnode(db, &ns.name,
12000 true, &node);
12001 if (result != ISC_R_SUCCESS)
12002 goto fail;
12003 result = dns_db_addrdataset(db, node, version, 0,
12004 rdataset, 0, NULL);
12005 dns_db_detachnode(db, &node);
12006 if (result != ISC_R_SUCCESS)
12007 goto fail;
12008 }
12009 }
12010 if (result != ISC_R_NOMORE)
12011 goto fail;
12012
12013 return (ISC_R_SUCCESS);
12014
12015 fail:
12016 return (result);
12017 }
12018
12019 static void
12020 stub_callback(isc_task_t *task, isc_event_t *event) {
12021 const char me[] = "stub_callback";
12022 dns_requestevent_t *revent = (dns_requestevent_t *)event;
12023 dns_stub_t *stub = NULL;
12024 dns_message_t *msg = NULL;
12025 dns_zone_t *zone = NULL;
12026 char master[ISC_SOCKADDR_FORMATSIZE];
12027 char source[ISC_SOCKADDR_FORMATSIZE];
12028 uint32_t nscnt, cnamecnt, refresh, retry, expire;
12029 isc_result_t result;
12030 isc_time_t now;
12031 bool exiting = false;
12032 isc_interval_t i;
12033 unsigned int j, soacount;
12034
12035 stub = revent->ev_arg;
12036 INSIST(DNS_STUB_VALID(stub));
12037
12038 UNUSED(task);
12039
12040 zone = stub->zone;
12041
12042 ENTER;
12043
12044 TIME_NOW(&now);
12045
12046 LOCK_ZONE(zone);
12047
12048 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12049 zone_debuglog(zone, me, 1, "exiting");
12050 exiting = true;
12051 goto next_master;
12052 }
12053
12054 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12055 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12056
12057 if (revent->result != ISC_R_SUCCESS) {
12058 if (revent->result == ISC_R_TIMEDOUT &&
12059 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12060 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12061 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12062 "refreshing stub: timeout retrying "
12063 " without EDNS master %s (source %s)",
12064 master, source);
12065 goto same_master;
12066 }
12067 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
12068 &zone->sourceaddr, &now);
12069 dns_zone_log(zone, ISC_LOG_INFO,
12070 "could not refresh stub from master %s"
12071 " (source %s): %s", master, source,
12072 dns_result_totext(revent->result));
12073 goto next_master;
12074 }
12075
12076 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12077 if (result != ISC_R_SUCCESS)
12078 goto next_master;
12079
12080 result = dns_request_getresponse(revent->request, msg, 0);
12081 if (result != ISC_R_SUCCESS)
12082 goto next_master;
12083
12084 /*
12085 * Unexpected rcode.
12086 */
12087 if (msg->rcode != dns_rcode_noerror) {
12088 char rcode[128];
12089 isc_buffer_t rb;
12090
12091 isc_buffer_init(&rb, rcode, sizeof(rcode));
12092 (void)dns_rcode_totext(msg->rcode, &rb);
12093
12094 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12095 (msg->rcode == dns_rcode_servfail ||
12096 msg->rcode == dns_rcode_notimp ||
12097 msg->rcode == dns_rcode_formerr)) {
12098 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12099 "refreshing stub: rcode (%.*s) retrying "
12100 "without EDNS master %s (source %s)",
12101 (int)rb.used, rcode, master, source);
12102 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12103 goto same_master;
12104 }
12105
12106 dns_zone_log(zone, ISC_LOG_INFO,
12107 "refreshing stub: "
12108 "unexpected rcode (%.*s) from %s (source %s)",
12109 (int)rb.used, rcode, master, source);
12110 goto next_master;
12111 }
12112
12113 /*
12114 * We need complete messages.
12115 */
12116 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
12117 if (dns_request_usedtcp(revent->request)) {
12118 dns_zone_log(zone, ISC_LOG_INFO,
12119 "refreshing stub: truncated TCP "
12120 "response from master %s (source %s)",
12121 master, source);
12122 goto next_master;
12123 }
12124 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
12125 goto same_master;
12126 }
12127
12128 /*
12129 * If non-auth log and next master.
12130 */
12131 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
12132 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
12133 "non-authoritative answer from "
12134 "master %s (source %s)", master, source);
12135 goto next_master;
12136 }
12137
12138 /*
12139 * Sanity checks.
12140 */
12141 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12142 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
12143
12144 if (cnamecnt != 0) {
12145 dns_zone_log(zone, ISC_LOG_INFO,
12146 "refreshing stub: unexpected CNAME response "
12147 "from master %s (source %s)", master, source);
12148 goto next_master;
12149 }
12150
12151 if (nscnt == 0) {
12152 dns_zone_log(zone, ISC_LOG_INFO,
12153 "refreshing stub: no NS records in response "
12154 "from master %s (source %s)", master, source);
12155 goto next_master;
12156 }
12157
12158 /*
12159 * Save answer.
12160 */
12161 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
12162 if (result != ISC_R_SUCCESS) {
12163 dns_zone_log(zone, ISC_LOG_INFO,
12164 "refreshing stub: unable to save NS records "
12165 "from master %s (source %s)", master, source);
12166 goto next_master;
12167 }
12168
12169 /*
12170 * Tidy up.
12171 */
12172 dns_db_closeversion(stub->db, &stub->version, true);
12173 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
12174 if (zone->db == NULL)
12175 zone_attachdb(zone, stub->db);
12176 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
12177 &refresh, &retry, &expire, NULL, NULL);
12178 if (result == ISC_R_SUCCESS && soacount > 0U) {
12179 zone->refresh = RANGE(refresh, zone->minrefresh,
12180 zone->maxrefresh);
12181 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
12182 zone->expire = RANGE(expire, zone->refresh + zone->retry,
12183 DNS_MAX_EXPIRE);
12184 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
12185 }
12186 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
12187 dns_db_detach(&stub->db);
12188
12189 dns_message_destroy(&msg);
12190 isc_event_free(&event);
12191 dns_request_destroy(&zone->request);
12192
12193 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12194 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
12195 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12196 isc_interval_set(&i, zone->expire, 0);
12197 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
12198
12199 if (zone->masterfile != NULL)
12200 zone_needdump(zone, 0);
12201
12202 zone_settimer(zone, &now);
12203 goto free_stub;
12204
12205 next_master:
12206 if (stub->version != NULL)
12207 dns_db_closeversion(stub->db, &stub->version, false);
12208 if (stub->db != NULL)
12209 dns_db_detach(&stub->db);
12210 if (msg != NULL)
12211 dns_message_destroy(&msg);
12212 isc_event_free(&event);
12213 dns_request_destroy(&zone->request);
12214 /*
12215 * Skip to next failed / untried master.
12216 */
12217 do {
12218 zone->curmaster++;
12219 } while (zone->curmaster < zone->masterscnt &&
12220 zone->mastersok[zone->curmaster]);
12221 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
12222 if (exiting || zone->curmaster >= zone->masterscnt) {
12223 bool done = true;
12224 if (!exiting &&
12225 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12226 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12227 /*
12228 * Did we get a good answer from all the masters?
12229 */
12230 for (j = 0; j < zone->masterscnt; j++)
12231 if (zone->mastersok[j] == false) {
12232 done = false;
12233 break;
12234 }
12235 } else
12236 done = true;
12237 if (!done) {
12238 zone->curmaster = 0;
12239 /*
12240 * Find the next failed master.
12241 */
12242 while (zone->curmaster < zone->masterscnt &&
12243 zone->mastersok[zone->curmaster])
12244 zone->curmaster++;
12245 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12246 } else {
12247 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12248
12249 zone_settimer(zone, &now);
12250 goto free_stub;
12251 }
12252 }
12253 queue_soa_query(zone);
12254 goto free_stub;
12255
12256 same_master:
12257 if (msg != NULL)
12258 dns_message_destroy(&msg);
12259 isc_event_free(&event);
12260 dns_request_destroy(&zone->request);
12261 ns_query(zone, NULL, stub);
12262 UNLOCK_ZONE(zone);
12263 goto done;
12264
12265 free_stub:
12266 UNLOCK_ZONE(zone);
12267 stub->magic = 0;
12268 dns_zone_idetach(&stub->zone);
12269 INSIST(stub->db == NULL);
12270 INSIST(stub->version == NULL);
12271 isc_mem_put(stub->mctx, stub, sizeof(*stub));
12272
12273 done:
12274 INSIST(event == NULL);
12275 return;
12276 }
12277
12278 /*
12279 * Get the EDNS EXPIRE option from the response and if it exists trim
12280 * expire to be not more than it.
12281 */
12282 static void
12283 get_edns_expire(dns_zone_t * zone, dns_message_t *message,
12284 uint32_t *expirep)
12285 {
12286 isc_result_t result;
12287 uint32_t expire;
12288 dns_rdata_t rdata = DNS_RDATA_INIT;
12289 isc_buffer_t optbuf;
12290 uint16_t optcode;
12291 uint16_t optlen;
12292
12293 REQUIRE(expirep != NULL);
12294 REQUIRE(message != NULL);
12295
12296 if (message->opt == NULL)
12297 return;
12298
12299 result = dns_rdataset_first(message->opt);
12300 if (result == ISC_R_SUCCESS) {
12301 dns_rdataset_current(message->opt, &rdata);
12302 isc_buffer_init(&optbuf, rdata.data, rdata.length);
12303 isc_buffer_add(&optbuf, rdata.length);
12304 while (isc_buffer_remaininglength(&optbuf) >= 4) {
12305 optcode = isc_buffer_getuint16(&optbuf);
12306 optlen = isc_buffer_getuint16(&optbuf);
12307 /*
12308 * A EDNS EXPIRE response has a length of 4.
12309 */
12310 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
12311 isc_buffer_forward(&optbuf, optlen);
12312 continue;
12313 }
12314 expire = isc_buffer_getuint32(&optbuf);
12315 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12316 "got EDNS EXPIRE of %u", expire);
12317 /*
12318 * Trim *expirep?
12319 */
12320 if (expire < *expirep)
12321 *expirep = expire;
12322 break;
12323 }
12324 }
12325 }
12326
12327 /*
12328 * Set the file modification time zone->expire seconds before expiretime.
12329 */
12330 static void
12331 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
12332 isc_result_t result;
12333 isc_time_t when;
12334 isc_interval_t i;
12335
12336 isc_interval_set(&i, zone->expire, 0);
12337 result = isc_time_subtract(expiretime, &i, &when);
12338 if (result != ISC_R_SUCCESS)
12339 return;
12340
12341 result = ISC_R_FAILURE;
12342 if (zone->journal != NULL)
12343 result = isc_file_settime(zone->journal, &when);
12344 if (result == ISC_R_SUCCESS &&
12345 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12346 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
12347 result = isc_file_settime(zone->masterfile, &when);
12348 else if (result != ISC_R_SUCCESS)
12349 result = isc_file_settime(zone->masterfile, &when);
12350
12351 /*
12352 * Someone removed the file from underneath us!
12353 */
12354 if (result == ISC_R_FILENOTFOUND) {
12355 zone_needdump(zone, DNS_DUMP_DELAY);
12356 } else if (result != ISC_R_SUCCESS)
12357 dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
12358 "file modification time of '%s': %s",
12359 zone->masterfile, dns_result_totext(result));
12360 }
12361
12362 /*
12363 * An SOA query has finished (successfully or not).
12364 */
12365 static void
12366 refresh_callback(isc_task_t *task, isc_event_t *event) {
12367 const char me[] = "refresh_callback";
12368 dns_requestevent_t *revent = (dns_requestevent_t *)event;
12369 dns_zone_t *zone;
12370 dns_message_t *msg = NULL;
12371 uint32_t soacnt, cnamecnt, soacount, nscount;
12372 isc_time_t now;
12373 char master[ISC_SOCKADDR_FORMATSIZE];
12374 char source[ISC_SOCKADDR_FORMATSIZE];
12375 dns_rdataset_t *rdataset = NULL;
12376 dns_rdata_t rdata = DNS_RDATA_INIT;
12377 dns_rdata_soa_t soa;
12378 isc_result_t result;
12379 uint32_t serial, oldserial = 0;
12380 unsigned int j;
12381 bool do_queue_xfrin = false;
12382
12383 zone = revent->ev_arg;
12384 INSIST(DNS_ZONE_VALID(zone));
12385
12386 UNUSED(task);
12387
12388 ENTER;
12389
12390 TIME_NOW(&now);
12391
12392 LOCK_ZONE(zone);
12393
12394 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12395 isc_event_free(&event);
12396 dns_request_destroy(&zone->request);
12397 goto detach;
12398 }
12399
12400 /*
12401 * if timeout log and next master;
12402 */
12403
12404 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
12405 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
12406
12407 if (revent->result != ISC_R_SUCCESS) {
12408 if (revent->result == ISC_R_TIMEDOUT &&
12409 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12410 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12411 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12412 "refresh: timeout retrying without EDNS "
12413 "master %s (source %s)", master, source);
12414 goto same_master;
12415 }
12416 if (revent->result == ISC_R_TIMEDOUT &&
12417 !dns_request_usedtcp(revent->request)) {
12418 dns_zone_log(zone, ISC_LOG_INFO,
12419 "refresh: retry limit for "
12420 "master %s exceeded (source %s)",
12421 master, source);
12422 /* Try with slave with TCP. */
12423 if ((zone->type == dns_zone_slave ||
12424 zone->type == dns_zone_mirror ||
12425 zone->type == dns_zone_redirect) &&
12426 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
12427 {
12428 if (!dns_zonemgr_unreachable(zone->zmgr,
12429 &zone->masteraddr,
12430 &zone->sourceaddr,
12431 &now))
12432 {
12433 DNS_ZONE_SETFLAG(zone,
12434 DNS_ZONEFLG_SOABEFOREAXFR);
12435 goto tcp_transfer;
12436 }
12437 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12438 "refresh: skipped tcp fallback "
12439 "as master %s (source %s) is "
12440 "unreachable (cached)",
12441 master, source);
12442 }
12443 } else
12444 dns_zone_log(zone, ISC_LOG_INFO,
12445 "refresh: failure trying master "
12446 "%s (source %s): %s", master, source,
12447 dns_result_totext(revent->result));
12448 goto next_master;
12449 }
12450
12451 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
12452 if (result != ISC_R_SUCCESS)
12453 goto next_master;
12454 result = dns_request_getresponse(revent->request, msg, 0);
12455 if (result != ISC_R_SUCCESS) {
12456 dns_zone_log(zone, ISC_LOG_INFO,
12457 "refresh: failure trying master "
12458 "%s (source %s): %s", master, source,
12459 dns_result_totext(result));
12460 goto next_master;
12461 }
12462
12463 /*
12464 * Unexpected rcode.
12465 */
12466 if (msg->rcode != dns_rcode_noerror) {
12467 char rcode[128];
12468 isc_buffer_t rb;
12469
12470 isc_buffer_init(&rb, rcode, sizeof(rcode));
12471 (void)dns_rcode_totext(msg->rcode, &rb);
12472
12473 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12474 (msg->rcode == dns_rcode_servfail ||
12475 msg->rcode == dns_rcode_notimp ||
12476 msg->rcode == dns_rcode_formerr)) {
12477 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12478 "refresh: rcode (%.*s) retrying without "
12479 "EDNS master %s (source %s)",
12480 (int)rb.used, rcode, master, source);
12481 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12482 goto same_master;
12483 }
12484 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12485 msg->rcode == dns_rcode_badvers) {
12486 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12487 "refresh: rcode (%.*s) retrying without "
12488 "EDNS EXPIRE OPTION master %s (source %s)",
12489 (int)rb.used, rcode, master, source);
12490 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12491 goto same_master;
12492 }
12493 dns_zone_log(zone, ISC_LOG_INFO,
12494 "refresh: unexpected rcode (%.*s) from "
12495 "master %s (source %s)", (int)rb.used, rcode,
12496 master, source);
12497 /*
12498 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
12499 */
12500 if (msg->rcode == dns_rcode_refused &&
12501 (zone->type == dns_zone_slave ||
12502 zone->type == dns_zone_mirror ||
12503 zone->type == dns_zone_redirect))
12504 {
12505 goto tcp_transfer;
12506 }
12507 goto next_master;
12508 }
12509
12510 /*
12511 * If truncated punt to zone transfer which will query again.
12512 */
12513 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
12514 if (zone->type == dns_zone_slave ||
12515 zone->type == dns_zone_mirror ||
12516 zone->type == dns_zone_redirect)
12517 {
12518 dns_zone_log(zone, ISC_LOG_INFO,
12519 "refresh: truncated UDP answer, "
12520 "initiating TCP zone xfer "
12521 "for master %s (source %s)",
12522 master, source);
12523 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
12524 goto tcp_transfer;
12525 } else {
12526 INSIST(zone->type == dns_zone_stub);
12527 if (dns_request_usedtcp(revent->request)) {
12528 dns_zone_log(zone, ISC_LOG_INFO,
12529 "refresh: truncated TCP response "
12530 "from master %s (source %s)",
12531 master, source);
12532 goto next_master;
12533 }
12534 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
12535 goto same_master;
12536 }
12537 }
12538
12539 /*
12540 * if non-auth log and next master;
12541 */
12542 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
12543 dns_zone_log(zone, ISC_LOG_INFO,
12544 "refresh: non-authoritative answer from "
12545 "master %s (source %s)", master, source);
12546 goto next_master;
12547 }
12548
12549 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12550 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
12551 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
12552 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
12553 dns_rdatatype_soa);
12554
12555 /*
12556 * There should not be a CNAME record at top of zone.
12557 */
12558 if (cnamecnt != 0) {
12559 dns_zone_log(zone, ISC_LOG_INFO,
12560 "refresh: CNAME at top of zone "
12561 "in master %s (source %s)", master, source);
12562 goto next_master;
12563 }
12564
12565 /*
12566 * if referral log and next master;
12567 */
12568 if (soacnt == 0 && soacount == 0 && nscount != 0) {
12569 dns_zone_log(zone, ISC_LOG_INFO,
12570 "refresh: referral response "
12571 "from master %s (source %s)", master, source);
12572 goto next_master;
12573 }
12574
12575 /*
12576 * if nodata log and next master;
12577 */
12578 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
12579 dns_zone_log(zone, ISC_LOG_INFO,
12580 "refresh: NODATA response "
12581 "from master %s (source %s)", master, source);
12582 goto next_master;
12583 }
12584
12585 /*
12586 * Only one soa at top of zone.
12587 */
12588 if (soacnt != 1) {
12589 dns_zone_log(zone, ISC_LOG_INFO,
12590 "refresh: answer SOA count (%d) != 1 "
12591 "from master %s (source %s)",
12592 soacnt, master, source);
12593 goto next_master;
12594 }
12595
12596 /*
12597 * Extract serial
12598 */
12599 rdataset = NULL;
12600 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
12601 dns_rdatatype_soa, dns_rdatatype_none,
12602 NULL, &rdataset);
12603 if (result != ISC_R_SUCCESS) {
12604 dns_zone_log(zone, ISC_LOG_INFO,
12605 "refresh: unable to get SOA record "
12606 "from master %s (source %s)", master, source);
12607 goto next_master;
12608 }
12609
12610 result = dns_rdataset_first(rdataset);
12611 if (result != ISC_R_SUCCESS) {
12612 dns_zone_log(zone, ISC_LOG_INFO,
12613 "refresh: dns_rdataset_first() failed");
12614 goto next_master;
12615 }
12616
12617 dns_rdataset_current(rdataset, &rdata);
12618 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12619 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12620
12621 serial = soa.serial;
12622 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
12623 unsigned int dbsoacount;
12624 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
12625 &oldserial, NULL, NULL, NULL, NULL,
12626 NULL);
12627 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12628 RUNTIME_CHECK(dbsoacount > 0U);
12629 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
12630 serial, oldserial);
12631 } else
12632 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
12633 serial);
12634
12635 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
12636 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
12637 isc_serial_gt(serial, oldserial)) {
12638 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12639 &zone->sourceaddr, &now))
12640 {
12641 dns_zone_log(zone, ISC_LOG_INFO,
12642 "refresh: skipping %s as master %s "
12643 "(source %s) is unreachable (cached)",
12644 (zone->type == dns_zone_slave ||
12645 zone->type == dns_zone_mirror ||
12646 zone->type == dns_zone_redirect) ?
12647 "zone transfer" : "NS query",
12648 master, source);
12649 goto next_master;
12650 }
12651 tcp_transfer:
12652 isc_event_free(&event);
12653 dns_request_destroy(&zone->request);
12654 if (zone->type == dns_zone_slave ||
12655 zone->type == dns_zone_mirror ||
12656 zone->type == dns_zone_redirect)
12657 {
12658 do_queue_xfrin = true;
12659 } else {
12660 INSIST(zone->type == dns_zone_stub);
12661 ns_query(zone, rdataset, NULL);
12662 }
12663 if (msg != NULL)
12664 dns_message_destroy(&msg);
12665 } else if (isc_serial_eq(soa.serial, oldserial)) {
12666 isc_time_t expiretime;
12667 uint32_t expire;
12668
12669 /*
12670 * Compute the new expire time based on this response.
12671 */
12672 expire = zone->expire;
12673 get_edns_expire(zone, msg, &expire);
12674 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
12675
12676 /*
12677 * Has the expire time improved?
12678 */
12679 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
12680 zone->expiretime = expiretime;
12681 if (zone->masterfile != NULL)
12682 setmodtime(zone, &expiretime);
12683 }
12684
12685 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12686 zone->mastersok[zone->curmaster] = true;
12687 goto next_master;
12688 } else {
12689 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
12690 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
12691 "received from master %s < ours (%u)",
12692 soa.serial, master, oldserial);
12693 else
12694 zone_debuglog(zone, me, 1, "ahead");
12695 zone->mastersok[zone->curmaster] = true;
12696 goto next_master;
12697 }
12698 if (msg != NULL)
12699 dns_message_destroy(&msg);
12700 goto detach;
12701
12702 next_master:
12703 if (msg != NULL)
12704 dns_message_destroy(&msg);
12705 isc_event_free(&event);
12706 dns_request_destroy(&zone->request);
12707 /*
12708 * Skip to next failed / untried master.
12709 */
12710 do {
12711 zone->curmaster++;
12712 } while (zone->curmaster < zone->masterscnt &&
12713 zone->mastersok[zone->curmaster]);
12714 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
12715 if (zone->curmaster >= zone->masterscnt) {
12716 bool done = true;
12717 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
12718 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12719 /*
12720 * Did we get a good answer from all the masters?
12721 */
12722 for (j = 0; j < zone->masterscnt; j++)
12723 if (zone->mastersok[j] == false) {
12724 done = false;
12725 break;
12726 }
12727 } else
12728 done = true;
12729 if (!done) {
12730 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12731 zone->curmaster = 0;
12732 /*
12733 * Find the next failed master.
12734 */
12735 while (zone->curmaster < zone->masterscnt &&
12736 zone->mastersok[zone->curmaster])
12737 zone->curmaster++;
12738 goto requeue;
12739 }
12740 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12741 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
12742 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12743 zone->refreshtime = now;
12744 }
12745 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12746 zone_settimer(zone, &now);
12747 goto detach;
12748 }
12749
12750 requeue:
12751 queue_soa_query(zone);
12752 goto detach;
12753
12754 same_master:
12755 if (msg != NULL)
12756 dns_message_destroy(&msg);
12757 isc_event_free(&event);
12758 dns_request_destroy(&zone->request);
12759 queue_soa_query(zone);
12760
12761 detach:
12762 UNLOCK_ZONE(zone);
12763 if (do_queue_xfrin)
12764 queue_xfrin(zone);
12765 dns_zone_idetach(&zone);
12766 return;
12767 }
12768
12769 static void
12770 queue_soa_query(dns_zone_t *zone) {
12771 const char me[] = "queue_soa_query";
12772 isc_event_t *e;
12773 dns_zone_t *dummy = NULL;
12774 isc_result_t result;
12775
12776 ENTER;
12777 /*
12778 * Locked by caller
12779 */
12780 REQUIRE(LOCKED_ZONE(zone));
12781
12782 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12783 cancel_refresh(zone);
12784 return;
12785 }
12786
12787 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
12788 soa_query, zone, sizeof(isc_event_t));
12789 if (e == NULL) {
12790 cancel_refresh(zone);
12791 return;
12792 }
12793
12794 /*
12795 * Attach so that we won't clean up
12796 * until the event is delivered.
12797 */
12798 zone_iattach(zone, &dummy);
12799
12800 e->ev_arg = zone;
12801 e->ev_sender = NULL;
12802 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
12803 if (result != ISC_R_SUCCESS) {
12804 zone_idetach(&dummy);
12805 isc_event_free(&e);
12806 cancel_refresh(zone);
12807 }
12808 }
12809
12810 static inline isc_result_t
12811 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
12812 dns_message_t **messagep)
12813 {
12814 dns_message_t *message = NULL;
12815 dns_name_t *qname = NULL;
12816 dns_rdataset_t *qrdataset = NULL;
12817 isc_result_t result;
12818
12819 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
12820 &message);
12821 if (result != ISC_R_SUCCESS)
12822 goto cleanup;
12823
12824 message->opcode = dns_opcode_query;
12825 message->rdclass = zone->rdclass;
12826
12827 result = dns_message_gettempname(message, &qname);
12828 if (result != ISC_R_SUCCESS)
12829 goto cleanup;
12830
12831 result = dns_message_gettemprdataset(message, &qrdataset);
12832 if (result != ISC_R_SUCCESS)
12833 goto cleanup;
12834
12835 /*
12836 * Make question.
12837 */
12838 dns_name_init(qname, NULL);
12839 dns_name_clone(&zone->origin, qname);
12840 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
12841 ISC_LIST_APPEND(qname->list, qrdataset, link);
12842 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
12843
12844 *messagep = message;
12845 return (ISC_R_SUCCESS);
12846
12847 cleanup:
12848 if (qname != NULL)
12849 dns_message_puttempname(message, &qname);
12850 if (qrdataset != NULL)
12851 dns_message_puttemprdataset(message, &qrdataset);
12852 if (message != NULL)
12853 dns_message_destroy(&message);
12854 return (result);
12855 }
12856
12857 static isc_result_t
12858 add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid,
12859 bool reqexpire)
12860 {
12861 isc_result_t result;
12862 dns_rdataset_t *rdataset = NULL;
12863 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
12864 int count = 0;
12865
12866 /* Set EDNS options if applicable */
12867 if (reqnsid) {
12868 INSIST(count < DNS_EDNSOPTIONS);
12869 ednsopts[count].code = DNS_OPT_NSID;
12870 ednsopts[count].length = 0;
12871 ednsopts[count].value = NULL;
12872 count++;
12873 }
12874 if (reqexpire) {
12875 INSIST(count < DNS_EDNSOPTIONS);
12876 ednsopts[count].code = DNS_OPT_EXPIRE;
12877 ednsopts[count].length = 0;
12878 ednsopts[count].value = NULL;
12879 count++;
12880 }
12881 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
12882 ednsopts, count);
12883 if (result != ISC_R_SUCCESS)
12884 return (result);
12885
12886 return (dns_message_setopt(message, rdataset));
12887 }
12888
12889 static void
12890 soa_query(isc_task_t *task, isc_event_t *event) {
12891 const char me[] = "soa_query";
12892 isc_result_t result = ISC_R_FAILURE;
12893 dns_message_t *message = NULL;
12894 dns_zone_t *zone = event->ev_arg;
12895 dns_zone_t *dummy = NULL;
12896 isc_netaddr_t masterip;
12897 dns_tsigkey_t *key = NULL;
12898 uint32_t options;
12899 bool cancel = true;
12900 int timeout;
12901 bool have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
12902 uint16_t udpsize = SEND_BUFFER_SIZE;
12903 isc_dscp_t dscp = -1;
12904
12905 REQUIRE(DNS_ZONE_VALID(zone));
12906
12907 UNUSED(task);
12908
12909 ENTER;
12910
12911 LOCK_ZONE(zone);
12912 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
12913 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12914 zone->view->requestmgr == NULL) {
12915 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12916 cancel = false;
12917 goto cleanup;
12918 }
12919
12920 again:
12921 result = create_query(zone, dns_rdatatype_soa, &message);
12922 if (result != ISC_R_SUCCESS)
12923 goto cleanup;
12924
12925 INSIST(zone->masterscnt > 0);
12926 INSIST(zone->curmaster < zone->masterscnt);
12927
12928 zone->masteraddr = zone->masters[zone->curmaster];
12929
12930 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12931 /*
12932 * First, look for a tsig key in the master statement, then
12933 * try for a server key.
12934 */
12935 if ((zone->masterkeynames != NULL) &&
12936 (zone->masterkeynames[zone->curmaster] != NULL)) {
12937 dns_view_t *view = dns_zone_getview(zone);
12938 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12939 result = dns_view_gettsig(view, keyname, &key);
12940 if (result != ISC_R_SUCCESS) {
12941 char namebuf[DNS_NAME_FORMATSIZE];
12942 dns_name_format(keyname, namebuf, sizeof(namebuf));
12943 dns_zone_log(zone, ISC_LOG_ERROR,
12944 "unable to find key: %s", namebuf);
12945 goto skip_master;
12946 }
12947 }
12948 if (key == NULL) {
12949 result = dns_view_getpeertsig(zone->view, &masterip, &key);
12950 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12951 char addrbuf[ISC_NETADDR_FORMATSIZE];
12952 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
12953 dns_zone_log(zone, ISC_LOG_ERROR,
12954 "unable to find TSIG key for %s", addrbuf);
12955 goto skip_master;
12956 }
12957 }
12958
12959 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
12960 DNS_REQUESTOPT_TCP : 0;
12961 have_xfrsource = have_xfrdscp = false;
12962 reqnsid = zone->view->requestnsid;
12963 reqexpire = zone->requestexpire;
12964 if (zone->view->peers != NULL) {
12965 dns_peer_t *peer = NULL;
12966 bool edns, usetcp;
12967 result = dns_peerlist_peerbyaddr(zone->view->peers,
12968 &masterip, &peer);
12969 if (result == ISC_R_SUCCESS) {
12970 result = dns_peer_getsupportedns(peer, &edns);
12971 if (result == ISC_R_SUCCESS && !edns)
12972 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12973 result = dns_peer_gettransfersource(peer,
12974 &zone->sourceaddr);
12975 if (result == ISC_R_SUCCESS)
12976 have_xfrsource = true;
12977 (void)dns_peer_gettransferdscp(peer, &dscp);
12978 if (dscp != -1)
12979 have_xfrdscp = true;
12980 if (zone->view->resolver != NULL)
12981 udpsize =
12982 dns_resolver_getudpsize(zone->view->resolver);
12983 (void)dns_peer_getudpsize(peer, &udpsize);
12984 (void)dns_peer_getrequestnsid(peer, &reqnsid);
12985 (void)dns_peer_getrequestexpire(peer, &reqexpire);
12986 result = dns_peer_getforcetcp(peer, &usetcp);
12987 if (result == ISC_R_SUCCESS && usetcp)
12988 options |= DNS_REQUESTOPT_TCP;
12989 }
12990 }
12991
12992 switch (isc_sockaddr_pf(&zone->masteraddr)) {
12993 case PF_INET:
12994 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12995 if (isc_sockaddr_equal(&zone->altxfrsource4,
12996 &zone->xfrsource4))
12997 goto skip_master;
12998 zone->sourceaddr = zone->altxfrsource4;
12999 if (!have_xfrdscp)
13000 dscp = zone->altxfrsource4dscp;
13001 } else if (!have_xfrsource) {
13002 zone->sourceaddr = zone->xfrsource4;
13003 if (!have_xfrdscp)
13004 dscp = zone->xfrsource4dscp;
13005 }
13006 break;
13007 case PF_INET6:
13008 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13009 if (isc_sockaddr_equal(&zone->altxfrsource6,
13010 &zone->xfrsource6))
13011 goto skip_master;
13012 zone->sourceaddr = zone->altxfrsource6;
13013 if (!have_xfrdscp)
13014 dscp = zone->altxfrsource6dscp;
13015 } else if (!have_xfrsource) {
13016 zone->sourceaddr = zone->xfrsource6;
13017 if (!have_xfrdscp)
13018 dscp = zone->xfrsource6dscp;
13019 }
13020 break;
13021 default:
13022 result = ISC_R_NOTIMPLEMENTED;
13023 goto cleanup;
13024 }
13025
13026 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13027 result = add_opt(message, udpsize, reqnsid, reqexpire);
13028 if (result != ISC_R_SUCCESS)
13029 zone_debuglog(zone, me, 1,
13030 "unable to add opt record: %s",
13031 dns_result_totext(result));
13032 }
13033
13034 zone_iattach(zone, &dummy);
13035 timeout = 15;
13036 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13037 timeout = 30;
13038 result = dns_request_createvia(zone->view->requestmgr, message,
13039 &zone->sourceaddr, &zone->masteraddr,
13040 dscp, options, key, timeout * 3,
13041 timeout, 0, zone->task,
13042 refresh_callback, zone, &zone->request);
13043 if (result != ISC_R_SUCCESS) {
13044 zone_idetach(&dummy);
13045 zone_debuglog(zone, me, 1,
13046 "dns_request_createvia4() failed: %s",
13047 dns_result_totext(result));
13048 goto skip_master;
13049 } else {
13050 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
13051 inc_stats(zone, dns_zonestatscounter_soaoutv4);
13052 else
13053 inc_stats(zone, dns_zonestatscounter_soaoutv6);
13054 }
13055 cancel = false;
13056
13057 cleanup:
13058 if (key != NULL)
13059 dns_tsigkey_detach(&key);
13060 if (result != ISC_R_SUCCESS)
13061 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13062 if (message != NULL)
13063 dns_message_destroy(&message);
13064 if (cancel)
13065 cancel_refresh(zone);
13066 isc_event_free(&event);
13067 UNLOCK_ZONE(zone);
13068 dns_zone_idetach(&zone);
13069 return;
13070
13071 skip_master:
13072 if (key != NULL)
13073 dns_tsigkey_detach(&key);
13074 dns_message_destroy(&message);
13075 /*
13076 * Skip to next failed / untried master.
13077 */
13078 do {
13079 zone->curmaster++;
13080 } while (zone->curmaster < zone->masterscnt &&
13081 zone->mastersok[zone->curmaster]);
13082 if (zone->curmaster < zone->masterscnt)
13083 goto again;
13084 zone->curmaster = 0;
13085 goto cleanup;
13086 }
13087
13088 static void
13089 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
13090 const char me[] = "ns_query";
13091 isc_result_t result;
13092 dns_message_t *message = NULL;
13093 isc_netaddr_t masterip;
13094 dns_tsigkey_t *key = NULL;
13095 dns_dbnode_t *node = NULL;
13096 int timeout;
13097 bool have_xfrsource = false, have_xfrdscp = false;
13098 bool reqnsid;
13099 uint16_t udpsize = SEND_BUFFER_SIZE;
13100 isc_dscp_t dscp = -1;
13101
13102 REQUIRE(DNS_ZONE_VALID(zone));
13103 REQUIRE(LOCKED_ZONE(zone));
13104 REQUIRE((soardataset != NULL && stub == NULL) ||
13105 (soardataset == NULL && stub != NULL));
13106 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
13107
13108 ENTER;
13109
13110 if (stub == NULL) {
13111 stub = isc_mem_get(zone->mctx, sizeof(*stub));
13112 if (stub == NULL)
13113 goto cleanup;
13114 stub->magic = STUB_MAGIC;
13115 stub->mctx = zone->mctx;
13116 stub->zone = NULL;
13117 stub->db = NULL;
13118 stub->version = NULL;
13119
13120 /*
13121 * Attach so that the zone won't disappear from under us.
13122 */
13123 zone_iattach(zone, &stub->zone);
13124
13125 /*
13126 * If a db exists we will update it, otherwise we create a
13127 * new one and attach it to the zone once we have the NS
13128 * RRset and glue.
13129 */
13130 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13131 if (zone->db != NULL) {
13132 dns_db_attach(zone->db, &stub->db);
13133 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13134 } else {
13135 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13136
13137 INSIST(zone->db_argc >= 1);
13138 result = dns_db_create(zone->mctx, zone->db_argv[0],
13139 &zone->origin, dns_dbtype_stub,
13140 zone->rdclass,
13141 zone->db_argc - 1,
13142 zone->db_argv + 1,
13143 &stub->db);
13144 if (result != ISC_R_SUCCESS) {
13145 dns_zone_log(zone, ISC_LOG_ERROR,
13146 "refreshing stub: "
13147 "could not create "
13148 "database: %s",
13149 dns_result_totext(result));
13150 goto cleanup;
13151 }
13152 dns_db_settask(stub->db, zone->task);
13153 }
13154
13155 result = dns_db_newversion(stub->db, &stub->version);
13156 if (result != ISC_R_SUCCESS) {
13157 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
13158 "dns_db_newversion() failed: %s",
13159 dns_result_totext(result));
13160 goto cleanup;
13161 }
13162
13163 /*
13164 * Update SOA record.
13165 */
13166 result = dns_db_findnode(stub->db, &zone->origin, true,
13167 &node);
13168 if (result != ISC_R_SUCCESS) {
13169 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
13170 "dns_db_findnode() failed: %s",
13171 dns_result_totext(result));
13172 goto cleanup;
13173 }
13174
13175 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
13176 soardataset, 0, NULL);
13177 dns_db_detachnode(stub->db, &node);
13178 if (result != ISC_R_SUCCESS) {
13179 dns_zone_log(zone, ISC_LOG_INFO,
13180 "refreshing stub: "
13181 "dns_db_addrdataset() failed: %s",
13182 dns_result_totext(result));
13183 goto cleanup;
13184 }
13185 }
13186
13187 /*
13188 * XXX Optimisation: Create message when zone is setup and reuse.
13189 */
13190 result = create_query(zone, dns_rdatatype_ns, &message);
13191 INSIST(result == ISC_R_SUCCESS);
13192
13193 INSIST(zone->masterscnt > 0);
13194 INSIST(zone->curmaster < zone->masterscnt);
13195 zone->masteraddr = zone->masters[zone->curmaster];
13196
13197 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
13198 /*
13199 * First, look for a tsig key in the master statement, then
13200 * try for a server key.
13201 */
13202 if ((zone->masterkeynames != NULL) &&
13203 (zone->masterkeynames[zone->curmaster] != NULL)) {
13204 dns_view_t *view = dns_zone_getview(zone);
13205 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
13206 result = dns_view_gettsig(view, keyname, &key);
13207 if (result != ISC_R_SUCCESS) {
13208 char namebuf[DNS_NAME_FORMATSIZE];
13209 dns_name_format(keyname, namebuf, sizeof(namebuf));
13210 dns_zone_log(zone, ISC_LOG_ERROR,
13211 "unable to find key: %s", namebuf);
13212 }
13213 }
13214 if (key == NULL)
13215 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
13216
13217 reqnsid = zone->view->requestnsid;
13218 if (zone->view->peers != NULL) {
13219 dns_peer_t *peer = NULL;
13220 bool edns;
13221 result = dns_peerlist_peerbyaddr(zone->view->peers,
13222 &masterip, &peer);
13223 if (result == ISC_R_SUCCESS) {
13224 result = dns_peer_getsupportedns(peer, &edns);
13225 if (result == ISC_R_SUCCESS && !edns)
13226 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
13227 result = dns_peer_gettransfersource(peer,
13228 &zone->sourceaddr);
13229 if (result == ISC_R_SUCCESS)
13230 have_xfrsource = true;
13231 result = dns_peer_gettransferdscp(peer, &dscp);
13232 if (result == ISC_R_SUCCESS && dscp != -1)
13233 have_xfrdscp = true;
13234 if (zone->view->resolver != NULL)
13235 udpsize =
13236 dns_resolver_getudpsize(zone->view->resolver);
13237 (void)dns_peer_getudpsize(peer, &udpsize);
13238 (void)dns_peer_getrequestnsid(peer, &reqnsid);
13239 }
13240
13241 }
13242 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
13243 result = add_opt(message, udpsize, reqnsid, false);
13244 if (result != ISC_R_SUCCESS)
13245 zone_debuglog(zone, me, 1,
13246 "unable to add opt record: %s",
13247 dns_result_totext(result));
13248 }
13249
13250 /*
13251 * Always use TCP so that we shouldn't truncate in additional section.
13252 */
13253 switch (isc_sockaddr_pf(&zone->masteraddr)) {
13254 case PF_INET:
13255 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13256 zone->sourceaddr = zone->altxfrsource4;
13257 if (!have_xfrdscp)
13258 dscp = zone->altxfrsource4dscp;
13259 } else if (!have_xfrsource) {
13260 zone->sourceaddr = zone->xfrsource4;
13261 if (!have_xfrdscp)
13262 dscp = zone->xfrsource4dscp;
13263 }
13264 break;
13265 case PF_INET6:
13266 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
13267 zone->sourceaddr = zone->altxfrsource6;
13268 if (!have_xfrdscp)
13269 dscp = zone->altxfrsource6dscp;
13270 } else if (!have_xfrsource) {
13271 zone->sourceaddr = zone->xfrsource6;
13272 if (!have_xfrdscp)
13273 dscp = zone->xfrsource6dscp;
13274 }
13275 break;
13276 default:
13277 result = ISC_R_NOTIMPLEMENTED;
13278 POST(result);
13279 goto cleanup;
13280 }
13281 timeout = 15;
13282 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
13283 timeout = 30;
13284 result = dns_request_createvia(zone->view->requestmgr, message,
13285 &zone->sourceaddr, &zone->masteraddr,
13286 dscp, DNS_REQUESTOPT_TCP, key,
13287 timeout * 3, timeout, 0, zone->task,
13288 stub_callback, stub, &zone->request);
13289 if (result != ISC_R_SUCCESS) {
13290 zone_debuglog(zone, me, 1,
13291 "dns_request_createvia() failed: %s",
13292 dns_result_totext(result));
13293 goto cleanup;
13294 }
13295 dns_message_destroy(&message);
13296 goto unlock;
13297
13298 cleanup:
13299 cancel_refresh(zone);
13300 if (stub != NULL) {
13301 stub->magic = 0;
13302 if (stub->version != NULL)
13303 dns_db_closeversion(stub->db, &stub->version,
13304 false);
13305 if (stub->db != NULL)
13306 dns_db_detach(&stub->db);
13307 if (stub->zone != NULL)
13308 zone_idetach(&stub->zone);
13309 isc_mem_put(stub->mctx, stub, sizeof(*stub));
13310 }
13311 if (message != NULL)
13312 dns_message_destroy(&message);
13313 unlock:
13314 if (key != NULL)
13315 dns_tsigkey_detach(&key);
13316 return;
13317 }
13318
13319 /*
13320 * Handle the control event. Note that although this event causes the zone
13321 * to shut down, it is not a shutdown event in the sense of the task library.
13322 */
13323 static void
13324 zone_shutdown(isc_task_t *task, isc_event_t *event) {
13325 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
13326 bool free_needed, linked = false;
13327 dns_zone_t *raw = NULL, *secure = NULL;
13328
13329 UNUSED(task);
13330 REQUIRE(DNS_ZONE_VALID(zone));
13331 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
13332 INSIST(isc_refcount_current(&zone->erefs) == 0);
13333
13334 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
13335
13336 /*
13337 * Stop things being restarted after we cancel them below.
13338 */
13339 LOCK_ZONE(zone);
13340 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
13341 UNLOCK_ZONE(zone);
13342
13343 /*
13344 * If we were waiting for xfrin quota, step out of
13345 * the queue.
13346 * If there's no zone manager, we can't be waiting for the
13347 * xfrin quota
13348 */
13349 if (zone->zmgr != NULL) {
13350 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13351 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
13352 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
13353 statelink);
13354 linked = true;
13355 zone->statelist = NULL;
13356 }
13357 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
13358 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
13359 statelink);
13360 zone->statelist = NULL;
13361 zmgr_resume_xfrs(zone->zmgr, false);
13362 }
13363 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
13364 }
13365
13366 /*
13367 * In task context, no locking required. See zone_xfrdone().
13368 */
13369 if (zone->xfr != NULL)
13370 dns_xfrin_shutdown(zone->xfr);
13371
13372 /* Safe to release the zone now */
13373 if (zone->zmgr != NULL)
13374 dns_zonemgr_releasezone(zone->zmgr, zone);
13375
13376 LOCK_ZONE(zone);
13377 INSIST(zone != zone->raw);
13378 if (linked) {
13379 INSIST(zone->irefs > 0);
13380 zone->irefs--;
13381 }
13382 if (zone->request != NULL) {
13383 dns_request_cancel(zone->request);
13384 }
13385
13386 if (zone->readio != NULL)
13387 zonemgr_cancelio(zone->readio);
13388
13389 if (zone->lctx != NULL)
13390 dns_loadctx_cancel(zone->lctx);
13391
13392 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
13393 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13394 if (zone->writeio != NULL)
13395 zonemgr_cancelio(zone->writeio);
13396
13397 if (zone->dctx != NULL)
13398 dns_dumpctx_cancel(zone->dctx);
13399 }
13400
13401 notify_cancel(zone);
13402
13403 forward_cancel(zone);
13404
13405 if (zone->timer != NULL) {
13406 isc_timer_detach(&zone->timer);
13407 INSIST(zone->irefs > 0);
13408 zone->irefs--;
13409 }
13410
13411 /*
13412 * We have now canceled everything set the flag to allow exit_check()
13413 * to succeed. We must not unlock between setting this flag and
13414 * calling exit_check().
13415 */
13416 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
13417 free_needed = exit_check(zone);
13418 if (inline_secure(zone)) {
13419 raw = zone->raw;
13420 zone->raw = NULL;
13421 }
13422 if (inline_raw(zone)) {
13423 secure = zone->secure;
13424 zone->secure = NULL;
13425 }
13426 UNLOCK_ZONE(zone);
13427 if (raw != NULL)
13428 dns_zone_detach(&raw);
13429 if (secure != NULL)
13430 dns_zone_idetach(&secure);
13431 if (free_needed)
13432 zone_free(zone);
13433 }
13434
13435 static void
13436 zone_timer(isc_task_t *task, isc_event_t *event) {
13437 const char me[] = "zone_timer";
13438 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
13439
13440 UNUSED(task);
13441 REQUIRE(DNS_ZONE_VALID(zone));
13442
13443 ENTER;
13444
13445 zone_maintenance(zone);
13446
13447 isc_event_free(&event);
13448 }
13449
13450 static void
13451 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
13452 const char me[] = "zone_settimer";
13453 isc_time_t next;
13454 isc_result_t result;
13455
13456 REQUIRE(DNS_ZONE_VALID(zone));
13457 ENTER;
13458
13459 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
13460 return;
13461
13462 isc_time_settoepoch(&next);
13463
13464 switch (zone->type) {
13465 case dns_zone_redirect:
13466 if (zone->masters != NULL)
13467 goto treat_as_slave;
13468 /* FALLTHROUGH */
13469
13470 case dns_zone_master:
13471 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
13472 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
13473 next = zone->notifytime;
13474 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13475 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13476 INSIST(!isc_time_isepoch(&zone->dumptime));
13477 if (isc_time_isepoch(&next) ||
13478 isc_time_compare(&zone->dumptime, &next) < 0)
13479 next = zone->dumptime;
13480 }
13481 if (zone->type == dns_zone_redirect)
13482 break;
13483 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
13484 !isc_time_isepoch(&zone->refreshkeytime)) {
13485 if (isc_time_isepoch(&next) ||
13486 isc_time_compare(&zone->refreshkeytime, &next) < 0)
13487 next = zone->refreshkeytime;
13488 }
13489 if (!isc_time_isepoch(&zone->resigntime)) {
13490 if (isc_time_isepoch(&next) ||
13491 isc_time_compare(&zone->resigntime, &next) < 0)
13492 next = zone->resigntime;
13493 }
13494 if (!isc_time_isepoch(&zone->keywarntime)) {
13495 if (isc_time_isepoch(&next) ||
13496 isc_time_compare(&zone->keywarntime, &next) < 0)
13497 next = zone->keywarntime;
13498 }
13499 if (!isc_time_isepoch(&zone->signingtime)) {
13500 if (isc_time_isepoch(&next) ||
13501 isc_time_compare(&zone->signingtime, &next) < 0)
13502 next = zone->signingtime;
13503 }
13504 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
13505 if (isc_time_isepoch(&next) ||
13506 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
13507 next = zone->nsec3chaintime;
13508 }
13509 break;
13510
13511 case dns_zone_slave:
13512 case dns_zone_mirror:
13513 treat_as_slave:
13514 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
13515 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
13516 next = zone->notifytime;
13517 /* FALLTHROUGH */
13518
13519 case dns_zone_stub:
13520 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
13521 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
13522 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
13523 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
13524 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
13525 !isc_time_isepoch(&zone->refreshtime) &&
13526 (isc_time_isepoch(&next) ||
13527 isc_time_compare(&zone->refreshtime, &next) < 0))
13528 next = zone->refreshtime;
13529 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13530 !isc_time_isepoch(&zone->expiretime)) {
13531 if (isc_time_isepoch(&next) ||
13532 isc_time_compare(&zone->expiretime, &next) < 0)
13533 next = zone->expiretime;
13534 }
13535 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13536 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13537 INSIST(!isc_time_isepoch(&zone->dumptime));
13538 if (isc_time_isepoch(&next) ||
13539 isc_time_compare(&zone->dumptime, &next) < 0)
13540 next = zone->dumptime;
13541 }
13542 break;
13543
13544 case dns_zone_key:
13545 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13546 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13547 INSIST(!isc_time_isepoch(&zone->dumptime));
13548 if (isc_time_isepoch(&next) ||
13549 isc_time_compare(&zone->dumptime, &next) < 0)
13550 next = zone->dumptime;
13551 }
13552 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
13553 if (isc_time_isepoch(&next) ||
13554 (!isc_time_isepoch(&zone->refreshkeytime) &&
13555 isc_time_compare(&zone->refreshkeytime, &next) < 0))
13556 next = zone->refreshkeytime;
13557 }
13558 break;
13559
13560 default:
13561 break;
13562 }
13563
13564 if (isc_time_isepoch(&next)) {
13565 zone_debuglog(zone, me, 10, "settimer inactive");
13566 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
13567 NULL, NULL, true);
13568 if (result != ISC_R_SUCCESS)
13569 dns_zone_log(zone, ISC_LOG_ERROR,
13570 "could not deactivate zone timer: %s",
13571 isc_result_totext(result));
13572 } else {
13573 if (isc_time_compare(&next, now) <= 0)
13574 next = *now;
13575 result = isc_timer_reset(zone->timer, isc_timertype_once,
13576 &next, NULL, true);
13577 if (result != ISC_R_SUCCESS)
13578 dns_zone_log(zone, ISC_LOG_ERROR,
13579 "could not reset zone timer: %s",
13580 isc_result_totext(result));
13581 }
13582 }
13583
13584 static void
13585 cancel_refresh(dns_zone_t *zone) {
13586 const char me[] = "cancel_refresh";
13587 isc_time_t now;
13588
13589 /*
13590 * 'zone' locked by caller.
13591 */
13592
13593 REQUIRE(DNS_ZONE_VALID(zone));
13594 REQUIRE(LOCKED_ZONE(zone));
13595
13596 ENTER;
13597
13598 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13599 TIME_NOW(&now);
13600 zone_settimer(zone, &now);
13601 }
13602
13603 static isc_result_t
13604 notify_createmessage(dns_zone_t *zone, unsigned int flags,
13605 dns_message_t **messagep)
13606 {
13607 dns_db_t *zonedb = NULL;
13608 dns_dbnode_t *node = NULL;
13609 dns_dbversion_t *version = NULL;
13610 dns_message_t *message = NULL;
13611 dns_rdataset_t rdataset;
13612 dns_rdata_t rdata = DNS_RDATA_INIT;
13613
13614 dns_name_t *tempname = NULL;
13615 dns_rdata_t *temprdata = NULL;
13616 dns_rdatalist_t *temprdatalist = NULL;
13617 dns_rdataset_t *temprdataset = NULL;
13618
13619 isc_result_t result;
13620 isc_region_t r;
13621 isc_buffer_t *b = NULL;
13622
13623 REQUIRE(DNS_ZONE_VALID(zone));
13624 REQUIRE(messagep != NULL && *messagep == NULL);
13625
13626 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
13627 &message);
13628 if (result != ISC_R_SUCCESS)
13629 return (result);
13630
13631 message->opcode = dns_opcode_notify;
13632 message->flags |= DNS_MESSAGEFLAG_AA;
13633 message->rdclass = zone->rdclass;
13634
13635 result = dns_message_gettempname(message, &tempname);
13636 if (result != ISC_R_SUCCESS)
13637 goto cleanup;
13638
13639 result = dns_message_gettemprdataset(message, &temprdataset);
13640 if (result != ISC_R_SUCCESS)
13641 goto cleanup;
13642
13643 /*
13644 * Make question.
13645 */
13646 dns_name_init(tempname, NULL);
13647 dns_name_clone(&zone->origin, tempname);
13648 dns_rdataset_makequestion(temprdataset, zone->rdclass,
13649 dns_rdatatype_soa);
13650 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13651 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
13652 tempname = NULL;
13653 temprdataset = NULL;
13654
13655 if ((flags & DNS_NOTIFY_NOSOA) != 0)
13656 goto done;
13657
13658 result = dns_message_gettempname(message, &tempname);
13659 if (result != ISC_R_SUCCESS)
13660 goto soa_cleanup;
13661 result = dns_message_gettemprdata(message, &temprdata);
13662 if (result != ISC_R_SUCCESS)
13663 goto soa_cleanup;
13664 result = dns_message_gettemprdataset(message, &temprdataset);
13665 if (result != ISC_R_SUCCESS)
13666 goto soa_cleanup;
13667 result = dns_message_gettemprdatalist(message, &temprdatalist);
13668 if (result != ISC_R_SUCCESS)
13669 goto soa_cleanup;
13670
13671 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13672 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
13673 dns_db_attach(zone->db, &zonedb);
13674 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13675
13676 dns_name_init(tempname, NULL);
13677 dns_name_clone(&zone->origin, tempname);
13678 dns_db_currentversion(zonedb, &version);
13679 result = dns_db_findnode(zonedb, tempname, false, &node);
13680 if (result != ISC_R_SUCCESS)
13681 goto soa_cleanup;
13682
13683 dns_rdataset_init(&rdataset);
13684 result = dns_db_findrdataset(zonedb, node, version,
13685 dns_rdatatype_soa,
13686 dns_rdatatype_none, 0, &rdataset,
13687 NULL);
13688 if (result != ISC_R_SUCCESS)
13689 goto soa_cleanup;
13690 result = dns_rdataset_first(&rdataset);
13691 if (result != ISC_R_SUCCESS)
13692 goto soa_cleanup;
13693 dns_rdataset_current(&rdataset, &rdata);
13694 dns_rdata_toregion(&rdata, &r);
13695 result = isc_buffer_allocate(zone->mctx, &b, r.length);
13696 if (result != ISC_R_SUCCESS)
13697 goto soa_cleanup;
13698 isc_buffer_putmem(b, r.base, r.length);
13699 isc_buffer_usedregion(b, &r);
13700 dns_rdata_init(temprdata);
13701 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
13702 dns_message_takebuffer(message, &b);
13703 result = dns_rdataset_next(&rdataset);
13704 dns_rdataset_disassociate(&rdataset);
13705 if (result != ISC_R_NOMORE)
13706 goto soa_cleanup;
13707 temprdatalist->rdclass = rdata.rdclass;
13708 temprdatalist->type = rdata.type;
13709 temprdatalist->ttl = rdataset.ttl;
13710 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
13711
13712 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
13713 if (result != ISC_R_SUCCESS)
13714 goto soa_cleanup;
13715
13716 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13717 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
13718 temprdatalist = NULL;
13719 temprdataset = NULL;
13720 temprdata = NULL;
13721 tempname = NULL;
13722
13723 soa_cleanup:
13724 if (node != NULL)
13725 dns_db_detachnode(zonedb, &node);
13726 if (version != NULL)
13727 dns_db_closeversion(zonedb, &version, false);
13728 if (zonedb != NULL)
13729 dns_db_detach(&zonedb);
13730 if (tempname != NULL)
13731 dns_message_puttempname(message, &tempname);
13732 if (temprdata != NULL)
13733 dns_message_puttemprdata(message, &temprdata);
13734 if (temprdataset != NULL)
13735 dns_message_puttemprdataset(message, &temprdataset);
13736 if (temprdatalist != NULL)
13737 dns_message_puttemprdatalist(message, &temprdatalist);
13738
13739 done:
13740 *messagep = message;
13741 return (ISC_R_SUCCESS);
13742
13743 cleanup:
13744 if (tempname != NULL)
13745 dns_message_puttempname(message, &tempname);
13746 if (temprdataset != NULL)
13747 dns_message_puttemprdataset(message, &temprdataset);
13748 dns_message_destroy(&message);
13749 return (result);
13750 }
13751
13752 isc_result_t
13753 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
13754 isc_sockaddr_t *to, dns_message_t *msg)
13755 {
13756 unsigned int i;
13757 dns_rdata_soa_t soa;
13758 dns_rdataset_t *rdataset = NULL;
13759 dns_rdata_t rdata = DNS_RDATA_INIT;
13760 isc_result_t result;
13761 char fromtext[ISC_SOCKADDR_FORMATSIZE];
13762 int match = 0;
13763 isc_netaddr_t netaddr;
13764 uint32_t serial = 0;
13765 bool have_serial = false;
13766 dns_tsigkey_t *tsigkey;
13767 const dns_name_t *tsig;
13768
13769 REQUIRE(DNS_ZONE_VALID(zone));
13770
13771 /*
13772 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
13773 * ROLLOVER.
13774 *
13775 * SOA: RFC1996
13776 * Check that 'from' is a valid notify source, (zone->masters).
13777 * Return DNS_R_REFUSED if not.
13778 *
13779 * If the notify message contains a serial number check it
13780 * against the zones serial and return if <= current serial
13781 *
13782 * If a refresh check is progress, if so just record the
13783 * fact we received a NOTIFY and from where and return.
13784 * We will perform a new refresh check when the current one
13785 * completes. Return ISC_R_SUCCESS.
13786 *
13787 * Otherwise initiate a refresh check using 'from' as the
13788 * first address to check. Return ISC_R_SUCCESS.
13789 */
13790
13791 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
13792
13793 /*
13794 * Notify messages are processed by the raw zone.
13795 */
13796 LOCK_ZONE(zone);
13797 INSIST(zone != zone->raw);
13798 if (inline_secure(zone)) {
13799 result = dns_zone_notifyreceive(zone->raw, from, to, msg);
13800 UNLOCK_ZONE(zone);
13801 return (result);
13802 }
13803 /*
13804 * We only handle NOTIFY (SOA) at the present.
13805 */
13806 if (isc_sockaddr_pf(from) == PF_INET)
13807 inc_stats(zone, dns_zonestatscounter_notifyinv4);
13808 else
13809 inc_stats(zone, dns_zonestatscounter_notifyinv6);
13810 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
13811 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
13812 dns_rdatatype_soa, dns_rdatatype_none,
13813 NULL, NULL) != ISC_R_SUCCESS) {
13814 UNLOCK_ZONE(zone);
13815 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
13816 dns_zone_log(zone, ISC_LOG_NOTICE,
13817 "NOTIFY with no "
13818 "question section from: %s", fromtext);
13819 return (DNS_R_FORMERR);
13820 }
13821 dns_zone_log(zone, ISC_LOG_NOTICE,
13822 "NOTIFY zone does not match");
13823 return (DNS_R_NOTIMP);
13824 }
13825
13826 /*
13827 * If we are a master zone just succeed.
13828 */
13829 if (zone->type == dns_zone_master) {
13830 UNLOCK_ZONE(zone);
13831 return (ISC_R_SUCCESS);
13832 }
13833
13834 isc_netaddr_fromsockaddr(&netaddr, from);
13835 for (i = 0; i < zone->masterscnt; i++) {
13836 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
13837 break;
13838 if (zone->view->aclenv.match_mapped &&
13839 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
13840 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
13841 isc_netaddr_t na1, na2;
13842 isc_netaddr_fromv4mapped(&na1, &netaddr);
13843 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
13844 if (isc_netaddr_equal(&na1, &na2))
13845 break;
13846 }
13847 }
13848
13849 /*
13850 * Accept notify requests from non masters if they are on
13851 * 'zone->notify_acl'.
13852 */
13853 tsigkey = dns_message_gettsigkey(msg);
13854 tsig = dns_tsigkey_identity(tsigkey);
13855 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
13856 (dns_acl_match(&netaddr, tsig, zone->notify_acl,
13857 &zone->view->aclenv, &match,
13858 NULL) == ISC_R_SUCCESS) &&
13859 match > 0)
13860 {
13861 /* Accept notify. */
13862 } else if (i >= zone->masterscnt) {
13863 UNLOCK_ZONE(zone);
13864 dns_zone_log(zone, ISC_LOG_INFO,
13865 "refused notify from non-master: %s", fromtext);
13866 inc_stats(zone, dns_zonestatscounter_notifyrej);
13867 return (DNS_R_REFUSED);
13868 }
13869
13870 /*
13871 * If the zone is loaded and there are answers check the serial
13872 * to see if we need to do a refresh. Do not worry about this
13873 * check if we are a dialup zone as we use the notify request
13874 * to trigger a refresh check.
13875 */
13876 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
13877 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13878 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
13879 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
13880 &zone->origin,
13881 dns_rdatatype_soa,
13882 dns_rdatatype_none, NULL,
13883 &rdataset);
13884 if (result == ISC_R_SUCCESS)
13885 result = dns_rdataset_first(rdataset);
13886 if (result == ISC_R_SUCCESS) {
13887 uint32_t oldserial;
13888 unsigned int soacount;
13889
13890 dns_rdataset_current(rdataset, &rdata);
13891 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13892 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13893 serial = soa.serial;
13894 have_serial = true;
13895 /*
13896 * The following should safely be performed without DB
13897 * lock and succeed in this context.
13898 */
13899 result = zone_get_from_db(zone, zone->db, NULL,
13900 &soacount, &oldserial, NULL,
13901 NULL, NULL, NULL, NULL);
13902 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13903 RUNTIME_CHECK(soacount > 0U);
13904 if (isc_serial_le(serial, oldserial)) {
13905 dns_zone_log(zone,
13906 ISC_LOG_INFO,
13907 "notify from %s: "
13908 "zone is up to date",
13909 fromtext);
13910 UNLOCK_ZONE(zone);
13911 return (ISC_R_SUCCESS);
13912 }
13913 }
13914 }
13915
13916 /*
13917 * If we got this far and there was a refresh in progress just
13918 * let it complete. Record where we got the notify from so we
13919 * can perform a refresh check when the current one completes
13920 */
13921 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
13922 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13923 zone->notifyfrom = *from;
13924 UNLOCK_ZONE(zone);
13925 if (have_serial)
13926 dns_zone_log(zone, ISC_LOG_INFO,
13927 "notify from %s: serial %u: refresh in "
13928 "progress, refresh check queued",
13929 fromtext, serial);
13930 else
13931 dns_zone_log(zone, ISC_LOG_INFO,
13932 "notify from %s: refresh in progress, "
13933 "refresh check queued", fromtext);
13934 return (ISC_R_SUCCESS);
13935 }
13936 if (have_serial)
13937 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
13938 fromtext, serial);
13939 else
13940 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
13941 fromtext);
13942 zone->notifyfrom = *from;
13943 UNLOCK_ZONE(zone);
13944
13945 if (to != NULL) {
13946 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
13947 }
13948 dns_zone_refresh(zone);
13949 return (ISC_R_SUCCESS);
13950 }
13951
13952 void
13953 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
13954
13955 REQUIRE(DNS_ZONE_VALID(zone));
13956
13957 LOCK_ZONE(zone);
13958 if (zone->notify_acl != NULL)
13959 dns_acl_detach(&zone->notify_acl);
13960 dns_acl_attach(acl, &zone->notify_acl);
13961 UNLOCK_ZONE(zone);
13962 }
13963
13964 void
13965 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
13966
13967 REQUIRE(DNS_ZONE_VALID(zone));
13968
13969 LOCK_ZONE(zone);
13970 if (zone->query_acl != NULL)
13971 dns_acl_detach(&zone->query_acl);
13972 dns_acl_attach(acl, &zone->query_acl);
13973 UNLOCK_ZONE(zone);
13974 }
13975
13976 void
13977 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
13978
13979 REQUIRE(DNS_ZONE_VALID(zone));
13980
13981 LOCK_ZONE(zone);
13982 if (zone->queryon_acl != NULL)
13983 dns_acl_detach(&zone->queryon_acl);
13984 dns_acl_attach(acl, &zone->queryon_acl);
13985 UNLOCK_ZONE(zone);
13986 }
13987
13988 void
13989 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
13990
13991 REQUIRE(DNS_ZONE_VALID(zone));
13992
13993 LOCK_ZONE(zone);
13994 if (zone->update_acl != NULL)
13995 dns_acl_detach(&zone->update_acl);
13996 dns_acl_attach(acl, &zone->update_acl);
13997 UNLOCK_ZONE(zone);
13998 }
13999
14000 void
14001 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
14002
14003 REQUIRE(DNS_ZONE_VALID(zone));
14004
14005 LOCK_ZONE(zone);
14006 if (zone->forward_acl != NULL)
14007 dns_acl_detach(&zone->forward_acl);
14008 dns_acl_attach(acl, &zone->forward_acl);
14009 UNLOCK_ZONE(zone);
14010 }
14011
14012 void
14013 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
14014
14015 REQUIRE(DNS_ZONE_VALID(zone));
14016
14017 LOCK_ZONE(zone);
14018 if (zone->xfr_acl != NULL)
14019 dns_acl_detach(&zone->xfr_acl);
14020 dns_acl_attach(acl, &zone->xfr_acl);
14021 UNLOCK_ZONE(zone);
14022 }
14023
14024 dns_acl_t *
14025 dns_zone_getnotifyacl(dns_zone_t *zone) {
14026
14027 REQUIRE(DNS_ZONE_VALID(zone));
14028
14029 return (zone->notify_acl);
14030 }
14031
14032 dns_acl_t *
14033 dns_zone_getqueryacl(dns_zone_t *zone) {
14034
14035 REQUIRE(DNS_ZONE_VALID(zone));
14036
14037 return (zone->query_acl);
14038 }
14039
14040 dns_acl_t *
14041 dns_zone_getqueryonacl(dns_zone_t *zone) {
14042
14043 REQUIRE(DNS_ZONE_VALID(zone));
14044
14045 return (zone->queryon_acl);
14046 }
14047
14048 dns_acl_t *
14049 dns_zone_getupdateacl(dns_zone_t *zone) {
14050
14051 REQUIRE(DNS_ZONE_VALID(zone));
14052
14053 return (zone->update_acl);
14054 }
14055
14056 dns_acl_t *
14057 dns_zone_getforwardacl(dns_zone_t *zone) {
14058
14059 REQUIRE(DNS_ZONE_VALID(zone));
14060
14061 return (zone->forward_acl);
14062 }
14063
14064 dns_acl_t *
14065 dns_zone_getxfracl(dns_zone_t *zone) {
14066
14067 REQUIRE(DNS_ZONE_VALID(zone));
14068
14069 return (zone->xfr_acl);
14070 }
14071
14072 void
14073 dns_zone_clearupdateacl(dns_zone_t *zone) {
14074
14075 REQUIRE(DNS_ZONE_VALID(zone));
14076
14077 LOCK_ZONE(zone);
14078 if (zone->update_acl != NULL)
14079 dns_acl_detach(&zone->update_acl);
14080 UNLOCK_ZONE(zone);
14081 }
14082
14083 void
14084 dns_zone_clearforwardacl(dns_zone_t *zone) {
14085
14086 REQUIRE(DNS_ZONE_VALID(zone));
14087
14088 LOCK_ZONE(zone);
14089 if (zone->forward_acl != NULL)
14090 dns_acl_detach(&zone->forward_acl);
14091 UNLOCK_ZONE(zone);
14092 }
14093
14094 void
14095 dns_zone_clearnotifyacl(dns_zone_t *zone) {
14096
14097 REQUIRE(DNS_ZONE_VALID(zone));
14098
14099 LOCK_ZONE(zone);
14100 if (zone->notify_acl != NULL)
14101 dns_acl_detach(&zone->notify_acl);
14102 UNLOCK_ZONE(zone);
14103 }
14104
14105 void
14106 dns_zone_clearqueryacl(dns_zone_t *zone) {
14107
14108 REQUIRE(DNS_ZONE_VALID(zone));
14109
14110 LOCK_ZONE(zone);
14111 if (zone->query_acl != NULL)
14112 dns_acl_detach(&zone->query_acl);
14113 UNLOCK_ZONE(zone);
14114 }
14115
14116 void
14117 dns_zone_clearqueryonacl(dns_zone_t *zone) {
14118
14119 REQUIRE(DNS_ZONE_VALID(zone));
14120
14121 LOCK_ZONE(zone);
14122 if (zone->queryon_acl != NULL)
14123 dns_acl_detach(&zone->queryon_acl);
14124 UNLOCK_ZONE(zone);
14125 }
14126
14127 void
14128 dns_zone_clearxfracl(dns_zone_t *zone) {
14129
14130 REQUIRE(DNS_ZONE_VALID(zone));
14131
14132 LOCK_ZONE(zone);
14133 if (zone->xfr_acl != NULL)
14134 dns_acl_detach(&zone->xfr_acl);
14135 UNLOCK_ZONE(zone);
14136 }
14137
14138 bool
14139 dns_zone_getupdatedisabled(dns_zone_t *zone) {
14140 REQUIRE(DNS_ZONE_VALID(zone));
14141 return (zone->update_disabled);
14142
14143 }
14144
14145 void
14146 dns_zone_setupdatedisabled(dns_zone_t *zone, bool state) {
14147 REQUIRE(DNS_ZONE_VALID(zone));
14148 zone->update_disabled = state;
14149 }
14150
14151 bool
14152 dns_zone_getzeronosoattl(dns_zone_t *zone) {
14153 REQUIRE(DNS_ZONE_VALID(zone));
14154 return (zone->zero_no_soa_ttl);
14155
14156 }
14157
14158 void
14159 dns_zone_setzeronosoattl(dns_zone_t *zone, bool state) {
14160 REQUIRE(DNS_ZONE_VALID(zone));
14161 zone->zero_no_soa_ttl = state;
14162 }
14163
14164 void
14165 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
14166 REQUIRE(DNS_ZONE_VALID(zone));
14167
14168 zone->check_names = severity;
14169 }
14170
14171 dns_severity_t
14172 dns_zone_getchecknames(dns_zone_t *zone) {
14173 REQUIRE(DNS_ZONE_VALID(zone));
14174
14175 return (zone->check_names);
14176 }
14177
14178 void
14179 dns_zone_setjournalsize(dns_zone_t *zone, int32_t size) {
14180 REQUIRE(DNS_ZONE_VALID(zone));
14181
14182 zone->journalsize = size;
14183 }
14184
14185 int32_t
14186 dns_zone_getjournalsize(dns_zone_t *zone) {
14187 REQUIRE(DNS_ZONE_VALID(zone));
14188
14189 return (zone->journalsize);
14190 }
14191
14192 static void
14193 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
14194 isc_result_t result = ISC_R_FAILURE;
14195 isc_buffer_t buffer;
14196
14197 REQUIRE(buf != NULL);
14198 REQUIRE(length > 1U);
14199
14200 /*
14201 * Leave space for terminating '\0'.
14202 */
14203 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14204 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
14205 if (dns_name_dynamic(&zone->origin))
14206 result = dns_name_totext(&zone->origin, true, &buffer);
14207 if (result != ISC_R_SUCCESS &&
14208 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
14209 isc_buffer_putstr(&buffer, "<UNKNOWN>");
14210
14211 if (isc_buffer_availablelength(&buffer) > 0)
14212 isc_buffer_putstr(&buffer, "/");
14213 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
14214 }
14215
14216 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
14217 strcmp(zone->view->name, "_default") != 0 &&
14218 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
14219 isc_buffer_putstr(&buffer, "/");
14220 isc_buffer_putstr(&buffer, zone->view->name);
14221 }
14222 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
14223 isc_buffer_putstr(&buffer, " (signed)");
14224 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
14225 isc_buffer_putstr(&buffer, " (unsigned)");
14226
14227 buf[isc_buffer_usedlength(&buffer)] = '\0';
14228 }
14229
14230 static void
14231 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
14232 isc_result_t result = ISC_R_FAILURE;
14233 isc_buffer_t buffer;
14234
14235 REQUIRE(buf != NULL);
14236 REQUIRE(length > 1U);
14237
14238 /*
14239 * Leave space for terminating '\0'.
14240 */
14241 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14242 if (dns_name_dynamic(&zone->origin))
14243 result = dns_name_totext(&zone->origin, true, &buffer);
14244 if (result != ISC_R_SUCCESS &&
14245 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
14246 isc_buffer_putstr(&buffer, "<UNKNOWN>");
14247
14248 buf[isc_buffer_usedlength(&buffer)] = '\0';
14249 }
14250
14251 static void
14252 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
14253 isc_buffer_t buffer;
14254
14255 REQUIRE(buf != NULL);
14256 REQUIRE(length > 1U);
14257
14258 /*
14259 * Leave space for terminating '\0'.
14260 */
14261 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14262 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
14263
14264 buf[isc_buffer_usedlength(&buffer)] = '\0';
14265 }
14266
14267 static void
14268 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
14269 isc_buffer_t buffer;
14270
14271 REQUIRE(buf != NULL);
14272 REQUIRE(length > 1U);
14273
14274
14275 /*
14276 * Leave space for terminating '\0'.
14277 */
14278 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
14279
14280 if (zone->view == NULL) {
14281 isc_buffer_putstr(&buffer, "_none");
14282 } else if (strlen(zone->view->name)
14283 < isc_buffer_availablelength(&buffer)) {
14284 isc_buffer_putstr(&buffer, zone->view->name);
14285 } else {
14286 isc_buffer_putstr(&buffer, "_toolong");
14287 }
14288
14289 buf[isc_buffer_usedlength(&buffer)] = '\0';
14290 }
14291
14292 void
14293 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
14294 REQUIRE(DNS_ZONE_VALID(zone));
14295 REQUIRE(buf != NULL);
14296 zone_namerd_tostr(zone, buf, length);
14297 }
14298
14299 void
14300 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
14301 REQUIRE(DNS_ZONE_VALID(zone));
14302 REQUIRE(buf != NULL);
14303 zone_name_tostr(zone, buf, length);
14304 }
14305
14306 void
14307 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
14308 const char *prefix, const char *fmt, va_list ap)
14309 {
14310 char message[4096];
14311 const char *zstr;
14312
14313 if (!isc_log_wouldlog(dns_lctx, level)) {
14314 return;
14315 }
14316
14317 vsnprintf(message, sizeof(message), fmt, ap);
14318
14319 switch (zone->type) {
14320 case dns_zone_key:
14321 zstr = "managed-keys-zone";
14322 break;
14323 case dns_zone_redirect:
14324 zstr = "redirect-zone";
14325 break;
14326 default:
14327 zstr = "zone ";
14328 }
14329
14330 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
14331 "%s%s%s%s: %s",
14332 (prefix != NULL ? prefix : ""),
14333 (prefix != NULL ? ": " : ""),
14334 zstr, zone->strnamerd, message);
14335 }
14336
14337 static void
14338 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14339 va_list ap;
14340
14341 va_start(ap, fmt);
14342 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
14343 va_end(ap);
14344 }
14345
14346 void
14347 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
14348 int level, const char *fmt, ...)
14349 {
14350 va_list ap;
14351
14352 va_start(ap, fmt);
14353 dns_zone_logv(zone, category, level, NULL, fmt, ap);
14354 va_end(ap);
14355 }
14356
14357 void
14358 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14359 va_list ap;
14360
14361 va_start(ap, fmt);
14362 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
14363 va_end(ap);
14364 }
14365
14366 static void
14367 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
14368 const char *fmt, ...)
14369 {
14370 int level = ISC_LOG_DEBUG(debuglevel);
14371 va_list ap;
14372
14373 va_start(ap, fmt);
14374 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
14375 va_end(ap);
14376 }
14377
14378 static void
14379 dnssec_log(dns_zone_t *zone, int level, const char *fmt, ...) {
14380 va_list ap;
14381
14382 va_start(ap, fmt);
14383 dns_zone_logv(zone, DNS_LOGCATEGORY_DNSSEC, level, NULL, fmt, ap);
14384 va_end(ap);
14385 }
14386
14387 static int
14388 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
14389 {
14390 isc_result_t result;
14391 dns_name_t *name;
14392 dns_rdataset_t *curr;
14393 int count = 0;
14394
14395 result = dns_message_firstname(msg, section);
14396 while (result == ISC_R_SUCCESS) {
14397 name = NULL;
14398 dns_message_currentname(msg, section, &name);
14399
14400 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
14401 curr = ISC_LIST_PREV(curr, link)) {
14402 if (curr->type == type)
14403 count++;
14404 }
14405 result = dns_message_nextname(msg, section);
14406 }
14407
14408 return (count);
14409 }
14410
14411 void
14412 dns_zone_setmaxxfrin(dns_zone_t *zone, uint32_t maxxfrin) {
14413 REQUIRE(DNS_ZONE_VALID(zone));
14414
14415 zone->maxxfrin = maxxfrin;
14416 }
14417
14418 uint32_t
14419 dns_zone_getmaxxfrin(dns_zone_t *zone) {
14420 REQUIRE(DNS_ZONE_VALID(zone));
14421
14422 return (zone->maxxfrin);
14423 }
14424
14425 void
14426 dns_zone_setmaxxfrout(dns_zone_t *zone, uint32_t maxxfrout) {
14427 REQUIRE(DNS_ZONE_VALID(zone));
14428 zone->maxxfrout = maxxfrout;
14429 }
14430
14431 uint32_t
14432 dns_zone_getmaxxfrout(dns_zone_t *zone) {
14433 REQUIRE(DNS_ZONE_VALID(zone));
14434
14435 return (zone->maxxfrout);
14436 }
14437
14438 dns_zonetype_t
14439 dns_zone_gettype(dns_zone_t *zone) {
14440 REQUIRE(DNS_ZONE_VALID(zone));
14441
14442 return (zone->type);
14443 }
14444
14445 dns_zonetype_t
14446 dns_zone_getredirecttype(dns_zone_t *zone) {
14447 REQUIRE(DNS_ZONE_VALID(zone));
14448 REQUIRE(zone->type == dns_zone_redirect);
14449
14450 return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
14451 }
14452
14453 dns_name_t *
14454 dns_zone_getorigin(dns_zone_t *zone) {
14455 REQUIRE(DNS_ZONE_VALID(zone));
14456
14457 return (&zone->origin);
14458 }
14459
14460 void
14461 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
14462 REQUIRE(DNS_ZONE_VALID(zone));
14463
14464 LOCK_ZONE(zone);
14465 if (zone->task != NULL)
14466 isc_task_detach(&zone->task);
14467 isc_task_attach(task, &zone->task);
14468 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14469 if (zone->db != NULL)
14470 dns_db_settask(zone->db, zone->task);
14471 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14472 UNLOCK_ZONE(zone);
14473 }
14474
14475 void
14476 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
14477 REQUIRE(DNS_ZONE_VALID(zone));
14478 isc_task_attach(zone->task, target);
14479 }
14480
14481 void
14482 dns_zone_setidlein(dns_zone_t *zone, uint32_t idlein) {
14483 REQUIRE(DNS_ZONE_VALID(zone));
14484
14485 if (idlein == 0)
14486 idlein = DNS_DEFAULT_IDLEIN;
14487 zone->idlein = idlein;
14488 }
14489
14490 uint32_t
14491 dns_zone_getidlein(dns_zone_t *zone) {
14492 REQUIRE(DNS_ZONE_VALID(zone));
14493
14494 return (zone->idlein);
14495 }
14496
14497 void
14498 dns_zone_setidleout(dns_zone_t *zone, uint32_t idleout) {
14499 REQUIRE(DNS_ZONE_VALID(zone));
14500
14501 zone->idleout = idleout;
14502 }
14503
14504 uint32_t
14505 dns_zone_getidleout(dns_zone_t *zone) {
14506 REQUIRE(DNS_ZONE_VALID(zone));
14507
14508 return (zone->idleout);
14509 }
14510
14511 static void
14512 notify_done(isc_task_t *task, isc_event_t *event) {
14513 dns_requestevent_t *revent = (dns_requestevent_t *)event;
14514 dns_notify_t *notify;
14515 isc_result_t result;
14516 dns_message_t *message = NULL;
14517 isc_buffer_t buf;
14518 char rcode[128];
14519 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
14520
14521 UNUSED(task);
14522
14523 notify = event->ev_arg;
14524 REQUIRE(DNS_NOTIFY_VALID(notify));
14525 INSIST(task == notify->zone->task);
14526
14527 isc_buffer_init(&buf, rcode, sizeof(rcode));
14528 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
14529
14530 result = revent->result;
14531 if (result == ISC_R_SUCCESS)
14532 result = dns_message_create(notify->zone->mctx,
14533 DNS_MESSAGE_INTENTPARSE, &message);
14534 if (result == ISC_R_SUCCESS)
14535 result = dns_request_getresponse(revent->request, message,
14536 DNS_MESSAGEPARSE_PRESERVEORDER);
14537 if (result == ISC_R_SUCCESS)
14538 result = dns_rcode_totext(message->rcode, &buf);
14539 if (result == ISC_R_SUCCESS)
14540 notify_log(notify->zone, ISC_LOG_DEBUG(3),
14541 "notify response from %s: %.*s",
14542 addrbuf, (int)buf.used, rcode);
14543 else
14544 notify_log(notify->zone, ISC_LOG_DEBUG(2),
14545 "notify to %s failed: %s", addrbuf,
14546 dns_result_totext(result));
14547
14548 /*
14549 * Old bind's return formerr if they see a soa record. Retry w/o
14550 * the soa if we see a formerr and had sent a SOA.
14551 */
14552 isc_event_free(&event);
14553 if (message != NULL && message->rcode == dns_rcode_formerr &&
14554 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
14555 bool startup;
14556
14557 notify->flags |= DNS_NOTIFY_NOSOA;
14558 dns_request_destroy(¬ify->request);
14559 startup = (notify->flags & DNS_NOTIFY_STARTUP);
14560 result = notify_send_queue(notify, startup);
14561 if (result != ISC_R_SUCCESS)
14562 notify_destroy(notify, false);
14563 } else {
14564 if (result == ISC_R_TIMEDOUT)
14565 notify_log(notify->zone, ISC_LOG_DEBUG(1),
14566 "notify to %s: retries exceeded", addrbuf);
14567 notify_destroy(notify, false);
14568 }
14569 if (message != NULL)
14570 dns_message_destroy(&message);
14571 }
14572
14573 struct secure_event {
14574 isc_event_t e;
14575 dns_db_t *db;
14576 uint32_t serial;
14577 };
14578
14579 static void
14580 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
14581 UNUSED(arg);
14582 dns_zone_log(zone, level, "%s", message);
14583 }
14584
14585 static isc_result_t
14586 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
14587 uint32_t start, uint32_t end,
14588 dns_difftuple_t **soatuplep, dns_diff_t *diff)
14589 {
14590 isc_result_t result;
14591 dns_difftuple_t *tuple = NULL;
14592 dns_diffop_t op = DNS_DIFFOP_ADD;
14593 int n_soa = 0;
14594
14595 REQUIRE(soatuplep != NULL);
14596
14597 if (start == end)
14598 return (DNS_R_UNCHANGED);
14599
14600 CHECK(dns_journal_iter_init(journal, start, end));
14601 for (result = dns_journal_first_rr(journal);
14602 result == ISC_R_SUCCESS;
14603 result = dns_journal_next_rr(journal))
14604 {
14605 dns_name_t *name = NULL;
14606 uint32_t ttl;
14607 dns_rdata_t *rdata = NULL;
14608 dns_journal_current_rr(journal, &name, &ttl, &rdata);
14609
14610 if (rdata->type == dns_rdatatype_soa) {
14611 n_soa++;
14612 if (n_soa == 2) {
14613 /*
14614 * Save the latest raw SOA record.
14615 */
14616 if (*soatuplep != NULL)
14617 dns_difftuple_free(soatuplep);
14618 CHECK(dns_difftuple_create(diff->mctx,
14619 DNS_DIFFOP_ADD,
14620 name, ttl, rdata,
14621 soatuplep));
14622 }
14623 if (n_soa == 3)
14624 n_soa = 1;
14625 continue;
14626 }
14627
14628 /* Sanity. */
14629 if (n_soa == 0) {
14630 dns_zone_log(raw, ISC_LOG_ERROR,
14631 "corrupt journal file: '%s'\n",
14632 raw->journal);
14633 return (ISC_R_FAILURE);
14634 }
14635
14636 if (zone->privatetype != 0 &&
14637 rdata->type == zone->privatetype)
14638 continue;
14639
14640 if (rdata->type == dns_rdatatype_nsec ||
14641 rdata->type == dns_rdatatype_rrsig ||
14642 rdata->type == dns_rdatatype_nsec3 ||
14643 rdata->type == dns_rdatatype_dnskey ||
14644 rdata->type == dns_rdatatype_nsec3param)
14645 continue;
14646
14647 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
14648
14649 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
14650 &tuple));
14651 dns_diff_appendminimal(diff, &tuple);
14652 }
14653 if (result == ISC_R_NOMORE)
14654 result = ISC_R_SUCCESS;
14655
14656 failure:
14657 return(result);
14658 }
14659
14660 static isc_result_t
14661 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
14662 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
14663 dns_diff_t *diff)
14664 {
14665 isc_result_t result;
14666 dns_db_t *rawdb = NULL;
14667 dns_dbversion_t *rawver = NULL;
14668 dns_difftuple_t *tuple = NULL, *next;
14669 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
14670 dns_rdata_soa_t oldsoa, newsoa;
14671
14672 REQUIRE(DNS_ZONE_VALID(seczone));
14673 REQUIRE(soatuple != NULL && *soatuple == NULL);
14674
14675 if (!seczone->sourceserialset)
14676 return (DNS_R_UNCHANGED);
14677
14678 dns_db_attach(raw->db, &rawdb);
14679 dns_db_currentversion(rawdb, &rawver);
14680 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
14681 dns_db_closeversion(rawdb, &rawver, false);
14682 dns_db_detach(&rawdb);
14683
14684 if (result != ISC_R_SUCCESS)
14685 return (result);
14686
14687 for (tuple = ISC_LIST_HEAD(diff->tuples);
14688 tuple != NULL;
14689 tuple = next)
14690 {
14691 next = ISC_LIST_NEXT(tuple, link);
14692 if (tuple->rdata.type == dns_rdatatype_nsec ||
14693 tuple->rdata.type == dns_rdatatype_rrsig ||
14694 tuple->rdata.type == dns_rdatatype_dnskey ||
14695 tuple->rdata.type == dns_rdatatype_nsec3 ||
14696 tuple->rdata.type == dns_rdatatype_nsec3param)
14697 {
14698 ISC_LIST_UNLINK(diff->tuples, tuple, link);
14699 dns_difftuple_free(&tuple);
14700 continue;
14701 }
14702 if (tuple->rdata.type == dns_rdatatype_soa) {
14703 if (tuple->op == DNS_DIFFOP_DEL) {
14704 INSIST(oldtuple == NULL);
14705 oldtuple = tuple;
14706 }
14707 if (tuple->op == DNS_DIFFOP_ADD) {
14708 INSIST(newtuple == NULL);
14709 newtuple = tuple;
14710 }
14711 }
14712 }
14713
14714 if (oldtuple != NULL && newtuple != NULL) {
14715
14716 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
14717 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14718
14719 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
14720 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14721
14722 /*
14723 * If the SOA records are the same except for the serial
14724 * remove them from the diff.
14725 */
14726 if (oldsoa.refresh == newsoa.refresh &&
14727 oldsoa.retry == newsoa.retry &&
14728 oldsoa.minimum == newsoa.minimum &&
14729 oldsoa.expire == newsoa.expire &&
14730 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
14731 dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
14732 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14733 dns_difftuple_free(&oldtuple);
14734 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14735 dns_difftuple_free(&newtuple);
14736 }
14737 }
14738
14739 if (ISC_LIST_EMPTY(diff->tuples))
14740 return (DNS_R_UNCHANGED);
14741
14742 /*
14743 * If there are still SOA records in the diff they can now be removed
14744 * saving the new SOA record.
14745 */
14746 if (oldtuple != NULL) {
14747 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14748 dns_difftuple_free(&oldtuple);
14749 }
14750
14751 if (newtuple != NULL) {
14752 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14753 *soatuple = newtuple;
14754 }
14755
14756 return (ISC_R_SUCCESS);
14757 }
14758
14759 static void
14760 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
14761 static char me[] = "receive_secure_serial";
14762 isc_result_t result = ISC_R_SUCCESS;
14763 dns_journal_t *rjournal = NULL;
14764 dns_journal_t *sjournal = NULL;
14765 uint32_t start, end;
14766 dns_zone_t *zone;
14767 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
14768 dns_update_log_t log = { update_log_cb, NULL };
14769 uint32_t newserial = 0, desired = 0;
14770 isc_time_t timenow;
14771 int level = ISC_LOG_ERROR;
14772
14773 UNUSED(task);
14774
14775 zone = event->ev_arg;
14776 end = ((struct secure_event *)event)->serial;
14777
14778 ENTER;
14779
14780 LOCK_ZONE(zone);
14781
14782 /*
14783 * If we are already processing a receive secure serial event
14784 * for the zone, just queue the new one and exit.
14785 */
14786 if (zone->rss_event != NULL && zone->rss_event != event) {
14787 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
14788 UNLOCK_ZONE(zone);
14789 return;
14790 }
14791
14792 nextevent:
14793 if (zone->rss_event != NULL) {
14794 INSIST(zone->rss_event == event);
14795 UNLOCK_ZONE(zone);
14796 } else {
14797 zone->rss_event = event;
14798 dns_diff_init(zone->mctx, &zone->rss_diff);
14799
14800 /*
14801 * zone->db may be NULL, if the load from disk failed.
14802 */
14803 result = ISC_R_SUCCESS;
14804 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14805 if (zone->db != NULL) {
14806 dns_db_attach(zone->db, &zone->rss_db);
14807 } else {
14808 result = ISC_R_FAILURE;
14809 }
14810 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14811
14812 if (result == ISC_R_SUCCESS && zone->raw != NULL) {
14813 dns_zone_attach(zone->raw, &zone->rss_raw);
14814 } else {
14815 result = ISC_R_FAILURE;
14816 }
14817
14818 UNLOCK_ZONE(zone);
14819
14820 CHECK(result);
14821
14822 /*
14823 * We first attempt to sync the raw zone to the secure zone
14824 * by using the raw zone's journal, applying all the deltas
14825 * from the latest source-serial of the secure zone up to
14826 * the current serial number of the raw zone.
14827 *
14828 * If that fails, then we'll fall back to a direct comparison
14829 * between raw and secure zones.
14830 */
14831 CHECK(dns_journal_open(zone->rss_raw->mctx,
14832 zone->rss_raw->journal,
14833 DNS_JOURNAL_WRITE, &rjournal));
14834
14835 result = dns_journal_open(zone->mctx, zone->journal,
14836 DNS_JOURNAL_READ, &sjournal);
14837 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
14838 goto failure;
14839 }
14840
14841 if (!dns_journal_get_sourceserial(rjournal, &start)) {
14842 start = dns_journal_first_serial(rjournal);
14843 dns_journal_set_sourceserial(rjournal, start);
14844 }
14845 if (sjournal != NULL) {
14846 uint32_t serial;
14847 /*
14848 * We read the secure journal first, if that
14849 * exists use its value provided it is greater
14850 * that from the raw journal.
14851 */
14852 if (dns_journal_get_sourceserial(sjournal, &serial)) {
14853 if (isc_serial_gt(serial, start))
14854 start = serial;
14855 }
14856 dns_journal_destroy(&sjournal);
14857 }
14858
14859 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
14860 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
14861
14862 /*
14863 * Try to apply diffs from the raw zone's journal to the secure
14864 * zone. If that fails, we recover by syncing up the databases
14865 * directly.
14866 */
14867 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
14868 start, end, &soatuple,
14869 &zone->rss_diff);
14870 if (result == DNS_R_UNCHANGED) {
14871 level = ISC_LOG_INFO;
14872 goto failure;
14873 } else if (result != ISC_R_SUCCESS) {
14874 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
14875 zone->rss_oldver, &soatuple,
14876 &zone->rss_diff));
14877 }
14878
14879 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
14880 zone->rss_newver));
14881
14882 if (soatuple != NULL) {
14883 uint32_t oldserial;
14884
14885 CHECK(dns_db_createsoatuple(zone->rss_db,
14886 zone->rss_oldver,
14887 zone->rss_diff.mctx,
14888 DNS_DIFFOP_DEL, &tuple));
14889 oldserial = dns_soa_getserial(&tuple->rdata);
14890 newserial = desired =
14891 dns_soa_getserial(&soatuple->rdata);
14892 if (!isc_serial_gt(newserial, oldserial)) {
14893 newserial = oldserial + 1;
14894 if (newserial == 0) {
14895 newserial++;
14896 }
14897 dns_soa_setserial(newserial, &soatuple->rdata);
14898 }
14899 CHECK(do_one_tuple(&tuple, zone->rss_db,
14900 zone->rss_newver, &zone->rss_diff));
14901 CHECK(do_one_tuple(&soatuple, zone->rss_db,
14902 zone->rss_newver, &zone->rss_diff));
14903 } else {
14904 CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
14905 &zone->rss_diff, zone->mctx,
14906 zone->updatemethod));
14907 }
14908
14909 }
14910 result = dns_update_signaturesinc(&log, zone, zone->rss_db,
14911 zone->rss_oldver, zone->rss_newver,
14912 &zone->rss_diff,
14913 zone->sigvalidityinterval,
14914 &zone->rss_state);
14915 if (result == DNS_R_CONTINUE) {
14916 if (rjournal != NULL) {
14917 dns_journal_destroy(&rjournal);
14918 }
14919 isc_task_send(task, &event);
14920 return;
14921 }
14922 /*
14923 * If something went wrong while trying to update the secure zone and
14924 * the latter was already signed before, do not apply raw zone deltas
14925 * to it as that would break existing DNSSEC signatures. However, if
14926 * the secure zone was not yet signed (e.g. because no signing keys
14927 * were created for it), commence applying raw zone deltas to it so
14928 * that contents of the raw zone and the secure zone are kept in sync.
14929 */
14930 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
14931 goto failure;
14932 }
14933
14934 if (rjournal == NULL) {
14935 CHECK(dns_journal_open(zone->rss_raw->mctx,
14936 zone->rss_raw->journal,
14937 DNS_JOURNAL_WRITE, &rjournal));
14938 }
14939 CHECK(zone_journal(zone, &zone->rss_diff, &end,
14940 "receive_secure_serial"));
14941
14942 dns_journal_set_sourceserial(rjournal, end);
14943 dns_journal_commit(rjournal);
14944
14945 LOCK_ZONE(zone);
14946 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14947
14948 zone->sourceserial = end;
14949 zone->sourceserialset = true;
14950 zone_needdump(zone, DNS_DUMP_DELAY);
14951
14952 TIME_NOW(&timenow);
14953 zone_settimer(zone, &timenow);
14954 UNLOCK_ZONE(zone);
14955
14956 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, false);
14957 dns_db_closeversion(zone->rss_db, &zone->rss_newver, true);
14958
14959 if (newserial != 0) {
14960 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
14961 newserial, desired);
14962 }
14963
14964 failure:
14965 isc_event_free(&zone->rss_event);
14966 event = ISC_LIST_HEAD(zone->rss_events);
14967
14968 if (zone->rss_raw != NULL) {
14969 dns_zone_detach(&zone->rss_raw);
14970 }
14971 if (result != ISC_R_SUCCESS) {
14972 dns_zone_log(zone, level, "receive_secure_serial: %s",
14973 dns_result_totext(result));
14974 }
14975 if (tuple != NULL) {
14976 dns_difftuple_free(&tuple);
14977 }
14978 if (soatuple != NULL) {
14979 dns_difftuple_free(&soatuple);
14980 }
14981 if (zone->rss_db != NULL) {
14982 if (zone->rss_oldver != NULL) {
14983 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
14984 false);
14985 }
14986 if (zone->rss_newver != NULL) {
14987 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
14988 false);
14989 }
14990 dns_db_detach(&zone->rss_db);
14991 }
14992 INSIST(zone->rss_oldver == NULL);
14993 INSIST(zone->rss_newver == NULL);
14994 if (rjournal != NULL) {
14995 dns_journal_destroy(&rjournal);
14996 }
14997 dns_diff_clear(&zone->rss_diff);
14998
14999 if (event != NULL) {
15000 LOCK_ZONE(zone);
15001 INSIST(zone->irefs > 1);
15002 zone->irefs--;
15003 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
15004 goto nextevent;
15005 }
15006
15007 event = ISC_LIST_HEAD(zone->rss_post);
15008 while (event != NULL) {
15009 ISC_LIST_UNLINK(zone->rss_post, event, ev_link);
15010 rss_post(zone, event);
15011 event = ISC_LIST_HEAD(zone->rss_post);
15012 }
15013
15014 dns_zone_idetach(&zone);
15015 }
15016
15017 static isc_result_t
15018 zone_send_secureserial(dns_zone_t *zone, uint32_t serial) {
15019 isc_event_t *e;
15020 dns_zone_t *dummy = NULL;
15021
15022 e = isc_event_allocate(zone->secure->mctx, zone,
15023 DNS_EVENT_ZONESECURESERIAL,
15024 receive_secure_serial, zone->secure,
15025 sizeof(struct secure_event));
15026 if (e == NULL)
15027 return (ISC_R_NOMEMORY);
15028 ((struct secure_event *)e)->serial = serial;
15029 INSIST(LOCKED_ZONE(zone->secure));
15030 zone_iattach(zone->secure, &dummy);
15031 isc_task_send(zone->secure->task, &e);
15032
15033 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
15034 return (ISC_R_SUCCESS);
15035 }
15036
15037 static isc_result_t
15038 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
15039 dns_rdataset_t *rdataset, uint32_t oldserial)
15040 {
15041 dns_rdata_soa_t soa;
15042 dns_rdata_t rdata = DNS_RDATA_INIT;
15043 dns_rdatalist_t temprdatalist;
15044 dns_rdataset_t temprdataset;
15045 isc_buffer_t b;
15046 isc_result_t result;
15047 unsigned char buf[DNS_SOA_BUFFERSIZE];
15048 dns_fixedname_t fixed;
15049 dns_name_t *name;
15050
15051 result = dns_rdataset_first(rdataset);
15052 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15053 dns_rdataset_current(rdataset, &rdata);
15054 result = dns_rdata_tostruct(&rdata, &soa, NULL);
15055 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15056
15057 if (isc_serial_gt(soa.serial, oldserial))
15058 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
15059 NULL));
15060 /*
15061 * Always bump the serial.
15062 */
15063 oldserial++;
15064 if (oldserial == 0)
15065 oldserial++;
15066 soa.serial = oldserial;
15067
15068 /*
15069 * Construct a replacement rdataset.
15070 */
15071 dns_rdata_reset(&rdata);
15072 isc_buffer_init(&b, buf, sizeof(buf));
15073 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
15074 dns_rdatatype_soa, &soa, &b);
15075 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15076 dns_rdatalist_init(&temprdatalist);
15077 temprdatalist.rdclass = rdata.rdclass;
15078 temprdatalist.type = rdata.type;
15079 temprdatalist.ttl = rdataset->ttl;
15080 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
15081
15082 dns_rdataset_init(&temprdataset);
15083 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
15084 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15085
15086 name = dns_fixedname_initname(&fixed);
15087 result = dns_db_nodefullname(db, node, name);
15088 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15089 dns_rdataset_getownercase(rdataset, name);
15090 dns_rdataset_setownercase(&temprdataset, name);
15091 return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
15092 0, NULL));
15093 }
15094
15095 /*
15096 * This function should populate an nsec3paramlist_t with the
15097 * nsecparam_t data from a zone.
15098 */
15099 static isc_result_t
15100 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
15101 isc_result_t result;
15102 dns_dbnode_t *node = NULL;
15103 dns_rdataset_t rdataset, prdataset;
15104 dns_dbversion_t *version = NULL;
15105 nsec3param_t *nsec3param = NULL;
15106 nsec3param_t *nsec3p = NULL;
15107 nsec3param_t *next;
15108 dns_db_t *db = NULL;
15109 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
15110
15111 REQUIRE(DNS_ZONE_VALID(zone));
15112 REQUIRE(nsec3list != NULL);
15113 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
15114
15115 dns_rdataset_init(&rdataset);
15116 dns_rdataset_init(&prdataset);
15117
15118 dns_db_attach(zone->db, &db);
15119 CHECK(dns_db_getoriginnode(db, &node));
15120
15121 dns_db_currentversion(db, &version);
15122 result = dns_db_findrdataset(db, node, version,
15123 dns_rdatatype_nsec3param,
15124 dns_rdatatype_none, 0, &rdataset, NULL);
15125
15126 if (result != ISC_R_SUCCESS)
15127 goto getprivate;
15128
15129 /*
15130 * walk nsec3param rdataset making a list of parameters (note that
15131 * multiple simultaneous nsec3 chains are annoyingly legal -- this
15132 * is why we use an nsec3list, even tho we will usually only have
15133 * one)
15134 */
15135 for (result = dns_rdataset_first(&rdataset);
15136 result == ISC_R_SUCCESS;
15137 result = dns_rdataset_next(&rdataset))
15138 {
15139 dns_rdata_t rdata = DNS_RDATA_INIT;
15140 dns_rdata_t private = DNS_RDATA_INIT;
15141
15142 dns_rdataset_current(&rdataset, &rdata);
15143 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15144 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15145 "looping through nsec3param data");
15146 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
15147 if (nsec3param == NULL)
15148 CHECK(ISC_R_NOMEMORY);
15149 ISC_LINK_INIT(nsec3param, link);
15150
15151 /*
15152 * now transfer the data from the rdata to
15153 * the nsec3param
15154 */
15155 dns_nsec3param_toprivate(&rdata, &private,
15156 zone->privatetype, nsec3param->data,
15157 sizeof(nsec3param->data));
15158 nsec3param->length = private.length;
15159 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
15160 }
15161
15162 getprivate:
15163 result = dns_db_findrdataset(db, node, version, zone->privatetype,
15164 dns_rdatatype_none, 0, &prdataset, NULL);
15165 if (result != ISC_R_SUCCESS)
15166 goto done;
15167
15168 /*
15169 * walk private type records, converting them to nsec3 parameters
15170 * using dns_nsec3param_fromprivate(), do the right thing based on
15171 * CREATE and REMOVE flags
15172 */
15173 for (result = dns_rdataset_first(&prdataset);
15174 result == ISC_R_SUCCESS;
15175 result = dns_rdataset_next(&prdataset))
15176 {
15177 dns_rdata_t rdata = DNS_RDATA_INIT;
15178 dns_rdata_t private = DNS_RDATA_INIT;
15179
15180 dns_rdataset_current(&prdataset, &private);
15181 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15182 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15183 "looping through nsec3param private data");
15184
15185 /*
15186 * Do we have a valid private record?
15187 */
15188 if (!dns_nsec3param_fromprivate(&private, &rdata,
15189 buf, sizeof(buf)))
15190 continue;
15191
15192 /*
15193 * Remove any NSEC3PARAM records scheduled to be removed.
15194 */
15195 if (NSEC3REMOVE(rdata.data[1])) {
15196 /*
15197 * Zero out the flags.
15198 */
15199 rdata.data[1] = 0;
15200
15201 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
15202 nsec3p != NULL;
15203 nsec3p = next)
15204 {
15205 next = ISC_LIST_NEXT(nsec3p, link);
15206
15207 if (nsec3p->length == rdata.length + 1 &&
15208 memcmp(rdata.data, nsec3p->data + 1,
15209 nsec3p->length - 1) == 0) {
15210 ISC_LIST_UNLINK(*nsec3list,
15211 nsec3p, link);
15212 isc_mem_put(zone->mctx, nsec3p,
15213 sizeof(nsec3param_t));
15214 }
15215 }
15216 continue;
15217 }
15218
15219 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
15220 if (nsec3param == NULL)
15221 CHECK(ISC_R_NOMEMORY);
15222 ISC_LINK_INIT(nsec3param, link);
15223
15224 /*
15225 * Copy the remaining private records so the nsec/nsec3
15226 * chain gets created.
15227 */
15228 INSIST(private.length <= sizeof(nsec3param->data));
15229 memmove(nsec3param->data, private.data, private.length);
15230 nsec3param->length = private.length;
15231 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
15232 }
15233
15234 done:
15235 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
15236 result = ISC_R_SUCCESS;
15237
15238 failure:
15239 if (node != NULL)
15240 dns_db_detachnode(db, &node);
15241 if (version != NULL)
15242 dns_db_closeversion(db, &version, false);
15243 if (db != NULL)
15244 dns_db_detach(&db);
15245 if (dns_rdataset_isassociated(&rdataset))
15246 dns_rdataset_disassociate(&rdataset);
15247 if (dns_rdataset_isassociated(&prdataset))
15248 dns_rdataset_disassociate(&prdataset);
15249 return (result);
15250 }
15251
15252 /*
15253 * Populate new zone db with private type records found by save_nsec3param().
15254 */
15255 static isc_result_t
15256 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
15257 nsec3paramlist_t *nsec3list)
15258 {
15259 isc_result_t result = ISC_R_SUCCESS;
15260 dns_diff_t diff;
15261 dns_rdata_t rdata;
15262 nsec3param_t *nsec3p = NULL;
15263 nsec3param_t *next;
15264
15265 REQUIRE(DNS_ZONE_VALID(zone));
15266 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
15267
15268 dns_diff_init(zone->mctx, &diff);
15269
15270 /*
15271 * Loop through the list of private-type records, set the INITIAL
15272 * and CREATE flags, and the add the record to the apex of the tree
15273 * in db.
15274 */
15275 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
15276 nsec3p != NULL;
15277 nsec3p = next)
15278 {
15279 next = ISC_LIST_NEXT(nsec3p, link);
15280 dns_rdata_init(&rdata);
15281 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
15282 rdata.length = nsec3p->length;
15283 rdata.data = nsec3p->data;
15284 rdata.type = zone->privatetype;
15285 rdata.rdclass = zone->rdclass;
15286 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
15287 &zone->origin, 0, &rdata);
15288 if (result != ISC_R_SUCCESS) {
15289 break;
15290 }
15291 }
15292
15293 dns_diff_clear(&diff);
15294 return (result);
15295 }
15296
15297 static void
15298 receive_secure_db(isc_task_t *task, isc_event_t *event) {
15299 isc_result_t result;
15300 dns_zone_t *zone;
15301 dns_db_t *rawdb, *db = NULL;
15302 dns_dbnode_t *rawnode = NULL, *node = NULL;
15303 dns_fixedname_t fname;
15304 dns_name_t *name;
15305 dns_dbiterator_t *dbiterator = NULL;
15306 dns_rdatasetiter_t *rdsit = NULL;
15307 dns_rdataset_t rdataset;
15308 dns_dbversion_t *version = NULL;
15309 isc_time_t loadtime;
15310 unsigned int oldserial = 0;
15311 bool have_oldserial = false;
15312 nsec3paramlist_t nsec3list;
15313 isc_event_t *setnsec3param_event;
15314 dns_zone_t *dummy;
15315
15316 UNUSED(task);
15317
15318 ISC_LIST_INIT(nsec3list);
15319
15320 zone = event->ev_arg;
15321 rawdb = ((struct secure_event *)event)->db;
15322 isc_event_free(&event);
15323
15324 name = dns_fixedname_initname(&fname);
15325 dns_rdataset_init(&rdataset);
15326
15327 LOCK_ZONE(zone);
15328 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
15329 result = ISC_R_SHUTTINGDOWN;
15330 goto failure;
15331 }
15332
15333 TIME_NOW(&loadtime);
15334 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15335 if (zone->db != NULL) {
15336 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
15337 if (result == ISC_R_SUCCESS)
15338 have_oldserial = true;
15339
15340 /*
15341 * assemble nsec3parameters from the old zone, and set a flag
15342 * if any are found
15343 */
15344 result = save_nsec3param(zone, &nsec3list);
15345 if (result != ISC_R_SUCCESS) {
15346 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15347 goto failure;
15348 }
15349 }
15350 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15351
15352 result = dns_db_create(zone->mctx, zone->db_argv[0],
15353 &zone->origin, dns_dbtype_zone, zone->rdclass,
15354 zone->db_argc - 1, zone->db_argv + 1, &db);
15355 if (result != ISC_R_SUCCESS)
15356 goto failure;
15357
15358 result = dns_db_setgluecachestats(db, zone->gluecachestats);
15359 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
15360 goto failure;
15361 }
15362
15363 result = dns_db_newversion(db, &version);
15364 if (result != ISC_R_SUCCESS)
15365 goto failure;
15366
15367 result = dns_db_createiterator(rawdb, 0, &dbiterator);
15368 if (result != ISC_R_SUCCESS)
15369 goto failure;
15370
15371 for (result = dns_dbiterator_first(dbiterator);
15372 result == ISC_R_SUCCESS;
15373 result = dns_dbiterator_next(dbiterator)) {
15374 result = dns_dbiterator_current(dbiterator, &rawnode, name);
15375 if (result != ISC_R_SUCCESS)
15376 continue;
15377
15378 result = dns_db_findnode(db, name, true, &node);
15379 if (result != ISC_R_SUCCESS)
15380 goto failure;
15381
15382 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
15383 if (result != ISC_R_SUCCESS)
15384 goto failure;
15385
15386 for (result = dns_rdatasetiter_first(rdsit);
15387 result == ISC_R_SUCCESS;
15388 result = dns_rdatasetiter_next(rdsit)) {
15389 dns_rdatasetiter_current(rdsit, &rdataset);
15390 if (rdataset.type == dns_rdatatype_nsec ||
15391 rdataset.type == dns_rdatatype_rrsig ||
15392 rdataset.type == dns_rdatatype_nsec3 ||
15393 rdataset.type == dns_rdatatype_dnskey ||
15394 rdataset.type == dns_rdatatype_nsec3param) {
15395 dns_rdataset_disassociate(&rdataset);
15396 continue;
15397 }
15398 if (rdataset.type == dns_rdatatype_soa &&
15399 have_oldserial) {
15400 result = checkandaddsoa(db, node, version,
15401 &rdataset, oldserial);
15402 } else
15403 result = dns_db_addrdataset(db, node, version,
15404 0, &rdataset, 0,
15405 NULL);
15406 if (result != ISC_R_SUCCESS)
15407 goto failure;
15408
15409 dns_rdataset_disassociate(&rdataset);
15410 }
15411 dns_rdatasetiter_destroy(&rdsit);
15412 dns_db_detachnode(rawdb, &rawnode);
15413 dns_db_detachnode(db, &node);
15414 }
15415
15416 /*
15417 * Call restore_nsec3param() to create private-type records from
15418 * the old nsec3 parameters and insert them into db
15419 */
15420 if (!ISC_LIST_EMPTY(nsec3list)) {
15421 result = restore_nsec3param(zone, db, version, &nsec3list);
15422 if (result != ISC_R_SUCCESS) {
15423 goto failure;
15424 }
15425 }
15426
15427 dns_db_closeversion(db, &version, true);
15428
15429 /*
15430 * Lock hierarchy: zmgr, zone, raw.
15431 */
15432 INSIST(zone != zone->raw);
15433 LOCK_ZONE(zone->raw);
15434 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15435 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
15436 zone_needdump(zone, 0); /* XXXMPA */
15437 UNLOCK_ZONE(zone->raw);
15438
15439 /*
15440 * Process any queued NSEC3PARAM change requests.
15441 */
15442 while (!ISC_LIST_EMPTY(zone->setnsec3param_queue)) {
15443 setnsec3param_event = ISC_LIST_HEAD(zone->setnsec3param_queue);
15444 ISC_LIST_UNLINK(zone->setnsec3param_queue, setnsec3param_event,
15445 ev_link);
15446 dummy = NULL;
15447 zone_iattach(zone, &dummy);
15448 isc_task_send(zone->task, &setnsec3param_event);
15449 }
15450
15451 failure:
15452 UNLOCK_ZONE(zone);
15453 if (result != ISC_R_SUCCESS)
15454 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
15455 dns_result_totext(result));
15456
15457 while (!ISC_LIST_EMPTY(nsec3list)) {
15458 nsec3param_t *nsec3p;
15459 nsec3p = ISC_LIST_HEAD(nsec3list);
15460 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
15461 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
15462 }
15463 if (dns_rdataset_isassociated(&rdataset))
15464 dns_rdataset_disassociate(&rdataset);
15465 if (db != NULL) {
15466 if (node != NULL)
15467 dns_db_detachnode(db, &node);
15468 if (version != NULL)
15469 dns_db_closeversion(db, &version, false);
15470 dns_db_detach(&db);
15471 }
15472 if (rawnode != NULL)
15473 dns_db_detachnode(rawdb, &rawnode);
15474 dns_db_detach(&rawdb);
15475 if (dbiterator != NULL)
15476 dns_dbiterator_destroy(&dbiterator);
15477 dns_zone_idetach(&zone);
15478
15479 INSIST(version == NULL);
15480 }
15481
15482 static isc_result_t
15483 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
15484 isc_event_t *e;
15485 dns_db_t *dummy = NULL;
15486 dns_zone_t *secure = NULL;
15487
15488 e = isc_event_allocate(zone->secure->mctx, zone,
15489 DNS_EVENT_ZONESECUREDB,
15490 receive_secure_db, zone->secure,
15491 sizeof(struct secure_event));
15492 if (e == NULL)
15493 return (ISC_R_NOMEMORY);
15494 dns_db_attach(db, &dummy);
15495 ((struct secure_event *)e)->db = dummy;
15496 INSIST(LOCKED_ZONE(zone->secure));
15497 zone_iattach(zone->secure, &secure);
15498 isc_task_send(zone->secure->task, &e);
15499 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
15500 return (ISC_R_SUCCESS);
15501 }
15502
15503 isc_result_t
15504 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
15505 isc_result_t result;
15506 dns_zone_t *secure = NULL;
15507
15508 REQUIRE(DNS_ZONE_VALID(zone));
15509 again:
15510 LOCK_ZONE(zone);
15511 if (inline_raw(zone)) {
15512 secure = zone->secure;
15513 INSIST(secure != zone);
15514 TRYLOCK_ZONE(result, secure);
15515 if (result != ISC_R_SUCCESS) {
15516 UNLOCK_ZONE(zone);
15517 secure = NULL;
15518 isc_thread_yield();
15519 goto again;
15520 }
15521 }
15522 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
15523 result = zone_replacedb(zone, db, dump);
15524 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
15525 if (secure != NULL)
15526 UNLOCK_ZONE(secure);
15527 UNLOCK_ZONE(zone);
15528 return (result);
15529 }
15530
15531 static isc_result_t
15532 zone_replacedb(dns_zone_t *zone, dns_db_t *db, bool dump) {
15533 dns_dbversion_t *ver;
15534 isc_result_t result;
15535 unsigned int soacount = 0;
15536 unsigned int nscount = 0;
15537
15538 /*
15539 * 'zone' and 'zone->db' locked by caller.
15540 */
15541 REQUIRE(DNS_ZONE_VALID(zone));
15542 REQUIRE(LOCKED_ZONE(zone));
15543 if (inline_raw(zone))
15544 REQUIRE(LOCKED_ZONE(zone->secure));
15545
15546 result = zone_get_from_db(zone, db, &nscount, &soacount,
15547 NULL, NULL, NULL, NULL, NULL, NULL);
15548 if (result == ISC_R_SUCCESS) {
15549 if (soacount != 1) {
15550 dns_zone_log(zone, ISC_LOG_ERROR,
15551 "has %d SOA records", soacount);
15552 result = DNS_R_BADZONE;
15553 }
15554 if (nscount == 0 && zone->type != dns_zone_key) {
15555 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
15556 result = DNS_R_BADZONE;
15557 }
15558 if (result != ISC_R_SUCCESS)
15559 return (result);
15560 } else {
15561 dns_zone_log(zone, ISC_LOG_ERROR,
15562 "retrieving SOA and NS records failed: %s",
15563 dns_result_totext(result));
15564 return (result);
15565 }
15566
15567 result = check_nsec3param(zone, db);
15568 if (result != ISC_R_SUCCESS)
15569 return (result);
15570
15571 ver = NULL;
15572 dns_db_currentversion(db, &ver);
15573
15574 /*
15575 * The initial version of a slave zone is always dumped;
15576 * subsequent versions may be journaled instead if this
15577 * is enabled in the configuration.
15578 */
15579 if (zone->db != NULL && zone->journal != NULL &&
15580 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
15581 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
15582 {
15583 uint32_t serial, oldserial;
15584
15585 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
15586
15587 result = dns_db_getsoaserial(db, ver, &serial);
15588 if (result != ISC_R_SUCCESS) {
15589 dns_zone_log(zone, ISC_LOG_ERROR,
15590 "ixfr-from-differences: unable to get "
15591 "new serial");
15592 goto fail;
15593 }
15594
15595 /*
15596 * This is checked in zone_postload() for master zones.
15597 */
15598 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
15599 &oldserial, NULL, NULL, NULL, NULL,
15600 NULL);
15601 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15602 RUNTIME_CHECK(soacount > 0U);
15603 if ((zone->type == dns_zone_slave ||
15604 (zone->type == dns_zone_redirect &&
15605 zone->masters != NULL))
15606 && !isc_serial_gt(serial, oldserial)) {
15607 uint32_t serialmin, serialmax;
15608 serialmin = (oldserial + 1) & 0xffffffffU;
15609 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
15610 dns_zone_log(zone, ISC_LOG_ERROR,
15611 "ixfr-from-differences: failed: "
15612 "new serial (%u) out of range [%u - %u]",
15613 serial, serialmin, serialmax);
15614 result = ISC_R_RANGE;
15615 goto fail;
15616 }
15617
15618 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
15619 zone->journal);
15620 if (result != ISC_R_SUCCESS) {
15621 char strbuf[ISC_STRERRORSIZE];
15622 strerror_r(errno, strbuf, sizeof(strbuf));
15623 dns_zone_log(zone, ISC_LOG_ERROR,
15624 "ixfr-from-differences: failed: "
15625 "%s", strbuf);
15626 goto fallback;
15627 }
15628 if (dump)
15629 zone_needdump(zone, DNS_DUMP_DELAY);
15630 else
15631 zone_journal_compact(zone, zone->db, serial);
15632 if (zone->type == dns_zone_master && inline_raw(zone))
15633 zone_send_secureserial(zone, serial);
15634 } else {
15635 fallback:
15636 if (dump && zone->masterfile != NULL) {
15637 /*
15638 * If DNS_ZONEFLG_FORCEXFER was set we don't want
15639 * to keep the old masterfile.
15640 */
15641 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
15642 remove(zone->masterfile) < 0 && errno != ENOENT) {
15643 char strbuf[ISC_STRERRORSIZE];
15644 strerror_r(errno, strbuf, sizeof(strbuf));
15645 isc_log_write(dns_lctx,
15646 DNS_LOGCATEGORY_GENERAL,
15647 DNS_LOGMODULE_ZONE,
15648 ISC_LOG_WARNING,
15649 "unable to remove masterfile "
15650 "'%s': '%s'",
15651 zone->masterfile, strbuf);
15652 }
15653 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
15654 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
15655 else
15656 zone_needdump(zone, 0);
15657 }
15658 if (dump && zone->journal != NULL) {
15659 /*
15660 * The in-memory database just changed, and
15661 * because 'dump' is set, it didn't change by
15662 * being loaded from disk. Also, we have not
15663 * journaled diffs for this change.
15664 * Therefore, the on-disk journal is missing
15665 * the deltas for this change. Since it can
15666 * no longer be used to bring the zone
15667 * up-to-date, it is useless and should be
15668 * removed.
15669 */
15670 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15671 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15672 "removing journal file");
15673 if (remove(zone->journal) < 0 && errno != ENOENT) {
15674 char strbuf[ISC_STRERRORSIZE];
15675 strerror_r(errno, strbuf, sizeof(strbuf));
15676 isc_log_write(dns_lctx,
15677 DNS_LOGCATEGORY_GENERAL,
15678 DNS_LOGMODULE_ZONE,
15679 ISC_LOG_WARNING,
15680 "unable to remove journal "
15681 "'%s': '%s'",
15682 zone->journal, strbuf);
15683 }
15684 }
15685
15686 if (inline_raw(zone))
15687 zone_send_securedb(zone, db);
15688 }
15689
15690 dns_db_closeversion(db, &ver, false);
15691
15692 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
15693
15694 if (zone->db != NULL)
15695 zone_detachdb(zone);
15696 zone_attachdb(zone, db);
15697 dns_db_settask(zone->db, zone->task);
15698 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
15699 return (ISC_R_SUCCESS);
15700
15701 fail:
15702 dns_db_closeversion(db, &ver, false);
15703 return (result);
15704 }
15705
15706 /* The caller must hold the dblock as a writer. */
15707 static inline void
15708 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
15709 REQUIRE(zone->db == NULL && db != NULL);
15710
15711 dns_db_attach(db, &zone->db);
15712 }
15713
15714 /* The caller must hold the dblock as a writer. */
15715 static inline void
15716 zone_detachdb(dns_zone_t *zone) {
15717 REQUIRE(zone->db != NULL);
15718
15719 dns_db_detach(&zone->db);
15720 }
15721
15722 static void
15723 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
15724 isc_time_t now;
15725 bool again = false;
15726 unsigned int soacount;
15727 unsigned int nscount;
15728 uint32_t serial, refresh, retry, expire, minimum;
15729 isc_result_t xfrresult = result;
15730 bool free_needed;
15731 dns_zone_t *secure = NULL;
15732
15733 REQUIRE(DNS_ZONE_VALID(zone));
15734
15735 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15736 "zone transfer finished: %s", dns_result_totext(result));
15737
15738 /*
15739 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
15740 * could result in a deadlock due to a LOR so we will spin if we
15741 * can't obtain the both locks.
15742 */
15743 again:
15744 LOCK_ZONE(zone);
15745 if (inline_raw(zone)) {
15746 secure = zone->secure;
15747 INSIST(secure != zone);
15748 TRYLOCK_ZONE(result, secure);
15749 if (result != ISC_R_SUCCESS) {
15750 UNLOCK_ZONE(zone);
15751 secure = NULL;
15752 isc_thread_yield();
15753 goto again;
15754 }
15755 }
15756
15757 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
15758 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15759 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
15760
15761 TIME_NOW(&now);
15762 switch (xfrresult) {
15763 case ISC_R_SUCCESS:
15764 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15765 /* FALLTHROUGH */
15766 case DNS_R_UPTODATE:
15767 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15768 /*
15769 * Has the zone expired underneath us?
15770 */
15771 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15772 if (zone->db == NULL) {
15773 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15774 goto same_master;
15775 }
15776
15777 /*
15778 * Update the zone structure's data from the actual
15779 * SOA received.
15780 */
15781 nscount = 0;
15782 soacount = 0;
15783 INSIST(zone->db != NULL);
15784 result = zone_get_from_db(zone, zone->db, &nscount,
15785 &soacount, &serial, &refresh,
15786 &retry, &expire, &minimum, NULL);
15787 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15788 if (result == ISC_R_SUCCESS) {
15789 if (soacount != 1)
15790 dns_zone_log(zone, ISC_LOG_ERROR,
15791 "transferred zone "
15792 "has %d SOA record%s", soacount,
15793 (soacount != 0) ? "s" : "");
15794 if (nscount == 0) {
15795 dns_zone_log(zone, ISC_LOG_ERROR,
15796 "transferred zone "
15797 "has no NS records");
15798 if (DNS_ZONE_FLAG(zone,
15799 DNS_ZONEFLG_HAVETIMERS)) {
15800 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
15801 zone->retry = DNS_ZONE_DEFAULTRETRY;
15802 }
15803 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15804 zone_unload(zone);
15805 goto next_master;
15806 }
15807 zone->refresh = RANGE(refresh, zone->minrefresh,
15808 zone->maxrefresh);
15809 zone->retry = RANGE(retry, zone->minretry,
15810 zone->maxretry);
15811 zone->expire = RANGE(expire,
15812 zone->refresh + zone->retry,
15813 DNS_MAX_EXPIRE);
15814 zone->minimum = minimum;
15815 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15816 }
15817
15818 /*
15819 * Set our next update/expire times.
15820 */
15821 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
15822 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15823 zone->refreshtime = now;
15824 DNS_ZONE_TIME_ADD(&now, zone->expire,
15825 &zone->expiretime);
15826 } else {
15827 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
15828 &zone->refreshtime);
15829 DNS_ZONE_TIME_ADD(&now, zone->expire,
15830 &zone->expiretime);
15831 }
15832 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
15833 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
15834 if (zone->tsigkey != NULL) {
15835 char namebuf[DNS_NAME_FORMATSIZE];
15836 dns_name_format(&zone->tsigkey->name, namebuf,
15837 sizeof(namebuf));
15838 snprintf(buf, sizeof(buf), ": TSIG '%s'",
15839 namebuf);
15840 } else
15841 buf[0] = '\0';
15842 dns_zone_log(zone, ISC_LOG_INFO,
15843 "transferred serial %u%s",
15844 serial, buf);
15845 if (inline_raw(zone))
15846 zone_send_secureserial(zone, serial);
15847 }
15848
15849 /*
15850 * This is not necessary if we just performed a AXFR
15851 * however it is necessary for an IXFR / UPTODATE and
15852 * won't hurt with an AXFR.
15853 */
15854 if (zone->masterfile != NULL || zone->journal != NULL) {
15855 unsigned int delay = DNS_DUMP_DELAY;
15856
15857 result = ISC_R_FAILURE;
15858 if (zone->journal != NULL)
15859 result = isc_file_settime(zone->journal, &now);
15860 if (result != ISC_R_SUCCESS &&
15861 zone->masterfile != NULL)
15862 result = isc_file_settime(zone->masterfile,
15863 &now);
15864
15865 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
15866 result == ISC_R_FILENOTFOUND)
15867 delay = 0;
15868
15869 if ((result == ISC_R_SUCCESS ||
15870 result == ISC_R_FILENOTFOUND) &&
15871 zone->masterfile != NULL)
15872 zone_needdump(zone, delay);
15873 else if (result != ISC_R_SUCCESS)
15874 dns_zone_log(zone, ISC_LOG_ERROR,
15875 "transfer: could not set file "
15876 "modification time of '%s': %s",
15877 zone->masterfile,
15878 dns_result_totext(result));
15879 }
15880 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
15881 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
15882 break;
15883
15884 case DNS_R_BADIXFR:
15885 /* Force retry with AXFR. */
15886 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
15887 goto same_master;
15888
15889 case DNS_R_TOOMANYRECORDS:
15890 case DNS_R_VERIFYFAILURE:
15891 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
15892 inc_stats(zone, dns_zonestatscounter_xfrfail);
15893 break;
15894
15895 default:
15896 next_master:
15897 /*
15898 * Skip to next failed / untried master.
15899 */
15900 do {
15901 zone->curmaster++;
15902 } while (zone->curmaster < zone->masterscnt &&
15903 zone->mastersok[zone->curmaster]);
15904 /* FALLTHROUGH */
15905 same_master:
15906 if (zone->curmaster >= zone->masterscnt) {
15907 zone->curmaster = 0;
15908 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
15909 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
15910 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15911 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15912 while (zone->curmaster < zone->masterscnt &&
15913 zone->mastersok[zone->curmaster])
15914 zone->curmaster++;
15915 again = true;
15916 } else
15917 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15918 } else {
15919 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15920 again = true;
15921 }
15922 inc_stats(zone, dns_zonestatscounter_xfrfail);
15923 break;
15924 }
15925 zone_settimer(zone, &now);
15926
15927 /*
15928 * If creating the transfer object failed, zone->xfr is NULL.
15929 * Otherwise, we are called as the done callback of a zone
15930 * transfer object that just entered its shutting-down
15931 * state. Since we are no longer responsible for shutting
15932 * it down, we can detach our reference.
15933 */
15934 if (zone->xfr != NULL)
15935 dns_xfrin_detach(&zone->xfr);
15936
15937 if (zone->tsigkey != NULL)
15938 dns_tsigkey_detach(&zone->tsigkey);
15939
15940 /*
15941 * Handle any deferred journal compaction.
15942 */
15943 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
15944 dns_db_t *db = NULL;
15945 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
15946 zone_journal_compact(zone, db, zone->compact_serial);
15947 dns_db_detach(&db);
15948 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
15949 }
15950 }
15951
15952 if (secure != NULL)
15953 UNLOCK_ZONE(secure);
15954 /*
15955 * This transfer finishing freed up a transfer quota slot.
15956 * Let any other zones waiting for quota have it.
15957 */
15958 if (zone->zmgr != NULL &&
15959 zone->statelist == &zone->zmgr->xfrin_in_progress) {
15960 UNLOCK_ZONE(zone);
15961 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15962 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
15963 zone->statelist = NULL;
15964 zmgr_resume_xfrs(zone->zmgr, false);
15965 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15966 LOCK_ZONE(zone);
15967 }
15968
15969 /*
15970 * Retry with a different server if necessary.
15971 */
15972 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
15973 queue_soa_query(zone);
15974
15975 INSIST(zone->irefs > 0);
15976 zone->irefs--;
15977 free_needed = exit_check(zone);
15978 UNLOCK_ZONE(zone);
15979 if (free_needed)
15980 zone_free(zone);
15981 }
15982
15983 static void
15984 zone_loaddone(void *arg, isc_result_t result) {
15985 static char me[] = "zone_loaddone";
15986 dns_load_t *load = arg;
15987 dns_zone_t *zone;
15988 isc_result_t tresult;
15989 dns_zone_t *secure = NULL;
15990
15991 REQUIRE(DNS_LOAD_VALID(load));
15992 zone = load->zone;
15993
15994 ENTER;
15995
15996 /*
15997 * If zone loading failed, remove the update db callbacks prior
15998 * to calling the list of callbacks in the zone load structure.
15999 */
16000 if (result != ISC_R_SUCCESS) {
16001 dns_zone_rpz_disable_db(zone, load->db);
16002 dns_zone_catz_disable_db(zone, load->db);
16003 }
16004
16005 tresult = dns_db_endload(load->db, &load->callbacks);
16006 if (tresult != ISC_R_SUCCESS &&
16007 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
16008 result = tresult;
16009
16010 /*
16011 * Lock hierarchy: zmgr, zone, raw.
16012 */
16013 again:
16014 LOCK_ZONE(zone);
16015 INSIST(zone != zone->raw);
16016 if (inline_secure(zone))
16017 LOCK_ZONE(zone->raw);
16018 else if (inline_raw(zone)) {
16019 secure = zone->secure;
16020 TRYLOCK_ZONE(tresult, secure);
16021 if (tresult != ISC_R_SUCCESS) {
16022 UNLOCK_ZONE(zone);
16023 secure = NULL;
16024 isc_thread_yield();
16025 goto again;
16026 }
16027 }
16028 (void)zone_postload(zone, load->db, load->loadtime, result);
16029 zonemgr_putio(&zone->readio);
16030 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
16031 zone_idetach(&load->callbacks.zone);
16032 /*
16033 * Leave the zone frozen if the reload fails.
16034 */
16035 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
16036 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
16037 zone->update_disabled = false;
16038 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
16039 if (inline_secure(zone))
16040 UNLOCK_ZONE(zone->raw);
16041 else if (secure != NULL)
16042 UNLOCK_ZONE(secure);
16043 UNLOCK_ZONE(zone);
16044
16045 load->magic = 0;
16046 dns_db_detach(&load->db);
16047 if (load->zone->lctx != NULL)
16048 dns_loadctx_detach(&load->zone->lctx);
16049 dns_zone_idetach(&load->zone);
16050 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
16051 }
16052
16053 void
16054 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
16055 REQUIRE(DNS_ZONE_VALID(zone));
16056 REQUIRE(table != NULL);
16057 REQUIRE(*table == NULL);
16058
16059 LOCK_ZONE(zone);
16060 if (zone->ssutable != NULL)
16061 dns_ssutable_attach(zone->ssutable, table);
16062 UNLOCK_ZONE(zone);
16063 }
16064
16065 void
16066 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
16067 REQUIRE(DNS_ZONE_VALID(zone));
16068
16069 LOCK_ZONE(zone);
16070 if (zone->ssutable != NULL)
16071 dns_ssutable_detach(&zone->ssutable);
16072 if (table != NULL)
16073 dns_ssutable_attach(table, &zone->ssutable);
16074 UNLOCK_ZONE(zone);
16075 }
16076
16077 void
16078 dns_zone_setsigvalidityinterval(dns_zone_t *zone, uint32_t interval) {
16079 REQUIRE(DNS_ZONE_VALID(zone));
16080
16081 zone->sigvalidityinterval = interval;
16082 }
16083
16084 uint32_t
16085 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
16086 REQUIRE(DNS_ZONE_VALID(zone));
16087
16088 return (zone->sigvalidityinterval);
16089 }
16090
16091 void
16092 dns_zone_setkeyvalidityinterval(dns_zone_t *zone, uint32_t interval) {
16093 REQUIRE(DNS_ZONE_VALID(zone));
16094
16095 zone->keyvalidityinterval = interval;
16096 }
16097
16098 uint32_t
16099 dns_zone_getkeyvalidityinterval(dns_zone_t *zone) {
16100 REQUIRE(DNS_ZONE_VALID(zone));
16101
16102 return (zone->keyvalidityinterval);
16103 }
16104
16105 void
16106 dns_zone_setsigresigninginterval(dns_zone_t *zone, uint32_t interval) {
16107 isc_time_t now;
16108
16109 REQUIRE(DNS_ZONE_VALID(zone));
16110
16111 LOCK_ZONE(zone);
16112 zone->sigresigninginterval = interval;
16113 set_resigntime(zone);
16114 if (zone->task != NULL) {
16115 TIME_NOW(&now);
16116 zone_settimer(zone, &now);
16117 }
16118 UNLOCK_ZONE(zone);
16119 }
16120
16121 uint32_t
16122 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
16123 REQUIRE(DNS_ZONE_VALID(zone));
16124
16125 return (zone->sigresigninginterval);
16126 }
16127
16128 static void
16129 queue_xfrin(dns_zone_t *zone) {
16130 const char me[] = "queue_xfrin";
16131 isc_result_t result;
16132 dns_zonemgr_t *zmgr = zone->zmgr;
16133
16134 ENTER;
16135
16136 INSIST(zone->statelist == NULL);
16137
16138 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16139 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
16140 LOCK_ZONE(zone);
16141 zone->irefs++;
16142 UNLOCK_ZONE(zone);
16143 zone->statelist = &zmgr->waiting_for_xfrin;
16144 result = zmgr_start_xfrin_ifquota(zmgr, zone);
16145 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16146
16147 if (result == ISC_R_QUOTA) {
16148 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
16149 "zone transfer deferred due to quota");
16150 } else if (result != ISC_R_SUCCESS) {
16151 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
16152 "starting zone transfer: %s",
16153 isc_result_totext(result));
16154 }
16155 }
16156
16157 /*
16158 * This event callback is called when a zone has received
16159 * any necessary zone transfer quota. This is the time
16160 * to go ahead and start the transfer.
16161 */
16162 static void
16163 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
16164 isc_result_t result = ISC_R_SUCCESS;
16165 dns_peer_t *peer = NULL;
16166 char master[ISC_SOCKADDR_FORMATSIZE];
16167 char source[ISC_SOCKADDR_FORMATSIZE];
16168 dns_rdatatype_t xfrtype;
16169 dns_zone_t *zone = event->ev_arg;
16170 isc_netaddr_t masterip;
16171 isc_sockaddr_t sourceaddr;
16172 isc_sockaddr_t masteraddr;
16173 isc_time_t now;
16174 const char *soa_before = "";
16175 isc_dscp_t dscp = -1;
16176 bool loaded;
16177
16178 UNUSED(task);
16179
16180 INSIST(task == zone->task);
16181
16182 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
16183 result = ISC_R_CANCELED;
16184 goto cleanup;
16185 }
16186
16187 TIME_NOW(&now);
16188
16189 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
16190 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
16191 &zone->sourceaddr, &now))
16192 {
16193 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
16194 dns_zone_log(zone, ISC_LOG_INFO,
16195 "got_transfer_quota: skipping zone transfer as "
16196 "master %s (source %s) is unreachable (cached)",
16197 master, source);
16198 result = ISC_R_CANCELED;
16199 goto cleanup;
16200 }
16201
16202 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
16203 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
16204
16205 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
16206 soa_before = "SOA before ";
16207 /*
16208 * Decide whether we should request IXFR or AXFR.
16209 */
16210 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
16211 loaded = (zone->db != NULL);
16212 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
16213
16214 if (!loaded) {
16215 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16216 "no database exists yet, requesting AXFR of "
16217 "initial version from %s", master);
16218 xfrtype = dns_rdatatype_axfr;
16219 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
16220 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16221 "forced reload, requesting AXFR of "
16222 "initial version from %s", master);
16223 xfrtype = dns_rdatatype_axfr;
16224 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
16225 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16226 "retrying with AXFR from %s due to "
16227 "previous IXFR failure", master);
16228 xfrtype = dns_rdatatype_axfr;
16229 LOCK_ZONE(zone);
16230 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
16231 UNLOCK_ZONE(zone);
16232 } else {
16233 bool use_ixfr = true;
16234 if (peer != NULL)
16235 result = dns_peer_getrequestixfr(peer, &use_ixfr);
16236 if (peer == NULL || result != ISC_R_SUCCESS)
16237 use_ixfr = zone->requestixfr;
16238 if (use_ixfr == false) {
16239 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16240 "IXFR disabled, requesting %sAXFR from %s",
16241 soa_before, master);
16242 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
16243 xfrtype = dns_rdatatype_soa;
16244 else
16245 xfrtype = dns_rdatatype_axfr;
16246 } else {
16247 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16248 "requesting IXFR from %s", master);
16249 xfrtype = dns_rdatatype_ixfr;
16250 }
16251 }
16252
16253 /*
16254 * Determine if we should attempt to sign the request with TSIG.
16255 */
16256 result = ISC_R_NOTFOUND;
16257
16258 /*
16259 * First, look for a tsig key in the master statement, then
16260 * try for a server key.
16261 */
16262 if ((zone->masterkeynames != NULL) &&
16263 (zone->masterkeynames[zone->curmaster] != NULL)) {
16264 dns_view_t *view = dns_zone_getview(zone);
16265 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
16266 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
16267 }
16268 if (zone->tsigkey == NULL)
16269 result = dns_view_getpeertsig(zone->view, &masterip,
16270 &zone->tsigkey);
16271
16272 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
16273 dns_zone_log(zone, ISC_LOG_ERROR,
16274 "could not get TSIG key for zone transfer: %s",
16275 isc_result_totext(result));
16276 }
16277
16278 if (zone->masterdscps != NULL)
16279 dscp = zone->masterdscps[zone->curmaster];
16280
16281 LOCK_ZONE(zone);
16282 masteraddr = zone->masteraddr;
16283 sourceaddr = zone->sourceaddr;
16284 switch (isc_sockaddr_pf(&masteraddr)) {
16285 case PF_INET:
16286 if (dscp == -1)
16287 dscp = zone->xfrsource4dscp;
16288 break;
16289 case PF_INET6:
16290 if (dscp == -1)
16291 dscp = zone->xfrsource6dscp;
16292 break;
16293 default:
16294 INSIST(0);
16295 ISC_UNREACHABLE();
16296 }
16297 UNLOCK_ZONE(zone);
16298 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
16299 result = dns_xfrin_create(zone, xfrtype, &masteraddr, &sourceaddr,
16300 dscp, zone->tsigkey, zone->mctx,
16301 zone->zmgr->timermgr, zone->zmgr->socketmgr,
16302 zone->task, zone_xfrdone, &zone->xfr);
16303 if (result == ISC_R_SUCCESS) {
16304 LOCK_ZONE(zone);
16305 if (xfrtype == dns_rdatatype_axfr) {
16306 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
16307 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
16308 else
16309 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
16310 } else if (xfrtype == dns_rdatatype_ixfr) {
16311 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
16312 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
16313 else
16314 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
16315 }
16316 UNLOCK_ZONE(zone);
16317 }
16318 cleanup:
16319 /*
16320 * Any failure in this function is handled like a failed
16321 * zone transfer. This ensures that we get removed from
16322 * zmgr->xfrin_in_progress.
16323 */
16324 if (result != ISC_R_SUCCESS)
16325 zone_xfrdone(zone, result);
16326
16327 isc_event_free(&event);
16328 }
16329
16330 /*
16331 * Update forwarding support.
16332 */
16333
16334 static void
16335 forward_destroy(dns_forward_t *forward) {
16336
16337 forward->magic = 0;
16338 if (forward->request != NULL)
16339 dns_request_destroy(&forward->request);
16340 if (forward->msgbuf != NULL)
16341 isc_buffer_free(&forward->msgbuf);
16342 if (forward->zone != NULL) {
16343 LOCK(&forward->zone->lock);
16344 if (ISC_LINK_LINKED(forward, link))
16345 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
16346 UNLOCK(&forward->zone->lock);
16347 dns_zone_idetach(&forward->zone);
16348 }
16349 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
16350 }
16351
16352 static isc_result_t
16353 sendtomaster(dns_forward_t *forward) {
16354 isc_result_t result;
16355 isc_sockaddr_t src;
16356 isc_dscp_t dscp = -1;
16357
16358 LOCK_ZONE(forward->zone);
16359
16360 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
16361 UNLOCK_ZONE(forward->zone);
16362 return (ISC_R_CANCELED);
16363 }
16364
16365 if (forward->which >= forward->zone->masterscnt) {
16366 UNLOCK_ZONE(forward->zone);
16367 return (ISC_R_NOMORE);
16368 }
16369
16370 forward->addr = forward->zone->masters[forward->which];
16371 /*
16372 * Always use TCP regardless of whether the original update
16373 * used TCP.
16374 * XXX The timeout may but a bit small if we are far down a
16375 * transfer graph and the master has to try several masters.
16376 */
16377 switch (isc_sockaddr_pf(&forward->addr)) {
16378 case PF_INET:
16379 src = forward->zone->xfrsource4;
16380 dscp = forward->zone->xfrsource4dscp;
16381 break;
16382 case PF_INET6:
16383 src = forward->zone->xfrsource6;
16384 dscp = forward->zone->xfrsource6dscp;
16385 break;
16386 default:
16387 result = ISC_R_NOTIMPLEMENTED;
16388 goto unlock;
16389 }
16390 result = dns_request_createraw(forward->zone->view->requestmgr,
16391 forward->msgbuf,
16392 &src, &forward->addr, dscp,
16393 forward->options, 15 /* XXX */,
16394 0, 0, forward->zone->task,
16395 forward_callback, forward,
16396 &forward->request);
16397 if (result == ISC_R_SUCCESS) {
16398 if (!ISC_LINK_LINKED(forward, link))
16399 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
16400 }
16401
16402 unlock:
16403 UNLOCK_ZONE(forward->zone);
16404 return (result);
16405 }
16406
16407 static void
16408 forward_callback(isc_task_t *task, isc_event_t *event) {
16409 const char me[] = "forward_callback";
16410 dns_requestevent_t *revent = (dns_requestevent_t *)event;
16411 dns_message_t *msg = NULL;
16412 char master[ISC_SOCKADDR_FORMATSIZE];
16413 isc_result_t result;
16414 dns_forward_t *forward;
16415 dns_zone_t *zone;
16416
16417 UNUSED(task);
16418
16419 forward = revent->ev_arg;
16420 INSIST(DNS_FORWARD_VALID(forward));
16421 zone = forward->zone;
16422 INSIST(DNS_ZONE_VALID(zone));
16423
16424 ENTER;
16425
16426 isc_sockaddr_format(&forward->addr, master, sizeof(master));
16427
16428 if (revent->result != ISC_R_SUCCESS) {
16429 dns_zone_log(zone, ISC_LOG_INFO,
16430 "could not forward dynamic update to %s: %s",
16431 master, dns_result_totext(revent->result));
16432 goto next_master;
16433 }
16434
16435 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
16436 if (result != ISC_R_SUCCESS)
16437 goto next_master;
16438
16439 result = dns_request_getresponse(revent->request, msg,
16440 DNS_MESSAGEPARSE_PRESERVEORDER |
16441 DNS_MESSAGEPARSE_CLONEBUFFER);
16442 if (result != ISC_R_SUCCESS)
16443 goto next_master;
16444
16445 switch (msg->rcode) {
16446 /*
16447 * Pass these rcodes back to client.
16448 */
16449 case dns_rcode_noerror:
16450 case dns_rcode_yxdomain:
16451 case dns_rcode_yxrrset:
16452 case dns_rcode_nxrrset:
16453 case dns_rcode_refused:
16454 case dns_rcode_nxdomain: {
16455 char rcode[128];
16456 isc_buffer_t rb;
16457
16458 isc_buffer_init(&rb, rcode, sizeof(rcode));
16459 (void)dns_rcode_totext(msg->rcode, &rb);
16460 dns_zone_log(zone, ISC_LOG_INFO,
16461 "forwarded dynamic update: "
16462 "master %s returned: %.*s",
16463 master, (int)rb.used, rcode);
16464 break;
16465 }
16466
16467 /* These should not occur if the masters/zone are valid. */
16468 case dns_rcode_notzone:
16469 case dns_rcode_notauth: {
16470 char rcode[128];
16471 isc_buffer_t rb;
16472
16473 isc_buffer_init(&rb, rcode, sizeof(rcode));
16474 (void)dns_rcode_totext(msg->rcode, &rb);
16475 dns_zone_log(zone, ISC_LOG_WARNING,
16476 "forwarding dynamic update: "
16477 "unexpected response: master %s returned: %.*s",
16478 master, (int)rb.used, rcode);
16479 goto next_master;
16480 }
16481
16482 /* Try another server for these rcodes. */
16483 case dns_rcode_formerr:
16484 case dns_rcode_servfail:
16485 case dns_rcode_notimp:
16486 case dns_rcode_badvers:
16487 default:
16488 goto next_master;
16489 }
16490
16491 /* call callback */
16492 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
16493 msg = NULL;
16494 dns_request_destroy(&forward->request);
16495 forward_destroy(forward);
16496 isc_event_free(&event);
16497 return;
16498
16499 next_master:
16500 if (msg != NULL)
16501 dns_message_destroy(&msg);
16502 isc_event_free(&event);
16503 forward->which++;
16504 dns_request_destroy(&forward->request);
16505 result = sendtomaster(forward);
16506 if (result != ISC_R_SUCCESS) {
16507 /* call callback */
16508 dns_zone_log(zone, ISC_LOG_DEBUG(3),
16509 "exhausted dynamic update forwarder list");
16510 (forward->callback)(forward->callback_arg, result, NULL);
16511 forward_destroy(forward);
16512 }
16513 }
16514
16515 isc_result_t
16516 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
16517 dns_updatecallback_t callback, void *callback_arg)
16518 {
16519 dns_forward_t *forward;
16520 isc_result_t result;
16521 isc_region_t *mr;
16522
16523 REQUIRE(DNS_ZONE_VALID(zone));
16524 REQUIRE(msg != NULL);
16525 REQUIRE(callback != NULL);
16526
16527 forward = isc_mem_get(zone->mctx, sizeof(*forward));
16528 if (forward == NULL)
16529 return (ISC_R_NOMEMORY);
16530
16531 forward->request = NULL;
16532 forward->zone = NULL;
16533 forward->msgbuf = NULL;
16534 forward->which = 0;
16535 forward->mctx = 0;
16536 forward->callback = callback;
16537 forward->callback_arg = callback_arg;
16538 ISC_LINK_INIT(forward, link);
16539 forward->magic = FORWARD_MAGIC;
16540 forward->options = DNS_REQUESTOPT_TCP;
16541 /*
16542 * If we have a SIG(0) signed message we need to preserve the
16543 * query id as that is included in the SIG(0) computation.
16544 */
16545 if (msg->sig0 != NULL)
16546 forward->options |= DNS_REQUESTOPT_FIXEDID;
16547
16548 mr = dns_message_getrawmessage(msg);
16549 if (mr == NULL) {
16550 result = ISC_R_UNEXPECTEDEND;
16551 goto cleanup;
16552 }
16553
16554 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
16555 if (result != ISC_R_SUCCESS)
16556 goto cleanup;
16557 result = isc_buffer_copyregion(forward->msgbuf, mr);
16558 if (result != ISC_R_SUCCESS)
16559 goto cleanup;
16560
16561 isc_mem_attach(zone->mctx, &forward->mctx);
16562 dns_zone_iattach(zone, &forward->zone);
16563 result = sendtomaster(forward);
16564
16565 cleanup:
16566 if (result != ISC_R_SUCCESS) {
16567 forward_destroy(forward);
16568 }
16569 return (result);
16570 }
16571
16572 isc_result_t
16573 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
16574 REQUIRE(DNS_ZONE_VALID(zone));
16575 REQUIRE(next != NULL && *next == NULL);
16576
16577 *next = ISC_LIST_NEXT(zone, link);
16578 if (*next == NULL)
16579 return (ISC_R_NOMORE);
16580 else
16581 return (ISC_R_SUCCESS);
16582 }
16583
16584 isc_result_t
16585 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
16586 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16587 REQUIRE(first != NULL && *first == NULL);
16588
16589 *first = ISC_LIST_HEAD(zmgr->zones);
16590 if (*first == NULL)
16591 return (ISC_R_NOMORE);
16592 else
16593 return (ISC_R_SUCCESS);
16594 }
16595
16596 /***
16597 *** Zone manager.
16598 ***/
16599
16600 isc_result_t
16601 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
16602 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
16603 dns_zonemgr_t **zmgrp)
16604 {
16605 dns_zonemgr_t *zmgr;
16606 isc_result_t result;
16607
16608 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
16609 if (zmgr == NULL)
16610 return (ISC_R_NOMEMORY);
16611 zmgr->mctx = NULL;
16612 zmgr->refs = 1;
16613 isc_mem_attach(mctx, &zmgr->mctx);
16614 zmgr->taskmgr = taskmgr;
16615 zmgr->timermgr = timermgr;
16616 zmgr->socketmgr = socketmgr;
16617 zmgr->zonetasks = NULL;
16618 zmgr->loadtasks = NULL;
16619 zmgr->mctxpool = NULL;
16620 zmgr->task = NULL;
16621 zmgr->notifyrl = NULL;
16622 zmgr->refreshrl = NULL;
16623 zmgr->startupnotifyrl = NULL;
16624 zmgr->startuprefreshrl = NULL;
16625 ISC_LIST_INIT(zmgr->zones);
16626 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
16627 ISC_LIST_INIT(zmgr->xfrin_in_progress);
16628 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
16629 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
16630 if (result != ISC_R_SUCCESS)
16631 goto free_mem;
16632
16633 zmgr->transfersin = 10;
16634 zmgr->transfersperns = 2;
16635
16636 /* Unreachable lock. */
16637 result = isc_rwlock_init(&zmgr->urlock, 0, 0);
16638 if (result != ISC_R_SUCCESS)
16639 goto free_rwlock;
16640
16641 /* Create a single task for queueing of SOA queries. */
16642 result = isc_task_create(taskmgr, 1, &zmgr->task);
16643 if (result != ISC_R_SUCCESS)
16644 goto free_urlock;
16645
16646 isc_task_setname(zmgr->task, "zmgr", zmgr);
16647 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16648 &zmgr->notifyrl);
16649 if (result != ISC_R_SUCCESS)
16650 goto free_task;
16651
16652 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16653 &zmgr->refreshrl);
16654 if (result != ISC_R_SUCCESS)
16655 goto free_notifyrl;
16656
16657 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16658 &zmgr->startupnotifyrl);
16659 if (result != ISC_R_SUCCESS)
16660 goto free_refreshrl;
16661
16662 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16663 &zmgr->startuprefreshrl);
16664 if (result != ISC_R_SUCCESS)
16665 goto free_startupnotifyrl;
16666
16667 /* default to 20 refresh queries / notifies per second. */
16668 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
16669 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
16670 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
16671 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
16672 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, true);
16673 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, true);
16674
16675 zmgr->iolimit = 1;
16676 zmgr->ioactive = 0;
16677 ISC_LIST_INIT(zmgr->high);
16678 ISC_LIST_INIT(zmgr->low);
16679
16680 isc_mutex_init(&zmgr->iolock);
16681
16682 zmgr->magic = ZONEMGR_MAGIC;
16683
16684 *zmgrp = zmgr;
16685 return (ISC_R_SUCCESS);
16686
16687 #if 0
16688 free_iolock:
16689 isc_mutex_destroy(&zmgr->iolock);
16690 #endif
16691 free_startupnotifyrl:
16692 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
16693 free_refreshrl:
16694 isc_ratelimiter_detach(&zmgr->refreshrl);
16695 free_notifyrl:
16696 isc_ratelimiter_detach(&zmgr->notifyrl);
16697 free_task:
16698 isc_task_detach(&zmgr->task);
16699 free_urlock:
16700 isc_rwlock_destroy(&zmgr->urlock);
16701 free_rwlock:
16702 isc_rwlock_destroy(&zmgr->rwlock);
16703 free_mem:
16704 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
16705 isc_mem_detach(&mctx);
16706 return (result);
16707 }
16708
16709 isc_result_t
16710 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
16711 isc_result_t result;
16712 isc_mem_t *mctx = NULL;
16713 dns_zone_t *zone = NULL;
16714 void *item;
16715
16716 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16717 REQUIRE(zonep != NULL && *zonep == NULL);
16718
16719 if (zmgr->mctxpool == NULL)
16720 return (ISC_R_FAILURE);
16721
16722 item = isc_pool_get(zmgr->mctxpool);
16723 if (item == NULL)
16724 return (ISC_R_FAILURE);
16725
16726 isc_mem_attach((isc_mem_t *) item, &mctx);
16727 result = dns_zone_create(&zone, mctx);
16728 isc_mem_detach(&mctx);
16729
16730 if (result == ISC_R_SUCCESS)
16731 *zonep = zone;
16732
16733 return (result);
16734 }
16735
16736 isc_result_t
16737 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16738 isc_result_t result;
16739
16740 REQUIRE(DNS_ZONE_VALID(zone));
16741 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16742
16743 if (zmgr->zonetasks == NULL)
16744 return (ISC_R_FAILURE);
16745
16746 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16747 LOCK_ZONE(zone);
16748 REQUIRE(zone->task == NULL);
16749 REQUIRE(zone->timer == NULL);
16750 REQUIRE(zone->zmgr == NULL);
16751
16752 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
16753 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
16754
16755 /*
16756 * Set the task name. The tag will arbitrarily point to one
16757 * of the zones sharing the task (in practice, the one
16758 * to be managed last).
16759 */
16760 isc_task_setname(zone->task, "zone", zone);
16761 isc_task_setname(zone->loadtask, "loadzone", zone);
16762
16763 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16764 NULL, NULL,
16765 zone->task, zone_timer, zone,
16766 &zone->timer);
16767
16768 if (result != ISC_R_SUCCESS)
16769 goto cleanup_tasks;
16770
16771 /*
16772 * The timer "holds" a iref.
16773 */
16774 zone->irefs++;
16775 INSIST(zone->irefs != 0);
16776
16777 ISC_LIST_APPEND(zmgr->zones, zone, link);
16778 zone->zmgr = zmgr;
16779 zmgr->refs++;
16780
16781 goto unlock;
16782
16783 cleanup_tasks:
16784 isc_task_detach(&zone->loadtask);
16785 isc_task_detach(&zone->task);
16786
16787 unlock:
16788 UNLOCK_ZONE(zone);
16789 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16790 return (result);
16791 }
16792
16793 void
16794 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16795 bool free_now = false;
16796
16797 REQUIRE(DNS_ZONE_VALID(zone));
16798 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16799 REQUIRE(zone->zmgr == zmgr);
16800
16801 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16802 LOCK_ZONE(zone);
16803
16804 ISC_LIST_UNLINK(zmgr->zones, zone, link);
16805 zone->zmgr = NULL;
16806 zmgr->refs--;
16807 if (zmgr->refs == 0)
16808 free_now = true;
16809
16810 UNLOCK_ZONE(zone);
16811 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16812
16813 if (free_now)
16814 zonemgr_free(zmgr);
16815 ENSURE(zone->zmgr == NULL);
16816 }
16817
16818 void
16819 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
16820 REQUIRE(DNS_ZONEMGR_VALID(source));
16821 REQUIRE(target != NULL && *target == NULL);
16822
16823 RWLOCK(&source->rwlock, isc_rwlocktype_write);
16824 REQUIRE(source->refs > 0);
16825 source->refs++;
16826 INSIST(source->refs > 0);
16827 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
16828 *target = source;
16829 }
16830
16831 void
16832 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
16833 dns_zonemgr_t *zmgr;
16834 bool free_now = false;
16835
16836 REQUIRE(zmgrp != NULL);
16837 zmgr = *zmgrp;
16838 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16839
16840 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16841 zmgr->refs--;
16842 if (zmgr->refs == 0)
16843 free_now = true;
16844 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16845
16846 if (free_now)
16847 zonemgr_free(zmgr);
16848 *zmgrp = NULL;
16849 }
16850
16851 isc_result_t
16852 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
16853 dns_zone_t *p;
16854
16855 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16856
16857 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16858 for (p = ISC_LIST_HEAD(zmgr->zones);
16859 p != NULL;
16860 p = ISC_LIST_NEXT(p, link))
16861 {
16862 dns_zone_maintenance(p);
16863 }
16864 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16865
16866 /*
16867 * Recent configuration changes may have increased the
16868 * amount of available transfers quota. Make sure any
16869 * transfers currently blocked on quota get started if
16870 * possible.
16871 */
16872 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16873 zmgr_resume_xfrs(zmgr, true);
16874 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16875 return (ISC_R_SUCCESS);
16876 }
16877
16878 void
16879 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
16880
16881 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16882
16883 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16884 zmgr_resume_xfrs(zmgr, true);
16885 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16886 }
16887
16888 void
16889 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
16890 dns_zone_t *zone;
16891
16892 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16893
16894 isc_ratelimiter_shutdown(zmgr->notifyrl);
16895 isc_ratelimiter_shutdown(zmgr->refreshrl);
16896 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
16897 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
16898
16899 if (zmgr->task != NULL)
16900 isc_task_destroy(&zmgr->task);
16901 if (zmgr->zonetasks != NULL)
16902 isc_taskpool_destroy(&zmgr->zonetasks);
16903 if (zmgr->loadtasks != NULL)
16904 isc_taskpool_destroy(&zmgr->loadtasks);
16905 if (zmgr->mctxpool != NULL)
16906 isc_pool_destroy(&zmgr->mctxpool);
16907
16908 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16909 for (zone = ISC_LIST_HEAD(zmgr->zones);
16910 zone != NULL;
16911 zone = ISC_LIST_NEXT(zone, link))
16912 {
16913 LOCK_ZONE(zone);
16914 forward_cancel(zone);
16915 UNLOCK_ZONE(zone);
16916 }
16917 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16918 }
16919
16920 static isc_result_t
16921 mctxinit(void **target, void *arg) {
16922 isc_result_t result;
16923 isc_mem_t *mctx = NULL;
16924
16925 UNUSED(arg);
16926
16927 REQUIRE(target != NULL && *target == NULL);
16928
16929 result = isc_mem_create(0, 0, &mctx);
16930 if (result != ISC_R_SUCCESS)
16931 return (result);
16932 isc_mem_setname(mctx, "zonemgr-pool", NULL);
16933
16934 *target = mctx;
16935 return (ISC_R_SUCCESS);
16936 }
16937
16938 static void
16939 mctxfree(void **target) {
16940 isc_mem_t *mctx = *(isc_mem_t **) target;
16941 isc_mem_detach(&mctx);
16942 *target = NULL;
16943 }
16944
16945 #define ZONES_PER_TASK 100
16946 #define ZONES_PER_MCTX 1000
16947
16948 isc_result_t
16949 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
16950 isc_result_t result;
16951 int ntasks = num_zones / ZONES_PER_TASK;
16952 int nmctx = num_zones / ZONES_PER_MCTX;
16953 isc_taskpool_t *pool = NULL;
16954 isc_pool_t *mctxpool = NULL;
16955
16956 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16957
16958 /*
16959 * For anything fewer than 1000 zones we use 10 tasks in
16960 * the task pools. More than that, and we'll scale at one
16961 * task per 100 zones. Similarly, for anything smaller than
16962 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
16963 */
16964 if (ntasks < 10)
16965 ntasks = 10;
16966 if (nmctx < 2)
16967 nmctx = 2;
16968
16969 /* Create or resize the zone task pools. */
16970 if (zmgr->zonetasks == NULL)
16971 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16972 ntasks, 2, &pool);
16973 else
16974 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
16975
16976 if (result == ISC_R_SUCCESS)
16977 zmgr->zonetasks = pool;
16978
16979 pool = NULL;
16980 if (zmgr->loadtasks == NULL)
16981 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16982 ntasks, 2, &pool);
16983 else
16984 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
16985
16986 if (result == ISC_R_SUCCESS)
16987 zmgr->loadtasks = pool;
16988
16989 /*
16990 * We always set all tasks in the zone-load task pool to
16991 * privileged. This prevents other tasks in the system from
16992 * running while the server task manager is in privileged
16993 * mode.
16994 *
16995 * NOTE: If we start using task privileges for any other
16996 * part of the system than zone tasks, then this will need to be
16997 * revisted. In that case we'd want to turn on privileges for
16998 * zone tasks only when we were loading, and turn them off the
16999 * rest of the time. For now, however, it's okay to just
17000 * set it and forget it.
17001 */
17002 isc_taskpool_setprivilege(zmgr->loadtasks, true);
17003
17004 /* Create or resize the zone memory context pool. */
17005 if (zmgr->mctxpool == NULL)
17006 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
17007 mctxinit, NULL, &mctxpool);
17008 else
17009 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
17010
17011 if (result == ISC_R_SUCCESS)
17012 zmgr->mctxpool = mctxpool;
17013
17014 return (result);
17015 }
17016
17017 static void
17018 zonemgr_free(dns_zonemgr_t *zmgr) {
17019 isc_mem_t *mctx;
17020
17021 INSIST(zmgr->refs == 0);
17022 INSIST(ISC_LIST_EMPTY(zmgr->zones));
17023
17024 zmgr->magic = 0;
17025
17026 isc_mutex_destroy(&zmgr->iolock);
17027 isc_ratelimiter_detach(&zmgr->notifyrl);
17028 isc_ratelimiter_detach(&zmgr->refreshrl);
17029 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
17030 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
17031
17032 isc_rwlock_destroy(&zmgr->urlock);
17033 isc_rwlock_destroy(&zmgr->rwlock);
17034 mctx = zmgr->mctx;
17035 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
17036 isc_mem_detach(&mctx);
17037 }
17038
17039 void
17040 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, uint32_t value) {
17041 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17042
17043 zmgr->transfersin = value;
17044 }
17045
17046 uint32_t
17047 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
17048 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17049
17050 return (zmgr->transfersin);
17051 }
17052
17053 void
17054 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, uint32_t value) {
17055 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17056
17057 zmgr->transfersperns = value;
17058 }
17059
17060 uint32_t
17061 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
17062 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17063
17064 return (zmgr->transfersperns);
17065 }
17066
17067 /*
17068 * Try to start a new incoming zone transfer to fill a quota
17069 * slot that was just vacated.
17070 *
17071 * Requires:
17072 * The zone manager is locked by the caller.
17073 */
17074 static void
17075 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, bool multi) {
17076 dns_zone_t *zone;
17077 dns_zone_t *next;
17078
17079 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
17080 zone != NULL;
17081 zone = next)
17082 {
17083 isc_result_t result;
17084 next = ISC_LIST_NEXT(zone, statelink);
17085 result = zmgr_start_xfrin_ifquota(zmgr, zone);
17086 if (result == ISC_R_SUCCESS) {
17087 if (multi)
17088 continue;
17089 /*
17090 * We successfully filled the slot. We're done.
17091 */
17092 break;
17093 } else if (result == ISC_R_QUOTA) {
17094 /*
17095 * Not enough quota. This is probably the per-server
17096 * quota, because we usually get called when a unit of
17097 * global quota has just been freed. Try the next
17098 * zone, it may succeed if it uses another master.
17099 */
17100 continue;
17101 } else {
17102 dns_zone_log(zone, ISC_LOG_DEBUG(1),
17103 "starting zone transfer: %s",
17104 isc_result_totext(result));
17105 break;
17106 }
17107 }
17108 }
17109
17110 /*
17111 * Try to start an incoming zone transfer for 'zone', quota permitting.
17112 *
17113 * Requires:
17114 * The zone manager is locked by the caller.
17115 *
17116 * Returns:
17117 * ISC_R_SUCCESS There was enough quota and we attempted to
17118 * start a transfer. zone_xfrdone() has been or will
17119 * be called.
17120 * ISC_R_QUOTA Not enough quota.
17121 * Others Failure.
17122 */
17123 static isc_result_t
17124 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
17125 dns_peer_t *peer = NULL;
17126 isc_netaddr_t masterip;
17127 uint32_t nxfrsin, nxfrsperns;
17128 dns_zone_t *x;
17129 uint32_t maxtransfersin, maxtransfersperns;
17130 isc_event_t *e;
17131
17132 /*
17133 * If we are exiting just pretend we got quota so the zone will
17134 * be cleaned up in the zone's task context.
17135 */
17136 LOCK_ZONE(zone);
17137 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
17138 UNLOCK_ZONE(zone);
17139 goto gotquota;
17140 }
17141
17142 /*
17143 * Find any configured information about the server we'd
17144 * like to transfer this zone from.
17145 */
17146 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
17147 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
17148 UNLOCK_ZONE(zone);
17149
17150 /*
17151 * Determine the total maximum number of simultaneous
17152 * transfers allowed, and the maximum for this specific
17153 * master.
17154 */
17155 maxtransfersin = zmgr->transfersin;
17156 maxtransfersperns = zmgr->transfersperns;
17157 if (peer != NULL)
17158 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
17159
17160 /*
17161 * Count the total number of transfers that are in progress,
17162 * and the number of transfers in progress from this master.
17163 * We linearly scan a list of all transfers; if this turns
17164 * out to be too slow, we could hash on the master address.
17165 */
17166 nxfrsin = nxfrsperns = 0;
17167 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
17168 x != NULL;
17169 x = ISC_LIST_NEXT(x, statelink))
17170 {
17171 isc_netaddr_t xip;
17172
17173 LOCK_ZONE(x);
17174 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
17175 UNLOCK_ZONE(x);
17176
17177 nxfrsin++;
17178 if (isc_netaddr_equal(&xip, &masterip))
17179 nxfrsperns++;
17180 }
17181
17182 /* Enforce quota. */
17183 if (nxfrsin >= maxtransfersin)
17184 return (ISC_R_QUOTA);
17185
17186 if (nxfrsperns >= maxtransfersperns)
17187 return (ISC_R_QUOTA);
17188
17189 gotquota:
17190 /*
17191 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
17192 * list and send it an event to let it start the actual transfer in the
17193 * context of its own task.
17194 */
17195 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
17196 got_transfer_quota, zone, sizeof(isc_event_t));
17197 if (e == NULL)
17198 return (ISC_R_NOMEMORY);
17199
17200 LOCK_ZONE(zone);
17201 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
17202 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
17203 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
17204 zone->statelist = &zmgr->xfrin_in_progress;
17205 isc_task_send(zone->task, &e);
17206 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
17207 UNLOCK_ZONE(zone);
17208
17209 return (ISC_R_SUCCESS);
17210 }
17211
17212 void
17213 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, uint32_t iolimit) {
17214
17215 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17216 REQUIRE(iolimit > 0);
17217
17218 zmgr->iolimit = iolimit;
17219 }
17220
17221 uint32_t
17222 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
17223
17224 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17225
17226 return (zmgr->iolimit);
17227 }
17228
17229 /*
17230 * Get permission to request a file handle from the OS.
17231 * An event will be sent to action when one is available.
17232 * There are two queues available (high and low), the high
17233 * queue will be serviced before the low one.
17234 *
17235 * zonemgr_putio() must be called after the event is delivered to
17236 * 'action'.
17237 */
17238
17239 static isc_result_t
17240 zonemgr_getio(dns_zonemgr_t *zmgr, bool high,
17241 isc_task_t *task, isc_taskaction_t action, void *arg,
17242 dns_io_t **iop)
17243 {
17244 dns_io_t *io;
17245 bool queue;
17246
17247 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17248 REQUIRE(iop != NULL && *iop == NULL);
17249
17250 io = isc_mem_get(zmgr->mctx, sizeof(*io));
17251 if (io == NULL)
17252 return (ISC_R_NOMEMORY);
17253
17254 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
17255 action, arg, sizeof(*io->event));
17256 if (io->event == NULL) {
17257 isc_mem_put(zmgr->mctx, io, sizeof(*io));
17258 return (ISC_R_NOMEMORY);
17259 }
17260
17261 io->zmgr = zmgr;
17262 io->high = high;
17263 io->task = NULL;
17264 isc_task_attach(task, &io->task);
17265 ISC_LINK_INIT(io, link);
17266 io->magic = IO_MAGIC;
17267
17268 LOCK(&zmgr->iolock);
17269 zmgr->ioactive++;
17270 queue = (zmgr->ioactive > zmgr->iolimit);
17271 if (queue) {
17272 if (io->high)
17273 ISC_LIST_APPEND(zmgr->high, io, link);
17274 else
17275 ISC_LIST_APPEND(zmgr->low, io, link);
17276 }
17277 UNLOCK(&zmgr->iolock);
17278 *iop = io;
17279
17280 if (!queue)
17281 isc_task_send(io->task, &io->event);
17282 return (ISC_R_SUCCESS);
17283 }
17284
17285 static void
17286 zonemgr_putio(dns_io_t **iop) {
17287 dns_io_t *io;
17288 dns_io_t *next;
17289 dns_zonemgr_t *zmgr;
17290
17291 REQUIRE(iop != NULL);
17292 io = *iop;
17293 REQUIRE(DNS_IO_VALID(io));
17294
17295 *iop = NULL;
17296
17297 INSIST(!ISC_LINK_LINKED(io, link));
17298 INSIST(io->event == NULL);
17299
17300 zmgr = io->zmgr;
17301 isc_task_detach(&io->task);
17302 io->magic = 0;
17303 isc_mem_put(zmgr->mctx, io, sizeof(*io));
17304
17305 LOCK(&zmgr->iolock);
17306 INSIST(zmgr->ioactive > 0);
17307 zmgr->ioactive--;
17308 next = HEAD(zmgr->high);
17309 if (next == NULL)
17310 next = HEAD(zmgr->low);
17311 if (next != NULL) {
17312 if (next->high)
17313 ISC_LIST_UNLINK(zmgr->high, next, link);
17314 else
17315 ISC_LIST_UNLINK(zmgr->low, next, link);
17316 INSIST(next->event != NULL);
17317 }
17318 UNLOCK(&zmgr->iolock);
17319 if (next != NULL)
17320 isc_task_send(next->task, &next->event);
17321 }
17322
17323 static void
17324 zonemgr_cancelio(dns_io_t *io) {
17325 bool send_event = false;
17326
17327 REQUIRE(DNS_IO_VALID(io));
17328
17329 /*
17330 * If we are queued to be run then dequeue.
17331 */
17332 LOCK(&io->zmgr->iolock);
17333 if (ISC_LINK_LINKED(io, link)) {
17334 if (io->high)
17335 ISC_LIST_UNLINK(io->zmgr->high, io, link);
17336 else
17337 ISC_LIST_UNLINK(io->zmgr->low, io, link);
17338
17339 send_event = true;
17340 INSIST(io->event != NULL);
17341 }
17342 UNLOCK(&io->zmgr->iolock);
17343 if (send_event) {
17344 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
17345 isc_task_send(io->task, &io->event);
17346 }
17347 }
17348
17349 static void
17350 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
17351 char *buf;
17352 int buflen;
17353 isc_result_t result;
17354
17355 buflen = strlen(path) + strlen(templat) + 2;
17356
17357 buf = isc_mem_get(zone->mctx, buflen);
17358 if (buf == NULL)
17359 return;
17360
17361 result = isc_file_template(path, templat, buf, buflen);
17362 if (result != ISC_R_SUCCESS)
17363 goto cleanup;
17364
17365 result = isc_file_renameunique(path, buf);
17366 if (result != ISC_R_SUCCESS)
17367 goto cleanup;
17368
17369 dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
17370 "renaming file to '%s' for failure analysis and "
17371 "retransferring.", path, buf);
17372
17373 cleanup:
17374 isc_mem_put(zone->mctx, buf, buflen);
17375 }
17376
17377 static void
17378 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
17379 isc_interval_t interval;
17380 uint32_t s, ns;
17381 uint32_t pertic;
17382 isc_result_t result;
17383
17384 if (value == 0)
17385 value = 1;
17386
17387 if (value == 1) {
17388 s = 1;
17389 ns = 0;
17390 pertic = 1;
17391 } else if (value <= 10) {
17392 s = 0;
17393 ns = 1000000000 / value;
17394 pertic = 1;
17395 } else {
17396 s = 0;
17397 ns = (1000000000 / value) * 10;
17398 pertic = 10;
17399 }
17400
17401 isc_interval_set(&interval, s, ns);
17402
17403 result = isc_ratelimiter_setinterval(rl, &interval);
17404 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17405 isc_ratelimiter_setpertic(rl, pertic);
17406
17407 *rate = value;
17408 }
17409
17410 void
17411 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
17412
17413 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17414
17415 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
17416 }
17417
17418 void
17419 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
17420
17421 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17422
17423 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
17424 }
17425
17426 void
17427 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
17428
17429 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17430
17431 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
17432 /* XXXMPA seperate out once we have the code to support this. */
17433 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
17434 }
17435
17436 unsigned int
17437 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
17438 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17439
17440 return (zmgr->notifyrate);
17441 }
17442
17443 unsigned int
17444 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
17445 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17446
17447 return (zmgr->startupnotifyrate);
17448 }
17449
17450 unsigned int
17451 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
17452 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17453
17454 return (zmgr->serialqueryrate);
17455 }
17456
17457 bool
17458 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17459 isc_sockaddr_t *local, isc_time_t *now)
17460 {
17461 unsigned int i;
17462 isc_rwlocktype_t locktype;
17463 isc_result_t result;
17464 uint32_t seconds = isc_time_seconds(now);
17465 uint32_t count = 0;
17466
17467 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17468
17469 locktype = isc_rwlocktype_read;
17470 RWLOCK(&zmgr->urlock, locktype);
17471 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17472 if (zmgr->unreachable[i].expire >= seconds &&
17473 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17474 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
17475 result = isc_rwlock_tryupgrade(&zmgr->urlock);
17476 if (result == ISC_R_SUCCESS) {
17477 locktype = isc_rwlocktype_write;
17478 zmgr->unreachable[i].last = seconds;
17479 count = zmgr->unreachable[i].count;
17480 }
17481 break;
17482 }
17483 }
17484 RWUNLOCK(&zmgr->urlock, locktype);
17485 return (i < UNREACH_CHACHE_SIZE && count > 1U);
17486 }
17487
17488 void
17489 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17490 isc_sockaddr_t *local)
17491 {
17492 unsigned int i;
17493 isc_rwlocktype_t locktype;
17494 isc_result_t result;
17495
17496 char master[ISC_SOCKADDR_FORMATSIZE];
17497 char source[ISC_SOCKADDR_FORMATSIZE];
17498
17499 isc_sockaddr_format(remote, master, sizeof(master));
17500 isc_sockaddr_format(local, source, sizeof(source));
17501
17502 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17503
17504 locktype = isc_rwlocktype_read;
17505 RWLOCK(&zmgr->urlock, locktype);
17506 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17507 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17508 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
17509 if (zmgr->unreachable[i].expire == 0)
17510 break;
17511 result = isc_rwlock_tryupgrade(&zmgr->urlock);
17512 if (result == ISC_R_SUCCESS) {
17513 locktype = isc_rwlocktype_write;
17514 zmgr->unreachable[i].expire = 0;
17515 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
17516 DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
17517 "master %s (source %s) deleted "
17518 "from unreachable cache",
17519 master, source);
17520 }
17521 break;
17522 }
17523 }
17524 RWUNLOCK(&zmgr->urlock, locktype);
17525 }
17526
17527 void
17528 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
17529 isc_sockaddr_t *local, isc_time_t *now)
17530 {
17531 uint32_t seconds = isc_time_seconds(now);
17532 uint32_t last = seconds;
17533 unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
17534
17535 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17536
17537 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
17538 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17539 /* Existing entry? */
17540 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17541 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
17542 break;
17543 /* Empty slot? */
17544 if (zmgr->unreachable[i].expire < seconds)
17545 slot = i;
17546 /* Least recently used slot? */
17547 if (zmgr->unreachable[i].last < last) {
17548 last = zmgr->unreachable[i].last;
17549 oldest = i;
17550 }
17551 }
17552 if (i < UNREACH_CHACHE_SIZE) {
17553 /*
17554 * Found a existing entry. Update the expire timer and
17555 * last usage timestamps.
17556 */
17557 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
17558 zmgr->unreachable[i].last = seconds;
17559 if (zmgr->unreachable[i].expire < seconds)
17560 zmgr->unreachable[i].count = 1;
17561 else
17562 zmgr->unreachable[i].count++;
17563 } else if (slot != UNREACH_CHACHE_SIZE) {
17564 /*
17565 * Found a empty slot. Add a new entry to the cache.
17566 */
17567 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
17568 zmgr->unreachable[slot].last = seconds;
17569 zmgr->unreachable[slot].remote = *remote;
17570 zmgr->unreachable[slot].local = *local;
17571 zmgr->unreachable[slot].count = 1;
17572 } else {
17573 /*
17574 * Replace the least recently used entry in the cache.
17575 */
17576 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
17577 zmgr->unreachable[oldest].last = seconds;
17578 zmgr->unreachable[oldest].remote = *remote;
17579 zmgr->unreachable[oldest].local = *local;
17580 zmgr->unreachable[oldest].count = 1;
17581 }
17582 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
17583 }
17584
17585 void
17586 dns_zone_forcereload(dns_zone_t *zone) {
17587 REQUIRE(DNS_ZONE_VALID(zone));
17588
17589 if (zone->type == dns_zone_master ||
17590 (zone->type == dns_zone_redirect && zone->masters == NULL))
17591 return;
17592
17593 LOCK_ZONE(zone);
17594 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17595 UNLOCK_ZONE(zone);
17596 dns_zone_refresh(zone);
17597 }
17598
17599 bool
17600 dns_zone_isforced(dns_zone_t *zone) {
17601 REQUIRE(DNS_ZONE_VALID(zone));
17602
17603 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
17604 }
17605
17606 isc_result_t
17607 dns_zone_setstatistics(dns_zone_t *zone, bool on) {
17608 /*
17609 * This function is obsoleted.
17610 */
17611 UNUSED(zone);
17612 UNUSED(on);
17613 return (ISC_R_NOTIMPLEMENTED);
17614 }
17615
17616 uint64_t *
17617 dns_zone_getstatscounters(dns_zone_t *zone) {
17618 /*
17619 * This function is obsoleted.
17620 */
17621 UNUSED(zone);
17622 return (NULL);
17623 }
17624
17625 void
17626 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
17627 REQUIRE(DNS_ZONE_VALID(zone));
17628 REQUIRE(zone->stats == NULL);
17629
17630 LOCK_ZONE(zone);
17631 zone->stats = NULL;
17632 isc_stats_attach(stats, &zone->stats);
17633 UNLOCK_ZONE(zone);
17634 }
17635
17636 void
17637 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
17638
17639 REQUIRE(DNS_ZONE_VALID(zone));
17640
17641 LOCK_ZONE(zone);
17642 if (zone->requeststats_on && stats == NULL)
17643 zone->requeststats_on = false;
17644 else if (!zone->requeststats_on && stats != NULL) {
17645 if (zone->requeststats == NULL) {
17646 isc_stats_attach(stats, &zone->requeststats);
17647 zone->requeststats_on = true;
17648 }
17649 }
17650 UNLOCK_ZONE(zone);
17651 }
17652
17653 void
17654 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
17655
17656 REQUIRE(DNS_ZONE_VALID(zone));
17657
17658 LOCK_ZONE(zone);
17659 if (zone->requeststats_on && stats != NULL) {
17660 if (zone->rcvquerystats == NULL) {
17661 dns_stats_attach(stats, &zone->rcvquerystats);
17662 zone->requeststats_on = true;
17663 }
17664 }
17665 UNLOCK_ZONE(zone);
17666 }
17667
17668 void
17669 dns_zone_setdnssecsignstats(dns_zone_t *zone, dns_stats_t *stats) {
17670 REQUIRE(DNS_ZONE_VALID(zone));
17671
17672 LOCK_ZONE(zone);
17673 if (stats != NULL && zone->dnssecsignstats == NULL) {
17674 dns_stats_attach(stats, &zone->dnssecsignstats);
17675 }
17676 UNLOCK_ZONE(zone);
17677 }
17678
17679 void
17680 dns_zone_setdnssecrefreshstats(dns_zone_t *zone, dns_stats_t *stats) {
17681 REQUIRE(DNS_ZONE_VALID(zone));
17682
17683 LOCK_ZONE(zone);
17684 if (stats != NULL && zone->dnssecrefreshstats == NULL) {
17685 dns_stats_attach(stats, &zone->dnssecrefreshstats);
17686 }
17687 UNLOCK_ZONE(zone);
17688 }
17689
17690 dns_stats_t*
17691 dns_zone_getdnssecsignstats(dns_zone_t *zone) {
17692 REQUIRE(DNS_ZONE_VALID(zone));
17693
17694 return (zone->dnssecsignstats);
17695 }
17696
17697 dns_stats_t*
17698 dns_zone_getdnssecrefreshstats(dns_zone_t *zone) {
17699 REQUIRE(DNS_ZONE_VALID(zone));
17700
17701 return (zone->dnssecrefreshstats);
17702 }
17703
17704 isc_stats_t *
17705 dns_zone_getrequeststats(dns_zone_t *zone) {
17706 /*
17707 * We don't lock zone for efficiency reason. This is not catastrophic
17708 * because requeststats must always be valid when requeststats_on is
17709 * true.
17710 * Some counters may be incremented while requeststats_on is becoming
17711 * false, or some cannot be incremented just after the statistics are
17712 * installed, but it shouldn't matter much in practice.
17713 */
17714 if (zone->requeststats_on)
17715 return (zone->requeststats);
17716 else
17717 return (NULL);
17718 }
17719
17720 /*
17721 * Return the received query stats bucket
17722 * see note from dns_zone_getrequeststats()
17723 */
17724 dns_stats_t *
17725 dns_zone_getrcvquerystats(dns_zone_t *zone) {
17726 if (zone->requeststats_on)
17727 return (zone->rcvquerystats);
17728 else
17729 return (NULL);
17730 }
17731
17732 void
17733 dns_zone_dialup(dns_zone_t *zone) {
17734
17735 REQUIRE(DNS_ZONE_VALID(zone));
17736
17737 zone_debuglog(zone, "dns_zone_dialup", 3,
17738 "notify = %d, refresh = %d",
17739 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
17740 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
17741
17742 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
17743 dns_zone_notify(zone);
17744 if (zone->type != dns_zone_master && zone->masters != NULL &&
17745 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
17746 dns_zone_refresh(zone);
17747 }
17748
17749 void
17750 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
17751 REQUIRE(DNS_ZONE_VALID(zone));
17752
17753 LOCK_ZONE(zone);
17754 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
17755 DNS_ZONEFLG_DIALREFRESH |
17756 DNS_ZONEFLG_NOREFRESH);
17757 switch (dialup) {
17758 case dns_dialuptype_no:
17759 break;
17760 case dns_dialuptype_yes:
17761 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
17762 DNS_ZONEFLG_DIALREFRESH |
17763 DNS_ZONEFLG_NOREFRESH));
17764 break;
17765 case dns_dialuptype_notify:
17766 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17767 break;
17768 case dns_dialuptype_notifypassive:
17769 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17770 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17771 break;
17772 case dns_dialuptype_refresh:
17773 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
17774 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17775 break;
17776 case dns_dialuptype_passive:
17777 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17778 break;
17779 default:
17780 INSIST(0);
17781 ISC_UNREACHABLE();
17782 }
17783 UNLOCK_ZONE(zone);
17784 }
17785
17786 isc_result_t
17787 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
17788 isc_result_t result = ISC_R_SUCCESS;
17789
17790 REQUIRE(DNS_ZONE_VALID(zone));
17791
17792 LOCK_ZONE(zone);
17793 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
17794 UNLOCK_ZONE(zone);
17795
17796 return (result);
17797 }
17798
17799 const char *
17800 dns_zone_getkeydirectory(dns_zone_t *zone) {
17801 REQUIRE(DNS_ZONE_VALID(zone));
17802
17803 return (zone->keydirectory);
17804 }
17805
17806 unsigned int
17807 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
17808 dns_zone_t *zone;
17809 unsigned int count = 0;
17810
17811 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17812
17813 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17814 switch (state) {
17815 case DNS_ZONESTATE_XFERRUNNING:
17816 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
17817 zone != NULL;
17818 zone = ISC_LIST_NEXT(zone, statelink))
17819 count++;
17820 break;
17821 case DNS_ZONESTATE_XFERDEFERRED:
17822 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
17823 zone != NULL;
17824 zone = ISC_LIST_NEXT(zone, statelink))
17825 count++;
17826 break;
17827 case DNS_ZONESTATE_SOAQUERY:
17828 for (zone = ISC_LIST_HEAD(zmgr->zones);
17829 zone != NULL;
17830 zone = ISC_LIST_NEXT(zone, link))
17831 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
17832 count++;
17833 break;
17834 case DNS_ZONESTATE_ANY:
17835 for (zone = ISC_LIST_HEAD(zmgr->zones);
17836 zone != NULL;
17837 zone = ISC_LIST_NEXT(zone, link)) {
17838 dns_view_t *view = zone->view;
17839 if (view != NULL && strcmp(view->name, "_bind") == 0)
17840 continue;
17841 count++;
17842 }
17843 break;
17844 case DNS_ZONESTATE_AUTOMATIC:
17845 for (zone = ISC_LIST_HEAD(zmgr->zones);
17846 zone != NULL;
17847 zone = ISC_LIST_NEXT(zone, link)) {
17848 dns_view_t *view = zone->view;
17849 if (view != NULL && strcmp(view->name, "_bind") == 0)
17850 continue;
17851 if (zone->automatic)
17852 count++;
17853 }
17854 break;
17855 default:
17856 INSIST(0);
17857 ISC_UNREACHABLE();
17858 }
17859
17860 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17861
17862 return (count);
17863 }
17864
17865 isc_result_t
17866 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
17867 dns_rdata_t *rdata)
17868 {
17869 bool ok = true;
17870 bool fail = false;
17871 char namebuf[DNS_NAME_FORMATSIZE];
17872 char namebuf2[DNS_NAME_FORMATSIZE];
17873 char typebuf[DNS_RDATATYPE_FORMATSIZE];
17874 int level = ISC_LOG_WARNING;
17875 dns_name_t bad;
17876
17877 REQUIRE(DNS_ZONE_VALID(zone));
17878
17879 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
17880 rdata->type != dns_rdatatype_nsec3)
17881 return (ISC_R_SUCCESS);
17882
17883 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
17884 rdata->type == dns_rdatatype_nsec3) {
17885 level = ISC_LOG_ERROR;
17886 fail = true;
17887 }
17888
17889 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, true);
17890 if (!ok) {
17891 dns_name_format(name, namebuf, sizeof(namebuf));
17892 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17893 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
17894 dns_result_totext(DNS_R_BADOWNERNAME));
17895 if (fail)
17896 return (DNS_R_BADOWNERNAME);
17897 }
17898
17899 dns_name_init(&bad, NULL);
17900 ok = dns_rdata_checknames(rdata, name, &bad);
17901 if (!ok) {
17902 dns_name_format(name, namebuf, sizeof(namebuf));
17903 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
17904 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17905 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
17906 namebuf2, dns_result_totext(DNS_R_BADNAME));
17907 if (fail)
17908 return (DNS_R_BADNAME);
17909 }
17910
17911 return (ISC_R_SUCCESS);
17912 }
17913
17914 void
17915 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
17916 REQUIRE(DNS_ZONE_VALID(zone));
17917 zone->checkmx = checkmx;
17918 }
17919
17920 void
17921 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
17922 REQUIRE(DNS_ZONE_VALID(zone));
17923 zone->checksrv = checksrv;
17924 }
17925
17926 void
17927 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
17928 REQUIRE(DNS_ZONE_VALID(zone));
17929 zone->checkns = checkns;
17930 }
17931
17932 void
17933 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
17934 REQUIRE(DNS_ZONE_VALID(zone));
17935
17936 LOCK_ZONE(zone);
17937 zone->isself = isself;
17938 zone->isselfarg = arg;
17939 UNLOCK_ZONE(zone);
17940 }
17941
17942 void
17943 dns_zone_setnotifydelay(dns_zone_t *zone, uint32_t delay) {
17944 REQUIRE(DNS_ZONE_VALID(zone));
17945
17946 LOCK_ZONE(zone);
17947 zone->notifydelay = delay;
17948 UNLOCK_ZONE(zone);
17949 }
17950
17951 uint32_t
17952 dns_zone_getnotifydelay(dns_zone_t *zone) {
17953 REQUIRE(DNS_ZONE_VALID(zone));
17954
17955 return (zone->notifydelay);
17956 }
17957
17958 isc_result_t
17959 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
17960 uint16_t keyid, bool deleteit)
17961 {
17962 isc_result_t result;
17963 REQUIRE(DNS_ZONE_VALID(zone));
17964
17965 dnssec_log(zone, ISC_LOG_NOTICE,
17966 "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
17967 algorithm, keyid);
17968 LOCK_ZONE(zone);
17969 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
17970 UNLOCK_ZONE(zone);
17971
17972 return (result);
17973 }
17974
17975 /*
17976 * Called when a dynamic update for an NSEC3PARAM record is received.
17977 *
17978 * If set, transform the NSEC3 salt into human-readable form so that it can be
17979 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
17980 */
17981 isc_result_t
17982 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
17983 isc_result_t result;
17984 char salt[255*2+1];
17985
17986 REQUIRE(DNS_ZONE_VALID(zone));
17987
17988 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
17989 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17990 dnssec_log(zone, ISC_LOG_NOTICE,
17991 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
17992 nsec3param->hash, nsec3param->iterations, salt);
17993 LOCK_ZONE(zone);
17994 result = zone_addnsec3chain(zone, nsec3param);
17995 UNLOCK_ZONE(zone);
17996
17997 return (result);
17998 }
17999
18000 void
18001 dns_zone_setnodes(dns_zone_t *zone, uint32_t nodes) {
18002 REQUIRE(DNS_ZONE_VALID(zone));
18003
18004 if (nodes == 0)
18005 nodes = 1;
18006 zone->nodes = nodes;
18007 }
18008
18009 void
18010 dns_zone_setsignatures(dns_zone_t *zone, uint32_t signatures) {
18011 REQUIRE(DNS_ZONE_VALID(zone));
18012
18013 /*
18014 * We treat signatures as a signed value so explicitly
18015 * limit its range here.
18016 */
18017 if (signatures > INT32_MAX)
18018 signatures = INT32_MAX;
18019 else if (signatures == 0)
18020 signatures = 1;
18021 zone->signatures = signatures;
18022 }
18023
18024 uint32_t
18025 dns_zone_getsignatures(dns_zone_t *zone) {
18026 REQUIRE(DNS_ZONE_VALID(zone));
18027 return (zone->signatures);
18028 }
18029
18030 void
18031 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
18032 REQUIRE(DNS_ZONE_VALID(zone));
18033 zone->privatetype = type;
18034 }
18035
18036 dns_rdatatype_t
18037 dns_zone_getprivatetype(dns_zone_t *zone) {
18038 REQUIRE(DNS_ZONE_VALID(zone));
18039 return (zone->privatetype);
18040 }
18041
18042 static isc_result_t
18043 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, uint16_t keyid,
18044 bool deleteit)
18045 {
18046 dns_signing_t *signing;
18047 dns_signing_t *current;
18048 isc_result_t result = ISC_R_SUCCESS;
18049 isc_time_t now;
18050 dns_db_t *db = NULL;
18051
18052 signing = isc_mem_get(zone->mctx, sizeof *signing);
18053 if (signing == NULL)
18054 return (ISC_R_NOMEMORY);
18055
18056 signing->magic = 0;
18057 signing->db = NULL;
18058 signing->dbiterator = NULL;
18059 signing->algorithm = algorithm;
18060 signing->keyid = keyid;
18061 signing->deleteit = deleteit;
18062 signing->done = false;
18063
18064 TIME_NOW(&now);
18065
18066 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18067 if (zone->db != NULL)
18068 dns_db_attach(zone->db, &db);
18069 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18070
18071 if (db == NULL) {
18072 result = ISC_R_NOTFOUND;
18073 goto cleanup;
18074 }
18075
18076 dns_db_attach(db, &signing->db);
18077
18078 for (current = ISC_LIST_HEAD(zone->signing);
18079 current != NULL;
18080 current = ISC_LIST_NEXT(current, link)) {
18081 if (current->db == signing->db &&
18082 current->algorithm == signing->algorithm &&
18083 current->keyid == signing->keyid) {
18084 if (current->deleteit != signing->deleteit)
18085 current->done = true;
18086 else
18087 goto cleanup;
18088 }
18089 }
18090
18091 result = dns_db_createiterator(signing->db, 0,
18092 &signing->dbiterator);
18093
18094 if (result == ISC_R_SUCCESS)
18095 result = dns_dbiterator_first(signing->dbiterator);
18096 if (result == ISC_R_SUCCESS) {
18097 dns_dbiterator_pause(signing->dbiterator);
18098 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
18099 signing = NULL;
18100 if (isc_time_isepoch(&zone->signingtime)) {
18101 zone->signingtime = now;
18102 if (zone->task != NULL)
18103 zone_settimer(zone, &now);
18104 }
18105 }
18106
18107 cleanup:
18108 if (signing != NULL) {
18109 if (signing->db != NULL)
18110 dns_db_detach(&signing->db);
18111 if (signing->dbiterator != NULL)
18112 dns_dbiterator_destroy(&signing->dbiterator);
18113 isc_mem_put(zone->mctx, signing, sizeof *signing);
18114 }
18115 if (db != NULL)
18116 dns_db_detach(&db);
18117 return (result);
18118 }
18119
18120 static void
18121 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
18122 dns_dnsseckey_t *key;
18123 while (!ISC_LIST_EMPTY(*list)) {
18124 key = ISC_LIST_HEAD(*list);
18125 ISC_LIST_UNLINK(*list, key, link);
18126 dns_dnsseckey_destroy(mctx, &key);
18127 }
18128 }
18129
18130 /* Called once; *timep should be set to the current time. */
18131 static isc_result_t
18132 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
18133 isc_result_t result;
18134 isc_stdtime_t now, then = 0, event;
18135 int i;
18136
18137 now = *timep;
18138
18139 for (i = 0; i <= DST_MAX_TIMES; i++) {
18140 result = dst_key_gettime(key, i, &event);
18141 if (result == ISC_R_SUCCESS && event > now &&
18142 (then == 0 || event < then))
18143 then = event;
18144 }
18145
18146 if (then != 0) {
18147 *timep = then;
18148 return (ISC_R_SUCCESS);
18149 }
18150
18151 return (ISC_R_NOTFOUND);
18152 }
18153
18154 static isc_result_t
18155 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
18156 const dns_rdata_t *rdata, bool *flag)
18157 {
18158 dns_rdataset_t rdataset;
18159 dns_dbnode_t *node = NULL;
18160 isc_result_t result;
18161
18162 dns_rdataset_init(&rdataset);
18163 if (rdata->type == dns_rdatatype_nsec3)
18164 CHECK(dns_db_findnsec3node(db, name, false, &node));
18165 else
18166 CHECK(dns_db_findnode(db, name, false, &node));
18167 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
18168 (isc_stdtime_t) 0, &rdataset, NULL);
18169 if (result == ISC_R_NOTFOUND) {
18170 *flag = false;
18171 result = ISC_R_SUCCESS;
18172 goto failure;
18173 }
18174
18175 for (result = dns_rdataset_first(&rdataset);
18176 result == ISC_R_SUCCESS;
18177 result = dns_rdataset_next(&rdataset)) {
18178 dns_rdata_t myrdata = DNS_RDATA_INIT;
18179 dns_rdataset_current(&rdataset, &myrdata);
18180 if (!dns_rdata_compare(&myrdata, rdata))
18181 break;
18182 }
18183 dns_rdataset_disassociate(&rdataset);
18184 if (result == ISC_R_SUCCESS) {
18185 *flag = true;
18186 } else if (result == ISC_R_NOMORE) {
18187 *flag = false;
18188 result = ISC_R_SUCCESS;
18189 }
18190
18191 failure:
18192 if (node != NULL)
18193 dns_db_detachnode(db, &node);
18194 return (result);
18195 }
18196
18197 /*
18198 * Add records to signal the state of signing or of key removal.
18199 */
18200 static isc_result_t
18201 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
18202 dns_dbversion_t *ver, dns_diff_t *diff, bool sign_all)
18203 {
18204 dns_difftuple_t *tuple, *newtuple = NULL;
18205 dns_rdata_dnskey_t dnskey;
18206 dns_rdata_t rdata = DNS_RDATA_INIT;
18207 bool flag;
18208 isc_region_t r;
18209 isc_result_t result = ISC_R_SUCCESS;
18210 uint16_t keyid;
18211 unsigned char buf[5];
18212 dns_name_t *name = dns_db_origin(db);
18213
18214 for (tuple = ISC_LIST_HEAD(diff->tuples);
18215 tuple != NULL;
18216 tuple = ISC_LIST_NEXT(tuple, link)) {
18217 if (tuple->rdata.type != dns_rdatatype_dnskey) {
18218 continue;
18219 }
18220
18221 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
18222 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18223 if ((dnskey.flags &
18224 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
18225 != DNS_KEYOWNER_ZONE)
18226 {
18227 continue;
18228 }
18229
18230 dns_rdata_toregion(&tuple->rdata, &r);
18231
18232 keyid = dst_region_computeid(&r);
18233
18234 buf[0] = dnskey.algorithm;
18235 buf[1] = (keyid & 0xff00) >> 8;
18236 buf[2] = (keyid & 0xff);
18237 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
18238 buf[4] = 0;
18239 rdata.data = buf;
18240 rdata.length = sizeof(buf);
18241 rdata.type = privatetype;
18242 rdata.rdclass = tuple->rdata.rdclass;
18243
18244 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
18245 CHECK(rr_exists(db, ver, name, &rdata, &flag));
18246 if (flag) {
18247 continue;
18248 }
18249
18250 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
18251 name, 0, &rdata, &newtuple));
18252 CHECK(do_one_tuple(&newtuple, db, ver, diff));
18253 INSIST(newtuple == NULL);
18254 }
18255
18256 /*
18257 * Remove any record which says this operation has already
18258 * completed.
18259 */
18260 buf[4] = 1;
18261 CHECK(rr_exists(db, ver, name, &rdata, &flag));
18262 if (flag) {
18263 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
18264 name, 0, &rdata, &newtuple));
18265 CHECK(do_one_tuple(&newtuple, db, ver, diff));
18266 INSIST(newtuple == NULL);
18267 }
18268 }
18269 failure:
18270 return (result);
18271 }
18272
18273 static isc_result_t
18274 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18275 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff)
18276 {
18277 isc_result_t result;
18278 isc_stdtime_t inception, soaexpire, keyexpire;
18279 bool check_ksk, keyset_kskonly;
18280 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
18281 unsigned int nkeys = 0, i;
18282 dns_difftuple_t *tuple;
18283
18284 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
18285 DNS_MAXZONEKEYS, zone_keys, &nkeys);
18286 if (result != ISC_R_SUCCESS) {
18287 dnssec_log(zone, ISC_LOG_ERROR,
18288 "sign_apex:dns__zone_findkeys -> %s",
18289 dns_result_totext(result));
18290 return (result);
18291 }
18292
18293 inception = now - 3600; /* Allow for clock skew. */
18294 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
18295
18296 keyexpire = dns_zone_getkeyvalidityinterval(zone);
18297 if (keyexpire == 0) {
18298 keyexpire = soaexpire - 1;
18299 } else {
18300 keyexpire += now;
18301 }
18302
18303 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
18304 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
18305
18306 /*
18307 * See if dns__zone_updatesigs() will update DNSKEY signature and if
18308 * not cause them to sign so that newly activated keys are used.
18309 */
18310 for (tuple = ISC_LIST_HEAD(diff->tuples);
18311 tuple != NULL;
18312 tuple = ISC_LIST_NEXT(tuple, link))
18313 {
18314 if (tuple->rdata.type == dns_rdatatype_dnskey &&
18315 dns_name_equal(&tuple->name, &zone->origin))
18316 {
18317 break;
18318 }
18319 }
18320
18321 if (tuple == NULL) {
18322 result = del_sigs(zone, db, ver, &zone->origin,
18323 dns_rdatatype_dnskey, zonediff,
18324 zone_keys, nkeys, now, false);
18325 if (result != ISC_R_SUCCESS) {
18326 dnssec_log(zone, ISC_LOG_ERROR,
18327 "sign_apex:del_sigs -> %s",
18328 dns_result_totext(result));
18329 goto failure;
18330 }
18331 result = add_sigs(db, ver, &zone->origin, zone,
18332 dns_rdatatype_dnskey, zonediff->diff,
18333 zone_keys, nkeys, zone->mctx, inception,
18334 keyexpire, check_ksk, keyset_kskonly);
18335 if (result != ISC_R_SUCCESS) {
18336 dnssec_log(zone, ISC_LOG_ERROR,
18337 "sign_apex:add_sigs -> %s",
18338 dns_result_totext(result));
18339 goto failure;
18340 }
18341 }
18342
18343 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
18344 inception, soaexpire, keyexpire, now,
18345 check_ksk, keyset_kskonly, zonediff);
18346
18347 if (result != ISC_R_SUCCESS) {
18348 dnssec_log(zone, ISC_LOG_ERROR,
18349 "sign_apex:dns__zone_updatesigs -> %s",
18350 dns_result_totext(result));
18351 goto failure;
18352 }
18353
18354 failure:
18355 for (i = 0; i < nkeys; i++) {
18356 dst_key_free(&zone_keys[i]);
18357 }
18358 return (result);
18359 }
18360
18361 /*
18362 * Prevent the zone entering a inconsistent state where
18363 * NSEC only DNSKEYs are present with NSEC3 chains.
18364 * See update.c:check_dnssec()
18365 */
18366 static bool
18367 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18368 dns_diff_t *diff)
18369 {
18370 isc_result_t result;
18371 dns_difftuple_t *tuple;
18372 bool nseconly = false, nsec3 = false;
18373 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
18374
18375 /* Scan the tuples for an NSEC-only DNSKEY */
18376 for (tuple = ISC_LIST_HEAD(diff->tuples);
18377 tuple != NULL;
18378 tuple = ISC_LIST_NEXT(tuple, link))
18379 {
18380 uint8_t alg;
18381 if (tuple->rdata.type != dns_rdatatype_dnskey ||
18382 tuple->op != DNS_DIFFOP_ADD)
18383 {
18384 continue;
18385 }
18386
18387 alg = tuple->rdata.data[3];
18388 if (alg == DST_ALG_RSASHA1) {
18389 nseconly = true;
18390 break;
18391 }
18392 }
18393
18394 /* Check existing DB for NSEC-only DNSKEY */
18395 if (!nseconly) {
18396 result = dns_nsec_nseconly(db, ver, &nseconly);
18397 if (result == ISC_R_NOTFOUND) {
18398 result = ISC_R_SUCCESS;
18399 }
18400 CHECK(result);
18401 }
18402
18403 /* Check existing DB for NSEC3 */
18404 if (!nsec3) {
18405 CHECK(dns_nsec3_activex(db, ver, false,
18406 privatetype, &nsec3));
18407 }
18408
18409 /* Refuse to allow NSEC3 with NSEC-only keys */
18410 if (nseconly && nsec3) {
18411 dnssec_log(zone, ISC_LOG_ERROR,
18412 "NSEC only DNSKEYs and NSEC3 chains not allowed");
18413 goto failure;
18414 }
18415
18416 return (true);
18417
18418 failure:
18419 return (false);
18420 }
18421
18422 static isc_result_t
18423 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18424 dns_diff_t *diff)
18425 {
18426 isc_result_t result;
18427 dns_dbnode_t *node = NULL;
18428 dns_rdataset_t rdataset;
18429
18430 dns_rdataset_init(&rdataset);
18431 CHECK(dns_db_getoriginnode(db, &node));
18432
18433 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
18434 dns_rdatatype_none, 0, &rdataset, NULL);
18435 if (dns_rdataset_isassociated(&rdataset))
18436 dns_rdataset_disassociate(&rdataset);
18437 if (result != ISC_R_NOTFOUND)
18438 goto failure;
18439
18440 result = dns_nsec3param_deletechains(db, ver, zone, true, diff);
18441
18442 failure:
18443 if (node != NULL)
18444 dns_db_detachnode(db, &node);
18445 return (result);
18446 }
18447
18448 /*
18449 * Given an RRSIG rdataset and an algorithm, determine whether there
18450 * are any signatures using that algorithm.
18451 */
18452 static bool
18453 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
18454 dns_rdata_t rdata = DNS_RDATA_INIT;
18455 dns_rdata_rrsig_t rrsig;
18456 isc_result_t result;
18457
18458 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
18459 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
18460 return (false);
18461 }
18462
18463 for (result = dns_rdataset_first(rdataset);
18464 result == ISC_R_SUCCESS;
18465 result = dns_rdataset_next(rdataset))
18466 {
18467 dns_rdataset_current(rdataset, &rdata);
18468 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
18469 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18470 dns_rdata_reset(&rdata);
18471 if (rrsig.algorithm == alg)
18472 return (true);
18473 }
18474
18475 return (false);
18476 }
18477
18478 static isc_result_t
18479 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
18480 dns_diff_t *diff)
18481 {
18482 dns_name_t *origin;
18483 bool build_nsec3;
18484 isc_result_t result;
18485
18486 origin = dns_db_origin(db);
18487 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
18488 &build_nsec3));
18489 if (build_nsec3)
18490 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
18491 false, zone->privatetype, diff));
18492 CHECK(updatesecure(db, ver, origin, zone->minimum, true, diff));
18493
18494 failure:
18495 return (result);
18496 }
18497
18498 static void
18499 dnssec_report(const char *format, ...) {
18500 va_list args;
18501 va_start(args, format);
18502 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_ZONE,
18503 ISC_LOG_INFO, format, args);
18504 va_end(args);
18505 }
18506
18507 static void
18508 zone_rekey(dns_zone_t *zone) {
18509 isc_result_t result;
18510 dns_db_t *db = NULL;
18511 dns_dbnode_t *node = NULL;
18512 dns_dbversion_t *ver = NULL;
18513 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
18514 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
18515 dns_dnsseckey_t *key = NULL;
18516 dns_diff_t diff, _sig_diff;
18517 dns__zonediff_t zonediff;
18518 bool commit = false, newactive = false;
18519 bool newalg = false;
18520 bool fullsign;
18521 dns_ttl_t ttl = 3600;
18522 const char *dir = NULL;
18523 isc_mem_t *mctx = NULL;
18524 isc_stdtime_t now;
18525 isc_time_t timenow;
18526 isc_interval_t ival;
18527 char timebuf[80];
18528
18529 REQUIRE(DNS_ZONE_VALID(zone));
18530
18531 ISC_LIST_INIT(dnskeys);
18532 ISC_LIST_INIT(keys);
18533 ISC_LIST_INIT(rmkeys);
18534 dns_rdataset_init(&soaset);
18535 dns_rdataset_init(&soasigs);
18536 dns_rdataset_init(&keyset);
18537 dns_rdataset_init(&keysigs);
18538 dns_rdataset_init(&cdsset);
18539 dns_rdataset_init(&cdnskeyset);
18540 dir = dns_zone_getkeydirectory(zone);
18541 mctx = zone->mctx;
18542 dns_diff_init(mctx, &diff);
18543 dns_diff_init(mctx, &_sig_diff);
18544 zonediff_init(&zonediff, &_sig_diff);
18545
18546 CHECK(dns_zone_getdb(zone, &db));
18547 CHECK(dns_db_newversion(db, &ver));
18548 CHECK(dns_db_getoriginnode(db, &node));
18549
18550 TIME_NOW(&timenow);
18551 now = isc_time_seconds(&timenow);
18552
18553 dnssec_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
18554
18555 /* Get the SOA record's TTL */
18556 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
18557 dns_rdatatype_none, 0, &soaset, &soasigs));
18558 ttl = soaset.ttl;
18559 dns_rdataset_disassociate(&soaset);
18560
18561 /* Get the DNSKEY rdataset */
18562 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
18563 dns_rdatatype_none, 0, &keyset, &keysigs);
18564 if (result == ISC_R_SUCCESS) {
18565 ttl = keyset.ttl;
18566 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
18567 mctx, &keyset,
18568 &keysigs, &soasigs,
18569 false, false,
18570 &dnskeys));
18571 } else if (result != ISC_R_NOTFOUND) {
18572 goto failure;
18573 }
18574
18575 /* Get the CDS rdataset */
18576 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
18577 dns_rdatatype_none, 0, &cdsset, NULL);
18578 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset))
18579 dns_rdataset_disassociate(&cdsset);
18580
18581 /* Get the CDNSKEY rdataset */
18582 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
18583 dns_rdatatype_none, 0, &cdnskeyset, NULL);
18584 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset))
18585 {
18586 dns_rdataset_disassociate(&cdnskeyset);
18587 }
18588
18589 /*
18590 * True when called from "rndc sign". Indicates the zone should be
18591 * fully signed now.
18592 */
18593 fullsign = DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN);
18594
18595 result = dns_dnssec_findmatchingkeys(&zone->origin, dir, now, mctx,
18596 &keys);
18597 if (result == ISC_R_SUCCESS) {
18598 bool check_ksk;
18599 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
18600 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
18601 &zone->origin, ttl, &diff,
18602 !check_ksk, mctx,
18603 dnssec_report);
18604 /*
18605 * Keys couldn't be updated for some reason;
18606 * try again later.
18607 */
18608 if (result != ISC_R_SUCCESS) {
18609 dnssec_log(zone, ISC_LOG_ERROR,
18610 "zone_rekey:couldn't update zone keys: %s",
18611 isc_result_totext(result));
18612 goto failure;
18613 }
18614
18615 /*
18616 * Update CDS / CDNSKEY records.
18617 */
18618 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
18619 &cdnskeyset, now, ttl,
18620 &diff, mctx);
18621 if (result != ISC_R_SUCCESS) {
18622 dnssec_log(zone, ISC_LOG_ERROR,
18623 "zone_rekey:couldn't update CDS/CDNSKEY: %s",
18624 isc_result_totext(result));
18625 goto failure;
18626 }
18627
18628 /*
18629 * See if any pre-existing keys have newly become active;
18630 * also, see if any new key is for a new algorithm, as in that
18631 * event, we need to sign the zone fully. (If there's a new
18632 * key, but it's for an already-existing algorithm, then
18633 * the zone signing can be handled incrementally.)
18634 */
18635 for (key = ISC_LIST_HEAD(dnskeys);
18636 key != NULL;
18637 key = ISC_LIST_NEXT(key, link))
18638 {
18639 if (!key->first_sign) {
18640 continue;
18641 }
18642
18643 newactive = true;
18644
18645 if (!dns_rdataset_isassociated(&keysigs)) {
18646 newalg = true;
18647 break;
18648 }
18649
18650 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
18651 /*
18652 * This isn't a new algorithm; clear
18653 * first_sign so we won't sign the
18654 * whole zone with this key later
18655 */
18656 key->first_sign = false;
18657 } else {
18658 newalg = true;
18659 break;
18660 }
18661 }
18662
18663 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
18664 dnskey_sane(zone, db, ver, &diff))
18665 {
18666 CHECK(dns_diff_apply(&diff, db, ver));
18667 CHECK(clean_nsec3param(zone, db, ver, &diff));
18668 CHECK(add_signing_records(db, zone->privatetype, ver,
18669 &diff, (newalg || fullsign)));
18670 CHECK(update_soa_serial(db, ver, &diff, mctx,
18671 zone->updatemethod));
18672 CHECK(add_chains(zone, db, ver, &diff));
18673 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
18674 CHECK(zone_journal(zone, zonediff.diff, NULL,
18675 "zone_rekey"));
18676 commit = true;
18677 }
18678 }
18679
18680 dns_db_closeversion(db, &ver, true);
18681
18682 if (commit) {
18683 dns_difftuple_t *tuple;
18684
18685 LOCK_ZONE(zone);
18686 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
18687
18688 zone_needdump(zone, DNS_DUMP_DELAY);
18689
18690 zone_settimer(zone, &timenow);
18691
18692 /* Remove any signatures from removed keys. */
18693 if (!ISC_LIST_EMPTY(rmkeys)) {
18694 for (key = ISC_LIST_HEAD(rmkeys);
18695 key != NULL;
18696 key = ISC_LIST_NEXT(key, link))
18697 {
18698 result = zone_signwithkey(zone,
18699 dst_key_alg(key->key),
18700 dst_key_id(key->key),
18701 true);
18702 if (result != ISC_R_SUCCESS) {
18703 dnssec_log(zone, ISC_LOG_ERROR,
18704 "zone_signwithkey failed: %s",
18705 dns_result_totext(result));
18706 }
18707 }
18708 }
18709
18710 if (fullsign) {
18711 /*
18712 * "rndc sign" was called, so we now sign the zone
18713 * with all active keys, whether they're new or not.
18714 */
18715 for (key = ISC_LIST_HEAD(dnskeys);
18716 key != NULL;
18717 key = ISC_LIST_NEXT(key, link))
18718 {
18719 if (!key->force_sign && !key->hint_sign) {
18720 continue;
18721 }
18722
18723 result = zone_signwithkey(zone,
18724 dst_key_alg(key->key),
18725 dst_key_id(key->key),
18726 false);
18727 if (result != ISC_R_SUCCESS) {
18728 dnssec_log(zone, ISC_LOG_ERROR,
18729 "zone_signwithkey failed: %s",
18730 dns_result_totext(result));
18731 }
18732 }
18733 } else if (newalg) {
18734 /*
18735 * We haven't been told to sign fully, but a new
18736 * algorithm was added to the DNSKEY. We sign
18737 * the full zone, but only with newly active
18738 * keys.
18739 */
18740 for (key = ISC_LIST_HEAD(dnskeys);
18741 key != NULL;
18742 key = ISC_LIST_NEXT(key, link))
18743 {
18744 if (!key->first_sign) {
18745 continue;
18746 }
18747
18748 result = zone_signwithkey(zone,
18749 dst_key_alg(key->key),
18750 dst_key_id(key->key),
18751 false);
18752 if (result != ISC_R_SUCCESS) {
18753 dnssec_log(zone, ISC_LOG_ERROR,
18754 "zone_signwithkey failed: %s",
18755 dns_result_totext(result));
18756 }
18757 }
18758 }
18759
18760 /*
18761 * Clear fullsign flag, if it was set, so we don't do
18762 * another full signing next time
18763 */
18764 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
18765
18766 /*
18767 * Cause the zone to add/delete NSEC3 chains for the
18768 * deferred NSEC3PARAM changes.
18769 */
18770 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
18771 tuple != NULL;
18772 tuple = ISC_LIST_NEXT(tuple, link))
18773 {
18774 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
18775 dns_rdata_t rdata = DNS_RDATA_INIT;
18776 dns_rdata_nsec3param_t nsec3param;
18777
18778 if (tuple->rdata.type != zone->privatetype ||
18779 tuple->op != DNS_DIFFOP_ADD)
18780 {
18781 continue;
18782 }
18783
18784 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
18785 buf, sizeof(buf)))
18786 {
18787 continue;
18788 }
18789
18790 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
18791 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18792 if (nsec3param.flags == 0) {
18793 continue;
18794 }
18795
18796 result = zone_addnsec3chain(zone, &nsec3param);
18797 if (result != ISC_R_SUCCESS) {
18798 dnssec_log(zone, ISC_LOG_ERROR,
18799 "zone_addnsec3chain failed: %s",
18800 dns_result_totext(result));
18801 }
18802 }
18803
18804 /*
18805 * Activate any NSEC3 chain updates that may have
18806 * been scheduled before this rekey.
18807 */
18808 if (fullsign || newalg) {
18809 resume_addnsec3chain(zone);
18810 }
18811
18812 /*
18813 * Schedule the next resigning event
18814 */
18815 set_resigntime(zone);
18816 UNLOCK_ZONE(zone);
18817 }
18818
18819 isc_time_settoepoch(&zone->refreshkeytime);
18820
18821 /*
18822 * If we're doing key maintenance, set the key refresh timer to
18823 * the next scheduled key event or to 'dnssec-loadkeys-interval'
18824 * seconds in the future, whichever is sooner.
18825 */
18826 if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
18827 isc_time_t timethen;
18828 isc_stdtime_t then;
18829
18830 LOCK_ZONE(zone);
18831 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
18832 &timethen);
18833 zone->refreshkeytime = timethen;
18834 UNLOCK_ZONE(zone);
18835
18836 for (key = ISC_LIST_HEAD(dnskeys);
18837 key != NULL;
18838 key = ISC_LIST_NEXT(key, link))
18839 {
18840 then = now;
18841 result = next_keyevent(key->key, &then);
18842 if (result != ISC_R_SUCCESS) {
18843 continue;
18844 }
18845
18846 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
18847 LOCK_ZONE(zone);
18848 if (isc_time_compare(&timethen,
18849 &zone->refreshkeytime) < 0)
18850 {
18851 zone->refreshkeytime = timethen;
18852 }
18853 UNLOCK_ZONE(zone);
18854 }
18855
18856 zone_settimer(zone, &timenow);
18857
18858 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
18859 dnssec_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
18860 }
18861
18862 result = ISC_R_SUCCESS;
18863
18864 failure:
18865 if (result != ISC_R_SUCCESS) {
18866 /*
18867 * Something went wrong; try again in ten minutes or
18868 * after a key refresh interval, whichever is shorter.
18869 */
18870 isc_interval_set(&ival,
18871 ISC_MIN(zone->refreshkeyinterval, 600), 0);
18872 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
18873 }
18874
18875 dns_diff_clear(&diff);
18876 dns_diff_clear(&_sig_diff);
18877
18878 clear_keylist(&dnskeys, mctx);
18879 clear_keylist(&keys, mctx);
18880 clear_keylist(&rmkeys, mctx);
18881
18882 if (ver != NULL) {
18883 dns_db_closeversion(db, &ver, false);
18884 }
18885 if (dns_rdataset_isassociated(&cdsset)) {
18886 dns_rdataset_disassociate(&cdsset);
18887 }
18888 if (dns_rdataset_isassociated(&keyset)) {
18889 dns_rdataset_disassociate(&keyset);
18890 }
18891 if (dns_rdataset_isassociated(&keysigs)) {
18892 dns_rdataset_disassociate(&keysigs);
18893 }
18894 if (dns_rdataset_isassociated(&soasigs)) {
18895 dns_rdataset_disassociate(&soasigs);
18896 }
18897 if (dns_rdataset_isassociated(&cdnskeyset)) {
18898 dns_rdataset_disassociate(&cdnskeyset);
18899 }
18900 if (node != NULL) {
18901 dns_db_detachnode(db, &node);
18902 }
18903 if (db != NULL) {
18904 dns_db_detach(&db);
18905 }
18906
18907 INSIST(ver == NULL);
18908 }
18909
18910 void
18911 dns_zone_rekey(dns_zone_t *zone, bool fullsign) {
18912 isc_time_t now;
18913
18914 if (zone->type == dns_zone_master && zone->task != NULL) {
18915 LOCK_ZONE(zone);
18916
18917 if (fullsign)
18918 zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
18919
18920 TIME_NOW(&now);
18921 zone->refreshkeytime = now;
18922 zone_settimer(zone, &now);
18923
18924 UNLOCK_ZONE(zone);
18925 }
18926 }
18927
18928 isc_result_t
18929 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
18930 unsigned int *errors)
18931 {
18932 isc_result_t result;
18933 dns_dbnode_t *node = NULL;
18934
18935 REQUIRE(DNS_ZONE_VALID(zone));
18936 REQUIRE(errors != NULL);
18937
18938 result = dns_db_getoriginnode(db, &node);
18939 if (result != ISC_R_SUCCESS)
18940 return (result);
18941 result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
18942 false);
18943 dns_db_detachnode(db, &node);
18944 return (result);
18945 }
18946
18947 isc_result_t
18948 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
18949 isc_result_t result;
18950 dns_dbnode_t *node = NULL;
18951 dns_rdataset_t dnskey, cds, cdnskey;
18952 unsigned char buffer[DNS_DS_BUFFERSIZE];
18953 unsigned char algorithms[256];
18954 unsigned int i;
18955
18956 REQUIRE(DNS_ZONE_VALID(zone));
18957
18958 result = dns_db_getoriginnode(db, &node);
18959 if (result != ISC_R_SUCCESS)
18960 return (result);
18961
18962 dns_rdataset_init(&cds);
18963 dns_rdataset_init(&dnskey);
18964 dns_rdataset_init(&cdnskey);
18965
18966 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
18967 dns_rdatatype_none, 0, &cds, NULL);
18968 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18969 goto failure;
18970
18971 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
18972 dns_rdatatype_none, 0, &cdnskey, NULL);
18973 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18974 goto failure;
18975
18976 if (!dns_rdataset_isassociated(&cds) &&
18977 !dns_rdataset_isassociated(&cdnskey)) {
18978 result = ISC_R_SUCCESS;
18979 goto failure;
18980 }
18981
18982 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
18983 dns_rdatatype_none, 0, &dnskey, NULL);
18984 if (result == ISC_R_NOTFOUND) {
18985 if (dns_rdataset_isassociated(&cds))
18986 result = DNS_R_BADCDS;
18987 else
18988 result = DNS_R_BADCDNSKEY;
18989 goto failure;
18990 }
18991 if (result != ISC_R_SUCCESS)
18992 goto failure;
18993
18994 /*
18995 * For each DNSSEC algorithm in the CDS RRset there must be
18996 * a matching DNSKEY record.
18997 */
18998 if (dns_rdataset_isassociated(&cds)) {
18999 memset(algorithms, 0, sizeof(algorithms));
19000 for (result = dns_rdataset_first(&cds);
19001 result == ISC_R_SUCCESS;
19002 result = dns_rdataset_next(&cds)) {
19003 dns_rdata_t crdata = DNS_RDATA_INIT;
19004 dns_rdata_cds_t structcds;
19005
19006 dns_rdataset_current(&cds, &crdata);
19007 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
19008 if (algorithms[structcds.algorithm] == 0)
19009 algorithms[structcds.algorithm] = 1;
19010 for (result = dns_rdataset_first(&dnskey);
19011 result == ISC_R_SUCCESS;
19012 result = dns_rdataset_next(&dnskey)) {
19013 dns_rdata_t rdata = DNS_RDATA_INIT;
19014 dns_rdata_t dsrdata = DNS_RDATA_INIT;
19015
19016 dns_rdataset_current(&dnskey, &rdata);
19017 CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
19018 structcds.digest_type,
19019 buffer, &dsrdata));
19020 if (crdata.length == dsrdata.length &&
19021 memcmp(crdata.data, dsrdata.data,
19022 dsrdata.length) == 0) {
19023 algorithms[structcds.algorithm] = 2;
19024 }
19025 }
19026 if (result != ISC_R_NOMORE)
19027 goto failure;
19028 }
19029 for (i = 0; i < sizeof(algorithms); i++) {
19030 if (algorithms[i] == 1) {
19031 result = DNS_R_BADCDNSKEY;
19032 goto failure;
19033 }
19034 }
19035 }
19036
19037 /*
19038 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
19039 * a matching DNSKEY record.
19040 */
19041 if (dns_rdataset_isassociated(&cdnskey)) {
19042 memset(algorithms, 0, sizeof(algorithms));
19043 for (result = dns_rdataset_first(&cdnskey);
19044 result == ISC_R_SUCCESS;
19045 result = dns_rdataset_next(&cdnskey)) {
19046 dns_rdata_t crdata = DNS_RDATA_INIT;
19047 dns_rdata_cdnskey_t structcdnskey;
19048
19049 dns_rdataset_current(&cdnskey, &crdata);
19050 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
19051 NULL));
19052 if (algorithms[structcdnskey.algorithm] == 0)
19053 algorithms[structcdnskey.algorithm] = 1;
19054 for (result = dns_rdataset_first(&dnskey);
19055 result == ISC_R_SUCCESS;
19056 result = dns_rdataset_next(&dnskey)) {
19057 dns_rdata_t rdata = DNS_RDATA_INIT;
19058
19059 dns_rdataset_current(&dnskey, &rdata);
19060 if (crdata.length == rdata.length &&
19061 memcmp(crdata.data, rdata.data,
19062 rdata.length) == 0) {
19063 algorithms[structcdnskey.algorithm] = 2;
19064 }
19065 }
19066 if (result != ISC_R_NOMORE)
19067 goto failure;
19068 }
19069 for (i = 0; i < sizeof(algorithms); i++) {
19070 if (algorithms[i] == 1) {
19071 result = DNS_R_BADCDS;
19072 goto failure;
19073 }
19074 }
19075 }
19076 result = ISC_R_SUCCESS;
19077
19078 failure:
19079 if (dns_rdataset_isassociated(&cds))
19080 dns_rdataset_disassociate(&cds);
19081 if (dns_rdataset_isassociated(&dnskey))
19082 dns_rdataset_disassociate(&dnskey);
19083 if (dns_rdataset_isassociated(&cdnskey))
19084 dns_rdataset_disassociate(&cdnskey);
19085 dns_db_detachnode(db, &node);
19086 return (result);
19087 }
19088
19089 void
19090 dns_zone_setautomatic(dns_zone_t *zone, bool automatic) {
19091 REQUIRE(DNS_ZONE_VALID(zone));
19092
19093 LOCK_ZONE(zone);
19094 zone->automatic = automatic;
19095 UNLOCK_ZONE(zone);
19096 }
19097
19098 bool
19099 dns_zone_getautomatic(dns_zone_t *zone) {
19100 REQUIRE(DNS_ZONE_VALID(zone));
19101 return (zone->automatic);
19102 }
19103
19104 void
19105 dns_zone_setadded(dns_zone_t *zone, bool added) {
19106 REQUIRE(DNS_ZONE_VALID(zone));
19107
19108 LOCK_ZONE(zone);
19109 zone->added = added;
19110 UNLOCK_ZONE(zone);
19111 }
19112
19113 bool
19114 dns_zone_getadded(dns_zone_t *zone) {
19115 REQUIRE(DNS_ZONE_VALID(zone));
19116 return (zone->added);
19117 }
19118
19119 isc_result_t
19120 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
19121 {
19122 isc_time_t loadtime;
19123 isc_result_t result;
19124 dns_zone_t *secure = NULL;
19125
19126 TIME_NOW(&loadtime);
19127
19128 /*
19129 * Lock hierarchy: zmgr, zone, raw.
19130 */
19131 again:
19132 LOCK_ZONE(zone);
19133 INSIST(zone != zone->raw);
19134 if (inline_secure(zone))
19135 LOCK_ZONE(zone->raw);
19136 else if (inline_raw(zone)) {
19137 secure = zone->secure;
19138 TRYLOCK_ZONE(result, secure);
19139 if (result != ISC_R_SUCCESS) {
19140 UNLOCK_ZONE(zone);
19141 secure = NULL;
19142 isc_thread_yield();
19143 goto again;
19144 }
19145 }
19146 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
19147 if (inline_secure(zone))
19148 UNLOCK_ZONE(zone->raw);
19149 else if (secure != NULL)
19150 UNLOCK_ZONE(secure);
19151 UNLOCK_ZONE(zone);
19152 return result;
19153 }
19154
19155 isc_result_t
19156 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, uint32_t interval) {
19157 REQUIRE(DNS_ZONE_VALID(zone));
19158 if (interval == 0)
19159 return (ISC_R_RANGE);
19160 /* Maximum value: 24 hours (3600 minutes) */
19161 if (interval > (24 * 60))
19162 interval = (24 * 60);
19163 /* Multiply by 60 for seconds */
19164 zone->refreshkeyinterval = interval * 60;
19165 return (ISC_R_SUCCESS);
19166 }
19167
19168 void
19169 dns_zone_setrequestixfr(dns_zone_t *zone, bool flag) {
19170 REQUIRE(DNS_ZONE_VALID(zone));
19171 zone->requestixfr = flag;
19172 }
19173
19174 bool
19175 dns_zone_getrequestixfr(dns_zone_t *zone) {
19176 REQUIRE(DNS_ZONE_VALID(zone));
19177 return (zone->requestixfr);
19178 }
19179
19180 void
19181 dns_zone_setrequestexpire(dns_zone_t *zone, bool flag) {
19182 REQUIRE(DNS_ZONE_VALID(zone));
19183 zone->requestexpire = flag;
19184 }
19185
19186 bool
19187 dns_zone_getrequestexpire(dns_zone_t *zone) {
19188 REQUIRE(DNS_ZONE_VALID(zone));
19189 return (zone->requestexpire);
19190 }
19191
19192 void
19193 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
19194 REQUIRE(DNS_ZONE_VALID(zone));
19195 zone->updatemethod = method;
19196 }
19197
19198 dns_updatemethod_t
19199 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
19200 REQUIRE(DNS_ZONE_VALID(zone));
19201 return(zone->updatemethod);
19202 }
19203
19204 /*
19205 * Lock hierarchy: zmgr, zone, raw.
19206 */
19207 isc_result_t
19208 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
19209 isc_result_t result;
19210 dns_zonemgr_t *zmgr;
19211
19212 REQUIRE(DNS_ZONE_VALID(zone));
19213 REQUIRE(zone->zmgr != NULL);
19214 REQUIRE(zone->task != NULL);
19215 REQUIRE(zone->loadtask != NULL);
19216 REQUIRE(zone->raw == NULL);
19217
19218 REQUIRE(DNS_ZONE_VALID(raw));
19219 REQUIRE(raw->zmgr == NULL);
19220 REQUIRE(raw->task == NULL);
19221 REQUIRE(raw->loadtask == NULL);
19222 REQUIRE(raw->secure == NULL);
19223
19224 REQUIRE(zone != raw);
19225
19226 /*
19227 * Lock hierarchy: zmgr, zone, raw.
19228 */
19229 zmgr = zone->zmgr;
19230 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19231 LOCK_ZONE(zone);
19232 LOCK_ZONE(raw);
19233
19234 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
19235 NULL, NULL, zone->task, zone_timer, raw,
19236 &raw->timer);
19237 if (result != ISC_R_SUCCESS)
19238 goto unlock;
19239
19240 /*
19241 * The timer "holds" a iref.
19242 */
19243 raw->irefs++;
19244 INSIST(raw->irefs != 0);
19245
19246
19247 /* dns_zone_attach(raw, &zone->raw); */
19248 isc_refcount_increment(&raw->erefs);
19249 zone->raw = raw;
19250
19251 /* dns_zone_iattach(zone, &raw->secure); */
19252 zone_iattach(zone, &raw->secure);
19253
19254 isc_task_attach(zone->task, &raw->task);
19255 isc_task_attach(zone->loadtask, &raw->loadtask);
19256
19257 ISC_LIST_APPEND(zmgr->zones, raw, link);
19258 raw->zmgr = zmgr;
19259 zmgr->refs++;
19260
19261 unlock:
19262 UNLOCK_ZONE(raw);
19263 UNLOCK_ZONE(zone);
19264 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
19265 return (result);
19266 }
19267
19268 void
19269 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
19270 REQUIRE(DNS_ZONE_VALID(zone));
19271 REQUIRE(raw != NULL && *raw == NULL);
19272
19273 LOCK(&zone->lock);
19274 INSIST(zone != zone->raw);
19275 if (zone->raw != NULL)
19276 dns_zone_attach(zone->raw, raw);
19277 UNLOCK(&zone->lock);
19278 }
19279
19280 struct keydone {
19281 isc_event_t event;
19282 bool all;
19283 unsigned char data[5];
19284 };
19285
19286 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
19287
19288 static void
19289 keydone(isc_task_t *task, isc_event_t *event) {
19290 const char *me = "keydone";
19291 bool commit = false;
19292 isc_result_t result;
19293 dns_rdata_t rdata = DNS_RDATA_INIT;
19294 dns_dbversion_t *oldver = NULL, *newver = NULL;
19295 dns_zone_t *zone;
19296 dns_db_t *db = NULL;
19297 dns_dbnode_t *node = NULL;
19298 dns_rdataset_t rdataset;
19299 dns_diff_t diff;
19300 struct keydone *kd = (struct keydone *)event;
19301 dns_update_log_t log = { update_log_cb, NULL };
19302 bool clear_pending = false;
19303
19304 UNUSED(task);
19305
19306 zone = event->ev_arg;
19307 INSIST(DNS_ZONE_VALID(zone));
19308
19309 ENTER;
19310
19311 dns_rdataset_init(&rdataset);
19312 dns_diff_init(zone->mctx, &diff);
19313
19314 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19315 if (zone->db != NULL) {
19316 dns_db_attach(zone->db, &db);
19317 }
19318 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19319 if (db == NULL) {
19320 goto failure;
19321 }
19322
19323 dns_db_currentversion(db, &oldver);
19324 result = dns_db_newversion(db, &newver);
19325 if (result != ISC_R_SUCCESS) {
19326 dnssec_log(zone, ISC_LOG_ERROR,
19327 "keydone:dns_db_newversion -> %s",
19328 dns_result_totext(result));
19329 goto failure;
19330 }
19331
19332 result = dns_db_getoriginnode(db, &node);
19333 if (result != ISC_R_SUCCESS) {
19334 goto failure;
19335 }
19336
19337 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
19338 dns_rdatatype_none, 0, &rdataset, NULL);
19339 if (result == ISC_R_NOTFOUND) {
19340 INSIST(!dns_rdataset_isassociated(&rdataset));
19341 goto failure;
19342 }
19343 if (result != ISC_R_SUCCESS) {
19344 INSIST(!dns_rdataset_isassociated(&rdataset));
19345 goto failure;
19346 }
19347
19348 for (result = dns_rdataset_first(&rdataset);
19349 result == ISC_R_SUCCESS;
19350 result = dns_rdataset_next(&rdataset))
19351 {
19352 bool found = false;
19353
19354 dns_rdataset_current(&rdataset, &rdata);
19355
19356 if (kd->all) {
19357 if (rdata.length == 5 && rdata.data[0] != 0 &&
19358 rdata.data[3] == 0 && rdata.data[4] == 1)
19359 {
19360 found = true;
19361 } else if (rdata.data[0] == 0 &&
19362 (rdata.data[2] & PENDINGFLAGS) != 0)
19363 {
19364 found = true;
19365 clear_pending = true;
19366 }
19367 } else if (rdata.length == 5 &&
19368 memcmp(rdata.data, kd->data, 5) == 0)
19369 {
19370 found = true;
19371 }
19372
19373 if (found) {
19374 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
19375 &zone->origin, rdataset.ttl,
19376 &rdata));
19377 }
19378 dns_rdata_reset(&rdata);
19379 }
19380
19381 if (!ISC_LIST_EMPTY(diff.tuples)) {
19382 /* Write changes to journal file. */
19383 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
19384 zone->updatemethod));
19385
19386 result = dns_update_signatures(&log, zone, db,
19387 oldver, newver, &diff,
19388 zone->sigvalidityinterval);
19389 if (!clear_pending) {
19390 CHECK(result);
19391 }
19392
19393 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
19394 commit = true;
19395
19396 LOCK_ZONE(zone);
19397 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
19398 zone_needdump(zone, 30);
19399 UNLOCK_ZONE(zone);
19400 }
19401
19402 failure:
19403 if (dns_rdataset_isassociated(&rdataset)) {
19404 dns_rdataset_disassociate(&rdataset);
19405 }
19406 if (db != NULL) {
19407 if (node != NULL) {
19408 dns_db_detachnode(db, &node);
19409 }
19410 if (oldver != NULL) {
19411 dns_db_closeversion(db, &oldver, false);
19412 }
19413 if (newver != NULL) {
19414 dns_db_closeversion(db, &newver, commit);
19415 }
19416 dns_db_detach(&db);
19417 }
19418 dns_diff_clear(&diff);
19419 isc_event_free(&event);
19420 dns_zone_idetach(&zone);
19421
19422 INSIST(oldver == NULL);
19423 INSIST(newver == NULL);
19424 }
19425
19426 isc_result_t
19427 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
19428 isc_result_t result = ISC_R_SUCCESS;
19429 isc_event_t *e;
19430 isc_buffer_t b;
19431 dns_zone_t *dummy = NULL;
19432 struct keydone *kd;
19433
19434 REQUIRE(DNS_ZONE_VALID(zone));
19435
19436 LOCK_ZONE(zone);
19437
19438 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
19439 zone, sizeof(struct keydone));
19440 if (e == NULL) {
19441 result = ISC_R_NOMEMORY;
19442 goto failure;
19443 }
19444
19445 kd = (struct keydone *) e;
19446 if (strcasecmp(keystr, "all") == 0) {
19447 kd->all = true;
19448 } else {
19449 isc_textregion_t r;
19450 const char *algstr;
19451 dns_keytag_t keyid;
19452 dns_secalg_t alg;
19453 size_t n;
19454
19455 kd->all = false;
19456
19457 n = sscanf(keystr, "%hu/", &keyid);
19458 if (n == 0U) {
19459 CHECK(ISC_R_FAILURE);
19460 }
19461
19462 algstr = strchr(keystr, '/');
19463 if (algstr != NULL) {
19464 algstr++;
19465 } else {
19466 CHECK(ISC_R_FAILURE);
19467 }
19468
19469 n = sscanf(algstr, "%hhu", &alg);
19470 if (n == 0U) {
19471 DE_CONST(algstr, r.base);
19472 r.length = strlen(algstr);
19473 CHECK(dns_secalg_fromtext(&alg, &r));
19474 }
19475
19476 /* construct a private-type rdata */
19477 isc_buffer_init(&b, kd->data, sizeof(kd->data));
19478 isc_buffer_putuint8(&b, alg);
19479 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
19480 isc_buffer_putuint8(&b, (keyid & 0xff));
19481 isc_buffer_putuint8(&b, 0);
19482 isc_buffer_putuint8(&b, 1);
19483 }
19484
19485 zone_iattach(zone, &dummy);
19486 isc_task_send(zone->task, &e);
19487
19488 failure:
19489 if (e != NULL) {
19490 isc_event_free(&e);
19491 }
19492 UNLOCK_ZONE(zone);
19493 return (result);
19494 }
19495
19496 /*
19497 * Called from the zone task's queue after the relevant event is posted by
19498 * dns_zone_setnsec3param().
19499 */
19500 static void
19501 setnsec3param(isc_task_t *task, isc_event_t *event) {
19502 const char *me = "setnsec3param";
19503 dns_zone_t *zone = event->ev_arg;
19504
19505 INSIST(DNS_ZONE_VALID(zone));
19506
19507 UNUSED(task);
19508
19509 ENTER;
19510
19511 /*
19512 * If receive_secure_serial is still processing or we have a
19513 * queued event append rss_post queue.
19514 */
19515 if (zone->rss_newver != NULL ||
19516 ISC_LIST_HEAD(zone->rss_post) != NULL)
19517 {
19518 /*
19519 * Wait for receive_secure_serial() to finish processing.
19520 */
19521 ISC_LIST_APPEND(zone->rss_post, event, ev_link);
19522 } else {
19523 rss_post(zone, event);
19524 }
19525 dns_zone_idetach(&zone);
19526 }
19527
19528 /*
19529 * Check whether NSEC3 chain addition or removal specified by the private-type
19530 * record passed with the event was already queued (or even fully performed).
19531 * If not, modify the relevant private-type records at the zone apex and call
19532 * resume_addnsec3chain().
19533 */
19534 static void
19535 rss_post(dns_zone_t *zone, isc_event_t *event) {
19536 const char *me = "rss_post";
19537 bool commit = false;
19538 isc_result_t result;
19539 dns_dbversion_t *oldver = NULL, *newver = NULL;
19540 dns_db_t *db = NULL;
19541 dns_dbnode_t *node = NULL;
19542 dns_rdataset_t prdataset, nrdataset;
19543 dns_diff_t diff;
19544 struct np3event *npe = (struct np3event *)event;
19545 nsec3param_t *np;
19546 dns_update_log_t log = { update_log_cb, NULL };
19547 dns_rdata_t rdata;
19548 bool nseconly;
19549 bool exists = false;
19550
19551 ENTER;
19552
19553 np = &npe->params;
19554
19555 dns_rdataset_init(&prdataset);
19556 dns_rdataset_init(&nrdataset);
19557 dns_diff_init(zone->mctx, &diff);
19558
19559 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19560 if (zone->db != NULL) {
19561 dns_db_attach(zone->db, &db);
19562 }
19563 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19564 if (db == NULL) {
19565 goto failure;
19566 }
19567
19568 dns_db_currentversion(db, &oldver);
19569 result = dns_db_newversion(db, &newver);
19570 if (result != ISC_R_SUCCESS) {
19571 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19572 dnssec_log(zone, ISC_LOG_ERROR,
19573 "setnsec3param:dns_db_newversion -> %s",
19574 dns_result_totext(result));
19575 goto failure;
19576 }
19577
19578 CHECK(dns_db_getoriginnode(db, &node));
19579
19580 /*
19581 * Does a private-type record already exist for this chain?
19582 */
19583 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
19584 dns_rdatatype_none, 0, &prdataset, NULL);
19585 if (result == ISC_R_SUCCESS) {
19586 for (result = dns_rdataset_first(&prdataset);
19587 result == ISC_R_SUCCESS;
19588 result = dns_rdataset_next(&prdataset))
19589 {
19590 dns_rdata_init(&rdata);
19591 dns_rdataset_current(&prdataset, &rdata);
19592
19593 if (np->length == rdata.length &&
19594 memcmp(rdata.data, np->data, np->length) == 0)
19595 {
19596 exists = true;
19597 break;
19598 }
19599 }
19600 } else if (result != ISC_R_NOTFOUND) {
19601 INSIST(!dns_rdataset_isassociated(&prdataset));
19602 goto failure;
19603 }
19604
19605 /*
19606 * Does the chain already exist?
19607 */
19608 result = dns_db_findrdataset(db, node, newver,
19609 dns_rdatatype_nsec3param,
19610 dns_rdatatype_none, 0, &nrdataset, NULL);
19611 if (result == ISC_R_SUCCESS) {
19612 for (result = dns_rdataset_first(&nrdataset);
19613 result == ISC_R_SUCCESS;
19614 result = dns_rdataset_next(&nrdataset))
19615 {
19616 dns_rdata_init(&rdata);
19617 dns_rdataset_current(&nrdataset, &rdata);
19618
19619 if (np->length == (rdata.length + 1) &&
19620 memcmp(rdata.data, np->data + 1,
19621 np->length - 1) == 0)
19622 {
19623 exists = true;
19624 break;
19625 }
19626 }
19627 } else if (result != ISC_R_NOTFOUND) {
19628 INSIST(!dns_rdataset_isassociated(&nrdataset));
19629 goto failure;
19630 }
19631
19632
19633 /*
19634 * We need to remove any existing NSEC3 chains if the supplied NSEC3
19635 * parameters are supposed to replace the current ones or if we are
19636 * switching to NSEC.
19637 */
19638 if (!exists && np->replace && (np->length != 0 || np->nsec)) {
19639 CHECK(dns_nsec3param_deletechains(db, newver, zone,
19640 !np->nsec, &diff));
19641 }
19642
19643 if (!exists && np->length != 0) {
19644 /*
19645 * We're creating an NSEC3 chain. Add the private-type record
19646 * passed in the event handler's argument to the zone apex.
19647 *
19648 * If the zone is not currently capable of supporting an NSEC3
19649 * chain (due to the DNSKEY RRset at the zone apex not existing
19650 * or containing at least one key using an NSEC-only
19651 * algorithm), add the INITIAL flag, so these parameters can be
19652 * used later when NSEC3 becomes available.
19653 */
19654 dns_rdata_init(&rdata);
19655
19656 np->data[2] |= DNS_NSEC3FLAG_CREATE;
19657 result = dns_nsec_nseconly(db, newver, &nseconly);
19658 if (result == ISC_R_NOTFOUND || nseconly) {
19659 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
19660 }
19661
19662 rdata.length = np->length;
19663 rdata.data = np->data;
19664 rdata.type = zone->privatetype;
19665 rdata.rdclass = zone->rdclass;
19666 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
19667 &zone->origin, 0, &rdata));
19668 }
19669
19670 /*
19671 * If we changed anything in the zone, write changes to journal file
19672 * and set commit to true so that resume_addnsec3chain() will be
19673 * called below in order to kick off adding/removing relevant NSEC3
19674 * records.
19675 */
19676 if (!ISC_LIST_EMPTY(diff.tuples)) {
19677 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
19678 zone->updatemethod));
19679 result = dns_update_signatures(&log, zone, db,
19680 oldver, newver, &diff,
19681 zone->sigvalidityinterval);
19682 if (result != ISC_R_NOTFOUND) {
19683 CHECK(result);
19684 }
19685 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
19686 commit = true;
19687
19688 LOCK_ZONE(zone);
19689 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
19690 zone_needdump(zone, 30);
19691 UNLOCK_ZONE(zone);
19692 }
19693
19694 failure:
19695 if (dns_rdataset_isassociated(&prdataset)) {
19696 dns_rdataset_disassociate(&prdataset);
19697 }
19698 if (dns_rdataset_isassociated(&nrdataset)) {
19699 dns_rdataset_disassociate(&nrdataset);
19700 }
19701 if (node != NULL) {
19702 dns_db_detachnode(db, &node);
19703 }
19704 if (oldver != NULL) {
19705 dns_db_closeversion(db, &oldver, false);
19706 }
19707 if (newver != NULL) {
19708 dns_db_closeversion(db, &newver, commit);
19709 }
19710 if (db != NULL) {
19711 dns_db_detach(&db);
19712 }
19713 if (commit) {
19714 LOCK_ZONE(zone);
19715 resume_addnsec3chain(zone);
19716 UNLOCK_ZONE(zone);
19717 }
19718 dns_diff_clear(&diff);
19719 isc_event_free(&event);
19720
19721 INSIST(oldver == NULL);
19722 INSIST(newver == NULL);
19723 }
19724
19725 /*
19726 * Called when an "rndc signing -nsec3param ..." command is received.
19727 *
19728 * Allocate and prepare an nsec3param_t structure which holds information about
19729 * the NSEC3 changes requested for the zone:
19730 *
19731 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
19732 * field of the structure to true and the "replace" field to the value
19733 * of the "replace" argument, leaving other fields initialized to zeros, to
19734 * signal that the zone should be signed using NSEC instead of NSEC3,
19735 *
19736 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
19737 * the zone apex, convert it to a private-type record and store the latter
19738 * in the "data" field of the nsec3param_t structure.
19739 *
19740 * Once the nsec3param_t structure is prepared, post an event to the zone's
19741 * task which will cause setnsec3param() to be called with the prepared
19742 * structure passed as an argument.
19743 */
19744 isc_result_t
19745 dns_zone_setnsec3param(dns_zone_t *zone, uint8_t hash, uint8_t flags,
19746 uint16_t iter, uint8_t saltlen,
19747 unsigned char *salt, bool replace)
19748 {
19749 isc_result_t result = ISC_R_SUCCESS;
19750 dns_rdata_nsec3param_t param;
19751 dns_rdata_t nrdata = DNS_RDATA_INIT;
19752 dns_rdata_t prdata = DNS_RDATA_INIT;
19753 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
19754 struct np3event *npe;
19755 nsec3param_t *np;
19756 dns_zone_t *dummy = NULL;
19757 isc_buffer_t b;
19758 isc_event_t *e;
19759
19760 REQUIRE(DNS_ZONE_VALID(zone));
19761 REQUIRE(salt != NULL);
19762
19763 LOCK_ZONE(zone);
19764
19765 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
19766 setnsec3param, zone, sizeof(struct np3event));
19767 if (e == NULL) {
19768 result = ISC_R_NOMEMORY;
19769 goto failure;
19770 }
19771
19772 npe = (struct np3event *) e;
19773 np = &npe->params;
19774
19775 np->replace = replace;
19776 if (hash == 0) {
19777 np->length = 0;
19778 np->nsec = true;
19779 } else {
19780 param.common.rdclass = zone->rdclass;
19781 param.common.rdtype = dns_rdatatype_nsec3param;
19782 ISC_LINK_INIT(¶m.common, link);
19783 param.mctx = NULL;
19784 param.hash = hash;
19785 param.flags = flags;
19786 param.iterations = iter;
19787 param.salt_length = saltlen;
19788 param.salt = salt;
19789 isc_buffer_init(&b, nbuf, sizeof(nbuf));
19790 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
19791 dns_rdatatype_nsec3param,
19792 ¶m, &b));
19793 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
19794 np->data, sizeof(np->data));
19795 np->length = prdata.length;
19796 np->nsec = false;
19797 }
19798
19799 /*
19800 * setnsec3param() will silently return early if the zone does not yet
19801 * have a database. Prevent that by queueing the event up if zone->db
19802 * is NULL. All events queued here are subsequently processed by
19803 * receive_secure_db() if it ever gets called or simply freed by
19804 * zone_free() otherwise.
19805 */
19806 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19807 if (zone->db != NULL) {
19808 zone_iattach(zone, &dummy);
19809 isc_task_send(zone->task, &e);
19810 } else {
19811 ISC_LIST_APPEND(zone->setnsec3param_queue, e, ev_link);
19812 e = NULL;
19813 }
19814 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19815
19816 failure:
19817 if (e != NULL) {
19818 isc_event_free(&e);
19819 }
19820 UNLOCK_ZONE(zone);
19821 return (result);
19822 }
19823
19824 isc_result_t
19825 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
19826 REQUIRE(DNS_ZONE_VALID(zone));
19827 REQUIRE(loadtime != NULL);
19828
19829 LOCK_ZONE(zone);
19830 *loadtime = zone->loadtime;
19831 UNLOCK_ZONE(zone);
19832 return (ISC_R_SUCCESS);
19833 }
19834
19835 isc_result_t
19836 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
19837 REQUIRE(DNS_ZONE_VALID(zone));
19838 REQUIRE(expiretime != NULL);
19839
19840 LOCK_ZONE(zone);
19841 *expiretime = zone->expiretime;
19842 UNLOCK_ZONE(zone);
19843 return (ISC_R_SUCCESS);
19844 }
19845
19846 isc_result_t
19847 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
19848 REQUIRE(DNS_ZONE_VALID(zone));
19849 REQUIRE(refreshtime != NULL);
19850
19851 LOCK_ZONE(zone);
19852 *refreshtime = zone->refreshtime;
19853 UNLOCK_ZONE(zone);
19854 return (ISC_R_SUCCESS);
19855 }
19856
19857 isc_result_t
19858 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
19859 REQUIRE(DNS_ZONE_VALID(zone));
19860 REQUIRE(refreshkeytime != NULL);
19861
19862 LOCK_ZONE(zone);
19863 *refreshkeytime = zone->refreshkeytime;
19864 UNLOCK_ZONE(zone);
19865 return (ISC_R_SUCCESS);
19866 }
19867
19868 unsigned int
19869 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
19870 dns_include_t *include;
19871 char **array = NULL;
19872 unsigned int n = 0;
19873
19874 REQUIRE(DNS_ZONE_VALID(zone));
19875 REQUIRE(includesp != NULL && *includesp == NULL);
19876
19877 LOCK_ZONE(zone);
19878 if (zone->nincludes == 0)
19879 goto done;
19880
19881 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
19882 if (array == NULL)
19883 goto done;
19884 for (include = ISC_LIST_HEAD(zone->includes);
19885 include != NULL;
19886 include = ISC_LIST_NEXT(include, link)) {
19887 INSIST(n < zone->nincludes);
19888 array[n++] = isc_mem_strdup(zone->mctx, include->name);
19889 }
19890 INSIST(n == zone->nincludes);
19891 *includesp = array;
19892
19893 done:
19894 UNLOCK_ZONE(zone);
19895 return (n);
19896 }
19897
19898 void
19899 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
19900 REQUIRE(DNS_ZONE_VALID(zone));
19901
19902 zone->statlevel = level;
19903 }
19904
19905 dns_zonestat_level_t
19906 dns_zone_getstatlevel(dns_zone_t *zone) {
19907 REQUIRE(DNS_ZONE_VALID(zone));
19908
19909 return (zone->statlevel);
19910 }
19911
19912 static void
19913 setserial(isc_task_t *task, isc_event_t *event) {
19914 uint32_t oldserial, desired;
19915 const char *me = "setserial";
19916 bool commit = false;
19917 isc_result_t result;
19918 dns_dbversion_t *oldver = NULL, *newver = NULL;
19919 dns_zone_t *zone;
19920 dns_db_t *db = NULL;
19921 dns_diff_t diff;
19922 struct ssevent *sse = (struct ssevent *)event;
19923 dns_update_log_t log = { update_log_cb, NULL };
19924 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
19925
19926 UNUSED(task);
19927
19928 zone = event->ev_arg;
19929 INSIST(DNS_ZONE_VALID(zone));
19930
19931 ENTER;
19932
19933 if (zone->update_disabled)
19934 goto failure;
19935
19936 desired = sse->serial;
19937
19938 dns_diff_init(zone->mctx, &diff);
19939
19940 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19941 if (zone->db != NULL)
19942 dns_db_attach(zone->db, &db);
19943 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19944 if (db == NULL)
19945 goto failure;
19946
19947 dns_db_currentversion(db, &oldver);
19948 result = dns_db_newversion(db, &newver);
19949 if (result != ISC_R_SUCCESS) {
19950 dns_zone_log(zone, ISC_LOG_ERROR,
19951 "setserial:dns_db_newversion -> %s",
19952 dns_result_totext(result));
19953 goto failure;
19954 }
19955
19956 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
19957 DNS_DIFFOP_DEL, &oldtuple));
19958 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
19959 newtuple->op = DNS_DIFFOP_ADD;
19960
19961 oldserial = dns_soa_getserial(&oldtuple->rdata);
19962 if (desired == 0U)
19963 desired = 1;
19964 if (!isc_serial_gt(desired, oldserial)) {
19965 if (desired != oldserial)
19966 dns_zone_log(zone, ISC_LOG_INFO,
19967 "setserial: desired serial (%u) "
19968 "out of range (%u-%u)", desired,
19969 oldserial + 1, (oldserial + 0x7fffffff));
19970 goto failure;
19971 }
19972
19973 dns_soa_setserial(desired, &newtuple->rdata);
19974 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
19975 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
19976 result = dns_update_signatures(&log, zone, db,
19977 oldver, newver, &diff,
19978 zone->sigvalidityinterval);
19979 if (result != ISC_R_NOTFOUND)
19980 CHECK(result);
19981
19982 /* Write changes to journal file. */
19983 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
19984 commit = true;
19985
19986 LOCK_ZONE(zone);
19987 zone_needdump(zone, 30);
19988 UNLOCK_ZONE(zone);
19989
19990 failure:
19991 if (oldtuple != NULL)
19992 dns_difftuple_free(&oldtuple);
19993 if (newtuple != NULL)
19994 dns_difftuple_free(&newtuple);
19995 if (oldver != NULL)
19996 dns_db_closeversion(db, &oldver, false);
19997 if (newver != NULL)
19998 dns_db_closeversion(db, &newver, commit);
19999 if (db != NULL)
20000 dns_db_detach(&db);
20001 dns_diff_clear(&diff);
20002 isc_event_free(&event);
20003 dns_zone_idetach(&zone);
20004
20005 INSIST(oldver == NULL);
20006 INSIST(newver == NULL);
20007 }
20008
20009 isc_result_t
20010 dns_zone_setserial(dns_zone_t *zone, uint32_t serial) {
20011 isc_result_t result = ISC_R_SUCCESS;
20012 dns_zone_t *dummy = NULL;
20013 isc_event_t *e = NULL;
20014 struct ssevent *sse;
20015
20016 REQUIRE(DNS_ZONE_VALID(zone));
20017
20018 LOCK_ZONE(zone);
20019
20020 if (!inline_secure(zone)) {
20021 if (!dns_zone_isdynamic(zone, true)) {
20022 result = DNS_R_NOTDYNAMIC;
20023 goto failure;
20024 }
20025 }
20026
20027 if (zone->update_disabled) {
20028 result = DNS_R_FROZEN;
20029 goto failure;
20030 }
20031
20032 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
20033 setserial, zone, sizeof(struct ssevent));
20034 if (e == NULL) {
20035 result = ISC_R_NOMEMORY;
20036 goto failure;
20037 }
20038
20039 sse = (struct ssevent *)e;
20040 sse->serial = serial;
20041
20042 zone_iattach(zone, &dummy);
20043 isc_task_send(zone->task, &e);
20044
20045 failure:
20046 if (e != NULL)
20047 isc_event_free(&e);
20048 UNLOCK_ZONE(zone);
20049 return (result);
20050 }
20051
20052 isc_stats_t *
20053 dns_zone_getgluecachestats(dns_zone_t *zone) {
20054 REQUIRE(DNS_ZONE_VALID(zone));
20055
20056 return (zone->gluecachestats);
20057 }
20058
20059 bool
20060 dns_zone_isloaded(const dns_zone_t *zone) {
20061 REQUIRE(DNS_ZONE_VALID(zone));
20062
20063 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED));
20064 }
20065
20066 isc_result_t
20067 dns_zone_verifydb(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver) {
20068 dns_dbversion_t *version = NULL;
20069 dns_keytable_t *secroots = NULL;
20070 isc_result_t result;
20071 dns_name_t *origin;
20072
20073 const char me[] = "dns_zone_verifydb";
20074 ENTER;
20075
20076 REQUIRE(DNS_ZONE_VALID(zone));
20077 REQUIRE(db != NULL);
20078
20079 if (dns_zone_gettype(zone) != dns_zone_mirror) {
20080 return (ISC_R_SUCCESS);
20081 }
20082
20083 if (ver == NULL) {
20084 dns_db_currentversion(db, &version);
20085 } else {
20086 version = ver;
20087 }
20088
20089 if (zone->view != NULL) {
20090 result = dns_view_getsecroots(zone->view, &secroots);
20091 if (result != ISC_R_SUCCESS) {
20092 goto done;
20093 }
20094 }
20095
20096 origin = dns_db_origin(db);
20097 result = dns_zoneverify_dnssec(zone, db, version, origin, secroots,
20098 zone->mctx, true, false);
20099
20100 done:
20101 if (secroots != NULL) {
20102 dns_keytable_detach(&secroots);
20103 }
20104
20105 if (ver == NULL) {
20106 dns_db_closeversion(db, &version, false);
20107 }
20108
20109 if (result != ISC_R_SUCCESS) {
20110 dnssec_log(zone, ISC_LOG_ERROR, "zone verification failed: %s",
20111 isc_result_totext(result));
20112 result = DNS_R_VERIFYFAILURE;
20113 }
20114
20115 return (result);
20116 }
20117