zone.c revision 1.2 1 /* $NetBSD: zone.c,v 1.2 2018/08/12 13:02:35 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <config.h>
17 #include <errno.h>
18
19 #include <isc/file.h>
20 #include <isc/hex.h>
21 #include <isc/mutex.h>
22 #include <isc/pool.h>
23 #include <isc/print.h>
24 #include <isc/random.h>
25 #include <isc/ratelimiter.h>
26 #include <isc/refcount.h>
27 #include <isc/rwlock.h>
28 #include <isc/serial.h>
29 #include <isc/stats.h>
30 #include <isc/stdtime.h>
31 #include <isc/strerror.h>
32 #include <isc/string.h>
33 #include <isc/taskpool.h>
34 #include <isc/thread.h>
35 #include <isc/timer.h>
36 #include <isc/util.h>
37
38 #include <dns/acl.h>
39 #include <dns/adb.h>
40 #include <dns/callbacks.h>
41 #include <dns/catz.h>
42 #include <dns/db.h>
43 #include <dns/dbiterator.h>
44 #include <dns/dlz.h>
45 #include <dns/dnssec.h>
46 #include <dns/events.h>
47 #include <dns/journal.h>
48 #include <dns/keydata.h>
49 #include <dns/keytable.h>
50 #include <dns/keyvalues.h>
51 #include <dns/log.h>
52 #include <dns/master.h>
53 #include <dns/masterdump.h>
54 #include <dns/message.h>
55 #include <dns/name.h>
56 #include <dns/nsec.h>
57 #include <dns/nsec3.h>
58 #include <dns/peer.h>
59 #include <dns/private.h>
60 #include <dns/rcode.h>
61 #include <dns/rdata.h>
62 #include <dns/rdataclass.h>
63 #include <dns/rdatalist.h>
64 #include <dns/rdataset.h>
65 #include <dns/rdatasetiter.h>
66 #include <dns/rdatastruct.h>
67 #include <dns/rdatatype.h>
68 #include <dns/request.h>
69 #include <dns/resolver.h>
70 #include <dns/result.h>
71 #include <dns/rriterator.h>
72 #include <dns/soa.h>
73 #include <dns/ssu.h>
74 #include <dns/stats.h>
75 #include <dns/time.h>
76 #include <dns/tsig.h>
77 #include <dns/update.h>
78 #include <dns/xfrin.h>
79 #include <dns/zone.h>
80 #include <dns/zt.h>
81
82 #include <dst/dst.h>
83
84 #include "zone_p.h"
85
86 #define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')
87 #define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)
88
89 #define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')
90 #define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
91
92 #define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')
93 #define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)
94
95 #define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')
96 #define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)
97
98 #define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')
99 #define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)
100
101 #define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')
102 #define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)
103
104 #define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')
105 #define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)
106
107 /*%
108 * Ensure 'a' is at least 'min' but not more than 'max'.
109 */
110 #define RANGE(a, min, max) \
111 (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))
112
113 #define NSEC3REMOVE(x) (((x) & DNS_NSEC3FLAG_REMOVE) != 0)
114
115 /*%
116 * Key flags
117 */
118 #define REVOKE(x) ((dst_key_flags(x) & DNS_KEYFLAG_REVOKE) != 0)
119 #define KSK(x) ((dst_key_flags(x) & DNS_KEYFLAG_KSK) != 0)
120 #define ALG(x) dst_key_alg(x)
121
122 /*
123 * Default values.
124 */
125 #define DNS_DEFAULT_IDLEIN 3600 /*%< 1 hour */
126 #define DNS_DEFAULT_IDLEOUT 3600 /*%< 1 hour */
127 #define MAX_XFER_TIME (2*3600) /*%< Documented default is 2 hours */
128 #define RESIGN_DELAY 3600 /*%< 1 hour */
129
130 #ifndef DNS_MAX_EXPIRE
131 #define DNS_MAX_EXPIRE 14515200 /*%< 24 weeks */
132 #endif
133
134 #ifndef DNS_DUMP_DELAY
135 #define DNS_DUMP_DELAY 900 /*%< 15 minutes */
136 #endif
137
138 typedef struct dns_notify dns_notify_t;
139 typedef struct dns_stub dns_stub_t;
140 typedef struct dns_load dns_load_t;
141 typedef struct dns_forward dns_forward_t;
142 typedef ISC_LIST(dns_forward_t) dns_forwardlist_t;
143 typedef struct dns_io dns_io_t;
144 typedef ISC_LIST(dns_io_t) dns_iolist_t;
145 typedef struct dns_signing dns_signing_t;
146 typedef ISC_LIST(dns_signing_t) dns_signinglist_t;
147 typedef struct dns_nsec3chain dns_nsec3chain_t;
148 typedef ISC_LIST(dns_nsec3chain_t) dns_nsec3chainlist_t;
149 typedef struct dns_keyfetch dns_keyfetch_t;
150 typedef struct dns_asyncload dns_asyncload_t;
151 typedef struct dns_include dns_include_t;
152
153 #define DNS_ZONE_CHECKLOCK
154 #ifdef DNS_ZONE_CHECKLOCK
155 #define LOCK_ZONE(z) \
156 do { LOCK(&(z)->lock); \
157 INSIST((z)->locked == ISC_FALSE); \
158 (z)->locked = ISC_TRUE; \
159 } while (/*CONSTCOND*/0)
160 #define UNLOCK_ZONE(z) \
161 do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (/*CONSTCOND*/0)
162 #define LOCKED_ZONE(z) ((z)->locked)
163 #define TRYLOCK_ZONE(result, z) \
164 do { \
165 result = isc_mutex_trylock(&(z)->lock); \
166 if (result == ISC_R_SUCCESS) { \
167 INSIST((z)->locked == ISC_FALSE); \
168 (z)->locked = ISC_TRUE; \
169 } \
170 } while (/*CONSTCOND*/0)
171 #else
172 #define LOCK_ZONE(z) LOCK(&(z)->lock)
173 #define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)
174 #define LOCKED_ZONE(z) ISC_TRUE
175 #define TRYLOCK_ZONE(result, z) \
176 do { result = isc_mutex_trylock(&(z)->lock); } while (/*CONSTCOND*/0)
177 #endif
178
179 #ifdef ISC_RWLOCK_USEATOMIC
180 #define ZONEDB_INITLOCK(l) isc_rwlock_init((l), 0, 0)
181 #define ZONEDB_DESTROYLOCK(l) isc_rwlock_destroy(l)
182 #define ZONEDB_LOCK(l, t) RWLOCK((l), (t))
183 #define ZONEDB_UNLOCK(l, t) RWUNLOCK((l), (t))
184 #else
185 #define ZONEDB_INITLOCK(l) isc_mutex_init(l)
186 #define ZONEDB_DESTROYLOCK(l) DESTROYLOCK(l)
187 #define ZONEDB_LOCK(l, t) LOCK(l)
188 #define ZONEDB_UNLOCK(l, t) UNLOCK(l)
189 #endif
190
191 #ifdef ENABLE_AFL
192 extern isc_boolean_t dns_fuzzing_resolver;
193 #endif
194
195 struct dns_zone {
196 /* Unlocked */
197 unsigned int magic;
198 isc_mutex_t lock;
199 #ifdef DNS_ZONE_CHECKLOCK
200 isc_boolean_t locked;
201 #endif
202 isc_mem_t *mctx;
203 isc_refcount_t erefs;
204
205 #ifdef ISC_RWLOCK_USEATOMIC
206 isc_rwlock_t dblock;
207 #else
208 isc_mutex_t dblock;
209 #endif
210 dns_db_t *db; /* Locked by dblock */
211
212 /* Locked */
213 dns_zonemgr_t *zmgr;
214 ISC_LINK(dns_zone_t) link; /* Used by zmgr. */
215 isc_timer_t *timer;
216 unsigned int irefs;
217 dns_name_t origin;
218 char *masterfile;
219 ISC_LIST(dns_include_t) includes; /* Include files */
220 ISC_LIST(dns_include_t) newincludes; /* Loading */
221 unsigned int nincludes;
222 dns_masterformat_t masterformat;
223 const dns_master_style_t *masterstyle;
224 char *journal;
225 isc_int32_t journalsize;
226 dns_rdataclass_t rdclass;
227 dns_zonetype_t type;
228 unsigned int flags;
229 unsigned int options;
230 unsigned int options2;
231 unsigned int db_argc;
232 char **db_argv;
233 isc_time_t expiretime;
234 isc_time_t refreshtime;
235 isc_time_t dumptime;
236 isc_time_t loadtime;
237 isc_time_t notifytime;
238 isc_time_t resigntime;
239 isc_time_t keywarntime;
240 isc_time_t signingtime;
241 isc_time_t nsec3chaintime;
242 isc_time_t refreshkeytime;
243 isc_uint32_t refreshkeyinterval;
244 isc_uint32_t refreshkeycount;
245 isc_uint32_t refresh;
246 isc_uint32_t retry;
247 isc_uint32_t expire;
248 isc_uint32_t minimum;
249 isc_stdtime_t key_expiry;
250 isc_stdtime_t log_key_expired_timer;
251 char *keydirectory;
252
253 isc_uint32_t maxrefresh;
254 isc_uint32_t minrefresh;
255 isc_uint32_t maxretry;
256 isc_uint32_t minretry;
257
258 isc_uint32_t maxrecords;
259
260 isc_sockaddr_t *masters;
261 isc_dscp_t *masterdscps;
262 dns_name_t **masterkeynames;
263 isc_boolean_t *mastersok;
264 unsigned int masterscnt;
265 unsigned int curmaster;
266 isc_sockaddr_t masteraddr;
267 dns_notifytype_t notifytype;
268 isc_sockaddr_t *notify;
269 dns_name_t **notifykeynames;
270 isc_dscp_t *notifydscp;
271 unsigned int notifycnt;
272 isc_sockaddr_t notifyfrom;
273 isc_task_t *task;
274 isc_task_t *loadtask;
275 isc_sockaddr_t notifysrc4;
276 isc_sockaddr_t notifysrc6;
277 isc_sockaddr_t xfrsource4;
278 isc_sockaddr_t xfrsource6;
279 isc_sockaddr_t altxfrsource4;
280 isc_sockaddr_t altxfrsource6;
281 isc_sockaddr_t sourceaddr;
282 isc_dscp_t notifysrc4dscp;
283 isc_dscp_t notifysrc6dscp;
284 isc_dscp_t xfrsource4dscp;
285 isc_dscp_t xfrsource6dscp;
286 isc_dscp_t altxfrsource4dscp;
287 isc_dscp_t altxfrsource6dscp;
288 dns_xfrin_ctx_t *xfr; /* task locked */
289 dns_tsigkey_t *tsigkey; /* key used for xfr */
290 /* Access Control Lists */
291 dns_acl_t *update_acl;
292 dns_acl_t *forward_acl;
293 dns_acl_t *notify_acl;
294 dns_acl_t *query_acl;
295 dns_acl_t *queryon_acl;
296 dns_acl_t *xfr_acl;
297 isc_boolean_t update_disabled;
298 isc_boolean_t zero_no_soa_ttl;
299 dns_severity_t check_names;
300 ISC_LIST(dns_notify_t) notifies;
301 dns_request_t *request;
302 dns_loadctx_t *lctx;
303 dns_io_t *readio;
304 dns_dumpctx_t *dctx;
305 dns_io_t *writeio;
306 isc_uint32_t maxxfrin;
307 isc_uint32_t maxxfrout;
308 isc_uint32_t idlein;
309 isc_uint32_t idleout;
310 isc_event_t ctlevent;
311 dns_ssutable_t *ssutable;
312 isc_uint32_t sigvalidityinterval;
313 isc_uint32_t sigresigninginterval;
314 dns_view_t *view;
315 dns_view_t *prev_view;
316 dns_checkmxfunc_t checkmx;
317 dns_checksrvfunc_t checksrv;
318 dns_checknsfunc_t checkns;
319 /*%
320 * Zones in certain states such as "waiting for zone transfer"
321 * or "zone transfer in progress" are kept on per-state linked lists
322 * in the zone manager using the 'statelink' field. The 'statelist'
323 * field points at the list the zone is currently on. It the zone
324 * is not on any such list, statelist is NULL.
325 */
326 ISC_LINK(dns_zone_t) statelink;
327 dns_zonelist_t *statelist;
328 /*%
329 * Statistics counters about zone management.
330 */
331 isc_stats_t *stats;
332 /*%
333 * Optional per-zone statistics counters. Counted outside of this
334 * module.
335 */
336 dns_zonestat_level_t statlevel;
337 isc_boolean_t requeststats_on;
338 isc_stats_t *requeststats;
339 dns_stats_t *rcvquerystats;
340 isc_uint32_t notifydelay;
341 dns_isselffunc_t isself;
342 void *isselfarg;
343
344 char * strnamerd;
345 char * strname;
346 char * strrdclass;
347 char * strviewname;
348
349 /*%
350 * Serial number for deferred journal compaction.
351 */
352 isc_uint32_t compact_serial;
353 /*%
354 * Keys that are signing the zone for the first time.
355 */
356 dns_signinglist_t signing;
357 dns_nsec3chainlist_t nsec3chain;
358 /*%
359 * Signing / re-signing quantum stopping parameters.
360 */
361 isc_uint32_t signatures;
362 isc_uint32_t nodes;
363 dns_rdatatype_t privatetype;
364
365 /*%
366 * Autosigning/key-maintenance options
367 */
368 isc_uint32_t keyopts;
369
370 /*%
371 * True if added by "rndc addzone"
372 */
373 isc_boolean_t added;
374
375 /*%
376 * True if added by automatically by named.
377 */
378 isc_boolean_t automatic;
379
380 /*%
381 * response policy data to be relayed to the database
382 */
383 dns_rpz_zones_t *rpzs;
384 dns_rpz_num_t rpz_num;
385
386 /*%
387 * catalog zone data
388 */
389 dns_catz_zones_t *catzs;
390
391 /*%
392 * parent catalog zone
393 */
394 dns_catz_zone_t *parentcatz;
395
396 /*%
397 * Serial number update method.
398 */
399 dns_updatemethod_t updatemethod;
400
401 /*%
402 * whether ixfr is requested
403 */
404 isc_boolean_t requestixfr;
405
406 /*%
407 * whether EDNS EXPIRE is requested
408 */
409 isc_boolean_t requestexpire;
410
411 /*%
412 * Outstanding forwarded UPDATE requests.
413 */
414 dns_forwardlist_t forwards;
415
416 dns_zone_t *raw;
417 dns_zone_t *secure;
418
419 isc_boolean_t sourceserialset;
420 isc_uint32_t sourceserial;
421
422 /*%
423 * maximum zone ttl
424 */
425 dns_ttl_t maxttl;
426
427 /*
428 * Inline zone signing state.
429 */
430 dns_diff_t rss_diff;
431 isc_eventlist_t rss_events;
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 = ISC_FALSE; \
447 } while (/*CONSTCOND*/0)
448
449 #define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))
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_ZONE_OPTION2(z,o) (((z)->options2 & (o)) != 0)
505 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
506
507 /* Flags for zone_load() */
508 #define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */
509 #define DNS_ZONELOADFLAG_THAW 0x00000002U /* Thaw the zone on successful
510 load. */
511
512 #define UNREACH_CHACHE_SIZE 10U
513 #define UNREACH_HOLD_TIME 600 /* 10 minutes */
514
515 #define CHECK(op) \
516 do { result = (op); \
517 if (result != ISC_R_SUCCESS) goto failure; \
518 } while (/*CONSTCOND*/0)
519
520 struct dns_unreachable {
521 isc_sockaddr_t remote;
522 isc_sockaddr_t local;
523 isc_uint32_t expire;
524 isc_uint32_t last;
525 isc_uint32_t count;
526 };
527
528 struct dns_zonemgr {
529 unsigned int magic;
530 isc_mem_t * mctx;
531 int refs; /* Locked by rwlock */
532 isc_taskmgr_t * taskmgr;
533 isc_timermgr_t * timermgr;
534 isc_socketmgr_t * socketmgr;
535 isc_taskpool_t * zonetasks;
536 isc_taskpool_t * loadtasks;
537 isc_task_t * task;
538 isc_pool_t * mctxpool;
539 isc_ratelimiter_t * notifyrl;
540 isc_ratelimiter_t * refreshrl;
541 isc_ratelimiter_t * startupnotifyrl;
542 isc_ratelimiter_t * startuprefreshrl;
543 isc_rwlock_t rwlock;
544 isc_mutex_t iolock;
545 isc_rwlock_t urlock;
546
547 /* Locked by rwlock. */
548 dns_zonelist_t zones;
549 dns_zonelist_t waiting_for_xfrin;
550 dns_zonelist_t xfrin_in_progress;
551
552 /* Configuration data. */
553 isc_uint32_t transfersin;
554 isc_uint32_t transfersperns;
555 unsigned int notifyrate;
556 unsigned int startupnotifyrate;
557 unsigned int serialqueryrate;
558 unsigned int startupserialqueryrate;
559
560 /* Locked by iolock */
561 isc_uint32_t iolimit;
562 isc_uint32_t ioactive;
563 dns_iolist_t high;
564 dns_iolist_t low;
565
566 /* Locked by urlock. */
567 /* LRU cache */
568 struct dns_unreachable unreachable[UNREACH_CHACHE_SIZE];
569 };
570
571 /*%
572 * Hold notify state.
573 */
574 struct dns_notify {
575 unsigned int magic;
576 unsigned int flags;
577 isc_mem_t *mctx;
578 dns_zone_t *zone;
579 dns_adbfind_t *find;
580 dns_request_t *request;
581 dns_name_t ns;
582 isc_sockaddr_t dst;
583 dns_tsigkey_t *key;
584 isc_dscp_t dscp;
585 ISC_LINK(dns_notify_t) link;
586 isc_event_t *event;
587 };
588
589 #define DNS_NOTIFY_NOSOA 0x0001U
590 #define DNS_NOTIFY_STARTUP 0x0002U
591
592 /*%
593 * dns_stub holds state while performing a 'stub' transfer.
594 * 'db' is the zone's 'db' or a new one if this is the initial
595 * transfer.
596 */
597
598 struct dns_stub {
599 unsigned int magic;
600 isc_mem_t *mctx;
601 dns_zone_t *zone;
602 dns_db_t *db;
603 dns_dbversion_t *version;
604 };
605
606 /*%
607 * Hold load state.
608 */
609 struct dns_load {
610 unsigned int magic;
611 isc_mem_t *mctx;
612 dns_zone_t *zone;
613 dns_db_t *db;
614 isc_time_t loadtime;
615 dns_rdatacallbacks_t callbacks;
616 };
617
618 /*%
619 * Hold forward state.
620 */
621 struct dns_forward {
622 unsigned int magic;
623 isc_mem_t *mctx;
624 dns_zone_t *zone;
625 isc_buffer_t *msgbuf;
626 dns_request_t *request;
627 isc_uint32_t which;
628 isc_sockaddr_t addr;
629 dns_updatecallback_t callback;
630 void *callback_arg;
631 unsigned int options;
632 ISC_LINK(dns_forward_t) link;
633 };
634
635 /*%
636 * Hold IO request state.
637 */
638 struct dns_io {
639 unsigned int magic;
640 dns_zonemgr_t *zmgr;
641 isc_boolean_t high;
642 isc_task_t *task;
643 ISC_LINK(dns_io_t) link;
644 isc_event_t *event;
645 };
646
647 /*%
648 * Hold state for when we are signing a zone with a new
649 * DNSKEY as result of an update.
650 */
651 struct dns_signing {
652 unsigned int magic;
653 dns_db_t *db;
654 dns_dbiterator_t *dbiterator;
655 dns_secalg_t algorithm;
656 isc_uint16_t keyid;
657 isc_boolean_t deleteit;
658 isc_boolean_t done;
659 ISC_LINK(dns_signing_t) link;
660 };
661
662 struct dns_nsec3chain {
663 unsigned int magic;
664 dns_db_t *db;
665 dns_dbiterator_t *dbiterator;
666 dns_rdata_nsec3param_t nsec3param;
667 unsigned char salt[255];
668 isc_boolean_t done;
669 isc_boolean_t seen_nsec;
670 isc_boolean_t delete_nsec;
671 isc_boolean_t save_delete_nsec;
672 ISC_LINK(dns_nsec3chain_t) link;
673 };
674 /*%<
675 * 'dbiterator' contains a iterator for the database. If we are creating
676 * a NSEC3 chain only the non-NSEC3 nodes will be iterated. If we are
677 * removing a NSEC3 chain then both NSEC3 and non-NSEC3 nodes will be
678 * iterated.
679 *
680 * 'nsec3param' contains the parameters of the NSEC3 chain being created
681 * or removed.
682 *
683 * 'salt' is buffer space and is referenced via 'nsec3param.salt'.
684 *
685 * 'seen_nsec' will be set to true if, while iterating the zone to create a
686 * NSEC3 chain, a NSEC record is seen.
687 *
688 * 'delete_nsec' will be set to true if, at the completion of the creation
689 * of a NSEC3 chain, 'seen_nsec' is true. If 'delete_nsec' is true then we
690 * are in the process of deleting the NSEC chain.
691 *
692 * 'save_delete_nsec' is used to store the initial state of 'delete_nsec'
693 * so it can be recovered in the event of a error.
694 */
695
696 struct dns_keyfetch {
697 dns_fixedname_t name;
698 dns_rdataset_t keydataset;
699 dns_rdataset_t dnskeyset;
700 dns_rdataset_t dnskeysigset;
701 dns_zone_t *zone;
702 dns_db_t *db;
703 dns_fetch_t *fetch;
704 };
705
706 /*%
707 * Hold state for an asynchronous load
708 */
709 struct dns_asyncload {
710 dns_zone_t *zone;
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 queue_xfrin(dns_zone_t *zone);
745 static isc_result_t update_one_rr(dns_db_t *db, dns_dbversion_t *ver,
746 dns_diff_t *diff, dns_diffop_t op,
747 dns_name_t *name, dns_ttl_t ttl,
748 dns_rdata_t *rdata);
749 static void zone_unload(dns_zone_t *zone);
750 static void zone_expire(dns_zone_t *zone);
751 static void zone_iattach(dns_zone_t *source, dns_zone_t **target);
752 static void zone_idetach(dns_zone_t **zonep);
753 static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
754 isc_boolean_t dump);
755 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
756 static inline void zone_detachdb(dns_zone_t *zone);
757 static isc_result_t default_journal(dns_zone_t *zone);
758 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
759 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
760 isc_time_t loadtime, isc_result_t result);
761 static void zone_needdump(dns_zone_t *zone, unsigned int delay);
762 static void zone_shutdown(isc_task_t *, isc_event_t *);
763 static void zone_loaddone(void *arg, isc_result_t result);
764 static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone,
765 isc_time_t loadtime);
766 static void zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length);
767 static void zone_name_tostr(dns_zone_t *zone, char *buf, size_t length);
768 static void zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length);
769 static void zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length);
770 static isc_result_t zone_send_secureserial(dns_zone_t *zone,
771 isc_uint32_t serial);
772
773 #if 0
774 /* ondestroy example */
775 static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
776 #endif
777
778 static void refresh_callback(isc_task_t *, isc_event_t *);
779 static void stub_callback(isc_task_t *, isc_event_t *);
780 static void queue_soa_query(dns_zone_t *zone);
781 static void soa_query(isc_task_t *, isc_event_t *);
782 static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset,
783 dns_stub_t *stub);
784 static int message_count(dns_message_t *msg, dns_section_t section,
785 dns_rdatatype_t type);
786 static void notify_cancel(dns_zone_t *zone);
787 static void notify_find_address(dns_notify_t *notify);
788 static void notify_send(dns_notify_t *notify);
789 static isc_result_t notify_createmessage(dns_zone_t *zone,
790 unsigned int flags,
791 dns_message_t **messagep);
792 static void notify_done(isc_task_t *task, isc_event_t *event);
793 static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);
794 static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);
795 static void got_transfer_quota(isc_task_t *task, isc_event_t *event);
796 static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr,
797 dns_zone_t *zone);
798 static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);
799 static void zonemgr_free(dns_zonemgr_t *zmgr);
800 static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
801 isc_task_t *task, isc_taskaction_t action,
802 void *arg, dns_io_t **iop);
803 static void zonemgr_putio(dns_io_t **iop);
804 static void zonemgr_cancelio(dns_io_t *io);
805
806 static isc_result_t
807 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
808 unsigned int *soacount, isc_uint32_t *serial,
809 isc_uint32_t *refresh, isc_uint32_t *retry,
810 isc_uint32_t *expire, isc_uint32_t *minimum,
811 unsigned int *errors);
812
813 static void zone_freedbargs(dns_zone_t *zone);
814 static void forward_callback(isc_task_t *task, isc_event_t *event);
815 static void zone_saveunique(dns_zone_t *zone, const char *path,
816 const char *templat);
817 static void zone_maintenance(dns_zone_t *zone);
818 static void zone_notify(dns_zone_t *zone, isc_time_t *now);
819 static void dump_done(void *arg, isc_result_t result);
820 static isc_result_t zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
821 isc_uint16_t keyid,
822 isc_boolean_t deleteit);
823 static isc_result_t delete_nsec(dns_db_t *db, dns_dbversion_t *ver,
824 dns_dbnode_t *node, dns_name_t *name,
825 dns_diff_t *diff);
826 static void zone_rekey(dns_zone_t *zone);
827 static isc_result_t zone_send_securedb(dns_zone_t *zone, dns_db_t *db);
828 static void setrl(isc_ratelimiter_t *rl, unsigned int *rate,
829 unsigned int value);
830
831 #define ENTER zone_debuglog(zone, me, 1, "enter")
832
833 static const unsigned int dbargc_default = 1;
834 static const char *dbargv_default[] = { "rbt" };
835
836 #define DNS_ZONE_JITTER_ADD(a, b, c) \
837 do { \
838 isc_interval_t _i; \
839 isc_uint32_t _j; \
840 _j = isc_random_jitter((b), (b)/4); \
841 isc_interval_set(&_i, _j, 0); \
842 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
843 dns_zone_log(zone, ISC_LOG_WARNING, \
844 "epoch approaching: upgrade required: " \
845 "now + %s failed", #b); \
846 isc_interval_set(&_i, _j/2, 0); \
847 (void)isc_time_add((a), &_i, (c)); \
848 } \
849 } while (/*CONSTCOND*/0)
850
851 #define DNS_ZONE_TIME_ADD(a, b, c) \
852 do { \
853 isc_interval_t _i; \
854 isc_interval_set(&_i, (b), 0); \
855 if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \
856 dns_zone_log(zone, ISC_LOG_WARNING, \
857 "epoch approaching: upgrade required: " \
858 "now + %s failed", #b); \
859 isc_interval_set(&_i, (b)/2, 0); \
860 (void)isc_time_add((a), &_i, (c)); \
861 } \
862 } while (/*CONSTCOND*/0)
863
864 typedef struct nsec3param nsec3param_t;
865 struct nsec3param {
866 unsigned char data[DNS_NSEC3PARAM_BUFFERSIZE + 1];
867 unsigned int length;
868 isc_boolean_t nsec;
869 isc_boolean_t replace;
870 ISC_LINK(nsec3param_t) link;
871 };
872 typedef ISC_LIST(nsec3param_t) nsec3paramlist_t;
873 struct np3event {
874 isc_event_t event;
875 nsec3param_t params;
876 };
877
878 struct ssevent {
879 isc_event_t event;
880 isc_uint32_t serial;
881 };
882
883 /*%
884 * Increment resolver-related statistics counters. Zone must be locked.
885 */
886 static inline void
887 inc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
888 if (zone->stats != NULL)
889 isc_stats_increment(zone->stats, counter);
890 }
891
892 /***
893 *** Public functions.
894 ***/
895
896 isc_result_t
897 dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
898 isc_result_t result;
899 dns_zone_t *zone;
900 isc_time_t now;
901
902 REQUIRE(zonep != NULL && *zonep == NULL);
903 REQUIRE(mctx != NULL);
904
905 TIME_NOW(&now);
906 zone = isc_mem_get(mctx, sizeof(*zone));
907 if (zone == NULL) {
908 return (ISC_R_NOMEMORY);
909 }
910
911 zone->mctx = NULL;
912 isc_mem_attach(mctx, &zone->mctx);
913
914 result = isc_mutex_init(&zone->lock);
915 if (result != ISC_R_SUCCESS) {
916 goto free_zone;
917 }
918
919 result = ZONEDB_INITLOCK(&zone->dblock);
920 if (result != ISC_R_SUCCESS) {
921 goto free_mutex;
922 }
923
924 /* XXX MPA check that all elements are initialised */
925 #ifdef DNS_ZONE_CHECKLOCK
926 zone->locked = ISC_FALSE;
927 #endif
928 zone->db = NULL;
929 zone->zmgr = NULL;
930 ISC_LINK_INIT(zone, link);
931 result = isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */
932 if (result != ISC_R_SUCCESS) {
933 goto free_dblock;
934 }
935 zone->irefs = 0;
936 dns_name_init(&zone->origin, NULL);
937 zone->strnamerd = NULL;
938 zone->strname = NULL;
939 zone->strrdclass = NULL;
940 zone->strviewname = NULL;
941 zone->masterfile = NULL;
942 ISC_LIST_INIT(zone->includes);
943 ISC_LIST_INIT(zone->newincludes);
944 zone->nincludes = 0;
945 zone->masterformat = dns_masterformat_none;
946 zone->masterstyle = NULL;
947 zone->keydirectory = NULL;
948 zone->journalsize = -1;
949 zone->journal = NULL;
950 zone->rdclass = dns_rdataclass_none;
951 zone->type = dns_zone_none;
952 zone->flags = 0;
953 zone->options = 0;
954 zone->options2 = 0;
955 zone->keyopts = 0;
956 zone->db_argc = 0;
957 zone->db_argv = NULL;
958 isc_time_settoepoch(&zone->expiretime);
959 isc_time_settoepoch(&zone->refreshtime);
960 isc_time_settoepoch(&zone->dumptime);
961 isc_time_settoepoch(&zone->loadtime);
962 zone->notifytime = now;
963 isc_time_settoepoch(&zone->resigntime);
964 isc_time_settoepoch(&zone->keywarntime);
965 isc_time_settoepoch(&zone->signingtime);
966 isc_time_settoepoch(&zone->nsec3chaintime);
967 isc_time_settoepoch(&zone->refreshkeytime);
968 zone->refreshkeyinterval = 0;
969 zone->refreshkeycount = 0;
970 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
971 zone->retry = DNS_ZONE_DEFAULTRETRY;
972 zone->expire = 0;
973 zone->minimum = 0;
974 zone->maxrefresh = DNS_ZONE_MAXREFRESH;
975 zone->minrefresh = DNS_ZONE_MINREFRESH;
976 zone->maxretry = DNS_ZONE_MAXRETRY;
977 zone->minretry = DNS_ZONE_MINRETRY;
978 zone->masters = NULL;
979 zone->masterdscps = NULL;
980 zone->masterkeynames = NULL;
981 zone->mastersok = NULL;
982 zone->masterscnt = 0;
983 zone->curmaster = 0;
984 zone->maxttl = 0;
985 zone->notify = NULL;
986 zone->notifykeynames = NULL;
987 zone->notifydscp = NULL;
988 zone->notifytype = dns_notifytype_yes;
989 zone->notifycnt = 0;
990 zone->task = NULL;
991 zone->loadtask = NULL;
992 zone->update_acl = NULL;
993 zone->forward_acl = NULL;
994 zone->notify_acl = NULL;
995 zone->query_acl = NULL;
996 zone->queryon_acl = NULL;
997 zone->xfr_acl = NULL;
998 zone->update_disabled = ISC_FALSE;
999 zone->zero_no_soa_ttl = ISC_TRUE;
1000 zone->check_names = dns_severity_ignore;
1001 zone->request = NULL;
1002 zone->lctx = NULL;
1003 zone->readio = NULL;
1004 zone->dctx = NULL;
1005 zone->writeio = NULL;
1006 zone->timer = NULL;
1007 zone->idlein = DNS_DEFAULT_IDLEIN;
1008 zone->idleout = DNS_DEFAULT_IDLEOUT;
1009 zone->log_key_expired_timer = 0;
1010 ISC_LIST_INIT(zone->notifies);
1011 isc_sockaddr_any(&zone->notifysrc4);
1012 isc_sockaddr_any6(&zone->notifysrc6);
1013 isc_sockaddr_any(&zone->xfrsource4);
1014 isc_sockaddr_any6(&zone->xfrsource6);
1015 isc_sockaddr_any(&zone->altxfrsource4);
1016 isc_sockaddr_any6(&zone->altxfrsource6);
1017 zone->notifysrc4dscp = -1;
1018 zone->notifysrc6dscp = -1;
1019 zone->xfrsource4dscp = -1;
1020 zone->xfrsource6dscp = -1;
1021 zone->altxfrsource4dscp = -1;
1022 zone->altxfrsource6dscp = -1;
1023 zone->xfr = NULL;
1024 zone->tsigkey = NULL;
1025 zone->maxxfrin = MAX_XFER_TIME;
1026 zone->maxxfrout = MAX_XFER_TIME;
1027 zone->ssutable = NULL;
1028 zone->sigvalidityinterval = 30 * 24 * 3600;
1029 zone->sigresigninginterval = 7 * 24 * 3600;
1030 zone->view = NULL;
1031 zone->prev_view = NULL;
1032 zone->checkmx = NULL;
1033 zone->checksrv = NULL;
1034 zone->checkns = NULL;
1035 ISC_LINK_INIT(zone, statelink);
1036 zone->statelist = NULL;
1037 zone->stats = NULL;
1038 zone->requeststats_on = ISC_FALSE;
1039 zone->statlevel = dns_zonestat_none;
1040 zone->requeststats = NULL;
1041 zone->rcvquerystats = NULL;
1042 zone->notifydelay = 5;
1043 zone->isself = NULL;
1044 zone->isselfarg = NULL;
1045 ISC_LIST_INIT(zone->signing);
1046 ISC_LIST_INIT(zone->nsec3chain);
1047 zone->signatures = 10;
1048 zone->nodes = 100;
1049 zone->privatetype = (dns_rdatatype_t)0xffffU;
1050 zone->added = ISC_FALSE;
1051 zone->automatic = ISC_FALSE;
1052 zone->rpzs = NULL;
1053 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1054
1055 zone->catzs = NULL;
1056 zone->parentcatz = NULL;
1057
1058 ISC_LIST_INIT(zone->forwards);
1059 zone->raw = NULL;
1060 zone->secure = NULL;
1061 zone->sourceserial = 0;
1062 zone->sourceserialset = ISC_FALSE;
1063 zone->requestixfr = ISC_TRUE;
1064 zone->requestexpire = ISC_TRUE;
1065 ISC_LIST_INIT(zone->rss_events);
1066 zone->rss_db = NULL;
1067 zone->rss_raw = NULL;
1068 zone->rss_newver = NULL;
1069 zone->rss_oldver = NULL;
1070 zone->rss_event = NULL;
1071 zone->rss_state = NULL;
1072 zone->updatemethod = dns_updatemethod_increment;
1073 zone->maxrecords = 0U;
1074
1075 zone->magic = ZONE_MAGIC;
1076
1077 zone->gluecachestats = NULL;
1078 result = isc_stats_create(mctx, &zone->gluecachestats,
1079 dns_gluecachestatscounter_max);
1080 if (result != ISC_R_SUCCESS) {
1081 goto free_erefs;
1082 }
1083
1084 /* Must be after magic is set. */
1085 result = dns_zone_setdbtype(zone, dbargc_default, dbargv_default);
1086 if (result != ISC_R_SUCCESS) {
1087 goto free_stats;
1088 }
1089
1090 ISC_EVENT_INIT(&zone->ctlevent, sizeof(zone->ctlevent), 0, NULL,
1091 DNS_EVENT_ZONECONTROL, zone_shutdown, zone, zone,
1092 NULL, NULL);
1093 *zonep = zone;
1094 return (ISC_R_SUCCESS);
1095
1096 free_stats:
1097 if (zone->gluecachestats != NULL)
1098 isc_stats_detach(&zone->gluecachestats);
1099
1100 free_erefs:
1101 isc_refcount_decrement(&zone->erefs, NULL);
1102 isc_refcount_destroy(&zone->erefs);
1103
1104 free_dblock:
1105 ZONEDB_DESTROYLOCK(&zone->dblock);
1106
1107 free_mutex:
1108 DESTROYLOCK(&zone->lock);
1109
1110 free_zone:
1111 isc_mem_putanddetach(&zone->mctx, zone, sizeof(*zone));
1112 return (result);
1113 }
1114
1115 /*
1116 * Free a zone. Because we require that there be no more
1117 * outstanding events or references, no locking is necessary.
1118 */
1119 static void
1120 zone_free(dns_zone_t *zone) {
1121 isc_mem_t *mctx = NULL;
1122 dns_signing_t *signing;
1123 dns_nsec3chain_t *nsec3chain;
1124 dns_include_t *include;
1125
1126 REQUIRE(DNS_ZONE_VALID(zone));
1127 REQUIRE(isc_refcount_current(&zone->erefs) == 0);
1128 REQUIRE(zone->irefs == 0);
1129 REQUIRE(!LOCKED_ZONE(zone));
1130 REQUIRE(zone->timer == NULL);
1131 REQUIRE(zone->zmgr == NULL);
1132
1133 /*
1134 * Managed objects. Order is important.
1135 */
1136 if (zone->request != NULL) {
1137 dns_request_destroy(&zone->request); /* XXXMPA */
1138 }
1139 INSIST(zone->readio == NULL);
1140 INSIST(zone->statelist == NULL);
1141 INSIST(zone->writeio == NULL);
1142
1143 if (zone->task != NULL) {
1144 isc_task_detach(&zone->task);
1145 }
1146 if (zone->loadtask != NULL) {
1147 isc_task_detach(&zone->loadtask);
1148 }
1149 if (zone->view != NULL) {
1150 dns_view_weakdetach(&zone->view);
1151 }
1152 if (zone->prev_view != NULL) {
1153 dns_view_weakdetach(&zone->prev_view);
1154 }
1155
1156 /* Unmanaged objects */
1157 for (signing = ISC_LIST_HEAD(zone->signing);
1158 signing != NULL;
1159 signing = ISC_LIST_HEAD(zone->signing)) {
1160 ISC_LIST_UNLINK(zone->signing, signing, link);
1161 dns_db_detach(&signing->db);
1162 dns_dbiterator_destroy(&signing->dbiterator);
1163 isc_mem_put(zone->mctx, signing, sizeof *signing);
1164 }
1165 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
1166 nsec3chain != NULL;
1167 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain)) {
1168 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
1169 dns_db_detach(&nsec3chain->db);
1170 dns_dbiterator_destroy(&nsec3chain->dbiterator);
1171 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
1172 }
1173 for (include = ISC_LIST_HEAD(zone->includes);
1174 include != NULL;
1175 include = ISC_LIST_HEAD(zone->includes)) {
1176 ISC_LIST_UNLINK(zone->includes, include, link);
1177 isc_mem_free(zone->mctx, include->name);
1178 isc_mem_put(zone->mctx, include, sizeof *include);
1179 }
1180 for (include = ISC_LIST_HEAD(zone->newincludes);
1181 include != NULL;
1182 include = ISC_LIST_HEAD(zone->newincludes)) {
1183 ISC_LIST_UNLINK(zone->newincludes, include, link);
1184 isc_mem_free(zone->mctx, include->name);
1185 isc_mem_put(zone->mctx, include, sizeof *include);
1186 }
1187 if (zone->masterfile != NULL) {
1188 isc_mem_free(zone->mctx, zone->masterfile);
1189 }
1190 zone->masterfile = NULL;
1191 if (zone->keydirectory != NULL) {
1192 isc_mem_free(zone->mctx, zone->keydirectory);
1193 }
1194 zone->keydirectory = NULL;
1195 zone->journalsize = -1;
1196 if (zone->journal != NULL) {
1197 isc_mem_free(zone->mctx, zone->journal);
1198 }
1199 zone->journal = NULL;
1200 if (zone->stats != NULL) {
1201 isc_stats_detach(&zone->stats);
1202 }
1203 if (zone->requeststats != NULL) {
1204 isc_stats_detach(&zone->requeststats);
1205 }
1206 if (zone->rcvquerystats != NULL){
1207 dns_stats_detach(&zone->rcvquerystats);
1208 }
1209 if (zone->db != NULL) {
1210 zone_detachdb(zone);
1211 }
1212 if (zone->rpzs != NULL) {
1213 REQUIRE(zone->rpz_num < zone->rpzs->p.num_zones);
1214 dns_rpz_detach_rpzs(&zone->rpzs);
1215 zone->rpz_num = DNS_RPZ_INVALID_NUM;
1216 }
1217 if (zone->catzs != NULL) {
1218 dns_catz_catzs_detach(&zone->catzs);
1219 }
1220 zone_freedbargs(zone);
1221 RUNTIME_CHECK(dns_zone_setmasterswithkeys(zone, NULL,
1222 NULL, 0) == ISC_R_SUCCESS);
1223 RUNTIME_CHECK(dns_zone_setalsonotify(zone, NULL, 0) == ISC_R_SUCCESS);
1224 zone->check_names = dns_severity_ignore;
1225 if (zone->update_acl != NULL) {
1226 dns_acl_detach(&zone->update_acl);
1227 }
1228 if (zone->forward_acl != NULL) {
1229 dns_acl_detach(&zone->forward_acl);
1230 }
1231 if (zone->notify_acl != NULL) {
1232 dns_acl_detach(&zone->notify_acl);
1233 }
1234 if (zone->query_acl != NULL) {
1235 dns_acl_detach(&zone->query_acl);
1236 }
1237 if (zone->queryon_acl != NULL) {
1238 dns_acl_detach(&zone->queryon_acl);
1239 }
1240 if (zone->xfr_acl != NULL) {
1241 dns_acl_detach(&zone->xfr_acl);
1242 }
1243 if (dns_name_dynamic(&zone->origin)) {
1244 dns_name_free(&zone->origin, zone->mctx);
1245 }
1246 if (zone->strnamerd != NULL) {
1247 isc_mem_free(zone->mctx, zone->strnamerd);
1248 }
1249 if (zone->strname != NULL) {
1250 isc_mem_free(zone->mctx, zone->strname);
1251 }
1252 if (zone->strrdclass != NULL) {
1253 isc_mem_free(zone->mctx, zone->strrdclass);
1254 }
1255 if (zone->strviewname != NULL) {
1256 isc_mem_free(zone->mctx, zone->strviewname);
1257 }
1258 if (zone->ssutable != NULL) {
1259 dns_ssutable_detach(&zone->ssutable);
1260 }
1261 if (zone->gluecachestats != NULL) {
1262 isc_stats_detach(&zone->gluecachestats);
1263 }
1264
1265 /* last stuff */
1266 ZONEDB_DESTROYLOCK(&zone->dblock);
1267 DESTROYLOCK(&zone->lock);
1268 isc_refcount_destroy(&zone->erefs);
1269 zone->magic = 0;
1270 mctx = zone->mctx;
1271 isc_mem_put(mctx, zone, sizeof(*zone));
1272 isc_mem_detach(&mctx);
1273 }
1274
1275 /*
1276 * Returns ISC_TRUE iff this the signed side of an inline-signing zone.
1277 * Caller should hold zone lock.
1278 */
1279 static inline isc_boolean_t
1280 inline_secure(dns_zone_t *zone) {
1281 REQUIRE(DNS_ZONE_VALID(zone));
1282 if (zone->raw != NULL)
1283 return (ISC_TRUE);
1284 return (ISC_FALSE);
1285 }
1286
1287 /*
1288 * Returns ISC_TRUE iff this the unsigned side of an inline-signing zone
1289 * Caller should hold zone lock.
1290 */
1291 static inline isc_boolean_t
1292 inline_raw(dns_zone_t *zone) {
1293 REQUIRE(DNS_ZONE_VALID(zone));
1294 if (zone->secure != NULL)
1295 return (ISC_TRUE);
1296 return (ISC_FALSE);
1297 }
1298
1299 /*
1300 * Single shot.
1301 */
1302 void
1303 dns_zone_setclass(dns_zone_t *zone, dns_rdataclass_t rdclass) {
1304 char namebuf[1024];
1305
1306 REQUIRE(DNS_ZONE_VALID(zone));
1307 REQUIRE(rdclass != dns_rdataclass_none);
1308
1309 /*
1310 * Test and set.
1311 */
1312 LOCK_ZONE(zone);
1313 INSIST(zone != zone->raw);
1314 REQUIRE(zone->rdclass == dns_rdataclass_none ||
1315 zone->rdclass == rdclass);
1316 zone->rdclass = rdclass;
1317
1318 if (zone->strnamerd != NULL)
1319 isc_mem_free(zone->mctx, zone->strnamerd);
1320 if (zone->strrdclass != NULL)
1321 isc_mem_free(zone->mctx, zone->strrdclass);
1322
1323 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1324 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1325 zone_rdclass_tostr(zone, namebuf, sizeof namebuf);
1326 zone->strrdclass = isc_mem_strdup(zone->mctx, namebuf);
1327
1328 if (inline_secure(zone))
1329 dns_zone_setclass(zone->raw, rdclass);
1330 UNLOCK_ZONE(zone);
1331 }
1332
1333 dns_rdataclass_t
1334 dns_zone_getclass(dns_zone_t *zone) {
1335 REQUIRE(DNS_ZONE_VALID(zone));
1336
1337 return (zone->rdclass);
1338 }
1339
1340 void
1341 dns_zone_setnotifytype(dns_zone_t *zone, dns_notifytype_t notifytype) {
1342 REQUIRE(DNS_ZONE_VALID(zone));
1343
1344 LOCK_ZONE(zone);
1345 zone->notifytype = notifytype;
1346 UNLOCK_ZONE(zone);
1347 }
1348
1349 isc_result_t
1350 dns_zone_getserial2(dns_zone_t *zone, isc_uint32_t *serialp) {
1351 isc_result_t result;
1352 unsigned int soacount;
1353
1354 REQUIRE(DNS_ZONE_VALID(zone));
1355 REQUIRE(serialp != NULL);
1356
1357 LOCK_ZONE(zone);
1358 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
1359 if (zone->db != NULL) {
1360 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
1361 serialp, NULL, NULL, NULL, NULL,
1362 NULL);
1363 if (result == ISC_R_SUCCESS && soacount == 0)
1364 result = ISC_R_FAILURE;
1365 } else
1366 result = DNS_R_NOTLOADED;
1367 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
1368 UNLOCK_ZONE(zone);
1369
1370 return (result);
1371 }
1372
1373 isc_uint32_t
1374 dns_zone_getserial(dns_zone_t *zone) {
1375 isc_result_t result;
1376 isc_uint32_t serial;
1377
1378 result = dns_zone_getserial2(zone, &serial);
1379 if (result != ISC_R_SUCCESS)
1380 serial = 0; /* XXX: not really correct, but no other choice */
1381
1382 return (serial);
1383 }
1384
1385 /*
1386 * Single shot.
1387 */
1388 void
1389 dns_zone_settype(dns_zone_t *zone, dns_zonetype_t type) {
1390 char namebuf[1024];
1391
1392 REQUIRE(DNS_ZONE_VALID(zone));
1393 REQUIRE(type != dns_zone_none);
1394
1395 /*
1396 * Test and set.
1397 */
1398 LOCK_ZONE(zone);
1399 REQUIRE(zone->type == dns_zone_none || zone->type == type);
1400 zone->type = type;
1401
1402 if (zone->strnamerd != NULL)
1403 isc_mem_free(zone->mctx, zone->strnamerd);
1404
1405 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1406 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1407 UNLOCK_ZONE(zone);
1408 }
1409
1410 static void
1411 zone_freedbargs(dns_zone_t *zone) {
1412 unsigned int i;
1413
1414 /* Free the old database argument list. */
1415 if (zone->db_argv != NULL) {
1416 for (i = 0; i < zone->db_argc; i++)
1417 isc_mem_free(zone->mctx, zone->db_argv[i]);
1418 isc_mem_put(zone->mctx, zone->db_argv,
1419 zone->db_argc * sizeof(*zone->db_argv));
1420 }
1421 zone->db_argc = 0;
1422 zone->db_argv = NULL;
1423 }
1424
1425 isc_result_t
1426 dns_zone_getdbtype(dns_zone_t *zone, char ***argv, isc_mem_t *mctx) {
1427 size_t size = 0;
1428 unsigned int i;
1429 isc_result_t result = ISC_R_SUCCESS;
1430 void *mem;
1431 char **tmp, *tmp2, *base;
1432
1433 REQUIRE(DNS_ZONE_VALID(zone));
1434 REQUIRE(argv != NULL && *argv == NULL);
1435
1436 LOCK_ZONE(zone);
1437 size = (zone->db_argc + 1) * sizeof(char *);
1438 for (i = 0; i < zone->db_argc; i++)
1439 size += strlen(zone->db_argv[i]) + 1;
1440 mem = isc_mem_allocate(mctx, size);
1441 if (mem != NULL) {
1442 tmp = mem;
1443 tmp2 = mem;
1444 base = mem;
1445 tmp2 += (zone->db_argc + 1) * sizeof(char *);
1446 for (i = 0; i < zone->db_argc; i++) {
1447 *tmp++ = tmp2;
1448 strlcpy(tmp2, zone->db_argv[i], size - (tmp2 - base));
1449 tmp2 += strlen(tmp2) + 1;
1450 }
1451 *tmp = NULL;
1452 } else
1453 result = ISC_R_NOMEMORY;
1454 UNLOCK_ZONE(zone);
1455 *argv = mem;
1456 return (result);
1457 }
1458
1459 isc_result_t
1460 dns_zone_setdbtype(dns_zone_t *zone,
1461 unsigned int dbargc, const char * const *dbargv)
1462 {
1463 isc_result_t result = ISC_R_SUCCESS;
1464 char **argv = NULL;
1465 unsigned int i;
1466
1467 REQUIRE(DNS_ZONE_VALID(zone));
1468 REQUIRE(dbargc >= 1);
1469 REQUIRE(dbargv != NULL);
1470
1471 LOCK_ZONE(zone);
1472
1473 /* Set up a new database argument list. */
1474 argv = isc_mem_get(zone->mctx, dbargc * sizeof(*argv));
1475 if (argv == NULL) {
1476 goto nomem;
1477 }
1478 for (i = 0; i < dbargc; i++) {
1479 argv[i] = NULL;
1480 }
1481 for (i = 0; i < dbargc; i++) {
1482 argv[i] = isc_mem_strdup(zone->mctx, dbargv[i]);
1483 if (argv[i] == NULL)
1484 goto nomem;
1485 }
1486
1487 /* Free the old list. */
1488 zone_freedbargs(zone);
1489
1490 zone->db_argc = dbargc;
1491 zone->db_argv = argv;
1492 result = ISC_R_SUCCESS;
1493 goto unlock;
1494
1495 nomem:
1496 if (argv != NULL) {
1497 for (i = 0; i < dbargc; i++) {
1498 if (argv[i] != NULL) {
1499 isc_mem_free(zone->mctx, argv[i]);
1500 }
1501 }
1502 isc_mem_put(zone->mctx, argv, dbargc * sizeof(*argv));
1503 }
1504 result = ISC_R_NOMEMORY;
1505
1506 unlock:
1507 UNLOCK_ZONE(zone);
1508 return (result);
1509 }
1510
1511 static void
1512 dns_zone_setview_helper(dns_zone_t *zone, dns_view_t *view) {
1513 char namebuf[1024];
1514
1515 if (zone->prev_view == NULL && zone->view != NULL) {
1516 dns_view_weakattach(zone->view, &zone->prev_view);
1517 }
1518
1519 INSIST(zone != zone->raw);
1520 if (zone->view != NULL) {
1521 dns_view_weakdetach(&zone->view);
1522 }
1523 dns_view_weakattach(view, &zone->view);
1524
1525 if (zone->strviewname != NULL) {
1526 isc_mem_free(zone->mctx, zone->strviewname);
1527 }
1528 if (zone->strnamerd != NULL) {
1529 isc_mem_free(zone->mctx, zone->strnamerd);
1530 }
1531
1532 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1533 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1534 zone_viewname_tostr(zone, namebuf, sizeof namebuf);
1535 zone->strviewname = isc_mem_strdup(zone->mctx, namebuf);
1536
1537 if (inline_secure(zone)) {
1538 dns_zone_setview(zone->raw, view);
1539 }
1540 }
1541
1542 void
1543 dns_zone_setview(dns_zone_t *zone, dns_view_t *view) {
1544 REQUIRE(DNS_ZONE_VALID(zone));
1545
1546 LOCK_ZONE(zone);
1547 dns_zone_setview_helper(zone, view);
1548 UNLOCK_ZONE(zone);
1549 }
1550
1551 dns_view_t *
1552 dns_zone_getview(dns_zone_t *zone) {
1553 REQUIRE(DNS_ZONE_VALID(zone));
1554
1555 return (zone->view);
1556 }
1557
1558 void
1559 dns_zone_setviewcommit(dns_zone_t *zone) {
1560 REQUIRE(DNS_ZONE_VALID(zone));
1561
1562 LOCK_ZONE(zone);
1563 if (zone->prev_view != NULL)
1564 dns_view_weakdetach(&zone->prev_view);
1565 UNLOCK_ZONE(zone);
1566 }
1567
1568 void
1569 dns_zone_setviewrevert(dns_zone_t *zone) {
1570 REQUIRE(DNS_ZONE_VALID(zone));
1571
1572 LOCK_ZONE(zone);
1573 if (zone->prev_view != NULL) {
1574 dns_zone_setview_helper(zone, zone->prev_view);
1575 dns_view_weakdetach(&zone->prev_view);
1576 }
1577 UNLOCK_ZONE(zone);
1578 }
1579
1580 isc_result_t
1581 dns_zone_setorigin(dns_zone_t *zone, const dns_name_t *origin) {
1582 isc_result_t result;
1583 char namebuf[1024];
1584
1585 REQUIRE(DNS_ZONE_VALID(zone));
1586 REQUIRE(origin != NULL);
1587
1588 LOCK_ZONE(zone);
1589 INSIST(zone != zone->raw);
1590 if (dns_name_dynamic(&zone->origin)) {
1591 dns_name_free(&zone->origin, zone->mctx);
1592 dns_name_init(&zone->origin, NULL);
1593 }
1594 result = dns_name_dup(origin, zone->mctx, &zone->origin);
1595
1596 if (zone->strnamerd != NULL)
1597 isc_mem_free(zone->mctx, zone->strnamerd);
1598 if (zone->strname != NULL)
1599 isc_mem_free(zone->mctx, zone->strname);
1600
1601 zone_namerd_tostr(zone, namebuf, sizeof namebuf);
1602 zone->strnamerd = isc_mem_strdup(zone->mctx, namebuf);
1603 zone_name_tostr(zone, namebuf, sizeof namebuf);
1604 zone->strname = isc_mem_strdup(zone->mctx, namebuf);
1605
1606 if (result == ISC_R_SUCCESS && inline_secure(zone))
1607 result = dns_zone_setorigin(zone->raw, origin);
1608 UNLOCK_ZONE(zone);
1609 return (result);
1610 }
1611
1612 static isc_result_t
1613 dns_zone_setstring(dns_zone_t *zone, char **field, const char *value) {
1614 char *copy;
1615
1616 if (value != NULL) {
1617 copy = isc_mem_strdup(zone->mctx, value);
1618 if (copy == NULL)
1619 return (ISC_R_NOMEMORY);
1620 } else {
1621 copy = NULL;
1622 }
1623
1624 if (*field != NULL)
1625 isc_mem_free(zone->mctx, *field);
1626
1627 *field = copy;
1628 return (ISC_R_SUCCESS);
1629 }
1630
1631 isc_result_t
1632 dns_zone_setfile(dns_zone_t *zone, const char *file) {
1633 return (dns_zone_setfile3(zone, file, dns_masterformat_text,
1634 &dns_master_style_default));
1635 }
1636
1637 isc_result_t
1638 dns_zone_setfile2(dns_zone_t *zone, const char *file,
1639 dns_masterformat_t format)
1640 {
1641 return (dns_zone_setfile3(zone, file, format,
1642 &dns_master_style_default));
1643 }
1644
1645 isc_result_t
1646 dns_zone_setfile3(dns_zone_t *zone, const char *file,
1647 dns_masterformat_t format,
1648 const dns_master_style_t *style)
1649 {
1650 isc_result_t result = ISC_R_SUCCESS;
1651
1652 REQUIRE(DNS_ZONE_VALID(zone));
1653
1654 LOCK_ZONE(zone);
1655 result = dns_zone_setstring(zone, &zone->masterfile, file);
1656 if (result == ISC_R_SUCCESS) {
1657 zone->masterformat = format;
1658 if (format == dns_masterformat_text)
1659 zone->masterstyle = style;
1660 result = default_journal(zone);
1661 }
1662 UNLOCK_ZONE(zone);
1663
1664 return (result);
1665 }
1666
1667 const char *
1668 dns_zone_getfile(dns_zone_t *zone) {
1669 REQUIRE(DNS_ZONE_VALID(zone));
1670
1671 return (zone->masterfile);
1672 }
1673
1674 dns_ttl_t
1675 dns_zone_getmaxttl(dns_zone_t *zone) {
1676 REQUIRE(DNS_ZONE_VALID(zone));
1677
1678 return (zone->maxttl);
1679 }
1680
1681 void
1682 dns_zone_setmaxttl(dns_zone_t *zone, dns_ttl_t maxttl) {
1683 REQUIRE(DNS_ZONE_VALID(zone));
1684
1685 LOCK_ZONE(zone);
1686 if (maxttl != 0)
1687 zone->options2 |= DNS_ZONEOPT2_CHECKTTL;
1688 else
1689 zone->options2 &= ~DNS_ZONEOPT2_CHECKTTL;
1690 zone->maxttl = maxttl;
1691 UNLOCK_ZONE(zone);
1692
1693 return;
1694 }
1695
1696 static isc_result_t
1697 default_journal(dns_zone_t *zone) {
1698 isc_result_t result;
1699 char *journal;
1700
1701 REQUIRE(DNS_ZONE_VALID(zone));
1702 REQUIRE(LOCKED_ZONE(zone));
1703
1704 if (zone->masterfile != NULL) {
1705 /* Calculate string length including '\0'. */
1706 int len = strlen(zone->masterfile) + sizeof(".jnl");
1707 journal = isc_mem_allocate(zone->mctx, len);
1708 if (journal == NULL)
1709 return (ISC_R_NOMEMORY);
1710 strlcpy(journal, zone->masterfile, len);
1711 strlcat(journal, ".jnl", len);
1712 } else {
1713 journal = NULL;
1714 }
1715 result = dns_zone_setstring(zone, &zone->journal, journal);
1716 if (journal != NULL)
1717 isc_mem_free(zone->mctx, journal);
1718 return (result);
1719 }
1720
1721 isc_result_t
1722 dns_zone_setjournal(dns_zone_t *zone, const char *myjournal) {
1723 isc_result_t result = ISC_R_SUCCESS;
1724
1725 REQUIRE(DNS_ZONE_VALID(zone));
1726
1727 LOCK_ZONE(zone);
1728 result = dns_zone_setstring(zone, &zone->journal, myjournal);
1729 UNLOCK_ZONE(zone);
1730
1731 return (result);
1732 }
1733
1734 char *
1735 dns_zone_getjournal(dns_zone_t *zone) {
1736 REQUIRE(DNS_ZONE_VALID(zone));
1737
1738 return (zone->journal);
1739 }
1740
1741 /*
1742 * Return true iff the zone is "dynamic", in the sense that the zone's
1743 * master file (if any) is written by the server, rather than being
1744 * updated manually and read by the server.
1745 *
1746 * This is true for slave zones, stub zones, key zones, and zones that
1747 * allow dynamic updates either by having an update policy ("ssutable")
1748 * or an "allow-update" ACL with a value other than exactly "{ none; }".
1749 */
1750 isc_boolean_t
1751 dns_zone_isdynamic(dns_zone_t *zone, isc_boolean_t ignore_freeze) {
1752 REQUIRE(DNS_ZONE_VALID(zone));
1753
1754 if (zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
1755 zone->type == dns_zone_key ||
1756 (zone->type == dns_zone_redirect && zone->masters != NULL))
1757 return (ISC_TRUE);
1758
1759 /* If !ignore_freeze, we need check whether updates are disabled. */
1760 if (zone->type == dns_zone_master &&
1761 (!zone->update_disabled || ignore_freeze) &&
1762 ((zone->ssutable != NULL) ||
1763 (zone->update_acl != NULL && !dns_acl_isnone(zone->update_acl))))
1764 return (ISC_TRUE);
1765
1766 return (ISC_FALSE);
1767
1768 }
1769
1770 /*
1771 * Set the response policy index and information for a zone.
1772 */
1773 isc_result_t
1774 dns_zone_rpz_enable(dns_zone_t *zone, dns_rpz_zones_t *rpzs,
1775 dns_rpz_num_t rpz_num)
1776 {
1777 /*
1778 * Only RBTDB zones can be used for response policy zones,
1779 * because only they have the code to load the create the summary data.
1780 * Only zones that are loaded instead of mmap()ed create the
1781 * summary data and so can be policy zones.
1782 */
1783 if (strcmp(zone->db_argv[0], "rbt") != 0 &&
1784 strcmp(zone->db_argv[0], "rbt64") != 0)
1785 return (ISC_R_NOTIMPLEMENTED);
1786 if (zone->masterformat == dns_masterformat_map)
1787 return (ISC_R_NOTIMPLEMENTED);
1788
1789 /*
1790 * This must happen only once or be redundant.
1791 */
1792 LOCK_ZONE(zone);
1793 if (zone->rpzs != NULL) {
1794 REQUIRE(zone->rpzs == rpzs && zone->rpz_num == rpz_num);
1795 } else {
1796 REQUIRE(zone->rpz_num == DNS_RPZ_INVALID_NUM);
1797 dns_rpz_attach_rpzs(rpzs, &zone->rpzs);
1798 zone->rpz_num = rpz_num;
1799 }
1800 rpzs->defined |= DNS_RPZ_ZBIT(rpz_num);
1801 UNLOCK_ZONE(zone);
1802
1803 return (ISC_R_SUCCESS);
1804 }
1805
1806 dns_rpz_num_t
1807 dns_zone_get_rpz_num(dns_zone_t *zone) {
1808 return (zone->rpz_num);
1809 }
1810
1811 /*
1812 * If a zone is a response policy zone, mark its new database.
1813 */
1814 void
1815 dns_zone_rpz_enable_db(dns_zone_t *zone, dns_db_t *db) {
1816 isc_result_t result;
1817 if (zone->rpz_num == DNS_RPZ_INVALID_NUM)
1818 return;
1819 REQUIRE(zone->rpzs != NULL);
1820 zone->rpzs->zones[zone->rpz_num]->db_registered = ISC_TRUE;
1821 result = dns_db_updatenotify_register(db,
1822 dns_rpz_dbupdate_callback,
1823 zone->rpzs->zones[zone->rpz_num]);
1824 REQUIRE(result == ISC_R_SUCCESS);
1825 }
1826
1827 void
1828 dns_zone_catz_enable(dns_zone_t *zone, dns_catz_zones_t *catzs) {
1829 REQUIRE(DNS_ZONE_VALID(zone));
1830 REQUIRE(catzs != NULL);
1831
1832 LOCK_ZONE(zone);
1833 INSIST(zone->catzs == NULL || zone->catzs == catzs);
1834 dns_catz_catzs_set_view(catzs, zone->view);
1835 if (zone->catzs == NULL)
1836 dns_catz_catzs_attach(catzs, &zone->catzs);
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 /*
1855 * Set catalog zone ownership of the zone
1856 */
1857 void
1858 dns_zone_set_parentcatz(dns_zone_t *zone, dns_catz_zone_t *catz) {
1859 REQUIRE(DNS_ZONE_VALID(zone));
1860 REQUIRE(catz != NULL);
1861 LOCK_ZONE(zone);
1862 INSIST(zone->parentcatz == NULL || zone->parentcatz == catz);
1863 zone->parentcatz = catz;
1864 UNLOCK_ZONE(zone);
1865 }
1866
1867 dns_catz_zone_t *
1868 dns_zone_get_parentcatz(const dns_zone_t *zone) {
1869 REQUIRE(DNS_ZONE_VALID(zone));
1870 return (zone->parentcatz);
1871 }
1872
1873
1874 static isc_boolean_t
1875 zone_touched(dns_zone_t *zone) {
1876 isc_result_t result;
1877 isc_time_t modtime;
1878 dns_include_t *include;
1879
1880 REQUIRE(DNS_ZONE_VALID(zone));
1881
1882 result = isc_file_getmodtime(zone->masterfile, &modtime);
1883 if (result != ISC_R_SUCCESS ||
1884 isc_time_compare(&modtime, &zone->loadtime) > 0)
1885 return (ISC_TRUE);
1886
1887 for (include = ISC_LIST_HEAD(zone->includes);
1888 include != NULL;
1889 include = ISC_LIST_NEXT(include, link))
1890 {
1891 result = isc_file_getmodtime(include->name, &modtime);
1892 if (result != ISC_R_SUCCESS ||
1893 isc_time_compare(&modtime, &include->filetime) > 0)
1894 return (ISC_TRUE);
1895 }
1896
1897 return (ISC_FALSE);
1898 }
1899
1900 static isc_result_t
1901 zone_load(dns_zone_t *zone, unsigned int flags, isc_boolean_t locked) {
1902 isc_result_t result;
1903 isc_time_t now;
1904 isc_time_t loadtime;
1905 dns_db_t *db = NULL;
1906 isc_boolean_t rbt, hasraw;
1907
1908 REQUIRE(DNS_ZONE_VALID(zone));
1909
1910 if (!locked)
1911 LOCK_ZONE(zone);
1912
1913 INSIST(zone != zone->raw);
1914 hasraw = inline_secure(zone);
1915 if (hasraw) {
1916 result = zone_load(zone->raw, flags, ISC_FALSE);
1917 if (result != ISC_R_SUCCESS) {
1918 if (!locked)
1919 UNLOCK_ZONE(zone);
1920 return(result);
1921 }
1922 LOCK_ZONE(zone->raw);
1923 }
1924
1925 TIME_NOW(&now);
1926
1927 INSIST(zone->type != dns_zone_none);
1928
1929 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING)) {
1930 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
1931 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
1932 result = DNS_R_CONTINUE;
1933 goto cleanup;
1934 }
1935
1936 INSIST(zone->db_argc >= 1);
1937
1938 rbt = strcmp(zone->db_argv[0], "rbt") == 0 ||
1939 strcmp(zone->db_argv[0], "rbt64") == 0;
1940
1941 if (zone->db != NULL && zone->masterfile == NULL && rbt) {
1942 /*
1943 * The zone has no master file configured.
1944 */
1945 result = ISC_R_SUCCESS;
1946 goto cleanup;
1947 }
1948
1949 if (zone->db != NULL && dns_zone_isdynamic(zone, ISC_FALSE)) {
1950 /*
1951 * This is a slave, stub, or dynamically updated
1952 * zone being reloaded. Do nothing - the database
1953 * we already have is guaranteed to be up-to-date.
1954 */
1955 if (zone->type == dns_zone_master)
1956 result = DNS_R_DYNAMIC;
1957 else
1958 result = ISC_R_SUCCESS;
1959 goto cleanup;
1960 }
1961
1962 /*
1963 * Store the current time before the zone is loaded, so that if the
1964 * file changes between the time of the load and the time that
1965 * zone->loadtime is set, then the file will still be reloaded
1966 * the next time dns_zone_load is called.
1967 */
1968 TIME_NOW(&loadtime);
1969
1970 /*
1971 * Don't do the load if the file that stores the zone is older
1972 * than the last time the zone was loaded. If the zone has not
1973 * been loaded yet, zone->loadtime will be the epoch.
1974 */
1975 if (zone->masterfile != NULL) {
1976 isc_time_t filetime;
1977
1978 /*
1979 * The file is already loaded. If we are just doing a
1980 * "rndc reconfig", we are done.
1981 */
1982 if (!isc_time_isepoch(&zone->loadtime) &&
1983 (flags & DNS_ZONELOADFLAG_NOSTAT) != 0) {
1984 result = ISC_R_SUCCESS;
1985 goto cleanup;
1986 }
1987
1988 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
1989 !zone_touched(zone))
1990 {
1991 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
1992 ISC_LOG_DEBUG(1),
1993 "skipping load: master file "
1994 "older than last load");
1995 result = DNS_R_UPTODATE;
1996 goto cleanup;
1997 }
1998
1999
2000 /*
2001 * If the file modification time is in the past
2002 * set loadtime to that value.
2003 */
2004 result = isc_file_getmodtime(zone->masterfile, &filetime);
2005 if (result == ISC_R_SUCCESS &&
2006 isc_time_compare(&loadtime, &filetime) > 0)
2007 loadtime = filetime;
2008 }
2009
2010 /*
2011 * Built in zones (with the exception of empty zones) don't need
2012 * to be reloaded.
2013 */
2014 if (zone->type == dns_zone_master &&
2015 strcmp(zone->db_argv[0], "_builtin") == 0 &&
2016 (zone->db_argc < 2 || strcmp(zone->db_argv[1], "empty") != 0) &&
2017 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
2018 result = ISC_R_SUCCESS;
2019 goto cleanup;
2020 }
2021
2022 /*
2023 * Zones associated with a DLZ don't need to be loaded either,
2024 * but we need to associate the database with the zone object.
2025 */
2026 if (strcmp(zone->db_argv[0], "dlz") == 0) {
2027 dns_dlzdb_t *dlzdb;
2028 dns_dlzfindzone_t findzone;
2029
2030 for (dlzdb = ISC_LIST_HEAD(zone->view->dlz_unsearched);
2031 dlzdb != NULL;
2032 dlzdb = ISC_LIST_NEXT(dlzdb, link))
2033 {
2034 INSIST(DNS_DLZ_VALID(dlzdb));
2035 if (strcmp(zone->db_argv[1], dlzdb->dlzname) == 0)
2036 break;
2037 }
2038
2039 if (dlzdb == NULL) {
2040 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2041 ISC_LOG_ERROR,
2042 "DLZ %s does not exist or is set "
2043 "to 'search yes;'", zone->db_argv[1]);
2044 result = ISC_R_NOTFOUND;
2045 goto cleanup;
2046 }
2047
2048 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
2049 /* ask SDLZ driver if the zone is supported */
2050 findzone = dlzdb->implementation->methods->findzone;
2051 result = (*findzone)(dlzdb->implementation->driverarg,
2052 dlzdb->dbdata, dlzdb->mctx,
2053 zone->view->rdclass, &zone->origin,
2054 NULL, NULL, &db);
2055 if (result != ISC_R_NOTFOUND) {
2056 if (zone->db != NULL)
2057 zone_detachdb(zone);
2058 zone_attachdb(zone, db);
2059 dns_db_detach(&db);
2060 result = ISC_R_SUCCESS;
2061 }
2062 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
2063
2064 if (result == ISC_R_SUCCESS) {
2065 if (dlzdb->configure_callback == NULL)
2066 goto cleanup;
2067
2068 result = (*dlzdb->configure_callback)(zone->view,
2069 dlzdb, zone);
2070 if (result != ISC_R_SUCCESS)
2071 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2072 ISC_LOG_ERROR,
2073 "DLZ configuration callback: %s",
2074 isc_result_totext(result));
2075 }
2076 goto cleanup;
2077 }
2078
2079 if ((zone->type == dns_zone_slave || zone->type == dns_zone_stub ||
2080 (zone->type == dns_zone_redirect && zone->masters != NULL)) &&
2081 rbt) {
2082 if (zone->masterfile == NULL ||
2083 !isc_file_exists(zone->masterfile)) {
2084 if (zone->masterfile != NULL) {
2085 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2086 ISC_LOG_DEBUG(1),
2087 "no master file");
2088 }
2089 zone->refreshtime = now;
2090 if (zone->task != NULL)
2091 zone_settimer(zone, &now);
2092 result = ISC_R_SUCCESS;
2093 goto cleanup;
2094 }
2095 }
2096
2097 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2098 ISC_LOG_DEBUG(1), "starting load");
2099
2100 result = dns_db_create(zone->mctx, zone->db_argv[0],
2101 &zone->origin, (zone->type == dns_zone_stub) ?
2102 dns_dbtype_stub : dns_dbtype_zone,
2103 zone->rdclass,
2104 zone->db_argc - 1, zone->db_argv + 1,
2105 &db);
2106
2107 if (result != ISC_R_SUCCESS) {
2108 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
2109 "loading zone: creating database: %s",
2110 isc_result_totext(result));
2111 goto cleanup;
2112 }
2113 dns_db_settask(db, zone->task);
2114
2115 if (zone->type == dns_zone_master || zone->type == dns_zone_slave) {
2116 result = dns_db_setgluecachestats(db, zone->gluecachestats);
2117 if (result == ISC_R_NOTIMPLEMENTED) {
2118 result = ISC_R_SUCCESS;
2119 }
2120 if (result != ISC_R_SUCCESS) {
2121 goto cleanup;
2122 }
2123 }
2124
2125 if (! dns_db_ispersistent(db)) {
2126 if (zone->masterfile != NULL) {
2127 result = zone_startload(db, zone, loadtime);
2128 } else {
2129 result = DNS_R_NOMASTERFILE;
2130 if (zone->type == dns_zone_master ||
2131 (zone->type == dns_zone_redirect &&
2132 zone->masters == NULL)) {
2133 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2134 ISC_LOG_ERROR,
2135 "loading zone: "
2136 "no master file configured");
2137 goto cleanup;
2138 }
2139 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
2140 ISC_LOG_INFO, "loading zone: "
2141 "no master file configured: continuing");
2142 }
2143 }
2144
2145 if (result == DNS_R_CONTINUE) {
2146 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING);
2147 if ((flags & DNS_ZONELOADFLAG_THAW) != 0)
2148 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_THAW);
2149 goto cleanup;
2150 }
2151
2152 result = zone_postload(zone, db, loadtime, result);
2153
2154 cleanup:
2155 if (hasraw)
2156 UNLOCK_ZONE(zone->raw);
2157 if (!locked)
2158 UNLOCK_ZONE(zone);
2159 if (db != NULL)
2160 dns_db_detach(&db);
2161 return (result);
2162 }
2163
2164 isc_result_t
2165 dns_zone_load(dns_zone_t *zone) {
2166 return (zone_load(zone, 0, ISC_FALSE));
2167 }
2168
2169 isc_result_t
2170 dns_zone_loadnew(dns_zone_t *zone) {
2171 return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT, ISC_FALSE));
2172 }
2173
2174 static void
2175 zone_asyncload(isc_task_t *task, isc_event_t *event) {
2176 dns_asyncload_t *asl = event->ev_arg;
2177 dns_zone_t *zone = asl->zone;
2178 isc_result_t result;
2179
2180 UNUSED(task);
2181
2182 REQUIRE(DNS_ZONE_VALID(zone));
2183
2184 isc_event_free(&event);
2185
2186 LOCK_ZONE(zone);
2187 result = zone_load(zone, 0, ISC_TRUE);
2188 if (result != DNS_R_CONTINUE) {
2189 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2190 }
2191 UNLOCK_ZONE(zone);
2192
2193 /* Inform the zone table we've finished loading */
2194 if (asl->loaded != NULL)
2195 (asl->loaded)(asl->loaded_arg, zone, task);
2196
2197 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2198 dns_zone_idetach(&zone);
2199 }
2200
2201 isc_result_t
2202 dns_zone_asyncload(dns_zone_t *zone, dns_zt_zoneloaded_t done, void *arg) {
2203 isc_event_t *e;
2204 dns_asyncload_t *asl = NULL;
2205 isc_result_t result = ISC_R_SUCCESS;
2206
2207 REQUIRE(DNS_ZONE_VALID(zone));
2208
2209 if (zone->zmgr == NULL)
2210 return (ISC_R_FAILURE);
2211
2212 /* If we already have a load pending, stop now */
2213 LOCK_ZONE(zone);
2214 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)) {
2215 UNLOCK_ZONE(zone);
2216 return (ISC_R_ALREADYRUNNING);
2217 }
2218
2219 asl = isc_mem_get(zone->mctx, sizeof (*asl));
2220 if (asl == NULL)
2221 CHECK(ISC_R_NOMEMORY);
2222
2223 asl->zone = NULL;
2224 asl->loaded = done;
2225 asl->loaded_arg = arg;
2226
2227 e = isc_event_allocate(zone->zmgr->mctx, zone->zmgr,
2228 DNS_EVENT_ZONELOAD,
2229 zone_asyncload, asl,
2230 sizeof(isc_event_t));
2231 if (e == NULL)
2232 CHECK(ISC_R_NOMEMORY);
2233
2234 zone_iattach(zone, &asl->zone);
2235 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPENDING);
2236 isc_task_send(zone->loadtask, &e);
2237 UNLOCK_ZONE(zone);
2238
2239 return (ISC_R_SUCCESS);
2240
2241 failure:
2242 if (asl != NULL)
2243 isc_mem_put(zone->mctx, asl, sizeof (*asl));
2244 UNLOCK_ZONE(zone);
2245 return (result);
2246 }
2247
2248 isc_boolean_t
2249 dns__zone_loadpending(dns_zone_t *zone) {
2250 REQUIRE(DNS_ZONE_VALID(zone));
2251
2252 return (ISC_TF(DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING)));
2253 }
2254
2255 isc_result_t
2256 dns_zone_loadandthaw(dns_zone_t *zone) {
2257 isc_result_t result;
2258
2259 if (inline_raw(zone))
2260 result = zone_load(zone->secure, DNS_ZONELOADFLAG_THAW,
2261 ISC_FALSE);
2262 else
2263 result = zone_load(zone, DNS_ZONELOADFLAG_THAW, ISC_FALSE);
2264
2265 switch (result) {
2266 case DNS_R_CONTINUE:
2267 /* Deferred thaw. */
2268 break;
2269 case DNS_R_UPTODATE:
2270 case ISC_R_SUCCESS:
2271 case DNS_R_SEENINCLUDE:
2272 zone->update_disabled = ISC_FALSE;
2273 break;
2274 case DNS_R_NOMASTERFILE:
2275 zone->update_disabled = ISC_FALSE;
2276 break;
2277 default:
2278 /* Error, remain in disabled state. */
2279 break;
2280 }
2281 return (result);
2282 }
2283
2284 static unsigned int
2285 get_master_options(dns_zone_t *zone) {
2286 unsigned int options;
2287
2288 options = DNS_MASTER_ZONE | DNS_MASTER_RESIGN;
2289 if (zone->type == dns_zone_slave ||
2290 (zone->type == dns_zone_redirect && zone->masters == NULL))
2291 options |= DNS_MASTER_SLAVE;
2292 if (zone->type == dns_zone_key)
2293 options |= DNS_MASTER_KEY;
2294 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS))
2295 options |= DNS_MASTER_CHECKNS;
2296 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS))
2297 options |= DNS_MASTER_FATALNS;
2298 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES))
2299 options |= DNS_MASTER_CHECKNAMES;
2300 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL))
2301 options |= DNS_MASTER_CHECKNAMESFAIL;
2302 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMX))
2303 options |= DNS_MASTER_CHECKMX;
2304 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2305 options |= DNS_MASTER_CHECKMXFAIL;
2306 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKWILDCARD))
2307 options |= DNS_MASTER_CHECKWILDCARD;
2308 if (DNS_ZONE_OPTION2(zone, DNS_ZONEOPT2_CHECKTTL))
2309 options |= DNS_MASTER_CHECKTTL;
2310 return (options);
2311 }
2312
2313 static void
2314 zone_registerinclude(const char *filename, void *arg) {
2315 isc_result_t result;
2316 dns_zone_t *zone = (dns_zone_t *) arg;
2317 dns_include_t *inc = NULL;
2318
2319 REQUIRE(DNS_ZONE_VALID(zone));
2320
2321 if (filename == NULL)
2322 return;
2323
2324 /*
2325 * Suppress duplicates.
2326 */
2327 for (inc = ISC_LIST_HEAD(zone->newincludes);
2328 inc != NULL;
2329 inc = ISC_LIST_NEXT(inc, link))
2330 if (strcmp(filename, inc->name) == 0)
2331 return;
2332
2333 inc = isc_mem_get(zone->mctx, sizeof(dns_include_t));
2334 if (inc == NULL)
2335 return;
2336 inc->name = isc_mem_strdup(zone->mctx, filename);
2337 if (inc->name == NULL) {
2338 isc_mem_put(zone->mctx, inc, sizeof(dns_include_t));
2339 return;
2340 }
2341 ISC_LINK_INIT(inc, link);
2342
2343 result = isc_file_getmodtime(filename, &inc->filetime);
2344 if (result != ISC_R_SUCCESS)
2345 isc_time_settoepoch(&inc->filetime);
2346
2347 ISC_LIST_APPEND(zone->newincludes, inc, link);
2348 }
2349
2350 static void
2351 zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
2352 dns_load_t *load = event->ev_arg;
2353 isc_result_t result = ISC_R_SUCCESS;
2354 unsigned int options;
2355
2356 REQUIRE(DNS_LOAD_VALID(load));
2357
2358 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2359 result = ISC_R_CANCELED;
2360 isc_event_free(&event);
2361 if (result == ISC_R_CANCELED)
2362 goto fail;
2363
2364 options = get_master_options(load->zone);
2365
2366 result = dns_master_loadfileinc5(load->zone->masterfile,
2367 dns_db_origin(load->db),
2368 dns_db_origin(load->db),
2369 load->zone->rdclass, options, 0,
2370 &load->callbacks, task,
2371 zone_loaddone, load,
2372 &load->zone->lctx,
2373 zone_registerinclude,
2374 load->zone, load->zone->mctx,
2375 load->zone->masterformat,
2376 load->zone->maxttl);
2377 if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
2378 result != DNS_R_SEENINCLUDE)
2379 goto fail;
2380 return;
2381
2382 fail:
2383 zone_loaddone(load, result);
2384 }
2385
2386 static void
2387 get_raw_serial(dns_zone_t *raw, dns_masterrawheader_t *rawdata) {
2388 isc_result_t result;
2389 unsigned int soacount;
2390
2391 LOCK(&raw->lock);
2392 if (raw->db != NULL) {
2393 result = zone_get_from_db(raw, raw->db, NULL, &soacount,
2394 &rawdata->sourceserial,
2395 NULL, NULL, NULL, NULL,
2396 NULL);
2397 if (result == ISC_R_SUCCESS && soacount > 0U)
2398 rawdata->flags |= DNS_MASTERRAW_SOURCESERIALSET;
2399 }
2400 UNLOCK(&raw->lock);
2401 }
2402
2403 static void
2404 zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
2405 const char me[] = "zone_gotwritehandle";
2406 dns_zone_t *zone = event->ev_arg;
2407 isc_result_t result = ISC_R_SUCCESS;
2408 dns_dbversion_t *version = NULL;
2409 dns_masterrawheader_t rawdata;
2410
2411 REQUIRE(DNS_ZONE_VALID(zone));
2412 INSIST(task == zone->task);
2413 ENTER;
2414
2415 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0)
2416 result = ISC_R_CANCELED;
2417 isc_event_free(&event);
2418 if (result == ISC_R_CANCELED)
2419 goto fail;
2420
2421 LOCK_ZONE(zone);
2422 INSIST(zone != zone->raw);
2423 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
2424 if (zone->db != NULL) {
2425 const dns_master_style_t *output_style;
2426
2427 dns_db_currentversion(zone->db, &version);
2428 dns_master_initrawheader(&rawdata);
2429 if (inline_secure(zone))
2430 get_raw_serial(zone->raw, &rawdata);
2431 if (zone->type == dns_zone_key)
2432 output_style = &dns_master_style_keyzone;
2433 else if (zone->masterstyle != NULL)
2434 output_style = zone->masterstyle;
2435 else
2436 output_style = &dns_master_style_default;
2437 result = dns_master_dumpinc3(zone->mctx, zone->db, version,
2438 output_style, zone->masterfile,
2439 zone->task, dump_done, zone, &zone->dctx, zone->masterformat,
2440 &rawdata);
2441 dns_db_closeversion(zone->db, &version, ISC_FALSE);
2442 } else
2443 result = ISC_R_CANCELED;
2444 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
2445 UNLOCK_ZONE(zone);
2446 if (result != DNS_R_CONTINUE)
2447 goto fail;
2448 return;
2449
2450 fail:
2451 dump_done(zone, result);
2452 }
2453
2454 /*
2455 * Save the raw serial number for inline-signing zones.
2456 * (XXX: Other information from the header will be used
2457 * for other purposes in the future, but for now this is
2458 * all we're interested in.)
2459 */
2460 static void
2461 zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2462 if ((header->flags & DNS_MASTERRAW_SOURCESERIALSET) == 0)
2463 return;
2464
2465 zone->sourceserial = header->sourceserial;
2466 zone->sourceserialset = ISC_TRUE;
2467 }
2468
2469 void
2470 dns_zone_setrawdata(dns_zone_t *zone, dns_masterrawheader_t *header) {
2471 if (zone == NULL)
2472 return;
2473
2474 LOCK_ZONE(zone);
2475 zone_setrawdata(zone, header);
2476 UNLOCK_ZONE(zone);
2477 }
2478
2479 static isc_result_t
2480 zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
2481 dns_load_t *load;
2482 isc_result_t result;
2483 isc_result_t tresult;
2484 unsigned int options;
2485
2486 dns_zone_rpz_enable_db(zone, db);
2487 dns_zone_catz_enable_db(zone, db);
2488 options = get_master_options(zone);
2489 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS))
2490 options |= DNS_MASTER_MANYERRORS;
2491
2492 if (zone->zmgr != NULL && zone->db != NULL && zone->loadtask != NULL) {
2493 load = isc_mem_get(zone->mctx, sizeof(*load));
2494 if (load == NULL)
2495 return (ISC_R_NOMEMORY);
2496
2497 load->mctx = NULL;
2498 load->zone = NULL;
2499 load->db = NULL;
2500 load->loadtime = loadtime;
2501 load->magic = LOAD_MAGIC;
2502
2503 isc_mem_attach(zone->mctx, &load->mctx);
2504 zone_iattach(zone, &load->zone);
2505 dns_db_attach(db, &load->db);
2506 dns_rdatacallbacks_init(&load->callbacks);
2507 load->callbacks.rawdata = zone_setrawdata;
2508 zone_iattach(zone, &load->callbacks.zone);
2509 result = dns_db_beginload(db, &load->callbacks);
2510 if (result != ISC_R_SUCCESS)
2511 goto cleanup;
2512 result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->loadtask,
2513 zone_gotreadhandle, load,
2514 &zone->readio);
2515 if (result != ISC_R_SUCCESS) {
2516 /*
2517 * We can't report multiple errors so ignore
2518 * the result of dns_db_endload().
2519 */
2520 (void)dns_db_endload(load->db, &load->callbacks);
2521 goto cleanup;
2522 } else
2523 result = DNS_R_CONTINUE;
2524 } else {
2525 dns_rdatacallbacks_t callbacks;
2526
2527 dns_rdatacallbacks_init(&callbacks);
2528 callbacks.rawdata = zone_setrawdata;
2529 zone_iattach(zone, &callbacks.zone);
2530 result = dns_db_beginload(db, &callbacks);
2531 if (result != ISC_R_SUCCESS) {
2532 zone_idetach(&callbacks.zone);
2533 return (result);
2534 }
2535 result = dns_master_loadfile5(zone->masterfile,
2536 &zone->origin, &zone->origin,
2537 zone->rdclass, options, 0,
2538 &callbacks,
2539 zone_registerinclude,
2540 zone, zone->mctx,
2541 zone->masterformat,
2542 zone->maxttl);
2543 tresult = dns_db_endload(db, &callbacks);
2544 if (result == ISC_R_SUCCESS)
2545 result = tresult;
2546 zone_idetach(&callbacks.zone);
2547 }
2548
2549 return (result);
2550
2551 cleanup:
2552 load->magic = 0;
2553 dns_db_detach(&load->db);
2554 zone_idetach(&load->zone);
2555 zone_idetach(&load->callbacks.zone);
2556 isc_mem_detach(&load->mctx);
2557 isc_mem_put(zone->mctx, load, sizeof(*load));
2558 return (result);
2559 }
2560
2561 static isc_boolean_t
2562 zone_check_mx(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2563 dns_name_t *owner)
2564 {
2565 isc_result_t result;
2566 char ownerbuf[DNS_NAME_FORMATSIZE];
2567 char namebuf[DNS_NAME_FORMATSIZE];
2568 char altbuf[DNS_NAME_FORMATSIZE];
2569 dns_fixedname_t fixed;
2570 dns_name_t *foundname;
2571 int level;
2572
2573 /*
2574 * "." means the services does not exist.
2575 */
2576 if (dns_name_equal(name, dns_rootname))
2577 return (ISC_TRUE);
2578
2579 /*
2580 * Outside of zone.
2581 */
2582 if (!dns_name_issubdomain(name, &zone->origin)) {
2583 if (zone->checkmx != NULL)
2584 return ((zone->checkmx)(zone, name, owner));
2585 return (ISC_TRUE);
2586 }
2587
2588 if (zone->type == dns_zone_master)
2589 level = ISC_LOG_ERROR;
2590 else
2591 level = ISC_LOG_WARNING;
2592
2593 foundname = dns_fixedname_initname(&fixed);
2594
2595 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2596 0, 0, NULL, foundname, NULL, NULL);
2597 if (result == ISC_R_SUCCESS)
2598 return (ISC_TRUE);
2599
2600 if (result == DNS_R_NXRRSET) {
2601 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2602 0, 0, NULL, foundname, NULL, NULL);
2603 if (result == ISC_R_SUCCESS)
2604 return (ISC_TRUE);
2605 }
2606
2607 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2608 dns_name_format(name, namebuf, sizeof namebuf);
2609 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2610 result == DNS_R_EMPTYNAME) {
2611 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKMXFAIL))
2612 level = ISC_LOG_WARNING;
2613 dns_zone_log(zone, level,
2614 "%s/MX '%s' has no address records (A or AAAA)",
2615 ownerbuf, namebuf);
2616 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2617 }
2618
2619 if (result == DNS_R_CNAME) {
2620 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2621 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2622 level = ISC_LOG_WARNING;
2623 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2624 dns_zone_log(zone, level,
2625 "%s/MX '%s' is a CNAME (illegal)",
2626 ownerbuf, namebuf);
2627 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2628 }
2629
2630 if (result == DNS_R_DNAME) {
2631 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNMXCNAME) ||
2632 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME))
2633 level = ISC_LOG_WARNING;
2634 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNOREMXCNAME)) {
2635 dns_name_format(foundname, altbuf, sizeof altbuf);
2636 dns_zone_log(zone, level, "%s/MX '%s' is below a DNAME"
2637 " '%s' (illegal)", ownerbuf, namebuf,
2638 altbuf);
2639 }
2640 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2641 }
2642
2643 if (zone->checkmx != NULL && result == DNS_R_DELEGATION)
2644 return ((zone->checkmx)(zone, name, owner));
2645
2646 return (ISC_TRUE);
2647 }
2648
2649 static isc_boolean_t
2650 zone_check_srv(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2651 dns_name_t *owner)
2652 {
2653 isc_result_t result;
2654 char ownerbuf[DNS_NAME_FORMATSIZE];
2655 char namebuf[DNS_NAME_FORMATSIZE];
2656 char altbuf[DNS_NAME_FORMATSIZE];
2657 dns_fixedname_t fixed;
2658 dns_name_t *foundname;
2659 int level;
2660
2661 /*
2662 * "." means the services does not exist.
2663 */
2664 if (dns_name_equal(name, dns_rootname))
2665 return (ISC_TRUE);
2666
2667 /*
2668 * Outside of zone.
2669 */
2670 if (!dns_name_issubdomain(name, &zone->origin)) {
2671 if (zone->checksrv != NULL)
2672 return ((zone->checksrv)(zone, name, owner));
2673 return (ISC_TRUE);
2674 }
2675
2676 if (zone->type == dns_zone_master)
2677 level = ISC_LOG_ERROR;
2678 else
2679 level = ISC_LOG_WARNING;
2680
2681 foundname = dns_fixedname_initname(&fixed);
2682
2683 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2684 0, 0, NULL, foundname, NULL, NULL);
2685 if (result == ISC_R_SUCCESS)
2686 return (ISC_TRUE);
2687
2688 if (result == DNS_R_NXRRSET) {
2689 result = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2690 0, 0, NULL, foundname, NULL, NULL);
2691 if (result == ISC_R_SUCCESS)
2692 return (ISC_TRUE);
2693 }
2694
2695 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2696 dns_name_format(name, namebuf, sizeof namebuf);
2697 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2698 result == DNS_R_EMPTYNAME) {
2699 dns_zone_log(zone, level,
2700 "%s/SRV '%s' has no address records (A or AAAA)",
2701 ownerbuf, namebuf);
2702 /* XXX950 make fatal for 9.5.0. */
2703 return (ISC_TRUE);
2704 }
2705
2706 if (result == DNS_R_CNAME) {
2707 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2708 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2709 level = ISC_LOG_WARNING;
2710 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2711 dns_zone_log(zone, level,
2712 "%s/SRV '%s' is a CNAME (illegal)",
2713 ownerbuf, namebuf);
2714 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2715 }
2716
2717 if (result == DNS_R_DNAME) {
2718 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_WARNSRVCNAME) ||
2719 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME))
2720 level = ISC_LOG_WARNING;
2721 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IGNORESRVCNAME)) {
2722 dns_name_format(foundname, altbuf, sizeof altbuf);
2723 dns_zone_log(zone, level, "%s/SRV '%s' is below a "
2724 "DNAME '%s' (illegal)", ownerbuf, namebuf,
2725 altbuf);
2726 }
2727 return ((level == ISC_LOG_WARNING) ? ISC_TRUE : ISC_FALSE);
2728 }
2729
2730 if (zone->checksrv != NULL && result == DNS_R_DELEGATION)
2731 return ((zone->checksrv)(zone, name, owner));
2732
2733 return (ISC_TRUE);
2734 }
2735
2736 static isc_boolean_t
2737 zone_check_glue(dns_zone_t *zone, dns_db_t *db, dns_name_t *name,
2738 dns_name_t *owner)
2739 {
2740 isc_boolean_t answer = ISC_TRUE;
2741 isc_result_t result, tresult;
2742 char ownerbuf[DNS_NAME_FORMATSIZE];
2743 char namebuf[DNS_NAME_FORMATSIZE];
2744 char altbuf[DNS_NAME_FORMATSIZE];
2745 dns_fixedname_t fixed;
2746 dns_name_t *foundname;
2747 dns_rdataset_t a;
2748 dns_rdataset_t aaaa;
2749 int level;
2750
2751 /*
2752 * Outside of zone.
2753 */
2754 if (!dns_name_issubdomain(name, &zone->origin)) {
2755 if (zone->checkns != NULL)
2756 return ((zone->checkns)(zone, name, owner, NULL, NULL));
2757 return (ISC_TRUE);
2758 }
2759
2760 if (zone->type == dns_zone_master)
2761 level = ISC_LOG_ERROR;
2762 else
2763 level = ISC_LOG_WARNING;
2764
2765 foundname = dns_fixedname_initname(&fixed);
2766 dns_rdataset_init(&a);
2767 dns_rdataset_init(&aaaa);
2768
2769 /*
2770 * Perform a regular lookup to catch DNAME records then look
2771 * for glue.
2772 */
2773 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2774 0, 0, NULL, foundname, &a, NULL);
2775 switch (result) {
2776 case ISC_R_SUCCESS:
2777 case DNS_R_DNAME:
2778 case DNS_R_CNAME:
2779 break;
2780 default:
2781 if (dns_rdataset_isassociated(&a))
2782 dns_rdataset_disassociate(&a);
2783 result = dns_db_find(db, name, NULL, dns_rdatatype_a,
2784 DNS_DBFIND_GLUEOK, 0, NULL,
2785 foundname, &a, NULL);
2786 }
2787 if (result == ISC_R_SUCCESS) {
2788 dns_rdataset_disassociate(&a);
2789 return (ISC_TRUE);
2790 } else if (result == DNS_R_DELEGATION)
2791 dns_rdataset_disassociate(&a);
2792
2793 if (result == DNS_R_NXRRSET || result == DNS_R_DELEGATION ||
2794 result == DNS_R_GLUE) {
2795 tresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
2796 DNS_DBFIND_GLUEOK, 0, NULL,
2797 foundname, &aaaa, NULL);
2798 if (tresult == ISC_R_SUCCESS) {
2799 if (dns_rdataset_isassociated(&a))
2800 dns_rdataset_disassociate(&a);
2801 dns_rdataset_disassociate(&aaaa);
2802 return (ISC_TRUE);
2803 }
2804 if (tresult == DNS_R_DELEGATION || tresult == DNS_R_DNAME)
2805 dns_rdataset_disassociate(&aaaa);
2806 if (result == DNS_R_GLUE || tresult == DNS_R_GLUE) {
2807 /*
2808 * Check glue against child zone.
2809 */
2810 if (zone->checkns != NULL)
2811 answer = (zone->checkns)(zone, name, owner,
2812 &a, &aaaa);
2813 if (dns_rdataset_isassociated(&a))
2814 dns_rdataset_disassociate(&a);
2815 if (dns_rdataset_isassociated(&aaaa))
2816 dns_rdataset_disassociate(&aaaa);
2817 return (answer);
2818 }
2819 }
2820
2821 dns_name_format(owner, ownerbuf, sizeof ownerbuf);
2822 dns_name_format(name, namebuf, sizeof namebuf);
2823 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
2824 result == DNS_R_EMPTYNAME || result == DNS_R_DELEGATION) {
2825 const char *what;
2826 isc_boolean_t required = ISC_FALSE;
2827 if (dns_name_issubdomain(name, owner)) {
2828 what = "REQUIRED GLUE ";
2829 required = ISC_TRUE;
2830 } else if (result == DNS_R_DELEGATION)
2831 what = "SIBLING GLUE ";
2832 else
2833 what = "";
2834
2835 if (result != DNS_R_DELEGATION || required ||
2836 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSIBLING)) {
2837 dns_zone_log(zone, level, "%s/NS '%s' has no %s"
2838 "address records (A or AAAA)",
2839 ownerbuf, namebuf, what);
2840 /*
2841 * Log missing address record.
2842 */
2843 if (result == DNS_R_DELEGATION && zone->checkns != NULL)
2844 (void)(zone->checkns)(zone, name, owner,
2845 &a, &aaaa);
2846 /* XXX950 make fatal for 9.5.0. */
2847 /* answer = ISC_FALSE; */
2848 }
2849 } else if (result == DNS_R_CNAME) {
2850 dns_zone_log(zone, level, "%s/NS '%s' is a CNAME (illegal)",
2851 ownerbuf, namebuf);
2852 /* XXX950 make fatal for 9.5.0. */
2853 /* answer = ISC_FALSE; */
2854 } else if (result == DNS_R_DNAME) {
2855 dns_name_format(foundname, altbuf, sizeof altbuf);
2856 dns_zone_log(zone, level,
2857 "%s/NS '%s' is below a DNAME '%s' (illegal)",
2858 ownerbuf, namebuf, altbuf);
2859 /* XXX950 make fatal for 9.5.0. */
2860 /* answer = ISC_FALSE; */
2861 }
2862
2863 if (dns_rdataset_isassociated(&a))
2864 dns_rdataset_disassociate(&a);
2865 if (dns_rdataset_isassociated(&aaaa))
2866 dns_rdataset_disassociate(&aaaa);
2867 return (answer);
2868 }
2869
2870 static isc_boolean_t
2871 zone_rrset_check_dup(dns_zone_t *zone, dns_name_t *owner,
2872 dns_rdataset_t *rdataset)
2873 {
2874 dns_rdataset_t tmprdataset;
2875 isc_result_t result;
2876 isc_boolean_t answer = ISC_TRUE;
2877 isc_boolean_t format = ISC_TRUE;
2878 int level = ISC_LOG_WARNING;
2879 char ownerbuf[DNS_NAME_FORMATSIZE];
2880 char typebuf[DNS_RDATATYPE_FORMATSIZE];
2881 unsigned int count1 = 0;
2882
2883 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRRFAIL))
2884 level = ISC_LOG_ERROR;
2885
2886 dns_rdataset_init(&tmprdataset);
2887 for (result = dns_rdataset_first(rdataset);
2888 result == ISC_R_SUCCESS;
2889 result = dns_rdataset_next(rdataset)) {
2890 dns_rdata_t rdata1 = DNS_RDATA_INIT;
2891 unsigned int count2 = 0;
2892
2893 count1++;
2894 dns_rdataset_current(rdataset, &rdata1);
2895 dns_rdataset_clone(rdataset, &tmprdataset);
2896 for (result = dns_rdataset_first(&tmprdataset);
2897 result == ISC_R_SUCCESS;
2898 result = dns_rdataset_next(&tmprdataset)) {
2899 dns_rdata_t rdata2 = DNS_RDATA_INIT;
2900 count2++;
2901 if (count1 >= count2)
2902 continue;
2903 dns_rdataset_current(&tmprdataset, &rdata2);
2904 if (dns_rdata_casecompare(&rdata1, &rdata2) == 0) {
2905 if (format) {
2906 dns_name_format(owner, ownerbuf,
2907 sizeof ownerbuf);
2908 dns_rdatatype_format(rdata1.type,
2909 typebuf,
2910 sizeof(typebuf));
2911 format = ISC_FALSE;
2912 }
2913 dns_zone_log(zone, level, "%s/%s has "
2914 "semantically identical records",
2915 ownerbuf, typebuf);
2916 if (level == ISC_LOG_ERROR)
2917 answer = ISC_FALSE;
2918 break;
2919 }
2920 }
2921 dns_rdataset_disassociate(&tmprdataset);
2922 if (!format)
2923 break;
2924 }
2925 return (answer);
2926 }
2927
2928 static isc_boolean_t
2929 zone_check_dup(dns_zone_t *zone, dns_db_t *db) {
2930 dns_dbiterator_t *dbiterator = NULL;
2931 dns_dbnode_t *node = NULL;
2932 dns_fixedname_t fixed;
2933 dns_name_t *name;
2934 dns_rdataset_t rdataset;
2935 dns_rdatasetiter_t *rdsit = NULL;
2936 isc_boolean_t ok = ISC_TRUE;
2937 isc_result_t result;
2938
2939 name = dns_fixedname_initname(&fixed);
2940 dns_rdataset_init(&rdataset);
2941
2942 result = dns_db_createiterator(db, 0, &dbiterator);
2943 if (result != ISC_R_SUCCESS)
2944 return (ISC_TRUE);
2945
2946 for (result = dns_dbiterator_first(dbiterator);
2947 result == ISC_R_SUCCESS;
2948 result = dns_dbiterator_next(dbiterator)) {
2949 result = dns_dbiterator_current(dbiterator, &node, name);
2950 if (result != ISC_R_SUCCESS)
2951 continue;
2952
2953 result = dns_db_allrdatasets(db, node, NULL, 0, &rdsit);
2954 if (result != ISC_R_SUCCESS)
2955 continue;
2956
2957 for (result = dns_rdatasetiter_first(rdsit);
2958 result == ISC_R_SUCCESS;
2959 result = dns_rdatasetiter_next(rdsit)) {
2960 dns_rdatasetiter_current(rdsit, &rdataset);
2961 if (!zone_rrset_check_dup(zone, name, &rdataset))
2962 ok = ISC_FALSE;
2963 dns_rdataset_disassociate(&rdataset);
2964 }
2965 dns_rdatasetiter_destroy(&rdsit);
2966 dns_db_detachnode(db, &node);
2967 }
2968
2969 if (node != NULL)
2970 dns_db_detachnode(db, &node);
2971 dns_dbiterator_destroy(&dbiterator);
2972
2973 return (ok);
2974 }
2975
2976 static isc_boolean_t
2977 isspf(const dns_rdata_t *rdata) {
2978 char buf[1024];
2979 const unsigned char *data = rdata->data;
2980 unsigned int rdl = rdata->length, i = 0, tl, len;
2981
2982 while (rdl > 0U) {
2983 len = tl = *data;
2984 ++data;
2985 --rdl;
2986 INSIST(tl <= rdl);
2987 if (len > sizeof(buf) - i - 1)
2988 len = sizeof(buf) - i - 1;
2989 memmove(buf + i, data, len);
2990 i += len;
2991 data += tl;
2992 rdl -= tl;
2993 }
2994
2995 if (i < 6U)
2996 return(ISC_FALSE);
2997
2998 buf[i] = 0;
2999 if (strncmp(buf, "v=spf1", 6) == 0 && (buf[6] == 0 || buf[6] == ' '))
3000 return (ISC_TRUE);
3001 return (ISC_FALSE);
3002 }
3003
3004 static isc_boolean_t
3005 integrity_checks(dns_zone_t *zone, dns_db_t *db) {
3006 dns_dbiterator_t *dbiterator = NULL;
3007 dns_dbnode_t *node = NULL;
3008 dns_rdataset_t rdataset;
3009 dns_fixedname_t fixed;
3010 dns_fixedname_t fixedbottom;
3011 dns_rdata_mx_t mx;
3012 dns_rdata_ns_t ns;
3013 dns_rdata_in_srv_t srv;
3014 dns_rdata_t rdata;
3015 dns_name_t *name;
3016 dns_name_t *bottom;
3017 isc_result_t result;
3018 isc_boolean_t ok = ISC_TRUE, have_spf, have_txt;
3019
3020 name = dns_fixedname_initname(&fixed);
3021 bottom = dns_fixedname_initname(&fixedbottom);
3022 dns_rdataset_init(&rdataset);
3023 dns_rdata_init(&rdata);
3024
3025 result = dns_db_createiterator(db, 0, &dbiterator);
3026 if (result != ISC_R_SUCCESS)
3027 return (ISC_TRUE);
3028
3029 result = dns_dbiterator_first(dbiterator);
3030 while (result == ISC_R_SUCCESS) {
3031 result = dns_dbiterator_current(dbiterator, &node, name);
3032 if (result != ISC_R_SUCCESS)
3033 goto cleanup;
3034
3035 /*
3036 * Is this name visible in the zone?
3037 */
3038 if (!dns_name_issubdomain(name, &zone->origin) ||
3039 (dns_name_countlabels(bottom) > 0 &&
3040 dns_name_issubdomain(name, bottom)))
3041 goto next;
3042
3043 /*
3044 * Don't check the NS records at the origin.
3045 */
3046 if (dns_name_equal(name, &zone->origin))
3047 goto checkfordname;
3048
3049 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_ns,
3050 0, 0, &rdataset, NULL);
3051 if (result != ISC_R_SUCCESS)
3052 goto checkfordname;
3053 /*
3054 * Remember bottom of zone due to NS.
3055 */
3056 dns_name_copy(name, bottom, NULL);
3057
3058 result = dns_rdataset_first(&rdataset);
3059 while (result == ISC_R_SUCCESS) {
3060 dns_rdataset_current(&rdataset, &rdata);
3061 result = dns_rdata_tostruct(&rdata, &ns, NULL);
3062 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3063 if (!zone_check_glue(zone, db, &ns.name, name))
3064 ok = ISC_FALSE;
3065 dns_rdata_reset(&rdata);
3066 result = dns_rdataset_next(&rdataset);
3067 }
3068 dns_rdataset_disassociate(&rdataset);
3069 goto next;
3070
3071 checkfordname:
3072 result = dns_db_findrdataset(db, node, NULL,
3073 dns_rdatatype_dname, 0, 0,
3074 &rdataset, NULL);
3075 if (result == ISC_R_SUCCESS) {
3076 /*
3077 * Remember bottom of zone due to DNAME.
3078 */
3079 dns_name_copy(name, bottom, NULL);
3080 dns_rdataset_disassociate(&rdataset);
3081 }
3082
3083 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_mx,
3084 0, 0, &rdataset, NULL);
3085 if (result != ISC_R_SUCCESS)
3086 goto checksrv;
3087 result = dns_rdataset_first(&rdataset);
3088 while (result == ISC_R_SUCCESS) {
3089 dns_rdataset_current(&rdataset, &rdata);
3090 result = dns_rdata_tostruct(&rdata, &mx, NULL);
3091 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3092 if (!zone_check_mx(zone, db, &mx.mx, name))
3093 ok = ISC_FALSE;
3094 dns_rdata_reset(&rdata);
3095 result = dns_rdataset_next(&rdataset);
3096 }
3097 dns_rdataset_disassociate(&rdataset);
3098
3099 checksrv:
3100 if (zone->rdclass != dns_rdataclass_in)
3101 goto next;
3102 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_srv,
3103 0, 0, &rdataset, NULL);
3104 if (result != ISC_R_SUCCESS)
3105 goto checkspf;
3106 result = dns_rdataset_first(&rdataset);
3107 while (result == ISC_R_SUCCESS) {
3108 dns_rdataset_current(&rdataset, &rdata);
3109 result = dns_rdata_tostruct(&rdata, &srv, NULL);
3110 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3111 if (!zone_check_srv(zone, db, &srv.target, name))
3112 ok = ISC_FALSE;
3113 dns_rdata_reset(&rdata);
3114 result = dns_rdataset_next(&rdataset);
3115 }
3116 dns_rdataset_disassociate(&rdataset);
3117
3118 checkspf:
3119 /*
3120 * Check if there is a type SPF record without an
3121 * SPF-formatted type TXT record also being present.
3122 */
3123 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKSPF))
3124 goto next;
3125 if (zone->rdclass != dns_rdataclass_in)
3126 goto next;
3127 have_spf = have_txt = ISC_FALSE;
3128 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_spf,
3129 0, 0, &rdataset, NULL);
3130 if (result == ISC_R_SUCCESS) {
3131 dns_rdataset_disassociate(&rdataset);
3132 have_spf = ISC_TRUE;
3133 }
3134 result = dns_db_findrdataset(db, node, NULL, dns_rdatatype_txt,
3135 0, 0, &rdataset, NULL);
3136 if (result != ISC_R_SUCCESS)
3137 goto notxt;
3138 result = dns_rdataset_first(&rdataset);
3139 while (result == ISC_R_SUCCESS) {
3140 dns_rdataset_current(&rdataset, &rdata);
3141 have_txt = isspf(&rdata);
3142 dns_rdata_reset(&rdata);
3143 if (have_txt)
3144 break;
3145 result = dns_rdataset_next(&rdataset);
3146 }
3147 dns_rdataset_disassociate(&rdataset);
3148
3149 notxt:
3150 if (have_spf && !have_txt) {
3151 char namebuf[DNS_NAME_FORMATSIZE];
3152
3153 dns_name_format(name, namebuf, sizeof(namebuf));
3154 dns_zone_log(zone, ISC_LOG_WARNING, "'%s' found type "
3155 "SPF record but no SPF TXT record found, "
3156 "add matching type TXT record", namebuf);
3157 }
3158
3159 next:
3160 dns_db_detachnode(db, &node);
3161 result = dns_dbiterator_next(dbiterator);
3162 }
3163
3164 cleanup:
3165 if (node != NULL)
3166 dns_db_detachnode(db, &node);
3167 dns_dbiterator_destroy(&dbiterator);
3168
3169 return (ok);
3170 }
3171
3172 /*
3173 * OpenSSL verification of RSA keys with exponent 3 is known to be
3174 * broken prior OpenSSL 0.9.8c/0.9.7k. Look for such keys and warn
3175 * if they are in use.
3176 */
3177 static void
3178 zone_check_dnskeys(dns_zone_t *zone, dns_db_t *db) {
3179 dns_dbnode_t *node = NULL;
3180 dns_dbversion_t *version = NULL;
3181 dns_rdata_dnskey_t dnskey;
3182 dns_rdata_t rdata = DNS_RDATA_INIT;
3183 dns_rdataset_t rdataset;
3184 isc_result_t result;
3185 isc_boolean_t logit, foundrsa = ISC_FALSE, foundmd5 = ISC_FALSE;
3186 const char *algorithm;
3187
3188 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3189 if (result != ISC_R_SUCCESS)
3190 goto cleanup;
3191
3192 dns_db_currentversion(db, &version);
3193 dns_rdataset_init(&rdataset);
3194 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
3195 dns_rdatatype_none, 0, &rdataset, NULL);
3196 if (result != ISC_R_SUCCESS)
3197 goto cleanup;
3198
3199 for (result = dns_rdataset_first(&rdataset);
3200 result == ISC_R_SUCCESS;
3201 result = dns_rdataset_next(&rdataset))
3202 {
3203 dns_rdataset_current(&rdataset, &rdata);
3204 result = dns_rdata_tostruct(&rdata, &dnskey, NULL);
3205 INSIST(result == ISC_R_SUCCESS);
3206
3207 if ((dnskey.algorithm == DST_ALG_RSASHA1 ||
3208 dnskey.algorithm == DST_ALG_RSAMD5) &&
3209 dnskey.datalen > 1 && dnskey.data[0] == 1 &&
3210 dnskey.data[1] == 3)
3211 {
3212 if (dnskey.algorithm == DST_ALG_RSASHA1) {
3213 logit = !foundrsa;
3214 foundrsa = ISC_TRUE;
3215 algorithm = "RSASHA1";
3216 } else {
3217 logit = !foundmd5;
3218 foundmd5 = ISC_TRUE;
3219 algorithm = "RSAMD5";
3220 }
3221 if (logit)
3222 dns_zone_log(zone, ISC_LOG_WARNING,
3223 "weak %s (%u) key found "
3224 "(exponent=3)", algorithm,
3225 dnskey.algorithm);
3226 if (foundrsa && foundmd5)
3227 break;
3228 }
3229 dns_rdata_reset(&rdata);
3230 }
3231 dns_rdataset_disassociate(&rdataset);
3232
3233 cleanup:
3234 if (node != NULL)
3235 dns_db_detachnode(db, &node);
3236 if (version != NULL)
3237 dns_db_closeversion(db, &version, ISC_FALSE);
3238 }
3239
3240 static void
3241 resume_signingwithkey(dns_zone_t *zone) {
3242 dns_dbnode_t *node = NULL;
3243 dns_dbversion_t *version = NULL;
3244 dns_rdata_t rdata = DNS_RDATA_INIT;
3245 dns_rdataset_t rdataset;
3246 isc_result_t result;
3247 dns_db_t *db = NULL;
3248
3249 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3250 if (zone->db != NULL)
3251 dns_db_attach(zone->db, &db);
3252 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3253 if (db == NULL)
3254 goto cleanup;
3255
3256 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3257 if (result != ISC_R_SUCCESS)
3258 goto cleanup;
3259
3260 dns_db_currentversion(db, &version);
3261 dns_rdataset_init(&rdataset);
3262 result = dns_db_findrdataset(db, node, version,
3263 zone->privatetype,
3264 dns_rdatatype_none, 0,
3265 &rdataset, NULL);
3266 if (result != ISC_R_SUCCESS) {
3267 INSIST(!dns_rdataset_isassociated(&rdataset));
3268 goto cleanup;
3269 }
3270
3271 for (result = dns_rdataset_first(&rdataset);
3272 result == ISC_R_SUCCESS;
3273 result = dns_rdataset_next(&rdataset))
3274 {
3275 dns_rdataset_current(&rdataset, &rdata);
3276 if (rdata.length != 5 ||
3277 rdata.data[0] == 0 || rdata.data[4] != 0) {
3278 dns_rdata_reset(&rdata);
3279 continue;
3280 }
3281
3282 result = zone_signwithkey(zone, rdata.data[0],
3283 (rdata.data[1] << 8) | rdata.data[2],
3284 ISC_TF(rdata.data[3]));
3285 if (result != ISC_R_SUCCESS) {
3286 dns_zone_log(zone, ISC_LOG_ERROR,
3287 "zone_signwithkey failed: %s",
3288 dns_result_totext(result));
3289 }
3290 dns_rdata_reset(&rdata);
3291 }
3292 dns_rdataset_disassociate(&rdataset);
3293
3294 cleanup:
3295 if (db != NULL) {
3296 if (node != NULL)
3297 dns_db_detachnode(db, &node);
3298 if (version != NULL)
3299 dns_db_closeversion(db, &version, ISC_FALSE);
3300 dns_db_detach(&db);
3301 }
3302 }
3303
3304 /*
3305 * Initiate adding/removing NSEC3 records belonging to the chain defined by the
3306 * supplied NSEC3PARAM RDATA.
3307 *
3308 * Zone must be locked by caller.
3309 */
3310 static isc_result_t
3311 zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
3312 dns_nsec3chain_t *nsec3chain, *current;
3313 dns_dbversion_t *version = NULL;
3314 isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
3315 isc_result_t result;
3316 isc_time_t now;
3317 unsigned int options = 0;
3318 char saltbuf[255*2+1];
3319 char flags[sizeof("INITIAL|REMOVE|CREATE|NONSEC|OPTOUT")];
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 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3326
3327 if (db == NULL) {
3328 result = ISC_R_SUCCESS;
3329 goto cleanup;
3330 }
3331
3332 /*
3333 * If this zone is not NSEC3-capable, attempting to remove any NSEC3
3334 * chain from it is pointless as it would not be possible for the
3335 * latter to exist in the first place.
3336 */
3337 dns_db_currentversion(db, &version);
3338 result = dns_nsec_nseconly(db, version, &nseconly);
3339 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3340 dns_db_closeversion(db, &version, ISC_FALSE);
3341 if (!nsec3ok && (nsec3param->flags & DNS_NSEC3FLAG_REMOVE) == 0) {
3342 result = ISC_R_SUCCESS;
3343 goto cleanup;
3344 }
3345
3346 /*
3347 * Allocate and initialize structure preserving state of
3348 * adding/removing records belonging to this NSEC3 chain between
3349 * separate zone_nsec3chain() calls.
3350 */
3351 nsec3chain = isc_mem_get(zone->mctx, sizeof *nsec3chain);
3352 if (nsec3chain == NULL) {
3353 result = ISC_R_NOMEMORY;
3354 goto cleanup;
3355 }
3356
3357 nsec3chain->magic = 0;
3358 nsec3chain->done = ISC_FALSE;
3359 nsec3chain->db = NULL;
3360 nsec3chain->dbiterator = NULL;
3361 nsec3chain->nsec3param.common.rdclass = nsec3param->common.rdclass;
3362 nsec3chain->nsec3param.common.rdtype = nsec3param->common.rdtype;
3363 nsec3chain->nsec3param.hash = nsec3param->hash;
3364 nsec3chain->nsec3param.iterations = nsec3param->iterations;
3365 nsec3chain->nsec3param.flags = nsec3param->flags;
3366 nsec3chain->nsec3param.salt_length = nsec3param->salt_length;
3367 memmove(nsec3chain->salt, nsec3param->salt, nsec3param->salt_length);
3368 nsec3chain->nsec3param.salt = nsec3chain->salt;
3369 nsec3chain->seen_nsec = ISC_FALSE;
3370 nsec3chain->delete_nsec = ISC_FALSE;
3371 nsec3chain->save_delete_nsec = ISC_FALSE;
3372
3373 /*
3374 * Log NSEC3 parameters defined by supplied NSEC3PARAM RDATA.
3375 */
3376 if (nsec3param->flags == 0)
3377 strlcpy(flags, "NONE", sizeof(flags));
3378 else {
3379 flags[0] = '\0';
3380 if (nsec3param->flags & DNS_NSEC3FLAG_REMOVE)
3381 strlcat(flags, "REMOVE", sizeof(flags));
3382 if (nsec3param->flags & DNS_NSEC3FLAG_INITIAL) {
3383 if (flags[0] == '\0')
3384 strlcpy(flags, "INITIAL", sizeof(flags));
3385 else
3386 strlcat(flags, "|INITIAL", sizeof(flags));
3387 }
3388 if (nsec3param->flags & DNS_NSEC3FLAG_CREATE) {
3389 if (flags[0] == '\0')
3390 strlcpy(flags, "CREATE", sizeof(flags));
3391 else
3392 strlcat(flags, "|CREATE", sizeof(flags));
3393 }
3394 if (nsec3param->flags & DNS_NSEC3FLAG_NONSEC) {
3395 if (flags[0] == '\0')
3396 strlcpy(flags, "NONSEC", sizeof(flags));
3397 else
3398 strlcat(flags, "|NONSEC", sizeof(flags));
3399 }
3400 if (nsec3param->flags & DNS_NSEC3FLAG_OPTOUT) {
3401 if (flags[0] == '\0')
3402 strlcpy(flags, "OPTOUT", sizeof(flags));
3403 else
3404 strlcat(flags, "|OPTOUT", sizeof(flags));
3405 }
3406 }
3407 result = dns_nsec3param_salttotext(nsec3param, saltbuf,
3408 sizeof(saltbuf));
3409 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3410 dns_zone_log(zone, ISC_LOG_INFO,
3411 "zone_addnsec3chain(%u,%s,%u,%s)",
3412 nsec3param->hash, flags, nsec3param->iterations,
3413 saltbuf);
3414
3415 /*
3416 * If the NSEC3 chain defined by the supplied NSEC3PARAM RDATA is
3417 * currently being processed, interrupt its processing to avoid
3418 * simultaneously adding and removing records for the same NSEC3 chain.
3419 */
3420 for (current = ISC_LIST_HEAD(zone->nsec3chain);
3421 current != NULL;
3422 current = ISC_LIST_NEXT(current, link)) {
3423 if (current->db == db &&
3424 current->nsec3param.hash == nsec3param->hash &&
3425 current->nsec3param.iterations == nsec3param->iterations &&
3426 current->nsec3param.salt_length == nsec3param->salt_length
3427 && !memcmp(current->nsec3param.salt, nsec3param->salt,
3428 nsec3param->salt_length))
3429 current->done = ISC_TRUE;
3430 }
3431
3432 /*
3433 * Attach zone database to the structure initialized above and create
3434 * an iterator for it with appropriate options in order to avoid
3435 * creating NSEC3 records for NSEC3 records.
3436 */
3437 dns_db_attach(db, &nsec3chain->db);
3438 if ((nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0)
3439 options = DNS_DB_NONSEC3;
3440 result = dns_db_createiterator(nsec3chain->db, options,
3441 &nsec3chain->dbiterator);
3442 if (result == ISC_R_SUCCESS)
3443 result = dns_dbiterator_first(nsec3chain->dbiterator);
3444 if (result == ISC_R_SUCCESS) {
3445 /*
3446 * Database iterator initialization succeeded. We are now
3447 * ready to kick off adding/removing records belonging to this
3448 * NSEC3 chain. Append the structure initialized above to the
3449 * "nsec3chain" list for the zone and set the appropriate zone
3450 * timer so that zone_nsec3chain() is called as soon as
3451 * possible.
3452 */
3453 dns_dbiterator_pause(nsec3chain->dbiterator);
3454 ISC_LIST_INITANDAPPEND(zone->nsec3chain,
3455 nsec3chain, link);
3456 nsec3chain = NULL;
3457 if (isc_time_isepoch(&zone->nsec3chaintime)) {
3458 TIME_NOW(&now);
3459 zone->nsec3chaintime = now;
3460 if (zone->task != NULL)
3461 zone_settimer(zone, &now);
3462 }
3463 }
3464
3465 if (nsec3chain != NULL) {
3466 if (nsec3chain->db != NULL)
3467 dns_db_detach(&nsec3chain->db);
3468 if (nsec3chain->dbiterator != NULL)
3469 dns_dbiterator_destroy(&nsec3chain->dbiterator);
3470 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
3471 }
3472
3473 cleanup:
3474 if (db != NULL)
3475 dns_db_detach(&db);
3476 return (result);
3477 }
3478
3479 /*
3480 * Find private-type records at the zone apex which signal that an NSEC3 chain
3481 * should be added or removed. For each such record, extract NSEC3PARAM RDATA
3482 * and pass it to zone_addnsec3chain().
3483 *
3484 * Zone must be locked by caller.
3485 */
3486 static void
3487 resume_addnsec3chain(dns_zone_t *zone) {
3488 dns_dbnode_t *node = NULL;
3489 dns_dbversion_t *version = NULL;
3490 dns_rdataset_t rdataset;
3491 isc_result_t result;
3492 dns_rdata_nsec3param_t nsec3param;
3493 isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
3494 dns_db_t *db = NULL;
3495
3496 INSIST(LOCKED_ZONE(zone));
3497
3498 if (zone->privatetype == 0)
3499 return;
3500
3501 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3502 if (zone->db != NULL)
3503 dns_db_attach(zone->db, &db);
3504 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3505 if (db == NULL)
3506 goto cleanup;
3507
3508 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3509 if (result != ISC_R_SUCCESS)
3510 goto cleanup;
3511
3512 dns_db_currentversion(db, &version);
3513
3514 /*
3515 * In order to create NSEC3 chains we need the DNSKEY RRset at zone
3516 * apex to exist and contain no keys using NSEC-only algorithms.
3517 */
3518 result = dns_nsec_nseconly(db, version, &nseconly);
3519 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
3520
3521 /*
3522 * Get the RRset containing all private-type records at the zone apex.
3523 */
3524 dns_rdataset_init(&rdataset);
3525 result = dns_db_findrdataset(db, node, version,
3526 zone->privatetype, dns_rdatatype_none,
3527 0, &rdataset, NULL);
3528 if (result != ISC_R_SUCCESS) {
3529 INSIST(!dns_rdataset_isassociated(&rdataset));
3530 goto cleanup;
3531 }
3532
3533 for (result = dns_rdataset_first(&rdataset);
3534 result == ISC_R_SUCCESS;
3535 result = dns_rdataset_next(&rdataset))
3536 {
3537 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
3538 dns_rdata_t rdata = DNS_RDATA_INIT;
3539 dns_rdata_t private = DNS_RDATA_INIT;
3540
3541 dns_rdataset_current(&rdataset, &private);
3542 /*
3543 * Try extracting NSEC3PARAM RDATA from this private-type
3544 * record. Failure means this private-type record does not
3545 * represent an NSEC3PARAM record, so skip it.
3546 */
3547 if (!dns_nsec3param_fromprivate(&private, &rdata, buf,
3548 sizeof(buf)))
3549 continue;
3550 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3551 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3552 if (((nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) ||
3553 ((nsec3param.flags & DNS_NSEC3FLAG_CREATE) != 0 && nsec3ok))
3554 {
3555 /*
3556 * Pass the NSEC3PARAM RDATA contained in this
3557 * private-type record to zone_addnsec3chain() so that
3558 * it can kick off adding or removing NSEC3 records.
3559 */
3560 result = zone_addnsec3chain(zone, &nsec3param);
3561 if (result != ISC_R_SUCCESS) {
3562 dns_zone_log(zone, ISC_LOG_ERROR,
3563 "zone_addnsec3chain failed: %s",
3564 dns_result_totext(result));
3565 }
3566 }
3567 }
3568 dns_rdataset_disassociate(&rdataset);
3569 cleanup:
3570 if (db != NULL) {
3571 if (node != NULL)
3572 dns_db_detachnode(db, &node);
3573 if (version != NULL)
3574 dns_db_closeversion(db, &version, ISC_FALSE);
3575 dns_db_detach(&db);
3576 }
3577 }
3578
3579 static void
3580 set_resigntime(dns_zone_t *zone) {
3581 dns_rdataset_t rdataset;
3582 dns_fixedname_t fixed;
3583 unsigned int resign;
3584 isc_result_t result;
3585 isc_uint32_t nanosecs;
3586 dns_db_t *db = NULL;
3587
3588 /* We only re-sign zones that can be dynamically updated */
3589 if (zone->update_disabled)
3590 return;
3591
3592 if (!inline_secure(zone) && (zone->type != dns_zone_master ||
3593 (zone->ssutable == NULL &&
3594 (zone->update_acl == NULL || dns_acl_isnone(zone->update_acl)))))
3595 return;
3596
3597 dns_rdataset_init(&rdataset);
3598 dns_fixedname_init(&fixed);
3599
3600 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
3601 if (zone->db != NULL)
3602 dns_db_attach(zone->db, &db);
3603 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
3604 if (db == NULL) {
3605 isc_time_settoepoch(&zone->resigntime);
3606 return;
3607 }
3608
3609 result = dns_db_getsigningtime(db, &rdataset,
3610 dns_fixedname_name(&fixed));
3611 if (result != ISC_R_SUCCESS) {
3612 isc_time_settoepoch(&zone->resigntime);
3613 goto cleanup;
3614 }
3615
3616 resign = rdataset.resign - zone->sigresigninginterval;
3617 dns_rdataset_disassociate(&rdataset);
3618 isc_random_get(&nanosecs);
3619 nanosecs %= 1000000000;
3620 isc_time_set(&zone->resigntime, resign, nanosecs);
3621 cleanup:
3622 dns_db_detach(&db);
3623 return;
3624 }
3625
3626 static isc_result_t
3627 check_nsec3param(dns_zone_t *zone, dns_db_t *db) {
3628 dns_dbnode_t *node = NULL;
3629 dns_rdataset_t rdataset;
3630 dns_dbversion_t *version = NULL;
3631 dns_rdata_nsec3param_t nsec3param;
3632 isc_boolean_t ok = ISC_FALSE;
3633 isc_result_t result;
3634 dns_rdata_t rdata = DNS_RDATA_INIT;
3635 isc_boolean_t dynamic = (zone->type == dns_zone_master) ?
3636 dns_zone_isdynamic(zone, ISC_FALSE) : ISC_FALSE;
3637
3638 dns_rdataset_init(&rdataset);
3639 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
3640 if (result != ISC_R_SUCCESS) {
3641 dns_zone_log(zone, ISC_LOG_ERROR,
3642 "nsec3param lookup failure: %s",
3643 dns_result_totext(result));
3644 return (result);
3645 }
3646 dns_db_currentversion(db, &version);
3647
3648 result = dns_db_findrdataset(db, node, version,
3649 dns_rdatatype_nsec3param,
3650 dns_rdatatype_none, 0, &rdataset, NULL);
3651 if (result == ISC_R_NOTFOUND) {
3652 INSIST(!dns_rdataset_isassociated(&rdataset));
3653 result = ISC_R_SUCCESS;
3654 goto cleanup;
3655 }
3656 if (result != ISC_R_SUCCESS) {
3657 INSIST(!dns_rdataset_isassociated(&rdataset));
3658 dns_zone_log(zone, ISC_LOG_ERROR,
3659 "nsec3param lookup failure: %s",
3660 dns_result_totext(result));
3661 goto cleanup;
3662 }
3663
3664 /*
3665 * For dynamic zones we must support every algorithm so we can
3666 * regenerate all the NSEC3 chains.
3667 * For non-dynamic zones we only need to find a supported algorithm.
3668 */
3669 for (result = dns_rdataset_first(&rdataset);
3670 result == ISC_R_SUCCESS;
3671 result = dns_rdataset_next(&rdataset))
3672 {
3673 dns_rdataset_current(&rdataset, &rdata);
3674 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
3675 dns_rdata_reset(&rdata);
3676 INSIST(result == ISC_R_SUCCESS);
3677 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NSEC3TESTZONE) &&
3678 nsec3param.hash == DNS_NSEC3_UNKNOWNALG && !dynamic)
3679 {
3680 dns_zone_log(zone, ISC_LOG_WARNING,
3681 "nsec3 test \"unknown\" hash algorithm found: %u",
3682 nsec3param.hash);
3683 ok = ISC_TRUE;
3684 } else if (!dns_nsec3_supportedhash(nsec3param.hash)) {
3685 if (dynamic) {
3686 dns_zone_log(zone, ISC_LOG_ERROR,
3687 "unsupported nsec3 hash algorithm"
3688 " in dynamic zone: %u",
3689 nsec3param.hash);
3690 result = DNS_R_BADZONE;
3691 /* Stop second error message. */
3692 ok = ISC_TRUE;
3693 break;
3694 } else
3695 dns_zone_log(zone, ISC_LOG_WARNING,
3696 "unsupported nsec3 hash algorithm: %u",
3697 nsec3param.hash);
3698 } else
3699 ok = ISC_TRUE;
3700 }
3701 if (result == ISC_R_NOMORE)
3702 result = ISC_R_SUCCESS;
3703
3704 if (!ok) {
3705 result = DNS_R_BADZONE;
3706 dns_zone_log(zone, ISC_LOG_ERROR,
3707 "no supported nsec3 hash algorithm");
3708 }
3709
3710 cleanup:
3711 if (dns_rdataset_isassociated(&rdataset))
3712 dns_rdataset_disassociate(&rdataset);
3713 dns_db_closeversion(db, &version, ISC_FALSE);
3714 dns_db_detachnode(db, &node);
3715 return (result);
3716 }
3717
3718 /*
3719 * Set the timer for refreshing the key zone to the soonest future time
3720 * of the set (current timer, keydata->refresh, keydata->addhd,
3721 * keydata->removehd).
3722 */
3723 static void
3724 set_refreshkeytimer(dns_zone_t *zone, dns_rdata_keydata_t *key,
3725 isc_stdtime_t now, isc_boolean_t force)
3726 {
3727 const char me[] = "set_refreshkeytimer";
3728 isc_stdtime_t then;
3729 isc_time_t timenow, timethen;
3730 char timebuf[80];
3731
3732 ENTER;
3733 then = key->refresh;
3734 if (force)
3735 then = now;
3736 if (key->addhd > now && key->addhd < then)
3737 then = key->addhd;
3738 if (key->removehd > now && key->removehd < then)
3739 then = key->removehd;
3740
3741 TIME_NOW(&timenow);
3742 if (then > now)
3743 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
3744 else
3745 timethen = timenow;
3746 if (isc_time_compare(&zone->refreshkeytime, &timenow) < 0 ||
3747 isc_time_compare(&timethen, &zone->refreshkeytime) < 0)
3748 zone->refreshkeytime = timethen;
3749
3750 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
3751 dns_zone_log(zone, ISC_LOG_DEBUG(1), "next key refresh: %s", timebuf);
3752 zone_settimer(zone, &timenow);
3753 }
3754
3755 /*
3756 * Convert key(s) linked from 'keynode' to KEYDATA and add to the key zone.
3757 * If the key zone is changed, set '*changed' to ISC_TRUE.
3758 */
3759 static isc_result_t
3760 create_keydata(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
3761 dns_diff_t *diff, dns_keytable_t *keytable,
3762 dns_keynode_t **keynodep, isc_boolean_t *changed)
3763 {
3764 const char me[] = "create_keydata";
3765 isc_result_t result = ISC_R_SUCCESS;
3766 isc_buffer_t keyb, dstb;
3767 unsigned char key_buf[4096], dst_buf[DST_KEY_MAXSIZE];
3768 dns_rdata_keydata_t keydata;
3769 dns_rdata_dnskey_t dnskey;
3770 dns_rdata_t rdata = DNS_RDATA_INIT;
3771 dns_keynode_t *keynode;
3772 isc_stdtime_t now;
3773 isc_region_t r;
3774 dst_key_t *key;
3775
3776 REQUIRE(keynodep != NULL);
3777 keynode = *keynodep;
3778
3779 ENTER;
3780 isc_stdtime_get(&now);
3781
3782 /* Loop in case there's more than one key. */
3783 while (result == ISC_R_SUCCESS) {
3784 dns_keynode_t *nextnode = NULL;
3785
3786 key = dns_keynode_key(keynode);
3787 if (key == NULL)
3788 goto skip;
3789
3790 isc_buffer_init(&dstb, dst_buf, sizeof(dst_buf));
3791 CHECK(dst_key_todns(key, &dstb));
3792
3793 /* Convert DST key to DNSKEY. */
3794 dns_rdata_reset(&rdata);
3795 isc_buffer_usedregion(&dstb, &r);
3796 dns_rdata_fromregion(&rdata, dst_key_class(key),
3797 dns_rdatatype_dnskey, &r);
3798
3799 /* DSTKEY to KEYDATA. */
3800 CHECK(dns_rdata_tostruct(&rdata, &dnskey, NULL));
3801 CHECK(dns_keydata_fromdnskey(&keydata, &dnskey, now, 0, 0,
3802 NULL));
3803
3804 /* KEYDATA to rdata. */
3805 dns_rdata_reset(&rdata);
3806 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
3807 CHECK(dns_rdata_fromstruct(&rdata,
3808 zone->rdclass, dns_rdatatype_keydata,
3809 &keydata, &keyb));
3810
3811 /* Add rdata to zone. */
3812 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD,
3813 dst_key_name(key), 0, &rdata));
3814 *changed = ISC_TRUE;
3815
3816 /* Refresh new keys from the zone apex as soon as possible. */
3817 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3818
3819 skip:
3820 result = dns_keytable_nextkeynode(keytable, keynode, &nextnode);
3821 if (result != ISC_R_NOTFOUND) {
3822 dns_keytable_detachkeynode(keytable, &keynode);
3823 keynode = nextnode;
3824 }
3825 }
3826
3827 if (keynode != NULL)
3828 dns_keytable_detachkeynode(keytable, &keynode);
3829 *keynodep = NULL;
3830
3831 return (ISC_R_SUCCESS);
3832
3833 failure:
3834 return (result);
3835 }
3836
3837 /*
3838 * Remove from the key zone all the KEYDATA records found in rdataset.
3839 */
3840 static isc_result_t
3841 delete_keydata(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
3842 dns_name_t *name, dns_rdataset_t *rdataset)
3843 {
3844 dns_rdata_t rdata = DNS_RDATA_INIT;
3845 isc_result_t result, uresult;
3846
3847 for (result = dns_rdataset_first(rdataset);
3848 result == ISC_R_SUCCESS;
3849 result = dns_rdataset_next(rdataset)) {
3850 dns_rdata_reset(&rdata);
3851 dns_rdataset_current(rdataset, &rdata);
3852 uresult = update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
3853 name, 0, &rdata);
3854 if (uresult != ISC_R_SUCCESS)
3855 return (uresult);
3856 }
3857 if (result == ISC_R_NOMORE)
3858 result = ISC_R_SUCCESS;
3859 return (result);
3860 }
3861
3862 /*
3863 * Compute the DNSSEC key ID for a DNSKEY record.
3864 */
3865 static isc_result_t
3866 compute_tag(dns_name_t *name, dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx,
3867 dns_keytag_t *tag)
3868 {
3869 isc_result_t result;
3870 dns_rdata_t rdata = DNS_RDATA_INIT;
3871 unsigned char data[4096];
3872 isc_buffer_t buffer;
3873 dst_key_t *dstkey = NULL;
3874
3875 isc_buffer_init(&buffer, data, sizeof(data));
3876 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3877 dns_rdatatype_dnskey, dnskey, &buffer);
3878
3879 result = dns_dnssec_keyfromrdata(name, &rdata, mctx, &dstkey);
3880 if (result == ISC_R_SUCCESS)
3881 *tag = dst_key_id(dstkey);
3882 dst_key_free(&dstkey);
3883
3884 return (result);
3885 }
3886
3887 /*
3888 * Add key to the security roots.
3889 */
3890 static void
3891 trust_key(dns_zone_t *zone, dns_name_t *keyname,
3892 dns_rdata_dnskey_t *dnskey, isc_boolean_t initial,
3893 isc_mem_t *mctx)
3894 {
3895 isc_result_t result;
3896 dns_rdata_t rdata = DNS_RDATA_INIT;
3897 unsigned char data[4096];
3898 isc_buffer_t buffer;
3899 dns_keytable_t *sr = NULL;
3900 dst_key_t *dstkey = NULL;
3901
3902 /* Convert dnskey to DST key. */
3903 isc_buffer_init(&buffer, data, sizeof(data));
3904 dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
3905 dns_rdatatype_dnskey, dnskey, &buffer);
3906
3907 result = dns_view_getsecroots(zone->view, &sr);
3908 if (result != ISC_R_SUCCESS)
3909 goto failure;
3910
3911 CHECK(dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &dstkey));
3912 CHECK(dns_keytable_add2(sr, ISC_TRUE, initial, &dstkey));
3913 dns_keytable_detach(&sr);
3914
3915 failure:
3916 if (dstkey != NULL)
3917 dst_key_free(&dstkey);
3918 if (sr != NULL)
3919 dns_keytable_detach(&sr);
3920 return;
3921 }
3922
3923 /*
3924 * Add a null key to the security roots for so that all queries
3925 * to the zone will fail.
3926 */
3927 static void
3928 fail_secure(dns_zone_t *zone, dns_name_t *keyname) {
3929 isc_result_t result;
3930 dns_keytable_t *sr = NULL;
3931
3932 result = dns_view_getsecroots(zone->view, &sr);
3933 if (result == ISC_R_SUCCESS) {
3934 dns_keytable_marksecure(sr, keyname);
3935 dns_keytable_detach(&sr);
3936 }
3937 }
3938
3939 /*
3940 * Scan a set of KEYDATA records from the key zone. The ones that are
3941 * valid (i.e., the add holddown timer has expired) become trusted keys.
3942 */
3943 static void
3944 load_secroots(dns_zone_t *zone, dns_name_t *name, dns_rdataset_t *rdataset) {
3945 isc_result_t result;
3946 dns_rdata_t rdata = DNS_RDATA_INIT;
3947 dns_rdata_keydata_t keydata;
3948 dns_rdata_dnskey_t dnskey;
3949 isc_mem_t *mctx = zone->mctx;
3950 int trusted = 0, revoked = 0, pending = 0;
3951 isc_stdtime_t now;
3952 dns_keytable_t *sr = NULL;
3953
3954 isc_stdtime_get(&now);
3955
3956 result = dns_view_getsecroots(zone->view, &sr);
3957 if (result == ISC_R_SUCCESS) {
3958 dns_keytable_delete(sr, name);
3959 dns_keytable_detach(&sr);
3960 }
3961
3962 /* Now insert all the accepted trust anchors from this keydata set. */
3963 for (result = dns_rdataset_first(rdataset);
3964 result == ISC_R_SUCCESS;
3965 result = dns_rdataset_next(rdataset)) {
3966 dns_rdata_reset(&rdata);
3967 dns_rdataset_current(rdataset, &rdata);
3968
3969 /* Convert rdata to keydata. */
3970 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
3971 if (result == ISC_R_UNEXPECTEDEND)
3972 continue;
3973 RUNTIME_CHECK(result == ISC_R_SUCCESS);
3974
3975 /* Set the key refresh timer to force a fast refresh. */
3976 set_refreshkeytimer(zone, &keydata, now, ISC_TRUE);
3977
3978 /* If the removal timer is nonzero, this key was revoked. */
3979 if (keydata.removehd != 0) {
3980 revoked++;
3981 continue;
3982 }
3983
3984 /*
3985 * If the add timer is still pending, this key is not
3986 * trusted yet.
3987 */
3988 if (now < keydata.addhd) {
3989 pending++;
3990 continue;
3991 }
3992
3993 /* Convert keydata to dnskey. */
3994 dns_keydata_todnskey(&keydata, &dnskey, NULL);
3995
3996 /* Add to keytables. */
3997 trusted++;
3998 trust_key(zone, name, &dnskey,
3999 ISC_TF(keydata.addhd == 0), mctx);
4000 }
4001
4002 if (trusted == 0 && pending != 0) {
4003 char namebuf[DNS_NAME_FORMATSIZE];
4004 dns_name_format(name, namebuf, sizeof namebuf);
4005 dns_zone_log(zone, ISC_LOG_ERROR,
4006 "No valid trust anchors for '%s'!", namebuf);
4007 dns_zone_log(zone, ISC_LOG_ERROR,
4008 "%d key(s) revoked, %d still pending",
4009 revoked, pending);
4010 dns_zone_log(zone, ISC_LOG_ERROR,
4011 "All queries to '%s' will fail", namebuf);
4012 fail_secure(zone, name);
4013 }
4014 }
4015
4016 static isc_result_t
4017 do_one_tuple(dns_difftuple_t **tuple, dns_db_t *db, dns_dbversion_t *ver,
4018 dns_diff_t *diff)
4019 {
4020 dns_diff_t temp_diff;
4021 isc_result_t result;
4022
4023 /*
4024 * Create a singleton diff.
4025 */
4026 dns_diff_init(diff->mctx, &temp_diff);
4027 ISC_LIST_APPEND(temp_diff.tuples, *tuple, link);
4028
4029 /*
4030 * Apply it to the database.
4031 */
4032 result = dns_diff_apply(&temp_diff, db, ver);
4033 ISC_LIST_UNLINK(temp_diff.tuples, *tuple, link);
4034 if (result != ISC_R_SUCCESS) {
4035 dns_difftuple_free(tuple);
4036 return (result);
4037 }
4038
4039 /*
4040 * Merge it into the current pending journal entry.
4041 */
4042 dns_diff_appendminimal(diff, tuple);
4043
4044 /*
4045 * Do not clear temp_diff.
4046 */
4047 return (ISC_R_SUCCESS);
4048 }
4049
4050 static isc_result_t
4051 update_one_rr(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4052 dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl,
4053 dns_rdata_t *rdata)
4054 {
4055 dns_difftuple_t *tuple = NULL;
4056 isc_result_t result;
4057 result = dns_difftuple_create(diff->mctx, op,
4058 name, ttl, rdata, &tuple);
4059 if (result != ISC_R_SUCCESS)
4060 return (result);
4061 return (do_one_tuple(&tuple, db, ver, diff));
4062 }
4063
4064 static isc_result_t
4065 update_soa_serial(dns_db_t *db, dns_dbversion_t *ver, dns_diff_t *diff,
4066 isc_mem_t *mctx, dns_updatemethod_t method) {
4067 dns_difftuple_t *deltuple = NULL;
4068 dns_difftuple_t *addtuple = NULL;
4069 isc_uint32_t serial;
4070 isc_result_t result;
4071
4072 INSIST(method != dns_updatemethod_none);
4073
4074 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_DEL, &deltuple));
4075 CHECK(dns_difftuple_copy(deltuple, &addtuple));
4076 addtuple->op = DNS_DIFFOP_ADD;
4077
4078 serial = dns_soa_getserial(&addtuple->rdata);
4079 serial = dns_update_soaserial(serial, method);
4080 dns_soa_setserial(serial, &addtuple->rdata);
4081 CHECK(do_one_tuple(&deltuple, db, ver, diff));
4082 CHECK(do_one_tuple(&addtuple, db, ver, diff));
4083 result = ISC_R_SUCCESS;
4084
4085 failure:
4086 if (addtuple != NULL)
4087 dns_difftuple_free(&addtuple);
4088 if (deltuple != NULL)
4089 dns_difftuple_free(&deltuple);
4090 return (result);
4091 }
4092
4093 /*
4094 * Write all transactions in 'diff' to the zone journal file.
4095 */
4096 static isc_result_t
4097 zone_journal(dns_zone_t *zone, dns_diff_t *diff, isc_uint32_t *sourceserial,
4098 const char *caller)
4099 {
4100 const char me[] = "zone_journal";
4101 const char *journalfile;
4102 isc_result_t result = ISC_R_SUCCESS;
4103 dns_journal_t *journal = NULL;
4104 unsigned int mode = DNS_JOURNAL_CREATE|DNS_JOURNAL_WRITE;
4105
4106 ENTER;
4107 journalfile = dns_zone_getjournal(zone);
4108 if (journalfile != NULL) {
4109 result = dns_journal_open(zone->mctx, journalfile, mode,
4110 &journal);
4111 if (result != ISC_R_SUCCESS) {
4112 dns_zone_log(zone, ISC_LOG_ERROR,
4113 "%s:dns_journal_open -> %s",
4114 caller, dns_result_totext(result));
4115 return (result);
4116 }
4117
4118 if (sourceserial != NULL)
4119 dns_journal_set_sourceserial(journal, *sourceserial);
4120
4121 result = dns_journal_write_transaction(journal, diff);
4122 if (result != ISC_R_SUCCESS) {
4123 dns_zone_log(zone, ISC_LOG_ERROR,
4124 "%s:dns_journal_write_transaction -> %s",
4125 caller, dns_result_totext(result));
4126 }
4127 dns_journal_destroy(&journal);
4128 }
4129
4130 return (result);
4131 }
4132
4133 /*
4134 * Create an SOA record for a newly-created zone
4135 */
4136 static isc_result_t
4137 add_soa(dns_zone_t *zone, dns_db_t *db) {
4138 isc_result_t result;
4139 dns_rdata_t rdata = DNS_RDATA_INIT;
4140 unsigned char buf[DNS_SOA_BUFFERSIZE];
4141 dns_dbversion_t *ver = NULL;
4142 dns_diff_t diff;
4143
4144 dns_zone_log(zone, ISC_LOG_DEBUG(1), "creating SOA");
4145
4146 dns_diff_init(zone->mctx, &diff);
4147 result = dns_db_newversion(db, &ver);
4148 if (result != ISC_R_SUCCESS) {
4149 dns_zone_log(zone, ISC_LOG_ERROR,
4150 "add_soa:dns_db_newversion -> %s",
4151 dns_result_totext(result));
4152 goto failure;
4153 }
4154
4155 /* Build SOA record */
4156 result = dns_soa_buildrdata(&zone->origin, dns_rootname, zone->rdclass,
4157 0, 0, 0, 0, 0, buf, &rdata);
4158 if (result != ISC_R_SUCCESS) {
4159 dns_zone_log(zone, ISC_LOG_ERROR,
4160 "add_soa:dns_soa_buildrdata -> %s",
4161 dns_result_totext(result));
4162 goto failure;
4163 }
4164
4165 result = update_one_rr(db, ver, &diff, DNS_DIFFOP_ADD,
4166 &zone->origin, 0, &rdata);
4167
4168 failure:
4169 dns_diff_clear(&diff);
4170 if (ver != NULL)
4171 dns_db_closeversion(db, &ver, ISC_TF(result == ISC_R_SUCCESS));
4172
4173 INSIST(ver == NULL);
4174
4175 return (result);
4176 }
4177
4178 struct addifmissing_arg {
4179 dns_db_t *db;
4180 dns_dbversion_t *ver;
4181 dns_diff_t *diff;
4182 dns_zone_t *zone;
4183 isc_boolean_t *changed;
4184 isc_result_t result;
4185 };
4186
4187 static void
4188 addifmissing(dns_keytable_t *keytable, dns_keynode_t *keynode, void *arg) {
4189 dns_db_t *db = ((struct addifmissing_arg *)arg)->db;
4190 dns_dbversion_t *ver = ((struct addifmissing_arg *)arg)->ver;
4191 dns_diff_t *diff = ((struct addifmissing_arg *)arg)->diff;
4192 dns_zone_t *zone = ((struct addifmissing_arg *)arg)->zone;
4193 isc_boolean_t *changed = ((struct addifmissing_arg *)arg)->changed;
4194 isc_result_t result;
4195 dns_keynode_t *dummy = NULL;
4196
4197 if (((struct addifmissing_arg *)arg)->result != ISC_R_SUCCESS)
4198 return;
4199
4200 if (dns_keynode_managed(keynode)) {
4201 dns_fixedname_t fname;
4202 dns_name_t *keyname;
4203 dst_key_t *key;
4204
4205 key = dns_keynode_key(keynode);
4206 if (key == NULL)
4207 return;
4208 dns_fixedname_init(&fname);
4209
4210 keyname = dst_key_name(key);
4211 result = dns_db_find(db, keyname, ver,
4212 dns_rdatatype_keydata,
4213 DNS_DBFIND_NOWILD, 0, NULL,
4214 dns_fixedname_name(&fname),
4215 NULL, NULL);
4216 if (result == ISC_R_SUCCESS)
4217 return;
4218 dns_keytable_attachkeynode(keytable, keynode, &dummy);
4219 result = create_keydata(zone, db, ver, diff, keytable,
4220 &dummy, changed);
4221 if (result != ISC_R_SUCCESS && result != ISC_R_NOMORE)
4222 ((struct addifmissing_arg *)arg)->result = result;
4223 }
4224 };
4225
4226 /*
4227 * Synchronize the set of initializing keys found in managed-keys {}
4228 * statements with the set of trust anchors found in the managed-keys.bind
4229 * zone. If a domain is no longer named in managed-keys, delete all keys
4230 * from that domain from the key zone. If a domain is mentioned in in
4231 * managed-keys but there are no references to it in the key zone, load
4232 * the key zone with the initializing key(s) for that domain.
4233 */
4234 static isc_result_t
4235 sync_keyzone(dns_zone_t *zone, dns_db_t *db) {
4236 isc_result_t result = ISC_R_SUCCESS;
4237 isc_boolean_t changed = ISC_FALSE;
4238 isc_boolean_t commit = ISC_FALSE;
4239 dns_keynode_t *keynode = NULL;
4240 dns_view_t *view = zone->view;
4241 dns_keytable_t *sr = NULL;
4242 dns_dbversion_t *ver = NULL;
4243 dns_diff_t diff;
4244 dns_rriterator_t rrit;
4245 struct addifmissing_arg arg;
4246
4247 dns_zone_log(zone, ISC_LOG_DEBUG(1), "synchronizing trusted keys");
4248
4249 dns_diff_init(zone->mctx, &diff);
4250
4251 CHECK(dns_view_getsecroots(view, &sr));
4252
4253 result = dns_db_newversion(db, &ver);
4254 if (result != ISC_R_SUCCESS) {
4255 dns_zone_log(zone, ISC_LOG_ERROR,
4256 "sync_keyzone:dns_db_newversion -> %s",
4257 dns_result_totext(result));
4258 goto failure;
4259 }
4260
4261 /*
4262 * Walk the zone DB. If we find any keys whose names are no longer
4263 * in managed-keys (or *are* in trusted-keys, meaning they are
4264 * permanent and not RFC5011-maintained), delete them from the
4265 * zone. Otherwise call load_secroots(), which loads keys into
4266 * secroots as appropriate.
4267 */
4268 dns_rriterator_init(&rrit, db, ver, 0);
4269 for (result = dns_rriterator_first(&rrit);
4270 result == ISC_R_SUCCESS;
4271 result = dns_rriterator_nextrrset(&rrit)) {
4272 dns_rdataset_t *rdataset = NULL;
4273 dns_name_t *rrname = NULL;
4274 isc_uint32_t ttl;
4275
4276 dns_rriterator_current(&rrit, &rrname, &ttl, &rdataset, NULL);
4277 if (!dns_rdataset_isassociated(rdataset)) {
4278 dns_rriterator_destroy(&rrit);
4279 goto failure;
4280 }
4281
4282 if (rdataset->type != dns_rdatatype_keydata)
4283 continue;
4284
4285 result = dns_keytable_find(sr, rrname, &keynode);
4286 if ((result != ISC_R_SUCCESS &&
4287 result != DNS_R_PARTIALMATCH) ||
4288 dns_keynode_managed(keynode) == ISC_FALSE)
4289 {
4290 CHECK(delete_keydata(db, ver, &diff,
4291 rrname, rdataset));
4292 changed = ISC_TRUE;
4293 } else {
4294 load_secroots(zone, rrname, rdataset);
4295 }
4296
4297 if (keynode != NULL)
4298 dns_keytable_detachkeynode(sr, &keynode);
4299 }
4300 dns_rriterator_destroy(&rrit);
4301
4302 /*
4303 * Now walk secroots to find any managed keys that aren't
4304 * in the zone. If we find any, we add them to the zone.
4305 */
4306 arg.db = db;
4307 arg.ver = ver;
4308 arg.result = ISC_R_SUCCESS;
4309 arg.diff = &diff;
4310 arg.zone = zone;
4311 arg.changed = &changed;
4312 dns_keytable_forall(sr, addifmissing, &arg);
4313 result = arg.result;
4314 if (changed) {
4315 /* Write changes to journal file. */
4316 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
4317 zone->updatemethod));
4318 CHECK(zone_journal(zone, &diff, NULL, "sync_keyzone"));
4319
4320 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
4321 zone_needdump(zone, 30);
4322 commit = ISC_TRUE;
4323 }
4324
4325 failure:
4326 if (result != ISC_R_SUCCESS &&
4327 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
4328 dns_zone_log(zone, ISC_LOG_ERROR,
4329 "unable to synchronize managed keys: %s",
4330 dns_result_totext(result));
4331 isc_time_settoepoch(&zone->refreshkeytime);
4332 }
4333 if (keynode != NULL)
4334 dns_keytable_detachkeynode(sr, &keynode);
4335 if (sr != NULL)
4336 dns_keytable_detach(&sr);
4337 if (ver != NULL)
4338 dns_db_closeversion(db, &ver, commit);
4339 dns_diff_clear(&diff);
4340
4341 INSIST(ver == NULL);
4342
4343 return (result);
4344 }
4345
4346 isc_result_t
4347 dns_zone_synckeyzone(dns_zone_t *zone) {
4348 isc_result_t result;
4349 dns_db_t *db = NULL;
4350
4351 if (zone->type != dns_zone_key)
4352 return (DNS_R_BADZONE);
4353
4354 CHECK(dns_zone_getdb(zone, &db));
4355
4356 LOCK_ZONE(zone);
4357 result = sync_keyzone(zone, db);
4358 UNLOCK_ZONE(zone);
4359
4360 failure:
4361 if (db != NULL)
4362 dns_db_detach(&db);
4363 return (result);
4364 }
4365
4366 static void
4367 maybe_send_secure(dns_zone_t *zone) {
4368 isc_result_t result;
4369
4370 /*
4371 * We've finished loading, or else failed to load, an inline-signing
4372 * 'secure' zone. We now need information about the status of the
4373 * 'raw' zone. If we failed to load, then we need it to send a
4374 * copy of its database; if we succeeded, we need it to send its
4375 * serial number so that we can sync with it. If it has not yet
4376 * loaded, we set a flag so that it will send the necessary
4377 * information when it has finished loading.
4378 */
4379 if (zone->raw->db != NULL) {
4380 if (zone->db != NULL) {
4381 isc_uint32_t serial;
4382 unsigned int soacount;
4383
4384 result = zone_get_from_db(zone->raw, zone->raw->db,
4385 NULL, &soacount, &serial, NULL,
4386 NULL, NULL, NULL, NULL);
4387 if (result == ISC_R_SUCCESS && soacount > 0U)
4388 zone_send_secureserial(zone->raw, serial);
4389 } else
4390 zone_send_securedb(zone->raw, zone->raw->db);
4391
4392 } else
4393 DNS_ZONE_SETFLAG(zone->raw, DNS_ZONEFLG_SENDSECURE);
4394 }
4395
4396 static isc_boolean_t
4397 zone_unchanged(dns_db_t *db1, dns_db_t *db2, isc_mem_t *mctx) {
4398 isc_result_t result;
4399 isc_boolean_t answer = ISC_FALSE;
4400 dns_diff_t diff;
4401
4402 dns_diff_init(mctx, &diff);
4403 result = dns_db_diffx(&diff, db1, NULL, db2, NULL, NULL);
4404 if (result == ISC_R_SUCCESS && ISC_LIST_EMPTY(diff.tuples))
4405 answer = ISC_TRUE;
4406 dns_diff_clear(&diff);
4407 return (answer);
4408 }
4409
4410 /*
4411 * The zone is presumed to be locked.
4412 * If this is a inline_raw zone the secure version is also locked.
4413 */
4414 static isc_result_t
4415 zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
4416 isc_result_t result)
4417 {
4418 unsigned int soacount = 0;
4419 unsigned int nscount = 0;
4420 unsigned int errors = 0;
4421 isc_uint32_t serial, oldserial, refresh, retry, expire, minimum;
4422 isc_time_t now;
4423 isc_boolean_t needdump = ISC_FALSE;
4424 isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4425 isc_boolean_t nomaster = ISC_FALSE;
4426 unsigned int options;
4427 dns_include_t *inc;
4428
4429 INSIST(LOCKED_ZONE(zone));
4430 if (inline_raw(zone))
4431 INSIST(LOCKED_ZONE(zone->secure));
4432
4433 TIME_NOW(&now);
4434
4435 /*
4436 * Initiate zone transfer? We may need a error code that
4437 * indicates that the "permanent" form does not exist.
4438 * XXX better error feedback to log.
4439 */
4440 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
4441 if (zone->type == dns_zone_slave ||
4442 zone->type == dns_zone_stub ||
4443 (zone->type == dns_zone_redirect &&
4444 zone->masters == NULL)) {
4445 if (result == ISC_R_FILENOTFOUND)
4446 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4447 ISC_LOG_DEBUG(1),
4448 "no master file");
4449 else if (result != DNS_R_NOMASTERFILE)
4450 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4451 ISC_LOG_ERROR,
4452 "loading from master file %s "
4453 "failed: %s",
4454 zone->masterfile,
4455 dns_result_totext(result));
4456 } else if (zone->type == dns_zone_master &&
4457 inline_secure(zone) && result == ISC_R_FILENOTFOUND)
4458 {
4459 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4460 ISC_LOG_DEBUG(1),
4461 "no master file, requesting db");
4462 maybe_send_secure(zone);
4463 } else {
4464 int level = ISC_LOG_ERROR;
4465 if (zone->type == dns_zone_key &&
4466 result == ISC_R_FILENOTFOUND)
4467 level = ISC_LOG_DEBUG(1);
4468 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, level,
4469 "loading from master file %s failed: %s",
4470 zone->masterfile,
4471 dns_result_totext(result));
4472 nomaster = ISC_TRUE;
4473 }
4474
4475 if (zone->type != dns_zone_key)
4476 goto cleanup;
4477 }
4478
4479 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(2),
4480 "number of nodes in database: %u",
4481 dns_db_nodecount(db));
4482
4483 if (result == DNS_R_SEENINCLUDE)
4484 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4485 else
4486 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE);
4487
4488 /*
4489 * If there's no master file for a key zone, then the zone is new:
4490 * create an SOA record. (We do this now, instead of later, so that
4491 * if there happens to be a journal file, we can roll forward from
4492 * a sane starting point.)
4493 */
4494 if (nomaster && zone->type == dns_zone_key) {
4495 result = add_soa(zone, db);
4496 if (result != ISC_R_SUCCESS)
4497 goto cleanup;
4498 }
4499
4500 /*
4501 * Apply update log, if any, on initial load.
4502 */
4503 if (zone->journal != NULL &&
4504 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) &&
4505 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
4506 {
4507 if (zone->type == dns_zone_master &&
4508 (zone->update_acl != NULL || zone->ssutable != NULL))
4509 options = DNS_JOURNALOPT_RESIGN;
4510 else
4511 options = 0;
4512 result = dns_journal_rollforward(zone->mctx, db, options,
4513 zone->journal);
4514 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND &&
4515 result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL &&
4516 result != ISC_R_RANGE)
4517 {
4518 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4519 ISC_LOG_ERROR,
4520 "journal rollforward failed: %s",
4521 dns_result_totext(result));
4522 goto cleanup;
4523
4524
4525 }
4526 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
4527 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4528 ISC_LOG_ERROR,
4529 "journal rollforward failed: "
4530 "journal out of sync with zone");
4531 goto cleanup;
4532 }
4533 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4534 "journal rollforward completed "
4535 "successfully: %s",
4536 dns_result_totext(result));
4537 if (result == ISC_R_SUCCESS)
4538 needdump = ISC_TRUE;
4539 }
4540
4541 /*
4542 * Obtain ns, soa and cname counts for top of zone.
4543 */
4544 INSIST(db != NULL);
4545 result = zone_get_from_db(zone, db, &nscount, &soacount, &serial,
4546 &refresh, &retry, &expire, &minimum,
4547 &errors);
4548 if (result != ISC_R_SUCCESS && zone->type != dns_zone_key) {
4549 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_ERROR,
4550 "could not find NS and/or SOA records");
4551 }
4552
4553 /*
4554 * Check to make sure the journal is up to date, and remove the
4555 * journal file if it isn't, as we wouldn't be able to apply
4556 * updates otherwise.
4557 */
4558 if (zone->journal != NULL && dns_zone_isdynamic(zone, ISC_TRUE) &&
4559 ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
4560 isc_uint32_t jserial;
4561 dns_journal_t *journal = NULL;
4562 isc_boolean_t empty = ISC_FALSE;
4563
4564 result = dns_journal_open(zone->mctx, zone->journal,
4565 DNS_JOURNAL_READ, &journal);
4566 if (result == ISC_R_SUCCESS) {
4567 jserial = dns_journal_last_serial(journal);
4568 empty = dns_journal_empty(journal);
4569 dns_journal_destroy(&journal);
4570 } else {
4571 jserial = serial;
4572 result = ISC_R_SUCCESS;
4573 }
4574
4575 if (jserial != serial) {
4576 if (!empty)
4577 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4578 ISC_LOG_INFO,
4579 "journal file is out of date: "
4580 "removing journal file");
4581 if (remove(zone->journal) < 0 && errno != ENOENT) {
4582 char strbuf[ISC_STRERRORSIZE];
4583 isc__strerror(errno, strbuf, sizeof(strbuf));
4584 isc_log_write(dns_lctx,
4585 DNS_LOGCATEGORY_GENERAL,
4586 DNS_LOGMODULE_ZONE,
4587 ISC_LOG_WARNING,
4588 "unable to remove journal "
4589 "'%s': '%s'",
4590 zone->journal, strbuf);
4591 }
4592 }
4593 }
4594
4595 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
4596 "loaded; checking validity");
4597
4598 /*
4599 * Master / Slave / Stub zones require both NS and SOA records at
4600 * the top of the zone.
4601 */
4602
4603 switch (zone->type) {
4604 case dns_zone_dlz:
4605 case dns_zone_master:
4606 case dns_zone_slave:
4607 case dns_zone_stub:
4608 case dns_zone_redirect:
4609 if (soacount != 1) {
4610 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4611 ISC_LOG_ERROR,
4612 "has %d SOA records", soacount);
4613 result = DNS_R_BADZONE;
4614 }
4615 if (nscount == 0) {
4616 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4617 ISC_LOG_ERROR,
4618 "has no NS records");
4619 result = DNS_R_BADZONE;
4620 }
4621 if (result != ISC_R_SUCCESS)
4622 goto cleanup;
4623 if (zone->type == dns_zone_master && errors != 0) {
4624 result = DNS_R_BADZONE;
4625 goto cleanup;
4626 }
4627 if (zone->type != dns_zone_stub &&
4628 zone->type != dns_zone_redirect) {
4629 result = check_nsec3param(zone, db);
4630 if (result != ISC_R_SUCCESS)
4631 goto cleanup;
4632 }
4633 if (zone->type == dns_zone_master &&
4634 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKINTEGRITY) &&
4635 !integrity_checks(zone, db)) {
4636 result = DNS_R_BADZONE;
4637 goto cleanup;
4638 }
4639 if (zone->type == dns_zone_master &&
4640 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKDUPRR) &&
4641 !zone_check_dup(zone, db)) {
4642 result = DNS_R_BADZONE;
4643 goto cleanup;
4644 }
4645
4646 if (zone->db != NULL) {
4647 unsigned int oldsoacount;
4648
4649 /*
4650 * This is checked in zone_replacedb() for slave zones
4651 * as they don't reload from disk.
4652 */
4653 result = zone_get_from_db(zone, zone->db, NULL,
4654 &oldsoacount, &oldserial,
4655 NULL, NULL, NULL, NULL,
4656 NULL);
4657 RUNTIME_CHECK(result == ISC_R_SUCCESS);
4658 RUNTIME_CHECK(soacount > 0U);
4659 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
4660 !isc_serial_gt(serial, oldserial)) {
4661 isc_uint32_t serialmin, serialmax;
4662
4663 INSIST(zone->type == dns_zone_master);
4664
4665 if (serial == oldserial &&
4666 zone_unchanged(zone->db, db, zone->mctx)) {
4667 dns_zone_logc(zone,
4668 DNS_LOGCATEGORY_ZONELOAD,
4669 ISC_LOG_INFO,
4670 "ixfr-from-differences: "
4671 "unchanged");
4672 return(ISC_R_SUCCESS);
4673 }
4674
4675 serialmin = (oldserial + 1) & 0xffffffffU;
4676 serialmax = (oldserial + 0x7fffffffU) &
4677 0xffffffffU;
4678 dns_zone_logc(zone,
4679 DNS_LOGCATEGORY_ZONELOAD,
4680 ISC_LOG_ERROR,
4681 "ixfr-from-differences: "
4682 "new serial (%u) out of range "
4683 "[%u - %u]", serial, serialmin,
4684 serialmax);
4685 result = DNS_R_BADZONE;
4686 goto cleanup;
4687 } else if (!isc_serial_ge(serial, oldserial))
4688 dns_zone_logc(zone,
4689 DNS_LOGCATEGORY_ZONELOAD,
4690 ISC_LOG_ERROR,
4691 "zone serial (%u/%u) has gone "
4692 "backwards", serial, oldserial);
4693 else if (serial == oldserial && !hasinclude &&
4694 strcmp(zone->db_argv[0], "_builtin") != 0)
4695 dns_zone_logc(zone,
4696 DNS_LOGCATEGORY_ZONELOAD,
4697 ISC_LOG_ERROR,
4698 "zone serial (%u) unchanged. "
4699 "zone may fail to transfer "
4700 "to slaves.", serial);
4701 }
4702
4703 if (zone->type == dns_zone_master &&
4704 (zone->update_acl != NULL || zone->ssutable != NULL) &&
4705 zone->sigresigninginterval < (3 * refresh) &&
4706 dns_db_issecure(db))
4707 {
4708 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4709 ISC_LOG_WARNING,
4710 "sig-re-signing-interval less than "
4711 "3 * refresh.");
4712 }
4713
4714 zone->refresh = RANGE(refresh,
4715 zone->minrefresh, zone->maxrefresh);
4716 zone->retry = RANGE(retry,
4717 zone->minretry, zone->maxretry);
4718 zone->expire = RANGE(expire, zone->refresh + zone->retry,
4719 DNS_MAX_EXPIRE);
4720 zone->minimum = minimum;
4721 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
4722
4723 if (zone->type == dns_zone_slave ||
4724 zone->type == dns_zone_stub ||
4725 (zone->type == dns_zone_redirect &&
4726 zone->masters != NULL)) {
4727 isc_time_t t;
4728 isc_uint32_t delay;
4729
4730 result = isc_file_getmodtime(zone->journal, &t);
4731 if (result != ISC_R_SUCCESS)
4732 result = isc_file_getmodtime(zone->masterfile,
4733 &t);
4734 if (result == ISC_R_SUCCESS)
4735 DNS_ZONE_TIME_ADD(&t, zone->expire,
4736 &zone->expiretime);
4737 else
4738 DNS_ZONE_TIME_ADD(&now, zone->retry,
4739 &zone->expiretime);
4740
4741 delay = isc_random_jitter(zone->retry,
4742 (zone->retry * 3) / 4);
4743 DNS_ZONE_TIME_ADD(&now, delay, &zone->refreshtime);
4744 if (isc_time_compare(&zone->refreshtime,
4745 &zone->expiretime) >= 0)
4746 zone->refreshtime = now;
4747 }
4748
4749 break;
4750
4751 case dns_zone_key:
4752 result = sync_keyzone(zone, db);
4753 if (result != ISC_R_SUCCESS) {
4754 goto cleanup;
4755 }
4756 break;
4757
4758 default:
4759 UNEXPECTED_ERROR(__FILE__, __LINE__,
4760 "unexpected zone type %d", zone->type);
4761 result = ISC_R_UNEXPECTED;
4762 goto cleanup;
4763 }
4764
4765 /*
4766 * Check for weak DNSKEY's.
4767 */
4768 if (zone->type == dns_zone_master)
4769 zone_check_dnskeys(zone, db);
4770
4771 /*
4772 * Schedule DNSSEC key refresh.
4773 */
4774 if (zone->type == dns_zone_master &&
4775 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN))
4776 zone->refreshkeytime = now;
4777
4778 #if 0
4779 /* destroy notification example. */
4780 {
4781 isc_event_t *e = isc_event_allocate(zone->mctx, NULL,
4782 DNS_EVENT_DBDESTROYED,
4783 dns_zonemgr_dbdestroyed,
4784 zone,
4785 sizeof(isc_event_t));
4786 dns_db_ondestroy(db, zone->task, &e);
4787 }
4788 #endif
4789
4790 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
4791 if (zone->db != NULL) {
4792 result = zone_replacedb(zone, db, ISC_FALSE);
4793 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4794 if (result != ISC_R_SUCCESS)
4795 goto cleanup;
4796 } else {
4797 zone_attachdb(zone, db);
4798 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
4799 DNS_ZONE_SETFLAG(zone,
4800 DNS_ZONEFLG_LOADED|
4801 DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
4802 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SENDSECURE) &&
4803 inline_raw(zone))
4804 {
4805 if (zone->secure->db == NULL)
4806 zone_send_securedb(zone, db);
4807 else
4808 zone_send_secureserial(zone, serial);
4809 }
4810 }
4811
4812 /*
4813 * Finished loading inline-signing zone; need to get status
4814 * from the raw side now.
4815 */
4816 if (zone->type == dns_zone_master && inline_secure(zone))
4817 maybe_send_secure(zone);
4818
4819
4820 result = ISC_R_SUCCESS;
4821
4822 if (needdump) {
4823 if (zone->type == dns_zone_key)
4824 zone_needdump(zone, 30);
4825 else
4826 zone_needdump(zone, DNS_DUMP_DELAY);
4827 }
4828
4829 if (zone->task != NULL) {
4830 if (zone->type == dns_zone_master) {
4831 set_resigntime(zone);
4832 resume_signingwithkey(zone);
4833 resume_addnsec3chain(zone);
4834 }
4835
4836 if (zone->type == dns_zone_master &&
4837 !DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN) &&
4838 dns_zone_isdynamic(zone, ISC_FALSE) &&
4839 dns_db_issecure(db)) {
4840 dns_name_t *name;
4841 dns_fixedname_t fixed;
4842 dns_rdataset_t next;
4843
4844 dns_rdataset_init(&next);
4845 name = dns_fixedname_initname(&fixed);
4846
4847 result = dns_db_getsigningtime(db, &next, name);
4848 if (result == ISC_R_SUCCESS) {
4849 isc_stdtime_t timenow;
4850 char namebuf[DNS_NAME_FORMATSIZE];
4851 char typebuf[DNS_RDATATYPE_FORMATSIZE];
4852
4853 isc_stdtime_get(&timenow);
4854 dns_name_format(name, namebuf, sizeof(namebuf));
4855 dns_rdatatype_format(next.covers,
4856 typebuf, sizeof(typebuf));
4857 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4858 ISC_LOG_DEBUG(3),
4859 "next resign: %s/%s "
4860 "in %d seconds", namebuf, typebuf,
4861 next.resign - timenow -
4862 zone->sigresigninginterval);
4863 dns_rdataset_disassociate(&next);
4864 } else
4865 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4866 ISC_LOG_WARNING,
4867 "signed dynamic zone has no "
4868 "resign event scheduled");
4869 }
4870
4871 zone_settimer(zone, &now);
4872 }
4873
4874 /*
4875 * Clear old include list.
4876 */
4877 for (inc = ISC_LIST_HEAD(zone->includes);
4878 inc != NULL;
4879 inc = ISC_LIST_HEAD(zone->includes)) {
4880 ISC_LIST_UNLINK(zone->includes, inc, link);
4881 isc_mem_free(zone->mctx, inc->name);
4882 isc_mem_put(zone->mctx, inc, sizeof(*inc));
4883 }
4884 zone->nincludes = 0;
4885
4886 /*
4887 * Transfer new include list.
4888 */
4889 for (inc = ISC_LIST_HEAD(zone->newincludes);
4890 inc != NULL;
4891 inc = ISC_LIST_HEAD(zone->newincludes)) {
4892 ISC_LIST_UNLINK(zone->newincludes, inc, link);
4893 ISC_LIST_APPEND(zone->includes, inc, link);
4894 zone->nincludes++;
4895 }
4896
4897 if (! dns_db_ispersistent(db)) {
4898 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4899 ISC_LOG_INFO, "loaded serial %u%s", serial,
4900 dns_db_issecure(db) ? " (DNSSEC signed)" : "");
4901 }
4902
4903 zone->loadtime = loadtime;
4904 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
4905 return (result);
4906
4907 cleanup:
4908 if (zone->type == dns_zone_key && result != ISC_R_SUCCESS) {
4909 dns_zone_log(zone, ISC_LOG_ERROR,
4910 "failed to initialize managed-keys (%s): "
4911 "DNSSEC validation is at risk",
4912 isc_result_totext(result));
4913 }
4914
4915 for (inc = ISC_LIST_HEAD(zone->newincludes);
4916 inc != NULL;
4917 inc = ISC_LIST_HEAD(zone->newincludes))
4918 {
4919 ISC_LIST_UNLINK(zone->newincludes, inc, link);
4920 isc_mem_free(zone->mctx, inc->name);
4921 isc_mem_put(zone->mctx, inc, sizeof(*inc));
4922 }
4923 if (zone->type == dns_zone_slave ||
4924 zone->type == dns_zone_stub ||
4925 zone->type == dns_zone_key ||
4926 (zone->type == dns_zone_redirect && zone->masters != NULL)) {
4927 if (result != ISC_R_NOMEMORY) {
4928 if (zone->journal != NULL)
4929 zone_saveunique(zone, zone->journal,
4930 "jn-XXXXXXXX");
4931 if (zone->masterfile != NULL)
4932 zone_saveunique(zone, zone->masterfile,
4933 "db-XXXXXXXX");
4934 }
4935
4936 /* Mark the zone for immediate refresh. */
4937 zone->refreshtime = now;
4938 if (zone->task != NULL)
4939 zone_settimer(zone, &now);
4940 result = ISC_R_SUCCESS;
4941 } else if (zone->type == dns_zone_master ||
4942 zone->type == dns_zone_redirect) {
4943 if (!(inline_secure(zone) && result == ISC_R_FILENOTFOUND))
4944 dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
4945 ISC_LOG_ERROR,
4946 "not loaded due to errors.");
4947 else if (zone->type == dns_zone_master)
4948 result = ISC_R_SUCCESS;
4949 }
4950
4951 return (result);
4952 }
4953
4954 static isc_boolean_t
4955 exit_check(dns_zone_t *zone) {
4956 REQUIRE(LOCKED_ZONE(zone));
4957
4958 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) {
4959 /*
4960 * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0.
4961 */
4962 INSIST(isc_refcount_current(&zone->erefs) == 0);
4963 return (ISC_TRUE);
4964 }
4965 return (ISC_FALSE);
4966 }
4967
4968 static isc_boolean_t
4969 zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
4970 dns_name_t *name, isc_boolean_t logit)
4971 {
4972 isc_result_t result;
4973 char namebuf[DNS_NAME_FORMATSIZE];
4974 char altbuf[DNS_NAME_FORMATSIZE];
4975 dns_fixedname_t fixed;
4976 dns_name_t *foundname;
4977 int level;
4978
4979 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
4980 return (ISC_TRUE);
4981
4982 if (zone->type == dns_zone_master)
4983 level = ISC_LOG_ERROR;
4984 else
4985 level = ISC_LOG_WARNING;
4986
4987 foundname = dns_fixedname_initname(&fixed);
4988
4989 result = dns_db_find(db, name, version, dns_rdatatype_a,
4990 0, 0, NULL, foundname, NULL, NULL);
4991 if (result == ISC_R_SUCCESS)
4992 return (ISC_TRUE);
4993
4994 if (result == DNS_R_NXRRSET) {
4995 result = dns_db_find(db, name, version, dns_rdatatype_aaaa,
4996 0, 0, NULL, foundname, NULL, NULL);
4997 if (result == ISC_R_SUCCESS)
4998 return (ISC_TRUE);
4999 }
5000
5001 if (result == DNS_R_NXRRSET || result == DNS_R_NXDOMAIN ||
5002 result == DNS_R_EMPTYNAME) {
5003 if (logit) {
5004 dns_name_format(name, namebuf, sizeof namebuf);
5005 dns_zone_log(zone, level, "NS '%s' has no address "
5006 "records (A or AAAA)", namebuf);
5007 }
5008 return (ISC_FALSE);
5009 }
5010
5011 if (result == DNS_R_CNAME) {
5012 if (logit) {
5013 dns_name_format(name, namebuf, sizeof namebuf);
5014 dns_zone_log(zone, level, "NS '%s' is a CNAME "
5015 "(illegal)", namebuf);
5016 }
5017 return (ISC_FALSE);
5018 }
5019
5020 if (result == DNS_R_DNAME) {
5021 if (logit) {
5022 dns_name_format(name, namebuf, sizeof namebuf);
5023 dns_name_format(foundname, altbuf, sizeof altbuf);
5024 dns_zone_log(zone, level, "NS '%s' is below a DNAME "
5025 "'%s' (illegal)", namebuf, altbuf);
5026 }
5027 return (ISC_FALSE);
5028 }
5029
5030 return (ISC_TRUE);
5031 }
5032
5033 static isc_result_t
5034 zone_count_ns_rr(dns_zone_t *zone, dns_db_t *db, dns_dbnode_t *node,
5035 dns_dbversion_t *version, unsigned int *nscount,
5036 unsigned int *errors, isc_boolean_t logit)
5037 {
5038 isc_result_t result;
5039 unsigned int count = 0;
5040 unsigned int ecount = 0;
5041 dns_rdataset_t rdataset;
5042 dns_rdata_t rdata;
5043 dns_rdata_ns_t ns;
5044
5045 dns_rdataset_init(&rdataset);
5046 result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns,
5047 dns_rdatatype_none, 0, &rdataset, NULL);
5048 if (result == ISC_R_NOTFOUND) {
5049 INSIST(!dns_rdataset_isassociated(&rdataset));
5050 goto success;
5051 }
5052 if (result != ISC_R_SUCCESS) {
5053 INSIST(!dns_rdataset_isassociated(&rdataset));
5054 goto invalidate_rdataset;
5055 }
5056
5057 result = dns_rdataset_first(&rdataset);
5058 while (result == ISC_R_SUCCESS) {
5059 if (errors != NULL && zone->rdclass == dns_rdataclass_in &&
5060 (zone->type == dns_zone_master ||
5061 zone->type == dns_zone_slave)) {
5062 dns_rdata_init(&rdata);
5063 dns_rdataset_current(&rdataset, &rdata);
5064 result = dns_rdata_tostruct(&rdata, &ns, NULL);
5065 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5066 if (dns_name_issubdomain(&ns.name, &zone->origin) &&
5067 !zone_check_ns(zone, db, version, &ns.name, logit))
5068 ecount++;
5069 }
5070 count++;
5071 result = dns_rdataset_next(&rdataset);
5072 }
5073 dns_rdataset_disassociate(&rdataset);
5074
5075 success:
5076 if (nscount != NULL)
5077 *nscount = count;
5078 if (errors != NULL)
5079 *errors = ecount;
5080
5081 result = ISC_R_SUCCESS;
5082
5083 invalidate_rdataset:
5084 dns_rdataset_invalidate(&rdataset);
5085
5086 return (result);
5087 }
5088
5089 static isc_result_t
5090 zone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
5091 unsigned int *soacount,
5092 isc_uint32_t *serial, isc_uint32_t *refresh,
5093 isc_uint32_t *retry, isc_uint32_t *expire,
5094 isc_uint32_t *minimum)
5095 {
5096 isc_result_t result;
5097 unsigned int count;
5098 dns_rdataset_t rdataset;
5099 dns_rdata_t rdata = DNS_RDATA_INIT;
5100 dns_rdata_soa_t soa;
5101
5102 dns_rdataset_init(&rdataset);
5103 result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa,
5104 dns_rdatatype_none, 0, &rdataset, NULL);
5105 if (result == ISC_R_NOTFOUND) {
5106 INSIST(!dns_rdataset_isassociated(&rdataset));
5107 if (soacount != NULL)
5108 *soacount = 0;
5109 if (serial != NULL)
5110 *serial = 0;
5111 if (refresh != NULL)
5112 *refresh = 0;
5113 if (retry != NULL)
5114 *retry = 0;
5115 if (expire != NULL)
5116 *expire = 0;
5117 if (minimum != NULL)
5118 *minimum = 0;
5119 result = ISC_R_SUCCESS;
5120 goto invalidate_rdataset;
5121 }
5122 if (result != ISC_R_SUCCESS) {
5123 INSIST(!dns_rdataset_isassociated(&rdataset));
5124 goto invalidate_rdataset;
5125 }
5126
5127 count = 0;
5128 result = dns_rdataset_first(&rdataset);
5129 while (result == ISC_R_SUCCESS) {
5130 dns_rdata_init(&rdata);
5131 dns_rdataset_current(&rdataset, &rdata);
5132 count++;
5133 if (count == 1) {
5134 result = dns_rdata_tostruct(&rdata, &soa, NULL);
5135 RUNTIME_CHECK(result == ISC_R_SUCCESS);
5136 }
5137
5138 result = dns_rdataset_next(&rdataset);
5139 dns_rdata_reset(&rdata);
5140 }
5141 dns_rdataset_disassociate(&rdataset);
5142
5143 if (soacount != NULL)
5144 *soacount = count;
5145
5146 if (count > 0) {
5147 if (serial != NULL)
5148 *serial = soa.serial;
5149 if (refresh != NULL)
5150 *refresh = soa.refresh;
5151 if (retry != NULL)
5152 *retry = soa.retry;
5153 if (expire != NULL)
5154 *expire = soa.expire;
5155 if (minimum != NULL)
5156 *minimum = soa.minimum;
5157 } else {
5158 if (soacount != NULL)
5159 *soacount = 0;
5160 if (serial != NULL)
5161 *serial = 0;
5162 if (refresh != NULL)
5163 *refresh = 0;
5164 if (retry != NULL)
5165 *retry = 0;
5166 if (expire != NULL)
5167 *expire = 0;
5168 if (minimum != NULL)
5169 *minimum = 0;
5170 }
5171
5172 result = ISC_R_SUCCESS;
5173
5174 invalidate_rdataset:
5175 dns_rdataset_invalidate(&rdataset);
5176
5177 return (result);
5178 }
5179
5180 /*
5181 * zone must be locked.
5182 */
5183 static isc_result_t
5184 zone_get_from_db(dns_zone_t *zone, dns_db_t *db, unsigned int *nscount,
5185 unsigned int *soacount, isc_uint32_t *serial,
5186 isc_uint32_t *refresh, isc_uint32_t *retry,
5187 isc_uint32_t *expire, isc_uint32_t *minimum,
5188 unsigned int *errors)
5189 {
5190 isc_result_t result;
5191 isc_result_t answer = ISC_R_SUCCESS;
5192 dns_dbversion_t *version = NULL;
5193 dns_dbnode_t *node;
5194
5195 REQUIRE(db != NULL);
5196 REQUIRE(zone != NULL);
5197
5198 dns_db_currentversion(db, &version);
5199
5200 if (nscount != NULL)
5201 *nscount = 0;
5202 if (soacount != NULL)
5203 *soacount = 0;
5204 if (serial != NULL)
5205 *serial = 0;
5206 if (refresh != NULL)
5207 *refresh = 0;
5208 if (retry != NULL)
5209 *retry = 0;
5210 if (expire != NULL)
5211 *expire = 0;
5212 if (errors != NULL)
5213 *errors = 0;
5214
5215 node = NULL;
5216 result = dns_db_findnode(db, &zone->origin, ISC_FALSE, &node);
5217 if (result != ISC_R_SUCCESS) {
5218 answer = result;
5219 goto closeversion;
5220 }
5221
5222 if (nscount != NULL || errors != NULL) {
5223 result = zone_count_ns_rr(zone, db, node, version,
5224 nscount, errors, ISC_TRUE);
5225 if (result != ISC_R_SUCCESS)
5226 answer = result;
5227 }
5228
5229 if (soacount != NULL || serial != NULL || refresh != NULL
5230 || retry != NULL || expire != NULL || minimum != NULL) {
5231 result = zone_load_soa_rr(db, node, version, soacount,
5232 serial, refresh, retry, expire,
5233 minimum);
5234 if (result != ISC_R_SUCCESS)
5235 answer = result;
5236 }
5237
5238 dns_db_detachnode(db, &node);
5239 closeversion:
5240 dns_db_closeversion(db, &version, ISC_FALSE);
5241
5242 return (answer);
5243 }
5244
5245 void
5246 dns_zone_attach(dns_zone_t *source, dns_zone_t **target) {
5247 REQUIRE(DNS_ZONE_VALID(source));
5248 REQUIRE(target != NULL && *target == NULL);
5249 isc_refcount_increment(&source->erefs, NULL);
5250 *target = source;
5251 }
5252
5253 void
5254 dns_zone_detach(dns_zone_t **zonep) {
5255 dns_zone_t *zone;
5256 dns_zone_t *raw = NULL;
5257 dns_zone_t *secure = NULL;
5258 unsigned int refs;
5259 isc_boolean_t free_now = ISC_FALSE;
5260
5261 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5262
5263 zone = *zonep;
5264
5265 isc_refcount_decrement(&zone->erefs, &refs);
5266
5267 if (refs == 0) {
5268 LOCK_ZONE(zone);
5269 INSIST(zone != zone->raw);
5270 /*
5271 * We just detached the last external reference.
5272 */
5273 if (zone->task != NULL) {
5274 /*
5275 * This zone is being managed. Post
5276 * its control event and let it clean
5277 * up synchronously in the context of
5278 * its task.
5279 */
5280 isc_event_t *ev = &zone->ctlevent;
5281 isc_task_send(zone->task, &ev);
5282 } else {
5283 /*
5284 * This zone is not being managed; it has
5285 * no task and can have no outstanding
5286 * events. Free it immediately.
5287 */
5288 /*
5289 * Unmanaged zones should not have non-null views;
5290 * we have no way of detaching from the view here
5291 * without causing deadlock because this code is called
5292 * with the view already locked.
5293 */
5294 INSIST(zone->view == NULL);
5295 free_now = ISC_TRUE;
5296 raw = zone->raw;
5297 zone->raw = NULL;
5298 secure = zone->secure;
5299 zone->secure = NULL;
5300 }
5301 UNLOCK_ZONE(zone);
5302 }
5303 *zonep = NULL;
5304 if (free_now) {
5305 if (raw != NULL)
5306 dns_zone_detach(&raw);
5307 if (secure != NULL)
5308 dns_zone_idetach(&secure);
5309 zone_free(zone);
5310 }
5311 }
5312
5313 void
5314 dns_zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5315 REQUIRE(DNS_ZONE_VALID(source));
5316 REQUIRE(target != NULL && *target == NULL);
5317 LOCK_ZONE(source);
5318 zone_iattach(source, target);
5319 UNLOCK_ZONE(source);
5320 }
5321
5322 static void
5323 zone_iattach(dns_zone_t *source, dns_zone_t **target) {
5324
5325 /*
5326 * 'source' locked by caller.
5327 */
5328 REQUIRE(LOCKED_ZONE(source));
5329 REQUIRE(DNS_ZONE_VALID(source));
5330 REQUIRE(target != NULL && *target == NULL);
5331 INSIST(source->irefs + isc_refcount_current(&source->erefs) > 0);
5332 source->irefs++;
5333 INSIST(source->irefs != 0);
5334 *target = source;
5335 }
5336
5337 static void
5338 zone_idetach(dns_zone_t **zonep) {
5339 dns_zone_t *zone;
5340
5341 /*
5342 * 'zone' locked by caller.
5343 */
5344 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5345 zone = *zonep;
5346 REQUIRE(LOCKED_ZONE(*zonep));
5347 *zonep = NULL;
5348
5349 INSIST(zone->irefs > 0);
5350 zone->irefs--;
5351 INSIST(zone->irefs + isc_refcount_current(&zone->erefs) > 0);
5352 }
5353
5354 void
5355 dns_zone_idetach(dns_zone_t **zonep) {
5356 dns_zone_t *zone;
5357 isc_boolean_t free_needed;
5358
5359 REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep));
5360 zone = *zonep;
5361 *zonep = NULL;
5362
5363 LOCK_ZONE(zone);
5364 INSIST(zone->irefs > 0);
5365 zone->irefs--;
5366 free_needed = exit_check(zone);
5367 UNLOCK_ZONE(zone);
5368 if (free_needed)
5369 zone_free(zone);
5370 }
5371
5372 isc_mem_t *
5373 dns_zone_getmctx(dns_zone_t *zone) {
5374 REQUIRE(DNS_ZONE_VALID(zone));
5375
5376 return (zone->mctx);
5377 }
5378
5379 dns_zonemgr_t *
5380 dns_zone_getmgr(dns_zone_t *zone) {
5381 REQUIRE(DNS_ZONE_VALID(zone));
5382
5383 return (zone->zmgr);
5384 }
5385
5386 void
5387 dns_zone_setflag(dns_zone_t *zone, unsigned int flags, isc_boolean_t value) {
5388 REQUIRE(DNS_ZONE_VALID(zone));
5389
5390 LOCK_ZONE(zone);
5391 if (value)
5392 DNS_ZONE_SETFLAG(zone, flags);
5393 else
5394 DNS_ZONE_CLRFLAG(zone, flags);
5395 UNLOCK_ZONE(zone);
5396 }
5397
5398 void
5399 dns_zone_setoption(dns_zone_t *zone, unsigned int option,
5400 isc_boolean_t value)
5401 {
5402 REQUIRE(DNS_ZONE_VALID(zone));
5403
5404 LOCK_ZONE(zone);
5405 if (value)
5406 zone->options |= option;
5407 else
5408 zone->options &= ~option;
5409 UNLOCK_ZONE(zone);
5410 }
5411
5412 void
5413 dns_zone_setoption2(dns_zone_t *zone, unsigned int option,
5414 isc_boolean_t value)
5415 {
5416 REQUIRE(DNS_ZONE_VALID(zone));
5417
5418 LOCK_ZONE(zone);
5419 if (value)
5420 zone->options2 |= option;
5421 else
5422 zone->options2 &= ~option;
5423 UNLOCK_ZONE(zone);
5424 }
5425
5426 unsigned int
5427 dns_zone_getoptions(dns_zone_t *zone) {
5428 REQUIRE(DNS_ZONE_VALID(zone));
5429
5430 return (zone->options);
5431 }
5432
5433 unsigned int
5434 dns_zone_getoptions2(dns_zone_t *zone) {
5435 REQUIRE(DNS_ZONE_VALID(zone));
5436
5437 return (zone->options2);
5438 }
5439
5440 void
5441 dns_zone_setkeyopt(dns_zone_t *zone, unsigned int keyopt, isc_boolean_t value)
5442 {
5443 REQUIRE(DNS_ZONE_VALID(zone));
5444
5445 LOCK_ZONE(zone);
5446 if (value)
5447 zone->keyopts |= keyopt;
5448 else
5449 zone->keyopts &= ~keyopt;
5450 UNLOCK_ZONE(zone);
5451 }
5452
5453 unsigned int
5454 dns_zone_getkeyopts(dns_zone_t *zone) {
5455
5456 REQUIRE(DNS_ZONE_VALID(zone));
5457
5458 return (zone->keyopts);
5459 }
5460
5461 isc_result_t
5462 dns_zone_setxfrsource4(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5463 REQUIRE(DNS_ZONE_VALID(zone));
5464
5465 LOCK_ZONE(zone);
5466 zone->xfrsource4 = *xfrsource;
5467 UNLOCK_ZONE(zone);
5468
5469 return (ISC_R_SUCCESS);
5470 }
5471
5472 isc_sockaddr_t *
5473 dns_zone_getxfrsource4(dns_zone_t *zone) {
5474 REQUIRE(DNS_ZONE_VALID(zone));
5475 return (&zone->xfrsource4);
5476 }
5477
5478 isc_result_t
5479 dns_zone_setxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5480 REQUIRE(DNS_ZONE_VALID(zone));
5481
5482 LOCK_ZONE(zone);
5483 zone->xfrsource4dscp = dscp;
5484 UNLOCK_ZONE(zone);
5485
5486 return (ISC_R_SUCCESS);
5487 }
5488
5489 isc_dscp_t
5490 dns_zone_getxfrsource4dscp(dns_zone_t *zone) {
5491 REQUIRE(DNS_ZONE_VALID(zone));
5492 return (zone->xfrsource4dscp);
5493 }
5494
5495 isc_result_t
5496 dns_zone_setxfrsource6(dns_zone_t *zone, const isc_sockaddr_t *xfrsource) {
5497 REQUIRE(DNS_ZONE_VALID(zone));
5498
5499 LOCK_ZONE(zone);
5500 zone->xfrsource6 = *xfrsource;
5501 UNLOCK_ZONE(zone);
5502
5503 return (ISC_R_SUCCESS);
5504 }
5505
5506 isc_sockaddr_t *
5507 dns_zone_getxfrsource6(dns_zone_t *zone) {
5508 REQUIRE(DNS_ZONE_VALID(zone));
5509 return (&zone->xfrsource6);
5510 }
5511
5512 isc_dscp_t
5513 dns_zone_getxfrsource6dscp(dns_zone_t *zone) {
5514 REQUIRE(DNS_ZONE_VALID(zone));
5515 return (zone->xfrsource6dscp);
5516 }
5517
5518 isc_result_t
5519 dns_zone_setxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5520 REQUIRE(DNS_ZONE_VALID(zone));
5521
5522 LOCK_ZONE(zone);
5523 zone->xfrsource6dscp = dscp;
5524 UNLOCK_ZONE(zone);
5525
5526 return (ISC_R_SUCCESS);
5527 }
5528
5529 isc_result_t
5530 dns_zone_setaltxfrsource4(dns_zone_t *zone,
5531 const isc_sockaddr_t *altxfrsource)
5532 {
5533 REQUIRE(DNS_ZONE_VALID(zone));
5534
5535 LOCK_ZONE(zone);
5536 zone->altxfrsource4 = *altxfrsource;
5537 UNLOCK_ZONE(zone);
5538
5539 return (ISC_R_SUCCESS);
5540 }
5541
5542 isc_sockaddr_t *
5543 dns_zone_getaltxfrsource4(dns_zone_t *zone) {
5544 REQUIRE(DNS_ZONE_VALID(zone));
5545 return (&zone->altxfrsource4);
5546 }
5547
5548 isc_result_t
5549 dns_zone_setaltxfrsource4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5550 REQUIRE(DNS_ZONE_VALID(zone));
5551
5552 LOCK_ZONE(zone);
5553 zone->altxfrsource4dscp = dscp;
5554 UNLOCK_ZONE(zone);
5555
5556 return (ISC_R_SUCCESS);
5557 }
5558
5559 isc_dscp_t
5560 dns_zone_getaltxfrsource4dscp(dns_zone_t *zone) {
5561 REQUIRE(DNS_ZONE_VALID(zone));
5562 return (zone->altxfrsource4dscp);
5563 }
5564
5565 isc_result_t
5566 dns_zone_setaltxfrsource6(dns_zone_t *zone,
5567 const isc_sockaddr_t *altxfrsource)
5568 {
5569 REQUIRE(DNS_ZONE_VALID(zone));
5570
5571 LOCK_ZONE(zone);
5572 zone->altxfrsource6 = *altxfrsource;
5573 UNLOCK_ZONE(zone);
5574
5575 return (ISC_R_SUCCESS);
5576 }
5577
5578 isc_sockaddr_t *
5579 dns_zone_getaltxfrsource6(dns_zone_t *zone) {
5580 REQUIRE(DNS_ZONE_VALID(zone));
5581 return (&zone->altxfrsource6);
5582 }
5583
5584 isc_result_t
5585 dns_zone_setaltxfrsource6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5586 REQUIRE(DNS_ZONE_VALID(zone));
5587
5588 LOCK_ZONE(zone);
5589 zone->altxfrsource6dscp = dscp;
5590 UNLOCK_ZONE(zone);
5591
5592 return (ISC_R_SUCCESS);
5593 }
5594
5595 isc_dscp_t
5596 dns_zone_getaltxfrsource6dscp(dns_zone_t *zone) {
5597 REQUIRE(DNS_ZONE_VALID(zone));
5598 return (zone->altxfrsource6dscp);
5599 }
5600
5601 isc_result_t
5602 dns_zone_setnotifysrc4(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5603 REQUIRE(DNS_ZONE_VALID(zone));
5604
5605 LOCK_ZONE(zone);
5606 zone->notifysrc4 = *notifysrc;
5607 UNLOCK_ZONE(zone);
5608
5609 return (ISC_R_SUCCESS);
5610 }
5611
5612 isc_sockaddr_t *
5613 dns_zone_getnotifysrc4(dns_zone_t *zone) {
5614 REQUIRE(DNS_ZONE_VALID(zone));
5615 return (&zone->notifysrc4);
5616 }
5617
5618 isc_result_t
5619 dns_zone_setnotifysrc4dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5620 REQUIRE(DNS_ZONE_VALID(zone));
5621
5622 LOCK_ZONE(zone);
5623 zone->notifysrc4dscp = dscp;
5624 UNLOCK_ZONE(zone);
5625
5626 return (ISC_R_SUCCESS);
5627 }
5628
5629 isc_dscp_t
5630 dns_zone_getnotifysrc4dscp(dns_zone_t *zone) {
5631 REQUIRE(DNS_ZONE_VALID(zone));
5632 return (zone->notifysrc4dscp);
5633 }
5634
5635 isc_result_t
5636 dns_zone_setnotifysrc6(dns_zone_t *zone, const isc_sockaddr_t *notifysrc) {
5637 REQUIRE(DNS_ZONE_VALID(zone));
5638
5639 LOCK_ZONE(zone);
5640 zone->notifysrc6 = *notifysrc;
5641 UNLOCK_ZONE(zone);
5642
5643 return (ISC_R_SUCCESS);
5644 }
5645
5646 isc_sockaddr_t *
5647 dns_zone_getnotifysrc6(dns_zone_t *zone) {
5648 REQUIRE(DNS_ZONE_VALID(zone));
5649 return (&zone->notifysrc6);
5650 }
5651
5652 static isc_boolean_t
5653 same_addrs(isc_sockaddr_t const *oldlist, isc_sockaddr_t const *newlist,
5654 isc_uint32_t count)
5655 {
5656 unsigned int i;
5657
5658 for (i = 0; i < count; i++)
5659 if (!isc_sockaddr_equal(&oldlist[i], &newlist[i]))
5660 return (ISC_FALSE);
5661 return (ISC_TRUE);
5662 }
5663
5664 static isc_boolean_t
5665 same_keynames(dns_name_t * const *oldlist, dns_name_t * const *newlist,
5666 isc_uint32_t count)
5667 {
5668 unsigned int i;
5669
5670 if (oldlist == NULL && newlist == NULL)
5671 return (ISC_TRUE);
5672 if (oldlist == NULL || newlist == NULL)
5673 return (ISC_FALSE);
5674
5675 for (i = 0; i < count; i++) {
5676 if (oldlist[i] == NULL && newlist[i] == NULL)
5677 continue;
5678 if (oldlist[i] == NULL || newlist[i] == NULL ||
5679 !dns_name_equal(oldlist[i], newlist[i]))
5680 return (ISC_FALSE);
5681 }
5682 return (ISC_TRUE);
5683 }
5684
5685 static void
5686 clear_addresskeylist(isc_sockaddr_t **addrsp, isc_dscp_t **dscpsp,
5687 dns_name_t ***keynamesp, unsigned int *countp,
5688 isc_mem_t *mctx)
5689 {
5690 unsigned int count;
5691 isc_sockaddr_t *addrs;
5692 isc_dscp_t *dscps;
5693 dns_name_t **keynames;
5694
5695 REQUIRE(countp != NULL && addrsp != NULL && dscpsp != NULL &&
5696 keynamesp != NULL);
5697
5698 count = *countp;
5699 *countp = 0;
5700 addrs = *addrsp;
5701 *addrsp = NULL;
5702 dscps = *dscpsp;
5703 *dscpsp = NULL;
5704 keynames = *keynamesp;
5705 *keynamesp = NULL;
5706
5707 if (addrs != NULL)
5708 isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
5709
5710 if (dscps != NULL)
5711 isc_mem_put(mctx, dscps, count * sizeof(isc_dscp_t));
5712
5713 if (keynames != NULL) {
5714 unsigned int i;
5715 for (i = 0; i < count; i++) {
5716 if (keynames[i] != NULL) {
5717 dns_name_free(keynames[i], mctx);
5718 isc_mem_put(mctx, keynames[i],
5719 sizeof(dns_name_t));
5720 keynames[i] = NULL;
5721 }
5722 }
5723 isc_mem_put(mctx, keynames, count * sizeof(dns_name_t *));
5724 }
5725 }
5726
5727 static isc_result_t
5728 set_addrkeylist(unsigned int count,
5729 const isc_sockaddr_t *addrs, isc_sockaddr_t **newaddrsp,
5730 const isc_dscp_t *dscp, isc_dscp_t **newdscpp,
5731 dns_name_t **names, dns_name_t ***newnamesp,
5732 isc_mem_t *mctx)
5733 {
5734 isc_result_t result;
5735 isc_sockaddr_t *newaddrs = NULL;
5736 isc_dscp_t *newdscp = NULL;
5737 dns_name_t **newnames = NULL;
5738 unsigned int i;
5739
5740 REQUIRE(newaddrsp != NULL && *newaddrsp == NULL);
5741 REQUIRE(newdscpp != NULL && *newdscpp == NULL);
5742 REQUIRE(newnamesp != NULL && *newnamesp == NULL);
5743
5744 newaddrs = isc_mem_get(mctx, count * sizeof(*newaddrs));
5745 if (newaddrs == NULL)
5746 return (ISC_R_NOMEMORY);
5747 memmove(newaddrs, addrs, count * sizeof(*newaddrs));
5748
5749 if (dscp != NULL) {
5750 newdscp = isc_mem_get(mctx, count * sizeof(*newdscp));
5751 if (newdscp == NULL) {
5752 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5753 return (ISC_R_NOMEMORY);
5754 }
5755 memmove(newdscp, dscp, count * sizeof(*newdscp));
5756 } else
5757 newdscp = NULL;
5758
5759 if (names != NULL) {
5760 newnames = isc_mem_get(mctx, count * sizeof(*newnames));
5761 if (newnames == NULL) {
5762 if (newdscp != NULL)
5763 isc_mem_put(mctx, newdscp,
5764 count * sizeof(*newdscp));
5765 isc_mem_put(mctx, newaddrs, count * sizeof(*newaddrs));
5766 return (ISC_R_NOMEMORY);
5767 }
5768 for (i = 0; i < count; i++)
5769 newnames[i] = NULL;
5770 for (i = 0; i < count; i++) {
5771 if (names[i] != NULL) {
5772 newnames[i] = isc_mem_get(mctx,
5773 sizeof(dns_name_t));
5774 if (newnames[i] == NULL)
5775 goto allocfail;
5776 dns_name_init(newnames[i], NULL);
5777 result = dns_name_dup(names[i], mctx,
5778 newnames[i]);
5779 if (result != ISC_R_SUCCESS) {
5780 allocfail:
5781 for (i = 0; i < count; i++)
5782 if (newnames[i] != NULL)
5783 dns_name_free(
5784 newnames[i],
5785 mctx);
5786 isc_mem_put(mctx, newaddrs,
5787 count * sizeof(*newaddrs));
5788 isc_mem_put(mctx, newdscp,
5789 count * sizeof(*newdscp));
5790 isc_mem_put(mctx, newnames,
5791 count * sizeof(*newnames));
5792 return (ISC_R_NOMEMORY);
5793 }
5794 }
5795 }
5796 } else
5797 newnames = NULL;
5798
5799 *newdscpp = newdscp;
5800 *newaddrsp = newaddrs;
5801 *newnamesp = newnames;
5802 return (ISC_R_SUCCESS);
5803 }
5804
5805 isc_result_t
5806 dns_zone_setnotifysrc6dscp(dns_zone_t *zone, isc_dscp_t dscp) {
5807 REQUIRE(DNS_ZONE_VALID(zone));
5808
5809 LOCK_ZONE(zone);
5810 zone->notifysrc6dscp = dscp;
5811 UNLOCK_ZONE(zone);
5812
5813 return (ISC_R_SUCCESS);
5814 }
5815
5816 isc_dscp_t
5817 dns_zone_getnotifysrc6dscp(dns_zone_t *zone) {
5818 REQUIRE(DNS_ZONE_VALID(zone));
5819 return (zone->notifysrc6dscp);
5820 }
5821
5822 isc_result_t
5823 dns_zone_setalsonotify(dns_zone_t *zone, const isc_sockaddr_t *notify,
5824 isc_uint32_t count)
5825 {
5826 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, NULL,
5827 count));
5828 }
5829
5830 isc_result_t
5831 dns_zone_setalsonotifywithkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5832 dns_name_t **keynames, isc_uint32_t count)
5833 {
5834 return (dns_zone_setalsonotifydscpkeys(zone, notify, NULL, keynames,
5835 count));
5836 }
5837
5838 isc_result_t
5839 dns_zone_setalsonotifydscpkeys(dns_zone_t *zone, const isc_sockaddr_t *notify,
5840 const isc_dscp_t *dscps, dns_name_t **keynames,
5841 isc_uint32_t count)
5842 {
5843 isc_result_t result;
5844 isc_sockaddr_t *newaddrs = NULL;
5845 isc_dscp_t *newdscps = NULL;
5846 dns_name_t **newnames = NULL;
5847
5848 REQUIRE(DNS_ZONE_VALID(zone));
5849 REQUIRE(count == 0 || notify != NULL);
5850 if (keynames != NULL)
5851 REQUIRE(count != 0);
5852
5853 LOCK_ZONE(zone);
5854
5855 if (count == zone->notifycnt &&
5856 same_addrs(zone->notify, notify, count) &&
5857 same_keynames(zone->notifykeynames, keynames, count))
5858 goto unlock;
5859
5860 clear_addresskeylist(&zone->notify, &zone->notifydscp,
5861 &zone->notifykeynames, &zone->notifycnt,
5862 zone->mctx);
5863
5864 if (count == 0)
5865 goto unlock;
5866
5867 /*
5868 * Set up the notify and notifykey lists
5869 */
5870 result = set_addrkeylist(count, notify, &newaddrs, dscps, &newdscps,
5871 keynames, &newnames, zone->mctx);
5872 if (result != ISC_R_SUCCESS)
5873 goto unlock;
5874
5875 /*
5876 * Everything is ok so attach to the zone.
5877 */
5878 zone->notify = newaddrs;
5879 zone->notifydscp = newdscps;
5880 zone->notifykeynames = newnames;
5881 zone->notifycnt = count;
5882 unlock:
5883 UNLOCK_ZONE(zone);
5884 return (ISC_R_SUCCESS);
5885 }
5886
5887 isc_result_t
5888 dns_zone_setmasters(dns_zone_t *zone, const isc_sockaddr_t *masters,
5889 isc_uint32_t count)
5890 {
5891 isc_result_t result;
5892
5893 result = dns_zone_setmasterswithkeys(zone, masters, NULL, count);
5894 return (result);
5895 }
5896
5897 isc_result_t
5898 dns_zone_setmasterswithkeys(dns_zone_t *zone,
5899 const isc_sockaddr_t *masters,
5900 dns_name_t **keynames,
5901 isc_uint32_t count)
5902 {
5903 isc_result_t result = ISC_R_SUCCESS;
5904 isc_sockaddr_t *newaddrs = NULL;
5905 isc_dscp_t *newdscps = NULL;
5906 dns_name_t **newnames = NULL;
5907 isc_boolean_t *newok;
5908 unsigned int i;
5909
5910 REQUIRE(DNS_ZONE_VALID(zone));
5911 REQUIRE(count == 0 || masters != NULL);
5912 if (keynames != NULL) {
5913 REQUIRE(count != 0);
5914 }
5915
5916 LOCK_ZONE(zone);
5917 /*
5918 * The refresh code assumes that 'masters' wouldn't change under it.
5919 * If it will change then kill off any current refresh in progress
5920 * and update the masters info. If it won't change then we can just
5921 * unlock and exit.
5922 */
5923 if (count != zone->masterscnt ||
5924 !same_addrs(zone->masters, masters, count) ||
5925 !same_keynames(zone->masterkeynames, keynames, count)) {
5926 if (zone->request != NULL)
5927 dns_request_cancel(zone->request);
5928 } else
5929 goto unlock;
5930
5931 /*
5932 * This needs to happen before clear_addresskeylist() sets
5933 * zone->masterscnt to 0:
5934 */
5935 if (zone->mastersok != NULL) {
5936 isc_mem_put(zone->mctx, zone->mastersok,
5937 zone->masterscnt * sizeof(isc_boolean_t));
5938 zone->mastersok = NULL;
5939 }
5940 clear_addresskeylist(&zone->masters, &zone->masterdscps,
5941 &zone->masterkeynames, &zone->masterscnt,
5942 zone->mctx);
5943 /*
5944 * If count == 0, don't allocate any space for masters, mastersok or
5945 * keynames so internally, those pointers are NULL if count == 0
5946 */
5947 if (count == 0)
5948 goto unlock;
5949
5950 /*
5951 * mastersok must contain count elements
5952 */
5953 newok = isc_mem_get(zone->mctx, count * sizeof(*newok));
5954 if (newok == NULL) {
5955 result = ISC_R_NOMEMORY;
5956 isc_mem_put(zone->mctx, newaddrs, count * sizeof(*newaddrs));
5957 goto unlock;
5958 };
5959 for (i = 0; i < count; i++)
5960 newok[i] = ISC_FALSE;
5961
5962 /*
5963 * Now set up the masters and masterkey lists
5964 */
5965 result = set_addrkeylist(count, masters, &newaddrs, NULL, &newdscps,
5966 keynames, &newnames, zone->mctx);
5967 INSIST(newdscps == NULL);
5968 if (result != ISC_R_SUCCESS) {
5969 isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
5970 goto unlock;
5971 }
5972
5973 /*
5974 * Everything is ok so attach to the zone.
5975 */
5976 zone->curmaster = 0;
5977 zone->mastersok = newok;
5978 zone->masters = newaddrs;
5979 zone->masterdscps = newdscps;
5980 zone->masterkeynames = newnames;
5981 zone->masterscnt = count;
5982 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
5983
5984 unlock:
5985 UNLOCK_ZONE(zone);
5986 return (result);
5987 }
5988
5989 isc_result_t
5990 dns_zone_getdb(dns_zone_t *zone, dns_db_t **dpb) {
5991 isc_result_t result = ISC_R_SUCCESS;
5992
5993 REQUIRE(DNS_ZONE_VALID(zone));
5994
5995 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
5996 if (zone->db == NULL)
5997 result = DNS_R_NOTLOADED;
5998 else
5999 dns_db_attach(zone->db, dpb);
6000 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6001
6002 return (result);
6003 }
6004
6005 void
6006 dns_zone_setdb(dns_zone_t *zone, dns_db_t *db) {
6007 REQUIRE(DNS_ZONE_VALID(zone));
6008 REQUIRE(zone->type == dns_zone_staticstub);
6009
6010 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
6011 REQUIRE(zone->db == NULL);
6012 dns_db_attach(db, &zone->db);
6013 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
6014 }
6015
6016 /*
6017 * Co-ordinates the starting of routine jobs.
6018 */
6019 void
6020 dns_zone_maintenance(dns_zone_t *zone) {
6021 const char me[] = "dns_zone_maintenance";
6022 isc_time_t now;
6023
6024 REQUIRE(DNS_ZONE_VALID(zone));
6025 ENTER;
6026
6027 LOCK_ZONE(zone);
6028 TIME_NOW(&now);
6029 zone_settimer(zone, &now);
6030 UNLOCK_ZONE(zone);
6031 }
6032
6033 static inline isc_boolean_t
6034 was_dumping(dns_zone_t *zone) {
6035 isc_boolean_t dumping;
6036
6037 REQUIRE(LOCKED_ZONE(zone));
6038
6039 dumping = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING);
6040 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
6041 if (!dumping) {
6042 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
6043 isc_time_settoepoch(&zone->dumptime);
6044 }
6045 return (dumping);
6046 }
6047
6048 /*%
6049 * Find up to 'maxkeys' DNSSEC keys used for signing version 'ver' of database
6050 * 'db' for zone 'zone' in its key directory, then load these keys into 'keys'.
6051 * Only load the public part of a given key if it is not active at timestamp
6052 * 'now'. Store the number of keys found in 'nkeys'.
6053 */
6054 isc_result_t
6055 dns__zone_findkeys(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
6056 isc_stdtime_t now, isc_mem_t *mctx, unsigned int maxkeys,
6057 dst_key_t **keys, unsigned int *nkeys)
6058 {
6059 isc_result_t result;
6060 dns_dbnode_t *node = NULL;
6061 const char *directory = dns_zone_getkeydirectory(zone);
6062
6063 CHECK(dns_db_findnode(db, dns_db_origin(db), ISC_FALSE, &node));
6064 memset(keys, 0, sizeof(*keys) * maxkeys);
6065 result = dns_dnssec_findzonekeys3(db, ver, node, dns_db_origin(db),
6066 directory, now, mctx, maxkeys, keys,
6067 nkeys);
6068 if (result == ISC_R_NOTFOUND)
6069 result = ISC_R_SUCCESS;
6070 failure:
6071 if (node != NULL)
6072 dns_db_detachnode(db, &node);
6073 return (result);
6074 }
6075
6076 static isc_result_t
6077 offline(dns_db_t *db, dns_dbversion_t *ver, dns__zonediff_t *zonediff,
6078 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
6079 {
6080 isc_result_t result;
6081
6082 if ((rdata->flags & DNS_RDATA_OFFLINE) != 0)
6083 return (ISC_R_SUCCESS);
6084 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_DELRESIGN,
6085 name, ttl, rdata);
6086 if (result != ISC_R_SUCCESS)
6087 return (result);
6088 rdata->flags |= DNS_RDATA_OFFLINE;
6089 result = update_one_rr(db, ver, zonediff->diff, DNS_DIFFOP_ADDRESIGN,
6090 name, ttl, rdata);
6091 zonediff->offline = ISC_TRUE;
6092 return (result);
6093 }
6094
6095 static void
6096 set_key_expiry_warning(dns_zone_t *zone, isc_stdtime_t when, isc_stdtime_t now)
6097 {
6098 unsigned int delta;
6099 char timebuf[80];
6100
6101 zone->key_expiry = when;
6102 if (when <= now) {
6103 dns_zone_log(zone, ISC_LOG_ERROR,
6104 "DNSKEY RRSIG(s) have expired");
6105 isc_time_settoepoch(&zone->keywarntime);
6106 } else if (when < now + 7 * 24 * 3600) {
6107 isc_time_t t;
6108 isc_time_set(&t, when, 0);
6109 isc_time_formattimestamp(&t, timebuf, 80);
6110 dns_zone_log(zone, ISC_LOG_WARNING,
6111 "DNSKEY RRSIG(s) will expire within 7 days: %s",
6112 timebuf);
6113 delta = when - now;
6114 delta--; /* loop prevention */
6115 delta /= 24 * 3600; /* to whole days */
6116 delta *= 24 * 3600; /* to seconds */
6117 isc_time_set(&zone->keywarntime, when - delta, 0);
6118 } else {
6119 isc_time_set(&zone->keywarntime, when - 7 * 24 * 3600, 0);
6120 isc_time_formattimestamp(&zone->keywarntime, timebuf, 80);
6121 dns_zone_log(zone, ISC_LOG_NOTICE,
6122 "setting keywarntime to %s", timebuf);
6123 }
6124 }
6125
6126 /*
6127 * Helper function to del_sigs(). We don't want to delete RRSIGs that
6128 * have no new key.
6129 */
6130 static isc_boolean_t
6131 delsig_ok(dns_rdata_rrsig_t *rrsig_ptr, dst_key_t **keys, unsigned int nkeys,
6132 isc_boolean_t *warn)
6133 {
6134 unsigned int i = 0;
6135 isc_boolean_t have_ksk = ISC_FALSE, have_zsk = ISC_FALSE;
6136 isc_boolean_t have_pksk = ISC_FALSE, have_pzsk = ISC_FALSE;
6137
6138 for (i = 0; i < nkeys; i++) {
6139 if (rrsig_ptr->algorithm != dst_key_alg(keys[i]))
6140 continue;
6141 if (dst_key_isprivate(keys[i])) {
6142 if (KSK(keys[i]))
6143 have_ksk = have_pksk = ISC_TRUE;
6144 else
6145 have_zsk = have_pzsk = ISC_TRUE;
6146 } else {
6147 if (KSK(keys[i]))
6148 have_ksk = ISC_TRUE;
6149 else
6150 have_zsk = ISC_TRUE;
6151 }
6152 }
6153
6154 if (have_zsk && have_ksk && !have_pzsk)
6155 *warn = ISC_TRUE;
6156
6157 /*
6158 * It's okay to delete a signature if there is an active key
6159 * with the same algorithm to replace it.
6160 */
6161 if (have_pksk || have_pzsk)
6162 return (ISC_TRUE);
6163
6164 /*
6165 * Failing that, it is *not* okay to delete a signature
6166 * if the associated public key is still in the DNSKEY RRset
6167 */
6168 for (i = 0; i < nkeys; i++) {
6169 if ((rrsig_ptr->algorithm == dst_key_alg(keys[i])) &&
6170 (rrsig_ptr->keyid == dst_key_id(keys[i])))
6171 return (ISC_FALSE);
6172 }
6173
6174 /*
6175 * But if the key is gone, then go ahead.
6176 */
6177 return (ISC_TRUE);
6178 }
6179
6180 /*
6181 * Delete expired RRsigs and any RRsigs we are about to re-sign.
6182 * See also update.c:del_keysigs().
6183 */
6184 static isc_result_t
6185 del_sigs(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6186 dns_rdatatype_t type, dns__zonediff_t *zonediff, dst_key_t **keys,
6187 unsigned int nkeys, isc_stdtime_t now, isc_boolean_t incremental)
6188 {
6189 isc_result_t result;
6190 dns_dbnode_t *node = NULL;
6191 dns_rdataset_t rdataset;
6192 unsigned int i;
6193 dns_rdata_rrsig_t rrsig;
6194 isc_boolean_t found;
6195 isc_int64_t timewarn = 0, timemaybe = 0;
6196
6197 dns_rdataset_init(&rdataset);
6198
6199 if (type == dns_rdatatype_nsec3)
6200 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
6201 else
6202 result = dns_db_findnode(db, name, ISC_FALSE, &node);
6203 if (result == ISC_R_NOTFOUND)
6204 return (ISC_R_SUCCESS);
6205 if (result != ISC_R_SUCCESS)
6206 goto failure;
6207 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_rrsig, type,
6208 (isc_stdtime_t) 0, &rdataset, NULL);
6209 dns_db_detachnode(db, &node);
6210
6211 if (result == ISC_R_NOTFOUND) {
6212 INSIST(!dns_rdataset_isassociated(&rdataset));
6213 return (ISC_R_SUCCESS);
6214 }
6215 if (result != ISC_R_SUCCESS) {
6216 INSIST(!dns_rdataset_isassociated(&rdataset));
6217 goto failure;
6218 }
6219
6220 for (result = dns_rdataset_first(&rdataset);
6221 result == ISC_R_SUCCESS;
6222 result = dns_rdataset_next(&rdataset)) {
6223 dns_rdata_t rdata = DNS_RDATA_INIT;
6224
6225 dns_rdataset_current(&rdataset, &rdata);
6226 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6227 RUNTIME_CHECK(result == ISC_R_SUCCESS);
6228
6229 if (type != dns_rdatatype_dnskey) {
6230 isc_boolean_t warn = ISC_FALSE, deleted = ISC_FALSE;
6231 if (delsig_ok(&rrsig, keys, nkeys, &warn)) {
6232 result = update_one_rr(db, ver, zonediff->diff,
6233 DNS_DIFFOP_DELRESIGN, name,
6234 rdataset.ttl, &rdata);
6235 if (result != ISC_R_SUCCESS)
6236 break;
6237 deleted = ISC_TRUE;
6238 }
6239 if (warn) {
6240 /*
6241 * At this point, we've got an RRSIG,
6242 * which is signed by an inactive key.
6243 * An administrator needs to provide a new
6244 * key/alg, but until that time, we want to
6245 * keep the old RRSIG. Marking the key as
6246 * offline will prevent us spinning waiting
6247 * for the private part.
6248 */
6249 if (incremental && !deleted) {
6250 result = offline(db, ver, zonediff,
6251 name, rdataset.ttl,
6252 &rdata);
6253 if (result != ISC_R_SUCCESS)
6254 break;
6255 }
6256
6257 /*
6258 * Log the key id and algorithm of
6259 * the inactive key with no replacement
6260 */
6261 if (zone->log_key_expired_timer <= now) {
6262 char origin[DNS_NAME_FORMATSIZE];
6263 char algbuf[DNS_NAME_FORMATSIZE];
6264 dns_name_format(&zone->origin, origin,
6265 sizeof(origin));
6266 dns_secalg_format(rrsig.algorithm,
6267 algbuf,
6268 sizeof(algbuf));
6269 dns_zone_log(zone, ISC_LOG_WARNING,
6270 "Key %s/%s/%d "
6271 "missing or inactive "
6272 "and has no replacement: "
6273 "retaining signatures.",
6274 origin, algbuf,
6275 rrsig.keyid);
6276 zone->log_key_expired_timer = now +
6277 3600;
6278 }
6279 }
6280 continue;
6281 }
6282
6283 /*
6284 * RRSIG(DNSKEY) requires special processing.
6285 */
6286 found = ISC_FALSE;
6287 for (i = 0; i < nkeys; i++) {
6288 if (rrsig.algorithm == dst_key_alg(keys[i]) &&
6289 rrsig.keyid == dst_key_id(keys[i])) {
6290 found = ISC_TRUE;
6291 /*
6292 * Mark offline RRSIG(DNSKEY).
6293 * We want the earliest offline expire time
6294 * iff there is a new offline signature.
6295 */
6296 if (!dst_key_inactive(keys[i]) &&
6297 !dst_key_isprivate(keys[i]))
6298 {
6299 isc_int64_t timeexpire =
6300 dns_time64_from32(rrsig.timeexpire);
6301 if (timewarn != 0 &&
6302 timewarn > timeexpire)
6303 timewarn = timeexpire;
6304 if (rdata.flags & DNS_RDATA_OFFLINE) {
6305 if (timemaybe == 0 ||
6306 timemaybe > timeexpire)
6307 timemaybe = timeexpire;
6308 break;
6309 }
6310 if (timewarn == 0)
6311 timewarn = timemaybe;
6312 if (timewarn == 0 ||
6313 timewarn > timeexpire)
6314 timewarn = timeexpire;
6315 result = offline(db, ver, zonediff,
6316 name, rdataset.ttl,
6317 &rdata);
6318 break;
6319 }
6320 result = update_one_rr(db, ver, zonediff->diff,
6321 DNS_DIFFOP_DELRESIGN,
6322 name, rdataset.ttl,
6323 &rdata);
6324 break;
6325 }
6326 }
6327
6328 /*
6329 * If there is not a matching DNSKEY then
6330 * delete the RRSIG.
6331 */
6332 if (!found)
6333 result = update_one_rr(db, ver, zonediff->diff,
6334 DNS_DIFFOP_DELRESIGN, name,
6335 rdataset.ttl, &rdata);
6336 if (result != ISC_R_SUCCESS)
6337 break;
6338 }
6339
6340 dns_rdataset_disassociate(&rdataset);
6341 if (result == ISC_R_NOMORE)
6342 result = ISC_R_SUCCESS;
6343 if (timewarn > 0) {
6344 #if defined(STDTIME_ON_32BITS)
6345 isc_stdtime_t stdwarn = (isc_stdtime_t)timewarn;
6346 if (timewarn == stdwarn)
6347 #endif
6348 set_key_expiry_warning(zone, (isc_stdtime_t)timewarn,
6349 now);
6350 #if defined(STDTIME_ON_32BITS)
6351 else
6352 dns_zone_log(zone, ISC_LOG_ERROR,
6353 "key expiry warning time out of range");
6354 #endif
6355 }
6356 failure:
6357 if (node != NULL)
6358 dns_db_detachnode(db, &node);
6359 return (result);
6360 }
6361
6362 static isc_result_t
6363 add_sigs(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
6364 dns_rdatatype_t type, dns_diff_t *diff, dst_key_t **keys,
6365 unsigned int nkeys, isc_mem_t *mctx, isc_stdtime_t inception,
6366 isc_stdtime_t expire, isc_boolean_t check_ksk,
6367 isc_boolean_t keyset_kskonly)
6368 {
6369 isc_result_t result;
6370 dns_dbnode_t *node = NULL;
6371 dns_rdataset_t rdataset;
6372 dns_rdata_t sig_rdata = DNS_RDATA_INIT;
6373 unsigned char data[1024]; /* XXX */
6374 isc_buffer_t buffer;
6375 unsigned int i, j;
6376
6377 dns_rdataset_init(&rdataset);
6378 isc_buffer_init(&buffer, data, sizeof(data));
6379
6380 if (type == dns_rdatatype_nsec3)
6381 result = dns_db_findnsec3node(db, name, ISC_FALSE, &node);
6382 else
6383 result = dns_db_findnode(db, name, ISC_FALSE, &node);
6384 if (result == ISC_R_NOTFOUND)
6385 return (ISC_R_SUCCESS);
6386 if (result != ISC_R_SUCCESS)
6387 goto failure;
6388 result = dns_db_findrdataset(db, node, ver, type, 0,
6389 (isc_stdtime_t) 0, &rdataset, NULL);
6390 dns_db_detachnode(db, &node);
6391 if (result == ISC_R_NOTFOUND) {
6392 INSIST(!dns_rdataset_isassociated(&rdataset));
6393 return (ISC_R_SUCCESS);
6394 }
6395 if (result != ISC_R_SUCCESS) {
6396 INSIST(!dns_rdataset_isassociated(&rdataset));
6397 goto failure;
6398 }
6399
6400 for (i = 0; i < nkeys; i++) {
6401 isc_boolean_t both = ISC_FALSE;
6402
6403 if (!dst_key_isprivate(keys[i]))
6404 continue;
6405 if (dst_key_inactive(keys[i])) /* Should be redundant. */
6406 continue;
6407
6408 if (check_ksk && !REVOKE(keys[i])) {
6409 isc_boolean_t have_ksk, have_nonksk;
6410 if (KSK(keys[i])) {
6411 have_ksk = ISC_TRUE;
6412 have_nonksk = ISC_FALSE;
6413 } else {
6414 have_ksk = ISC_FALSE;
6415 have_nonksk = ISC_TRUE;
6416 }
6417 for (j = 0; j < nkeys; j++) {
6418 if (j == i || ALG(keys[i]) != ALG(keys[j]))
6419 continue;
6420 if (!dst_key_isprivate(keys[j]))
6421 continue;
6422 if (dst_key_inactive(keys[j])) /* SBR */
6423 continue;
6424 if (REVOKE(keys[j]))
6425 continue;
6426 if (KSK(keys[j]))
6427 have_ksk = ISC_TRUE;
6428 else
6429 have_nonksk = ISC_TRUE;
6430 both = have_ksk && have_nonksk;
6431 if (both)
6432 break;
6433 }
6434 }
6435 if (both) {
6436 /*
6437 * CDS and CDNSKEY are signed with KSK (RFC 7344, 4.1).
6438 */
6439 if (type == dns_rdatatype_dnskey ||
6440 type == dns_rdatatype_cdnskey ||
6441 type == dns_rdatatype_cds)
6442 {
6443 if (!KSK(keys[i]) && keyset_kskonly)
6444 continue;
6445 } else if (KSK(keys[i])) {
6446 continue;
6447 }
6448 } else if (REVOKE(keys[i]) && type != dns_rdatatype_dnskey) {
6449 continue;
6450 }
6451
6452 /* Calculate the signature, creating a RRSIG RDATA. */
6453 isc_buffer_clear(&buffer);
6454 CHECK(dns_dnssec_sign(name, &rdataset, keys[i],
6455 &inception, &expire,
6456 mctx, &buffer, &sig_rdata));
6457 /* Update the database and journal with the RRSIG. */
6458 /* XXX inefficient - will cause dataset merging */
6459 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADDRESIGN,
6460 name, rdataset.ttl, &sig_rdata));
6461 dns_rdata_reset(&sig_rdata);
6462 isc_buffer_init(&buffer, data, sizeof(data));
6463 }
6464
6465 failure:
6466 if (dns_rdataset_isassociated(&rdataset))
6467 dns_rdataset_disassociate(&rdataset);
6468 if (node != NULL)
6469 dns_db_detachnode(db, &node);
6470 return (result);
6471 }
6472
6473 static void
6474 zone_resigninc(dns_zone_t *zone) {
6475 const char *me = "zone_resigninc";
6476 dns_db_t *db = NULL;
6477 dns_dbversion_t *version = NULL;
6478 dns_diff_t _sig_diff;
6479 dns__zonediff_t zonediff;
6480 dns_fixedname_t fixed;
6481 dns_name_t *name;
6482 dns_rdataset_t rdataset;
6483 dns_rdatatype_t covers;
6484 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
6485 isc_boolean_t check_ksk, keyset_kskonly = ISC_FALSE;
6486 isc_result_t result;
6487 isc_stdtime_t now, inception, soaexpire, expire, stop;
6488 isc_uint32_t jitter, sigvalidityinterval;
6489 unsigned int i;
6490 unsigned int nkeys = 0;
6491 unsigned int resign;
6492
6493 ENTER;
6494
6495 dns_rdataset_init(&rdataset);
6496 dns_diff_init(zone->mctx, &_sig_diff);
6497 zonediff_init(&zonediff, &_sig_diff);
6498
6499 /*
6500 * Zone is frozen or automatic resigning is disabled.
6501 * Pause for 5 minutes.
6502 */
6503 if (zone->update_disabled ||
6504 DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_NORESIGN))
6505 {
6506 result = ISC_R_FAILURE;
6507 goto failure;
6508 }
6509
6510 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
6511 dns_db_attach(zone->db, &db);
6512 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
6513
6514 result = dns_db_newversion(db, &version);
6515 if (result != ISC_R_SUCCESS) {
6516 dns_zone_log(zone, ISC_LOG_ERROR,
6517 "zone_resigninc:dns_db_newversion -> %s",
6518 dns_result_totext(result));
6519 goto failure;
6520 }
6521
6522 isc_stdtime_get(&now);
6523
6524 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
6525 DNS_MAXZONEKEYS, zone_keys, &nkeys);
6526 if (result != ISC_R_SUCCESS) {
6527 dns_zone_log(zone, ISC_LOG_ERROR,
6528 "zone_resigninc:dns__zone_findkeys -> %s",
6529 dns_result_totext(result));
6530 goto failure;
6531 }
6532
6533 sigvalidityinterval = zone->sigvalidityinterval;
6534 inception = now - 3600; /* Allow for clock skew. */
6535 soaexpire = now + sigvalidityinterval;
6536 /*
6537 * Spread out signatures over time if they happen to be
6538 * clumped. We don't do this for each add_sigs() call as
6539 * we still want some clustering to occur.
6540 */
6541 if (sigvalidityinterval >= 3600U) {
6542 isc_random_get(&jitter);
6543 if (sigvalidityinterval > 7200U) {
6544 jitter %= 3600;
6545 } else {
6546 jitter %= 1200;
6547 }
6548 expire = soaexpire - jitter - 1;
6549 } else {
6550 expire = soaexpire - 1;
6551 }
6552 stop = now + 5;
6553
6554 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
6555 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
6556
6557 name = dns_fixedname_initname(&fixed);
6558 result = dns_db_getsigningtime(db, &rdataset, name);
6559 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
6560 dns_zone_log(zone, ISC_LOG_ERROR,
6561 "zone_resigninc:dns_db_getsigningtime -> %s",
6562 dns_result_totext(result));
6563 }
6564
6565 i = 0;
6566 while (result == ISC_R_SUCCESS) {
6567 resign = rdataset.resign - zone->sigresigninginterval;
6568 covers = rdataset.covers;
6569 dns_rdataset_disassociate(&rdataset);
6570
6571 /*
6572 * Stop if we hit the SOA as that means we have walked the
6573 * entire zone. The SOA record should always be the most
6574 * recent signature.
6575 */
6576 /* XXXMPA increase number of RRsets signed pre call */
6577 if (covers == dns_rdatatype_soa || i++ > zone->signatures ||
6578 resign > stop)
6579 break;
6580
6581 result = del_sigs(zone, db, version, name, covers, &zonediff,
6582 zone_keys, nkeys, now, ISC_TRUE);
6583 if (result != ISC_R_SUCCESS) {
6584 dns_zone_log(zone, ISC_LOG_ERROR,
6585 "zone_resigninc:del_sigs -> %s",
6586 dns_result_totext(result));
6587 break;
6588 }
6589
6590 result = add_sigs(db, version, name, covers, zonediff.diff,
6591 zone_keys, nkeys, zone->mctx, inception,
6592 expire, check_ksk, keyset_kskonly);
6593 if (result != ISC_R_SUCCESS) {
6594 dns_zone_log(zone, ISC_LOG_ERROR,
6595 "zone_resigninc:add_sigs -> %s",
6596 dns_result_totext(result));
6597 break;
6598 }
6599 result = dns_db_getsigningtime(db, &rdataset, name);
6600 if (nkeys == 0 && result == ISC_R_NOTFOUND) {
6601 result = ISC_R_SUCCESS;
6602 break;
6603 }
6604 if (result != ISC_R_SUCCESS)
6605 dns_zone_log(zone, ISC_LOG_ERROR,
6606 "zone_resigninc:dns_db_getsigningtime -> %s",
6607 dns_result_totext(result));
6608 }
6609
6610 if (result != ISC_R_NOMORE && result != ISC_R_SUCCESS)
6611 goto failure;
6612
6613 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
6614 &zonediff, zone_keys, nkeys, now, ISC_TRUE);
6615 if (result != ISC_R_SUCCESS) {
6616 dns_zone_log(zone, ISC_LOG_ERROR,
6617 "zone_resigninc:del_sigs -> %s",
6618 dns_result_totext(result));
6619 goto failure;
6620 }
6621
6622 /*
6623 * Did we change anything in the zone?
6624 */
6625 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
6626 /*
6627 * Commit the changes if any key has been marked as offline.
6628 */
6629 if (zonediff.offline)
6630 dns_db_closeversion(db, &version, ISC_TRUE);
6631 goto failure;
6632 }
6633
6634 /* Increment SOA serial if we have made changes */
6635 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
6636 zone->updatemethod);
6637 if (result != ISC_R_SUCCESS) {
6638 dns_zone_log(zone, ISC_LOG_ERROR,
6639 "zone_resigninc:update_soa_serial -> %s",
6640 dns_result_totext(result));
6641 goto failure;
6642 }
6643
6644 /*
6645 * Generate maximum life time signatures so that the above loop
6646 * termination is sensible.
6647 */
6648 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
6649 zonediff.diff, zone_keys, nkeys, zone->mctx,
6650 inception, soaexpire, check_ksk, keyset_kskonly);
6651 if (result != ISC_R_SUCCESS) {
6652 dns_zone_log(zone, ISC_LOG_ERROR,
6653 "zone_resigninc:add_sigs -> %s",
6654 dns_result_totext(result));
6655 goto failure;
6656 }
6657
6658 /* Write changes to journal file. */
6659 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_resigninc"));
6660
6661 /* Everything has succeeded. Commit the changes. */
6662 dns_db_closeversion(db, &version, ISC_TRUE);
6663
6664 failure:
6665 dns_diff_clear(&_sig_diff);
6666 for (i = 0; i < nkeys; i++)
6667 dst_key_free(&zone_keys[i]);
6668 if (version != NULL) {
6669 dns_db_closeversion(db, &version, ISC_FALSE);
6670 dns_db_detach(&db);
6671 } else if (db != NULL)
6672 dns_db_detach(&db);
6673 if (result == ISC_R_SUCCESS) {
6674 set_resigntime(zone);
6675 LOCK_ZONE(zone);
6676 zone_needdump(zone, DNS_DUMP_DELAY);
6677 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
6678 UNLOCK_ZONE(zone);
6679 } else {
6680 /*
6681 * Something failed. Retry in 5 minutes.
6682 */
6683 isc_interval_t ival;
6684 isc_interval_set(&ival, 300, 0);
6685 isc_time_nowplusinterval(&zone->resigntime, &ival);
6686 }
6687
6688 INSIST(version == NULL);
6689 }
6690
6691 static isc_result_t
6692 next_active(dns_db_t *db, dns_dbversion_t *version, dns_name_t *oldname,
6693 dns_name_t *newname, isc_boolean_t bottom)
6694 {
6695 isc_result_t result;
6696 dns_dbiterator_t *dbit = NULL;
6697 dns_rdatasetiter_t *rdsit = NULL;
6698 dns_dbnode_t *node = NULL;
6699
6700 CHECK(dns_db_createiterator(db, DNS_DB_NONSEC3, &dbit));
6701 CHECK(dns_dbiterator_seek(dbit, oldname));
6702 do {
6703 result = dns_dbiterator_next(dbit);
6704 if (result == ISC_R_NOMORE)
6705 CHECK(dns_dbiterator_first(dbit));
6706 CHECK(dns_dbiterator_current(dbit, &node, newname));
6707 if (bottom && dns_name_issubdomain(newname, oldname) &&
6708 !dns_name_equal(newname, oldname)) {
6709 dns_db_detachnode(db, &node);
6710 continue;
6711 }
6712 /*
6713 * Is this node empty?
6714 */
6715 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsit));
6716 result = dns_rdatasetiter_first(rdsit);
6717 dns_db_detachnode(db, &node);
6718 dns_rdatasetiter_destroy(&rdsit);
6719 if (result != ISC_R_NOMORE)
6720 break;
6721 } while (1);
6722 failure:
6723 if (node != NULL)
6724 dns_db_detachnode(db, &node);
6725 if (dbit != NULL)
6726 dns_dbiterator_destroy(&dbit);
6727 return (result);
6728 }
6729
6730 static isc_boolean_t
6731 signed_with_key(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
6732 dns_rdatatype_t type, dst_key_t *key)
6733 {
6734 isc_result_t result;
6735 dns_rdataset_t rdataset;
6736 dns_rdata_t rdata = DNS_RDATA_INIT;
6737 dns_rdata_rrsig_t rrsig;
6738
6739 dns_rdataset_init(&rdataset);
6740 result = dns_db_findrdataset(db, node, version, dns_rdatatype_rrsig,
6741 type, 0, &rdataset, NULL);
6742 if (result != ISC_R_SUCCESS) {
6743 INSIST(!dns_rdataset_isassociated(&rdataset));
6744 return (ISC_FALSE);
6745 }
6746 for (result = dns_rdataset_first(&rdataset);
6747 result == ISC_R_SUCCESS;
6748 result = dns_rdataset_next(&rdataset)) {
6749 dns_rdataset_current(&rdataset, &rdata);
6750 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
6751 INSIST(result == ISC_R_SUCCESS);
6752 if (rrsig.algorithm == dst_key_alg(key) &&
6753 rrsig.keyid == dst_key_id(key)) {
6754 dns_rdataset_disassociate(&rdataset);
6755 return (ISC_TRUE);
6756 }
6757 dns_rdata_reset(&rdata);
6758 }
6759 dns_rdataset_disassociate(&rdataset);
6760 return (ISC_FALSE);
6761 }
6762
6763 static isc_result_t
6764 add_nsec(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6765 dns_dbnode_t *node, dns_ttl_t ttl, isc_boolean_t bottom,
6766 dns_diff_t *diff)
6767 {
6768 dns_fixedname_t fixed;
6769 dns_name_t *next;
6770 dns_rdata_t rdata = DNS_RDATA_INIT;
6771 isc_result_t result;
6772 unsigned char nsecbuffer[DNS_NSEC_BUFFERSIZE];
6773
6774 next = dns_fixedname_initname(&fixed);
6775
6776 CHECK(next_active(db, version, name, next, bottom));
6777 CHECK(dns_nsec_buildrdata(db, version, node, next, nsecbuffer,
6778 &rdata));
6779 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADD, name, ttl,
6780 &rdata));
6781 failure:
6782 return (result);
6783 }
6784
6785 static isc_result_t
6786 sign_a_node(dns_db_t *db, dns_name_t *name, dns_dbnode_t *node,
6787 dns_dbversion_t *version, isc_boolean_t build_nsec3,
6788 isc_boolean_t build_nsec, dst_key_t *key,
6789 isc_stdtime_t inception, isc_stdtime_t expire,
6790 unsigned int minimum, isc_boolean_t is_ksk,
6791 isc_boolean_t keyset_kskonly, isc_boolean_t *delegation,
6792 dns_diff_t *diff, isc_int32_t *signatures, isc_mem_t *mctx)
6793 {
6794 isc_result_t result;
6795 dns_rdatasetiter_t *iterator = NULL;
6796 dns_rdataset_t rdataset;
6797 dns_rdata_t rdata = DNS_RDATA_INIT;
6798 isc_buffer_t buffer;
6799 unsigned char data[1024];
6800 isc_boolean_t seen_soa, seen_ns, seen_rr, seen_dname, seen_nsec,
6801 seen_nsec3, seen_ds;
6802 isc_boolean_t bottom;
6803
6804 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
6805 if (result != ISC_R_SUCCESS) {
6806 if (result == ISC_R_NOTFOUND)
6807 result = ISC_R_SUCCESS;
6808 return (result);
6809 }
6810
6811 dns_rdataset_init(&rdataset);
6812 isc_buffer_init(&buffer, data, sizeof(data));
6813 seen_rr = seen_soa = seen_ns = seen_dname = seen_nsec =
6814 seen_nsec3 = seen_ds = ISC_FALSE;
6815 for (result = dns_rdatasetiter_first(iterator);
6816 result == ISC_R_SUCCESS;
6817 result = dns_rdatasetiter_next(iterator)) {
6818 dns_rdatasetiter_current(iterator, &rdataset);
6819 if (rdataset.type == dns_rdatatype_soa)
6820 seen_soa = ISC_TRUE;
6821 else if (rdataset.type == dns_rdatatype_ns)
6822 seen_ns = ISC_TRUE;
6823 else if (rdataset.type == dns_rdatatype_ds)
6824 seen_ds = ISC_TRUE;
6825 else if (rdataset.type == dns_rdatatype_dname)
6826 seen_dname = ISC_TRUE;
6827 else if (rdataset.type == dns_rdatatype_nsec)
6828 seen_nsec = ISC_TRUE;
6829 else if (rdataset.type == dns_rdatatype_nsec3)
6830 seen_nsec3 = ISC_TRUE;
6831 if (rdataset.type != dns_rdatatype_rrsig)
6832 seen_rr = ISC_TRUE;
6833 dns_rdataset_disassociate(&rdataset);
6834 }
6835 if (result != ISC_R_NOMORE)
6836 goto failure;
6837 if (seen_ns && !seen_soa)
6838 *delegation = ISC_TRUE;
6839 /*
6840 * Going from insecure to NSEC3.
6841 * Don't generate NSEC3 records for NSEC3 records.
6842 */
6843 if (build_nsec3 && !seen_nsec3 && seen_rr) {
6844 isc_boolean_t unsecure = !seen_ds && seen_ns && !seen_soa;
6845 CHECK(dns_nsec3_addnsec3s(db, version, name, minimum,
6846 unsecure, diff));
6847 (*signatures)--;
6848 }
6849 /*
6850 * Going from insecure to NSEC.
6851 * Don't generate NSEC records for NSEC3 records.
6852 */
6853 if (build_nsec && !seen_nsec3 && !seen_nsec && seen_rr) {
6854 /* Build and add NSEC. */
6855 bottom = (seen_ns && !seen_soa) || seen_dname;
6856 /*
6857 * Build a NSEC record except at the origin.
6858 */
6859 if (!dns_name_equal(name, dns_db_origin(db))) {
6860 CHECK(add_nsec(db, version, name, node, minimum,
6861 bottom, diff));
6862 /* Count a NSEC generation as a signature generation. */
6863 (*signatures)--;
6864 }
6865 }
6866 result = dns_rdatasetiter_first(iterator);
6867 while (result == ISC_R_SUCCESS) {
6868 dns_rdatasetiter_current(iterator, &rdataset);
6869 if (rdataset.type == dns_rdatatype_soa ||
6870 rdataset.type == dns_rdatatype_rrsig)
6871 {
6872 goto next_rdataset;
6873 }
6874 if (rdataset.type == dns_rdatatype_dnskey ||
6875 rdataset.type == dns_rdatatype_cdnskey ||
6876 rdataset.type == dns_rdatatype_cds)
6877 {
6878 /*
6879 * CDS and CDNSKEY are signed with KSK like DNSKEY.
6880 * (RFC 7344, section 4.1 specifies that they must
6881 * be signed with a key in the current DS RRset,
6882 * which would only include KSK's.)
6883 */
6884 if (!is_ksk && keyset_kskonly) {
6885 goto next_rdataset;
6886 }
6887 } else if (is_ksk) {
6888 goto next_rdataset;
6889 }
6890 if (*delegation &&
6891 rdataset.type != dns_rdatatype_ds &&
6892 rdataset.type != dns_rdatatype_nsec)
6893 {
6894 goto next_rdataset;
6895 }
6896 if (signed_with_key(db, node, version, rdataset.type, key)) {
6897 goto next_rdataset;
6898 }
6899 /* Calculate the signature, creating a RRSIG RDATA. */
6900 isc_buffer_clear(&buffer);
6901 CHECK(dns_dnssec_sign(name, &rdataset, key, &inception,
6902 &expire, mctx, &buffer, &rdata));
6903 /* Update the database and journal with the RRSIG. */
6904 /* XXX inefficient - will cause dataset merging */
6905 CHECK(update_one_rr(db, version, diff, DNS_DIFFOP_ADDRESIGN,
6906 name, rdataset.ttl, &rdata));
6907 dns_rdata_reset(&rdata);
6908 (*signatures)--;
6909 next_rdataset:
6910 dns_rdataset_disassociate(&rdataset);
6911 result = dns_rdatasetiter_next(iterator);
6912 }
6913 if (result == ISC_R_NOMORE)
6914 result = ISC_R_SUCCESS;
6915 if (seen_dname)
6916 *delegation = ISC_TRUE;
6917 failure:
6918 if (dns_rdataset_isassociated(&rdataset))
6919 dns_rdataset_disassociate(&rdataset);
6920 if (iterator != NULL)
6921 dns_rdatasetiter_destroy(&iterator);
6922 return (result);
6923 }
6924
6925 /*
6926 * If 'update_only' is set then don't create a NSEC RRset if it doesn't exist.
6927 */
6928 static isc_result_t
6929 updatesecure(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
6930 dns_ttl_t minimum, isc_boolean_t update_only, dns_diff_t *diff)
6931 {
6932 isc_result_t result;
6933 dns_rdataset_t rdataset;
6934 dns_dbnode_t *node = NULL;
6935
6936 CHECK(dns_db_getoriginnode(db, &node));
6937 if (update_only) {
6938 dns_rdataset_init(&rdataset);
6939 result = dns_db_findrdataset(db, node, version,
6940 dns_rdatatype_nsec,
6941 dns_rdatatype_none,
6942 0, &rdataset, NULL);
6943 if (dns_rdataset_isassociated(&rdataset))
6944 dns_rdataset_disassociate(&rdataset);
6945 if (result == ISC_R_NOTFOUND)
6946 goto success;
6947 if (result != ISC_R_SUCCESS)
6948 goto failure;
6949 }
6950 CHECK(delete_nsec(db, version, node, name, diff));
6951 CHECK(add_nsec(db, version, name, node, minimum, ISC_FALSE, diff));
6952 success:
6953 result = ISC_R_SUCCESS;
6954 failure:
6955 if (node != NULL)
6956 dns_db_detachnode(db, &node);
6957 return (result);
6958 }
6959
6960 static isc_result_t
6961 updatesignwithkey(dns_zone_t *zone, dns_signing_t *signing,
6962 dns_dbversion_t *version, isc_boolean_t build_nsec3,
6963 dns_ttl_t minimum, dns_diff_t *diff)
6964 {
6965 isc_result_t result;
6966 dns_dbnode_t *node = NULL;
6967 dns_rdataset_t rdataset;
6968 dns_rdata_t rdata = DNS_RDATA_INIT;
6969 unsigned char data[5];
6970 isc_boolean_t seen_done = ISC_FALSE;
6971 isc_boolean_t have_rr = ISC_FALSE;
6972
6973 dns_rdataset_init(&rdataset);
6974 result = dns_db_getoriginnode(signing->db, &node);
6975 if (result != ISC_R_SUCCESS)
6976 goto failure;
6977
6978 result = dns_db_findrdataset(signing->db, node, version,
6979 zone->privatetype, dns_rdatatype_none,
6980 0, &rdataset, NULL);
6981 if (result == ISC_R_NOTFOUND) {
6982 INSIST(!dns_rdataset_isassociated(&rdataset));
6983 result = ISC_R_SUCCESS;
6984 goto failure;
6985 }
6986 if (result != ISC_R_SUCCESS) {
6987 INSIST(!dns_rdataset_isassociated(&rdataset));
6988 goto failure;
6989 }
6990 for (result = dns_rdataset_first(&rdataset);
6991 result == ISC_R_SUCCESS;
6992 result = dns_rdataset_next(&rdataset)) {
6993 dns_rdataset_current(&rdataset, &rdata);
6994 /*
6995 * If we don't match the algorithm or keyid skip the record.
6996 */
6997 if (rdata.length != 5 ||
6998 rdata.data[0] != signing->algorithm ||
6999 rdata.data[1] != ((signing->keyid >> 8) & 0xff) ||
7000 rdata.data[2] != (signing->keyid & 0xff)) {
7001 have_rr = ISC_TRUE;
7002 dns_rdata_reset(&rdata);
7003 continue;
7004 }
7005 /*
7006 * We have a match. If we were signing (!signing->deleteit)
7007 * and we already have a record indicating that we have
7008 * finished signing (rdata.data[4] != 0) then keep it.
7009 * Otherwise it needs to be deleted as we have removed all
7010 * the signatures (signing->deleteit), so any record indicating
7011 * completion is now out of date, or we have finished signing
7012 * with the new record so we no longer need to remember that
7013 * we need to sign the zone with the matching key across a
7014 * nameserver re-start.
7015 */
7016 if (!signing->deleteit && rdata.data[4] != 0) {
7017 seen_done = ISC_TRUE;
7018 have_rr = ISC_TRUE;
7019 } else
7020 CHECK(update_one_rr(signing->db, version, diff,
7021 DNS_DIFFOP_DEL, &zone->origin,
7022 rdataset.ttl, &rdata));
7023 dns_rdata_reset(&rdata);
7024 }
7025 if (result == ISC_R_NOMORE)
7026 result = ISC_R_SUCCESS;
7027 if (!signing->deleteit && !seen_done) {
7028 /*
7029 * If we were signing then we need to indicate that we have
7030 * finished signing the zone with this key. If it is already
7031 * there we don't need to add it a second time.
7032 */
7033 data[0] = signing->algorithm;
7034 data[1] = (signing->keyid >> 8) & 0xff;
7035 data[2] = signing->keyid & 0xff;
7036 data[3] = 0;
7037 data[4] = 1;
7038 rdata.length = sizeof(data);
7039 rdata.data = data;
7040 rdata.type = zone->privatetype;
7041 rdata.rdclass = dns_db_class(signing->db);
7042 CHECK(update_one_rr(signing->db, version, diff, DNS_DIFFOP_ADD,
7043 &zone->origin, rdataset.ttl, &rdata));
7044 } else if (!have_rr) {
7045 dns_name_t *origin = dns_db_origin(signing->db);
7046 /*
7047 * Rebuild the NSEC/NSEC3 record for the origin as we no
7048 * longer have any private records.
7049 */
7050 if (build_nsec3)
7051 CHECK(dns_nsec3_addnsec3s(signing->db, version, origin,
7052 minimum, ISC_FALSE, diff));
7053 CHECK(updatesecure(signing->db, version, origin, minimum,
7054 ISC_TRUE, diff));
7055 }
7056
7057 failure:
7058 if (dns_rdataset_isassociated(&rdataset))
7059 dns_rdataset_disassociate(&rdataset);
7060 if (node != NULL)
7061 dns_db_detachnode(signing->db, &node);
7062 return (result);
7063 }
7064
7065 /*
7066 * Called from zone_nsec3chain() in order to update zone records indicating
7067 * processing status of given NSEC3 chain:
7068 *
7069 * - If the supplied dns_nsec3chain_t structure has been fully processed
7070 * (which is indicated by "active" being set to ISC_FALSE):
7071 *
7072 * - remove all NSEC3PARAM records matching the relevant NSEC3 chain,
7073 *
7074 * - remove all private-type records containing NSEC3PARAM RDATA matching
7075 * the relevant NSEC3 chain.
7076 *
7077 * - If the supplied dns_nsec3chain_t structure has not been fully processed
7078 * (which is indicated by "active" being set to ISC_TRUE), only remove the
7079 * NSEC3PARAM record which matches the relevant NSEC3 chain and has the
7080 * "flags" field set to 0.
7081 *
7082 * - If given NSEC3 chain is being added, add an NSEC3PARAM record contained
7083 * in the relevant private-type record, but with the "flags" field set to
7084 * 0, indicating that this NSEC3 chain is now complete for this zone.
7085 *
7086 * Note that this function is called at different processing stages for NSEC3
7087 * chain additions vs. removals and needs to handle all cases properly.
7088 */
7089 static isc_result_t
7090 fixup_nsec3param(dns_db_t *db, dns_dbversion_t *ver, dns_nsec3chain_t *chain,
7091 isc_boolean_t active, dns_rdatatype_t privatetype,
7092 dns_diff_t *diff)
7093 {
7094 dns_dbnode_t *node = NULL;
7095 dns_name_t *name = dns_db_origin(db);
7096 dns_rdata_t rdata = DNS_RDATA_INIT;
7097 dns_rdataset_t rdataset;
7098 dns_rdata_nsec3param_t nsec3param;
7099 isc_result_t result;
7100 isc_buffer_t buffer;
7101 unsigned char parambuf[DNS_NSEC3PARAM_BUFFERSIZE];
7102 dns_ttl_t ttl = 0;
7103 isc_boolean_t nseconly = ISC_FALSE, nsec3ok = ISC_FALSE;
7104
7105 dns_rdataset_init(&rdataset);
7106
7107 result = dns_db_getoriginnode(db, &node);
7108 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7109 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7110 0, 0, &rdataset, NULL);
7111 if (result == ISC_R_NOTFOUND)
7112 goto try_private;
7113 if (result != ISC_R_SUCCESS)
7114 goto failure;
7115
7116 /*
7117 * Preserve the existing ttl.
7118 */
7119 ttl = rdataset.ttl;
7120
7121 /*
7122 * Delete all NSEC3PARAM records which match that in nsec3chain.
7123 */
7124 for (result = dns_rdataset_first(&rdataset);
7125 result == ISC_R_SUCCESS;
7126 result = dns_rdataset_next(&rdataset)) {
7127
7128 dns_rdataset_current(&rdataset, &rdata);
7129 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7130
7131 if (nsec3param.hash != chain->nsec3param.hash ||
7132 (active && nsec3param.flags != 0) ||
7133 nsec3param.iterations != chain->nsec3param.iterations ||
7134 nsec3param.salt_length != chain->nsec3param.salt_length ||
7135 memcmp(nsec3param.salt, chain->nsec3param.salt,
7136 nsec3param.salt_length)) {
7137 dns_rdata_reset(&rdata);
7138 continue;
7139 }
7140
7141 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7142 name, rdataset.ttl, &rdata));
7143 dns_rdata_reset(&rdata);
7144 }
7145 if (result != ISC_R_NOMORE)
7146 goto failure;
7147
7148 dns_rdataset_disassociate(&rdataset);
7149
7150 try_private:
7151
7152 if (active)
7153 goto add;
7154
7155 result = dns_nsec_nseconly(db, ver, &nseconly);
7156 nsec3ok = (result == ISC_R_SUCCESS && !nseconly);
7157
7158 /*
7159 * Delete all private records which match that in nsec3chain.
7160 */
7161 result = dns_db_findrdataset(db, node, ver, privatetype,
7162 0, 0, &rdataset, NULL);
7163 if (result == ISC_R_NOTFOUND)
7164 goto add;
7165 if (result != ISC_R_SUCCESS)
7166 goto failure;
7167
7168 for (result = dns_rdataset_first(&rdataset);
7169 result == ISC_R_SUCCESS;
7170 result = dns_rdataset_next(&rdataset)) {
7171 dns_rdata_t private = DNS_RDATA_INIT;
7172 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
7173
7174 dns_rdataset_current(&rdataset, &private);
7175 if (!dns_nsec3param_fromprivate(&private, &rdata,
7176 buf, sizeof(buf)))
7177 continue;
7178 CHECK(dns_rdata_tostruct(&rdata, &nsec3param, NULL));
7179
7180 if ((!nsec3ok &&
7181 (nsec3param.flags & DNS_NSEC3FLAG_INITIAL) != 0) ||
7182 nsec3param.hash != chain->nsec3param.hash ||
7183 nsec3param.iterations != chain->nsec3param.iterations ||
7184 nsec3param.salt_length != chain->nsec3param.salt_length ||
7185 memcmp(nsec3param.salt, chain->nsec3param.salt,
7186 nsec3param.salt_length)) {
7187 dns_rdata_reset(&rdata);
7188 continue;
7189 }
7190
7191 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL,
7192 name, rdataset.ttl, &private));
7193 dns_rdata_reset(&rdata);
7194 }
7195 if (result != ISC_R_NOMORE)
7196 goto failure;
7197
7198 add:
7199 if ((chain->nsec3param.flags & DNS_NSEC3FLAG_REMOVE) != 0) {
7200 result = ISC_R_SUCCESS;
7201 goto failure;
7202 }
7203
7204 /*
7205 * Add a NSEC3PARAM record which matches that in nsec3chain but
7206 * with all flags bits cleared.
7207 *
7208 * Note: we do not clear chain->nsec3param.flags as this change
7209 * may be reversed.
7210 */
7211 isc_buffer_init(&buffer, ¶mbuf, sizeof(parambuf));
7212 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db),
7213 dns_rdatatype_nsec3param,
7214 &chain->nsec3param, &buffer));
7215 rdata.data[1] = 0; /* Clear flag bits. */
7216 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_ADD, name, ttl, &rdata));
7217
7218 failure:
7219 dns_db_detachnode(db, &node);
7220 if (dns_rdataset_isassociated(&rdataset))
7221 dns_rdataset_disassociate(&rdataset);
7222 return (result);
7223 }
7224
7225 static isc_result_t
7226 delete_nsec(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7227 dns_name_t *name, dns_diff_t *diff)
7228 {
7229 dns_rdataset_t rdataset;
7230 isc_result_t result;
7231
7232 dns_rdataset_init(&rdataset);
7233
7234 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7235 0, 0, &rdataset, NULL);
7236 if (result == ISC_R_NOTFOUND)
7237 return (ISC_R_SUCCESS);
7238 if (result != ISC_R_SUCCESS)
7239 return (result);
7240 for (result = dns_rdataset_first(&rdataset);
7241 result == ISC_R_SUCCESS;
7242 result = dns_rdataset_next(&rdataset)) {
7243 dns_rdata_t rdata = DNS_RDATA_INIT;
7244
7245 dns_rdataset_current(&rdataset, &rdata);
7246 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7247 rdataset.ttl, &rdata));
7248 }
7249 if (result == ISC_R_NOMORE)
7250 result = ISC_R_SUCCESS;
7251 failure:
7252 dns_rdataset_disassociate(&rdataset);
7253 return (result);
7254 }
7255
7256 static isc_result_t
7257 deletematchingnsec3(dns_db_t *db, dns_dbversion_t *ver, dns_dbnode_t *node,
7258 dns_name_t *name, const dns_rdata_nsec3param_t *param,
7259 dns_diff_t *diff)
7260 {
7261 dns_rdataset_t rdataset;
7262 dns_rdata_nsec3_t nsec3;
7263 isc_result_t result;
7264
7265 dns_rdataset_init(&rdataset);
7266 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3,
7267 0, 0, &rdataset, NULL);
7268 if (result == ISC_R_NOTFOUND)
7269 return (ISC_R_SUCCESS);
7270 if (result != ISC_R_SUCCESS)
7271 return (result);
7272
7273 for (result = dns_rdataset_first(&rdataset);
7274 result == ISC_R_SUCCESS;
7275 result = dns_rdataset_next(&rdataset)) {
7276 dns_rdata_t rdata = DNS_RDATA_INIT;
7277
7278 dns_rdataset_current(&rdataset, &rdata);
7279 CHECK(dns_rdata_tostruct(&rdata, &nsec3, NULL));
7280 if (nsec3.hash != param->hash ||
7281 nsec3.iterations != param->iterations ||
7282 nsec3.salt_length != param->salt_length ||
7283 memcmp(nsec3.salt, param->salt, nsec3.salt_length))
7284 continue;
7285 CHECK(update_one_rr(db, ver, diff, DNS_DIFFOP_DEL, name,
7286 rdataset.ttl, &rdata));
7287 }
7288 if (result == ISC_R_NOMORE)
7289 result = ISC_R_SUCCESS;
7290 failure:
7291 dns_rdataset_disassociate(&rdataset);
7292 return (result);
7293 }
7294
7295 static isc_result_t
7296 need_nsec_chain(dns_db_t *db, dns_dbversion_t *ver,
7297 const dns_rdata_nsec3param_t *param,
7298 isc_boolean_t *answer)
7299 {
7300 dns_dbnode_t *node = NULL;
7301 dns_rdata_t rdata = DNS_RDATA_INIT;
7302 dns_rdata_nsec3param_t myparam;
7303 dns_rdataset_t rdataset;
7304 isc_result_t result;
7305
7306 *answer = ISC_FALSE;
7307
7308 result = dns_db_getoriginnode(db, &node);
7309 RUNTIME_CHECK(result == ISC_R_SUCCESS);
7310
7311 dns_rdataset_init(&rdataset);
7312
7313 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec,
7314 0, 0, &rdataset, NULL);
7315 if (result == ISC_R_SUCCESS) {
7316 dns_rdataset_disassociate(&rdataset);
7317 dns_db_detachnode(db, &node);
7318 return (result);
7319 }
7320 if (result != ISC_R_NOTFOUND) {
7321 dns_db_detachnode(db, &node);
7322 return (result);
7323 }
7324
7325 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_nsec3param,
7326 0, 0, &rdataset, NULL);
7327 if (result == ISC_R_NOTFOUND) {
7328 *answer = ISC_TRUE;
7329 dns_db_detachnode(db, &node);
7330 return (ISC_R_SUCCESS);
7331 }
7332 if (result != ISC_R_SUCCESS) {
7333 dns_db_detachnode(db, &node);
7334 return (result);
7335 }
7336
7337 for (result = dns_rdataset_first(&rdataset);
7338 result == ISC_R_SUCCESS;
7339 result = dns_rdataset_next(&rdataset)) {
7340 dns_rdataset_current(&rdataset, &rdata);
7341 CHECK(dns_rdata_tostruct(&rdata, &myparam, NULL));
7342 dns_rdata_reset(&rdata);
7343 /*
7344 * Ignore any NSEC3PARAM removals.
7345 */
7346 if (NSEC3REMOVE(myparam.flags))
7347 continue;
7348 /*
7349 * Ignore the chain that we are in the process of deleting.
7350 */
7351 if (myparam.hash == param->hash &&
7352 myparam.iterations == param->iterations &&
7353 myparam.salt_length == param->salt_length &&
7354 !memcmp(myparam.salt, param->salt, myparam.salt_length))
7355 continue;
7356 /*
7357 * Found an active NSEC3 chain.
7358 */
7359 break;
7360 }
7361 if (result == ISC_R_NOMORE) {
7362 *answer = ISC_TRUE;
7363 result = ISC_R_SUCCESS;
7364 }
7365
7366 failure:
7367 if (dns_rdataset_isassociated(&rdataset))
7368 dns_rdataset_disassociate(&rdataset);
7369 dns_db_detachnode(db, &node);
7370 return (result);
7371 }
7372
7373 /*%
7374 * Add/remove DNSSEC signatures for the list of "raw" zone changes supplied in
7375 * 'diff'. Gradually remove tuples from 'diff' and append them to 'zonediff'
7376 * along with tuples representing relevant signature changes.
7377 */
7378 isc_result_t
7379 dns__zone_updatesigs(dns_diff_t *diff, dns_db_t *db, dns_dbversion_t *version,
7380 dst_key_t *zone_keys[], unsigned int nkeys,
7381 dns_zone_t *zone, isc_stdtime_t inception,
7382 isc_stdtime_t expire, isc_stdtime_t now,
7383 isc_boolean_t check_ksk, isc_boolean_t keyset_kskonly,
7384 dns__zonediff_t *zonediff)
7385 {
7386 dns_difftuple_t *tuple;
7387 isc_result_t result;
7388
7389 for (tuple = ISC_LIST_HEAD(diff->tuples);
7390 tuple != NULL;
7391 tuple = ISC_LIST_HEAD(diff->tuples)) {
7392 result = del_sigs(zone, db, version, &tuple->name,
7393 tuple->rdata.type, zonediff,
7394 zone_keys, nkeys, now, ISC_FALSE);
7395 if (result != ISC_R_SUCCESS) {
7396 dns_zone_log(zone, ISC_LOG_ERROR,
7397 "dns__zone_updatesigs:del_sigs -> %s",
7398 dns_result_totext(result));
7399 return (result);
7400 }
7401 result = add_sigs(db, version, &tuple->name,
7402 tuple->rdata.type, zonediff->diff,
7403 zone_keys, nkeys, zone->mctx, inception,
7404 expire, check_ksk, keyset_kskonly);
7405 if (result != ISC_R_SUCCESS) {
7406 dns_zone_log(zone, ISC_LOG_ERROR,
7407 "dns__zone_updatesigs:add_sigs -> %s",
7408 dns_result_totext(result));
7409 return (result);
7410 }
7411
7412 do {
7413 dns_difftuple_t *next = ISC_LIST_NEXT(tuple, link);
7414 while (next != NULL &&
7415 (tuple->rdata.type != next->rdata.type ||
7416 !dns_name_equal(&tuple->name, &next->name)))
7417 next = ISC_LIST_NEXT(next, link);
7418 ISC_LIST_UNLINK(diff->tuples, tuple, link);
7419 dns_diff_appendminimal(zonediff->diff, &tuple);
7420 INSIST(tuple == NULL);
7421 tuple = next;
7422 } while (tuple != NULL);
7423 }
7424 return (ISC_R_SUCCESS);
7425 }
7426
7427 /*
7428 * Incrementally build and sign a new NSEC3 chain using the parameters
7429 * requested.
7430 */
7431 static void
7432 zone_nsec3chain(dns_zone_t *zone) {
7433 const char *me = "zone_nsec3chain";
7434 dns_db_t *db = NULL;
7435 dns_dbnode_t *node = NULL;
7436 dns_dbversion_t *version = NULL;
7437 dns_diff_t _sig_diff;
7438 dns_diff_t nsec_diff;
7439 dns_diff_t nsec3_diff;
7440 dns_diff_t param_diff;
7441 dns__zonediff_t zonediff;
7442 dns_fixedname_t fixed;
7443 dns_fixedname_t nextfixed;
7444 dns_name_t *name, *nextname;
7445 dns_rdataset_t rdataset;
7446 dns_nsec3chain_t *nsec3chain = NULL, *nextnsec3chain;
7447 dns_nsec3chainlist_t cleanup;
7448 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
7449 isc_int32_t signatures;
7450 isc_boolean_t check_ksk, keyset_kskonly;
7451 isc_boolean_t delegation;
7452 isc_boolean_t first;
7453 isc_result_t result;
7454 isc_stdtime_t now, inception, soaexpire, expire;
7455 isc_uint32_t jitter, sigvalidityinterval;
7456 unsigned int i;
7457 unsigned int nkeys = 0;
7458 isc_uint32_t nodes;
7459 isc_boolean_t unsecure = ISC_FALSE;
7460 isc_boolean_t seen_soa, seen_ns, seen_dname, seen_ds;
7461 isc_boolean_t seen_nsec, seen_nsec3, seen_rr;
7462 dns_rdatasetiter_t *iterator = NULL;
7463 isc_boolean_t buildnsecchain;
7464 isc_boolean_t updatensec = ISC_FALSE;
7465 dns_rdatatype_t privatetype = zone->privatetype;
7466
7467 ENTER;
7468
7469 dns_rdataset_init(&rdataset);
7470 name = dns_fixedname_initname(&fixed);
7471 nextname = dns_fixedname_initname(&nextfixed);
7472 dns_diff_init(zone->mctx, ¶m_diff);
7473 dns_diff_init(zone->mctx, &nsec3_diff);
7474 dns_diff_init(zone->mctx, &nsec_diff);
7475 dns_diff_init(zone->mctx, &_sig_diff);
7476 zonediff_init(&zonediff, &_sig_diff);
7477 ISC_LIST_INIT(cleanup);
7478
7479 /*
7480 * Updates are disabled. Pause for 5 minutes.
7481 */
7482 if (zone->update_disabled) {
7483 result = ISC_R_FAILURE;
7484 goto failure;
7485 }
7486
7487 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7488 /*
7489 * This function is called when zone timer fires, after the latter gets
7490 * set by zone_addnsec3chain(). If the action triggering the call to
7491 * zone_addnsec3chain() is closely followed by a zone deletion request,
7492 * it might turn out that the timer thread will not be woken up until
7493 * after the zone is deleted by rmzone(), which calls dns_db_detach()
7494 * for zone->db, causing the latter to become NULL. Return immediately
7495 * if that happens.
7496 */
7497 if (zone->db != NULL) {
7498 dns_db_attach(zone->db, &db);
7499 }
7500 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7501 if (db == NULL) {
7502 return;
7503 }
7504
7505 result = dns_db_newversion(db, &version);
7506 if (result != ISC_R_SUCCESS) {
7507 dns_zone_log(zone, ISC_LOG_ERROR,
7508 "zone_nsec3chain:dns_db_newversion -> %s",
7509 dns_result_totext(result));
7510 goto failure;
7511 }
7512
7513 isc_stdtime_get(&now);
7514
7515 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
7516 DNS_MAXZONEKEYS, zone_keys, &nkeys);
7517 if (result != ISC_R_SUCCESS) {
7518 dns_zone_log(zone, ISC_LOG_ERROR,
7519 "zone_nsec3chain:dns__zone_findkeys -> %s",
7520 dns_result_totext(result));
7521 goto failure;
7522 }
7523
7524 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
7525 inception = now - 3600; /* Allow for clock skew. */
7526 soaexpire = now + sigvalidityinterval;
7527
7528 /*
7529 * Spread out signatures over time if they happen to be
7530 * clumped. We don't do this for each add_sigs() call as
7531 * we still want some clustering to occur.
7532 */
7533 if (sigvalidityinterval >= 3600U) {
7534 isc_random_get(&jitter);
7535 if (sigvalidityinterval > 7200U) {
7536 jitter %= 3600;
7537 } else {
7538 jitter %= 1200;
7539 }
7540 expire = soaexpire - jitter - 1;
7541 } else {
7542 expire = soaexpire - 1;
7543 }
7544
7545 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
7546 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
7547
7548 /*
7549 * We keep pulling nodes off each iterator in turn until
7550 * we have no more nodes to pull off or we reach the limits
7551 * for this quantum.
7552 */
7553 nodes = zone->nodes;
7554 signatures = zone->signatures;
7555 LOCK_ZONE(zone);
7556 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7557 UNLOCK_ZONE(zone);
7558 first = ISC_TRUE;
7559
7560 if (nsec3chain != NULL)
7561 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7562 /*
7563 * Generate new NSEC3 chains first.
7564 *
7565 * The following while loop iterates over nodes in the zone database,
7566 * updating the NSEC3 chain by calling dns_nsec3_addnsec3() for each of
7567 * them. Once all nodes are processed, the "delete_nsec" field is
7568 * consulted to check whether we are supposed to remove NSEC records
7569 * from the zone database; if so, the database iterator is reset to
7570 * point to the first node and the loop traverses all of them again,
7571 * this time removing NSEC records. If we hit a node which is obscured
7572 * by a delegation or a DNAME, nodes are skipped over until we find one
7573 * that is not obscured by the same obscuring name and then normal
7574 * processing is resumed.
7575 *
7576 * The above is repeated until all requested NSEC3 chain changes are
7577 * applied or when we reach the limits for this quantum, whichever
7578 * happens first.
7579 *
7580 * Note that the "signatures" variable is only used here to limit the
7581 * amount of work performed. Actual DNSSEC signatures are only
7582 * generated by dns__zone_updatesigs() calls later in this function.
7583 */
7584 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7585 LOCK_ZONE(zone);
7586 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7587
7588 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
7589 if (nsec3chain->done || nsec3chain->db != zone->db) {
7590 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain, link);
7591 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7592 }
7593 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
7594 UNLOCK_ZONE(zone);
7595 if (ISC_LIST_TAIL(cleanup) == nsec3chain)
7596 goto next_addchain;
7597
7598 /*
7599 * Possible future db.
7600 */
7601 if (nsec3chain->db != db) {
7602 goto next_addchain;
7603 }
7604
7605 if (NSEC3REMOVE(nsec3chain->nsec3param.flags))
7606 goto next_addchain;
7607
7608 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
7609
7610 if (nsec3chain->delete_nsec) {
7611 delegation = ISC_FALSE;
7612 dns_dbiterator_pause(nsec3chain->dbiterator);
7613 CHECK(delete_nsec(db, version, node, name, &nsec_diff));
7614 goto next_addnode;
7615 }
7616 /*
7617 * On the first pass we need to check if the current node
7618 * has not been obscured.
7619 */
7620 delegation = ISC_FALSE;
7621 unsecure = ISC_FALSE;
7622 if (first) {
7623 dns_fixedname_t ffound;
7624 dns_name_t *found;
7625 found = dns_fixedname_initname(&ffound);
7626 result = dns_db_find(db, name, version,
7627 dns_rdatatype_soa,
7628 DNS_DBFIND_NOWILD, 0, NULL, found,
7629 NULL, NULL);
7630 if ((result == DNS_R_DELEGATION ||
7631 result == DNS_R_DNAME) &&
7632 !dns_name_equal(name, found)) {
7633 /*
7634 * Remember the obscuring name so that
7635 * we skip all obscured names.
7636 */
7637 dns_name_copy(found, name, NULL);
7638 delegation = ISC_TRUE;
7639 goto next_addnode;
7640 }
7641 }
7642
7643 /*
7644 * Check to see if this is a bottom of zone node.
7645 */
7646 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7647 if (result == ISC_R_NOTFOUND) /* Empty node? */
7648 goto next_addnode;
7649 if (result != ISC_R_SUCCESS)
7650 goto failure;
7651
7652 seen_soa = seen_ns = seen_dname = seen_ds = seen_nsec =
7653 ISC_FALSE;
7654 for (result = dns_rdatasetiter_first(iterator);
7655 result == ISC_R_SUCCESS;
7656 result = dns_rdatasetiter_next(iterator)) {
7657 dns_rdatasetiter_current(iterator, &rdataset);
7658 INSIST(rdataset.type != dns_rdatatype_nsec3);
7659 if (rdataset.type == dns_rdatatype_soa)
7660 seen_soa = ISC_TRUE;
7661 else if (rdataset.type == dns_rdatatype_ns)
7662 seen_ns = ISC_TRUE;
7663 else if (rdataset.type == dns_rdatatype_dname)
7664 seen_dname = ISC_TRUE;
7665 else if (rdataset.type == dns_rdatatype_ds)
7666 seen_ds = ISC_TRUE;
7667 else if (rdataset.type == dns_rdatatype_nsec)
7668 seen_nsec = ISC_TRUE;
7669 dns_rdataset_disassociate(&rdataset);
7670 }
7671 dns_rdatasetiter_destroy(&iterator);
7672 /*
7673 * Is there a NSEC chain than needs to be cleaned up?
7674 */
7675 if (seen_nsec)
7676 nsec3chain->seen_nsec = ISC_TRUE;
7677 if (seen_ns && !seen_soa && !seen_ds)
7678 unsecure = ISC_TRUE;
7679 if ((seen_ns && !seen_soa) || seen_dname)
7680 delegation = ISC_TRUE;
7681
7682 /*
7683 * Process one node.
7684 */
7685 dns_dbiterator_pause(nsec3chain->dbiterator);
7686 result = dns_nsec3_addnsec3(db, version, name,
7687 &nsec3chain->nsec3param,
7688 zone->minimum, unsecure,
7689 &nsec3_diff);
7690 if (result != ISC_R_SUCCESS) {
7691 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
7692 "dns_nsec3_addnsec3 -> %s",
7693 dns_result_totext(result));
7694 goto failure;
7695 }
7696
7697 /*
7698 * Treat each call to dns_nsec3_addnsec3() as if it's cost is
7699 * two signatures. Additionally there will, in general, be
7700 * two signature generated below.
7701 *
7702 * If we are only changing the optout flag the cost is half
7703 * that of the cost of generating a completely new chain.
7704 */
7705 signatures -= 4;
7706
7707 /*
7708 * Go onto next node.
7709 */
7710 next_addnode:
7711 first = ISC_FALSE;
7712 dns_db_detachnode(db, &node);
7713 do {
7714 result = dns_dbiterator_next(nsec3chain->dbiterator);
7715
7716 if (result == ISC_R_NOMORE && nsec3chain->delete_nsec) {
7717 dns_dbiterator_pause(nsec3chain->dbiterator);
7718 CHECK(fixup_nsec3param(db, version, nsec3chain,
7719 ISC_FALSE, privatetype,
7720 ¶m_diff));
7721 LOCK_ZONE(zone);
7722 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7723 link);
7724 UNLOCK_ZONE(zone);
7725 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7726 goto next_addchain;
7727 }
7728 if (result == ISC_R_NOMORE) {
7729 dns_dbiterator_pause(nsec3chain->dbiterator);
7730 if (nsec3chain->seen_nsec) {
7731 CHECK(fixup_nsec3param(db, version,
7732 nsec3chain,
7733 ISC_TRUE,
7734 privatetype,
7735 ¶m_diff));
7736 nsec3chain->delete_nsec = ISC_TRUE;
7737 goto same_addchain;
7738 }
7739 CHECK(fixup_nsec3param(db, version, nsec3chain,
7740 ISC_FALSE, privatetype,
7741 ¶m_diff));
7742 LOCK_ZONE(zone);
7743 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7744 link);
7745 UNLOCK_ZONE(zone);
7746 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7747 goto next_addchain;
7748 } else if (result != ISC_R_SUCCESS) {
7749 dns_zone_log(zone, ISC_LOG_ERROR,
7750 "zone_nsec3chain:"
7751 "dns_dbiterator_next -> %s",
7752 dns_result_totext(result));
7753 goto failure;
7754 } else if (delegation) {
7755 dns_dbiterator_current(nsec3chain->dbiterator,
7756 &node, nextname);
7757 dns_db_detachnode(db, &node);
7758 if (!dns_name_issubdomain(nextname, name))
7759 break;
7760 } else
7761 break;
7762 } while (1);
7763 continue;
7764
7765 same_addchain:
7766 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7767 first = ISC_TRUE;
7768 continue;
7769
7770 next_addchain:
7771 dns_dbiterator_pause(nsec3chain->dbiterator);
7772 nsec3chain = nextnsec3chain;
7773 first = ISC_TRUE;
7774 if (nsec3chain != NULL)
7775 nsec3chain->save_delete_nsec = nsec3chain->delete_nsec;
7776 }
7777
7778 if (nsec3chain != NULL)
7779 goto skip_removals;
7780
7781 /*
7782 * Process removals.
7783 *
7784 * This is a counterpart of the above while loop which takes care of
7785 * removing an NSEC3 chain. It starts with determining whether the
7786 * zone needs to switch from NSEC3 to NSEC; if so, it first builds an
7787 * NSEC chain by iterating over all nodes in the zone database and only
7788 * then goes on to remove NSEC3 records be iterating over all nodes
7789 * again and calling deletematchingnsec3() for each of them; otherwise,
7790 * it starts removing NSEC3 records immediately. Rules for processing
7791 * obscured nodes and interrupting work are the same as for the while
7792 * loop above.
7793 */
7794 LOCK_ZONE(zone);
7795 nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
7796 UNLOCK_ZONE(zone);
7797 first = ISC_TRUE;
7798 buildnsecchain = ISC_FALSE;
7799 while (nsec3chain != NULL && nodes-- > 0 && signatures > 0) {
7800 LOCK_ZONE(zone);
7801 nextnsec3chain = ISC_LIST_NEXT(nsec3chain, link);
7802 UNLOCK_ZONE(zone);
7803
7804 if (nsec3chain->db != db)
7805 goto next_removechain;
7806
7807 if (!NSEC3REMOVE(nsec3chain->nsec3param.flags))
7808 goto next_removechain;
7809
7810 /*
7811 * Work out if we need to build a NSEC chain as a consequence
7812 * of removing this NSEC3 chain.
7813 */
7814 if (first && !updatensec &&
7815 (nsec3chain->nsec3param.flags & DNS_NSEC3FLAG_NONSEC) == 0)
7816 {
7817 result = need_nsec_chain(db, version,
7818 &nsec3chain->nsec3param,
7819 &buildnsecchain);
7820 if (result != ISC_R_SUCCESS) {
7821 dns_zone_log(zone, ISC_LOG_ERROR,
7822 "zone_nsec3chain:"
7823 "need_nsec_chain -> %s",
7824 dns_result_totext(result));
7825 goto failure;
7826 }
7827 }
7828
7829 if (first)
7830 dns_zone_log(zone, ISC_LOG_DEBUG(3), "zone_nsec3chain:"
7831 "buildnsecchain = %u\n", buildnsecchain);
7832
7833 dns_dbiterator_current(nsec3chain->dbiterator, &node, name);
7834 delegation = ISC_FALSE;
7835
7836 if (!buildnsecchain) {
7837 /*
7838 * Delete the NSEC3PARAM record matching this chain.
7839 */
7840 if (first) {
7841 result = fixup_nsec3param(db, version,
7842 nsec3chain,
7843 ISC_TRUE, privatetype,
7844 ¶m_diff);
7845 if (result != ISC_R_SUCCESS) {
7846 dns_zone_log(zone, ISC_LOG_ERROR,
7847 "zone_nsec3chain:"
7848 "fixup_nsec3param -> %s",
7849 dns_result_totext(result));
7850 goto failure;
7851 }
7852 }
7853
7854 /*
7855 * Delete the NSEC3 records.
7856 */
7857 result = deletematchingnsec3(db, version, node, name,
7858 &nsec3chain->nsec3param,
7859 &nsec3_diff);
7860 if (result != ISC_R_SUCCESS) {
7861 dns_zone_log(zone, ISC_LOG_ERROR,
7862 "zone_nsec3chain:"
7863 "deletematchingnsec3 -> %s",
7864 dns_result_totext(result));
7865 goto failure;
7866 }
7867 goto next_removenode;
7868 }
7869
7870 if (first) {
7871 dns_fixedname_t ffound;
7872 dns_name_t *found;
7873 found = dns_fixedname_initname(&ffound);
7874 result = dns_db_find(db, name, version,
7875 dns_rdatatype_soa,
7876 DNS_DBFIND_NOWILD, 0, NULL, found,
7877 NULL, NULL);
7878 if ((result == DNS_R_DELEGATION ||
7879 result == DNS_R_DNAME) &&
7880 !dns_name_equal(name, found)) {
7881 /*
7882 * Remember the obscuring name so that
7883 * we skip all obscured names.
7884 */
7885 dns_name_copy(found, name, NULL);
7886 delegation = ISC_TRUE;
7887 goto next_removenode;
7888 }
7889 }
7890
7891 /*
7892 * Check to see if this is a bottom of zone node.
7893 */
7894 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
7895 if (result == ISC_R_NOTFOUND) /* Empty node? */
7896 goto next_removenode;
7897 if (result != ISC_R_SUCCESS)
7898 goto failure;
7899
7900 seen_soa = seen_ns = seen_dname = seen_nsec3 = seen_nsec =
7901 seen_rr = ISC_FALSE;
7902 for (result = dns_rdatasetiter_first(iterator);
7903 result == ISC_R_SUCCESS;
7904 result = dns_rdatasetiter_next(iterator)) {
7905 dns_rdatasetiter_current(iterator, &rdataset);
7906 if (rdataset.type == dns_rdatatype_soa)
7907 seen_soa = ISC_TRUE;
7908 else if (rdataset.type == dns_rdatatype_ns)
7909 seen_ns = ISC_TRUE;
7910 else if (rdataset.type == dns_rdatatype_dname)
7911 seen_dname = ISC_TRUE;
7912 else if (rdataset.type == dns_rdatatype_nsec)
7913 seen_nsec = ISC_TRUE;
7914 else if (rdataset.type == dns_rdatatype_nsec3)
7915 seen_nsec3 = ISC_TRUE;
7916 if (rdataset.type != dns_rdatatype_rrsig)
7917 seen_rr = ISC_TRUE;
7918 dns_rdataset_disassociate(&rdataset);
7919 }
7920 dns_rdatasetiter_destroy(&iterator);
7921
7922 if (!seen_rr || seen_nsec3 || seen_nsec)
7923 goto next_removenode;
7924 if ((seen_ns && !seen_soa) || seen_dname)
7925 delegation = ISC_TRUE;
7926
7927 /*
7928 * Add a NSEC record except at the origin.
7929 */
7930 if (!dns_name_equal(name, dns_db_origin(db))) {
7931 dns_dbiterator_pause(nsec3chain->dbiterator);
7932 CHECK(add_nsec(db, version, name, node, zone->minimum,
7933 delegation, &nsec_diff));
7934 signatures--;
7935 }
7936
7937 next_removenode:
7938 first = ISC_FALSE;
7939 dns_db_detachnode(db, &node);
7940 do {
7941 result = dns_dbiterator_next(nsec3chain->dbiterator);
7942 if (result == ISC_R_NOMORE && buildnsecchain) {
7943 /*
7944 * The NSEC chain should now be built.
7945 * We can now remove the NSEC3 chain.
7946 */
7947 updatensec = ISC_TRUE;
7948 goto same_removechain;
7949 }
7950 if (result == ISC_R_NOMORE) {
7951 LOCK_ZONE(zone);
7952 ISC_LIST_UNLINK(zone->nsec3chain, nsec3chain,
7953 link);
7954 UNLOCK_ZONE(zone);
7955 ISC_LIST_APPEND(cleanup, nsec3chain, link);
7956 dns_dbiterator_pause(nsec3chain->dbiterator);
7957 result = fixup_nsec3param(db, version,
7958 nsec3chain, ISC_FALSE,
7959 privatetype,
7960 ¶m_diff);
7961 if (result != ISC_R_SUCCESS) {
7962 dns_zone_log(zone, ISC_LOG_ERROR,
7963 "zone_nsec3chain:"
7964 "fixup_nsec3param -> %s",
7965 dns_result_totext(result));
7966 goto failure;
7967 }
7968 goto next_removechain;
7969 } else if (result != ISC_R_SUCCESS) {
7970 dns_zone_log(zone, ISC_LOG_ERROR,
7971 "zone_nsec3chain:"
7972 "dns_dbiterator_next -> %s",
7973 dns_result_totext(result));
7974 goto failure;
7975 } else if (delegation) {
7976 dns_dbiterator_current(nsec3chain->dbiterator,
7977 &node, nextname);
7978 dns_db_detachnode(db, &node);
7979 if (!dns_name_issubdomain(nextname, name))
7980 break;
7981 } else
7982 break;
7983 } while (1);
7984 continue;
7985
7986 same_removechain:
7987 CHECK(dns_dbiterator_first(nsec3chain->dbiterator));
7988 buildnsecchain = ISC_FALSE;
7989 first = ISC_TRUE;
7990 continue;
7991
7992 next_removechain:
7993 dns_dbiterator_pause(nsec3chain->dbiterator);
7994 nsec3chain = nextnsec3chain;
7995 first = ISC_TRUE;
7996 }
7997
7998 skip_removals:
7999 /*
8000 * We may need to update the NSEC/NSEC3 records for the zone apex.
8001 */
8002 if (!ISC_LIST_EMPTY(param_diff.tuples)) {
8003 isc_boolean_t rebuild_nsec = ISC_FALSE,
8004 rebuild_nsec3 = ISC_FALSE;
8005 result = dns_db_getoriginnode(db, &node);
8006 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8007 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8008 if (result != ISC_R_SUCCESS) {
8009 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8010 "dns_db_allrdatasets -> %s",
8011 dns_result_totext(result));
8012 goto failure;
8013 }
8014 for (result = dns_rdatasetiter_first(iterator);
8015 result == ISC_R_SUCCESS;
8016 result = dns_rdatasetiter_next(iterator)) {
8017 dns_rdatasetiter_current(iterator, &rdataset);
8018 if (rdataset.type == dns_rdatatype_nsec)
8019 rebuild_nsec = ISC_TRUE;
8020 if (rdataset.type == dns_rdatatype_nsec3param)
8021 rebuild_nsec3 = ISC_TRUE;
8022 dns_rdataset_disassociate(&rdataset);
8023 }
8024 dns_rdatasetiter_destroy(&iterator);
8025 dns_db_detachnode(db, &node);
8026
8027 if (rebuild_nsec) {
8028 if (nsec3chain != NULL)
8029 dns_dbiterator_pause(nsec3chain->dbiterator);
8030
8031 result = updatesecure(db, version, &zone->origin,
8032 zone->minimum, ISC_TRUE,
8033 &nsec_diff);
8034 if (result != ISC_R_SUCCESS) {
8035 dns_zone_log(zone, ISC_LOG_ERROR,
8036 "zone_nsec3chain:"
8037 "updatesecure -> %s",
8038 dns_result_totext(result));
8039 goto failure;
8040 }
8041 }
8042
8043 if (rebuild_nsec3) {
8044 if (nsec3chain != NULL)
8045 dns_dbiterator_pause(nsec3chain->dbiterator);
8046
8047 result = dns_nsec3_addnsec3s(db, version,
8048 dns_db_origin(db),
8049 zone->minimum, ISC_FALSE,
8050 &nsec3_diff);
8051 if (result != ISC_R_SUCCESS) {
8052 dns_zone_log(zone, ISC_LOG_ERROR,
8053 "zone_nsec3chain:"
8054 "dns_nsec3_addnsec3s -> %s",
8055 dns_result_totext(result));
8056 goto failure;
8057 }
8058 }
8059 }
8060
8061 /*
8062 * Add / update signatures for the NSEC3 records.
8063 */
8064 if (nsec3chain != NULL)
8065 dns_dbiterator_pause(nsec3chain->dbiterator);
8066 result = dns__zone_updatesigs(&nsec3_diff, db, version, zone_keys,
8067 nkeys, zone, inception, expire, now,
8068 check_ksk, keyset_kskonly, &zonediff);
8069 if (result != ISC_R_SUCCESS) {
8070 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8071 "dns__zone_updatesigs -> %s",
8072 dns_result_totext(result));
8073 goto failure;
8074 }
8075
8076 /*
8077 * We have changed the NSEC3PARAM or private RRsets
8078 * above so we need to update the signatures.
8079 */
8080 result = dns__zone_updatesigs(¶m_diff, db, version, zone_keys,
8081 nkeys, zone, inception, expire, now,
8082 check_ksk, keyset_kskonly, &zonediff);
8083 if (result != ISC_R_SUCCESS) {
8084 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8085 "dns__zone_updatesigs -> %s",
8086 dns_result_totext(result));
8087 goto failure;
8088 }
8089
8090 if (updatensec) {
8091 result = updatesecure(db, version, &zone->origin,
8092 zone->minimum, ISC_FALSE, &nsec_diff);
8093 if (result != ISC_R_SUCCESS) {
8094 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8095 "updatesecure -> %s",
8096 dns_result_totext(result));
8097 goto failure;
8098 }
8099 }
8100
8101 result = dns__zone_updatesigs(&nsec_diff, db, version, zone_keys,
8102 nkeys, zone, inception, expire, now,
8103 check_ksk, keyset_kskonly, &zonediff);
8104 if (result != ISC_R_SUCCESS) {
8105 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8106 "dns__zone_updatesigs -> %s",
8107 dns_result_totext(result));
8108 goto failure;
8109 }
8110
8111 /*
8112 * If we made no effective changes to the zone then we can just
8113 * cleanup otherwise we need to increment the serial.
8114 */
8115 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8116 /*
8117 * No need to call dns_db_closeversion() here as it is
8118 * called with commit = ISC_TRUE below.
8119 */
8120 goto done;
8121 }
8122
8123 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8124 &zonediff, zone_keys, nkeys, now, ISC_FALSE);
8125 if (result != ISC_R_SUCCESS) {
8126 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8127 "del_sigs -> %s", dns_result_totext(result));
8128 goto failure;
8129 }
8130
8131 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
8132 zone->updatemethod);
8133 if (result != ISC_R_SUCCESS) {
8134 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8135 "update_soa_serial -> %s",
8136 dns_result_totext(result));
8137 goto failure;
8138 }
8139
8140 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
8141 zonediff.diff, zone_keys, nkeys, zone->mctx,
8142 inception, soaexpire, check_ksk, keyset_kskonly);
8143 if (result != ISC_R_SUCCESS) {
8144 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain:"
8145 "add_sigs -> %s", dns_result_totext(result));
8146 goto failure;
8147 }
8148
8149 /* Write changes to journal file. */
8150 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_nsec3chain"));
8151
8152 LOCK_ZONE(zone);
8153 zone_needdump(zone, DNS_DUMP_DELAY);
8154 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8155 UNLOCK_ZONE(zone);
8156
8157 done:
8158 /*
8159 * Pause all iterators so that dns_db_closeversion() can succeed.
8160 */
8161 LOCK_ZONE(zone);
8162 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8163 nsec3chain != NULL;
8164 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8165 dns_dbiterator_pause(nsec3chain->dbiterator);
8166 UNLOCK_ZONE(zone);
8167
8168 /*
8169 * Everything has succeeded. Commit the changes.
8170 * Unconditionally commit as zonediff.offline not checked above.
8171 */
8172 dns_db_closeversion(db, &version, ISC_TRUE);
8173
8174 /*
8175 * Everything succeeded so we can clean these up now.
8176 */
8177 nsec3chain = ISC_LIST_HEAD(cleanup);
8178 while (nsec3chain != NULL) {
8179 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8180 dns_db_detach(&nsec3chain->db);
8181 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8182 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8183 nsec3chain = ISC_LIST_HEAD(cleanup);
8184 }
8185
8186 set_resigntime(zone);
8187
8188 failure:
8189 if (result != ISC_R_SUCCESS)
8190 dns_zone_log(zone, ISC_LOG_ERROR, "zone_nsec3chain: %s",
8191 dns_result_totext(result));
8192 /*
8193 * On error roll back the current nsec3chain.
8194 */
8195 if (result != ISC_R_SUCCESS && nsec3chain != NULL) {
8196 if (nsec3chain->done) {
8197 dns_db_detach(&nsec3chain->db);
8198 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8199 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8200 } else {
8201 result = dns_dbiterator_first(nsec3chain->dbiterator);
8202 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8203 dns_dbiterator_pause(nsec3chain->dbiterator);
8204 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8205 }
8206 }
8207
8208 /*
8209 * Rollback the cleanup list.
8210 */
8211 nsec3chain = ISC_LIST_TAIL(cleanup);
8212 while (nsec3chain != NULL) {
8213 ISC_LIST_UNLINK(cleanup, nsec3chain, link);
8214 if (nsec3chain->done) {
8215 dns_db_detach(&nsec3chain->db);
8216 dns_dbiterator_destroy(&nsec3chain->dbiterator);
8217 isc_mem_put(zone->mctx, nsec3chain, sizeof *nsec3chain);
8218 } else {
8219 LOCK_ZONE(zone);
8220 ISC_LIST_PREPEND(zone->nsec3chain, nsec3chain, link);
8221 UNLOCK_ZONE(zone);
8222 result = dns_dbiterator_first(nsec3chain->dbiterator);
8223 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8224 dns_dbiterator_pause(nsec3chain->dbiterator);
8225 nsec3chain->delete_nsec = nsec3chain->save_delete_nsec;
8226 }
8227 nsec3chain = ISC_LIST_TAIL(cleanup);
8228 }
8229
8230 LOCK_ZONE(zone);
8231 for (nsec3chain = ISC_LIST_HEAD(zone->nsec3chain);
8232 nsec3chain != NULL;
8233 nsec3chain = ISC_LIST_NEXT(nsec3chain, link))
8234 dns_dbiterator_pause(nsec3chain->dbiterator);
8235 UNLOCK_ZONE(zone);
8236
8237 dns_diff_clear(¶m_diff);
8238 dns_diff_clear(&nsec3_diff);
8239 dns_diff_clear(&nsec_diff);
8240 dns_diff_clear(&_sig_diff);
8241
8242 if (iterator != NULL)
8243 dns_rdatasetiter_destroy(&iterator);
8244
8245 for (i = 0; i < nkeys; i++)
8246 dst_key_free(&zone_keys[i]);
8247
8248 if (node != NULL)
8249 dns_db_detachnode(db, &node);
8250 if (version != NULL) {
8251 dns_db_closeversion(db, &version, ISC_FALSE);
8252 dns_db_detach(&db);
8253 } else if (db != NULL)
8254 dns_db_detach(&db);
8255
8256 LOCK_ZONE(zone);
8257 if (ISC_LIST_HEAD(zone->nsec3chain) != NULL) {
8258 isc_interval_t interval;
8259 if (zone->update_disabled || result != ISC_R_SUCCESS)
8260 isc_interval_set(&interval, 60, 0); /* 1 minute */
8261 else
8262 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
8263 isc_time_nowplusinterval(&zone->nsec3chaintime, &interval);
8264 } else
8265 isc_time_settoepoch(&zone->nsec3chaintime);
8266 UNLOCK_ZONE(zone);
8267
8268 INSIST(version == NULL);
8269 }
8270
8271 /*%
8272 * Delete all RRSIG records with the given algorithm and keyid.
8273 * Remove the NSEC record and RRSIGs if nkeys is zero.
8274 * If all remaining RRsets are signed with the given algorithm
8275 * set *has_algp to ISC_TRUE.
8276 */
8277 static isc_result_t
8278 del_sig(dns_db_t *db, dns_dbversion_t *version, dns_name_t *name,
8279 dns_dbnode_t *node, unsigned int nkeys, dns_secalg_t algorithm,
8280 isc_uint16_t keyid, isc_boolean_t *has_algp, dns_diff_t *diff)
8281 {
8282 dns_rdata_rrsig_t rrsig;
8283 dns_rdataset_t rdataset;
8284 dns_rdatasetiter_t *iterator = NULL;
8285 isc_result_t result;
8286 isc_boolean_t alg_missed = ISC_FALSE;
8287 isc_boolean_t alg_found = ISC_FALSE;
8288
8289 char namebuf[DNS_NAME_FORMATSIZE];
8290 dns_name_format(name, namebuf, sizeof(namebuf));
8291
8292 result = dns_db_allrdatasets(db, node, version, 0, &iterator);
8293 if (result != ISC_R_SUCCESS) {
8294 if (result == ISC_R_NOTFOUND)
8295 result = ISC_R_SUCCESS;
8296 return (result);
8297 }
8298
8299 dns_rdataset_init(&rdataset);
8300 for (result = dns_rdatasetiter_first(iterator);
8301 result == ISC_R_SUCCESS;
8302 result = dns_rdatasetiter_next(iterator)) {
8303 isc_boolean_t has_alg = ISC_FALSE;
8304 dns_rdatasetiter_current(iterator, &rdataset);
8305 if (nkeys == 0 && rdataset.type == dns_rdatatype_nsec) {
8306 for (result = dns_rdataset_first(&rdataset);
8307 result == ISC_R_SUCCESS;
8308 result = dns_rdataset_next(&rdataset)) {
8309 dns_rdata_t rdata = DNS_RDATA_INIT;
8310 dns_rdataset_current(&rdataset, &rdata);
8311 CHECK(update_one_rr(db, version, diff,
8312 DNS_DIFFOP_DEL, name,
8313 rdataset.ttl, &rdata));
8314 }
8315 if (result != ISC_R_NOMORE)
8316 goto failure;
8317 dns_rdataset_disassociate(&rdataset);
8318 continue;
8319 }
8320 if (rdataset.type != dns_rdatatype_rrsig) {
8321 dns_rdataset_disassociate(&rdataset);
8322 continue;
8323 }
8324 for (result = dns_rdataset_first(&rdataset);
8325 result == ISC_R_SUCCESS;
8326 result = dns_rdataset_next(&rdataset))
8327 {
8328 dns_rdata_t rdata = DNS_RDATA_INIT;
8329 dns_rdataset_current(&rdataset, &rdata);
8330 CHECK(dns_rdata_tostruct(&rdata, &rrsig, NULL));
8331 if (nkeys != 0 &&
8332 (rrsig.algorithm != algorithm ||
8333 rrsig.keyid != keyid))
8334 {
8335 if (rrsig.algorithm == algorithm) {
8336 has_alg = ISC_TRUE;
8337 }
8338 continue;
8339 }
8340 CHECK(update_one_rr(db, version, diff,
8341 DNS_DIFFOP_DELRESIGN, name,
8342 rdataset.ttl, &rdata));
8343 }
8344 dns_rdataset_disassociate(&rdataset);
8345 if (result != ISC_R_NOMORE)
8346 break;
8347
8348 /*
8349 * After deleting, if there's still a signature for
8350 * 'algorithm', set alg_found; if not, set alg_missed.
8351 */
8352 if (has_alg) {
8353 alg_found = ISC_TRUE;
8354 } else {
8355 alg_missed = ISC_TRUE;
8356 }
8357 }
8358 if (result == ISC_R_NOMORE)
8359 result = ISC_R_SUCCESS;
8360
8361 /*
8362 * Set `has_algp` if the algorithm was found in every RRset:
8363 * i.e., found in at least one, and not missing from any.
8364 */
8365 *has_algp = ISC_TF(alg_found && !alg_missed);
8366 failure:
8367 if (dns_rdataset_isassociated(&rdataset))
8368 dns_rdataset_disassociate(&rdataset);
8369 dns_rdatasetiter_destroy(&iterator);
8370 return (result);
8371 }
8372
8373 /*
8374 * Incrementally sign the zone using the keys requested.
8375 * Builds the NSEC chain if required.
8376 */
8377 static void
8378 zone_sign(dns_zone_t *zone) {
8379 const char *me = "zone_sign";
8380 dns_db_t *db = NULL;
8381 dns_dbnode_t *node = NULL;
8382 dns_dbversion_t *version = NULL;
8383 dns_diff_t _sig_diff;
8384 dns_diff_t post_diff;
8385 dns__zonediff_t zonediff;
8386 dns_fixedname_t fixed;
8387 dns_fixedname_t nextfixed;
8388 dns_name_t *name, *nextname;
8389 dns_rdataset_t rdataset;
8390 dns_signing_t *signing, *nextsigning;
8391 dns_signinglist_t cleanup;
8392 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
8393 isc_int32_t signatures;
8394 isc_boolean_t check_ksk, keyset_kskonly, is_ksk;
8395 isc_boolean_t with_ksk, with_zsk;
8396 isc_boolean_t commit = ISC_FALSE;
8397 isc_boolean_t delegation;
8398 isc_boolean_t build_nsec = ISC_FALSE;
8399 isc_boolean_t build_nsec3 = ISC_FALSE;
8400 isc_boolean_t first;
8401 isc_result_t result;
8402 isc_stdtime_t now, inception, soaexpire, expire;
8403 isc_uint32_t jitter, sigvalidityinterval;
8404 unsigned int i, j;
8405 unsigned int nkeys = 0;
8406 isc_uint32_t nodes;
8407
8408 ENTER;
8409
8410 dns_rdataset_init(&rdataset);
8411 name = dns_fixedname_initname(&fixed);
8412 nextname = dns_fixedname_initname(&nextfixed);
8413 dns_diff_init(zone->mctx, &_sig_diff);
8414 dns_diff_init(zone->mctx, &post_diff);
8415 zonediff_init(&zonediff, &_sig_diff);
8416 ISC_LIST_INIT(cleanup);
8417
8418 /*
8419 * Updates are disabled. Pause for 5 minutes.
8420 */
8421 if (zone->update_disabled) {
8422 result = ISC_R_FAILURE;
8423 goto failure;
8424 }
8425
8426 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8427 if (zone->db != NULL)
8428 dns_db_attach(zone->db, &db);
8429 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8430 if (db == NULL) {
8431 result = ISC_R_FAILURE;
8432 goto failure;
8433 }
8434
8435 result = dns_db_newversion(db, &version);
8436 if (result != ISC_R_SUCCESS) {
8437 dns_zone_log(zone, ISC_LOG_ERROR,
8438 "zone_sign:dns_db_newversion -> %s",
8439 dns_result_totext(result));
8440 goto failure;
8441 }
8442
8443 isc_stdtime_get(&now);
8444
8445 result = dns__zone_findkeys(zone, db, version, now, zone->mctx,
8446 DNS_MAXZONEKEYS, zone_keys, &nkeys);
8447 if (result != ISC_R_SUCCESS) {
8448 dns_zone_log(zone, ISC_LOG_ERROR,
8449 "zone_sign:dns__zone_findkeys -> %s",
8450 dns_result_totext(result));
8451 goto failure;
8452 }
8453
8454 sigvalidityinterval = dns_zone_getsigvalidityinterval(zone);
8455 inception = now - 3600; /* Allow for clock skew. */
8456 soaexpire = now + sigvalidityinterval;
8457
8458 /*
8459 * Spread out signatures over time if they happen to be
8460 * clumped. We don't do this for each add_sigs() call as
8461 * we still want some clustering to occur.
8462 */
8463 if (sigvalidityinterval >= 3600U) {
8464 isc_random_get(&jitter);
8465 if (sigvalidityinterval > 7200U) {
8466 jitter %= 3600;
8467 } else {
8468 jitter %= 1200;
8469 }
8470 expire = soaexpire - jitter - 1;
8471 } else {
8472 expire = soaexpire - 1;
8473 }
8474
8475 /*
8476 * We keep pulling nodes off each iterator in turn until
8477 * we have no more nodes to pull off or we reach the limits
8478 * for this quantum.
8479 */
8480 nodes = zone->nodes;
8481 signatures = zone->signatures;
8482 signing = ISC_LIST_HEAD(zone->signing);
8483 first = ISC_TRUE;
8484
8485 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
8486 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
8487
8488 /* Determine which type of chain to build */
8489 CHECK(dns_private_chains(db, version, zone->privatetype,
8490 &build_nsec, &build_nsec3));
8491
8492 /* If neither chain is found, default to NSEC */
8493 if (!build_nsec && !build_nsec3)
8494 build_nsec = ISC_TRUE;
8495
8496 while (signing != NULL && nodes-- > 0 && signatures > 0) {
8497 isc_boolean_t has_alg = ISC_FALSE;
8498 nextsigning = ISC_LIST_NEXT(signing, link);
8499
8500 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
8501 if (signing->done || signing->db != zone->db) {
8502 /*
8503 * The zone has been reloaded. We will have
8504 * created new signings as part of the reload
8505 * process so we can destroy this one.
8506 */
8507 ISC_LIST_UNLINK(zone->signing, signing, link);
8508 ISC_LIST_APPEND(cleanup, signing, link);
8509 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8510 goto next_signing;
8511 }
8512 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
8513
8514 if (signing->db != db)
8515 goto next_signing;
8516
8517 delegation = ISC_FALSE;
8518
8519 if (first && signing->deleteit) {
8520 /*
8521 * Remove the key we are deleting from consideration.
8522 */
8523 for (i = 0, j = 0; i < nkeys; i++) {
8524 /*
8525 * Find the key we want to remove.
8526 */
8527 if (ALG(zone_keys[i]) == signing->algorithm &&
8528 dst_key_id(zone_keys[i]) == signing->keyid)
8529 {
8530 if (KSK(zone_keys[i]))
8531 dst_key_free(&zone_keys[i]);
8532 continue;
8533 }
8534 zone_keys[j] = zone_keys[i];
8535 j++;
8536 }
8537 for (i = j; i < nkeys; i++) {
8538 zone_keys[i] = NULL;
8539 }
8540 nkeys = j;
8541 }
8542
8543 dns_dbiterator_current(signing->dbiterator, &node, name);
8544
8545 if (signing->deleteit) {
8546 dns_dbiterator_pause(signing->dbiterator);
8547 CHECK(del_sig(db, version, name, node, nkeys,
8548 signing->algorithm, signing->keyid,
8549 &has_alg, zonediff.diff));
8550 }
8551
8552 /*
8553 * On the first pass we need to check if the current node
8554 * has not been obscured.
8555 */
8556 if (first) {
8557 dns_fixedname_t ffound;
8558 dns_name_t *found;
8559 found = dns_fixedname_initname(&ffound);
8560 result = dns_db_find(db, name, version,
8561 dns_rdatatype_soa,
8562 DNS_DBFIND_NOWILD, 0, NULL, found,
8563 NULL, NULL);
8564 if ((result == DNS_R_DELEGATION ||
8565 result == DNS_R_DNAME) &&
8566 !dns_name_equal(name, found)) {
8567 /*
8568 * Remember the obscuring name so that
8569 * we skip all obscured names.
8570 */
8571 dns_name_copy(found, name, NULL);
8572 delegation = ISC_TRUE;
8573 goto next_node;
8574 }
8575 }
8576
8577 /*
8578 * Process one node.
8579 */
8580 with_ksk = ISC_FALSE;
8581 with_zsk = ISC_FALSE;
8582 dns_dbiterator_pause(signing->dbiterator);
8583 for (i = 0; !has_alg && i < nkeys; i++) {
8584 isc_boolean_t both = ISC_FALSE;
8585
8586 /*
8587 * Find the keys we want to sign with.
8588 */
8589 if (!dst_key_isprivate(zone_keys[i]))
8590 continue;
8591 /*
8592 * Should be redundant.
8593 */
8594 if (dst_key_inactive(zone_keys[i]))
8595 continue;
8596
8597 /*
8598 * When adding look for the specific key.
8599 */
8600 if (!signing->deleteit &&
8601 (dst_key_alg(zone_keys[i]) != signing->algorithm ||
8602 dst_key_id(zone_keys[i]) != signing->keyid))
8603 continue;
8604
8605 /*
8606 * When deleting make sure we are properly signed
8607 * with the algorithm that was being removed.
8608 */
8609 if (signing->deleteit &&
8610 ALG(zone_keys[i]) != signing->algorithm)
8611 continue;
8612
8613 /*
8614 * Do we do KSK processing?
8615 */
8616 if (check_ksk && !REVOKE(zone_keys[i])) {
8617 isc_boolean_t have_ksk, have_nonksk;
8618 if (KSK(zone_keys[i])) {
8619 have_ksk = ISC_TRUE;
8620 have_nonksk = ISC_FALSE;
8621 } else {
8622 have_ksk = ISC_FALSE;
8623 have_nonksk = ISC_TRUE;
8624 }
8625 for (j = 0; j < nkeys; j++) {
8626 if (j == i ||
8627 ALG(zone_keys[i]) !=
8628 ALG(zone_keys[j]))
8629 continue;
8630 if (!dst_key_isprivate(zone_keys[j]))
8631 continue;
8632 /*
8633 * Should be redundant.
8634 */
8635 if (dst_key_inactive(zone_keys[j]))
8636 continue;
8637 if (REVOKE(zone_keys[j]))
8638 continue;
8639 if (KSK(zone_keys[j]))
8640 have_ksk = ISC_TRUE;
8641 else
8642 have_nonksk = ISC_TRUE;
8643 both = have_ksk && have_nonksk;
8644 if (both)
8645 break;
8646 }
8647 }
8648 if (both || REVOKE(zone_keys[i]))
8649 is_ksk = KSK(zone_keys[i]);
8650 else
8651 is_ksk = ISC_FALSE;
8652
8653 /*
8654 * If deleting signatures, we need to ensure that
8655 * the RRset is still signed at least once by a
8656 * KSK and a ZSK.
8657 */
8658 if (signing->deleteit && !is_ksk && with_zsk) {
8659 continue;
8660 }
8661
8662 if (signing->deleteit && is_ksk && with_ksk) {
8663 continue;
8664 }
8665
8666 CHECK(sign_a_node(db, name, node, version, build_nsec3,
8667 build_nsec, zone_keys[i], inception,
8668 expire, zone->minimum, is_ksk,
8669 ISC_TF(both && keyset_kskonly),
8670 &delegation, zonediff.diff,
8671 &signatures, zone->mctx));
8672 /*
8673 * If we are adding we are done. Look for other keys
8674 * of the same algorithm if deleting.
8675 */
8676 if (!signing->deleteit) {
8677 break;
8678 }
8679 if (!is_ksk) {
8680 with_zsk = ISC_TRUE;
8681 }
8682 if (KSK(zone_keys[i])) {
8683 with_ksk = ISC_TRUE;
8684 }
8685 }
8686
8687 /*
8688 * Go onto next node.
8689 */
8690 next_node:
8691 first = ISC_FALSE;
8692 dns_db_detachnode(db, &node);
8693 do {
8694 result = dns_dbiterator_next(signing->dbiterator);
8695 if (result == ISC_R_NOMORE) {
8696 ISC_LIST_UNLINK(zone->signing, signing, link);
8697 ISC_LIST_APPEND(cleanup, signing, link);
8698 dns_dbiterator_pause(signing->dbiterator);
8699 if (nkeys != 0 && build_nsec) {
8700 /*
8701 * We have finished regenerating the
8702 * zone with a zone signing key.
8703 * The NSEC chain is now complete and
8704 * there is a full set of signatures
8705 * for the zone. We can now clear the
8706 * OPT bit from the NSEC record.
8707 */
8708 result = updatesecure(db, version,
8709 &zone->origin,
8710 zone->minimum,
8711 ISC_FALSE,
8712 &post_diff);
8713 if (result != ISC_R_SUCCESS) {
8714 dns_zone_log(zone,
8715 ISC_LOG_ERROR,
8716 "updatesecure -> %s",
8717 dns_result_totext(result));
8718 goto failure;
8719 }
8720 }
8721 result = updatesignwithkey(zone, signing,
8722 version,
8723 build_nsec3,
8724 zone->minimum,
8725 &post_diff);
8726 if (result != ISC_R_SUCCESS) {
8727 dns_zone_log(zone, ISC_LOG_ERROR,
8728 "updatesignwithkey -> %s",
8729 dns_result_totext(result));
8730 goto failure;
8731 }
8732 build_nsec = ISC_FALSE;
8733 goto next_signing;
8734 } else if (result != ISC_R_SUCCESS) {
8735 dns_zone_log(zone, ISC_LOG_ERROR,
8736 "zone_sign:dns_dbiterator_next -> %s",
8737 dns_result_totext(result));
8738 goto failure;
8739 } else if (delegation) {
8740 dns_dbiterator_current(signing->dbiterator,
8741 &node, nextname);
8742 dns_db_detachnode(db, &node);
8743 if (!dns_name_issubdomain(nextname, name))
8744 break;
8745 } else
8746 break;
8747 } while (1);
8748 continue;
8749
8750 next_signing:
8751 dns_dbiterator_pause(signing->dbiterator);
8752 signing = nextsigning;
8753 first = ISC_TRUE;
8754 }
8755
8756 if (ISC_LIST_HEAD(post_diff.tuples) != NULL) {
8757 result = dns__zone_updatesigs(&post_diff, db, version,
8758 zone_keys, nkeys, zone,
8759 inception, expire, now,
8760 check_ksk, keyset_kskonly,
8761 &zonediff);
8762 if (result != ISC_R_SUCCESS) {
8763 dns_zone_log(zone, ISC_LOG_ERROR, "zone_sign:"
8764 "dns__zone_updatesigs -> %s",
8765 dns_result_totext(result));
8766 goto failure;
8767 }
8768 }
8769
8770 /*
8771 * Have we changed anything?
8772 */
8773 if (ISC_LIST_EMPTY(zonediff.diff->tuples)) {
8774 if (zonediff.offline)
8775 commit = ISC_TRUE;
8776 result = ISC_R_SUCCESS;
8777 goto pauseall;
8778 }
8779
8780 commit = ISC_TRUE;
8781
8782 result = del_sigs(zone, db, version, &zone->origin, dns_rdatatype_soa,
8783 &zonediff, zone_keys, nkeys, now, ISC_FALSE);
8784 if (result != ISC_R_SUCCESS) {
8785 dns_zone_log(zone, ISC_LOG_ERROR,
8786 "zone_sign:del_sigs -> %s",
8787 dns_result_totext(result));
8788 goto failure;
8789 }
8790
8791 result = update_soa_serial(db, version, zonediff.diff, zone->mctx,
8792 zone->updatemethod);
8793 if (result != ISC_R_SUCCESS) {
8794 dns_zone_log(zone, ISC_LOG_ERROR,
8795 "zone_sign:update_soa_serial -> %s",
8796 dns_result_totext(result));
8797 goto failure;
8798 }
8799
8800 /*
8801 * Generate maximum life time signatures so that the above loop
8802 * termination is sensible.
8803 */
8804 result = add_sigs(db, version, &zone->origin, dns_rdatatype_soa,
8805 zonediff.diff, zone_keys, nkeys, zone->mctx,
8806 inception, soaexpire, check_ksk, keyset_kskonly);
8807 if (result != ISC_R_SUCCESS) {
8808 dns_zone_log(zone, ISC_LOG_ERROR,
8809 "zone_sign:add_sigs -> %s",
8810 dns_result_totext(result));
8811 goto failure;
8812 }
8813
8814 /*
8815 * Write changes to journal file.
8816 */
8817 CHECK(zone_journal(zone, zonediff.diff, NULL, "zone_sign"));
8818
8819 pauseall:
8820 /*
8821 * Pause all iterators so that dns_db_closeversion() can succeed.
8822 */
8823 for (signing = ISC_LIST_HEAD(zone->signing);
8824 signing != NULL;
8825 signing = ISC_LIST_NEXT(signing, link))
8826 dns_dbiterator_pause(signing->dbiterator);
8827
8828 for (signing = ISC_LIST_HEAD(cleanup);
8829 signing != NULL;
8830 signing = ISC_LIST_NEXT(signing, link))
8831 dns_dbiterator_pause(signing->dbiterator);
8832
8833 /*
8834 * Everything has succeeded. Commit the changes.
8835 */
8836 dns_db_closeversion(db, &version, commit);
8837
8838 /*
8839 * Everything succeeded so we can clean these up now.
8840 */
8841 signing = ISC_LIST_HEAD(cleanup);
8842 while (signing != NULL) {
8843 ISC_LIST_UNLINK(cleanup, signing, link);
8844 dns_db_detach(&signing->db);
8845 dns_dbiterator_destroy(&signing->dbiterator);
8846 isc_mem_put(zone->mctx, signing, sizeof *signing);
8847 signing = ISC_LIST_HEAD(cleanup);
8848 }
8849
8850 set_resigntime(zone);
8851
8852 if (commit) {
8853 LOCK_ZONE(zone);
8854 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
8855 zone_needdump(zone, DNS_DUMP_DELAY);
8856 UNLOCK_ZONE(zone);
8857 }
8858
8859 failure:
8860 /*
8861 * Pause all dbiterators.
8862 */
8863 for (signing = ISC_LIST_HEAD(zone->signing);
8864 signing != NULL;
8865 signing = ISC_LIST_NEXT(signing, link))
8866 dns_dbiterator_pause(signing->dbiterator);
8867
8868 /*
8869 * Rollback the cleanup list.
8870 */
8871 signing = ISC_LIST_HEAD(cleanup);
8872 while (signing != NULL) {
8873 ISC_LIST_UNLINK(cleanup, signing, link);
8874 ISC_LIST_PREPEND(zone->signing, signing, link);
8875 dns_dbiterator_first(signing->dbiterator);
8876 dns_dbiterator_pause(signing->dbiterator);
8877 signing = ISC_LIST_HEAD(cleanup);
8878 }
8879
8880 dns_diff_clear(&_sig_diff);
8881
8882 for (i = 0; i < nkeys; i++)
8883 dst_key_free(&zone_keys[i]);
8884
8885 if (node != NULL)
8886 dns_db_detachnode(db, &node);
8887
8888 if (version != NULL) {
8889 dns_db_closeversion(db, &version, ISC_FALSE);
8890 dns_db_detach(&db);
8891 } else if (db != NULL)
8892 dns_db_detach(&db);
8893
8894 if (ISC_LIST_HEAD(zone->signing) != NULL) {
8895 isc_interval_t interval;
8896 if (zone->update_disabled || result != ISC_R_SUCCESS)
8897 isc_interval_set(&interval, 60, 0); /* 1 minute */
8898 else
8899 isc_interval_set(&interval, 0, 10000000); /* 10 ms */
8900 isc_time_nowplusinterval(&zone->signingtime, &interval);
8901 } else
8902 isc_time_settoepoch(&zone->signingtime);
8903
8904 INSIST(version == NULL);
8905 }
8906
8907 static isc_result_t
8908 normalize_key(dns_rdata_t *rr, dns_rdata_t *target,
8909 unsigned char *data, int size)
8910 {
8911 dns_rdata_dnskey_t dnskey;
8912 dns_rdata_keydata_t keydata;
8913 isc_buffer_t buf;
8914 isc_result_t result;
8915
8916 dns_rdata_reset(target);
8917 isc_buffer_init(&buf, data, size);
8918
8919 switch (rr->type) {
8920 case dns_rdatatype_dnskey:
8921 result = dns_rdata_tostruct(rr, &dnskey, NULL);
8922 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8923 dnskey.flags &= ~DNS_KEYFLAG_REVOKE;
8924 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
8925 &dnskey, &buf);
8926 break;
8927 case dns_rdatatype_keydata:
8928 result = dns_rdata_tostruct(rr, &keydata, NULL);
8929 if (result == ISC_R_UNEXPECTEDEND)
8930 return (result);
8931 RUNTIME_CHECK(result == ISC_R_SUCCESS);
8932 dns_keydata_todnskey(&keydata, &dnskey, NULL);
8933 dns_rdata_fromstruct(target, rr->rdclass, dns_rdatatype_dnskey,
8934 &dnskey, &buf);
8935 break;
8936 default:
8937 INSIST(0);
8938 }
8939 return (ISC_R_SUCCESS);
8940 }
8941
8942 /*
8943 * 'rdset' contains either a DNSKEY rdataset from the zone apex, or
8944 * a KEYDATA rdataset from the key zone.
8945 *
8946 * 'rr' contains either a DNSKEY record, or a KEYDATA record
8947 *
8948 * After normalizing keys to the same format (DNSKEY, with revoke bit
8949 * cleared), return ISC_TRUE if a key that matches 'rr' is found in
8950 * 'rdset', or ISC_FALSE if not.
8951 */
8952
8953 static isc_boolean_t
8954 matchkey(dns_rdataset_t *rdset, dns_rdata_t *rr) {
8955 unsigned char data1[4096], data2[4096];
8956 dns_rdata_t rdata, rdata1, rdata2;
8957 isc_result_t result;
8958
8959 dns_rdata_init(&rdata);
8960 dns_rdata_init(&rdata1);
8961 dns_rdata_init(&rdata2);
8962
8963 result = normalize_key(rr, &rdata1, data1, sizeof(data1));
8964 if (result != ISC_R_SUCCESS)
8965 return (ISC_FALSE);
8966
8967 for (result = dns_rdataset_first(rdset);
8968 result == ISC_R_SUCCESS;
8969 result = dns_rdataset_next(rdset)) {
8970 dns_rdata_reset(&rdata);
8971 dns_rdataset_current(rdset, &rdata);
8972 result = normalize_key(&rdata, &rdata2, data2, sizeof(data2));
8973 if (result != ISC_R_SUCCESS)
8974 continue;
8975 if (dns_rdata_compare(&rdata1, &rdata2) == 0)
8976 return (ISC_TRUE);
8977 }
8978
8979 return (ISC_FALSE);
8980 }
8981
8982 /*
8983 * Calculate the refresh interval for a keydata zone, per
8984 * RFC5011: MAX(1 hr,
8985 * MIN(15 days,
8986 * 1/2 * OrigTTL,
8987 * 1/2 * RRSigExpirationInterval))
8988 * or for retries: MAX(1 hr,
8989 * MIN(1 day,
8990 * 1/10 * OrigTTL,
8991 * 1/10 * RRSigExpirationInterval))
8992 */
8993 static inline isc_stdtime_t
8994 refresh_time(dns_keyfetch_t *kfetch, isc_boolean_t retry) {
8995 isc_result_t result;
8996 isc_uint32_t t;
8997 dns_rdataset_t *rdset;
8998 dns_rdata_t sigrr = DNS_RDATA_INIT;
8999 dns_rdata_sig_t sig;
9000 isc_stdtime_t now;
9001
9002 isc_stdtime_get(&now);
9003
9004 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
9005 rdset = &kfetch->dnskeysigset;
9006 else
9007 return (now + dns_zone_mkey_hour);
9008
9009 result = dns_rdataset_first(rdset);
9010 if (result != ISC_R_SUCCESS)
9011 return (now + dns_zone_mkey_hour);
9012
9013 dns_rdataset_current(rdset, &sigrr);
9014 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9015 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9016
9017 if (!retry) {
9018 t = sig.originalttl / 2;
9019
9020 if (isc_serial_gt(sig.timeexpire, now)) {
9021 isc_uint32_t exp = (sig.timeexpire - now) / 2;
9022 if (t > exp)
9023 t = exp;
9024 }
9025
9026 if (t > (15 * dns_zone_mkey_day))
9027 t = (15 * dns_zone_mkey_day);
9028
9029 if (t < dns_zone_mkey_hour)
9030 t = dns_zone_mkey_hour;
9031 } else {
9032 t = sig.originalttl / 10;
9033
9034 if (isc_serial_gt(sig.timeexpire, now)) {
9035 isc_uint32_t exp = (sig.timeexpire - now) / 10;
9036 if (t > exp)
9037 t = exp;
9038 }
9039
9040 if (t > dns_zone_mkey_day)
9041 t = dns_zone_mkey_day;
9042
9043 if (t < dns_zone_mkey_hour)
9044 t = dns_zone_mkey_hour;
9045 }
9046
9047 return (now + t);
9048 }
9049
9050 /*
9051 * This routine is called when no changes are needed in a KEYDATA
9052 * record except to simply update the refresh timer. Caller should
9053 * hold zone lock.
9054 */
9055 static isc_result_t
9056 minimal_update(dns_keyfetch_t *kfetch, dns_dbversion_t *ver, dns_diff_t *diff)
9057 {
9058 isc_result_t result;
9059 isc_buffer_t keyb;
9060 unsigned char key_buf[4096];
9061 dns_rdata_t rdata = DNS_RDATA_INIT;
9062 dns_rdata_keydata_t keydata;
9063 dns_name_t *name;
9064 dns_zone_t *zone = kfetch->zone;
9065 isc_stdtime_t now;
9066
9067 name = dns_fixedname_name(&kfetch->name);
9068 isc_stdtime_get(&now);
9069
9070 for (result = dns_rdataset_first(&kfetch->keydataset);
9071 result == ISC_R_SUCCESS;
9072 result = dns_rdataset_next(&kfetch->keydataset)) {
9073 dns_rdata_reset(&rdata);
9074 dns_rdataset_current(&kfetch->keydataset, &rdata);
9075
9076 /* Delete old version */
9077 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_DEL,
9078 name, 0, &rdata));
9079
9080 /* Update refresh timer */
9081 result = dns_rdata_tostruct(&rdata, &keydata, NULL);
9082 if (result == ISC_R_UNEXPECTEDEND)
9083 continue;
9084 if (result != ISC_R_SUCCESS)
9085 goto failure;
9086 keydata.refresh = refresh_time(kfetch, ISC_TRUE);
9087 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
9088
9089 dns_rdata_reset(&rdata);
9090 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9091 CHECK(dns_rdata_fromstruct(&rdata,
9092 zone->rdclass, dns_rdatatype_keydata,
9093 &keydata, &keyb));
9094
9095 /* Insert updated version */
9096 CHECK(update_one_rr(kfetch->db, ver, diff, DNS_DIFFOP_ADD,
9097 name, 0, &rdata));
9098 }
9099 result = ISC_R_SUCCESS;
9100 failure:
9101 return (result);
9102 }
9103
9104 /*
9105 * Verify that DNSKEY set is signed by the key specified in 'keydata'.
9106 */
9107 static isc_boolean_t
9108 revocable(dns_keyfetch_t *kfetch, dns_rdata_keydata_t *keydata) {
9109 isc_result_t result;
9110 dns_name_t *keyname;
9111 isc_mem_t *mctx;
9112 dns_rdata_t sigrr = DNS_RDATA_INIT;
9113 dns_rdata_t rr = DNS_RDATA_INIT;
9114 dns_rdata_rrsig_t sig;
9115 dns_rdata_dnskey_t dnskey;
9116 dst_key_t *dstkey = NULL;
9117 unsigned char key_buf[4096];
9118 isc_buffer_t keyb;
9119 isc_boolean_t answer = ISC_FALSE;
9120
9121 REQUIRE(kfetch != NULL && keydata != NULL);
9122 REQUIRE(dns_rdataset_isassociated(&kfetch->dnskeysigset));
9123
9124 keyname = dns_fixedname_name(&kfetch->name);
9125 mctx = kfetch->zone->view->mctx;
9126
9127 /* Generate a key from keydata */
9128 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9129 dns_keydata_todnskey(keydata, &dnskey, NULL);
9130 dns_rdata_fromstruct(&rr, keydata->common.rdclass,
9131 dns_rdatatype_dnskey, &dnskey, &keyb);
9132 result = dns_dnssec_keyfromrdata(keyname, &rr, mctx, &dstkey);
9133 if (result != ISC_R_SUCCESS)
9134 return (ISC_FALSE);
9135
9136 /* See if that key generated any of the signatures */
9137 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9138 result == ISC_R_SUCCESS;
9139 result = dns_rdataset_next(&kfetch->dnskeysigset))
9140 {
9141 dns_fixedname_t fixed;
9142 dns_fixedname_init(&fixed);
9143
9144 dns_rdata_reset(&sigrr);
9145 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9146 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9147 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9148
9149 if (dst_key_alg(dstkey) == sig.algorithm &&
9150 dst_key_rid(dstkey) == sig.keyid)
9151 {
9152 result = dns_dnssec_verify2(keyname,
9153 &kfetch->dnskeyset,
9154 dstkey, ISC_FALSE, mctx, &sigrr,
9155 dns_fixedname_name(&fixed));
9156
9157 dns_zone_log(kfetch->zone, ISC_LOG_DEBUG(3),
9158 "Confirm revoked DNSKEY is self-signed: "
9159 "%s", dns_result_totext(result));
9160
9161 if (result == ISC_R_SUCCESS) {
9162 answer = ISC_TRUE;
9163 break;
9164 }
9165 }
9166 }
9167
9168 dst_key_free(&dstkey);
9169 return (answer);
9170 }
9171
9172 /*
9173 * A DNSKEY set has been fetched from the zone apex of a zone whose trust
9174 * anchors are being managed; scan the keyset, and update the key zone and the
9175 * local trust anchors according to RFC5011.
9176 */
9177 static void
9178 keyfetch_done(isc_task_t *task, isc_event_t *event) {
9179 isc_result_t result, eresult;
9180 dns_fetchevent_t *devent;
9181 dns_keyfetch_t *kfetch;
9182 dns_zone_t *zone;
9183 isc_mem_t *mctx = NULL;
9184 dns_keytable_t *secroots = NULL;
9185 dns_dbversion_t *ver = NULL;
9186 dns_diff_t diff;
9187 isc_boolean_t alldone = ISC_FALSE;
9188 isc_boolean_t commit = ISC_FALSE;
9189 dns_name_t *keyname;
9190 dns_rdata_t sigrr = DNS_RDATA_INIT;
9191 dns_rdata_t dnskeyrr = DNS_RDATA_INIT;
9192 dns_rdata_t keydatarr = DNS_RDATA_INIT;
9193 dns_rdata_rrsig_t sig;
9194 dns_rdata_dnskey_t dnskey;
9195 dns_rdata_keydata_t keydata;
9196 isc_boolean_t initializing;
9197 char namebuf[DNS_NAME_FORMATSIZE];
9198 unsigned char key_buf[4096];
9199 isc_buffer_t keyb;
9200 dst_key_t *dstkey;
9201 isc_stdtime_t now;
9202 int pending = 0;
9203 isc_boolean_t secure = ISC_FALSE, initial = ISC_FALSE;
9204 isc_boolean_t free_needed;
9205
9206 UNUSED(task);
9207 INSIST(event != NULL && event->ev_type == DNS_EVENT_FETCHDONE);
9208 INSIST(event->ev_arg != NULL);
9209
9210 kfetch = event->ev_arg;
9211 zone = kfetch->zone;
9212 isc_mem_attach(zone->mctx, &mctx);
9213 keyname = dns_fixedname_name(&kfetch->name);
9214
9215 devent = (dns_fetchevent_t *) event;
9216 eresult = devent->result;
9217
9218 /* Free resources which are not of interest */
9219 if (devent->node != NULL)
9220 dns_db_detachnode(devent->db, &devent->node);
9221 if (devent->db != NULL)
9222 dns_db_detach(&devent->db);
9223 isc_event_free(&event);
9224 dns_resolver_destroyfetch(&kfetch->fetch);
9225
9226 LOCK_ZONE(zone);
9227 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || zone->view == NULL)
9228 goto cleanup;
9229
9230 isc_stdtime_get(&now);
9231 dns_name_format(keyname, namebuf, sizeof(namebuf));
9232
9233 result = dns_view_getsecroots(zone->view, &secroots);
9234 INSIST(result == ISC_R_SUCCESS);
9235
9236 dns_diff_init(mctx, &diff);
9237
9238 CHECK(dns_db_newversion(kfetch->db, &ver));
9239
9240 zone->refreshkeycount--;
9241 alldone = ISC_TF(zone->refreshkeycount == 0);
9242
9243 if (alldone)
9244 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
9245
9246 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9247 "Returned from key fetch in keyfetch_done() for "
9248 "'%s': %s", namebuf, dns_result_totext(eresult));
9249
9250 /* Fetch failed */
9251 if (eresult != ISC_R_SUCCESS ||
9252 !dns_rdataset_isassociated(&kfetch->dnskeyset)) {
9253 dns_zone_log(zone, ISC_LOG_WARNING,
9254 "Unable to fetch DNSKEY set "
9255 "'%s': %s", namebuf, dns_result_totext(eresult));
9256 CHECK(minimal_update(kfetch, ver, &diff));
9257 goto done;
9258 }
9259
9260 /* No RRSIGs found */
9261 if (!dns_rdataset_isassociated(&kfetch->dnskeysigset)) {
9262 dns_zone_log(zone, ISC_LOG_WARNING,
9263 "No DNSKEY RRSIGs found for "
9264 "'%s': %s", namebuf, dns_result_totext(eresult));
9265 CHECK(minimal_update(kfetch, ver, &diff));
9266 goto done;
9267 }
9268
9269 /*
9270 * Clear any cached trust level, as we need to run validation
9271 * over again; trusted keys might have changed.
9272 */
9273 kfetch->dnskeyset.trust = kfetch->dnskeysigset.trust = dns_trust_none;
9274
9275 /*
9276 * Validate the dnskeyset against the current trusted keys.
9277 */
9278 for (result = dns_rdataset_first(&kfetch->dnskeysigset);
9279 result == ISC_R_SUCCESS;
9280 result = dns_rdataset_next(&kfetch->dnskeysigset))
9281 {
9282 dns_keynode_t *keynode = NULL;
9283
9284 dns_rdata_reset(&sigrr);
9285 dns_rdataset_current(&kfetch->dnskeysigset, &sigrr);
9286 result = dns_rdata_tostruct(&sigrr, &sig, NULL);
9287 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9288
9289 result = dns_keytable_find(secroots, keyname, &keynode);
9290 while (result == ISC_R_SUCCESS) {
9291 dns_keynode_t *nextnode = NULL;
9292 dns_fixedname_t fixed;
9293 dns_fixedname_init(&fixed);
9294
9295 dstkey = dns_keynode_key(keynode);
9296 if (dstkey == NULL) /* fail_secure() was called */
9297 break;
9298
9299 if (dst_key_alg(dstkey) == sig.algorithm &&
9300 dst_key_id(dstkey) == sig.keyid)
9301 {
9302 result = dns_dnssec_verify2(keyname,
9303 &kfetch->dnskeyset,
9304 dstkey, ISC_FALSE,
9305 zone->view->mctx, &sigrr,
9306 dns_fixedname_name(&fixed));
9307
9308 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9309 "Verifying DNSKEY set for zone "
9310 "'%s' using key %d/%d: %s",
9311 namebuf, sig.keyid, sig.algorithm,
9312 dns_result_totext(result));
9313
9314 if (result == ISC_R_SUCCESS) {
9315 kfetch->dnskeyset.trust =
9316 dns_trust_secure;
9317 kfetch->dnskeysigset.trust =
9318 dns_trust_secure;
9319 secure = ISC_TRUE;
9320 initial = dns_keynode_initial(keynode);
9321 dns_keynode_trust(keynode);
9322 break;
9323 }
9324 }
9325
9326 result = dns_keytable_nextkeynode(secroots,
9327 keynode, &nextnode);
9328 dns_keytable_detachkeynode(secroots, &keynode);
9329 keynode = nextnode;
9330 }
9331
9332 if (keynode != NULL) {
9333 dns_keytable_detachkeynode(secroots, &keynode);
9334 }
9335
9336 if (secure) {
9337 break;
9338 }
9339 }
9340
9341 /*
9342 * If we were not able to verify the answer using the current
9343 * trusted keys then all we can do is look at any revoked keys.
9344 */
9345 if (!secure) {
9346 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9347 "DNSKEY set for zone '%s' could not be verified "
9348 "with current keys", namebuf);
9349 }
9350
9351 /*
9352 * First scan keydataset to find keys that are not in dnskeyset
9353 * - Missing keys which are not scheduled for removal,
9354 * log a warning
9355 * - Missing keys which are scheduled for removal and
9356 * the remove hold-down timer has completed should
9357 * be removed from the key zone
9358 * - Missing keys whose acceptance timers have not yet
9359 * completed, log a warning and reset the acceptance
9360 * timer to 30 days in the future
9361 * - All keys not being removed have their refresh timers
9362 * updated
9363 */
9364 initializing = ISC_TRUE;
9365 for (result = dns_rdataset_first(&kfetch->keydataset);
9366 result == ISC_R_SUCCESS;
9367 result = dns_rdataset_next(&kfetch->keydataset))
9368 {
9369 dns_keytag_t keytag;
9370
9371 dns_rdata_reset(&keydatarr);
9372 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9373 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9374 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9375
9376 dns_keydata_todnskey(&keydata, &dnskey, NULL);
9377 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9378 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9379
9380 /*
9381 * If any keydata record has a nonzero add holddown, then
9382 * there was a pre-existing trust anchor for this domain;
9383 * that means we are *not* initializing it and shouldn't
9384 * automatically trust all the keys we find at the zone apex.
9385 */
9386 initializing = initializing && ISC_TF(keydata.addhd == 0);
9387
9388 if (! matchkey(&kfetch->dnskeyset, &keydatarr)) {
9389 isc_boolean_t deletekey = ISC_FALSE;
9390
9391 if (!secure) {
9392 if (keydata.removehd != 0 &&
9393 keydata.removehd <= now) {
9394 deletekey = ISC_TRUE;
9395 }
9396 } else if (keydata.addhd == 0) {
9397 deletekey = ISC_TRUE;
9398 } else if (keydata.addhd > now) {
9399 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9400 "Pending key %d for zone %s "
9401 "unexpectedly missing "
9402 "restarting 30-day acceptance "
9403 "timer", keytag, namebuf);
9404 if (keydata.addhd < now + dns_zone_mkey_month)
9405 keydata.addhd =
9406 now + dns_zone_mkey_month;
9407 keydata.refresh = refresh_time(kfetch,
9408 ISC_FALSE);
9409 } else if (keydata.removehd == 0) {
9410 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9411 "Active key %d for zone %s "
9412 "unexpectedly missing",
9413 keytag, namebuf);
9414 keydata.refresh = now + dns_zone_mkey_hour;
9415 } else if (keydata.removehd <= now) {
9416 deletekey = ISC_TRUE;
9417 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9418 "Revoked key %d for zone %s "
9419 "missing: deleting from "
9420 "managed keys database",
9421 keytag, namebuf);
9422 } else {
9423 keydata.refresh = refresh_time(kfetch,
9424 ISC_FALSE);
9425 }
9426
9427 if (secure || deletekey) {
9428 /* Delete old version */
9429 CHECK(update_one_rr(kfetch->db, ver, &diff,
9430 DNS_DIFFOP_DEL, keyname, 0,
9431 &keydatarr));
9432 }
9433
9434 if (!secure || deletekey)
9435 continue;
9436
9437 dns_rdata_reset(&keydatarr);
9438 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9439 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9440 dns_rdatatype_keydata,
9441 &keydata, &keyb);
9442
9443 /* Insert updated version */
9444 CHECK(update_one_rr(kfetch->db, ver, &diff,
9445 DNS_DIFFOP_ADD, keyname, 0,
9446 &keydatarr));
9447
9448 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
9449 }
9450 }
9451
9452 /*
9453 * Next scan dnskeyset:
9454 * - If new keys are found (i.e., lacking a match in keydataset)
9455 * add them to the key zone and set the acceptance timer
9456 * to 30 days in the future (or to immediately if we've
9457 * determined that we're initializing the zone for the
9458 * first time)
9459 * - Previously-known keys that have been revoked
9460 * must be scheduled for removal from the key zone (or,
9461 * if they hadn't been accepted as trust anchors yet
9462 * anyway, removed at once)
9463 * - Previously-known unrevoked keys whose acceptance timers
9464 * have completed are promoted to trust anchors
9465 * - All keys not being removed have their refresh
9466 * timers updated
9467 */
9468 for (result = dns_rdataset_first(&kfetch->dnskeyset);
9469 result == ISC_R_SUCCESS;
9470 result = dns_rdataset_next(&kfetch->dnskeyset))
9471 {
9472 isc_boolean_t revoked = ISC_FALSE;
9473 isc_boolean_t newkey = ISC_FALSE;
9474 isc_boolean_t updatekey = ISC_FALSE;
9475 isc_boolean_t deletekey = ISC_FALSE;
9476 isc_boolean_t trustkey = ISC_FALSE;
9477 dns_keytag_t keytag;
9478
9479 dns_rdata_reset(&dnskeyrr);
9480 dns_rdataset_current(&kfetch->dnskeyset, &dnskeyrr);
9481 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9482 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9483
9484 /* Skip ZSK's */
9485 if (!ISC_TF(dnskey.flags & DNS_KEYFLAG_KSK))
9486 continue;
9487
9488 result = compute_tag(keyname, &dnskey, mctx, &keytag);
9489 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9490
9491 revoked = ISC_TF(dnskey.flags & DNS_KEYFLAG_REVOKE);
9492
9493 if (matchkey(&kfetch->keydataset, &dnskeyrr)) {
9494 dns_rdata_reset(&keydatarr);
9495 dns_rdataset_current(&kfetch->keydataset, &keydatarr);
9496 result = dns_rdata_tostruct(&keydatarr, &keydata, NULL);
9497 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9498
9499 if (revoked && revocable(kfetch, &keydata)) {
9500 if (keydata.addhd > now) {
9501 /*
9502 * Key wasn't trusted yet, and now
9503 * it's been revoked? Just remove it
9504 */
9505 deletekey = ISC_TRUE;
9506 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9507 "Pending key %d "
9508 "for zone %s is now "
9509 "revoked: "
9510 "deleting from the "
9511 "managed keys database",
9512 keytag, namebuf);
9513 } else if (keydata.removehd == 0) {
9514 /*
9515 * Remove key from secroots.
9516 */
9517 dns_view_untrust(zone->view, keyname,
9518 &dnskey, mctx);
9519
9520 /* If initializing, delete now */
9521 if (keydata.addhd == 0)
9522 deletekey = ISC_TRUE;
9523 else {
9524 keydata.removehd = now +
9525 dns_zone_mkey_month;
9526 keydata.flags |=
9527 DNS_KEYFLAG_REVOKE;
9528 }
9529
9530 dns_zone_log(zone, ISC_LOG_INFO,
9531 "Trusted key %d "
9532 "for zone %s is now "
9533 "revoked",
9534 keytag, namebuf);
9535 } else if (keydata.removehd < now) {
9536 /* Scheduled for removal */
9537 deletekey = ISC_TRUE;
9538
9539 dns_zone_log(zone, ISC_LOG_INFO,
9540 "Revoked key %d "
9541 "for zone %s removal "
9542 "timer complete: "
9543 "deleting from the "
9544 "managed keys database",
9545 keytag, namebuf);
9546 }
9547 } else if (revoked && keydata.removehd == 0) {
9548 dns_zone_log(zone, ISC_LOG_WARNING,
9549 "Active key %d for zone "
9550 "%s is revoked but "
9551 "did not self-sign; "
9552 "ignoring", keytag, namebuf);
9553 continue;
9554 } else if (secure) {
9555 if (keydata.removehd != 0) {
9556 /*
9557 * Key isn't revoked--but it
9558 * seems it used to be.
9559 * Remove it now and add it
9560 * back as if it were a fresh key,
9561 * with a 30-day acceptance timer.
9562 */
9563 deletekey = ISC_TRUE;
9564 newkey = ISC_TRUE;
9565 keydata.removehd = 0;
9566 keydata.addhd =
9567 now + dns_zone_mkey_month;
9568
9569 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9570 "Revoked key %d "
9571 "for zone %s "
9572 "has returned: starting "
9573 "30-day acceptance timer",
9574 keytag, namebuf);
9575 } else if (keydata.addhd > now)
9576 pending++;
9577 else if (keydata.addhd == 0)
9578 keydata.addhd = now;
9579
9580 if (keydata.addhd <= now) {
9581 trustkey = ISC_TRUE;
9582 dns_zone_log(zone, ISC_LOG_INFO,
9583 "Key %d for zone %s "
9584 "is now trusted (%s)",
9585 keytag, namebuf,
9586 initial
9587 ? "initializing key "
9588 "verified"
9589 : "acceptance timer "
9590 "complete");
9591 }
9592 } else if (keydata.addhd > now) {
9593 /*
9594 * Not secure, and key is pending:
9595 * reset the acceptance timer
9596 */
9597 pending++;
9598 keydata.addhd = now + dns_zone_mkey_month;
9599 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9600 "Pending key %d "
9601 "for zone %s was "
9602 "not validated: restarting "
9603 "30-day acceptance timer",
9604 keytag, namebuf);
9605 }
9606
9607 if (!deletekey && !newkey)
9608 updatekey = ISC_TRUE;
9609 } else if (secure) {
9610 /*
9611 * Key wasn't in the key zone but it's
9612 * revoked now anyway, so just skip it
9613 */
9614 if (revoked)
9615 continue;
9616
9617 /* Key wasn't in the key zone: add it */
9618 newkey = ISC_TRUE;
9619
9620 if (initializing) {
9621 dns_zone_log(zone, ISC_LOG_WARNING,
9622 "Initializing automatic trust "
9623 "anchor management for zone '%s'; "
9624 "DNSKEY ID %d is now trusted, "
9625 "waiving the normal 30-day "
9626 "waiting period.",
9627 namebuf, keytag);
9628 trustkey = ISC_TRUE;
9629 } else {
9630 dns_zone_log(zone, ISC_LOG_INFO,
9631 "New key %d observed "
9632 "for zone '%s': "
9633 "starting 30-day "
9634 "acceptance timer",
9635 keytag, namebuf);
9636 }
9637 } else {
9638 /*
9639 * No previously known key, and the key is not
9640 * secure, so skip it.
9641 */
9642 continue;
9643 }
9644
9645 /* Delete old version */
9646 if (deletekey || !newkey)
9647 CHECK(update_one_rr(kfetch->db, ver, &diff,
9648 DNS_DIFFOP_DEL, keyname, 0,
9649 &keydatarr));
9650
9651 if (updatekey) {
9652 /* Set refresh timer */
9653 keydata.refresh = refresh_time(kfetch, ISC_FALSE);
9654 dns_rdata_reset(&keydatarr);
9655 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9656 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9657 dns_rdatatype_keydata,
9658 &keydata, &keyb);
9659
9660 /* Insert updated version */
9661 CHECK(update_one_rr(kfetch->db, ver, &diff,
9662 DNS_DIFFOP_ADD, keyname, 0,
9663 &keydatarr));
9664 } else if (newkey) {
9665 /* Convert DNSKEY to KEYDATA */
9666 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9667 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9668 dns_keydata_fromdnskey(&keydata, &dnskey, 0, 0, 0,
9669 NULL);
9670 keydata.addhd = initializing
9671 ? now : now + dns_zone_mkey_month;
9672 keydata.refresh = refresh_time(kfetch, ISC_FALSE);
9673 dns_rdata_reset(&keydatarr);
9674 isc_buffer_init(&keyb, key_buf, sizeof(key_buf));
9675 dns_rdata_fromstruct(&keydatarr, zone->rdclass,
9676 dns_rdatatype_keydata,
9677 &keydata, &keyb);
9678
9679 /* Insert into key zone */
9680 CHECK(update_one_rr(kfetch->db, ver, &diff,
9681 DNS_DIFFOP_ADD, keyname, 0,
9682 &keydatarr));
9683 }
9684
9685 if (trustkey) {
9686 /* Trust this key. */
9687 result = dns_rdata_tostruct(&dnskeyrr, &dnskey, NULL);
9688 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9689 trust_key(zone, keyname, &dnskey, ISC_FALSE, mctx);
9690 }
9691
9692 if (secure && !deletekey) {
9693 INSIST(newkey || updatekey);
9694 set_refreshkeytimer(zone, &keydata, now, ISC_FALSE);
9695 }
9696 }
9697
9698 /*
9699 * RFC5011 says, "A trust point that has all of its trust anchors
9700 * revoked is considered deleted and is treated as if the trust
9701 * point was never configured." But if someone revoked their
9702 * active key before the standby was trusted, that would mean the
9703 * zone would suddenly be nonsecured. We avoid this by checking to
9704 * see if there's pending keydata. If so, we put a null key in
9705 * the security roots; then all queries to the zone will fail.
9706 */
9707 if (pending != 0)
9708 fail_secure(zone, keyname);
9709
9710 done:
9711 if (!ISC_LIST_EMPTY(diff.tuples)) {
9712 /* Write changes to journal file. */
9713 CHECK(update_soa_serial(kfetch->db, ver, &diff, mctx,
9714 zone->updatemethod));
9715 CHECK(zone_journal(zone, &diff, NULL, "keyfetch_done"));
9716 commit = ISC_TRUE;
9717
9718 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9719 zone_needdump(zone, 30);
9720 } else if (result == ISC_R_NOMORE) {
9721 /*
9722 * If "updatekey" was true for all keys found in the DNSKEY
9723 * response and the previous update of those keys happened
9724 * during the same second (only possible if a key refresh was
9725 * externally triggered), it may happen that all relevant
9726 * update_one_rr() calls will return ISC_R_SUCCESS, but
9727 * diff.tuples will remain empty. Reset result to
9728 * ISC_R_SUCCESS to prevent a bogus warning from being logged.
9729 */
9730 result = ISC_R_SUCCESS;
9731 }
9732
9733 failure:
9734 if (result != ISC_R_SUCCESS) {
9735 dns_zone_log(zone, ISC_LOG_ERROR,
9736 "error during managed-keys processing (%s): "
9737 "DNSSEC validation may be at risk",
9738 isc_result_totext(result));
9739 }
9740 dns_diff_clear(&diff);
9741 if (ver != NULL)
9742 dns_db_closeversion(kfetch->db, &ver, commit);
9743
9744 cleanup:
9745 dns_db_detach(&kfetch->db);
9746
9747 INSIST(zone->irefs > 0);
9748 zone->irefs--;
9749 kfetch->zone = NULL;
9750
9751 if (dns_rdataset_isassociated(&kfetch->keydataset))
9752 dns_rdataset_disassociate(&kfetch->keydataset);
9753 if (dns_rdataset_isassociated(&kfetch->dnskeyset))
9754 dns_rdataset_disassociate(&kfetch->dnskeyset);
9755 if (dns_rdataset_isassociated(&kfetch->dnskeysigset))
9756 dns_rdataset_disassociate(&kfetch->dnskeysigset);
9757
9758 dns_name_free(keyname, mctx);
9759 isc_mem_put(mctx, kfetch, sizeof(dns_keyfetch_t));
9760 isc_mem_detach(&mctx);
9761
9762 if (secroots != NULL)
9763 dns_keytable_detach(&secroots);
9764
9765 free_needed = exit_check(zone);
9766 UNLOCK_ZONE(zone);
9767 if (free_needed)
9768 zone_free(zone);
9769
9770 INSIST(ver == NULL);
9771 }
9772
9773 /*
9774 * Refresh the data in the key zone. Initiate a fetch to get new DNSKEY
9775 * records from the zone apex.
9776 */
9777 static void
9778 zone_refreshkeys(dns_zone_t *zone) {
9779 const char me[] = "zone_refreshkeys";
9780 isc_result_t result;
9781 dns_rriterator_t rrit;
9782 dns_db_t *db = NULL;
9783 dns_dbversion_t *ver = NULL;
9784 dns_diff_t diff;
9785 dns_rdata_t rdata = DNS_RDATA_INIT;
9786 dns_rdata_keydata_t kd;
9787 isc_stdtime_t now;
9788 isc_boolean_t commit = ISC_FALSE;
9789 isc_boolean_t fetching = ISC_FALSE, fetch_err = ISC_FALSE;
9790
9791 ENTER;
9792 REQUIRE(zone->db != NULL);
9793
9794 isc_stdtime_get(&now);
9795
9796 LOCK_ZONE(zone);
9797 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
9798 isc_time_settoepoch(&zone->refreshkeytime);
9799 UNLOCK_ZONE(zone);
9800 return;
9801 }
9802
9803 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
9804 dns_db_attach(zone->db, &db);
9805 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
9806
9807 dns_diff_init(zone->mctx, &diff);
9808
9809 CHECK(dns_db_newversion(db, &ver));
9810
9811 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESHING);
9812
9813 dns_rriterator_init(&rrit, db, ver, 0);
9814 for (result = dns_rriterator_first(&rrit);
9815 result == ISC_R_SUCCESS;
9816 result = dns_rriterator_nextrrset(&rrit)) {
9817 isc_stdtime_t timer = 0xffffffff;
9818 dns_name_t *name = NULL, *kname = NULL;
9819 dns_rdataset_t *kdset = NULL;
9820 dns_keyfetch_t *kfetch;
9821 isc_uint32_t ttl;
9822
9823 dns_rriterator_current(&rrit, &name, &ttl, &kdset, NULL);
9824 if (kdset == NULL || kdset->type != dns_rdatatype_keydata ||
9825 !dns_rdataset_isassociated(kdset))
9826 continue;
9827
9828 /*
9829 * Scan the stored keys looking for ones that need
9830 * removal or refreshing
9831 */
9832 for (result = dns_rdataset_first(kdset);
9833 result == ISC_R_SUCCESS;
9834 result = dns_rdataset_next(kdset)) {
9835 dns_rdata_reset(&rdata);
9836 dns_rdataset_current(kdset, &rdata);
9837 result = dns_rdata_tostruct(&rdata, &kd, NULL);
9838 RUNTIME_CHECK(result == ISC_R_SUCCESS);
9839
9840 /* Removal timer expired? */
9841 if (kd.removehd != 0 && kd.removehd < now) {
9842 CHECK(update_one_rr(db, ver, &diff,
9843 DNS_DIFFOP_DEL, name, ttl,
9844 &rdata));
9845 continue;
9846 }
9847
9848 /* Acceptance timer expired? */
9849 if (kd.addhd <= now)
9850 timer = kd.addhd;
9851
9852 /* Or do we just need to refresh the keyset? */
9853 if (timer > kd.refresh)
9854 timer = kd.refresh;
9855 }
9856
9857 if (timer > now)
9858 continue;
9859
9860 kfetch = isc_mem_get(zone->mctx, sizeof(dns_keyfetch_t));
9861 if (kfetch == NULL) {
9862 fetch_err = ISC_TRUE;
9863 goto failure;
9864 }
9865
9866 zone->refreshkeycount++;
9867 kfetch->zone = zone;
9868 zone->irefs++;
9869 INSIST(zone->irefs != 0);
9870 kname = dns_fixedname_initname(&kfetch->name);
9871 dns_name_dup(name, zone->mctx, kname);
9872 dns_rdataset_init(&kfetch->dnskeyset);
9873 dns_rdataset_init(&kfetch->dnskeysigset);
9874 dns_rdataset_init(&kfetch->keydataset);
9875 dns_rdataset_clone(kdset, &kfetch->keydataset);
9876 kfetch->db = NULL;
9877 dns_db_attach(db, &kfetch->db);
9878 kfetch->fetch = NULL;
9879
9880 if (isc_log_wouldlog(dns_lctx, ISC_LOG_DEBUG(3))) {
9881 char namebuf[DNS_NAME_FORMATSIZE];
9882 dns_name_format(kname, namebuf,
9883 sizeof(namebuf));
9884 dns_zone_log(zone, ISC_LOG_DEBUG(3),
9885 "Creating key fetch in "
9886 "zone_refreshkeys() for '%s'",
9887 namebuf);
9888 }
9889
9890 /*
9891 * Use of DNS_FETCHOPT_NOCACHED is essential here. If it is
9892 * not set and the cache still holds a non-expired, validated
9893 * version of the RRset being queried for by the time the
9894 * response is received, the cached RRset will be passed to
9895 * keyfetch_done() instead of the one received in the response
9896 * as the latter will have a lower trust level due to not being
9897 * validated until keyfetch_done() is called.
9898 */
9899
9900 #ifdef ENABLE_AFL
9901 if (dns_fuzzing_resolver == ISC_FALSE) {
9902 #endif
9903 result = dns_resolver_createfetch(zone->view->resolver,
9904 kname, dns_rdatatype_dnskey,
9905 NULL, NULL, NULL,
9906 DNS_FETCHOPT_NOVALIDATE|
9907 DNS_FETCHOPT_UNSHARED|
9908 DNS_FETCHOPT_NOCACHED,
9909 zone->task,
9910 keyfetch_done, kfetch,
9911 &kfetch->dnskeyset,
9912 &kfetch->dnskeysigset,
9913 &kfetch->fetch);
9914 #ifdef ENABLE_AFL
9915 } else {
9916 result = ISC_R_FAILURE;
9917 }
9918 #endif
9919 if (result == ISC_R_SUCCESS)
9920 fetching = ISC_TRUE;
9921 else {
9922 zone->refreshkeycount--;
9923 zone->irefs--;
9924 dns_db_detach(&kfetch->db);
9925 dns_rdataset_disassociate(&kfetch->keydataset);
9926 dns_name_free(kname, zone->mctx);
9927 isc_mem_put(zone->mctx, kfetch, sizeof(dns_keyfetch_t));
9928 dns_zone_log(zone, ISC_LOG_WARNING,
9929 "Failed to create fetch for "
9930 "DNSKEY update");
9931 fetch_err = ISC_TRUE;
9932 }
9933 }
9934 if (!ISC_LIST_EMPTY(diff.tuples)) {
9935 CHECK(update_soa_serial(db, ver, &diff, zone->mctx,
9936 zone->updatemethod));
9937 CHECK(zone_journal(zone, &diff, NULL, "zone_refreshkeys"));
9938 commit = ISC_TRUE;
9939 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
9940 zone_needdump(zone, 30);
9941 }
9942
9943 failure:
9944 if (fetch_err) {
9945 /*
9946 * Error during a key fetch; retry in an hour.
9947 */
9948 isc_time_t timenow, timethen;
9949 char timebuf[80];
9950
9951 TIME_NOW(&timenow);
9952 DNS_ZONE_TIME_ADD(&timenow, dns_zone_mkey_hour, &timethen);
9953 zone->refreshkeytime = timethen;
9954 zone_settimer(zone, &timenow);
9955
9956 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
9957 dns_zone_log(zone, ISC_LOG_DEBUG(1), "retry key refresh: %s",
9958 timebuf);
9959 }
9960
9961 if (!fetching)
9962 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESHING);
9963
9964 dns_diff_clear(&diff);
9965 if (ver != NULL) {
9966 dns_rriterator_destroy(&rrit);
9967 dns_db_closeversion(db, &ver, commit);
9968 }
9969 dns_db_detach(&db);
9970
9971 UNLOCK_ZONE(zone);
9972
9973 INSIST(ver == NULL);
9974 }
9975
9976 static void
9977 zone_maintenance(dns_zone_t *zone) {
9978 const char me[] = "zone_maintenance";
9979 isc_time_t now;
9980 isc_result_t result;
9981 isc_boolean_t dumping;
9982
9983 REQUIRE(DNS_ZONE_VALID(zone));
9984 ENTER;
9985
9986 /*
9987 * Are we pending load/reload?
9988 */
9989 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING))
9990 return;
9991
9992 /*
9993 * Configuring the view of this zone may have
9994 * failed, for example because the config file
9995 * had a syntax error. In that case, the view
9996 * adb or resolver will be NULL, and we had better not try
9997 * to do further maintenance on it.
9998 */
9999 if (zone->view == NULL || zone->view->adb == NULL)
10000 return;
10001
10002 TIME_NOW(&now);
10003
10004 /*
10005 * Expire check.
10006 */
10007 switch (zone->type) {
10008 case dns_zone_redirect:
10009 if (zone->masters == NULL)
10010 break;
10011 /* FALLTHROUGH */
10012 case dns_zone_slave:
10013 case dns_zone_stub:
10014 LOCK_ZONE(zone);
10015 if (isc_time_compare(&now, &zone->expiretime) >= 0 &&
10016 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10017 zone_expire(zone);
10018 zone->refreshtime = now;
10019 }
10020 UNLOCK_ZONE(zone);
10021 break;
10022 default:
10023 break;
10024 }
10025
10026 /*
10027 * Up to date check.
10028 */
10029 switch (zone->type) {
10030 case dns_zone_redirect:
10031 if (zone->masters == NULL)
10032 break;
10033 /* FALLTHROUGH */
10034 case dns_zone_slave:
10035 case dns_zone_stub:
10036 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) &&
10037 isc_time_compare(&now, &zone->refreshtime) >= 0)
10038 dns_zone_refresh(zone);
10039 break;
10040 default:
10041 break;
10042 }
10043
10044 /*
10045 * Slaves send notifies before backing up to disk, masters after.
10046 */
10047 if (zone->type == dns_zone_slave &&
10048 (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10049 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY)) &&
10050 isc_time_compare(&now, &zone->notifytime) >= 0)
10051 zone_notify(zone, &now);
10052
10053 /*
10054 * Do we need to consolidate the backing store?
10055 */
10056 switch (zone->type) {
10057 case dns_zone_master:
10058 case dns_zone_slave:
10059 case dns_zone_key:
10060 case dns_zone_redirect:
10061 case dns_zone_stub:
10062 LOCK_ZONE(zone);
10063 if (zone->masterfile != NULL &&
10064 isc_time_compare(&now, &zone->dumptime) >= 0 &&
10065 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10066 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) {
10067 dumping = was_dumping(zone);
10068 } else
10069 dumping = ISC_TRUE;
10070 UNLOCK_ZONE(zone);
10071 if (!dumping) {
10072 result = zone_dump(zone, ISC_TRUE); /* task locked */
10073 if (result != ISC_R_SUCCESS)
10074 dns_zone_log(zone, ISC_LOG_WARNING,
10075 "dump failed: %s",
10076 dns_result_totext(result));
10077 }
10078 break;
10079 default:
10080 break;
10081 }
10082
10083 /*
10084 * Master/redirect zones send notifies now, if needed
10085 */
10086 switch (zone->type) {
10087 case dns_zone_master:
10088 case dns_zone_redirect:
10089 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
10090 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))&&
10091 isc_time_compare(&now, &zone->notifytime) >= 0)
10092 zone_notify(zone, &now);
10093 default:
10094 break;
10095 }
10096
10097 /*
10098 * Do we need to refresh keys?
10099 */
10100 switch (zone->type) {
10101 case dns_zone_key:
10102 if (isc_time_compare(&now, &zone->refreshkeytime) >= 0) {
10103 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
10104 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
10105 zone_refreshkeys(zone);
10106 }
10107 }
10108 break;
10109 case dns_zone_master:
10110 if (!isc_time_isepoch(&zone->refreshkeytime) &&
10111 isc_time_compare(&now, &zone->refreshkeytime) >= 0 &&
10112 zone->rss_event == NULL)
10113 zone_rekey(zone);
10114 default:
10115 break;
10116 }
10117
10118 switch (zone->type) {
10119 case dns_zone_master:
10120 case dns_zone_redirect:
10121 case dns_zone_slave:
10122 /*
10123 * Do we need to sign/resign some RRsets?
10124 */
10125 if (zone->rss_event != NULL)
10126 break;
10127 if (!isc_time_isepoch(&zone->signingtime) &&
10128 isc_time_compare(&now, &zone->signingtime) >= 0)
10129 zone_sign(zone);
10130 else if (!isc_time_isepoch(&zone->resigntime) &&
10131 isc_time_compare(&now, &zone->resigntime) >= 0)
10132 zone_resigninc(zone);
10133 else if (!isc_time_isepoch(&zone->nsec3chaintime) &&
10134 isc_time_compare(&now, &zone->nsec3chaintime) >= 0)
10135 zone_nsec3chain(zone);
10136 /*
10137 * Do we need to issue a key expiry warning?
10138 */
10139 if (!isc_time_isepoch(&zone->keywarntime) &&
10140 isc_time_compare(&now, &zone->keywarntime) >= 0)
10141 set_key_expiry_warning(zone, zone->key_expiry,
10142 isc_time_seconds(&now));
10143 break;
10144
10145 default:
10146 break;
10147 }
10148 zone_settimer(zone, &now);
10149 }
10150
10151 void
10152 dns_zone_markdirty(dns_zone_t *zone) {
10153 isc_uint32_t serial;
10154 isc_result_t result = ISC_R_SUCCESS;
10155 dns_zone_t *secure = NULL;
10156
10157 /*
10158 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
10159 * could result in a deadlock due to a LOR so we will spin if we
10160 * can't obtain the both locks.
10161 */
10162 again:
10163 LOCK_ZONE(zone);
10164 if (zone->type == dns_zone_master) {
10165 if (inline_raw(zone)) {
10166 unsigned int soacount;
10167 secure = zone->secure;
10168 INSIST(secure != zone);
10169 TRYLOCK_ZONE(result, secure);
10170 if (result != ISC_R_SUCCESS) {
10171 UNLOCK_ZONE(zone);
10172 secure = NULL;
10173 #ifdef ISC_PLATFORM_USETHREADS
10174 isc_thread_yield();
10175 #endif
10176 goto again;
10177 }
10178
10179 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10180 if (zone->db != NULL) {
10181 result = zone_get_from_db(zone, zone->db, NULL,
10182 &soacount, &serial,
10183 NULL, NULL, NULL,
10184 NULL, NULL);
10185 } else
10186 result = DNS_R_NOTLOADED;
10187 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10188 if (result == ISC_R_SUCCESS && soacount > 0U)
10189 zone_send_secureserial(zone, serial);
10190 }
10191
10192 /* XXXMPA make separate call back */
10193 if (result == ISC_R_SUCCESS)
10194 set_resigntime(zone);
10195 }
10196 if (secure != NULL)
10197 UNLOCK_ZONE(secure);
10198 zone_needdump(zone, DNS_DUMP_DELAY);
10199 UNLOCK_ZONE(zone);
10200 }
10201
10202 void
10203 dns_zone_expire(dns_zone_t *zone) {
10204 REQUIRE(DNS_ZONE_VALID(zone));
10205
10206 LOCK_ZONE(zone);
10207 zone_expire(zone);
10208 UNLOCK_ZONE(zone);
10209 }
10210
10211 static void
10212 zone_expire(dns_zone_t *zone) {
10213 /*
10214 * 'zone' locked by caller.
10215 */
10216
10217 REQUIRE(LOCKED_ZONE(zone));
10218
10219 dns_zone_log(zone, ISC_LOG_WARNING, "expired");
10220
10221 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED);
10222 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
10223 zone->retry = DNS_ZONE_DEFAULTRETRY;
10224 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
10225 zone_unload(zone);
10226 }
10227
10228 void
10229 dns_zone_refresh(dns_zone_t *zone) {
10230 isc_interval_t i;
10231 isc_uint32_t oldflags;
10232 unsigned int j;
10233 isc_result_t result;
10234
10235 REQUIRE(DNS_ZONE_VALID(zone));
10236
10237 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
10238 return;
10239
10240 /*
10241 * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation
10242 * in progress at a time.
10243 */
10244
10245 LOCK_ZONE(zone);
10246 oldflags = zone->flags;
10247 if (zone->masterscnt == 0) {
10248 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS);
10249 if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0)
10250 dns_zone_log(zone, ISC_LOG_ERROR,
10251 "cannot refresh: no masters");
10252 goto unlock;
10253 }
10254 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
10255 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
10256 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
10257 if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0)
10258 goto unlock;
10259
10260 /*
10261 * Set the next refresh time as if refresh check has failed.
10262 * Setting this to the retry time will do that. XXXMLG
10263 * If we are successful it will be reset using zone->refresh.
10264 */
10265 isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4),
10266 0);
10267 result = isc_time_nowplusinterval(&zone->refreshtime, &i);
10268 if (result != ISC_R_SUCCESS)
10269 dns_zone_log(zone, ISC_LOG_WARNING,
10270 "isc_time_nowplusinterval() failed: %s",
10271 dns_result_totext(result));
10272
10273 /*
10274 * When lacking user-specified timer values from the SOA,
10275 * do exponential backoff of the retry time up to a
10276 * maximum of six hours.
10277 */
10278 if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS))
10279 zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
10280
10281 zone->curmaster = 0;
10282 for (j = 0; j < zone->masterscnt; j++)
10283 zone->mastersok[j] = ISC_FALSE;
10284 /* initiate soa query */
10285 queue_soa_query(zone);
10286 unlock:
10287 UNLOCK_ZONE(zone);
10288 }
10289
10290 static void
10291 zone_journal_compact(dns_zone_t *zone, dns_db_t *db, isc_uint32_t serial) {
10292 isc_result_t result;
10293 isc_int32_t journalsize;
10294 dns_dbversion_t *ver = NULL;
10295 isc_uint64_t dbsize;
10296
10297 INSIST(LOCKED_ZONE(zone));
10298 if (inline_raw(zone))
10299 INSIST(LOCKED_ZONE(zone->secure));
10300
10301 journalsize = zone->journalsize;
10302 if (journalsize == -1) {
10303 journalsize = DNS_JOURNAL_SIZE_MAX;
10304 dns_db_currentversion(db, &ver);
10305 result = dns_db_getsize(db, ver, NULL, &dbsize);
10306 dns_db_closeversion(db, &ver, ISC_FALSE);
10307 if (result != ISC_R_SUCCESS) {
10308 dns_zone_log(zone, ISC_LOG_ERROR,
10309 "zone_journal_compact: "
10310 "could not get zone size: %s",
10311 isc_result_totext(result));
10312 } else if (dbsize < DNS_JOURNAL_SIZE_MAX / 2) {
10313 journalsize = (isc_int32_t)dbsize * 2;
10314 }
10315 }
10316 zone_debuglog(zone, "zone_journal_compact", 1,
10317 "target journal size %d", journalsize);
10318 result = dns_journal_compact(zone->mctx, zone->journal,
10319 serial, journalsize);
10320 switch (result) {
10321 case ISC_R_SUCCESS:
10322 case ISC_R_NOSPACE:
10323 case ISC_R_NOTFOUND:
10324 dns_zone_log(zone, ISC_LOG_DEBUG(3),
10325 "dns_journal_compact: %s",
10326 dns_result_totext(result));
10327 break;
10328 default:
10329 dns_zone_log(zone, ISC_LOG_ERROR,
10330 "dns_journal_compact failed: %s",
10331 dns_result_totext(result));
10332 break;
10333 }
10334 }
10335
10336 isc_result_t
10337 dns_zone_flush(dns_zone_t *zone) {
10338 isc_result_t result = ISC_R_SUCCESS;
10339 isc_boolean_t dumping;
10340
10341 REQUIRE(DNS_ZONE_VALID(zone));
10342
10343 LOCK_ZONE(zone);
10344 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH);
10345 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10346 zone->masterfile != NULL) {
10347 result = ISC_R_ALREADYRUNNING;
10348 dumping = was_dumping(zone);
10349 } else
10350 dumping = ISC_TRUE;
10351 UNLOCK_ZONE(zone);
10352 if (!dumping)
10353 result = zone_dump(zone, ISC_TRUE); /* Unknown task. */
10354 return (result);
10355 }
10356
10357 isc_result_t
10358 dns_zone_dump(dns_zone_t *zone) {
10359 isc_result_t result = ISC_R_ALREADYRUNNING;
10360 isc_boolean_t dumping;
10361
10362 REQUIRE(DNS_ZONE_VALID(zone));
10363
10364 LOCK_ZONE(zone);
10365 dumping = was_dumping(zone);
10366 UNLOCK_ZONE(zone);
10367 if (!dumping)
10368 result = zone_dump(zone, ISC_FALSE); /* Unknown task. */
10369 return (result);
10370 }
10371
10372 static void
10373 zone_needdump(dns_zone_t *zone, unsigned int delay) {
10374 const char me[] = "zone_needdump";
10375 isc_time_t dumptime;
10376 isc_time_t now;
10377
10378 /*
10379 * 'zone' locked by caller
10380 */
10381
10382 REQUIRE(DNS_ZONE_VALID(zone));
10383 REQUIRE(LOCKED_ZONE(zone));
10384 ENTER;
10385
10386 /*
10387 * Do we have a place to dump to and are we loaded?
10388 */
10389 if (zone->masterfile == NULL ||
10390 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
10391 return;
10392
10393 TIME_NOW(&now);
10394 /* add some noise */
10395 DNS_ZONE_JITTER_ADD(&now, delay, &dumptime);
10396
10397 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10398 if (isc_time_isepoch(&zone->dumptime) ||
10399 isc_time_compare(&zone->dumptime, &dumptime) > 0)
10400 zone->dumptime = dumptime;
10401 if (zone->task != NULL)
10402 zone_settimer(zone, &now);
10403 }
10404
10405 static void
10406 dump_done(void *arg, isc_result_t result) {
10407 const char me[] = "dump_done";
10408 dns_zone_t *zone = arg;
10409 dns_zone_t *secure = NULL;
10410 dns_db_t *db;
10411 dns_dbversion_t *version;
10412 isc_boolean_t again = ISC_FALSE;
10413 isc_boolean_t compact = ISC_FALSE;
10414 isc_uint32_t serial;
10415 isc_result_t tresult;
10416
10417 REQUIRE(DNS_ZONE_VALID(zone));
10418
10419 ENTER;
10420
10421 if (result == ISC_R_SUCCESS && zone->journal != NULL) {
10422 /*
10423 * We don't own these, zone->dctx must stay valid.
10424 */
10425 db = dns_dumpctx_db(zone->dctx);
10426 version = dns_dumpctx_version(zone->dctx);
10427 tresult = dns_db_getsoaserial(db, version, &serial);
10428
10429 /*
10430 * Handle lock order inversion.
10431 */
10432 again:
10433 LOCK_ZONE(zone);
10434 if (inline_raw(zone)) {
10435 secure = zone->secure;
10436 INSIST(secure != zone);
10437 TRYLOCK_ZONE(result, secure);
10438 if (result != ISC_R_SUCCESS) {
10439 UNLOCK_ZONE(zone);
10440 secure = NULL;
10441 #if ISC_PLATFORM_USETHREADS
10442 isc_thread_yield();
10443 #endif
10444 goto again;
10445 }
10446 }
10447
10448 /*
10449 * If there is a secure version of this zone
10450 * use its serial if it is less than ours.
10451 */
10452 if (tresult == ISC_R_SUCCESS && secure != NULL) {
10453 isc_uint32_t sserial;
10454 isc_result_t mresult;
10455
10456 ZONEDB_LOCK(&secure->dblock, isc_rwlocktype_read);
10457 if (secure->db != NULL) {
10458 mresult = dns_db_getsoaserial(zone->secure->db,
10459 NULL, &sserial);
10460 if (mresult == ISC_R_SUCCESS &&
10461 isc_serial_lt(sserial, serial))
10462 serial = sserial;
10463 }
10464 ZONEDB_UNLOCK(&secure->dblock, isc_rwlocktype_read);
10465 }
10466 if (tresult == ISC_R_SUCCESS && zone->xfr == NULL) {
10467 dns_db_t *zdb = NULL;
10468 if (dns_zone_getdb(zone, &zdb) == ISC_R_SUCCESS) {
10469 zone_journal_compact(zone, zdb, serial);
10470 dns_db_detach(&zdb);
10471 }
10472 } else if (tresult == ISC_R_SUCCESS) {
10473 compact = ISC_TRUE;
10474 zone->compact_serial = serial;
10475 }
10476 if (secure != NULL)
10477 UNLOCK_ZONE(secure);
10478 UNLOCK_ZONE(zone);
10479 }
10480
10481 LOCK_ZONE(zone);
10482 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
10483 if (compact)
10484 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
10485 if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) {
10486 /*
10487 * Try again in a short while.
10488 */
10489 zone_needdump(zone, DNS_DUMP_DELAY);
10490 } else if (result == ISC_R_SUCCESS &&
10491 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
10492 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10493 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10494 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10495 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
10496 isc_time_settoepoch(&zone->dumptime);
10497 again = ISC_TRUE;
10498 } else if (result == ISC_R_SUCCESS)
10499 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
10500
10501 if (zone->dctx != NULL)
10502 dns_dumpctx_detach(&zone->dctx);
10503 zonemgr_putio(&zone->writeio);
10504 UNLOCK_ZONE(zone);
10505 if (again)
10506 (void)zone_dump(zone, ISC_FALSE);
10507 dns_zone_idetach(&zone);
10508 }
10509
10510 static isc_result_t
10511 zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
10512 const char me[] = "zone_dump";
10513 isc_result_t result;
10514 dns_dbversion_t *version = NULL;
10515 isc_boolean_t again;
10516 dns_db_t *db = NULL;
10517 char *masterfile = NULL;
10518 dns_masterformat_t masterformat = dns_masterformat_none;
10519
10520 /*
10521 * 'compact' MUST only be set if we are task locked.
10522 */
10523
10524 REQUIRE(DNS_ZONE_VALID(zone));
10525 ENTER;
10526
10527 redo:
10528 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10529 if (zone->db != NULL)
10530 dns_db_attach(zone->db, &db);
10531 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10532 LOCK_ZONE(zone);
10533 if (zone->masterfile != NULL) {
10534 masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
10535 masterformat = zone->masterformat;
10536 }
10537 UNLOCK_ZONE(zone);
10538 if (db == NULL) {
10539 result = DNS_R_NOTLOADED;
10540 goto fail;
10541 }
10542 if (masterfile == NULL) {
10543 result = DNS_R_NOMASTERFILE;
10544 goto fail;
10545 }
10546
10547 if (compact && zone->type != dns_zone_stub) {
10548 dns_zone_t *dummy = NULL;
10549 LOCK_ZONE(zone);
10550 zone_iattach(zone, &dummy);
10551 result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task,
10552 zone_gotwritehandle, zone,
10553 &zone->writeio);
10554 if (result != ISC_R_SUCCESS)
10555 zone_idetach(&dummy);
10556 else
10557 result = DNS_R_CONTINUE;
10558 UNLOCK_ZONE(zone);
10559 } else {
10560 const dns_master_style_t *output_style;
10561
10562 dns_masterrawheader_t rawdata;
10563 dns_db_currentversion(db, &version);
10564 dns_master_initrawheader(&rawdata);
10565 if (inline_secure(zone))
10566 get_raw_serial(zone->raw, &rawdata);
10567 if (zone->type == dns_zone_key)
10568 output_style = &dns_master_style_keyzone;
10569 else
10570 output_style = &dns_master_style_default;
10571 result = dns_master_dump3(zone->mctx, db, version,
10572 output_style, masterfile,
10573 masterformat, &rawdata);
10574 dns_db_closeversion(db, &version, ISC_FALSE);
10575 }
10576 fail:
10577 if (db != NULL)
10578 dns_db_detach(&db);
10579 if (masterfile != NULL)
10580 isc_mem_free(zone->mctx, masterfile);
10581 masterfile = NULL;
10582
10583 if (result == DNS_R_CONTINUE)
10584 return (ISC_R_SUCCESS); /* XXXMPA */
10585
10586 again = ISC_FALSE;
10587 LOCK_ZONE(zone);
10588 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING);
10589 if (result != ISC_R_SUCCESS) {
10590 /*
10591 * Try again in a short while.
10592 */
10593 zone_needdump(zone, DNS_DUMP_DELAY);
10594 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) &&
10595 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
10596 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
10597 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10598 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING);
10599 isc_time_settoepoch(&zone->dumptime);
10600 again = ISC_TRUE;
10601 } else
10602 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH);
10603 UNLOCK_ZONE(zone);
10604 if (again)
10605 goto redo;
10606
10607 return (result);
10608 }
10609
10610 static isc_result_t
10611 dumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style,
10612 dns_masterformat_t format, const isc_uint32_t rawversion)
10613 {
10614 isc_result_t result;
10615 dns_dbversion_t *version = NULL;
10616 dns_db_t *db = NULL;
10617 dns_masterrawheader_t rawdata;
10618
10619 REQUIRE(DNS_ZONE_VALID(zone));
10620
10621 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
10622 if (zone->db != NULL)
10623 dns_db_attach(zone->db, &db);
10624 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
10625 if (db == NULL)
10626 return (DNS_R_NOTLOADED);
10627
10628 dns_db_currentversion(db, &version);
10629 dns_master_initrawheader(&rawdata);
10630 if (rawversion == 0)
10631 rawdata.flags |= DNS_MASTERRAW_COMPAT;
10632 else if (inline_secure(zone))
10633 get_raw_serial(zone->raw, &rawdata);
10634 else if (zone->sourceserialset) {
10635 rawdata.flags = DNS_MASTERRAW_SOURCESERIALSET;
10636 rawdata.sourceserial = zone->sourceserial;
10637 }
10638 result = dns_master_dumptostream3(zone->mctx, db, version, style,
10639 format, &rawdata, fd);
10640 dns_db_closeversion(db, &version, ISC_FALSE);
10641 dns_db_detach(&db);
10642 return (result);
10643 }
10644
10645 isc_result_t
10646 dns_zone_dumptostream3(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
10647 const dns_master_style_t *style,
10648 const isc_uint32_t rawversion)
10649 {
10650 return (dumptostream(zone, fd, style, format, rawversion));
10651 }
10652
10653 isc_result_t
10654 dns_zone_dumptostream2(dns_zone_t *zone, FILE *fd, dns_masterformat_t format,
10655 const dns_master_style_t *style) {
10656 return (dumptostream(zone, fd, style, format, DNS_RAWFORMAT_VERSION));
10657 }
10658
10659 isc_result_t
10660 dns_zone_dumptostream(dns_zone_t *zone, FILE *fd) {
10661 return (dumptostream(zone, fd, &dns_master_style_default,
10662 dns_masterformat_text, 0));
10663 }
10664
10665 isc_result_t
10666 dns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) {
10667 return (dumptostream(zone, fd, &dns_master_style_full,
10668 dns_masterformat_text, 0));
10669 }
10670
10671 void
10672 dns_zone_unload(dns_zone_t *zone) {
10673 REQUIRE(DNS_ZONE_VALID(zone));
10674
10675 LOCK_ZONE(zone);
10676 zone_unload(zone);
10677 UNLOCK_ZONE(zone);
10678 }
10679
10680 static void
10681 notify_cancel(dns_zone_t *zone) {
10682 dns_notify_t *notify;
10683
10684 /*
10685 * 'zone' locked by caller.
10686 */
10687
10688 REQUIRE(LOCKED_ZONE(zone));
10689
10690 for (notify = ISC_LIST_HEAD(zone->notifies);
10691 notify != NULL;
10692 notify = ISC_LIST_NEXT(notify, link)) {
10693 if (notify->find != NULL)
10694 dns_adb_cancelfind(notify->find);
10695 if (notify->request != NULL)
10696 dns_request_cancel(notify->request);
10697 }
10698 }
10699
10700 static void
10701 forward_cancel(dns_zone_t *zone) {
10702 dns_forward_t *forward;
10703
10704 /*
10705 * 'zone' locked by caller.
10706 */
10707
10708 REQUIRE(LOCKED_ZONE(zone));
10709
10710 for (forward = ISC_LIST_HEAD(zone->forwards);
10711 forward != NULL;
10712 forward = ISC_LIST_NEXT(forward, link)) {
10713 if (forward->request != NULL)
10714 dns_request_cancel(forward->request);
10715 }
10716 }
10717
10718 static void
10719 zone_unload(dns_zone_t *zone) {
10720 /*
10721 * 'zone' locked by caller.
10722 */
10723
10724 REQUIRE(LOCKED_ZONE(zone));
10725
10726 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
10727 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
10728 if (zone->writeio != NULL)
10729 zonemgr_cancelio(zone->writeio);
10730
10731 if (zone->dctx != NULL)
10732 dns_dumpctx_cancel(zone->dctx);
10733 }
10734 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
10735 zone_detachdb(zone);
10736 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
10737 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);
10738 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP);
10739 }
10740
10741 void
10742 dns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
10743 REQUIRE(DNS_ZONE_VALID(zone));
10744 REQUIRE(val > 0);
10745
10746 zone->minrefresh = val;
10747 }
10748
10749 void
10750 dns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) {
10751 REQUIRE(DNS_ZONE_VALID(zone));
10752 REQUIRE(val > 0);
10753
10754 zone->maxrefresh = val;
10755 }
10756
10757 void
10758 dns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) {
10759 REQUIRE(DNS_ZONE_VALID(zone));
10760 REQUIRE(val > 0);
10761
10762 zone->minretry = val;
10763 }
10764
10765 void
10766 dns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) {
10767 REQUIRE(DNS_ZONE_VALID(zone));
10768 REQUIRE(val > 0);
10769
10770 zone->maxretry = val;
10771 }
10772
10773 isc_uint32_t
10774 dns_zone_getmaxrecords(dns_zone_t *zone) {
10775 REQUIRE(DNS_ZONE_VALID(zone));
10776
10777 return (zone->maxrecords);
10778 }
10779
10780 void
10781 dns_zone_setmaxrecords(dns_zone_t *zone, isc_uint32_t val) {
10782 REQUIRE(DNS_ZONE_VALID(zone));
10783
10784 zone->maxrecords = val;
10785 }
10786
10787 static isc_boolean_t
10788 notify_isqueued(dns_zone_t *zone, unsigned int flags, dns_name_t *name,
10789 isc_sockaddr_t *addr, dns_tsigkey_t *key)
10790 {
10791 dns_notify_t *notify;
10792 dns_zonemgr_t *zmgr;
10793 isc_result_t result;
10794
10795 for (notify = ISC_LIST_HEAD(zone->notifies);
10796 notify != NULL;
10797 notify = ISC_LIST_NEXT(notify, link)) {
10798 if (notify->request != NULL)
10799 continue;
10800 if (name != NULL && dns_name_dynamic(¬ify->ns) &&
10801 dns_name_equal(name, ¬ify->ns))
10802 goto requeue;
10803 if (addr != NULL && isc_sockaddr_equal(addr, ¬ify->dst) &&
10804 notify->key == key)
10805 goto requeue;
10806 }
10807 return (ISC_FALSE);
10808
10809 requeue:
10810 /*
10811 * If we are enqueued on the startup ratelimiter and this is
10812 * not a startup notify, re-enqueue on the normal notify
10813 * ratelimiter.
10814 */
10815 if (notify->event != NULL && (flags & DNS_NOTIFY_STARTUP) == 0 &&
10816 (notify->flags & DNS_NOTIFY_STARTUP) != 0) {
10817 zmgr = notify->zone->zmgr;
10818 result = isc_ratelimiter_dequeue(zmgr->startupnotifyrl,
10819 notify->event);
10820 if (result != ISC_R_SUCCESS)
10821 return (ISC_TRUE);
10822
10823 notify->flags &= ~DNS_NOTIFY_STARTUP;
10824 result = isc_ratelimiter_enqueue(notify->zone->zmgr->notifyrl,
10825 notify->zone->task,
10826 ¬ify->event);
10827 if (result != ISC_R_SUCCESS) {
10828 isc_event_free(¬ify->event);
10829 return (ISC_FALSE);
10830 }
10831 }
10832
10833 return (ISC_TRUE);
10834 }
10835
10836 static isc_boolean_t
10837 notify_isself(dns_zone_t *zone, isc_sockaddr_t *dst) {
10838 dns_tsigkey_t *key = NULL;
10839 isc_sockaddr_t src;
10840 isc_sockaddr_t any;
10841 isc_boolean_t isself;
10842 isc_netaddr_t dstaddr;
10843 isc_result_t result;
10844
10845 if (zone->view == NULL || zone->isself == NULL)
10846 return (ISC_FALSE);
10847
10848 switch (isc_sockaddr_pf(dst)) {
10849 case PF_INET:
10850 src = zone->notifysrc4;
10851 isc_sockaddr_any(&any);
10852 break;
10853 case PF_INET6:
10854 src = zone->notifysrc6;
10855 isc_sockaddr_any6(&any);
10856 break;
10857 default:
10858 return (ISC_FALSE);
10859 }
10860
10861 /*
10862 * When sending from any the kernel will assign a source address
10863 * that matches the destination address.
10864 */
10865 if (isc_sockaddr_eqaddr(&any, &src))
10866 src = *dst;
10867
10868 isc_netaddr_fromsockaddr(&dstaddr, dst);
10869 result = dns_view_getpeertsig(zone->view, &dstaddr, &key);
10870 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
10871 return (ISC_FALSE);
10872 isself = (zone->isself)(zone->view, key, &src, dst, zone->rdclass,
10873 zone->isselfarg);
10874 if (key != NULL)
10875 dns_tsigkey_detach(&key);
10876 return (isself);
10877 }
10878
10879 static void
10880 notify_destroy(dns_notify_t *notify, isc_boolean_t locked) {
10881 isc_mem_t *mctx;
10882
10883 REQUIRE(DNS_NOTIFY_VALID(notify));
10884
10885 if (notify->zone != NULL) {
10886 if (!locked)
10887 LOCK_ZONE(notify->zone);
10888 REQUIRE(LOCKED_ZONE(notify->zone));
10889 if (ISC_LINK_LINKED(notify, link))
10890 ISC_LIST_UNLINK(notify->zone->notifies, notify, link);
10891 if (!locked)
10892 UNLOCK_ZONE(notify->zone);
10893 if (locked)
10894 zone_idetach(¬ify->zone);
10895 else
10896 dns_zone_idetach(¬ify->zone);
10897 }
10898 if (notify->find != NULL)
10899 dns_adb_destroyfind(¬ify->find);
10900 if (notify->request != NULL)
10901 dns_request_destroy(¬ify->request);
10902 if (dns_name_dynamic(¬ify->ns))
10903 dns_name_free(¬ify->ns, notify->mctx);
10904 if (notify->key != NULL)
10905 dns_tsigkey_detach(¬ify->key);
10906 mctx = notify->mctx;
10907 isc_mem_put(notify->mctx, notify, sizeof(*notify));
10908 isc_mem_detach(&mctx);
10909 }
10910
10911 static isc_result_t
10912 notify_create(isc_mem_t *mctx, unsigned int flags, dns_notify_t **notifyp) {
10913 dns_notify_t *notify;
10914
10915 REQUIRE(notifyp != NULL && *notifyp == NULL);
10916
10917 notify = isc_mem_get(mctx, sizeof(*notify));
10918 if (notify == NULL)
10919 return (ISC_R_NOMEMORY);
10920
10921 notify->mctx = NULL;
10922 isc_mem_attach(mctx, ¬ify->mctx);
10923 notify->flags = flags;
10924 notify->zone = NULL;
10925 notify->find = NULL;
10926 notify->request = NULL;
10927 notify->key = NULL;
10928 notify->event = NULL;
10929 isc_sockaddr_any(¬ify->dst);
10930 dns_name_init(¬ify->ns, NULL);
10931 ISC_LINK_INIT(notify, link);
10932 notify->magic = NOTIFY_MAGIC;
10933 *notifyp = notify;
10934 return (ISC_R_SUCCESS);
10935 }
10936
10937 /*
10938 * XXXAG should check for DNS_ZONEFLG_EXITING
10939 */
10940 static void
10941 process_adb_event(isc_task_t *task, isc_event_t *ev) {
10942 dns_notify_t *notify;
10943 isc_eventtype_t result;
10944
10945 UNUSED(task);
10946
10947 notify = ev->ev_arg;
10948 REQUIRE(DNS_NOTIFY_VALID(notify));
10949 INSIST(task == notify->zone->task);
10950 result = ev->ev_type;
10951 isc_event_free(&ev);
10952 if (result == DNS_EVENT_ADBMOREADDRESSES) {
10953 dns_adb_destroyfind(¬ify->find);
10954 notify_find_address(notify);
10955 return;
10956 }
10957 if (result == DNS_EVENT_ADBNOMOREADDRESSES) {
10958 LOCK_ZONE(notify->zone);
10959 notify_send(notify);
10960 UNLOCK_ZONE(notify->zone);
10961 }
10962 notify_destroy(notify, ISC_FALSE);
10963 }
10964
10965 static void
10966 notify_find_address(dns_notify_t *notify) {
10967 isc_result_t result;
10968 unsigned int options;
10969
10970 REQUIRE(DNS_NOTIFY_VALID(notify));
10971 options = DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_INET |
10972 DNS_ADBFIND_INET6 | DNS_ADBFIND_RETURNLAME;
10973
10974 if (notify->zone->view->adb == NULL)
10975 goto destroy;
10976
10977 result = dns_adb_createfind(notify->zone->view->adb,
10978 notify->zone->task,
10979 process_adb_event, notify,
10980 ¬ify->ns, dns_rootname, 0,
10981 options, 0, NULL,
10982 notify->zone->view->dstport,
10983 ¬ify->find);
10984
10985 /* Something failed? */
10986 if (result != ISC_R_SUCCESS)
10987 goto destroy;
10988
10989 /* More addresses pending? */
10990 if ((notify->find->options & DNS_ADBFIND_WANTEVENT) != 0)
10991 return;
10992
10993 /* We have as many addresses as we can get. */
10994 LOCK_ZONE(notify->zone);
10995 notify_send(notify);
10996 UNLOCK_ZONE(notify->zone);
10997
10998 destroy:
10999 notify_destroy(notify, ISC_FALSE);
11000 }
11001
11002
11003 static isc_result_t
11004 notify_send_queue(dns_notify_t *notify, isc_boolean_t startup) {
11005 isc_event_t *e;
11006 isc_result_t result;
11007
11008 INSIST(notify->event == NULL);
11009 e = isc_event_allocate(notify->mctx, NULL, DNS_EVENT_NOTIFYSENDTOADDR,
11010 notify_send_toaddr, notify, sizeof(isc_event_t));
11011 if (e == NULL)
11012 return (ISC_R_NOMEMORY);
11013 if (startup)
11014 notify->event = e;
11015 e->ev_arg = notify;
11016 e->ev_sender = NULL;
11017 result = isc_ratelimiter_enqueue(startup
11018 ? notify->zone->zmgr->startupnotifyrl
11019 : notify->zone->zmgr->notifyrl,
11020 notify->zone->task, &e);
11021 if (result != ISC_R_SUCCESS) {
11022 isc_event_free(&e);
11023 notify->event = NULL;
11024 }
11025 return (result);
11026 }
11027
11028 static void
11029 notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
11030 dns_notify_t *notify;
11031 isc_result_t result;
11032 dns_message_t *message = NULL;
11033 isc_netaddr_t dstip;
11034 dns_tsigkey_t *key = NULL;
11035 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
11036 isc_sockaddr_t src;
11037 unsigned int options, timeout;
11038 isc_boolean_t have_notifysource = ISC_FALSE;
11039 isc_boolean_t have_notifydscp = ISC_FALSE;
11040 isc_dscp_t dscp = -1;
11041
11042 notify = event->ev_arg;
11043 REQUIRE(DNS_NOTIFY_VALID(notify));
11044
11045 UNUSED(task);
11046
11047 LOCK_ZONE(notify->zone);
11048
11049 notify->event = NULL;
11050
11051 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_LOADED) == 0) {
11052 result = ISC_R_CANCELED;
11053 goto cleanup;
11054 }
11055
11056 if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0 ||
11057 DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING) ||
11058 notify->zone->view->requestmgr == NULL ||
11059 notify->zone->db == NULL) {
11060 result = ISC_R_CANCELED;
11061 goto cleanup;
11062 }
11063
11064 /*
11065 * The raw IPv4 address should also exist. Don't send to the
11066 * mapped form.
11067 */
11068 if (isc_sockaddr_pf(¬ify->dst) == PF_INET6 &&
11069 IN6_IS_ADDR_V4MAPPED(¬ify->dst.type.sin6.sin6_addr)) {
11070 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
11071 notify_log(notify->zone, ISC_LOG_DEBUG(3),
11072 "notify: ignoring IPv6 mapped IPV4 address: %s",
11073 addrbuf);
11074 result = ISC_R_CANCELED;
11075 goto cleanup;
11076 }
11077
11078 result = notify_createmessage(notify->zone, notify->flags, &message);
11079 if (result != ISC_R_SUCCESS)
11080 goto cleanup;
11081
11082 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
11083 if (notify->key != NULL) {
11084 /* Transfer ownership of key */
11085 key = notify->key;
11086 notify->key = NULL;
11087 } else {
11088 isc_netaddr_fromsockaddr(&dstip, ¬ify->dst);
11089 result = dns_view_getpeertsig(notify->zone->view, &dstip, &key);
11090 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
11091 notify_log(notify->zone, ISC_LOG_ERROR,
11092 "NOTIFY to %s not sent. "
11093 "Peer TSIG key lookup failure.", addrbuf);
11094 goto cleanup_message;
11095 }
11096 }
11097
11098 /* XXX: should we log the tsig key too? */
11099 notify_log(notify->zone, ISC_LOG_DEBUG(3), "sending notify to %s",
11100 addrbuf);
11101 options = 0;
11102 if (notify->zone->view->peers != NULL) {
11103 dns_peer_t *peer = NULL;
11104 isc_boolean_t usetcp = ISC_FALSE;
11105 result = dns_peerlist_peerbyaddr(notify->zone->view->peers,
11106 &dstip, &peer);
11107 if (result == ISC_R_SUCCESS) {
11108 result = dns_peer_getnotifysource(peer, &src);
11109 if (result == ISC_R_SUCCESS)
11110 have_notifysource = ISC_TRUE;
11111 dns_peer_getnotifydscp(peer, &dscp);
11112 if (dscp != -1)
11113 have_notifydscp = ISC_TRUE;
11114 result = dns_peer_getforcetcp(peer, &usetcp);
11115 if (result == ISC_R_SUCCESS && usetcp)
11116 options |= DNS_FETCHOPT_TCP;
11117 }
11118 }
11119 switch (isc_sockaddr_pf(¬ify->dst)) {
11120 case PF_INET:
11121 if (!have_notifysource)
11122 src = notify->zone->notifysrc4;
11123 if (!have_notifydscp)
11124 dscp = notify->zone->notifysrc4dscp;
11125 break;
11126 case PF_INET6:
11127 if (!have_notifysource)
11128 src = notify->zone->notifysrc6;
11129 if (!have_notifydscp)
11130 dscp = notify->zone->notifysrc6dscp;
11131 break;
11132 default:
11133 result = ISC_R_NOTIMPLEMENTED;
11134 goto cleanup_key;
11135 }
11136 timeout = 15;
11137 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_DIALNOTIFY))
11138 timeout = 30;
11139 result = dns_request_createvia4(notify->zone->view->requestmgr,
11140 message, &src, ¬ify->dst, dscp,
11141 options, key, timeout * 3, timeout,
11142 0, notify->zone->task, notify_done,
11143 notify, ¬ify->request);
11144 if (result == ISC_R_SUCCESS) {
11145 if (isc_sockaddr_pf(¬ify->dst) == AF_INET) {
11146 inc_stats(notify->zone,
11147 dns_zonestatscounter_notifyoutv4);
11148 } else {
11149 inc_stats(notify->zone,
11150 dns_zonestatscounter_notifyoutv6);
11151 }
11152 }
11153
11154 cleanup_key:
11155 if (key != NULL)
11156 dns_tsigkey_detach(&key);
11157 cleanup_message:
11158 dns_message_destroy(&message);
11159 cleanup:
11160 UNLOCK_ZONE(notify->zone);
11161 isc_event_free(&event);
11162 if (result != ISC_R_SUCCESS)
11163 notify_destroy(notify, ISC_FALSE);
11164 }
11165
11166 static void
11167 notify_send(dns_notify_t *notify) {
11168 dns_adbaddrinfo_t *ai;
11169 isc_sockaddr_t dst;
11170 isc_result_t result;
11171 dns_notify_t *newnotify = NULL;
11172 unsigned int flags;
11173 isc_boolean_t startup;
11174
11175 /*
11176 * Zone lock held by caller.
11177 */
11178 REQUIRE(DNS_NOTIFY_VALID(notify));
11179 REQUIRE(LOCKED_ZONE(notify->zone));
11180
11181 if (DNS_ZONE_FLAG(notify->zone, DNS_ZONEFLG_EXITING))
11182 return;
11183
11184 for (ai = ISC_LIST_HEAD(notify->find->list);
11185 ai != NULL;
11186 ai = ISC_LIST_NEXT(ai, publink)) {
11187 dst = ai->sockaddr;
11188 if (notify_isqueued(notify->zone, notify->flags, NULL, &dst,
11189 NULL))
11190 continue;
11191 if (notify_isself(notify->zone, &dst))
11192 continue;
11193 newnotify = NULL;
11194 flags = notify->flags & DNS_NOTIFY_NOSOA;
11195 result = notify_create(notify->mctx, flags, &newnotify);
11196 if (result != ISC_R_SUCCESS)
11197 goto cleanup;
11198 zone_iattach(notify->zone, &newnotify->zone);
11199 ISC_LIST_APPEND(newnotify->zone->notifies, newnotify, link);
11200 newnotify->dst = dst;
11201 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
11202 result = notify_send_queue(newnotify, startup);
11203 if (result != ISC_R_SUCCESS)
11204 goto cleanup;
11205 newnotify = NULL;
11206 }
11207
11208 cleanup:
11209 if (newnotify != NULL)
11210 notify_destroy(newnotify, ISC_TRUE);
11211 }
11212
11213 void
11214 dns_zone_notify(dns_zone_t *zone) {
11215 isc_time_t now;
11216
11217 REQUIRE(DNS_ZONE_VALID(zone));
11218
11219 LOCK_ZONE(zone);
11220 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11221
11222 TIME_NOW(&now);
11223 zone_settimer(zone, &now);
11224 UNLOCK_ZONE(zone);
11225 }
11226
11227 static void
11228 zone_notify(dns_zone_t *zone, isc_time_t *now) {
11229 dns_dbnode_t *node = NULL;
11230 dns_db_t *zonedb = NULL;
11231 dns_dbversion_t *version = NULL;
11232 dns_name_t *origin = NULL;
11233 dns_name_t master;
11234 dns_rdata_ns_t ns;
11235 dns_rdata_soa_t soa;
11236 isc_uint32_t serial;
11237 dns_rdata_t rdata = DNS_RDATA_INIT;
11238 dns_rdataset_t nsrdset;
11239 dns_rdataset_t soardset;
11240 isc_result_t result;
11241 unsigned int i;
11242 isc_sockaddr_t dst;
11243 isc_boolean_t isqueued;
11244 dns_notifytype_t notifytype;
11245 unsigned int flags = 0;
11246 isc_boolean_t loggednotify = ISC_FALSE;
11247 isc_boolean_t startup;
11248
11249 REQUIRE(DNS_ZONE_VALID(zone));
11250
11251 LOCK_ZONE(zone);
11252 startup = !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11253 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
11254 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY);
11255 notifytype = zone->notifytype;
11256 DNS_ZONE_TIME_ADD(now, zone->notifydelay, &zone->notifytime);
11257 UNLOCK_ZONE(zone);
11258
11259 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
11260 ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED))
11261 return;
11262
11263 if (notifytype == dns_notifytype_no)
11264 return;
11265
11266 if (notifytype == dns_notifytype_masteronly &&
11267 zone->type != dns_zone_master)
11268 return;
11269
11270 origin = &zone->origin;
11271
11272 /*
11273 * If the zone is dialup we are done as we don't want to send
11274 * the current soa so as to force a refresh query.
11275 */
11276 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
11277 flags |= DNS_NOTIFY_NOSOA;
11278
11279 /*
11280 * Record that this was a notify due to starting up.
11281 */
11282 if (startup)
11283 flags |= DNS_NOTIFY_STARTUP;
11284
11285 /*
11286 * Get SOA RRset.
11287 */
11288 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
11289 if (zone->db != NULL)
11290 dns_db_attach(zone->db, &zonedb);
11291 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
11292 if (zonedb == NULL)
11293 return;
11294 dns_db_currentversion(zonedb, &version);
11295 result = dns_db_findnode(zonedb, origin, ISC_FALSE, &node);
11296 if (result != ISC_R_SUCCESS)
11297 goto cleanup1;
11298
11299 dns_rdataset_init(&soardset);
11300 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_soa,
11301 dns_rdatatype_none, 0, &soardset, NULL);
11302 if (result != ISC_R_SUCCESS)
11303 goto cleanup2;
11304
11305 /*
11306 * Find serial and master server's name.
11307 */
11308 dns_name_init(&master, NULL);
11309 result = dns_rdataset_first(&soardset);
11310 if (result != ISC_R_SUCCESS)
11311 goto cleanup3;
11312 dns_rdataset_current(&soardset, &rdata);
11313 result = dns_rdata_tostruct(&rdata, &soa, NULL);
11314 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11315 dns_rdata_reset(&rdata);
11316 result = dns_name_dup(&soa.origin, zone->mctx, &master);
11317 serial = soa.serial;
11318 dns_rdataset_disassociate(&soardset);
11319 if (result != ISC_R_SUCCESS)
11320 goto cleanup3;
11321
11322 /*
11323 * Enqueue notify requests for 'also-notify' servers.
11324 */
11325 LOCK_ZONE(zone);
11326 for (i = 0; i < zone->notifycnt; i++) {
11327 dns_tsigkey_t *key = NULL;
11328 dns_notify_t *notify = NULL;
11329
11330 if ((zone->notifykeynames != NULL) &&
11331 (zone->notifykeynames[i] != NULL)) {
11332 dns_view_t *view = dns_zone_getview(zone);
11333 dns_name_t *keyname = zone->notifykeynames[i];
11334 (void)dns_view_gettsig(view, keyname, &key);
11335 }
11336
11337 dst = zone->notify[i];
11338 if (notify_isqueued(zone, flags, NULL, &dst, key)) {
11339 if (key != NULL)
11340 dns_tsigkey_detach(&key);
11341 continue;
11342 }
11343
11344 result = notify_create(zone->mctx, flags, ¬ify);
11345 if (result != ISC_R_SUCCESS) {
11346 if (key != NULL)
11347 dns_tsigkey_detach(&key);
11348 continue;
11349 }
11350
11351 zone_iattach(zone, ¬ify->zone);
11352 notify->dst = dst;
11353
11354 INSIST(notify->key == NULL);
11355
11356 if (key != NULL) {
11357 notify->key = key;
11358 key = NULL;
11359 }
11360
11361 ISC_LIST_APPEND(zone->notifies, notify, link);
11362 result = notify_send_queue(notify, startup);
11363 if (result != ISC_R_SUCCESS)
11364 notify_destroy(notify, ISC_TRUE);
11365 if (!loggednotify) {
11366 notify_log(zone, ISC_LOG_INFO,
11367 "sending notifies (serial %u)",
11368 serial);
11369 loggednotify = ISC_TRUE;
11370 }
11371 }
11372 UNLOCK_ZONE(zone);
11373
11374 if (notifytype == dns_notifytype_explicit)
11375 goto cleanup3;
11376
11377 /*
11378 * Process NS RRset to generate notifies.
11379 */
11380
11381 dns_rdataset_init(&nsrdset);
11382 result = dns_db_findrdataset(zonedb, node, version, dns_rdatatype_ns,
11383 dns_rdatatype_none, 0, &nsrdset, NULL);
11384 if (result != ISC_R_SUCCESS)
11385 goto cleanup3;
11386
11387 result = dns_rdataset_first(&nsrdset);
11388 while (result == ISC_R_SUCCESS) {
11389 dns_notify_t *notify = NULL;
11390
11391 dns_rdataset_current(&nsrdset, &rdata);
11392 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11393 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11394 dns_rdata_reset(&rdata);
11395 /*
11396 * Don't notify the master server unless explicitly
11397 * configured to do so.
11398 */
11399 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOTIFYTOSOA) &&
11400 dns_name_compare(&master, &ns.name) == 0) {
11401 result = dns_rdataset_next(&nsrdset);
11402 continue;
11403 }
11404
11405 if (!loggednotify) {
11406 notify_log(zone, ISC_LOG_INFO,
11407 "sending notifies (serial %u)",
11408 serial);
11409 loggednotify = ISC_TRUE;
11410 }
11411
11412 LOCK_ZONE(zone);
11413 isqueued = notify_isqueued(zone, flags, &ns.name, NULL, NULL);
11414 UNLOCK_ZONE(zone);
11415 if (isqueued) {
11416 result = dns_rdataset_next(&nsrdset);
11417 continue;
11418 }
11419 result = notify_create(zone->mctx, flags, ¬ify);
11420 if (result != ISC_R_SUCCESS)
11421 continue;
11422 dns_zone_iattach(zone, ¬ify->zone);
11423 result = dns_name_dup(&ns.name, zone->mctx, ¬ify->ns);
11424 if (result != ISC_R_SUCCESS) {
11425 LOCK_ZONE(zone);
11426 notify_destroy(notify, ISC_TRUE);
11427 UNLOCK_ZONE(zone);
11428 continue;
11429 }
11430 LOCK_ZONE(zone);
11431 ISC_LIST_APPEND(zone->notifies, notify, link);
11432 UNLOCK_ZONE(zone);
11433 notify_find_address(notify);
11434 result = dns_rdataset_next(&nsrdset);
11435 }
11436 dns_rdataset_disassociate(&nsrdset);
11437
11438 cleanup3:
11439 if (dns_name_dynamic(&master))
11440 dns_name_free(&master, zone->mctx);
11441 cleanup2:
11442 dns_db_detachnode(zonedb, &node);
11443 cleanup1:
11444 dns_db_closeversion(zonedb, &version, ISC_FALSE);
11445 dns_db_detach(&zonedb);
11446 }
11447
11448 /***
11449 *** Private
11450 ***/
11451
11452 static inline isc_result_t
11453 save_nsrrset(dns_message_t *message, dns_name_t *name,
11454 dns_db_t *db, dns_dbversion_t *version)
11455 {
11456 dns_rdataset_t *nsrdataset = NULL;
11457 dns_rdataset_t *rdataset = NULL;
11458 dns_dbnode_t *node = NULL;
11459 dns_rdata_ns_t ns;
11460 isc_result_t result;
11461 dns_rdata_t rdata = DNS_RDATA_INIT;
11462
11463 /*
11464 * Extract NS RRset from message.
11465 */
11466 result = dns_message_findname(message, DNS_SECTION_ANSWER, name,
11467 dns_rdatatype_ns, dns_rdatatype_none,
11468 NULL, &nsrdataset);
11469 if (result != ISC_R_SUCCESS)
11470 goto fail;
11471
11472 /*
11473 * Add NS rdataset.
11474 */
11475 result = dns_db_findnode(db, name, ISC_TRUE, &node);
11476 if (result != ISC_R_SUCCESS)
11477 goto fail;
11478 result = dns_db_addrdataset(db, node, version, 0,
11479 nsrdataset, 0, NULL);
11480 dns_db_detachnode(db, &node);
11481 if (result != ISC_R_SUCCESS)
11482 goto fail;
11483 /*
11484 * Add glue rdatasets.
11485 */
11486 for (result = dns_rdataset_first(nsrdataset);
11487 result == ISC_R_SUCCESS;
11488 result = dns_rdataset_next(nsrdataset)) {
11489 dns_rdataset_current(nsrdataset, &rdata);
11490 result = dns_rdata_tostruct(&rdata, &ns, NULL);
11491 RUNTIME_CHECK(result == ISC_R_SUCCESS);
11492 dns_rdata_reset(&rdata);
11493 if (!dns_name_issubdomain(&ns.name, name))
11494 continue;
11495 rdataset = NULL;
11496 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11497 &ns.name, dns_rdatatype_aaaa,
11498 dns_rdatatype_none, NULL,
11499 &rdataset);
11500 if (result == ISC_R_SUCCESS) {
11501 result = dns_db_findnode(db, &ns.name,
11502 ISC_TRUE, &node);
11503 if (result != ISC_R_SUCCESS)
11504 goto fail;
11505 result = dns_db_addrdataset(db, node, version, 0,
11506 rdataset, 0, NULL);
11507 dns_db_detachnode(db, &node);
11508 if (result != ISC_R_SUCCESS)
11509 goto fail;
11510 }
11511 rdataset = NULL;
11512 result = dns_message_findname(message, DNS_SECTION_ADDITIONAL,
11513 &ns.name, dns_rdatatype_a,
11514 dns_rdatatype_none, NULL,
11515 &rdataset);
11516 if (result == ISC_R_SUCCESS) {
11517 result = dns_db_findnode(db, &ns.name,
11518 ISC_TRUE, &node);
11519 if (result != ISC_R_SUCCESS)
11520 goto fail;
11521 result = dns_db_addrdataset(db, node, version, 0,
11522 rdataset, 0, NULL);
11523 dns_db_detachnode(db, &node);
11524 if (result != ISC_R_SUCCESS)
11525 goto fail;
11526 }
11527 }
11528 if (result != ISC_R_NOMORE)
11529 goto fail;
11530
11531 return (ISC_R_SUCCESS);
11532
11533 fail:
11534 return (result);
11535 }
11536
11537 static void
11538 stub_callback(isc_task_t *task, isc_event_t *event) {
11539 const char me[] = "stub_callback";
11540 dns_requestevent_t *revent = (dns_requestevent_t *)event;
11541 dns_stub_t *stub = NULL;
11542 dns_message_t *msg = NULL;
11543 dns_zone_t *zone = NULL;
11544 char master[ISC_SOCKADDR_FORMATSIZE];
11545 char source[ISC_SOCKADDR_FORMATSIZE];
11546 isc_uint32_t nscnt, cnamecnt, refresh, retry, expire;
11547 isc_result_t result;
11548 isc_time_t now;
11549 isc_boolean_t exiting = ISC_FALSE;
11550 isc_interval_t i;
11551 unsigned int j, soacount;
11552
11553 stub = revent->ev_arg;
11554 INSIST(DNS_STUB_VALID(stub));
11555
11556 UNUSED(task);
11557
11558 zone = stub->zone;
11559
11560 ENTER;
11561
11562 TIME_NOW(&now);
11563
11564 LOCK_ZONE(zone);
11565
11566 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11567 zone_debuglog(zone, me, 1, "exiting");
11568 exiting = ISC_TRUE;
11569 goto next_master;
11570 }
11571
11572 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
11573 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
11574
11575 if (revent->result != ISC_R_SUCCESS) {
11576 if (revent->result == ISC_R_TIMEDOUT &&
11577 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11578 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11579 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11580 "refreshing stub: timeout retrying "
11581 " without EDNS master %s (source %s)",
11582 master, source);
11583 goto same_master;
11584 }
11585 dns_zonemgr_unreachableadd(zone->zmgr, &zone->masteraddr,
11586 &zone->sourceaddr, &now);
11587 dns_zone_log(zone, ISC_LOG_INFO,
11588 "could not refresh stub from master %s"
11589 " (source %s): %s", master, source,
11590 dns_result_totext(revent->result));
11591 goto next_master;
11592 }
11593
11594 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
11595 if (result != ISC_R_SUCCESS)
11596 goto next_master;
11597
11598 result = dns_request_getresponse(revent->request, msg, 0);
11599 if (result != ISC_R_SUCCESS)
11600 goto next_master;
11601
11602 /*
11603 * Unexpected rcode.
11604 */
11605 if (msg->rcode != dns_rcode_noerror) {
11606 char rcode[128];
11607 isc_buffer_t rb;
11608
11609 isc_buffer_init(&rb, rcode, sizeof(rcode));
11610 (void)dns_rcode_totext(msg->rcode, &rb);
11611
11612 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
11613 (msg->rcode == dns_rcode_servfail ||
11614 msg->rcode == dns_rcode_notimp ||
11615 msg->rcode == dns_rcode_formerr)) {
11616 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11617 "refreshing stub: rcode (%.*s) retrying "
11618 "without EDNS master %s (source %s)",
11619 (int)rb.used, rcode, master, source);
11620 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11621 goto same_master;
11622 }
11623
11624 dns_zone_log(zone, ISC_LOG_INFO,
11625 "refreshing stub: "
11626 "unexpected rcode (%.*s) from %s (source %s)",
11627 (int)rb.used, rcode, master, source);
11628 goto next_master;
11629 }
11630
11631 /*
11632 * We need complete messages.
11633 */
11634 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
11635 if (dns_request_usedtcp(revent->request)) {
11636 dns_zone_log(zone, ISC_LOG_INFO,
11637 "refreshing stub: truncated TCP "
11638 "response from master %s (source %s)",
11639 master, source);
11640 goto next_master;
11641 }
11642 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
11643 goto same_master;
11644 }
11645
11646 /*
11647 * If non-auth log and next master.
11648 */
11649 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
11650 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
11651 "non-authoritative answer from "
11652 "master %s (source %s)", master, source);
11653 goto next_master;
11654 }
11655
11656 /*
11657 * Sanity checks.
11658 */
11659 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
11660 nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
11661
11662 if (cnamecnt != 0) {
11663 dns_zone_log(zone, ISC_LOG_INFO,
11664 "refreshing stub: unexpected CNAME response "
11665 "from master %s (source %s)", master, source);
11666 goto next_master;
11667 }
11668
11669 if (nscnt == 0) {
11670 dns_zone_log(zone, ISC_LOG_INFO,
11671 "refreshing stub: no NS records in response "
11672 "from master %s (source %s)", master, source);
11673 goto next_master;
11674 }
11675
11676 /*
11677 * Save answer.
11678 */
11679 result = save_nsrrset(msg, &zone->origin, stub->db, stub->version);
11680 if (result != ISC_R_SUCCESS) {
11681 dns_zone_log(zone, ISC_LOG_INFO,
11682 "refreshing stub: unable to save NS records "
11683 "from master %s (source %s)", master, source);
11684 goto next_master;
11685 }
11686
11687 /*
11688 * Tidy up.
11689 */
11690 dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
11691 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
11692 if (zone->db == NULL)
11693 zone_attachdb(zone, stub->db);
11694 result = zone_get_from_db(zone, zone->db, NULL, &soacount, NULL,
11695 &refresh, &retry, &expire, NULL, NULL);
11696 if (result == ISC_R_SUCCESS && soacount > 0U) {
11697 zone->refresh = RANGE(refresh, zone->minrefresh,
11698 zone->maxrefresh);
11699 zone->retry = RANGE(retry, zone->minretry, zone->maxretry);
11700 zone->expire = RANGE(expire, zone->refresh + zone->retry,
11701 DNS_MAX_EXPIRE);
11702 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
11703 }
11704 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
11705 dns_db_detach(&stub->db);
11706
11707 dns_message_destroy(&msg);
11708 isc_event_free(&event);
11709 dns_request_destroy(&zone->request);
11710
11711 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11712 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
11713 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
11714 isc_interval_set(&i, zone->expire, 0);
11715 DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
11716
11717 if (zone->masterfile != NULL)
11718 zone_needdump(zone, 0);
11719
11720 zone_settimer(zone, &now);
11721 goto free_stub;
11722
11723 next_master:
11724 if (stub->version != NULL)
11725 dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
11726 if (stub->db != NULL)
11727 dns_db_detach(&stub->db);
11728 if (msg != NULL)
11729 dns_message_destroy(&msg);
11730 isc_event_free(&event);
11731 dns_request_destroy(&zone->request);
11732 /*
11733 * Skip to next failed / untried master.
11734 */
11735 do {
11736 zone->curmaster++;
11737 } while (zone->curmaster < zone->masterscnt &&
11738 zone->mastersok[zone->curmaster]);
11739 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
11740 if (exiting || zone->curmaster >= zone->masterscnt) {
11741 isc_boolean_t done = ISC_TRUE;
11742 if (!exiting &&
11743 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
11744 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
11745 /*
11746 * Did we get a good answer from all the masters?
11747 */
11748 for (j = 0; j < zone->masterscnt; j++)
11749 if (zone->mastersok[j] == ISC_FALSE) {
11750 done = ISC_FALSE;
11751 break;
11752 }
11753 } else
11754 done = ISC_TRUE;
11755 if (!done) {
11756 zone->curmaster = 0;
11757 /*
11758 * Find the next failed master.
11759 */
11760 while (zone->curmaster < zone->masterscnt &&
11761 zone->mastersok[zone->curmaster])
11762 zone->curmaster++;
11763 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
11764 } else {
11765 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
11766
11767 zone_settimer(zone, &now);
11768 goto free_stub;
11769 }
11770 }
11771 queue_soa_query(zone);
11772 goto free_stub;
11773
11774 same_master:
11775 if (msg != NULL)
11776 dns_message_destroy(&msg);
11777 isc_event_free(&event);
11778 dns_request_destroy(&zone->request);
11779 ns_query(zone, NULL, stub);
11780 UNLOCK_ZONE(zone);
11781 goto done;
11782
11783 free_stub:
11784 UNLOCK_ZONE(zone);
11785 stub->magic = 0;
11786 dns_zone_idetach(&stub->zone);
11787 INSIST(stub->db == NULL);
11788 INSIST(stub->version == NULL);
11789 isc_mem_put(stub->mctx, stub, sizeof(*stub));
11790
11791 done:
11792 INSIST(event == NULL);
11793 return;
11794 }
11795
11796 /*
11797 * Get the EDNS EXPIRE option from the response and if it exists trim
11798 * expire to be not more than it.
11799 */
11800 static void
11801 get_edns_expire(dns_zone_t * zone, dns_message_t *message,
11802 isc_uint32_t *expirep)
11803 {
11804 isc_result_t result;
11805 isc_uint32_t expire;
11806 dns_rdata_t rdata = DNS_RDATA_INIT;
11807 isc_buffer_t optbuf;
11808 isc_uint16_t optcode;
11809 isc_uint16_t optlen;
11810
11811 REQUIRE(expirep != NULL);
11812 REQUIRE(message != NULL);
11813
11814 if (message->opt == NULL)
11815 return;
11816
11817 result = dns_rdataset_first(message->opt);
11818 if (result == ISC_R_SUCCESS) {
11819 dns_rdataset_current(message->opt, &rdata);
11820 isc_buffer_init(&optbuf, rdata.data, rdata.length);
11821 isc_buffer_add(&optbuf, rdata.length);
11822 while (isc_buffer_remaininglength(&optbuf) >= 4) {
11823 optcode = isc_buffer_getuint16(&optbuf);
11824 optlen = isc_buffer_getuint16(&optbuf);
11825 /*
11826 * A EDNS EXPIRE response has a length of 4.
11827 */
11828 if (optcode != DNS_OPT_EXPIRE || optlen != 4) {
11829 isc_buffer_forward(&optbuf, optlen);
11830 continue;
11831 }
11832 expire = isc_buffer_getuint32(&optbuf);
11833 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11834 "got EDNS EXPIRE of %u", expire);
11835 /*
11836 * Trim *expirep?
11837 */
11838 if (expire < *expirep)
11839 *expirep = expire;
11840 break;
11841 }
11842 }
11843 }
11844
11845 /*
11846 * Set the file modification time zone->expire seconds before expiretime.
11847 */
11848 static void
11849 setmodtime(dns_zone_t *zone, isc_time_t *expiretime) {
11850 isc_result_t result;
11851 isc_time_t when;
11852 isc_interval_t i;
11853
11854 isc_interval_set(&i, zone->expire, 0);
11855 result = isc_time_subtract(expiretime, &i, &when);
11856 if (result != ISC_R_SUCCESS)
11857 return;
11858
11859 result = ISC_R_FAILURE;
11860 if (zone->journal != NULL)
11861 result = isc_file_settime(zone->journal, &when);
11862 if (result == ISC_R_SUCCESS &&
11863 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
11864 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP))
11865 result = isc_file_settime(zone->masterfile, &when);
11866 else if (result != ISC_R_SUCCESS)
11867 result = isc_file_settime(zone->masterfile, &when);
11868
11869 /*
11870 * Someone removed the file from underneath us!
11871 */
11872 if (result == ISC_R_FILENOTFOUND) {
11873 zone_needdump(zone, DNS_DUMP_DELAY);
11874 } else if (result != ISC_R_SUCCESS)
11875 dns_zone_log(zone, ISC_LOG_ERROR, "refresh: could not set "
11876 "file modification time of '%s': %s",
11877 zone->masterfile, dns_result_totext(result));
11878 }
11879
11880 /*
11881 * An SOA query has finished (successfully or not).
11882 */
11883 static void
11884 refresh_callback(isc_task_t *task, isc_event_t *event) {
11885 const char me[] = "refresh_callback";
11886 dns_requestevent_t *revent = (dns_requestevent_t *)event;
11887 dns_zone_t *zone;
11888 dns_message_t *msg = NULL;
11889 isc_uint32_t soacnt, cnamecnt, soacount, nscount;
11890 isc_time_t now;
11891 char master[ISC_SOCKADDR_FORMATSIZE];
11892 char source[ISC_SOCKADDR_FORMATSIZE];
11893 dns_rdataset_t *rdataset = NULL;
11894 dns_rdata_t rdata = DNS_RDATA_INIT;
11895 dns_rdata_soa_t soa;
11896 isc_result_t result;
11897 isc_uint32_t serial, oldserial = 0;
11898 unsigned int j;
11899 isc_boolean_t do_queue_xfrin = ISC_FALSE;
11900
11901 zone = revent->ev_arg;
11902 INSIST(DNS_ZONE_VALID(zone));
11903
11904 UNUSED(task);
11905
11906 ENTER;
11907
11908 TIME_NOW(&now);
11909
11910 LOCK_ZONE(zone);
11911
11912 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
11913 isc_event_free(&event);
11914 dns_request_destroy(&zone->request);
11915 goto detach;
11916 }
11917
11918 /*
11919 * if timeout log and next master;
11920 */
11921
11922 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
11923 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
11924
11925 if (revent->result != ISC_R_SUCCESS) {
11926 if (revent->result == ISC_R_TIMEDOUT &&
11927 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
11928 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11929 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11930 "refresh: timeout retrying without EDNS "
11931 "master %s (source %s)", master, source);
11932 goto same_master;
11933 }
11934 if (revent->result == ISC_R_TIMEDOUT &&
11935 !dns_request_usedtcp(revent->request)) {
11936 dns_zone_log(zone, ISC_LOG_INFO,
11937 "refresh: retry limit for "
11938 "master %s exceeded (source %s)",
11939 master, source);
11940 /* Try with slave with TCP. */
11941 if ((zone->type == dns_zone_slave ||
11942 zone->type == dns_zone_redirect) &&
11943 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
11944 if (!dns_zonemgr_unreachable(zone->zmgr,
11945 &zone->masteraddr,
11946 &zone->sourceaddr,
11947 &now))
11948 {
11949 DNS_ZONE_SETFLAG(zone,
11950 DNS_ZONEFLG_SOABEFOREAXFR);
11951 goto tcp_transfer;
11952 }
11953 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11954 "refresh: skipped tcp fallback "
11955 "as master %s (source %s) is "
11956 "unreachable (cached)",
11957 master, source);
11958 }
11959 } else
11960 dns_zone_log(zone, ISC_LOG_INFO,
11961 "refresh: failure trying master "
11962 "%s (source %s): %s", master, source,
11963 dns_result_totext(revent->result));
11964 goto next_master;
11965 }
11966
11967 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
11968 if (result != ISC_R_SUCCESS)
11969 goto next_master;
11970 result = dns_request_getresponse(revent->request, msg, 0);
11971 if (result != ISC_R_SUCCESS) {
11972 dns_zone_log(zone, ISC_LOG_INFO,
11973 "refresh: failure trying master "
11974 "%s (source %s): %s", master, source,
11975 dns_result_totext(result));
11976 goto next_master;
11977 }
11978
11979 /*
11980 * Unexpected rcode.
11981 */
11982 if (msg->rcode != dns_rcode_noerror) {
11983 char rcode[128];
11984 isc_buffer_t rb;
11985
11986 isc_buffer_init(&rb, rcode, sizeof(rcode));
11987 (void)dns_rcode_totext(msg->rcode, &rb);
11988
11989 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
11990 (msg->rcode == dns_rcode_servfail ||
11991 msg->rcode == dns_rcode_notimp ||
11992 msg->rcode == dns_rcode_formerr)) {
11993 dns_zone_log(zone, ISC_LOG_DEBUG(1),
11994 "refresh: rcode (%.*s) retrying without "
11995 "EDNS master %s (source %s)",
11996 (int)rb.used, rcode, master, source);
11997 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
11998 goto same_master;
11999 }
12000 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS) &&
12001 msg->rcode == dns_rcode_badvers) {
12002 dns_zone_log(zone, ISC_LOG_DEBUG(1),
12003 "refresh: rcode (%.*s) retrying without "
12004 "EDNS EXPIRE OPTION master %s (source %s)",
12005 (int)rb.used, rcode, master, source);
12006 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12007 goto same_master;
12008 }
12009 dns_zone_log(zone, ISC_LOG_INFO,
12010 "refresh: unexpected rcode (%.*s) from "
12011 "master %s (source %s)", (int)rb.used, rcode,
12012 master, source);
12013 /*
12014 * Perhaps AXFR/IXFR is allowed even if SOA queries aren't.
12015 */
12016 if (msg->rcode == dns_rcode_refused &&
12017 (zone->type == dns_zone_slave ||
12018 zone->type == dns_zone_redirect))
12019 goto tcp_transfer;
12020 goto next_master;
12021 }
12022
12023 /*
12024 * If truncated punt to zone transfer which will query again.
12025 */
12026 if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
12027 if (zone->type == dns_zone_slave ||
12028 zone->type == dns_zone_redirect) {
12029 dns_zone_log(zone, ISC_LOG_INFO,
12030 "refresh: truncated UDP answer, "
12031 "initiating TCP zone xfer "
12032 "for master %s (source %s)",
12033 master, source);
12034 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
12035 goto tcp_transfer;
12036 } else {
12037 INSIST(zone->type == dns_zone_stub);
12038 if (dns_request_usedtcp(revent->request)) {
12039 dns_zone_log(zone, ISC_LOG_INFO,
12040 "refresh: truncated TCP response "
12041 "from master %s (source %s)",
12042 master, source);
12043 goto next_master;
12044 }
12045 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC);
12046 goto same_master;
12047 }
12048 }
12049
12050 /*
12051 * if non-auth log and next master;
12052 */
12053 if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
12054 dns_zone_log(zone, ISC_LOG_INFO,
12055 "refresh: non-authoritative answer from "
12056 "master %s (source %s)", master, source);
12057 goto next_master;
12058 }
12059
12060 cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
12061 soacnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_soa);
12062 nscount = message_count(msg, DNS_SECTION_AUTHORITY, dns_rdatatype_ns);
12063 soacount = message_count(msg, DNS_SECTION_AUTHORITY,
12064 dns_rdatatype_soa);
12065
12066 /*
12067 * There should not be a CNAME record at top of zone.
12068 */
12069 if (cnamecnt != 0) {
12070 dns_zone_log(zone, ISC_LOG_INFO,
12071 "refresh: CNAME at top of zone "
12072 "in master %s (source %s)", master, source);
12073 goto next_master;
12074 }
12075
12076 /*
12077 * if referral log and next master;
12078 */
12079 if (soacnt == 0 && soacount == 0 && nscount != 0) {
12080 dns_zone_log(zone, ISC_LOG_INFO,
12081 "refresh: referral response "
12082 "from master %s (source %s)", master, source);
12083 goto next_master;
12084 }
12085
12086 /*
12087 * if nodata log and next master;
12088 */
12089 if (soacnt == 0 && (nscount == 0 || soacount != 0)) {
12090 dns_zone_log(zone, ISC_LOG_INFO,
12091 "refresh: NODATA response "
12092 "from master %s (source %s)", master, source);
12093 goto next_master;
12094 }
12095
12096 /*
12097 * Only one soa at top of zone.
12098 */
12099 if (soacnt != 1) {
12100 dns_zone_log(zone, ISC_LOG_INFO,
12101 "refresh: answer SOA count (%d) != 1 "
12102 "from master %s (source %s)",
12103 soacnt, master, source);
12104 goto next_master;
12105 }
12106
12107 /*
12108 * Extract serial
12109 */
12110 rdataset = NULL;
12111 result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
12112 dns_rdatatype_soa, dns_rdatatype_none,
12113 NULL, &rdataset);
12114 if (result != ISC_R_SUCCESS) {
12115 dns_zone_log(zone, ISC_LOG_INFO,
12116 "refresh: unable to get SOA record "
12117 "from master %s (source %s)", master, source);
12118 goto next_master;
12119 }
12120
12121 result = dns_rdataset_first(rdataset);
12122 if (result != ISC_R_SUCCESS) {
12123 dns_zone_log(zone, ISC_LOG_INFO,
12124 "refresh: dns_rdataset_first() failed");
12125 goto next_master;
12126 }
12127
12128 dns_rdataset_current(rdataset, &rdata);
12129 result = dns_rdata_tostruct(&rdata, &soa, NULL);
12130 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12131
12132 serial = soa.serial;
12133 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) {
12134 unsigned int dbsoacount;
12135 result = zone_get_from_db(zone, zone->db, NULL, &dbsoacount,
12136 &oldserial, NULL, NULL, NULL, NULL,
12137 NULL);
12138 RUNTIME_CHECK(result == ISC_R_SUCCESS);
12139 RUNTIME_CHECK(dbsoacount > 0U);
12140 zone_debuglog(zone, me, 1, "serial: new %u, old %u",
12141 serial, oldserial);
12142 } else
12143 zone_debuglog(zone, me, 1, "serial: new %u, old not loaded",
12144 serial);
12145
12146 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) ||
12147 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) ||
12148 isc_serial_gt(serial, oldserial)) {
12149 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
12150 &zone->sourceaddr, &now))
12151 {
12152 dns_zone_log(zone, ISC_LOG_INFO,
12153 "refresh: skipping %s as master %s "
12154 "(source %s) is unreachable (cached)",
12155 (zone->type == dns_zone_slave ||
12156 zone->type == dns_zone_redirect) ?
12157 "zone transfer" : "NS query",
12158 master, source);
12159 goto next_master;
12160 }
12161 tcp_transfer:
12162 isc_event_free(&event);
12163 dns_request_destroy(&zone->request);
12164 if (zone->type == dns_zone_slave ||
12165 zone->type == dns_zone_redirect) {
12166 do_queue_xfrin = ISC_TRUE;
12167 } else {
12168 INSIST(zone->type == dns_zone_stub);
12169 ns_query(zone, rdataset, NULL);
12170 }
12171 if (msg != NULL)
12172 dns_message_destroy(&msg);
12173 } else if (isc_serial_eq(soa.serial, oldserial)) {
12174 isc_time_t expiretime;
12175 isc_uint32_t expire;
12176
12177 /*
12178 * Compute the new expire time based on this response.
12179 */
12180 expire = zone->expire;
12181 get_edns_expire(zone, msg, &expire);
12182 DNS_ZONE_TIME_ADD(&now, expire, &expiretime);
12183
12184 /*
12185 * Has the expire time improved?
12186 */
12187 if (isc_time_compare(&expiretime, &zone->expiretime) > 0) {
12188 zone->expiretime = expiretime;
12189 if (zone->masterfile != NULL)
12190 setmodtime(zone, &expiretime);
12191 }
12192
12193 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
12194 zone->mastersok[zone->curmaster] = ISC_TRUE;
12195 goto next_master;
12196 } else {
12197 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
12198 dns_zone_log(zone, ISC_LOG_INFO, "serial number (%u) "
12199 "received from master %s < ours (%u)",
12200 soa.serial, master, oldserial);
12201 else
12202 zone_debuglog(zone, me, 1, "ahead");
12203 zone->mastersok[zone->curmaster] = ISC_TRUE;
12204 goto next_master;
12205 }
12206 if (msg != NULL)
12207 dns_message_destroy(&msg);
12208 goto detach;
12209
12210 next_master:
12211 if (msg != NULL)
12212 dns_message_destroy(&msg);
12213 isc_event_free(&event);
12214 dns_request_destroy(&zone->request);
12215 /*
12216 * Skip to next failed / untried master.
12217 */
12218 do {
12219 zone->curmaster++;
12220 } while (zone->curmaster < zone->masterscnt &&
12221 zone->mastersok[zone->curmaster]);
12222 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
12223 if (zone->curmaster >= zone->masterscnt) {
12224 isc_boolean_t done = ISC_TRUE;
12225 if (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] == ISC_FALSE) {
12232 done = ISC_FALSE;
12233 break;
12234 }
12235 } else
12236 done = ISC_TRUE;
12237 if (!done) {
12238 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12239 zone->curmaster = 0;
12240 /*
12241 * Find the next failed master.
12242 */
12243 while (zone->curmaster < zone->masterscnt &&
12244 zone->mastersok[zone->curmaster])
12245 zone->curmaster++;
12246 goto requeue;
12247 }
12248 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12249 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
12250 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
12251 zone->refreshtime = now;
12252 }
12253 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
12254 zone_settimer(zone, &now);
12255 goto detach;
12256 }
12257
12258 requeue:
12259 queue_soa_query(zone);
12260 goto detach;
12261
12262 same_master:
12263 if (msg != NULL)
12264 dns_message_destroy(&msg);
12265 isc_event_free(&event);
12266 dns_request_destroy(&zone->request);
12267 queue_soa_query(zone);
12268
12269 detach:
12270 UNLOCK_ZONE(zone);
12271 if (do_queue_xfrin)
12272 queue_xfrin(zone);
12273 dns_zone_idetach(&zone);
12274 return;
12275 }
12276
12277 static void
12278 queue_soa_query(dns_zone_t *zone) {
12279 const char me[] = "queue_soa_query";
12280 isc_event_t *e;
12281 dns_zone_t *dummy = NULL;
12282 isc_result_t result;
12283
12284 ENTER;
12285 /*
12286 * Locked by caller
12287 */
12288 REQUIRE(LOCKED_ZONE(zone));
12289
12290 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
12291 cancel_refresh(zone);
12292 return;
12293 }
12294
12295 e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_ZONE,
12296 soa_query, zone, sizeof(isc_event_t));
12297 if (e == NULL) {
12298 cancel_refresh(zone);
12299 return;
12300 }
12301
12302 /*
12303 * Attach so that we won't clean up
12304 * until the event is delivered.
12305 */
12306 zone_iattach(zone, &dummy);
12307
12308 e->ev_arg = zone;
12309 e->ev_sender = NULL;
12310 result = isc_ratelimiter_enqueue(zone->zmgr->refreshrl, zone->task, &e);
12311 if (result != ISC_R_SUCCESS) {
12312 zone_idetach(&dummy);
12313 isc_event_free(&e);
12314 cancel_refresh(zone);
12315 }
12316 }
12317
12318 static inline isc_result_t
12319 create_query(dns_zone_t *zone, dns_rdatatype_t rdtype,
12320 dns_message_t **messagep)
12321 {
12322 dns_message_t *message = NULL;
12323 dns_name_t *qname = NULL;
12324 dns_rdataset_t *qrdataset = NULL;
12325 isc_result_t result;
12326
12327 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
12328 &message);
12329 if (result != ISC_R_SUCCESS)
12330 goto cleanup;
12331
12332 message->opcode = dns_opcode_query;
12333 message->rdclass = zone->rdclass;
12334
12335 result = dns_message_gettempname(message, &qname);
12336 if (result != ISC_R_SUCCESS)
12337 goto cleanup;
12338
12339 result = dns_message_gettemprdataset(message, &qrdataset);
12340 if (result != ISC_R_SUCCESS)
12341 goto cleanup;
12342
12343 /*
12344 * Make question.
12345 */
12346 dns_name_init(qname, NULL);
12347 dns_name_clone(&zone->origin, qname);
12348 dns_rdataset_makequestion(qrdataset, zone->rdclass, rdtype);
12349 ISC_LIST_APPEND(qname->list, qrdataset, link);
12350 dns_message_addname(message, qname, DNS_SECTION_QUESTION);
12351
12352 *messagep = message;
12353 return (ISC_R_SUCCESS);
12354
12355 cleanup:
12356 if (qname != NULL)
12357 dns_message_puttempname(message, &qname);
12358 if (qrdataset != NULL)
12359 dns_message_puttemprdataset(message, &qrdataset);
12360 if (message != NULL)
12361 dns_message_destroy(&message);
12362 return (result);
12363 }
12364
12365 static isc_result_t
12366 add_opt(dns_message_t *message, isc_uint16_t udpsize, isc_boolean_t reqnsid,
12367 isc_boolean_t reqexpire)
12368 {
12369 isc_result_t result;
12370 dns_rdataset_t *rdataset = NULL;
12371 dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS];
12372 int count = 0;
12373
12374 /* Set EDNS options if applicable */
12375 if (reqnsid) {
12376 INSIST(count < DNS_EDNSOPTIONS);
12377 ednsopts[count].code = DNS_OPT_NSID;
12378 ednsopts[count].length = 0;
12379 ednsopts[count].value = NULL;
12380 count++;
12381 }
12382 if (reqexpire) {
12383 INSIST(count < DNS_EDNSOPTIONS);
12384 ednsopts[count].code = DNS_OPT_EXPIRE;
12385 ednsopts[count].length = 0;
12386 ednsopts[count].value = NULL;
12387 count++;
12388 }
12389 result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0,
12390 ednsopts, count);
12391 if (result != ISC_R_SUCCESS)
12392 return (result);
12393
12394 return (dns_message_setopt(message, rdataset));
12395 }
12396
12397 static void
12398 soa_query(isc_task_t *task, isc_event_t *event) {
12399 const char me[] = "soa_query";
12400 isc_result_t result = ISC_R_FAILURE;
12401 dns_message_t *message = NULL;
12402 dns_zone_t *zone = event->ev_arg;
12403 dns_zone_t *dummy = NULL;
12404 isc_netaddr_t masterip;
12405 dns_tsigkey_t *key = NULL;
12406 isc_uint32_t options;
12407 isc_boolean_t cancel = ISC_TRUE;
12408 int timeout;
12409 isc_boolean_t have_xfrsource, have_xfrdscp, reqnsid, reqexpire;
12410 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
12411 isc_dscp_t dscp = -1;
12412
12413 REQUIRE(DNS_ZONE_VALID(zone));
12414
12415 UNUSED(task);
12416
12417 ENTER;
12418
12419 LOCK_ZONE(zone);
12420 if (((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) ||
12421 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) ||
12422 zone->view->requestmgr == NULL) {
12423 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12424 cancel = ISC_FALSE;
12425 goto cleanup;
12426 }
12427
12428 again:
12429 result = create_query(zone, dns_rdatatype_soa, &message);
12430 if (result != ISC_R_SUCCESS)
12431 goto cleanup;
12432
12433 INSIST(zone->masterscnt > 0);
12434 INSIST(zone->curmaster < zone->masterscnt);
12435
12436 zone->masteraddr = zone->masters[zone->curmaster];
12437
12438 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12439 /*
12440 * First, look for a tsig key in the master statement, then
12441 * try for a server key.
12442 */
12443 if ((zone->masterkeynames != NULL) &&
12444 (zone->masterkeynames[zone->curmaster] != NULL)) {
12445 dns_view_t *view = dns_zone_getview(zone);
12446 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12447 result = dns_view_gettsig(view, keyname, &key);
12448 if (result != ISC_R_SUCCESS) {
12449 char namebuf[DNS_NAME_FORMATSIZE];
12450 dns_name_format(keyname, namebuf, sizeof(namebuf));
12451 dns_zone_log(zone, ISC_LOG_ERROR,
12452 "unable to find key: %s", namebuf);
12453 goto skip_master;
12454 }
12455 }
12456 if (key == NULL) {
12457 result = dns_view_getpeertsig(zone->view, &masterip, &key);
12458 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
12459 char addrbuf[ISC_NETADDR_FORMATSIZE];
12460 isc_netaddr_format(&masterip, addrbuf, sizeof(addrbuf));
12461 dns_zone_log(zone, ISC_LOG_ERROR,
12462 "unable to find TSIG key for %s", addrbuf);
12463 goto skip_master;
12464 }
12465 }
12466
12467 options = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEVC) ?
12468 DNS_REQUESTOPT_TCP : 0;
12469 have_xfrsource = have_xfrdscp = ISC_FALSE;
12470 reqnsid = zone->view->requestnsid;
12471 reqexpire = zone->requestexpire;
12472 if (zone->view->peers != NULL) {
12473 dns_peer_t *peer = NULL;
12474 isc_boolean_t edns, usetcp;
12475 result = dns_peerlist_peerbyaddr(zone->view->peers,
12476 &masterip, &peer);
12477 if (result == ISC_R_SUCCESS) {
12478 result = dns_peer_getsupportedns(peer, &edns);
12479 if (result == ISC_R_SUCCESS && !edns)
12480 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12481 result = dns_peer_gettransfersource(peer,
12482 &zone->sourceaddr);
12483 if (result == ISC_R_SUCCESS)
12484 have_xfrsource = ISC_TRUE;
12485 (void)dns_peer_gettransferdscp(peer, &dscp);
12486 if (dscp != -1)
12487 have_xfrdscp = ISC_TRUE;
12488 if (zone->view->resolver != NULL)
12489 udpsize =
12490 dns_resolver_getudpsize(zone->view->resolver);
12491 (void)dns_peer_getudpsize(peer, &udpsize);
12492 (void)dns_peer_getrequestnsid(peer, &reqnsid);
12493 (void)dns_peer_getrequestexpire(peer, &reqexpire);
12494 result = dns_peer_getforcetcp(peer, &usetcp);
12495 if (result == ISC_R_SUCCESS && usetcp)
12496 options |= DNS_REQUESTOPT_TCP;
12497 }
12498 }
12499
12500 switch (isc_sockaddr_pf(&zone->masteraddr)) {
12501 case PF_INET:
12502 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12503 if (isc_sockaddr_equal(&zone->altxfrsource4,
12504 &zone->xfrsource4))
12505 goto skip_master;
12506 zone->sourceaddr = zone->altxfrsource4;
12507 if (!have_xfrdscp)
12508 dscp = zone->altxfrsource4dscp;
12509 } else if (!have_xfrsource) {
12510 zone->sourceaddr = zone->xfrsource4;
12511 if (!have_xfrdscp)
12512 dscp = zone->xfrsource4dscp;
12513 }
12514 break;
12515 case PF_INET6:
12516 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12517 if (isc_sockaddr_equal(&zone->altxfrsource6,
12518 &zone->xfrsource6))
12519 goto skip_master;
12520 zone->sourceaddr = zone->altxfrsource6;
12521 if (!have_xfrdscp)
12522 dscp = zone->altxfrsource6dscp;
12523 } else if (!have_xfrsource) {
12524 zone->sourceaddr = zone->xfrsource6;
12525 if (!have_xfrdscp)
12526 dscp = zone->xfrsource6dscp;
12527 }
12528 break;
12529 default:
12530 result = ISC_R_NOTIMPLEMENTED;
12531 goto cleanup;
12532 }
12533
12534 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12535 result = add_opt(message, udpsize, reqnsid, reqexpire);
12536 if (result != ISC_R_SUCCESS)
12537 zone_debuglog(zone, me, 1,
12538 "unable to add opt record: %s",
12539 dns_result_totext(result));
12540 }
12541
12542 zone_iattach(zone, &dummy);
12543 timeout = 15;
12544 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
12545 timeout = 30;
12546 result = dns_request_createvia4(zone->view->requestmgr, message,
12547 &zone->sourceaddr, &zone->masteraddr,
12548 dscp, options, key, timeout * 3,
12549 timeout, 0, zone->task,
12550 refresh_callback, zone, &zone->request);
12551 if (result != ISC_R_SUCCESS) {
12552 zone_idetach(&dummy);
12553 zone_debuglog(zone, me, 1,
12554 "dns_request_createvia4() failed: %s",
12555 dns_result_totext(result));
12556 goto skip_master;
12557 } else {
12558 if (isc_sockaddr_pf(&zone->masteraddr) == PF_INET)
12559 inc_stats(zone, dns_zonestatscounter_soaoutv4);
12560 else
12561 inc_stats(zone, dns_zonestatscounter_soaoutv6);
12562 }
12563 cancel = ISC_FALSE;
12564
12565 cleanup:
12566 if (key != NULL)
12567 dns_tsigkey_detach(&key);
12568 if (result != ISC_R_SUCCESS)
12569 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
12570 if (message != NULL)
12571 dns_message_destroy(&message);
12572 if (cancel)
12573 cancel_refresh(zone);
12574 isc_event_free(&event);
12575 UNLOCK_ZONE(zone);
12576 dns_zone_idetach(&zone);
12577 return;
12578
12579 skip_master:
12580 if (key != NULL)
12581 dns_tsigkey_detach(&key);
12582 dns_message_destroy(&message);
12583 /*
12584 * Skip to next failed / untried master.
12585 */
12586 do {
12587 zone->curmaster++;
12588 } while (zone->curmaster < zone->masterscnt &&
12589 zone->mastersok[zone->curmaster]);
12590 if (zone->curmaster < zone->masterscnt)
12591 goto again;
12592 zone->curmaster = 0;
12593 goto cleanup;
12594 }
12595
12596 static void
12597 ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
12598 const char me[] = "ns_query";
12599 isc_result_t result;
12600 dns_message_t *message = NULL;
12601 isc_netaddr_t masterip;
12602 dns_tsigkey_t *key = NULL;
12603 dns_dbnode_t *node = NULL;
12604 int timeout;
12605 isc_boolean_t have_xfrsource = ISC_FALSE, have_xfrdscp = ISC_FALSE;
12606 isc_boolean_t reqnsid;
12607 isc_uint16_t udpsize = SEND_BUFFER_SIZE;
12608 isc_dscp_t dscp = -1;
12609
12610 REQUIRE(DNS_ZONE_VALID(zone));
12611 REQUIRE(LOCKED_ZONE(zone));
12612 REQUIRE((soardataset != NULL && stub == NULL) ||
12613 (soardataset == NULL && stub != NULL));
12614 REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
12615
12616 ENTER;
12617
12618 if (stub == NULL) {
12619 stub = isc_mem_get(zone->mctx, sizeof(*stub));
12620 if (stub == NULL)
12621 goto cleanup;
12622 stub->magic = STUB_MAGIC;
12623 stub->mctx = zone->mctx;
12624 stub->zone = NULL;
12625 stub->db = NULL;
12626 stub->version = NULL;
12627
12628 /*
12629 * Attach so that the zone won't disappear from under us.
12630 */
12631 zone_iattach(zone, &stub->zone);
12632
12633 /*
12634 * If a db exists we will update it, otherwise we create a
12635 * new one and attach it to the zone once we have the NS
12636 * RRset and glue.
12637 */
12638 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
12639 if (zone->db != NULL) {
12640 dns_db_attach(zone->db, &stub->db);
12641 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12642 } else {
12643 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
12644
12645 INSIST(zone->db_argc >= 1);
12646 result = dns_db_create(zone->mctx, zone->db_argv[0],
12647 &zone->origin, dns_dbtype_stub,
12648 zone->rdclass,
12649 zone->db_argc - 1,
12650 zone->db_argv + 1,
12651 &stub->db);
12652 if (result != ISC_R_SUCCESS) {
12653 dns_zone_log(zone, ISC_LOG_ERROR,
12654 "refreshing stub: "
12655 "could not create "
12656 "database: %s",
12657 dns_result_totext(result));
12658 goto cleanup;
12659 }
12660 dns_db_settask(stub->db, zone->task);
12661 }
12662
12663 result = dns_db_newversion(stub->db, &stub->version);
12664 if (result != ISC_R_SUCCESS) {
12665 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
12666 "dns_db_newversion() failed: %s",
12667 dns_result_totext(result));
12668 goto cleanup;
12669 }
12670
12671 /*
12672 * Update SOA record.
12673 */
12674 result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
12675 &node);
12676 if (result != ISC_R_SUCCESS) {
12677 dns_zone_log(zone, ISC_LOG_INFO, "refreshing stub: "
12678 "dns_db_findnode() failed: %s",
12679 dns_result_totext(result));
12680 goto cleanup;
12681 }
12682
12683 result = dns_db_addrdataset(stub->db, node, stub->version, 0,
12684 soardataset, 0, NULL);
12685 dns_db_detachnode(stub->db, &node);
12686 if (result != ISC_R_SUCCESS) {
12687 dns_zone_log(zone, ISC_LOG_INFO,
12688 "refreshing stub: "
12689 "dns_db_addrdataset() failed: %s",
12690 dns_result_totext(result));
12691 goto cleanup;
12692 }
12693 }
12694
12695 /*
12696 * XXX Optimisation: Create message when zone is setup and reuse.
12697 */
12698 result = create_query(zone, dns_rdatatype_ns, &message);
12699 INSIST(result == ISC_R_SUCCESS);
12700
12701 INSIST(zone->masterscnt > 0);
12702 INSIST(zone->curmaster < zone->masterscnt);
12703 zone->masteraddr = zone->masters[zone->curmaster];
12704
12705 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
12706 /*
12707 * First, look for a tsig key in the master statement, then
12708 * try for a server key.
12709 */
12710 if ((zone->masterkeynames != NULL) &&
12711 (zone->masterkeynames[zone->curmaster] != NULL)) {
12712 dns_view_t *view = dns_zone_getview(zone);
12713 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
12714 result = dns_view_gettsig(view, keyname, &key);
12715 if (result != ISC_R_SUCCESS) {
12716 char namebuf[DNS_NAME_FORMATSIZE];
12717 dns_name_format(keyname, namebuf, sizeof(namebuf));
12718 dns_zone_log(zone, ISC_LOG_ERROR,
12719 "unable to find key: %s", namebuf);
12720 }
12721 }
12722 if (key == NULL)
12723 (void)dns_view_getpeertsig(zone->view, &masterip, &key);
12724
12725 reqnsid = zone->view->requestnsid;
12726 if (zone->view->peers != NULL) {
12727 dns_peer_t *peer = NULL;
12728 isc_boolean_t edns;
12729 result = dns_peerlist_peerbyaddr(zone->view->peers,
12730 &masterip, &peer);
12731 if (result == ISC_R_SUCCESS) {
12732 result = dns_peer_getsupportedns(peer, &edns);
12733 if (result == ISC_R_SUCCESS && !edns)
12734 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS);
12735 result = dns_peer_gettransfersource(peer,
12736 &zone->sourceaddr);
12737 if (result == ISC_R_SUCCESS)
12738 have_xfrsource = ISC_TRUE;
12739 result = dns_peer_gettransferdscp(peer, &dscp);
12740 if (result == ISC_R_SUCCESS && dscp != -1)
12741 have_xfrdscp = ISC_TRUE;
12742 if (zone->view->resolver != NULL)
12743 udpsize =
12744 dns_resolver_getudpsize(zone->view->resolver);
12745 (void)dns_peer_getudpsize(peer, &udpsize);
12746 (void)dns_peer_getrequestnsid(peer, &reqnsid);
12747 }
12748
12749 }
12750 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) {
12751 result = add_opt(message, udpsize, reqnsid, ISC_FALSE);
12752 if (result != ISC_R_SUCCESS)
12753 zone_debuglog(zone, me, 1,
12754 "unable to add opt record: %s",
12755 dns_result_totext(result));
12756 }
12757
12758 /*
12759 * Always use TCP so that we shouldn't truncate in additional section.
12760 */
12761 switch (isc_sockaddr_pf(&zone->masteraddr)) {
12762 case PF_INET:
12763 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12764 zone->sourceaddr = zone->altxfrsource4;
12765 if (!have_xfrdscp)
12766 dscp = zone->altxfrsource4dscp;
12767 } else if (!have_xfrsource) {
12768 zone->sourceaddr = zone->xfrsource4;
12769 if (!have_xfrdscp)
12770 dscp = zone->xfrsource4dscp;
12771 }
12772 break;
12773 case PF_INET6:
12774 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
12775 zone->sourceaddr = zone->altxfrsource6;
12776 if (!have_xfrdscp)
12777 dscp = zone->altxfrsource6dscp;
12778 } else if (!have_xfrsource) {
12779 zone->sourceaddr = zone->xfrsource6;
12780 if (!have_xfrdscp)
12781 dscp = zone->xfrsource6dscp;
12782 }
12783 break;
12784 default:
12785 result = ISC_R_NOTIMPLEMENTED;
12786 POST(result);
12787 goto cleanup;
12788 }
12789 timeout = 15;
12790 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
12791 timeout = 30;
12792 result = dns_request_createvia4(zone->view->requestmgr, message,
12793 &zone->sourceaddr, &zone->masteraddr,
12794 dscp, DNS_REQUESTOPT_TCP, key,
12795 timeout * 3, timeout, 0, zone->task,
12796 stub_callback, stub, &zone->request);
12797 if (result != ISC_R_SUCCESS) {
12798 zone_debuglog(zone, me, 1,
12799 "dns_request_createvia() failed: %s",
12800 dns_result_totext(result));
12801 goto cleanup;
12802 }
12803 dns_message_destroy(&message);
12804 goto unlock;
12805
12806 cleanup:
12807 cancel_refresh(zone);
12808 if (stub != NULL) {
12809 stub->magic = 0;
12810 if (stub->version != NULL)
12811 dns_db_closeversion(stub->db, &stub->version,
12812 ISC_FALSE);
12813 if (stub->db != NULL)
12814 dns_db_detach(&stub->db);
12815 if (stub->zone != NULL)
12816 zone_idetach(&stub->zone);
12817 isc_mem_put(stub->mctx, stub, sizeof(*stub));
12818 }
12819 if (message != NULL)
12820 dns_message_destroy(&message);
12821 unlock:
12822 if (key != NULL)
12823 dns_tsigkey_detach(&key);
12824 return;
12825 }
12826
12827 /*
12828 * Handle the control event. Note that although this event causes the zone
12829 * to shut down, it is not a shutdown event in the sense of the task library.
12830 */
12831 static void
12832 zone_shutdown(isc_task_t *task, isc_event_t *event) {
12833 dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
12834 isc_boolean_t free_needed, linked = ISC_FALSE;
12835 dns_zone_t *raw = NULL, *secure = NULL;
12836
12837 UNUSED(task);
12838 REQUIRE(DNS_ZONE_VALID(zone));
12839 INSIST(event->ev_type == DNS_EVENT_ZONECONTROL);
12840 INSIST(isc_refcount_current(&zone->erefs) == 0);
12841
12842 zone_debuglog(zone, "zone_shutdown", 3, "shutting down");
12843
12844 /*
12845 * Stop things being restarted after we cancel them below.
12846 */
12847 LOCK_ZONE(zone);
12848 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXITING);
12849 UNLOCK_ZONE(zone);
12850
12851 /*
12852 * If we were waiting for xfrin quota, step out of
12853 * the queue.
12854 * If there's no zone manager, we can't be waiting for the
12855 * xfrin quota
12856 */
12857 if (zone->zmgr != NULL) {
12858 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12859 if (zone->statelist == &zone->zmgr->waiting_for_xfrin) {
12860 ISC_LIST_UNLINK(zone->zmgr->waiting_for_xfrin, zone,
12861 statelink);
12862 linked = ISC_TRUE;
12863 zone->statelist = NULL;
12864 }
12865 if (zone->statelist == &zone->zmgr->xfrin_in_progress) {
12866 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone,
12867 statelink);
12868 zone->statelist = NULL;
12869 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
12870 }
12871 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
12872 }
12873
12874 /*
12875 * In task context, no locking required. See zone_xfrdone().
12876 */
12877 if (zone->xfr != NULL)
12878 dns_xfrin_shutdown(zone->xfr);
12879
12880 /* Safe to release the zone now */
12881 if (zone->zmgr != NULL)
12882 dns_zonemgr_releasezone(zone->zmgr, zone);
12883
12884 LOCK_ZONE(zone);
12885 INSIST(zone != zone->raw);
12886 if (linked) {
12887 INSIST(zone->irefs > 0);
12888 zone->irefs--;
12889 }
12890 if (zone->request != NULL) {
12891 dns_request_cancel(zone->request);
12892 }
12893
12894 if (zone->readio != NULL)
12895 zonemgr_cancelio(zone->readio);
12896
12897 if (zone->lctx != NULL)
12898 dns_loadctx_cancel(zone->lctx);
12899
12900 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) ||
12901 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12902 if (zone->writeio != NULL)
12903 zonemgr_cancelio(zone->writeio);
12904
12905 if (zone->dctx != NULL)
12906 dns_dumpctx_cancel(zone->dctx);
12907 }
12908
12909 notify_cancel(zone);
12910
12911 forward_cancel(zone);
12912
12913 if (zone->timer != NULL) {
12914 isc_timer_detach(&zone->timer);
12915 INSIST(zone->irefs > 0);
12916 zone->irefs--;
12917 }
12918
12919 /*
12920 * We have now canceled everything set the flag to allow exit_check()
12921 * to succeed. We must not unlock between setting this flag and
12922 * calling exit_check().
12923 */
12924 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SHUTDOWN);
12925 free_needed = exit_check(zone);
12926 if (inline_secure(zone)) {
12927 raw = zone->raw;
12928 zone->raw = NULL;
12929 }
12930 if (inline_raw(zone)) {
12931 secure = zone->secure;
12932 zone->secure = NULL;
12933 }
12934 UNLOCK_ZONE(zone);
12935 if (raw != NULL)
12936 dns_zone_detach(&raw);
12937 if (secure != NULL)
12938 dns_zone_idetach(&secure);
12939 if (free_needed)
12940 zone_free(zone);
12941 }
12942
12943 static void
12944 zone_timer(isc_task_t *task, isc_event_t *event) {
12945 const char me[] = "zone_timer";
12946 dns_zone_t *zone = (dns_zone_t *)event->ev_arg;
12947
12948 UNUSED(task);
12949 REQUIRE(DNS_ZONE_VALID(zone));
12950
12951 ENTER;
12952
12953 zone_maintenance(zone);
12954
12955 isc_event_free(&event);
12956 }
12957
12958 static void
12959 zone_settimer(dns_zone_t *zone, isc_time_t *now) {
12960 const char me[] = "zone_settimer";
12961 isc_time_t next;
12962 isc_result_t result;
12963
12964 REQUIRE(DNS_ZONE_VALID(zone));
12965 ENTER;
12966
12967 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
12968 return;
12969
12970 isc_time_settoepoch(&next);
12971
12972 switch (zone->type) {
12973 case dns_zone_redirect:
12974 if (zone->masters != NULL)
12975 goto treat_as_slave;
12976 /* FALLTHROUGH */
12977
12978 case dns_zone_master:
12979 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
12980 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
12981 next = zone->notifytime;
12982 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
12983 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
12984 INSIST(!isc_time_isepoch(&zone->dumptime));
12985 if (isc_time_isepoch(&next) ||
12986 isc_time_compare(&zone->dumptime, &next) < 0)
12987 next = zone->dumptime;
12988 }
12989 if (zone->type == dns_zone_redirect)
12990 break;
12991 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING) &&
12992 !isc_time_isepoch(&zone->refreshkeytime)) {
12993 if (isc_time_isepoch(&next) ||
12994 isc_time_compare(&zone->refreshkeytime, &next) < 0)
12995 next = zone->refreshkeytime;
12996 }
12997 if (!isc_time_isepoch(&zone->resigntime)) {
12998 if (isc_time_isepoch(&next) ||
12999 isc_time_compare(&zone->resigntime, &next) < 0)
13000 next = zone->resigntime;
13001 }
13002 if (!isc_time_isepoch(&zone->keywarntime)) {
13003 if (isc_time_isepoch(&next) ||
13004 isc_time_compare(&zone->keywarntime, &next) < 0)
13005 next = zone->keywarntime;
13006 }
13007 if (!isc_time_isepoch(&zone->signingtime)) {
13008 if (isc_time_isepoch(&next) ||
13009 isc_time_compare(&zone->signingtime, &next) < 0)
13010 next = zone->signingtime;
13011 }
13012 if (!isc_time_isepoch(&zone->nsec3chaintime)) {
13013 if (isc_time_isepoch(&next) ||
13014 isc_time_compare(&zone->nsec3chaintime, &next) < 0)
13015 next = zone->nsec3chaintime;
13016 }
13017 break;
13018
13019 case dns_zone_slave:
13020 treat_as_slave:
13021 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY) ||
13022 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDSTARTUPNOTIFY))
13023 next = zone->notifytime;
13024 /* FALLTHROUGH */
13025
13026 case dns_zone_stub:
13027 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH) &&
13028 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOMASTERS) &&
13029 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH) &&
13030 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADING) &&
13031 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPENDING) &&
13032 !isc_time_isepoch(&zone->refreshtime) &&
13033 (isc_time_isepoch(&next) ||
13034 isc_time_compare(&zone->refreshtime, &next) < 0))
13035 next = zone->refreshtime;
13036 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13037 !isc_time_isepoch(&zone->expiretime)) {
13038 if (isc_time_isepoch(&next) ||
13039 isc_time_compare(&zone->expiretime, &next) < 0)
13040 next = zone->expiretime;
13041 }
13042 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13043 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13044 INSIST(!isc_time_isepoch(&zone->dumptime));
13045 if (isc_time_isepoch(&next) ||
13046 isc_time_compare(&zone->dumptime, &next) < 0)
13047 next = zone->dumptime;
13048 }
13049 break;
13050
13051 case dns_zone_key:
13052 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) &&
13053 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) {
13054 INSIST(!isc_time_isepoch(&zone->dumptime));
13055 if (isc_time_isepoch(&next) ||
13056 isc_time_compare(&zone->dumptime, &next) < 0)
13057 next = zone->dumptime;
13058 }
13059 if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESHING)) {
13060 if (isc_time_isepoch(&next) ||
13061 (!isc_time_isepoch(&zone->refreshkeytime) &&
13062 isc_time_compare(&zone->refreshkeytime, &next) < 0))
13063 next = zone->refreshkeytime;
13064 }
13065 break;
13066
13067 default:
13068 break;
13069 }
13070
13071 if (isc_time_isepoch(&next)) {
13072 zone_debuglog(zone, me, 10, "settimer inactive");
13073 result = isc_timer_reset(zone->timer, isc_timertype_inactive,
13074 NULL, NULL, ISC_TRUE);
13075 if (result != ISC_R_SUCCESS)
13076 dns_zone_log(zone, ISC_LOG_ERROR,
13077 "could not deactivate zone timer: %s",
13078 isc_result_totext(result));
13079 } else {
13080 if (isc_time_compare(&next, now) <= 0)
13081 next = *now;
13082 result = isc_timer_reset(zone->timer, isc_timertype_once,
13083 &next, NULL, ISC_TRUE);
13084 if (result != ISC_R_SUCCESS)
13085 dns_zone_log(zone, ISC_LOG_ERROR,
13086 "could not reset zone timer: %s",
13087 isc_result_totext(result));
13088 }
13089 }
13090
13091 static void
13092 cancel_refresh(dns_zone_t *zone) {
13093 const char me[] = "cancel_refresh";
13094 isc_time_t now;
13095
13096 /*
13097 * 'zone' locked by caller.
13098 */
13099
13100 REQUIRE(DNS_ZONE_VALID(zone));
13101 REQUIRE(LOCKED_ZONE(zone));
13102
13103 ENTER;
13104
13105 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
13106 TIME_NOW(&now);
13107 zone_settimer(zone, &now);
13108 }
13109
13110 static isc_result_t
13111 notify_createmessage(dns_zone_t *zone, unsigned int flags,
13112 dns_message_t **messagep)
13113 {
13114 dns_db_t *zonedb = NULL;
13115 dns_dbnode_t *node = NULL;
13116 dns_dbversion_t *version = NULL;
13117 dns_message_t *message = NULL;
13118 dns_rdataset_t rdataset;
13119 dns_rdata_t rdata = DNS_RDATA_INIT;
13120
13121 dns_name_t *tempname = NULL;
13122 dns_rdata_t *temprdata = NULL;
13123 dns_rdatalist_t *temprdatalist = NULL;
13124 dns_rdataset_t *temprdataset = NULL;
13125
13126 isc_result_t result;
13127 isc_region_t r;
13128 isc_buffer_t *b = NULL;
13129
13130 REQUIRE(DNS_ZONE_VALID(zone));
13131 REQUIRE(messagep != NULL && *messagep == NULL);
13132
13133 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
13134 &message);
13135 if (result != ISC_R_SUCCESS)
13136 return (result);
13137
13138 message->opcode = dns_opcode_notify;
13139 message->flags |= DNS_MESSAGEFLAG_AA;
13140 message->rdclass = zone->rdclass;
13141
13142 result = dns_message_gettempname(message, &tempname);
13143 if (result != ISC_R_SUCCESS)
13144 goto cleanup;
13145
13146 result = dns_message_gettemprdataset(message, &temprdataset);
13147 if (result != ISC_R_SUCCESS)
13148 goto cleanup;
13149
13150 /*
13151 * Make question.
13152 */
13153 dns_name_init(tempname, NULL);
13154 dns_name_clone(&zone->origin, tempname);
13155 dns_rdataset_makequestion(temprdataset, zone->rdclass,
13156 dns_rdatatype_soa);
13157 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13158 dns_message_addname(message, tempname, DNS_SECTION_QUESTION);
13159 tempname = NULL;
13160 temprdataset = NULL;
13161
13162 if ((flags & DNS_NOTIFY_NOSOA) != 0)
13163 goto done;
13164
13165 result = dns_message_gettempname(message, &tempname);
13166 if (result != ISC_R_SUCCESS)
13167 goto soa_cleanup;
13168 result = dns_message_gettemprdata(message, &temprdata);
13169 if (result != ISC_R_SUCCESS)
13170 goto soa_cleanup;
13171 result = dns_message_gettemprdataset(message, &temprdataset);
13172 if (result != ISC_R_SUCCESS)
13173 goto soa_cleanup;
13174 result = dns_message_gettemprdatalist(message, &temprdatalist);
13175 if (result != ISC_R_SUCCESS)
13176 goto soa_cleanup;
13177
13178 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13179 INSIST(zone->db != NULL); /* XXXJT: is this assumption correct? */
13180 dns_db_attach(zone->db, &zonedb);
13181 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13182
13183 dns_name_init(tempname, NULL);
13184 dns_name_clone(&zone->origin, tempname);
13185 dns_db_currentversion(zonedb, &version);
13186 result = dns_db_findnode(zonedb, tempname, ISC_FALSE, &node);
13187 if (result != ISC_R_SUCCESS)
13188 goto soa_cleanup;
13189
13190 dns_rdataset_init(&rdataset);
13191 result = dns_db_findrdataset(zonedb, node, version,
13192 dns_rdatatype_soa,
13193 dns_rdatatype_none, 0, &rdataset,
13194 NULL);
13195 if (result != ISC_R_SUCCESS)
13196 goto soa_cleanup;
13197 result = dns_rdataset_first(&rdataset);
13198 if (result != ISC_R_SUCCESS)
13199 goto soa_cleanup;
13200 dns_rdataset_current(&rdataset, &rdata);
13201 dns_rdata_toregion(&rdata, &r);
13202 result = isc_buffer_allocate(zone->mctx, &b, r.length);
13203 if (result != ISC_R_SUCCESS)
13204 goto soa_cleanup;
13205 isc_buffer_putmem(b, r.base, r.length);
13206 isc_buffer_usedregion(b, &r);
13207 dns_rdata_init(temprdata);
13208 dns_rdata_fromregion(temprdata, rdata.rdclass, rdata.type, &r);
13209 dns_message_takebuffer(message, &b);
13210 result = dns_rdataset_next(&rdataset);
13211 dns_rdataset_disassociate(&rdataset);
13212 if (result != ISC_R_NOMORE)
13213 goto soa_cleanup;
13214 temprdatalist->rdclass = rdata.rdclass;
13215 temprdatalist->type = rdata.type;
13216 temprdatalist->ttl = rdataset.ttl;
13217 ISC_LIST_APPEND(temprdatalist->rdata, temprdata, link);
13218
13219 result = dns_rdatalist_tordataset(temprdatalist, temprdataset);
13220 if (result != ISC_R_SUCCESS)
13221 goto soa_cleanup;
13222
13223 ISC_LIST_APPEND(tempname->list, temprdataset, link);
13224 dns_message_addname(message, tempname, DNS_SECTION_ANSWER);
13225 temprdatalist = NULL;
13226 temprdataset = NULL;
13227 temprdata = NULL;
13228 tempname = NULL;
13229
13230 soa_cleanup:
13231 if (node != NULL)
13232 dns_db_detachnode(zonedb, &node);
13233 if (version != NULL)
13234 dns_db_closeversion(zonedb, &version, ISC_FALSE);
13235 if (zonedb != NULL)
13236 dns_db_detach(&zonedb);
13237 if (tempname != NULL)
13238 dns_message_puttempname(message, &tempname);
13239 if (temprdata != NULL)
13240 dns_message_puttemprdata(message, &temprdata);
13241 if (temprdataset != NULL)
13242 dns_message_puttemprdataset(message, &temprdataset);
13243 if (temprdatalist != NULL)
13244 dns_message_puttemprdatalist(message, &temprdatalist);
13245
13246 done:
13247 *messagep = message;
13248 return (ISC_R_SUCCESS);
13249
13250 cleanup:
13251 if (tempname != NULL)
13252 dns_message_puttempname(message, &tempname);
13253 if (temprdataset != NULL)
13254 dns_message_puttemprdataset(message, &temprdataset);
13255 dns_message_destroy(&message);
13256 return (result);
13257 }
13258
13259 isc_result_t
13260 dns_zone_notifyreceive(dns_zone_t *zone, isc_sockaddr_t *from,
13261 dns_message_t *msg)
13262 {
13263 return (dns_zone_notifyreceive2(zone, from, NULL, msg));
13264 }
13265
13266 isc_result_t
13267 dns_zone_notifyreceive2(dns_zone_t *zone, isc_sockaddr_t *from,
13268 isc_sockaddr_t *to, dns_message_t *msg)
13269 {
13270 unsigned int i;
13271 dns_rdata_soa_t soa;
13272 dns_rdataset_t *rdataset = NULL;
13273 dns_rdata_t rdata = DNS_RDATA_INIT;
13274 isc_result_t result;
13275 char fromtext[ISC_SOCKADDR_FORMATSIZE];
13276 int match = 0;
13277 isc_netaddr_t netaddr;
13278 isc_uint32_t serial = 0;
13279 isc_boolean_t have_serial = ISC_FALSE;
13280 dns_tsigkey_t *tsigkey;
13281 dns_name_t *tsig;
13282
13283 REQUIRE(DNS_ZONE_VALID(zone));
13284
13285 /*
13286 * If type != T_SOA return DNS_R_NOTIMP. We don't yet support
13287 * ROLLOVER.
13288 *
13289 * SOA: RFC1996
13290 * Check that 'from' is a valid notify source, (zone->masters).
13291 * Return DNS_R_REFUSED if not.
13292 *
13293 * If the notify message contains a serial number check it
13294 * against the zones serial and return if <= current serial
13295 *
13296 * If a refresh check is progress, if so just record the
13297 * fact we received a NOTIFY and from where and return.
13298 * We will perform a new refresh check when the current one
13299 * completes. Return ISC_R_SUCCESS.
13300 *
13301 * Otherwise initiate a refresh check using 'from' as the
13302 * first address to check. Return ISC_R_SUCCESS.
13303 */
13304
13305 isc_sockaddr_format(from, fromtext, sizeof(fromtext));
13306
13307 /*
13308 * Notify messages are processed by the raw zone.
13309 */
13310 LOCK_ZONE(zone);
13311 INSIST(zone != zone->raw);
13312 if (inline_secure(zone)) {
13313 result = dns_zone_notifyreceive2(zone->raw, from, to, msg);
13314 UNLOCK_ZONE(zone);
13315 return (result);
13316 }
13317 /*
13318 * We only handle NOTIFY (SOA) at the present.
13319 */
13320 if (isc_sockaddr_pf(from) == PF_INET)
13321 inc_stats(zone, dns_zonestatscounter_notifyinv4);
13322 else
13323 inc_stats(zone, dns_zonestatscounter_notifyinv6);
13324 if (msg->counts[DNS_SECTION_QUESTION] == 0 ||
13325 dns_message_findname(msg, DNS_SECTION_QUESTION, &zone->origin,
13326 dns_rdatatype_soa, dns_rdatatype_none,
13327 NULL, NULL) != ISC_R_SUCCESS) {
13328 UNLOCK_ZONE(zone);
13329 if (msg->counts[DNS_SECTION_QUESTION] == 0) {
13330 dns_zone_log(zone, ISC_LOG_NOTICE,
13331 "NOTIFY with no "
13332 "question section from: %s", fromtext);
13333 return (DNS_R_FORMERR);
13334 }
13335 dns_zone_log(zone, ISC_LOG_NOTICE,
13336 "NOTIFY zone does not match");
13337 return (DNS_R_NOTIMP);
13338 }
13339
13340 /*
13341 * If we are a master zone just succeed.
13342 */
13343 if (zone->type == dns_zone_master) {
13344 UNLOCK_ZONE(zone);
13345 return (ISC_R_SUCCESS);
13346 }
13347
13348 isc_netaddr_fromsockaddr(&netaddr, from);
13349 for (i = 0; i < zone->masterscnt; i++) {
13350 if (isc_sockaddr_eqaddr(from, &zone->masters[i]))
13351 break;
13352 if (zone->view->aclenv.match_mapped &&
13353 IN6_IS_ADDR_V4MAPPED(&from->type.sin6.sin6_addr) &&
13354 isc_sockaddr_pf(&zone->masters[i]) == AF_INET) {
13355 isc_netaddr_t na1, na2;
13356 isc_netaddr_fromv4mapped(&na1, &netaddr);
13357 isc_netaddr_fromsockaddr(&na2, &zone->masters[i]);
13358 if (isc_netaddr_equal(&na1, &na2))
13359 break;
13360 }
13361 }
13362
13363 /*
13364 * Accept notify requests from non masters if they are on
13365 * 'zone->notify_acl'.
13366 */
13367 tsigkey = dns_message_gettsigkey(msg);
13368 tsig = dns_tsigkey_identity(tsigkey);
13369 if (i >= zone->masterscnt && zone->notify_acl != NULL &&
13370 dns_acl_match(&netaddr, tsig, zone->notify_acl,
13371 &zone->view->aclenv,
13372 &match, NULL) == ISC_R_SUCCESS &&
13373 match > 0)
13374 {
13375 /* Accept notify. */
13376 } else if (i >= zone->masterscnt) {
13377 UNLOCK_ZONE(zone);
13378 dns_zone_log(zone, ISC_LOG_INFO,
13379 "refused notify from non-master: %s", fromtext);
13380 inc_stats(zone, dns_zonestatscounter_notifyrej);
13381 return (DNS_R_REFUSED);
13382 }
13383
13384 /*
13385 * If the zone is loaded and there are answers check the serial
13386 * to see if we need to do a refresh. Do not worry about this
13387 * check if we are a dialup zone as we use the notify request
13388 * to trigger a refresh check.
13389 */
13390 if (msg->counts[DNS_SECTION_ANSWER] > 0 &&
13391 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
13392 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOREFRESH)) {
13393 result = dns_message_findname(msg, DNS_SECTION_ANSWER,
13394 &zone->origin,
13395 dns_rdatatype_soa,
13396 dns_rdatatype_none, NULL,
13397 &rdataset);
13398 if (result == ISC_R_SUCCESS)
13399 result = dns_rdataset_first(rdataset);
13400 if (result == ISC_R_SUCCESS) {
13401 isc_uint32_t oldserial;
13402 unsigned int soacount;
13403
13404 dns_rdataset_current(rdataset, &rdata);
13405 result = dns_rdata_tostruct(&rdata, &soa, NULL);
13406 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13407 serial = soa.serial;
13408 have_serial = ISC_TRUE;
13409 /*
13410 * The following should safely be performed without DB
13411 * lock and succeed in this context.
13412 */
13413 result = zone_get_from_db(zone, zone->db, NULL,
13414 &soacount, &oldserial, NULL,
13415 NULL, NULL, NULL, NULL);
13416 RUNTIME_CHECK(result == ISC_R_SUCCESS);
13417 RUNTIME_CHECK(soacount > 0U);
13418 if (isc_serial_le(serial, oldserial)) {
13419 dns_zone_log(zone,
13420 ISC_LOG_INFO,
13421 "notify from %s: "
13422 "zone is up to date",
13423 fromtext);
13424 UNLOCK_ZONE(zone);
13425 return (ISC_R_SUCCESS);
13426 }
13427 }
13428 }
13429
13430 /*
13431 * If we got this far and there was a refresh in progress just
13432 * let it complete. Record where we got the notify from so we
13433 * can perform a refresh check when the current one completes
13434 */
13435 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH)) {
13436 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
13437 zone->notifyfrom = *from;
13438 UNLOCK_ZONE(zone);
13439 if (have_serial)
13440 dns_zone_log(zone, ISC_LOG_INFO,
13441 "notify from %s: serial %u: refresh in "
13442 "progress, refresh check queued",
13443 fromtext, serial);
13444 else
13445 dns_zone_log(zone, ISC_LOG_INFO,
13446 "notify from %s: refresh in progress, "
13447 "refresh check queued", fromtext);
13448 return (ISC_R_SUCCESS);
13449 }
13450 if (have_serial)
13451 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: serial %u",
13452 fromtext, serial);
13453 else
13454 dns_zone_log(zone, ISC_LOG_INFO, "notify from %s: no serial",
13455 fromtext);
13456 zone->notifyfrom = *from;
13457 UNLOCK_ZONE(zone);
13458
13459 if (to != NULL) {
13460 dns_zonemgr_unreachabledel(zone->zmgr, from, to);
13461 }
13462 dns_zone_refresh(zone);
13463 return (ISC_R_SUCCESS);
13464 }
13465
13466 void
13467 dns_zone_setnotifyacl(dns_zone_t *zone, dns_acl_t *acl) {
13468
13469 REQUIRE(DNS_ZONE_VALID(zone));
13470
13471 LOCK_ZONE(zone);
13472 if (zone->notify_acl != NULL)
13473 dns_acl_detach(&zone->notify_acl);
13474 dns_acl_attach(acl, &zone->notify_acl);
13475 UNLOCK_ZONE(zone);
13476 }
13477
13478 void
13479 dns_zone_setqueryacl(dns_zone_t *zone, dns_acl_t *acl) {
13480
13481 REQUIRE(DNS_ZONE_VALID(zone));
13482
13483 LOCK_ZONE(zone);
13484 if (zone->query_acl != NULL)
13485 dns_acl_detach(&zone->query_acl);
13486 dns_acl_attach(acl, &zone->query_acl);
13487 UNLOCK_ZONE(zone);
13488 }
13489
13490 void
13491 dns_zone_setqueryonacl(dns_zone_t *zone, dns_acl_t *acl) {
13492
13493 REQUIRE(DNS_ZONE_VALID(zone));
13494
13495 LOCK_ZONE(zone);
13496 if (zone->queryon_acl != NULL)
13497 dns_acl_detach(&zone->queryon_acl);
13498 dns_acl_attach(acl, &zone->queryon_acl);
13499 UNLOCK_ZONE(zone);
13500 }
13501
13502 void
13503 dns_zone_setupdateacl(dns_zone_t *zone, dns_acl_t *acl) {
13504
13505 REQUIRE(DNS_ZONE_VALID(zone));
13506
13507 LOCK_ZONE(zone);
13508 if (zone->update_acl != NULL)
13509 dns_acl_detach(&zone->update_acl);
13510 dns_acl_attach(acl, &zone->update_acl);
13511 UNLOCK_ZONE(zone);
13512 }
13513
13514 void
13515 dns_zone_setforwardacl(dns_zone_t *zone, dns_acl_t *acl) {
13516
13517 REQUIRE(DNS_ZONE_VALID(zone));
13518
13519 LOCK_ZONE(zone);
13520 if (zone->forward_acl != NULL)
13521 dns_acl_detach(&zone->forward_acl);
13522 dns_acl_attach(acl, &zone->forward_acl);
13523 UNLOCK_ZONE(zone);
13524 }
13525
13526 void
13527 dns_zone_setxfracl(dns_zone_t *zone, dns_acl_t *acl) {
13528
13529 REQUIRE(DNS_ZONE_VALID(zone));
13530
13531 LOCK_ZONE(zone);
13532 if (zone->xfr_acl != NULL)
13533 dns_acl_detach(&zone->xfr_acl);
13534 dns_acl_attach(acl, &zone->xfr_acl);
13535 UNLOCK_ZONE(zone);
13536 }
13537
13538 dns_acl_t *
13539 dns_zone_getnotifyacl(dns_zone_t *zone) {
13540
13541 REQUIRE(DNS_ZONE_VALID(zone));
13542
13543 return (zone->notify_acl);
13544 }
13545
13546 dns_acl_t *
13547 dns_zone_getqueryacl(dns_zone_t *zone) {
13548
13549 REQUIRE(DNS_ZONE_VALID(zone));
13550
13551 return (zone->query_acl);
13552 }
13553
13554 dns_acl_t *
13555 dns_zone_getqueryonacl(dns_zone_t *zone) {
13556
13557 REQUIRE(DNS_ZONE_VALID(zone));
13558
13559 return (zone->queryon_acl);
13560 }
13561
13562 dns_acl_t *
13563 dns_zone_getupdateacl(dns_zone_t *zone) {
13564
13565 REQUIRE(DNS_ZONE_VALID(zone));
13566
13567 return (zone->update_acl);
13568 }
13569
13570 dns_acl_t *
13571 dns_zone_getforwardacl(dns_zone_t *zone) {
13572
13573 REQUIRE(DNS_ZONE_VALID(zone));
13574
13575 return (zone->forward_acl);
13576 }
13577
13578 dns_acl_t *
13579 dns_zone_getxfracl(dns_zone_t *zone) {
13580
13581 REQUIRE(DNS_ZONE_VALID(zone));
13582
13583 return (zone->xfr_acl);
13584 }
13585
13586 void
13587 dns_zone_clearupdateacl(dns_zone_t *zone) {
13588
13589 REQUIRE(DNS_ZONE_VALID(zone));
13590
13591 LOCK_ZONE(zone);
13592 if (zone->update_acl != NULL)
13593 dns_acl_detach(&zone->update_acl);
13594 UNLOCK_ZONE(zone);
13595 }
13596
13597 void
13598 dns_zone_clearforwardacl(dns_zone_t *zone) {
13599
13600 REQUIRE(DNS_ZONE_VALID(zone));
13601
13602 LOCK_ZONE(zone);
13603 if (zone->forward_acl != NULL)
13604 dns_acl_detach(&zone->forward_acl);
13605 UNLOCK_ZONE(zone);
13606 }
13607
13608 void
13609 dns_zone_clearnotifyacl(dns_zone_t *zone) {
13610
13611 REQUIRE(DNS_ZONE_VALID(zone));
13612
13613 LOCK_ZONE(zone);
13614 if (zone->notify_acl != NULL)
13615 dns_acl_detach(&zone->notify_acl);
13616 UNLOCK_ZONE(zone);
13617 }
13618
13619 void
13620 dns_zone_clearqueryacl(dns_zone_t *zone) {
13621
13622 REQUIRE(DNS_ZONE_VALID(zone));
13623
13624 LOCK_ZONE(zone);
13625 if (zone->query_acl != NULL)
13626 dns_acl_detach(&zone->query_acl);
13627 UNLOCK_ZONE(zone);
13628 }
13629
13630 void
13631 dns_zone_clearqueryonacl(dns_zone_t *zone) {
13632
13633 REQUIRE(DNS_ZONE_VALID(zone));
13634
13635 LOCK_ZONE(zone);
13636 if (zone->queryon_acl != NULL)
13637 dns_acl_detach(&zone->queryon_acl);
13638 UNLOCK_ZONE(zone);
13639 }
13640
13641 void
13642 dns_zone_clearxfracl(dns_zone_t *zone) {
13643
13644 REQUIRE(DNS_ZONE_VALID(zone));
13645
13646 LOCK_ZONE(zone);
13647 if (zone->xfr_acl != NULL)
13648 dns_acl_detach(&zone->xfr_acl);
13649 UNLOCK_ZONE(zone);
13650 }
13651
13652 isc_boolean_t
13653 dns_zone_getupdatedisabled(dns_zone_t *zone) {
13654 REQUIRE(DNS_ZONE_VALID(zone));
13655 return (zone->update_disabled);
13656
13657 }
13658
13659 void
13660 dns_zone_setupdatedisabled(dns_zone_t *zone, isc_boolean_t state) {
13661 REQUIRE(DNS_ZONE_VALID(zone));
13662 zone->update_disabled = state;
13663 }
13664
13665 isc_boolean_t
13666 dns_zone_getzeronosoattl(dns_zone_t *zone) {
13667 REQUIRE(DNS_ZONE_VALID(zone));
13668 return (zone->zero_no_soa_ttl);
13669
13670 }
13671
13672 void
13673 dns_zone_setzeronosoattl(dns_zone_t *zone, isc_boolean_t state) {
13674 REQUIRE(DNS_ZONE_VALID(zone));
13675 zone->zero_no_soa_ttl = state;
13676 }
13677
13678 void
13679 dns_zone_setchecknames(dns_zone_t *zone, dns_severity_t severity) {
13680 REQUIRE(DNS_ZONE_VALID(zone));
13681
13682 zone->check_names = severity;
13683 }
13684
13685 dns_severity_t
13686 dns_zone_getchecknames(dns_zone_t *zone) {
13687 REQUIRE(DNS_ZONE_VALID(zone));
13688
13689 return (zone->check_names);
13690 }
13691
13692 void
13693 dns_zone_setjournalsize(dns_zone_t *zone, isc_int32_t size) {
13694 REQUIRE(DNS_ZONE_VALID(zone));
13695
13696 zone->journalsize = size;
13697 }
13698
13699 isc_int32_t
13700 dns_zone_getjournalsize(dns_zone_t *zone) {
13701 REQUIRE(DNS_ZONE_VALID(zone));
13702
13703 return (zone->journalsize);
13704 }
13705
13706 static void
13707 zone_namerd_tostr(dns_zone_t *zone, char *buf, size_t length) {
13708 isc_result_t result = ISC_R_FAILURE;
13709 isc_buffer_t buffer;
13710
13711 REQUIRE(buf != NULL);
13712 REQUIRE(length > 1U);
13713
13714 /*
13715 * Leave space for terminating '\0'.
13716 */
13717 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13718 if (zone->type != dns_zone_redirect && zone->type != dns_zone_key) {
13719 if (dns_name_dynamic(&zone->origin))
13720 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
13721 if (result != ISC_R_SUCCESS &&
13722 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
13723 isc_buffer_putstr(&buffer, "<UNKNOWN>");
13724
13725 if (isc_buffer_availablelength(&buffer) > 0)
13726 isc_buffer_putstr(&buffer, "/");
13727 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
13728 }
13729
13730 if (zone->view != NULL && strcmp(zone->view->name, "_bind") != 0 &&
13731 strcmp(zone->view->name, "_default") != 0 &&
13732 strlen(zone->view->name) < isc_buffer_availablelength(&buffer)) {
13733 isc_buffer_putstr(&buffer, "/");
13734 isc_buffer_putstr(&buffer, zone->view->name);
13735 }
13736 if (inline_secure(zone) && 9U < isc_buffer_availablelength(&buffer))
13737 isc_buffer_putstr(&buffer, " (signed)");
13738 if (inline_raw(zone) && 11U < isc_buffer_availablelength(&buffer))
13739 isc_buffer_putstr(&buffer, " (unsigned)");
13740
13741 buf[isc_buffer_usedlength(&buffer)] = '\0';
13742 }
13743
13744 static void
13745 zone_name_tostr(dns_zone_t *zone, char *buf, size_t length) {
13746 isc_result_t result = ISC_R_FAILURE;
13747 isc_buffer_t buffer;
13748
13749 REQUIRE(buf != NULL);
13750 REQUIRE(length > 1U);
13751
13752 /*
13753 * Leave space for terminating '\0'.
13754 */
13755 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13756 if (dns_name_dynamic(&zone->origin))
13757 result = dns_name_totext(&zone->origin, ISC_TRUE, &buffer);
13758 if (result != ISC_R_SUCCESS &&
13759 isc_buffer_availablelength(&buffer) >= (sizeof("<UNKNOWN>") - 1))
13760 isc_buffer_putstr(&buffer, "<UNKNOWN>");
13761
13762 buf[isc_buffer_usedlength(&buffer)] = '\0';
13763 }
13764
13765 static void
13766 zone_rdclass_tostr(dns_zone_t *zone, char *buf, size_t length) {
13767 isc_buffer_t buffer;
13768
13769 REQUIRE(buf != NULL);
13770 REQUIRE(length > 1U);
13771
13772 /*
13773 * Leave space for terminating '\0'.
13774 */
13775 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13776 (void)dns_rdataclass_totext(zone->rdclass, &buffer);
13777
13778 buf[isc_buffer_usedlength(&buffer)] = '\0';
13779 }
13780
13781 static void
13782 zone_viewname_tostr(dns_zone_t *zone, char *buf, size_t length) {
13783 isc_buffer_t buffer;
13784
13785 REQUIRE(buf != NULL);
13786 REQUIRE(length > 1U);
13787
13788
13789 /*
13790 * Leave space for terminating '\0'.
13791 */
13792 isc_buffer_init(&buffer, buf, (unsigned int)length - 1);
13793
13794 if (zone->view == NULL) {
13795 isc_buffer_putstr(&buffer, "_none");
13796 } else if (strlen(zone->view->name)
13797 < isc_buffer_availablelength(&buffer)) {
13798 isc_buffer_putstr(&buffer, zone->view->name);
13799 } else {
13800 isc_buffer_putstr(&buffer, "_toolong");
13801 }
13802
13803 buf[isc_buffer_usedlength(&buffer)] = '\0';
13804 }
13805
13806 void
13807 dns_zone_name(dns_zone_t *zone, char *buf, size_t length) {
13808 REQUIRE(DNS_ZONE_VALID(zone));
13809 REQUIRE(buf != NULL);
13810 zone_namerd_tostr(zone, buf, length);
13811 }
13812
13813 void
13814 dns_zone_nameonly(dns_zone_t *zone, char *buf, size_t length) {
13815 REQUIRE(DNS_ZONE_VALID(zone));
13816 REQUIRE(buf != NULL);
13817 zone_name_tostr(zone, buf, length);
13818 }
13819
13820 void
13821 dns_zone_logv(dns_zone_t *zone, isc_logcategory_t *category, int level,
13822 const char *prefix, const char *fmt, va_list ap)
13823 {
13824 char message[4096];
13825 const char *zstr;
13826
13827 if (!isc_log_wouldlog(dns_lctx, level)) {
13828 return;
13829 }
13830
13831 vsnprintf(message, sizeof(message), fmt, ap);
13832
13833 switch (zone->type) {
13834 case dns_zone_key:
13835 zstr = "managed-keys-zone";
13836 break;
13837 case dns_zone_redirect:
13838 zstr = "redirect-zone";
13839 break;
13840 default:
13841 zstr = "zone ";
13842 }
13843
13844 isc_log_write(dns_lctx, category, DNS_LOGMODULE_ZONE, level,
13845 "%s%s%s%s: %s",
13846 (prefix != NULL ? prefix : ""),
13847 (prefix != NULL ? ": " : ""),
13848 zstr, zone->strnamerd, message);
13849 }
13850
13851 static void
13852 notify_log(dns_zone_t *zone, int level, const char *fmt, ...) {
13853 va_list ap;
13854
13855 va_start(ap, fmt);
13856 dns_zone_logv(zone, DNS_LOGCATEGORY_NOTIFY, level, NULL, fmt, ap);
13857 va_end(ap);
13858 }
13859
13860 void
13861 dns_zone_logc(dns_zone_t *zone, isc_logcategory_t *category,
13862 int level, const char *fmt, ...)
13863 {
13864 va_list ap;
13865
13866 va_start(ap, fmt);
13867 dns_zone_logv(zone, category, level, NULL, fmt, ap);
13868 va_end(ap);
13869 }
13870
13871 void
13872 dns_zone_log(dns_zone_t *zone, int level, const char *fmt, ...) {
13873 va_list ap;
13874
13875 va_start(ap, fmt);
13876 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, NULL, fmt, ap);
13877 va_end(ap);
13878 }
13879
13880 static void
13881 zone_debuglog(dns_zone_t *zone, const char *me, int debuglevel,
13882 const char *fmt, ...)
13883 {
13884 int level = ISC_LOG_DEBUG(debuglevel);
13885 va_list ap;
13886
13887 va_start(ap, fmt);
13888 dns_zone_logv(zone, DNS_LOGCATEGORY_GENERAL, level, me, fmt, ap);
13889 va_end(ap);
13890 }
13891
13892 static int
13893 message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type)
13894 {
13895 isc_result_t result;
13896 dns_name_t *name;
13897 dns_rdataset_t *curr;
13898 int count = 0;
13899
13900 result = dns_message_firstname(msg, section);
13901 while (result == ISC_R_SUCCESS) {
13902 name = NULL;
13903 dns_message_currentname(msg, section, &name);
13904
13905 for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
13906 curr = ISC_LIST_PREV(curr, link)) {
13907 if (curr->type == type)
13908 count++;
13909 }
13910 result = dns_message_nextname(msg, section);
13911 }
13912
13913 return (count);
13914 }
13915
13916 void
13917 dns_zone_setmaxxfrin(dns_zone_t *zone, isc_uint32_t maxxfrin) {
13918 REQUIRE(DNS_ZONE_VALID(zone));
13919
13920 zone->maxxfrin = maxxfrin;
13921 }
13922
13923 isc_uint32_t
13924 dns_zone_getmaxxfrin(dns_zone_t *zone) {
13925 REQUIRE(DNS_ZONE_VALID(zone));
13926
13927 return (zone->maxxfrin);
13928 }
13929
13930 void
13931 dns_zone_setmaxxfrout(dns_zone_t *zone, isc_uint32_t maxxfrout) {
13932 REQUIRE(DNS_ZONE_VALID(zone));
13933 zone->maxxfrout = maxxfrout;
13934 }
13935
13936 isc_uint32_t
13937 dns_zone_getmaxxfrout(dns_zone_t *zone) {
13938 REQUIRE(DNS_ZONE_VALID(zone));
13939
13940 return (zone->maxxfrout);
13941 }
13942
13943 dns_zonetype_t
13944 dns_zone_gettype(dns_zone_t *zone) {
13945 REQUIRE(DNS_ZONE_VALID(zone));
13946
13947 return (zone->type);
13948 }
13949
13950 dns_zonetype_t
13951 dns_zone_getredirecttype(dns_zone_t *zone) {
13952 REQUIRE(DNS_ZONE_VALID(zone));
13953 REQUIRE(zone->type == dns_zone_redirect);
13954
13955 return (zone->masters == NULL ? dns_zone_master : dns_zone_slave);
13956 }
13957
13958 dns_name_t *
13959 dns_zone_getorigin(dns_zone_t *zone) {
13960 REQUIRE(DNS_ZONE_VALID(zone));
13961
13962 return (&zone->origin);
13963 }
13964
13965 void
13966 dns_zone_settask(dns_zone_t *zone, isc_task_t *task) {
13967 REQUIRE(DNS_ZONE_VALID(zone));
13968
13969 LOCK_ZONE(zone);
13970 if (zone->task != NULL)
13971 isc_task_detach(&zone->task);
13972 isc_task_attach(task, &zone->task);
13973 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
13974 if (zone->db != NULL)
13975 dns_db_settask(zone->db, zone->task);
13976 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
13977 UNLOCK_ZONE(zone);
13978 }
13979
13980 void
13981 dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) {
13982 REQUIRE(DNS_ZONE_VALID(zone));
13983 isc_task_attach(zone->task, target);
13984 }
13985
13986 void
13987 dns_zone_setidlein(dns_zone_t *zone, isc_uint32_t idlein) {
13988 REQUIRE(DNS_ZONE_VALID(zone));
13989
13990 if (idlein == 0)
13991 idlein = DNS_DEFAULT_IDLEIN;
13992 zone->idlein = idlein;
13993 }
13994
13995 isc_uint32_t
13996 dns_zone_getidlein(dns_zone_t *zone) {
13997 REQUIRE(DNS_ZONE_VALID(zone));
13998
13999 return (zone->idlein);
14000 }
14001
14002 void
14003 dns_zone_setidleout(dns_zone_t *zone, isc_uint32_t idleout) {
14004 REQUIRE(DNS_ZONE_VALID(zone));
14005
14006 zone->idleout = idleout;
14007 }
14008
14009 isc_uint32_t
14010 dns_zone_getidleout(dns_zone_t *zone) {
14011 REQUIRE(DNS_ZONE_VALID(zone));
14012
14013 return (zone->idleout);
14014 }
14015
14016 static void
14017 notify_done(isc_task_t *task, isc_event_t *event) {
14018 dns_requestevent_t *revent = (dns_requestevent_t *)event;
14019 dns_notify_t *notify;
14020 isc_result_t result;
14021 dns_message_t *message = NULL;
14022 isc_buffer_t buf;
14023 char rcode[128];
14024 char addrbuf[ISC_SOCKADDR_FORMATSIZE];
14025
14026 UNUSED(task);
14027
14028 notify = event->ev_arg;
14029 REQUIRE(DNS_NOTIFY_VALID(notify));
14030 INSIST(task == notify->zone->task);
14031
14032 isc_buffer_init(&buf, rcode, sizeof(rcode));
14033 isc_sockaddr_format(¬ify->dst, addrbuf, sizeof(addrbuf));
14034
14035 result = revent->result;
14036 if (result == ISC_R_SUCCESS)
14037 result = dns_message_create(notify->zone->mctx,
14038 DNS_MESSAGE_INTENTPARSE, &message);
14039 if (result == ISC_R_SUCCESS)
14040 result = dns_request_getresponse(revent->request, message,
14041 DNS_MESSAGEPARSE_PRESERVEORDER);
14042 if (result == ISC_R_SUCCESS)
14043 result = dns_rcode_totext(message->rcode, &buf);
14044 if (result == ISC_R_SUCCESS)
14045 notify_log(notify->zone, ISC_LOG_DEBUG(3),
14046 "notify response from %s: %.*s",
14047 addrbuf, (int)buf.used, rcode);
14048 else
14049 notify_log(notify->zone, ISC_LOG_DEBUG(2),
14050 "notify to %s failed: %s", addrbuf,
14051 dns_result_totext(result));
14052
14053 /*
14054 * Old bind's return formerr if they see a soa record. Retry w/o
14055 * the soa if we see a formerr and had sent a SOA.
14056 */
14057 isc_event_free(&event);
14058 if (message != NULL && message->rcode == dns_rcode_formerr &&
14059 (notify->flags & DNS_NOTIFY_NOSOA) == 0) {
14060 isc_boolean_t startup;
14061
14062 notify->flags |= DNS_NOTIFY_NOSOA;
14063 dns_request_destroy(¬ify->request);
14064 startup = ISC_TF((notify->flags & DNS_NOTIFY_STARTUP) != 0);
14065 result = notify_send_queue(notify, startup);
14066 if (result != ISC_R_SUCCESS)
14067 notify_destroy(notify, ISC_FALSE);
14068 } else {
14069 if (result == ISC_R_TIMEDOUT)
14070 notify_log(notify->zone, ISC_LOG_DEBUG(1),
14071 "notify to %s: retries exceeded", addrbuf);
14072 notify_destroy(notify, ISC_FALSE);
14073 }
14074 if (message != NULL)
14075 dns_message_destroy(&message);
14076 }
14077
14078 struct secure_event {
14079 isc_event_t e;
14080 dns_db_t *db;
14081 isc_uint32_t serial;
14082 };
14083
14084 static void
14085 update_log_cb(void *arg, dns_zone_t *zone, int level, const char *message) {
14086 UNUSED(arg);
14087 dns_zone_log(zone, level, "%s", message);
14088 }
14089
14090 static isc_result_t
14091 sync_secure_journal(dns_zone_t *zone, dns_zone_t *raw, dns_journal_t *journal,
14092 isc_uint32_t start, isc_uint32_t end,
14093 dns_difftuple_t **soatuplep, dns_diff_t *diff)
14094 {
14095 isc_result_t result;
14096 dns_difftuple_t *tuple = NULL;
14097 dns_diffop_t op = DNS_DIFFOP_ADD;
14098 int n_soa = 0;
14099
14100 REQUIRE(soatuplep != NULL);
14101
14102 if (start == end)
14103 return (DNS_R_UNCHANGED);
14104
14105 CHECK(dns_journal_iter_init(journal, start, end));
14106 for (result = dns_journal_first_rr(journal);
14107 result == ISC_R_SUCCESS;
14108 result = dns_journal_next_rr(journal))
14109 {
14110 dns_name_t *name = NULL;
14111 isc_uint32_t ttl;
14112 dns_rdata_t *rdata = NULL;
14113 dns_journal_current_rr(journal, &name, &ttl, &rdata);
14114
14115 if (rdata->type == dns_rdatatype_soa) {
14116 n_soa++;
14117 if (n_soa == 2) {
14118 /*
14119 * Save the latest raw SOA record.
14120 */
14121 if (*soatuplep != NULL)
14122 dns_difftuple_free(soatuplep);
14123 CHECK(dns_difftuple_create(diff->mctx,
14124 DNS_DIFFOP_ADD,
14125 name, ttl, rdata,
14126 soatuplep));
14127 }
14128 if (n_soa == 3)
14129 n_soa = 1;
14130 continue;
14131 }
14132
14133 /* Sanity. */
14134 if (n_soa == 0) {
14135 dns_zone_log(raw, ISC_LOG_ERROR,
14136 "corrupt journal file: '%s'\n",
14137 raw->journal);
14138 return (ISC_R_FAILURE);
14139 }
14140
14141 if (zone->privatetype != 0 &&
14142 rdata->type == zone->privatetype)
14143 continue;
14144
14145 if (rdata->type == dns_rdatatype_nsec ||
14146 rdata->type == dns_rdatatype_rrsig ||
14147 rdata->type == dns_rdatatype_nsec3 ||
14148 rdata->type == dns_rdatatype_dnskey ||
14149 rdata->type == dns_rdatatype_nsec3param)
14150 continue;
14151
14152 op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
14153
14154 CHECK(dns_difftuple_create(diff->mctx, op, name, ttl, rdata,
14155 &tuple));
14156 dns_diff_appendminimal(diff, &tuple);
14157 }
14158 if (result == ISC_R_NOMORE)
14159 result = ISC_R_SUCCESS;
14160
14161 failure:
14162 return(result);
14163 }
14164
14165 static isc_result_t
14166 sync_secure_db(dns_zone_t *seczone, dns_zone_t *raw, dns_db_t *secdb,
14167 dns_dbversion_t *secver, dns_difftuple_t **soatuple,
14168 dns_diff_t *diff)
14169 {
14170 isc_result_t result;
14171 dns_db_t *rawdb = NULL;
14172 dns_dbversion_t *rawver = NULL;
14173 dns_difftuple_t *tuple = NULL, *next;
14174 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
14175 dns_rdata_soa_t oldsoa, newsoa;
14176
14177 REQUIRE(DNS_ZONE_VALID(seczone));
14178 REQUIRE(soatuple != NULL && *soatuple == NULL);
14179
14180 if (!seczone->sourceserialset)
14181 return (DNS_R_UNCHANGED);
14182
14183 dns_db_attach(raw->db, &rawdb);
14184 dns_db_currentversion(rawdb, &rawver);
14185 result = dns_db_diffx(diff, rawdb, rawver, secdb, secver, NULL);
14186 dns_db_closeversion(rawdb, &rawver, ISC_FALSE);
14187 dns_db_detach(&rawdb);
14188
14189 if (result != ISC_R_SUCCESS)
14190 return (result);
14191
14192 for (tuple = ISC_LIST_HEAD(diff->tuples);
14193 tuple != NULL;
14194 tuple = next)
14195 {
14196 next = ISC_LIST_NEXT(tuple, link);
14197 if (tuple->rdata.type == dns_rdatatype_nsec ||
14198 tuple->rdata.type == dns_rdatatype_rrsig ||
14199 tuple->rdata.type == dns_rdatatype_dnskey ||
14200 tuple->rdata.type == dns_rdatatype_nsec3 ||
14201 tuple->rdata.type == dns_rdatatype_nsec3param)
14202 {
14203 ISC_LIST_UNLINK(diff->tuples, tuple, link);
14204 dns_difftuple_free(&tuple);
14205 continue;
14206 }
14207 if (tuple->rdata.type == dns_rdatatype_soa) {
14208 if (tuple->op == DNS_DIFFOP_DEL) {
14209 INSIST(oldtuple == NULL);
14210 oldtuple = tuple;
14211 }
14212 if (tuple->op == DNS_DIFFOP_ADD) {
14213 INSIST(newtuple == NULL);
14214 newtuple = tuple;
14215 }
14216 }
14217 }
14218
14219 if (oldtuple != NULL && newtuple != NULL) {
14220
14221 result = dns_rdata_tostruct(&oldtuple->rdata, &oldsoa, NULL);
14222 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14223
14224 result = dns_rdata_tostruct(&newtuple->rdata, &newsoa, NULL);
14225 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14226
14227 /*
14228 * If the SOA records are the same except for the serial
14229 * remove them from the diff.
14230 */
14231 if (oldsoa.refresh == newsoa.refresh &&
14232 oldsoa.retry == newsoa.retry &&
14233 oldsoa.minimum == newsoa.minimum &&
14234 oldsoa.expire == newsoa.expire &&
14235 dns_name_equal(&oldsoa.origin, &newsoa.origin) &&
14236 dns_name_equal(&oldsoa.contact, &newsoa.contact)) {
14237 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14238 dns_difftuple_free(&oldtuple);
14239 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14240 dns_difftuple_free(&newtuple);
14241 }
14242 }
14243
14244 if (ISC_LIST_EMPTY(diff->tuples))
14245 return (DNS_R_UNCHANGED);
14246
14247 /*
14248 * If there are still SOA records in the diff they can now be removed
14249 * saving the new SOA record.
14250 */
14251 if (oldtuple != NULL) {
14252 ISC_LIST_UNLINK(diff->tuples, oldtuple, link);
14253 dns_difftuple_free(&oldtuple);
14254 }
14255
14256 if (newtuple != NULL) {
14257 ISC_LIST_UNLINK(diff->tuples, newtuple, link);
14258 *soatuple = newtuple;
14259 }
14260
14261 return (ISC_R_SUCCESS);
14262 }
14263
14264 static void
14265 receive_secure_serial(isc_task_t *task, isc_event_t *event) {
14266 static char me[] = "receive_secure_serial";
14267 isc_result_t result = ISC_R_SUCCESS;
14268 dns_journal_t *rjournal = NULL;
14269 dns_journal_t *sjournal = NULL;
14270 isc_uint32_t start, end;
14271 dns_zone_t *zone;
14272 dns_difftuple_t *tuple = NULL, *soatuple = NULL;
14273 dns_update_log_t log = { update_log_cb, NULL };
14274 isc_uint32_t newserial = 0, desired = 0;
14275 isc_time_t timenow;
14276
14277 UNUSED(task);
14278
14279 zone = event->ev_arg;
14280 end = ((struct secure_event *)event)->serial;
14281
14282 ENTER;
14283
14284 LOCK_ZONE(zone);
14285
14286 /*
14287 * If we are already processing a receive secure serial event
14288 * for the zone, just queue the new one and exit.
14289 */
14290 if (zone->rss_event != NULL && zone->rss_event != event) {
14291 ISC_LIST_APPEND(zone->rss_events, event, ev_link);
14292 UNLOCK_ZONE(zone);
14293 return;
14294 }
14295
14296 nextevent:
14297 if (zone->rss_event != NULL) {
14298 INSIST(zone->rss_event == event);
14299 UNLOCK_ZONE(zone);
14300 } else {
14301 zone->rss_event = event;
14302 dns_diff_init(zone->mctx, &zone->rss_diff);
14303
14304 /*
14305 * zone->db may be NULL, if the load from disk failed.
14306 */
14307 result = ISC_R_SUCCESS;
14308 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14309 if (zone->db != NULL)
14310 dns_db_attach(zone->db, &zone->rss_db);
14311 else
14312 result = ISC_R_FAILURE;
14313 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14314
14315 if (result == ISC_R_SUCCESS && zone->raw != NULL)
14316 dns_zone_attach(zone->raw, &zone->rss_raw);
14317 else
14318 result = ISC_R_FAILURE;
14319
14320 UNLOCK_ZONE(zone);
14321
14322 CHECK(result);
14323
14324 /*
14325 * We first attempt to sync the raw zone to the secure zone
14326 * by using the raw zone's journal, applying all the deltas
14327 * from the latest source-serial of the secure zone up to
14328 * the current serial number of the raw zone.
14329 *
14330 * If that fails, then we'll fall back to a direct comparison
14331 * between raw and secure zones.
14332 */
14333 CHECK(dns_journal_open(zone->rss_raw->mctx,
14334 zone->rss_raw->journal,
14335 DNS_JOURNAL_WRITE, &rjournal));
14336
14337 result = dns_journal_open(zone->mctx, zone->journal,
14338 DNS_JOURNAL_READ, &sjournal);
14339 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
14340 goto failure;
14341
14342 if (!dns_journal_get_sourceserial(rjournal, &start)) {
14343 start = dns_journal_first_serial(rjournal);
14344 dns_journal_set_sourceserial(rjournal, start);
14345 }
14346 if (sjournal != NULL) {
14347 isc_uint32_t serial;
14348 /*
14349 * We read the secure journal first, if that
14350 * exists use its value provided it is greater
14351 * that from the raw journal.
14352 */
14353 if (dns_journal_get_sourceserial(sjournal, &serial)) {
14354 if (isc_serial_gt(serial, start))
14355 start = serial;
14356 }
14357 dns_journal_destroy(&sjournal);
14358 }
14359
14360 dns_db_currentversion(zone->rss_db, &zone->rss_oldver);
14361 CHECK(dns_db_newversion(zone->rss_db, &zone->rss_newver));
14362
14363 /*
14364 * Try to apply diffs from the raw zone's journal to the secure
14365 * zone. If that fails, we recover by syncing up the databases
14366 * directly.
14367 */
14368 result = sync_secure_journal(zone, zone->rss_raw, rjournal,
14369 start, end, &soatuple,
14370 &zone->rss_diff);
14371 if (result == DNS_R_UNCHANGED)
14372 goto failure;
14373 else if (result != ISC_R_SUCCESS)
14374 CHECK(sync_secure_db(zone, zone->rss_raw, zone->rss_db,
14375 zone->rss_oldver, &soatuple,
14376 &zone->rss_diff));
14377
14378 CHECK(dns_diff_apply(&zone->rss_diff, zone->rss_db,
14379 zone->rss_newver));
14380
14381 if (soatuple != NULL) {
14382 isc_uint32_t oldserial;
14383
14384 CHECK(dns_db_createsoatuple(zone->rss_db,
14385 zone->rss_oldver,
14386 zone->rss_diff.mctx,
14387 DNS_DIFFOP_DEL, &tuple));
14388 oldserial = dns_soa_getserial(&tuple->rdata);
14389 newserial = desired =
14390 dns_soa_getserial(&soatuple->rdata);
14391 if (!isc_serial_gt(newserial, oldserial)) {
14392 newserial = oldserial + 1;
14393 if (newserial == 0)
14394 newserial++;
14395 dns_soa_setserial(newserial, &soatuple->rdata);
14396 }
14397 CHECK(do_one_tuple(&tuple, zone->rss_db,
14398 zone->rss_newver, &zone->rss_diff));
14399 CHECK(do_one_tuple(&soatuple, zone->rss_db,
14400 zone->rss_newver, &zone->rss_diff));
14401 } else
14402 CHECK(update_soa_serial(zone->rss_db, zone->rss_newver,
14403 &zone->rss_diff, zone->mctx,
14404 zone->updatemethod));
14405
14406 }
14407 result = dns_update_signaturesinc(&log, zone, zone->rss_db,
14408 zone->rss_oldver, zone->rss_newver,
14409 &zone->rss_diff,
14410 zone->sigvalidityinterval,
14411 &zone->rss_state);
14412 if (result == DNS_R_CONTINUE) {
14413 if (rjournal != NULL)
14414 dns_journal_destroy(&rjournal);
14415 isc_task_send(task, &event);
14416 fprintf(stderr, "looping on dns_update_signaturesinc\n");
14417 return;
14418 }
14419 /*
14420 * If something went wrong while trying to update the secure zone and
14421 * the latter was already signed before, do not apply raw zone deltas
14422 * to it as that would break existing DNSSEC signatures. However, if
14423 * the secure zone was not yet signed (e.g. because no signing keys
14424 * were created for it), commence applying raw zone deltas to it so
14425 * that contents of the raw zone and the secure zone are kept in sync.
14426 */
14427 if (result != ISC_R_SUCCESS && dns_db_issecure(zone->rss_db)) {
14428 goto failure;
14429 }
14430
14431 if (rjournal == NULL)
14432 CHECK(dns_journal_open(zone->rss_raw->mctx,
14433 zone->rss_raw->journal,
14434 DNS_JOURNAL_WRITE, &rjournal));
14435 CHECK(zone_journal(zone, &zone->rss_diff, &end,
14436 "receive_secure_serial"));
14437
14438 dns_journal_set_sourceserial(rjournal, end);
14439 dns_journal_commit(rjournal);
14440
14441 LOCK_ZONE(zone);
14442 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14443
14444 zone->sourceserial = end;
14445 zone->sourceserialset = ISC_TRUE;
14446 zone_needdump(zone, DNS_DUMP_DELAY);
14447
14448 TIME_NOW(&timenow);
14449 zone_settimer(zone, &timenow);
14450 UNLOCK_ZONE(zone);
14451
14452 dns_db_closeversion(zone->rss_db, &zone->rss_oldver, ISC_FALSE);
14453 dns_db_closeversion(zone->rss_db, &zone->rss_newver, ISC_TRUE);
14454
14455 if (newserial != 0) {
14456 dns_zone_log(zone, ISC_LOG_INFO, "serial %u (unsigned %u)",
14457 newserial, desired);
14458 }
14459
14460 failure:
14461 isc_event_free(&zone->rss_event);
14462 event = ISC_LIST_HEAD(zone->rss_events);
14463
14464 if (zone->rss_raw != NULL)
14465 dns_zone_detach(&zone->rss_raw);
14466 if (result != ISC_R_SUCCESS)
14467 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_serial: %s",
14468 dns_result_totext(result));
14469 if (tuple != NULL)
14470 dns_difftuple_free(&tuple);
14471 if (soatuple != NULL)
14472 dns_difftuple_free(&soatuple);
14473 if (zone->rss_db != NULL) {
14474 if (zone->rss_oldver != NULL)
14475 dns_db_closeversion(zone->rss_db, &zone->rss_oldver,
14476 ISC_FALSE);
14477 if (zone->rss_newver != NULL)
14478 dns_db_closeversion(zone->rss_db, &zone->rss_newver,
14479 ISC_FALSE);
14480 dns_db_detach(&zone->rss_db);
14481 }
14482 INSIST(zone->rss_oldver == NULL);
14483 INSIST(zone->rss_newver == NULL);
14484 if (rjournal != NULL)
14485 dns_journal_destroy(&rjournal);
14486 dns_diff_clear(&zone->rss_diff);
14487
14488 if (event != NULL) {
14489 LOCK_ZONE(zone);
14490 INSIST(zone->irefs > 1);
14491 zone->irefs--;
14492 ISC_LIST_UNLINK(zone->rss_events, event, ev_link);
14493 goto nextevent;
14494 }
14495 dns_zone_idetach(&zone);
14496 }
14497
14498 static isc_result_t
14499 zone_send_secureserial(dns_zone_t *zone, isc_uint32_t serial) {
14500 isc_event_t *e;
14501 dns_zone_t *dummy = NULL;
14502
14503 e = isc_event_allocate(zone->secure->mctx, zone,
14504 DNS_EVENT_ZONESECURESERIAL,
14505 receive_secure_serial, zone->secure,
14506 sizeof(struct secure_event));
14507 if (e == NULL)
14508 return (ISC_R_NOMEMORY);
14509 ((struct secure_event *)e)->serial = serial;
14510 INSIST(LOCKED_ZONE(zone->secure));
14511 zone_iattach(zone->secure, &dummy);
14512 isc_task_send(zone->secure->task, &e);
14513
14514 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
14515 return (ISC_R_SUCCESS);
14516 }
14517
14518 static isc_result_t
14519 checkandaddsoa(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
14520 dns_rdataset_t *rdataset, isc_uint32_t oldserial)
14521 {
14522 dns_rdata_soa_t soa;
14523 dns_rdata_t rdata = DNS_RDATA_INIT;
14524 dns_rdatalist_t temprdatalist;
14525 dns_rdataset_t temprdataset;
14526 isc_buffer_t b;
14527 isc_result_t result;
14528 unsigned char buf[DNS_SOA_BUFFERSIZE];
14529 dns_fixedname_t fixed;
14530 dns_name_t *name;
14531
14532 result = dns_rdataset_first(rdataset);
14533 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14534 dns_rdataset_current(rdataset, &rdata);
14535 result = dns_rdata_tostruct(&rdata, &soa, NULL);
14536 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14537
14538 if (isc_serial_gt(soa.serial, oldserial))
14539 return (dns_db_addrdataset(db, node, version, 0, rdataset, 0,
14540 NULL));
14541 /*
14542 * Always bump the serial.
14543 */
14544 oldserial++;
14545 if (oldserial == 0)
14546 oldserial++;
14547 soa.serial = oldserial;
14548
14549 /*
14550 * Construct a replacement rdataset.
14551 */
14552 dns_rdata_reset(&rdata);
14553 isc_buffer_init(&b, buf, sizeof(buf));
14554 result = dns_rdata_fromstruct(&rdata, rdataset->rdclass,
14555 dns_rdatatype_soa, &soa, &b);
14556 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14557 dns_rdatalist_init(&temprdatalist);
14558 temprdatalist.rdclass = rdata.rdclass;
14559 temprdatalist.type = rdata.type;
14560 temprdatalist.ttl = rdataset->ttl;
14561 ISC_LIST_APPEND(temprdatalist.rdata, &rdata, link);
14562
14563 dns_rdataset_init(&temprdataset);
14564 result = dns_rdatalist_tordataset(&temprdatalist, &temprdataset);
14565 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14566
14567 name = dns_fixedname_initname(&fixed);
14568 result = dns_db_nodefullname(db, node, name);
14569 RUNTIME_CHECK(result == ISC_R_SUCCESS);
14570 dns_rdataset_getownercase(rdataset, name);
14571 dns_rdataset_setownercase(&temprdataset, name);
14572 return (dns_db_addrdataset(db, node, version, 0, &temprdataset,
14573 0, NULL));
14574 }
14575
14576 /*
14577 * This function should populate an nsec3paramlist_t with the
14578 * nsecparam_t data from a zone.
14579 */
14580 static isc_result_t
14581 save_nsec3param(dns_zone_t *zone, nsec3paramlist_t *nsec3list) {
14582 isc_result_t result;
14583 dns_dbnode_t *node = NULL;
14584 dns_rdataset_t rdataset, prdataset;
14585 dns_dbversion_t *version = NULL;
14586 nsec3param_t *nsec3param = NULL;
14587 nsec3param_t *nsec3p = NULL;
14588 nsec3param_t *next;
14589 dns_db_t *db = NULL;
14590 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
14591
14592 REQUIRE(DNS_ZONE_VALID(zone));
14593 REQUIRE(nsec3list != NULL);
14594 REQUIRE(ISC_LIST_EMPTY(*nsec3list));
14595
14596 dns_rdataset_init(&rdataset);
14597 dns_rdataset_init(&prdataset);
14598
14599 dns_db_attach(zone->db, &db);
14600 CHECK(dns_db_getoriginnode(db, &node));
14601
14602 dns_db_currentversion(db, &version);
14603 result = dns_db_findrdataset(db, node, version,
14604 dns_rdatatype_nsec3param,
14605 dns_rdatatype_none, 0, &rdataset, NULL);
14606
14607 if (result != ISC_R_SUCCESS)
14608 goto getprivate;
14609
14610 /*
14611 * walk nsec3param rdataset making a list of parameters (note that
14612 * multiple simultaneous nsec3 chains are annoyingly legal -- this
14613 * is why we use an nsec3list, even tho we will usually only have
14614 * one)
14615 */
14616 for (result = dns_rdataset_first(&rdataset);
14617 result == ISC_R_SUCCESS;
14618 result = dns_rdataset_next(&rdataset))
14619 {
14620 dns_rdata_t rdata = DNS_RDATA_INIT;
14621 dns_rdata_t private = DNS_RDATA_INIT;
14622
14623 dns_rdataset_current(&rdataset, &rdata);
14624 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14625 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14626 "looping through nsec3param data");
14627 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
14628 if (nsec3param == NULL)
14629 CHECK(ISC_R_NOMEMORY);
14630 ISC_LINK_INIT(nsec3param, link);
14631
14632 /*
14633 * now transfer the data from the rdata to
14634 * the nsec3param
14635 */
14636 dns_nsec3param_toprivate(&rdata, &private,
14637 zone->privatetype, nsec3param->data,
14638 sizeof(nsec3param->data));
14639 nsec3param->length = private.length;
14640 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
14641 }
14642
14643 getprivate:
14644 result = dns_db_findrdataset(db, node, version, zone->privatetype,
14645 dns_rdatatype_none, 0, &prdataset, NULL);
14646 if (result != ISC_R_SUCCESS)
14647 goto done;
14648
14649 /*
14650 * walk private type records, converting them to nsec3 parameters
14651 * using dns_nsec3param_fromprivate(), do the right thing based on
14652 * CREATE and REMOVE flags
14653 */
14654 for (result = dns_rdataset_first(&prdataset);
14655 result == ISC_R_SUCCESS;
14656 result = dns_rdataset_next(&prdataset))
14657 {
14658 dns_rdata_t rdata = DNS_RDATA_INIT;
14659 dns_rdata_t private = DNS_RDATA_INIT;
14660
14661 dns_rdataset_current(&prdataset, &private);
14662 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
14663 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
14664 "looping through nsec3param private data");
14665
14666 /*
14667 * Do we have a valid private record?
14668 */
14669 if (!dns_nsec3param_fromprivate(&private, &rdata,
14670 buf, sizeof(buf)))
14671 continue;
14672
14673 /*
14674 * Remove any NSEC3PARAM records scheduled to be removed.
14675 */
14676 if (NSEC3REMOVE(rdata.data[1])) {
14677 /*
14678 * Zero out the flags.
14679 */
14680 rdata.data[1] = 0;
14681
14682 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
14683 nsec3p != NULL;
14684 nsec3p = next)
14685 {
14686 next = ISC_LIST_NEXT(nsec3p, link);
14687
14688 if (nsec3p->length == rdata.length + 1 &&
14689 memcmp(rdata.data, nsec3p->data + 1,
14690 nsec3p->length - 1) == 0) {
14691 ISC_LIST_UNLINK(*nsec3list,
14692 nsec3p, link);
14693 isc_mem_put(zone->mctx, nsec3p,
14694 sizeof(nsec3param_t));
14695 }
14696 }
14697 continue;
14698 }
14699
14700 nsec3param = isc_mem_get(zone->mctx, sizeof(nsec3param_t));
14701 if (nsec3param == NULL)
14702 CHECK(ISC_R_NOMEMORY);
14703 ISC_LINK_INIT(nsec3param, link);
14704
14705 /*
14706 * Copy the remaining private records so the nsec/nsec3
14707 * chain gets created.
14708 */
14709 INSIST(private.length <= sizeof(nsec3param->data));
14710 memmove(nsec3param->data, private.data, private.length);
14711 nsec3param->length = private.length;
14712 ISC_LIST_APPEND(*nsec3list, nsec3param, link);
14713 }
14714
14715 done:
14716 if (result == ISC_R_NOMORE || result == ISC_R_NOTFOUND)
14717 result = ISC_R_SUCCESS;
14718
14719 failure:
14720 if (node != NULL)
14721 dns_db_detachnode(db, &node);
14722 if (version != NULL)
14723 dns_db_closeversion(db, &version, ISC_FALSE);
14724 if (db != NULL)
14725 dns_db_detach(&db);
14726 if (dns_rdataset_isassociated(&rdataset))
14727 dns_rdataset_disassociate(&rdataset);
14728 if (dns_rdataset_isassociated(&prdataset))
14729 dns_rdataset_disassociate(&prdataset);
14730 return (result);
14731 }
14732
14733 /*
14734 * Populate new zone db with private type records found by save_nsec3param().
14735 */
14736 static isc_result_t
14737 restore_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
14738 nsec3paramlist_t *nsec3list)
14739 {
14740 isc_result_t result;
14741 dns_diff_t diff;
14742 dns_rdata_t rdata;
14743 nsec3param_t *nsec3p = NULL;
14744 nsec3param_t *next;
14745
14746 REQUIRE(DNS_ZONE_VALID(zone));
14747 REQUIRE(!ISC_LIST_EMPTY(*nsec3list));
14748
14749 dns_diff_init(zone->mctx, &diff);
14750
14751 /*
14752 * Loop through the list of private-type records, set the INITIAL
14753 * and CREATE flags, and the add the record to the apex of the tree
14754 * in db.
14755 */
14756 for (nsec3p = ISC_LIST_HEAD(*nsec3list);
14757 nsec3p != NULL;
14758 nsec3p = next)
14759 {
14760 next = ISC_LIST_NEXT(nsec3p, link);
14761 dns_rdata_init(&rdata);
14762 nsec3p->data[2] = DNS_NSEC3FLAG_CREATE | DNS_NSEC3FLAG_INITIAL;
14763 rdata.length = nsec3p->length;
14764 rdata.data = nsec3p->data;
14765 rdata.type = zone->privatetype;
14766 rdata.rdclass = zone->rdclass;
14767 result = update_one_rr(db, version, &diff, DNS_DIFFOP_ADD,
14768 &zone->origin, 0, &rdata);
14769 if (result != ISC_R_SUCCESS) {
14770 break;
14771 }
14772 }
14773
14774 dns_diff_clear(&diff);
14775 return (result);
14776 }
14777
14778 static void
14779 receive_secure_db(isc_task_t *task, isc_event_t *event) {
14780 isc_result_t result;
14781 dns_zone_t *zone;
14782 dns_db_t *rawdb, *db = NULL;
14783 dns_dbnode_t *rawnode = NULL, *node = NULL;
14784 dns_fixedname_t fname;
14785 dns_name_t *name;
14786 dns_dbiterator_t *dbiterator = NULL;
14787 dns_rdatasetiter_t *rdsit = NULL;
14788 dns_rdataset_t rdataset;
14789 dns_dbversion_t *version = NULL;
14790 isc_time_t loadtime;
14791 unsigned int oldserial = 0;
14792 isc_boolean_t have_oldserial = ISC_FALSE;
14793 nsec3paramlist_t nsec3list;
14794
14795 UNUSED(task);
14796
14797 ISC_LIST_INIT(nsec3list);
14798
14799 zone = event->ev_arg;
14800 rawdb = ((struct secure_event *)event)->db;
14801 isc_event_free(&event);
14802
14803 name = dns_fixedname_initname(&fname);
14804 dns_rdataset_init(&rdataset);
14805
14806 LOCK_ZONE(zone);
14807 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING) || !inline_secure(zone)) {
14808 result = ISC_R_SHUTTINGDOWN;
14809 goto failure;
14810 }
14811
14812 TIME_NOW(&loadtime);
14813 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
14814 if (zone->db != NULL) {
14815 result = dns_db_getsoaserial(zone->db, NULL, &oldserial);
14816 if (result == ISC_R_SUCCESS)
14817 have_oldserial = ISC_TRUE;
14818
14819 /*
14820 * assemble nsec3parameters from the old zone, and set a flag
14821 * if any are found
14822 */
14823 result = save_nsec3param(zone, &nsec3list);
14824 if (result != ISC_R_SUCCESS) {
14825 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14826 goto failure;
14827 }
14828 }
14829 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
14830
14831 result = dns_db_create(zone->mctx, zone->db_argv[0],
14832 &zone->origin, dns_dbtype_zone, zone->rdclass,
14833 zone->db_argc - 1, zone->db_argv + 1, &db);
14834 if (result != ISC_R_SUCCESS)
14835 goto failure;
14836
14837 result = dns_db_setgluecachestats(db, zone->gluecachestats);
14838 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
14839 goto failure;
14840 }
14841
14842 result = dns_db_newversion(db, &version);
14843 if (result != ISC_R_SUCCESS)
14844 goto failure;
14845
14846 result = dns_db_createiterator(rawdb, 0, &dbiterator);
14847 if (result != ISC_R_SUCCESS)
14848 goto failure;
14849
14850 for (result = dns_dbiterator_first(dbiterator);
14851 result == ISC_R_SUCCESS;
14852 result = dns_dbiterator_next(dbiterator)) {
14853 result = dns_dbiterator_current(dbiterator, &rawnode, name);
14854 if (result != ISC_R_SUCCESS)
14855 continue;
14856
14857 result = dns_db_findnode(db, name, ISC_TRUE, &node);
14858 if (result != ISC_R_SUCCESS)
14859 goto failure;
14860
14861 result = dns_db_allrdatasets(rawdb, rawnode, NULL, 0, &rdsit);
14862 if (result != ISC_R_SUCCESS)
14863 goto failure;
14864
14865 for (result = dns_rdatasetiter_first(rdsit);
14866 result == ISC_R_SUCCESS;
14867 result = dns_rdatasetiter_next(rdsit)) {
14868 dns_rdatasetiter_current(rdsit, &rdataset);
14869 if (rdataset.type == dns_rdatatype_nsec ||
14870 rdataset.type == dns_rdatatype_rrsig ||
14871 rdataset.type == dns_rdatatype_nsec3 ||
14872 rdataset.type == dns_rdatatype_dnskey ||
14873 rdataset.type == dns_rdatatype_nsec3param) {
14874 dns_rdataset_disassociate(&rdataset);
14875 continue;
14876 }
14877 if (rdataset.type == dns_rdatatype_soa &&
14878 have_oldserial) {
14879 result = checkandaddsoa(db, node, version,
14880 &rdataset, oldserial);
14881 } else
14882 result = dns_db_addrdataset(db, node, version,
14883 0, &rdataset, 0,
14884 NULL);
14885 if (result != ISC_R_SUCCESS)
14886 goto failure;
14887
14888 dns_rdataset_disassociate(&rdataset);
14889 }
14890 dns_rdatasetiter_destroy(&rdsit);
14891 dns_db_detachnode(rawdb, &rawnode);
14892 dns_db_detachnode(db, &node);
14893 }
14894
14895 /*
14896 * Call restore_nsec3param() to create private-type records from
14897 * the old nsec3 parameters and insert them into db
14898 */
14899 if (!ISC_LIST_EMPTY(nsec3list)) {
14900 result = restore_nsec3param(zone, db, version, &nsec3list);
14901 if (result != ISC_R_SUCCESS) {
14902 goto failure;
14903 }
14904 }
14905
14906 dns_db_closeversion(db, &version, ISC_TRUE);
14907
14908 /*
14909 * Lock hierarchy: zmgr, zone, raw.
14910 */
14911 INSIST(zone != zone->raw);
14912 LOCK_ZONE(zone->raw);
14913 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
14914 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
14915 zone_needdump(zone, 0); /* XXXMPA */
14916 UNLOCK_ZONE(zone->raw);
14917
14918 failure:
14919 UNLOCK_ZONE(zone);
14920 if (result != ISC_R_SUCCESS)
14921 dns_zone_log(zone, ISC_LOG_ERROR, "receive_secure_db: %s",
14922 dns_result_totext(result));
14923
14924 while (!ISC_LIST_EMPTY(nsec3list)) {
14925 nsec3param_t *nsec3p;
14926 nsec3p = ISC_LIST_HEAD(nsec3list);
14927 ISC_LIST_UNLINK(nsec3list, nsec3p, link);
14928 isc_mem_put(zone->mctx, nsec3p, sizeof(nsec3param_t));
14929 }
14930 if (dns_rdataset_isassociated(&rdataset))
14931 dns_rdataset_disassociate(&rdataset);
14932 if (db != NULL) {
14933 if (node != NULL)
14934 dns_db_detachnode(db, &node);
14935 if (version != NULL)
14936 dns_db_closeversion(db, &version, ISC_FALSE);
14937 dns_db_detach(&db);
14938 }
14939 if (rawnode != NULL)
14940 dns_db_detachnode(rawdb, &rawnode);
14941 dns_db_detach(&rawdb);
14942 if (dbiterator != NULL)
14943 dns_dbiterator_destroy(&dbiterator);
14944 dns_zone_idetach(&zone);
14945
14946 INSIST(version == NULL);
14947 }
14948
14949 static isc_result_t
14950 zone_send_securedb(dns_zone_t *zone, dns_db_t *db) {
14951 isc_event_t *e;
14952 dns_db_t *dummy = NULL;
14953 dns_zone_t *secure = NULL;
14954
14955 e = isc_event_allocate(zone->secure->mctx, zone,
14956 DNS_EVENT_ZONESECUREDB,
14957 receive_secure_db, zone->secure,
14958 sizeof(struct secure_event));
14959 if (e == NULL)
14960 return (ISC_R_NOMEMORY);
14961 dns_db_attach(db, &dummy);
14962 ((struct secure_event *)e)->db = dummy;
14963 INSIST(LOCKED_ZONE(zone->secure));
14964 zone_iattach(zone->secure, &secure);
14965 isc_task_send(zone->secure->task, &e);
14966 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SENDSECURE);
14967 return (ISC_R_SUCCESS);
14968 }
14969
14970 isc_result_t
14971 dns_zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
14972 isc_result_t result;
14973 dns_zone_t *secure = NULL;
14974
14975 REQUIRE(DNS_ZONE_VALID(zone));
14976 again:
14977 LOCK_ZONE(zone);
14978 if (inline_raw(zone)) {
14979 secure = zone->secure;
14980 INSIST(secure != zone);
14981 TRYLOCK_ZONE(result, secure);
14982 if (result != ISC_R_SUCCESS) {
14983 UNLOCK_ZONE(zone);
14984 secure = NULL;
14985 #if ISC_PLATFORM_USETHREADS
14986 isc_thread_yield();
14987 #endif
14988 goto again;
14989 }
14990 }
14991 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);
14992 result = zone_replacedb(zone, db, dump);
14993 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);
14994 if (secure != NULL)
14995 UNLOCK_ZONE(secure);
14996 UNLOCK_ZONE(zone);
14997 return (result);
14998 }
14999
15000 static isc_result_t
15001 zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) {
15002 dns_dbversion_t *ver;
15003 isc_result_t result;
15004 unsigned int soacount = 0;
15005 unsigned int nscount = 0;
15006
15007 /*
15008 * 'zone' and 'zone->db' locked by caller.
15009 */
15010 REQUIRE(DNS_ZONE_VALID(zone));
15011 REQUIRE(LOCKED_ZONE(zone));
15012 if (inline_raw(zone))
15013 REQUIRE(LOCKED_ZONE(zone->secure));
15014
15015 result = zone_get_from_db(zone, db, &nscount, &soacount,
15016 NULL, NULL, NULL, NULL, NULL, NULL);
15017 if (result == ISC_R_SUCCESS) {
15018 if (soacount != 1) {
15019 dns_zone_log(zone, ISC_LOG_ERROR,
15020 "has %d SOA records", soacount);
15021 result = DNS_R_BADZONE;
15022 }
15023 if (nscount == 0 && zone->type != dns_zone_key) {
15024 dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records");
15025 result = DNS_R_BADZONE;
15026 }
15027 if (result != ISC_R_SUCCESS)
15028 return (result);
15029 } else {
15030 dns_zone_log(zone, ISC_LOG_ERROR,
15031 "retrieving SOA and NS records failed: %s",
15032 dns_result_totext(result));
15033 return (result);
15034 }
15035
15036 result = check_nsec3param(zone, db);
15037 if (result != ISC_R_SUCCESS)
15038 return (result);
15039
15040 ver = NULL;
15041 dns_db_currentversion(db, &ver);
15042
15043 /*
15044 * The initial version of a slave zone is always dumped;
15045 * subsequent versions may be journaled instead if this
15046 * is enabled in the configuration.
15047 */
15048 if (zone->db != NULL && zone->journal != NULL &&
15049 DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
15050 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER))
15051 {
15052 isc_uint32_t serial, oldserial;
15053
15054 dns_zone_log(zone, ISC_LOG_DEBUG(3), "generating diffs");
15055
15056 result = dns_db_getsoaserial(db, ver, &serial);
15057 if (result != ISC_R_SUCCESS) {
15058 dns_zone_log(zone, ISC_LOG_ERROR,
15059 "ixfr-from-differences: unable to get "
15060 "new serial");
15061 goto fail;
15062 }
15063
15064 /*
15065 * This is checked in zone_postload() for master zones.
15066 */
15067 result = zone_get_from_db(zone, zone->db, NULL, &soacount,
15068 &oldserial, NULL, NULL, NULL, NULL,
15069 NULL);
15070 RUNTIME_CHECK(result == ISC_R_SUCCESS);
15071 RUNTIME_CHECK(soacount > 0U);
15072 if ((zone->type == dns_zone_slave ||
15073 (zone->type == dns_zone_redirect &&
15074 zone->masters != NULL))
15075 && !isc_serial_gt(serial, oldserial)) {
15076 isc_uint32_t serialmin, serialmax;
15077 serialmin = (oldserial + 1) & 0xffffffffU;
15078 serialmax = (oldserial + 0x7fffffffU) & 0xffffffffU;
15079 dns_zone_log(zone, ISC_LOG_ERROR,
15080 "ixfr-from-differences: failed: "
15081 "new serial (%u) out of range [%u - %u]",
15082 serial, serialmin, serialmax);
15083 result = ISC_R_RANGE;
15084 goto fail;
15085 }
15086
15087 result = dns_db_diff(zone->mctx, db, ver, zone->db, NULL,
15088 zone->journal);
15089 if (result != ISC_R_SUCCESS) {
15090 char strbuf[ISC_STRERRORSIZE];
15091 isc__strerror(errno, strbuf, sizeof(strbuf));
15092 dns_zone_log(zone, ISC_LOG_ERROR,
15093 "ixfr-from-differences: failed: "
15094 "%s", strbuf);
15095 goto fallback;
15096 }
15097 if (dump)
15098 zone_needdump(zone, DNS_DUMP_DELAY);
15099 else
15100 zone_journal_compact(zone, zone->db, serial);
15101 if (zone->type == dns_zone_master && inline_raw(zone))
15102 zone_send_secureserial(zone, serial);
15103 } else {
15104 fallback:
15105 if (dump && zone->masterfile != NULL) {
15106 /*
15107 * If DNS_ZONEFLG_FORCEXFER was set we don't want
15108 * to keep the old masterfile.
15109 */
15110 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER) &&
15111 remove(zone->masterfile) < 0 && errno != ENOENT) {
15112 char strbuf[ISC_STRERRORSIZE];
15113 isc__strerror(errno, strbuf, sizeof(strbuf));
15114 isc_log_write(dns_lctx,
15115 DNS_LOGCATEGORY_GENERAL,
15116 DNS_LOGMODULE_ZONE,
15117 ISC_LOG_WARNING,
15118 "unable to remove masterfile "
15119 "'%s': '%s'",
15120 zone->masterfile, strbuf);
15121 }
15122 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0)
15123 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NODELAY);
15124 else
15125 zone_needdump(zone, 0);
15126 }
15127 if (dump && zone->journal != NULL) {
15128 /*
15129 * The in-memory database just changed, and
15130 * because 'dump' is set, it didn't change by
15131 * being loaded from disk. Also, we have not
15132 * journaled diffs for this change.
15133 * Therefore, the on-disk journal is missing
15134 * the deltas for this change. Since it can
15135 * no longer be used to bring the zone
15136 * up-to-date, it is useless and should be
15137 * removed.
15138 */
15139 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
15140 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
15141 "removing journal file");
15142 if (remove(zone->journal) < 0 && errno != ENOENT) {
15143 char strbuf[ISC_STRERRORSIZE];
15144 isc__strerror(errno, strbuf, sizeof(strbuf));
15145 isc_log_write(dns_lctx,
15146 DNS_LOGCATEGORY_GENERAL,
15147 DNS_LOGMODULE_ZONE,
15148 ISC_LOG_WARNING,
15149 "unable to remove journal "
15150 "'%s': '%s'",
15151 zone->journal, strbuf);
15152 }
15153 }
15154
15155 if (inline_raw(zone))
15156 zone_send_securedb(zone, db);
15157 }
15158
15159 dns_db_closeversion(db, &ver, ISC_FALSE);
15160
15161 dns_zone_log(zone, ISC_LOG_DEBUG(3), "replacing zone database");
15162
15163 if (zone->db != NULL)
15164 zone_detachdb(zone);
15165 zone_attachdb(zone, db);
15166 dns_db_settask(zone->db, zone->task);
15167 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY);
15168 return (ISC_R_SUCCESS);
15169
15170 fail:
15171 dns_db_closeversion(db, &ver, ISC_FALSE);
15172 return (result);
15173 }
15174
15175 /* The caller must hold the dblock as a writer. */
15176 static inline void
15177 zone_attachdb(dns_zone_t *zone, dns_db_t *db) {
15178 REQUIRE(zone->db == NULL && db != NULL);
15179
15180 dns_db_attach(db, &zone->db);
15181 }
15182
15183 /* The caller must hold the dblock as a writer. */
15184 static inline void
15185 zone_detachdb(dns_zone_t *zone) {
15186 REQUIRE(zone->db != NULL);
15187
15188 dns_db_detach(&zone->db);
15189 }
15190
15191 static void
15192 zone_xfrdone(dns_zone_t *zone, isc_result_t result) {
15193 isc_time_t now;
15194 isc_boolean_t again = ISC_FALSE;
15195 unsigned int soacount;
15196 unsigned int nscount;
15197 isc_uint32_t serial, refresh, retry, expire, minimum;
15198 isc_result_t xfrresult = result;
15199 isc_boolean_t free_needed;
15200 dns_zone_t *secure = NULL;
15201
15202 REQUIRE(DNS_ZONE_VALID(zone));
15203
15204 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15205 "zone transfer finished: %s", dns_result_totext(result));
15206
15207 /*
15208 * Obtaining a lock on the zone->secure (see zone_send_secureserial)
15209 * could result in a deadlock due to a LOR so we will spin if we
15210 * can't obtain the both locks.
15211 */
15212 again:
15213 LOCK_ZONE(zone);
15214 if (inline_raw(zone)) {
15215 secure = zone->secure;
15216 INSIST(secure != zone);
15217 TRYLOCK_ZONE(result, secure);
15218 if (result != ISC_R_SUCCESS) {
15219 UNLOCK_ZONE(zone);
15220 secure = NULL;
15221 #if ISC_PLATFORM_USETHREADS
15222 isc_thread_yield();
15223 #endif
15224 goto again;
15225 }
15226 }
15227
15228 INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
15229 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
15230 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
15231
15232 TIME_NOW(&now);
15233 switch (xfrresult) {
15234 case ISC_R_SUCCESS:
15235 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
15236 /* FALLTHROUGH */
15237 case DNS_R_UPTODATE:
15238 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FORCEXFER);
15239 /*
15240 * Has the zone expired underneath us?
15241 */
15242 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15243 if (zone->db == NULL) {
15244 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15245 goto same_master;
15246 }
15247
15248 /*
15249 * Update the zone structure's data from the actual
15250 * SOA received.
15251 */
15252 nscount = 0;
15253 soacount = 0;
15254 INSIST(zone->db != NULL);
15255 result = zone_get_from_db(zone, zone->db, &nscount,
15256 &soacount, &serial, &refresh,
15257 &retry, &expire, &minimum, NULL);
15258 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15259 if (result == ISC_R_SUCCESS) {
15260 if (soacount != 1)
15261 dns_zone_log(zone, ISC_LOG_ERROR,
15262 "transferred zone "
15263 "has %d SOA record%s", soacount,
15264 (soacount != 0) ? "s" : "");
15265 if (nscount == 0) {
15266 dns_zone_log(zone, ISC_LOG_ERROR,
15267 "transferred zone "
15268 "has no NS records");
15269 if (DNS_ZONE_FLAG(zone,
15270 DNS_ZONEFLG_HAVETIMERS)) {
15271 zone->refresh = DNS_ZONE_DEFAULTREFRESH;
15272 zone->retry = DNS_ZONE_DEFAULTRETRY;
15273 }
15274 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15275 zone_unload(zone);
15276 goto next_master;
15277 }
15278 zone->refresh = RANGE(refresh, zone->minrefresh,
15279 zone->maxrefresh);
15280 zone->retry = RANGE(retry, zone->minretry,
15281 zone->maxretry);
15282 zone->expire = RANGE(expire,
15283 zone->refresh + zone->retry,
15284 DNS_MAX_EXPIRE);
15285 zone->minimum = minimum;
15286 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS);
15287 }
15288
15289 /*
15290 * Set our next update/expire times.
15291 */
15292 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDREFRESH)) {
15293 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDREFRESH);
15294 zone->refreshtime = now;
15295 DNS_ZONE_TIME_ADD(&now, zone->expire,
15296 &zone->expiretime);
15297 } else {
15298 DNS_ZONE_JITTER_ADD(&now, zone->refresh,
15299 &zone->refreshtime);
15300 DNS_ZONE_TIME_ADD(&now, zone->expire,
15301 &zone->expiretime);
15302 }
15303 if (result == ISC_R_SUCCESS && xfrresult == ISC_R_SUCCESS) {
15304 char buf[DNS_NAME_FORMATSIZE + sizeof(": TSIG ''")];
15305 if (zone->tsigkey != NULL) {
15306 char namebuf[DNS_NAME_FORMATSIZE];
15307 dns_name_format(&zone->tsigkey->name, namebuf,
15308 sizeof(namebuf));
15309 snprintf(buf, sizeof(buf), ": TSIG '%s'",
15310 namebuf);
15311 } else
15312 buf[0] = '\0';
15313 dns_zone_log(zone, ISC_LOG_INFO,
15314 "transferred serial %u%s",
15315 serial, buf);
15316 if (inline_raw(zone))
15317 zone_send_secureserial(zone, serial);
15318 }
15319
15320 /*
15321 * This is not necessary if we just performed a AXFR
15322 * however it is necessary for an IXFR / UPTODATE and
15323 * won't hurt with an AXFR.
15324 */
15325 if (zone->masterfile != NULL || zone->journal != NULL) {
15326 unsigned int delay = DNS_DUMP_DELAY;
15327
15328 result = ISC_R_FAILURE;
15329 if (zone->journal != NULL)
15330 result = isc_file_settime(zone->journal, &now);
15331 if (result != ISC_R_SUCCESS &&
15332 zone->masterfile != NULL)
15333 result = isc_file_settime(zone->masterfile,
15334 &now);
15335
15336 if ((DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NODELAY) != 0) ||
15337 result == ISC_R_FILENOTFOUND)
15338 delay = 0;
15339
15340 if ((result == ISC_R_SUCCESS ||
15341 result == ISC_R_FILENOTFOUND) &&
15342 zone->masterfile != NULL)
15343 zone_needdump(zone, delay);
15344 else if (result != ISC_R_SUCCESS)
15345 dns_zone_log(zone, ISC_LOG_ERROR,
15346 "transfer: could not set file "
15347 "modification time of '%s': %s",
15348 zone->masterfile,
15349 dns_result_totext(result));
15350 }
15351 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NODELAY);
15352 inc_stats(zone, dns_zonestatscounter_xfrsuccess);
15353 break;
15354
15355 case DNS_R_BADIXFR:
15356 /* Force retry with AXFR. */
15357 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLAG_NOIXFR);
15358 goto same_master;
15359
15360 case DNS_R_TOOMANYRECORDS:
15361 DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
15362 inc_stats(zone, dns_zonestatscounter_xfrfail);
15363 break;
15364
15365 default:
15366 next_master:
15367 /*
15368 * Skip to next failed / untried master.
15369 */
15370 do {
15371 zone->curmaster++;
15372 } while (zone->curmaster < zone->masterscnt &&
15373 zone->mastersok[zone->curmaster]);
15374 /* FALLTHROUGH */
15375 same_master:
15376 if (zone->curmaster >= zone->masterscnt) {
15377 zone->curmaster = 0;
15378 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
15379 !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
15380 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15381 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15382 while (zone->curmaster < zone->masterscnt &&
15383 zone->mastersok[zone->curmaster])
15384 zone->curmaster++;
15385 again = ISC_TRUE;
15386 } else
15387 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
15388 } else {
15389 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
15390 again = ISC_TRUE;
15391 }
15392 inc_stats(zone, dns_zonestatscounter_xfrfail);
15393 break;
15394 }
15395 zone_settimer(zone, &now);
15396
15397 /*
15398 * If creating the transfer object failed, zone->xfr is NULL.
15399 * Otherwise, we are called as the done callback of a zone
15400 * transfer object that just entered its shutting-down
15401 * state. Since we are no longer responsible for shutting
15402 * it down, we can detach our reference.
15403 */
15404 if (zone->xfr != NULL)
15405 dns_xfrin_detach(&zone->xfr);
15406
15407 if (zone->tsigkey != NULL)
15408 dns_tsigkey_detach(&zone->tsigkey);
15409
15410 /*
15411 * Handle any deferred journal compaction.
15412 */
15413 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDCOMPACT)) {
15414 dns_db_t *db = NULL;
15415 if (dns_zone_getdb(zone, &db) == ISC_R_SUCCESS) {
15416 zone_journal_compact(zone, db, zone->compact_serial);
15417 dns_db_detach(&db);
15418 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDCOMPACT);
15419 }
15420 }
15421
15422 if (secure != NULL)
15423 UNLOCK_ZONE(secure);
15424 /*
15425 * This transfer finishing freed up a transfer quota slot.
15426 * Let any other zones waiting for quota have it.
15427 */
15428 if (zone->zmgr != NULL &&
15429 zone->statelist == &zone->zmgr->xfrin_in_progress) {
15430 UNLOCK_ZONE(zone);
15431 RWLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15432 ISC_LIST_UNLINK(zone->zmgr->xfrin_in_progress, zone, statelink);
15433 zone->statelist = NULL;
15434 zmgr_resume_xfrs(zone->zmgr, ISC_FALSE);
15435 RWUNLOCK(&zone->zmgr->rwlock, isc_rwlocktype_write);
15436 LOCK_ZONE(zone);
15437 }
15438
15439 /*
15440 * Retry with a different server if necessary.
15441 */
15442 if (again && !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING))
15443 queue_soa_query(zone);
15444
15445 INSIST(zone->irefs > 0);
15446 zone->irefs--;
15447 free_needed = exit_check(zone);
15448 UNLOCK_ZONE(zone);
15449 if (free_needed)
15450 zone_free(zone);
15451 }
15452
15453 static void
15454 zone_loaddone(void *arg, isc_result_t result) {
15455 static char me[] = "zone_loaddone";
15456 dns_load_t *load = arg;
15457 dns_zone_t *zone;
15458 isc_result_t tresult;
15459 dns_zone_t *secure = NULL;
15460
15461 REQUIRE(DNS_LOAD_VALID(load));
15462 zone = load->zone;
15463
15464 ENTER;
15465
15466 tresult = dns_db_endload(load->db, &load->callbacks);
15467 if (tresult != ISC_R_SUCCESS &&
15468 (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
15469 result = tresult;
15470
15471 /*
15472 * Lock hierarchy: zmgr, zone, raw.
15473 */
15474 again:
15475 LOCK_ZONE(zone);
15476 INSIST(zone != zone->raw);
15477 if (inline_secure(zone))
15478 LOCK_ZONE(zone->raw);
15479 else if (inline_raw(zone)) {
15480 secure = zone->secure;
15481 TRYLOCK_ZONE(result, secure);
15482 if (result != ISC_R_SUCCESS) {
15483 UNLOCK_ZONE(zone);
15484 secure = NULL;
15485 #if ISC_PLATFORM_USETHREADS
15486 isc_thread_yield();
15487 #endif
15488 goto again;
15489 }
15490 }
15491 (void)zone_postload(zone, load->db, load->loadtime, result);
15492 zonemgr_putio(&zone->readio);
15493 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADING);
15494 zone_idetach(&load->callbacks.zone);
15495 /*
15496 * Leave the zone frozen if the reload fails.
15497 */
15498 if ((result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) &&
15499 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_THAW))
15500 zone->update_disabled = ISC_FALSE;
15501 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_THAW);
15502 if (inline_secure(zone))
15503 UNLOCK_ZONE(zone->raw);
15504 else if (secure != NULL)
15505 UNLOCK_ZONE(secure);
15506 UNLOCK_ZONE(zone);
15507
15508 load->magic = 0;
15509 dns_db_detach(&load->db);
15510 if (load->zone->lctx != NULL)
15511 dns_loadctx_detach(&load->zone->lctx);
15512 dns_zone_idetach(&load->zone);
15513 isc_mem_putanddetach(&load->mctx, load, sizeof(*load));
15514 }
15515
15516 void
15517 dns_zone_getssutable(dns_zone_t *zone, dns_ssutable_t **table) {
15518 REQUIRE(DNS_ZONE_VALID(zone));
15519 REQUIRE(table != NULL);
15520 REQUIRE(*table == NULL);
15521
15522 LOCK_ZONE(zone);
15523 if (zone->ssutable != NULL)
15524 dns_ssutable_attach(zone->ssutable, table);
15525 UNLOCK_ZONE(zone);
15526 }
15527
15528 void
15529 dns_zone_setssutable(dns_zone_t *zone, dns_ssutable_t *table) {
15530 REQUIRE(DNS_ZONE_VALID(zone));
15531
15532 LOCK_ZONE(zone);
15533 if (zone->ssutable != NULL)
15534 dns_ssutable_detach(&zone->ssutable);
15535 if (table != NULL)
15536 dns_ssutable_attach(table, &zone->ssutable);
15537 UNLOCK_ZONE(zone);
15538 }
15539
15540 void
15541 dns_zone_setsigvalidityinterval(dns_zone_t *zone, isc_uint32_t interval) {
15542 REQUIRE(DNS_ZONE_VALID(zone));
15543
15544 zone->sigvalidityinterval = interval;
15545 }
15546
15547 isc_uint32_t
15548 dns_zone_getsigvalidityinterval(dns_zone_t *zone) {
15549 REQUIRE(DNS_ZONE_VALID(zone));
15550
15551 return (zone->sigvalidityinterval);
15552 }
15553
15554 void
15555 dns_zone_setsigresigninginterval(dns_zone_t *zone, isc_uint32_t interval) {
15556 isc_time_t now;
15557
15558 REQUIRE(DNS_ZONE_VALID(zone));
15559
15560 LOCK_ZONE(zone);
15561 zone->sigresigninginterval = interval;
15562 set_resigntime(zone);
15563 if (zone->task != NULL) {
15564 TIME_NOW(&now);
15565 zone_settimer(zone, &now);
15566 }
15567 UNLOCK_ZONE(zone);
15568 }
15569
15570 isc_uint32_t
15571 dns_zone_getsigresigninginterval(dns_zone_t *zone) {
15572 REQUIRE(DNS_ZONE_VALID(zone));
15573
15574 return (zone->sigresigninginterval);
15575 }
15576
15577 static void
15578 queue_xfrin(dns_zone_t *zone) {
15579 const char me[] = "queue_xfrin";
15580 isc_result_t result;
15581 dns_zonemgr_t *zmgr = zone->zmgr;
15582
15583 ENTER;
15584
15585 INSIST(zone->statelist == NULL);
15586
15587 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15588 ISC_LIST_APPEND(zmgr->waiting_for_xfrin, zone, statelink);
15589 LOCK_ZONE(zone);
15590 zone->irefs++;
15591 UNLOCK_ZONE(zone);
15592 zone->statelist = &zmgr->waiting_for_xfrin;
15593 result = zmgr_start_xfrin_ifquota(zmgr, zone);
15594 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
15595
15596 if (result == ISC_R_QUOTA) {
15597 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_INFO,
15598 "zone transfer deferred due to quota");
15599 } else if (result != ISC_R_SUCCESS) {
15600 dns_zone_logc(zone, DNS_LOGCATEGORY_XFER_IN, ISC_LOG_ERROR,
15601 "starting zone transfer: %s",
15602 isc_result_totext(result));
15603 }
15604 }
15605
15606 /*
15607 * This event callback is called when a zone has received
15608 * any necessary zone transfer quota. This is the time
15609 * to go ahead and start the transfer.
15610 */
15611 static void
15612 got_transfer_quota(isc_task_t *task, isc_event_t *event) {
15613 isc_result_t result = ISC_R_SUCCESS;
15614 dns_peer_t *peer = NULL;
15615 char master[ISC_SOCKADDR_FORMATSIZE];
15616 char source[ISC_SOCKADDR_FORMATSIZE];
15617 dns_rdatatype_t xfrtype;
15618 dns_zone_t *zone = event->ev_arg;
15619 isc_netaddr_t masterip;
15620 isc_sockaddr_t sourceaddr;
15621 isc_sockaddr_t masteraddr;
15622 isc_time_t now;
15623 const char *soa_before = "";
15624 isc_dscp_t dscp = -1;
15625 isc_boolean_t loaded;
15626
15627 UNUSED(task);
15628
15629 INSIST(task == zone->task);
15630
15631 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
15632 result = ISC_R_CANCELED;
15633 goto cleanup;
15634 }
15635
15636 TIME_NOW(&now);
15637
15638 isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));
15639 if (dns_zonemgr_unreachable(zone->zmgr, &zone->masteraddr,
15640 &zone->sourceaddr, &now))
15641 {
15642 isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source));
15643 dns_zone_log(zone, ISC_LOG_INFO,
15644 "got_transfer_quota: skipping zone transfer as "
15645 "master %s (source %s) is unreachable (cached)",
15646 master, source);
15647 result = ISC_R_CANCELED;
15648 goto cleanup;
15649 }
15650
15651 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
15652 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
15653
15654 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
15655 soa_before = "SOA before ";
15656 /*
15657 * Decide whether we should request IXFR or AXFR.
15658 */
15659 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
15660 loaded = ISC_TF(zone->db != NULL);
15661 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
15662
15663 if (!loaded) {
15664 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15665 "no database exists yet, requesting AXFR of "
15666 "initial version from %s", master);
15667 xfrtype = dns_rdatatype_axfr;
15668 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER)) {
15669 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15670 "forced reload, requesting AXFR of "
15671 "initial version from %s", master);
15672 xfrtype = dns_rdatatype_axfr;
15673 } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLAG_NOIXFR)) {
15674 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15675 "retrying with AXFR from %s due to "
15676 "previous IXFR failure", master);
15677 xfrtype = dns_rdatatype_axfr;
15678 LOCK_ZONE(zone);
15679 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLAG_NOIXFR);
15680 UNLOCK_ZONE(zone);
15681 } else {
15682 isc_boolean_t use_ixfr = ISC_TRUE;
15683 if (peer != NULL)
15684 result = dns_peer_getrequestixfr(peer, &use_ixfr);
15685 if (peer == NULL || result != ISC_R_SUCCESS)
15686 use_ixfr = zone->requestixfr;
15687 if (use_ixfr == ISC_FALSE) {
15688 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15689 "IXFR disabled, requesting %sAXFR from %s",
15690 soa_before, master);
15691 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
15692 xfrtype = dns_rdatatype_soa;
15693 else
15694 xfrtype = dns_rdatatype_axfr;
15695 } else {
15696 dns_zone_log(zone, ISC_LOG_DEBUG(1),
15697 "requesting IXFR from %s", master);
15698 xfrtype = dns_rdatatype_ixfr;
15699 }
15700 }
15701
15702 /*
15703 * Determine if we should attempt to sign the request with TSIG.
15704 */
15705 result = ISC_R_NOTFOUND;
15706
15707 /*
15708 * First, look for a tsig key in the master statement, then
15709 * try for a server key.
15710 */
15711 if ((zone->masterkeynames != NULL) &&
15712 (zone->masterkeynames[zone->curmaster] != NULL)) {
15713 dns_view_t *view = dns_zone_getview(zone);
15714 dns_name_t *keyname = zone->masterkeynames[zone->curmaster];
15715 result = dns_view_gettsig(view, keyname, &zone->tsigkey);
15716 }
15717 if (zone->tsigkey == NULL)
15718 result = dns_view_getpeertsig(zone->view, &masterip,
15719 &zone->tsigkey);
15720
15721 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND) {
15722 dns_zone_log(zone, ISC_LOG_ERROR,
15723 "could not get TSIG key for zone transfer: %s",
15724 isc_result_totext(result));
15725 }
15726
15727 if (zone->masterdscps != NULL)
15728 dscp = zone->masterdscps[zone->curmaster];
15729
15730 LOCK_ZONE(zone);
15731 masteraddr = zone->masteraddr;
15732 sourceaddr = zone->sourceaddr;
15733 switch (isc_sockaddr_pf(&masteraddr)) {
15734 case PF_INET:
15735 if (dscp == -1)
15736 dscp = zone->xfrsource4dscp;
15737 break;
15738 case PF_INET6:
15739 if (dscp == -1)
15740 dscp = zone->xfrsource6dscp;
15741 break;
15742 default:
15743 INSIST(0);
15744 };
15745 UNLOCK_ZONE(zone);
15746 INSIST(isc_sockaddr_pf(&masteraddr) == isc_sockaddr_pf(&sourceaddr));
15747 result = dns_xfrin_create3(zone, xfrtype, &masteraddr, &sourceaddr,
15748 dscp, zone->tsigkey, zone->mctx,
15749 zone->zmgr->timermgr, zone->zmgr->socketmgr,
15750 zone->task, zone_xfrdone, &zone->xfr);
15751 if (result == ISC_R_SUCCESS) {
15752 LOCK_ZONE(zone);
15753 if (xfrtype == dns_rdatatype_axfr) {
15754 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
15755 inc_stats(zone, dns_zonestatscounter_axfrreqv4);
15756 else
15757 inc_stats(zone, dns_zonestatscounter_axfrreqv6);
15758 } else if (xfrtype == dns_rdatatype_ixfr) {
15759 if (isc_sockaddr_pf(&masteraddr) == PF_INET)
15760 inc_stats(zone, dns_zonestatscounter_ixfrreqv4);
15761 else
15762 inc_stats(zone, dns_zonestatscounter_ixfrreqv6);
15763 }
15764 UNLOCK_ZONE(zone);
15765 }
15766 cleanup:
15767 /*
15768 * Any failure in this function is handled like a failed
15769 * zone transfer. This ensures that we get removed from
15770 * zmgr->xfrin_in_progress.
15771 */
15772 if (result != ISC_R_SUCCESS)
15773 zone_xfrdone(zone, result);
15774
15775 isc_event_free(&event);
15776 }
15777
15778 /*
15779 * Update forwarding support.
15780 */
15781
15782 static void
15783 forward_destroy(dns_forward_t *forward) {
15784
15785 forward->magic = 0;
15786 if (forward->request != NULL)
15787 dns_request_destroy(&forward->request);
15788 if (forward->msgbuf != NULL)
15789 isc_buffer_free(&forward->msgbuf);
15790 if (forward->zone != NULL) {
15791 LOCK(&forward->zone->lock);
15792 if (ISC_LINK_LINKED(forward, link))
15793 ISC_LIST_UNLINK(forward->zone->forwards, forward, link);
15794 UNLOCK(&forward->zone->lock);
15795 dns_zone_idetach(&forward->zone);
15796 }
15797 isc_mem_putanddetach(&forward->mctx, forward, sizeof(*forward));
15798 }
15799
15800 static isc_result_t
15801 sendtomaster(dns_forward_t *forward) {
15802 isc_result_t result;
15803 isc_sockaddr_t src;
15804 isc_dscp_t dscp = -1;
15805
15806 LOCK_ZONE(forward->zone);
15807
15808 if (DNS_ZONE_FLAG(forward->zone, DNS_ZONEFLG_EXITING)) {
15809 UNLOCK_ZONE(forward->zone);
15810 return (ISC_R_CANCELED);
15811 }
15812
15813 if (forward->which >= forward->zone->masterscnt) {
15814 UNLOCK_ZONE(forward->zone);
15815 return (ISC_R_NOMORE);
15816 }
15817
15818 forward->addr = forward->zone->masters[forward->which];
15819 /*
15820 * Always use TCP regardless of whether the original update
15821 * used TCP.
15822 * XXX The timeout may but a bit small if we are far down a
15823 * transfer graph and the master has to try several masters.
15824 */
15825 switch (isc_sockaddr_pf(&forward->addr)) {
15826 case PF_INET:
15827 src = forward->zone->xfrsource4;
15828 dscp = forward->zone->xfrsource4dscp;
15829 break;
15830 case PF_INET6:
15831 src = forward->zone->xfrsource6;
15832 dscp = forward->zone->xfrsource6dscp;
15833 break;
15834 default:
15835 result = ISC_R_NOTIMPLEMENTED;
15836 goto unlock;
15837 }
15838 result = dns_request_createraw4(forward->zone->view->requestmgr,
15839 forward->msgbuf,
15840 &src, &forward->addr, dscp,
15841 forward->options, 15 /* XXX */,
15842 0, 0, forward->zone->task,
15843 forward_callback, forward,
15844 &forward->request);
15845 if (result == ISC_R_SUCCESS) {
15846 if (!ISC_LINK_LINKED(forward, link))
15847 ISC_LIST_APPEND(forward->zone->forwards, forward, link);
15848 }
15849
15850 unlock:
15851 UNLOCK_ZONE(forward->zone);
15852 return (result);
15853 }
15854
15855 static void
15856 forward_callback(isc_task_t *task, isc_event_t *event) {
15857 const char me[] = "forward_callback";
15858 dns_requestevent_t *revent = (dns_requestevent_t *)event;
15859 dns_message_t *msg = NULL;
15860 char master[ISC_SOCKADDR_FORMATSIZE];
15861 isc_result_t result;
15862 dns_forward_t *forward;
15863 dns_zone_t *zone;
15864
15865 UNUSED(task);
15866
15867 forward = revent->ev_arg;
15868 INSIST(DNS_FORWARD_VALID(forward));
15869 zone = forward->zone;
15870 INSIST(DNS_ZONE_VALID(zone));
15871
15872 ENTER;
15873
15874 isc_sockaddr_format(&forward->addr, master, sizeof(master));
15875
15876 if (revent->result != ISC_R_SUCCESS) {
15877 dns_zone_log(zone, ISC_LOG_INFO,
15878 "could not forward dynamic update to %s: %s",
15879 master, dns_result_totext(revent->result));
15880 goto next_master;
15881 }
15882
15883 result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
15884 if (result != ISC_R_SUCCESS)
15885 goto next_master;
15886
15887 result = dns_request_getresponse(revent->request, msg,
15888 DNS_MESSAGEPARSE_PRESERVEORDER |
15889 DNS_MESSAGEPARSE_CLONEBUFFER);
15890 if (result != ISC_R_SUCCESS)
15891 goto next_master;
15892
15893 switch (msg->rcode) {
15894 /*
15895 * Pass these rcodes back to client.
15896 */
15897 case dns_rcode_noerror:
15898 case dns_rcode_yxdomain:
15899 case dns_rcode_yxrrset:
15900 case dns_rcode_nxrrset:
15901 case dns_rcode_refused:
15902 case dns_rcode_nxdomain: {
15903 char rcode[128];
15904 isc_buffer_t rb;
15905
15906 isc_buffer_init(&rb, rcode, sizeof(rcode));
15907 (void)dns_rcode_totext(msg->rcode, &rb);
15908 dns_zone_log(zone, ISC_LOG_INFO,
15909 "forwarded dynamic update: "
15910 "master %s returned: %.*s",
15911 master, (int)rb.used, rcode);
15912 break;
15913 }
15914
15915 /* These should not occur if the masters/zone are valid. */
15916 case dns_rcode_notzone:
15917 case dns_rcode_notauth: {
15918 char rcode[128];
15919 isc_buffer_t rb;
15920
15921 isc_buffer_init(&rb, rcode, sizeof(rcode));
15922 (void)dns_rcode_totext(msg->rcode, &rb);
15923 dns_zone_log(zone, ISC_LOG_WARNING,
15924 "forwarding dynamic update: "
15925 "unexpected response: master %s returned: %.*s",
15926 master, (int)rb.used, rcode);
15927 goto next_master;
15928 }
15929
15930 /* Try another server for these rcodes. */
15931 case dns_rcode_formerr:
15932 case dns_rcode_servfail:
15933 case dns_rcode_notimp:
15934 case dns_rcode_badvers:
15935 default:
15936 goto next_master;
15937 }
15938
15939 /* call callback */
15940 (forward->callback)(forward->callback_arg, ISC_R_SUCCESS, msg);
15941 msg = NULL;
15942 dns_request_destroy(&forward->request);
15943 forward_destroy(forward);
15944 isc_event_free(&event);
15945 return;
15946
15947 next_master:
15948 if (msg != NULL)
15949 dns_message_destroy(&msg);
15950 isc_event_free(&event);
15951 forward->which++;
15952 dns_request_destroy(&forward->request);
15953 result = sendtomaster(forward);
15954 if (result != ISC_R_SUCCESS) {
15955 /* call callback */
15956 dns_zone_log(zone, ISC_LOG_DEBUG(3),
15957 "exhausted dynamic update forwarder list");
15958 (forward->callback)(forward->callback_arg, result, NULL);
15959 forward_destroy(forward);
15960 }
15961 }
15962
15963 isc_result_t
15964 dns_zone_forwardupdate(dns_zone_t *zone, dns_message_t *msg,
15965 dns_updatecallback_t callback, void *callback_arg)
15966 {
15967 dns_forward_t *forward;
15968 isc_result_t result;
15969 isc_region_t *mr;
15970
15971 REQUIRE(DNS_ZONE_VALID(zone));
15972 REQUIRE(msg != NULL);
15973 REQUIRE(callback != NULL);
15974
15975 forward = isc_mem_get(zone->mctx, sizeof(*forward));
15976 if (forward == NULL)
15977 return (ISC_R_NOMEMORY);
15978
15979 forward->request = NULL;
15980 forward->zone = NULL;
15981 forward->msgbuf = NULL;
15982 forward->which = 0;
15983 forward->mctx = 0;
15984 forward->callback = callback;
15985 forward->callback_arg = callback_arg;
15986 ISC_LINK_INIT(forward, link);
15987 forward->magic = FORWARD_MAGIC;
15988 forward->options = DNS_REQUESTOPT_TCP;
15989 /*
15990 * If we have a SIG(0) signed message we need to preserve the
15991 * query id as that is included in the SIG(0) computation.
15992 */
15993 if (msg->sig0 != NULL)
15994 forward->options |= DNS_REQUESTOPT_FIXEDID;
15995
15996 mr = dns_message_getrawmessage(msg);
15997 if (mr == NULL) {
15998 result = ISC_R_UNEXPECTEDEND;
15999 goto cleanup;
16000 }
16001
16002 result = isc_buffer_allocate(zone->mctx, &forward->msgbuf, mr->length);
16003 if (result != ISC_R_SUCCESS)
16004 goto cleanup;
16005 result = isc_buffer_copyregion(forward->msgbuf, mr);
16006 if (result != ISC_R_SUCCESS)
16007 goto cleanup;
16008
16009 isc_mem_attach(zone->mctx, &forward->mctx);
16010 dns_zone_iattach(zone, &forward->zone);
16011 result = sendtomaster(forward);
16012
16013 cleanup:
16014 if (result != ISC_R_SUCCESS) {
16015 forward_destroy(forward);
16016 }
16017 return (result);
16018 }
16019
16020 isc_result_t
16021 dns_zone_next(dns_zone_t *zone, dns_zone_t **next) {
16022 REQUIRE(DNS_ZONE_VALID(zone));
16023 REQUIRE(next != NULL && *next == NULL);
16024
16025 *next = ISC_LIST_NEXT(zone, link);
16026 if (*next == NULL)
16027 return (ISC_R_NOMORE);
16028 else
16029 return (ISC_R_SUCCESS);
16030 }
16031
16032 isc_result_t
16033 dns_zone_first(dns_zonemgr_t *zmgr, dns_zone_t **first) {
16034 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16035 REQUIRE(first != NULL && *first == NULL);
16036
16037 *first = ISC_LIST_HEAD(zmgr->zones);
16038 if (*first == NULL)
16039 return (ISC_R_NOMORE);
16040 else
16041 return (ISC_R_SUCCESS);
16042 }
16043
16044 /***
16045 *** Zone manager.
16046 ***/
16047
16048 isc_result_t
16049 dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,
16050 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
16051 dns_zonemgr_t **zmgrp)
16052 {
16053 dns_zonemgr_t *zmgr;
16054 isc_result_t result;
16055
16056 zmgr = isc_mem_get(mctx, sizeof(*zmgr));
16057 if (zmgr == NULL)
16058 return (ISC_R_NOMEMORY);
16059 zmgr->mctx = NULL;
16060 zmgr->refs = 1;
16061 isc_mem_attach(mctx, &zmgr->mctx);
16062 zmgr->taskmgr = taskmgr;
16063 zmgr->timermgr = timermgr;
16064 zmgr->socketmgr = socketmgr;
16065 zmgr->zonetasks = NULL;
16066 zmgr->loadtasks = NULL;
16067 zmgr->mctxpool = NULL;
16068 zmgr->task = NULL;
16069 zmgr->notifyrl = NULL;
16070 zmgr->refreshrl = NULL;
16071 zmgr->startupnotifyrl = NULL;
16072 zmgr->startuprefreshrl = NULL;
16073 ISC_LIST_INIT(zmgr->zones);
16074 ISC_LIST_INIT(zmgr->waiting_for_xfrin);
16075 ISC_LIST_INIT(zmgr->xfrin_in_progress);
16076 memset(zmgr->unreachable, 0, sizeof(zmgr->unreachable));
16077 result = isc_rwlock_init(&zmgr->rwlock, 0, 0);
16078 if (result != ISC_R_SUCCESS)
16079 goto free_mem;
16080
16081 zmgr->transfersin = 10;
16082 zmgr->transfersperns = 2;
16083
16084 /* Unreachable lock. */
16085 result = isc_rwlock_init(&zmgr->urlock, 0, 0);
16086 if (result != ISC_R_SUCCESS)
16087 goto free_rwlock;
16088
16089 /* Create a single task for queueing of SOA queries. */
16090 result = isc_task_create(taskmgr, 1, &zmgr->task);
16091 if (result != ISC_R_SUCCESS)
16092 goto free_urlock;
16093
16094 isc_task_setname(zmgr->task, "zmgr", zmgr);
16095 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16096 &zmgr->notifyrl);
16097 if (result != ISC_R_SUCCESS)
16098 goto free_task;
16099
16100 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16101 &zmgr->refreshrl);
16102 if (result != ISC_R_SUCCESS)
16103 goto free_notifyrl;
16104
16105 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16106 &zmgr->startupnotifyrl);
16107 if (result != ISC_R_SUCCESS)
16108 goto free_refreshrl;
16109
16110 result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,
16111 &zmgr->startuprefreshrl);
16112 if (result != ISC_R_SUCCESS)
16113 goto free_startupnotifyrl;
16114
16115 /* default to 20 refresh queries / notifies per second. */
16116 setrl(zmgr->notifyrl, &zmgr->notifyrate, 20);
16117 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, 20);
16118 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, 20);
16119 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, 20);
16120 isc_ratelimiter_setpushpop(zmgr->startupnotifyrl, ISC_TRUE);
16121 isc_ratelimiter_setpushpop(zmgr->startuprefreshrl, ISC_TRUE);
16122
16123 zmgr->iolimit = 1;
16124 zmgr->ioactive = 0;
16125 ISC_LIST_INIT(zmgr->high);
16126 ISC_LIST_INIT(zmgr->low);
16127
16128 result = isc_mutex_init(&zmgr->iolock);
16129 if (result != ISC_R_SUCCESS)
16130 goto free_startuprefreshrl;
16131
16132 zmgr->magic = ZONEMGR_MAGIC;
16133
16134 *zmgrp = zmgr;
16135 return (ISC_R_SUCCESS);
16136
16137 #if 0
16138 free_iolock:
16139 DESTROYLOCK(&zmgr->iolock);
16140 #endif
16141 free_startuprefreshrl:
16142 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
16143 free_startupnotifyrl:
16144 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
16145 free_refreshrl:
16146 isc_ratelimiter_detach(&zmgr->refreshrl);
16147 free_notifyrl:
16148 isc_ratelimiter_detach(&zmgr->notifyrl);
16149 free_task:
16150 isc_task_detach(&zmgr->task);
16151 free_urlock:
16152 isc_rwlock_destroy(&zmgr->urlock);
16153 free_rwlock:
16154 isc_rwlock_destroy(&zmgr->rwlock);
16155 free_mem:
16156 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
16157 isc_mem_detach(&mctx);
16158 return (result);
16159 }
16160
16161 isc_result_t
16162 dns_zonemgr_createzone(dns_zonemgr_t *zmgr, dns_zone_t **zonep) {
16163 isc_result_t result;
16164 isc_mem_t *mctx = NULL;
16165 dns_zone_t *zone = NULL;
16166 void *item;
16167
16168 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16169 REQUIRE(zonep != NULL && *zonep == NULL);
16170
16171 if (zmgr->mctxpool == NULL)
16172 return (ISC_R_FAILURE);
16173
16174 item = isc_pool_get(zmgr->mctxpool);
16175 if (item == NULL)
16176 return (ISC_R_FAILURE);
16177
16178 isc_mem_attach((isc_mem_t *) item, &mctx);
16179 result = dns_zone_create(&zone, mctx);
16180 isc_mem_detach(&mctx);
16181
16182 if (result == ISC_R_SUCCESS)
16183 *zonep = zone;
16184
16185 return (result);
16186 }
16187
16188 isc_result_t
16189 dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16190 isc_result_t result;
16191
16192 REQUIRE(DNS_ZONE_VALID(zone));
16193 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16194
16195 if (zmgr->zonetasks == NULL)
16196 return (ISC_R_FAILURE);
16197
16198 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16199 LOCK_ZONE(zone);
16200 REQUIRE(zone->task == NULL);
16201 REQUIRE(zone->timer == NULL);
16202 REQUIRE(zone->zmgr == NULL);
16203
16204 isc_taskpool_gettask(zmgr->zonetasks, &zone->task);
16205 isc_taskpool_gettask(zmgr->loadtasks, &zone->loadtask);
16206
16207 /*
16208 * Set the task name. The tag will arbitrarily point to one
16209 * of the zones sharing the task (in practice, the one
16210 * to be managed last).
16211 */
16212 isc_task_setname(zone->task, "zone", zone);
16213 isc_task_setname(zone->loadtask, "loadzone", zone);
16214
16215 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
16216 NULL, NULL,
16217 zone->task, zone_timer, zone,
16218 &zone->timer);
16219
16220 if (result != ISC_R_SUCCESS)
16221 goto cleanup_tasks;
16222
16223 /*
16224 * The timer "holds" a iref.
16225 */
16226 zone->irefs++;
16227 INSIST(zone->irefs != 0);
16228
16229 ISC_LIST_APPEND(zmgr->zones, zone, link);
16230 zone->zmgr = zmgr;
16231 zmgr->refs++;
16232
16233 goto unlock;
16234
16235 cleanup_tasks:
16236 isc_task_detach(&zone->loadtask);
16237 isc_task_detach(&zone->task);
16238
16239 unlock:
16240 UNLOCK_ZONE(zone);
16241 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16242 return (result);
16243 }
16244
16245 void
16246 dns_zonemgr_releasezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16247 isc_boolean_t free_now = ISC_FALSE;
16248
16249 REQUIRE(DNS_ZONE_VALID(zone));
16250 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16251 REQUIRE(zone->zmgr == zmgr);
16252
16253 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16254 LOCK_ZONE(zone);
16255
16256 ISC_LIST_UNLINK(zmgr->zones, zone, link);
16257 zone->zmgr = NULL;
16258 zmgr->refs--;
16259 if (zmgr->refs == 0)
16260 free_now = ISC_TRUE;
16261
16262 UNLOCK_ZONE(zone);
16263 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16264
16265 if (free_now)
16266 zonemgr_free(zmgr);
16267 ENSURE(zone->zmgr == NULL);
16268 }
16269
16270 void
16271 dns_zonemgr_attach(dns_zonemgr_t *source, dns_zonemgr_t **target) {
16272 REQUIRE(DNS_ZONEMGR_VALID(source));
16273 REQUIRE(target != NULL && *target == NULL);
16274
16275 RWLOCK(&source->rwlock, isc_rwlocktype_write);
16276 REQUIRE(source->refs > 0);
16277 source->refs++;
16278 INSIST(source->refs > 0);
16279 RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
16280 *target = source;
16281 }
16282
16283 void
16284 dns_zonemgr_detach(dns_zonemgr_t **zmgrp) {
16285 dns_zonemgr_t *zmgr;
16286 isc_boolean_t free_now = ISC_FALSE;
16287
16288 REQUIRE(zmgrp != NULL);
16289 zmgr = *zmgrp;
16290 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16291
16292 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16293 zmgr->refs--;
16294 if (zmgr->refs == 0)
16295 free_now = ISC_TRUE;
16296 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16297
16298 if (free_now)
16299 zonemgr_free(zmgr);
16300 *zmgrp = NULL;
16301 }
16302
16303 isc_result_t
16304 dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) {
16305 dns_zone_t *p;
16306
16307 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16308
16309 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16310 for (p = ISC_LIST_HEAD(zmgr->zones);
16311 p != NULL;
16312 p = ISC_LIST_NEXT(p, link))
16313 {
16314 dns_zone_maintenance(p);
16315 }
16316 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16317
16318 /*
16319 * Recent configuration changes may have increased the
16320 * amount of available transfers quota. Make sure any
16321 * transfers currently blocked on quota get started if
16322 * possible.
16323 */
16324 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16325 zmgr_resume_xfrs(zmgr, ISC_TRUE);
16326 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16327 return (ISC_R_SUCCESS);
16328 }
16329
16330 void
16331 dns_zonemgr_resumexfrs(dns_zonemgr_t *zmgr) {
16332
16333 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16334
16335 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16336 zmgr_resume_xfrs(zmgr, ISC_TRUE);
16337 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
16338 }
16339
16340 void
16341 dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {
16342 dns_zone_t *zone;
16343
16344 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16345
16346 isc_ratelimiter_shutdown(zmgr->notifyrl);
16347 isc_ratelimiter_shutdown(zmgr->refreshrl);
16348 isc_ratelimiter_shutdown(zmgr->startupnotifyrl);
16349 isc_ratelimiter_shutdown(zmgr->startuprefreshrl);
16350
16351 if (zmgr->task != NULL)
16352 isc_task_destroy(&zmgr->task);
16353 if (zmgr->zonetasks != NULL)
16354 isc_taskpool_destroy(&zmgr->zonetasks);
16355 if (zmgr->loadtasks != NULL)
16356 isc_taskpool_destroy(&zmgr->loadtasks);
16357 if (zmgr->mctxpool != NULL)
16358 isc_pool_destroy(&zmgr->mctxpool);
16359
16360 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16361 for (zone = ISC_LIST_HEAD(zmgr->zones);
16362 zone != NULL;
16363 zone = ISC_LIST_NEXT(zone, link))
16364 {
16365 LOCK_ZONE(zone);
16366 forward_cancel(zone);
16367 UNLOCK_ZONE(zone);
16368 }
16369 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
16370 }
16371
16372 static isc_result_t
16373 mctxinit(void **target, void *arg) {
16374 isc_result_t result;
16375 isc_mem_t *mctx = NULL;
16376
16377 UNUSED(arg);
16378
16379 REQUIRE(target != NULL && *target == NULL);
16380
16381 result = isc_mem_create(0, 0, &mctx);
16382 if (result != ISC_R_SUCCESS)
16383 return (result);
16384 isc_mem_setname(mctx, "zonemgr-pool", NULL);
16385
16386 *target = mctx;
16387 return (ISC_R_SUCCESS);
16388 }
16389
16390 static void
16391 mctxfree(void **target) {
16392 isc_mem_t *mctx = *(isc_mem_t **) target;
16393 isc_mem_detach(&mctx);
16394 *target = NULL;
16395 }
16396
16397 #define ZONES_PER_TASK 100
16398 #define ZONES_PER_MCTX 1000
16399
16400 isc_result_t
16401 dns_zonemgr_setsize(dns_zonemgr_t *zmgr, int num_zones) {
16402 isc_result_t result;
16403 int ntasks = num_zones / ZONES_PER_TASK;
16404 int nmctx = num_zones / ZONES_PER_MCTX;
16405 isc_taskpool_t *pool = NULL;
16406 isc_pool_t *mctxpool = NULL;
16407
16408 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16409
16410 /*
16411 * For anything fewer than 1000 zones we use 10 tasks in
16412 * the task pools. More than that, and we'll scale at one
16413 * task per 100 zones. Similarly, for anything smaller than
16414 * 2000 zones we use 2 memory contexts, then scale at 1:1000.
16415 */
16416 if (ntasks < 10)
16417 ntasks = 10;
16418 if (nmctx < 2)
16419 nmctx = 2;
16420
16421 /* Create or resize the zone task pools. */
16422 if (zmgr->zonetasks == NULL)
16423 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16424 ntasks, 2, &pool);
16425 else
16426 result = isc_taskpool_expand(&zmgr->zonetasks, ntasks, &pool);
16427
16428 if (result == ISC_R_SUCCESS)
16429 zmgr->zonetasks = pool;
16430
16431 pool = NULL;
16432 if (zmgr->loadtasks == NULL)
16433 result = isc_taskpool_create(zmgr->taskmgr, zmgr->mctx,
16434 ntasks, 2, &pool);
16435 else
16436 result = isc_taskpool_expand(&zmgr->loadtasks, ntasks, &pool);
16437
16438 if (result == ISC_R_SUCCESS)
16439 zmgr->loadtasks = pool;
16440
16441 /*
16442 * We always set all tasks in the zone-load task pool to
16443 * privileged. This prevents other tasks in the system from
16444 * running while the server task manager is in privileged
16445 * mode.
16446 *
16447 * NOTE: If we start using task privileges for any other
16448 * part of the system than zone tasks, then this will need to be
16449 * revisted. In that case we'd want to turn on privileges for
16450 * zone tasks only when we were loading, and turn them off the
16451 * rest of the time. For now, however, it's okay to just
16452 * set it and forget it.
16453 */
16454 isc_taskpool_setprivilege(zmgr->loadtasks, ISC_TRUE);
16455
16456 /* Create or resize the zone memory context pool. */
16457 if (zmgr->mctxpool == NULL)
16458 result = isc_pool_create(zmgr->mctx, nmctx, mctxfree,
16459 mctxinit, NULL, &mctxpool);
16460 else
16461 result = isc_pool_expand(&zmgr->mctxpool, nmctx, &mctxpool);
16462
16463 if (result == ISC_R_SUCCESS)
16464 zmgr->mctxpool = mctxpool;
16465
16466 return (result);
16467 }
16468
16469 static void
16470 zonemgr_free(dns_zonemgr_t *zmgr) {
16471 isc_mem_t *mctx;
16472
16473 INSIST(zmgr->refs == 0);
16474 INSIST(ISC_LIST_EMPTY(zmgr->zones));
16475
16476 zmgr->magic = 0;
16477
16478 DESTROYLOCK(&zmgr->iolock);
16479 isc_ratelimiter_detach(&zmgr->notifyrl);
16480 isc_ratelimiter_detach(&zmgr->refreshrl);
16481 isc_ratelimiter_detach(&zmgr->startupnotifyrl);
16482 isc_ratelimiter_detach(&zmgr->startuprefreshrl);
16483
16484 isc_rwlock_destroy(&zmgr->urlock);
16485 isc_rwlock_destroy(&zmgr->rwlock);
16486 mctx = zmgr->mctx;
16487 isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr));
16488 isc_mem_detach(&mctx);
16489 }
16490
16491 void
16492 dns_zonemgr_settransfersin(dns_zonemgr_t *zmgr, isc_uint32_t value) {
16493 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16494
16495 zmgr->transfersin = value;
16496 }
16497
16498 isc_uint32_t
16499 dns_zonemgr_getttransfersin(dns_zonemgr_t *zmgr) {
16500 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16501
16502 return (zmgr->transfersin);
16503 }
16504
16505 void
16506 dns_zonemgr_settransfersperns(dns_zonemgr_t *zmgr, isc_uint32_t value) {
16507 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16508
16509 zmgr->transfersperns = value;
16510 }
16511
16512 isc_uint32_t
16513 dns_zonemgr_getttransfersperns(dns_zonemgr_t *zmgr) {
16514 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16515
16516 return (zmgr->transfersperns);
16517 }
16518
16519 /*
16520 * Try to start a new incoming zone transfer to fill a quota
16521 * slot that was just vacated.
16522 *
16523 * Requires:
16524 * The zone manager is locked by the caller.
16525 */
16526 static void
16527 zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi) {
16528 dns_zone_t *zone;
16529 dns_zone_t *next;
16530
16531 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
16532 zone != NULL;
16533 zone = next)
16534 {
16535 isc_result_t result;
16536 next = ISC_LIST_NEXT(zone, statelink);
16537 result = zmgr_start_xfrin_ifquota(zmgr, zone);
16538 if (result == ISC_R_SUCCESS) {
16539 if (multi)
16540 continue;
16541 /*
16542 * We successfully filled the slot. We're done.
16543 */
16544 break;
16545 } else if (result == ISC_R_QUOTA) {
16546 /*
16547 * Not enough quota. This is probably the per-server
16548 * quota, because we usually get called when a unit of
16549 * global quota has just been freed. Try the next
16550 * zone, it may succeed if it uses another master.
16551 */
16552 continue;
16553 } else {
16554 dns_zone_log(zone, ISC_LOG_DEBUG(1),
16555 "starting zone transfer: %s",
16556 isc_result_totext(result));
16557 break;
16558 }
16559 }
16560 }
16561
16562 /*
16563 * Try to start an incoming zone transfer for 'zone', quota permitting.
16564 *
16565 * Requires:
16566 * The zone manager is locked by the caller.
16567 *
16568 * Returns:
16569 * ISC_R_SUCCESS There was enough quota and we attempted to
16570 * start a transfer. zone_xfrdone() has been or will
16571 * be called.
16572 * ISC_R_QUOTA Not enough quota.
16573 * Others Failure.
16574 */
16575 static isc_result_t
16576 zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone) {
16577 dns_peer_t *peer = NULL;
16578 isc_netaddr_t masterip;
16579 isc_uint32_t nxfrsin, nxfrsperns;
16580 dns_zone_t *x;
16581 isc_uint32_t maxtransfersin, maxtransfersperns;
16582 isc_event_t *e;
16583
16584 /*
16585 * If we are exiting just pretend we got quota so the zone will
16586 * be cleaned up in the zone's task context.
16587 */
16588 LOCK_ZONE(zone);
16589 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
16590 UNLOCK_ZONE(zone);
16591 goto gotquota;
16592 }
16593
16594 /*
16595 * Find any configured information about the server we'd
16596 * like to transfer this zone from.
16597 */
16598 isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
16599 (void)dns_peerlist_peerbyaddr(zone->view->peers, &masterip, &peer);
16600 UNLOCK_ZONE(zone);
16601
16602 /*
16603 * Determine the total maximum number of simultaneous
16604 * transfers allowed, and the maximum for this specific
16605 * master.
16606 */
16607 maxtransfersin = zmgr->transfersin;
16608 maxtransfersperns = zmgr->transfersperns;
16609 if (peer != NULL)
16610 (void)dns_peer_gettransfers(peer, &maxtransfersperns);
16611
16612 /*
16613 * Count the total number of transfers that are in progress,
16614 * and the number of transfers in progress from this master.
16615 * We linearly scan a list of all transfers; if this turns
16616 * out to be too slow, we could hash on the master address.
16617 */
16618 nxfrsin = nxfrsperns = 0;
16619 for (x = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
16620 x != NULL;
16621 x = ISC_LIST_NEXT(x, statelink))
16622 {
16623 isc_netaddr_t xip;
16624
16625 LOCK_ZONE(x);
16626 isc_netaddr_fromsockaddr(&xip, &x->masteraddr);
16627 UNLOCK_ZONE(x);
16628
16629 nxfrsin++;
16630 if (isc_netaddr_equal(&xip, &masterip))
16631 nxfrsperns++;
16632 }
16633
16634 /* Enforce quota. */
16635 if (nxfrsin >= maxtransfersin)
16636 return (ISC_R_QUOTA);
16637
16638 if (nxfrsperns >= maxtransfersperns)
16639 return (ISC_R_QUOTA);
16640
16641 gotquota:
16642 /*
16643 * We have sufficient quota. Move the zone to the "xfrin_in_progress"
16644 * list and send it an event to let it start the actual transfer in the
16645 * context of its own task.
16646 */
16647 e = isc_event_allocate(zmgr->mctx, zmgr, DNS_EVENT_ZONESTARTXFRIN,
16648 got_transfer_quota, zone, sizeof(isc_event_t));
16649 if (e == NULL)
16650 return (ISC_R_NOMEMORY);
16651
16652 LOCK_ZONE(zone);
16653 INSIST(zone->statelist == &zmgr->waiting_for_xfrin);
16654 ISC_LIST_UNLINK(zmgr->waiting_for_xfrin, zone, statelink);
16655 ISC_LIST_APPEND(zmgr->xfrin_in_progress, zone, statelink);
16656 zone->statelist = &zmgr->xfrin_in_progress;
16657 isc_task_send(zone->task, &e);
16658 dns_zone_log(zone, ISC_LOG_INFO, "Transfer started.");
16659 UNLOCK_ZONE(zone);
16660
16661 return (ISC_R_SUCCESS);
16662 }
16663
16664 void
16665 dns_zonemgr_setiolimit(dns_zonemgr_t *zmgr, isc_uint32_t iolimit) {
16666
16667 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16668 REQUIRE(iolimit > 0);
16669
16670 zmgr->iolimit = iolimit;
16671 }
16672
16673 isc_uint32_t
16674 dns_zonemgr_getiolimit(dns_zonemgr_t *zmgr) {
16675
16676 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16677
16678 return (zmgr->iolimit);
16679 }
16680
16681 /*
16682 * Get permission to request a file handle from the OS.
16683 * An event will be sent to action when one is available.
16684 * There are two queues available (high and low), the high
16685 * queue will be serviced before the low one.
16686 *
16687 * zonemgr_putio() must be called after the event is delivered to
16688 * 'action'.
16689 */
16690
16691 static isc_result_t
16692 zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high,
16693 isc_task_t *task, isc_taskaction_t action, void *arg,
16694 dns_io_t **iop)
16695 {
16696 dns_io_t *io;
16697 isc_boolean_t queue;
16698
16699 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16700 REQUIRE(iop != NULL && *iop == NULL);
16701
16702 io = isc_mem_get(zmgr->mctx, sizeof(*io));
16703 if (io == NULL)
16704 return (ISC_R_NOMEMORY);
16705
16706 io->event = isc_event_allocate(zmgr->mctx, task, DNS_EVENT_IOREADY,
16707 action, arg, sizeof(*io->event));
16708 if (io->event == NULL) {
16709 isc_mem_put(zmgr->mctx, io, sizeof(*io));
16710 return (ISC_R_NOMEMORY);
16711 }
16712
16713 io->zmgr = zmgr;
16714 io->high = high;
16715 io->task = NULL;
16716 isc_task_attach(task, &io->task);
16717 ISC_LINK_INIT(io, link);
16718 io->magic = IO_MAGIC;
16719
16720 LOCK(&zmgr->iolock);
16721 zmgr->ioactive++;
16722 queue = ISC_TF(zmgr->ioactive > zmgr->iolimit);
16723 if (queue) {
16724 if (io->high)
16725 ISC_LIST_APPEND(zmgr->high, io, link);
16726 else
16727 ISC_LIST_APPEND(zmgr->low, io, link);
16728 }
16729 UNLOCK(&zmgr->iolock);
16730 *iop = io;
16731
16732 if (!queue)
16733 isc_task_send(io->task, &io->event);
16734 return (ISC_R_SUCCESS);
16735 }
16736
16737 static void
16738 zonemgr_putio(dns_io_t **iop) {
16739 dns_io_t *io;
16740 dns_io_t *next;
16741 dns_zonemgr_t *zmgr;
16742
16743 REQUIRE(iop != NULL);
16744 io = *iop;
16745 REQUIRE(DNS_IO_VALID(io));
16746
16747 *iop = NULL;
16748
16749 INSIST(!ISC_LINK_LINKED(io, link));
16750 INSIST(io->event == NULL);
16751
16752 zmgr = io->zmgr;
16753 isc_task_detach(&io->task);
16754 io->magic = 0;
16755 isc_mem_put(zmgr->mctx, io, sizeof(*io));
16756
16757 LOCK(&zmgr->iolock);
16758 INSIST(zmgr->ioactive > 0);
16759 zmgr->ioactive--;
16760 next = HEAD(zmgr->high);
16761 if (next == NULL)
16762 next = HEAD(zmgr->low);
16763 if (next != NULL) {
16764 if (next->high)
16765 ISC_LIST_UNLINK(zmgr->high, next, link);
16766 else
16767 ISC_LIST_UNLINK(zmgr->low, next, link);
16768 INSIST(next->event != NULL);
16769 }
16770 UNLOCK(&zmgr->iolock);
16771 if (next != NULL)
16772 isc_task_send(next->task, &next->event);
16773 }
16774
16775 static void
16776 zonemgr_cancelio(dns_io_t *io) {
16777 isc_boolean_t send_event = ISC_FALSE;
16778
16779 REQUIRE(DNS_IO_VALID(io));
16780
16781 /*
16782 * If we are queued to be run then dequeue.
16783 */
16784 LOCK(&io->zmgr->iolock);
16785 if (ISC_LINK_LINKED(io, link)) {
16786 if (io->high)
16787 ISC_LIST_UNLINK(io->zmgr->high, io, link);
16788 else
16789 ISC_LIST_UNLINK(io->zmgr->low, io, link);
16790
16791 send_event = ISC_TRUE;
16792 INSIST(io->event != NULL);
16793 }
16794 UNLOCK(&io->zmgr->iolock);
16795 if (send_event) {
16796 io->event->ev_attributes |= ISC_EVENTATTR_CANCELED;
16797 isc_task_send(io->task, &io->event);
16798 }
16799 }
16800
16801 static void
16802 zone_saveunique(dns_zone_t *zone, const char *path, const char *templat) {
16803 char *buf;
16804 int buflen;
16805 isc_result_t result;
16806
16807 buflen = strlen(path) + strlen(templat) + 2;
16808
16809 buf = isc_mem_get(zone->mctx, buflen);
16810 if (buf == NULL)
16811 return;
16812
16813 result = isc_file_template(path, templat, buf, buflen);
16814 if (result != ISC_R_SUCCESS)
16815 goto cleanup;
16816
16817 result = isc_file_renameunique(path, buf);
16818 if (result != ISC_R_SUCCESS)
16819 goto cleanup;
16820
16821 dns_zone_log(zone, ISC_LOG_WARNING, "unable to load from '%s'; "
16822 "renaming file to '%s' for failure analysis and "
16823 "retransferring.", path, buf);
16824
16825 cleanup:
16826 isc_mem_put(zone->mctx, buf, buflen);
16827 }
16828
16829 #if 0
16830 /* Hook for ondestroy notification from a database. */
16831
16832 static void
16833 dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event) {
16834 dns_db_t *db = event->sender;
16835 UNUSED(task);
16836
16837 isc_event_free(&event);
16838
16839 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16840 DNS_LOGMODULE_ZONE, ISC_LOG_DEBUG(3),
16841 "database (%p) destroyed", (void*) db);
16842 }
16843 #endif
16844
16845 static void
16846 setrl(isc_ratelimiter_t *rl, unsigned int *rate, unsigned int value) {
16847 isc_interval_t interval;
16848 isc_uint32_t s, ns;
16849 isc_uint32_t pertic;
16850 isc_result_t result;
16851
16852 if (value == 0)
16853 value = 1;
16854
16855 if (value == 1) {
16856 s = 1;
16857 ns = 0;
16858 pertic = 1;
16859 } else if (value <= 10) {
16860 s = 0;
16861 ns = 1000000000 / value;
16862 pertic = 1;
16863 } else {
16864 s = 0;
16865 ns = (1000000000 / value) * 10;
16866 pertic = 10;
16867 }
16868
16869 isc_interval_set(&interval, s, ns);
16870
16871 result = isc_ratelimiter_setinterval(rl, &interval);
16872 RUNTIME_CHECK(result == ISC_R_SUCCESS);
16873 isc_ratelimiter_setpertic(rl, pertic);
16874
16875 *rate = value;
16876 }
16877
16878 void
16879 dns_zonemgr_setnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
16880
16881 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16882
16883 setrl(zmgr->notifyrl, &zmgr->notifyrate, value);
16884 }
16885
16886 void
16887 dns_zonemgr_setstartupnotifyrate(dns_zonemgr_t *zmgr, unsigned int value) {
16888
16889 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16890
16891 setrl(zmgr->startupnotifyrl, &zmgr->startupnotifyrate, value);
16892 }
16893
16894 void
16895 dns_zonemgr_setserialqueryrate(dns_zonemgr_t *zmgr, unsigned int value) {
16896
16897 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16898
16899 setrl(zmgr->refreshrl, &zmgr->serialqueryrate, value);
16900 /* XXXMPA seperate out once we have the code to support this. */
16901 setrl(zmgr->startuprefreshrl, &zmgr->startupserialqueryrate, value);
16902 }
16903
16904 unsigned int
16905 dns_zonemgr_getnotifyrate(dns_zonemgr_t *zmgr) {
16906 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16907
16908 return (zmgr->notifyrate);
16909 }
16910
16911 unsigned int
16912 dns_zonemgr_getstartupnotifyrate(dns_zonemgr_t *zmgr) {
16913 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16914
16915 return (zmgr->startupnotifyrate);
16916 }
16917
16918 unsigned int
16919 dns_zonemgr_getserialqueryrate(dns_zonemgr_t *zmgr) {
16920 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16921
16922 return (zmgr->serialqueryrate);
16923 }
16924
16925 isc_boolean_t
16926 dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16927 isc_sockaddr_t *local, isc_time_t *now)
16928 {
16929 unsigned int i;
16930 isc_rwlocktype_t locktype;
16931 isc_result_t result;
16932 isc_uint32_t seconds = isc_time_seconds(now);
16933 isc_uint32_t count = 0;
16934
16935 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16936
16937 locktype = isc_rwlocktype_read;
16938 RWLOCK(&zmgr->urlock, locktype);
16939 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16940 if (zmgr->unreachable[i].expire >= seconds &&
16941 isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16942 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
16943 result = isc_rwlock_tryupgrade(&zmgr->urlock);
16944 if (result == ISC_R_SUCCESS) {
16945 locktype = isc_rwlocktype_write;
16946 zmgr->unreachable[i].last = seconds;
16947 count = zmgr->unreachable[i].count;
16948 }
16949 break;
16950 }
16951 }
16952 RWUNLOCK(&zmgr->urlock, locktype);
16953 return (ISC_TF(i < UNREACH_CHACHE_SIZE && count > 1U));
16954 }
16955
16956 void
16957 dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16958 isc_sockaddr_t *local)
16959 {
16960 unsigned int i;
16961 isc_rwlocktype_t locktype;
16962 isc_result_t result;
16963
16964 char master[ISC_SOCKADDR_FORMATSIZE];
16965 char source[ISC_SOCKADDR_FORMATSIZE];
16966
16967 isc_sockaddr_format(remote, master, sizeof(master));
16968 isc_sockaddr_format(local, source, sizeof(source));
16969
16970 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
16971
16972 locktype = isc_rwlocktype_read;
16973 RWLOCK(&zmgr->urlock, locktype);
16974 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
16975 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
16976 isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) {
16977 if (zmgr->unreachable[i].expire == 0)
16978 break;
16979 result = isc_rwlock_tryupgrade(&zmgr->urlock);
16980 if (result == ISC_R_SUCCESS) {
16981 locktype = isc_rwlocktype_write;
16982 zmgr->unreachable[i].expire = 0;
16983 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
16984 DNS_LOGMODULE_ZONE, ISC_LOG_INFO,
16985 "master %s (source %s) deleted "
16986 "from unreachable cache",
16987 master, source);
16988 }
16989 break;
16990 }
16991 }
16992 RWUNLOCK(&zmgr->urlock, locktype);
16993 }
16994
16995 void
16996 dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,
16997 isc_sockaddr_t *local, isc_time_t *now)
16998 {
16999 isc_uint32_t seconds = isc_time_seconds(now);
17000 isc_uint32_t last = seconds;
17001 unsigned int i, slot = UNREACH_CHACHE_SIZE, oldest = 0;
17002
17003 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17004
17005 RWLOCK(&zmgr->urlock, isc_rwlocktype_write);
17006 for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {
17007 /* Existing entry? */
17008 if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&
17009 isc_sockaddr_equal(&zmgr->unreachable[i].local, local))
17010 break;
17011 /* Empty slot? */
17012 if (zmgr->unreachable[i].expire < seconds)
17013 slot = i;
17014 /* Least recently used slot? */
17015 if (zmgr->unreachable[i].last < last) {
17016 last = zmgr->unreachable[i].last;
17017 oldest = i;
17018 }
17019 }
17020 if (i < UNREACH_CHACHE_SIZE) {
17021 /*
17022 * Found a existing entry. Update the expire timer and
17023 * last usage timestamps.
17024 */
17025 zmgr->unreachable[i].expire = seconds + UNREACH_HOLD_TIME;
17026 zmgr->unreachable[i].last = seconds;
17027 if (zmgr->unreachable[i].expire < seconds)
17028 zmgr->unreachable[i].count = 1;
17029 else
17030 zmgr->unreachable[i].count++;
17031 } else if (slot != UNREACH_CHACHE_SIZE) {
17032 /*
17033 * Found a empty slot. Add a new entry to the cache.
17034 */
17035 zmgr->unreachable[slot].expire = seconds + UNREACH_HOLD_TIME;
17036 zmgr->unreachable[slot].last = seconds;
17037 zmgr->unreachable[slot].remote = *remote;
17038 zmgr->unreachable[slot].local = *local;
17039 zmgr->unreachable[slot].count = 1;
17040 } else {
17041 /*
17042 * Replace the least recently used entry in the cache.
17043 */
17044 zmgr->unreachable[oldest].expire = seconds + UNREACH_HOLD_TIME;
17045 zmgr->unreachable[oldest].last = seconds;
17046 zmgr->unreachable[oldest].remote = *remote;
17047 zmgr->unreachable[oldest].local = *local;
17048 zmgr->unreachable[oldest].count = 1;
17049 }
17050 RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);
17051 }
17052
17053 void
17054 dns_zone_forcereload(dns_zone_t *zone) {
17055 REQUIRE(DNS_ZONE_VALID(zone));
17056
17057 if (zone->type == dns_zone_master ||
17058 (zone->type == dns_zone_redirect && zone->masters == NULL))
17059 return;
17060
17061 LOCK_ZONE(zone);
17062 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FORCEXFER);
17063 UNLOCK_ZONE(zone);
17064 dns_zone_refresh(zone);
17065 }
17066
17067 isc_boolean_t
17068 dns_zone_isforced(dns_zone_t *zone) {
17069 REQUIRE(DNS_ZONE_VALID(zone));
17070
17071 return (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FORCEXFER));
17072 }
17073
17074 isc_result_t
17075 dns_zone_setstatistics(dns_zone_t *zone, isc_boolean_t on) {
17076 /*
17077 * This function is obsoleted.
17078 */
17079 UNUSED(zone);
17080 UNUSED(on);
17081 return (ISC_R_NOTIMPLEMENTED);
17082 }
17083
17084 isc_uint64_t *
17085 dns_zone_getstatscounters(dns_zone_t *zone) {
17086 /*
17087 * This function is obsoleted.
17088 */
17089 UNUSED(zone);
17090 return (NULL);
17091 }
17092
17093 void
17094 dns_zone_setstats(dns_zone_t *zone, isc_stats_t *stats) {
17095 REQUIRE(DNS_ZONE_VALID(zone));
17096 REQUIRE(zone->stats == NULL);
17097
17098 LOCK_ZONE(zone);
17099 zone->stats = NULL;
17100 isc_stats_attach(stats, &zone->stats);
17101 UNLOCK_ZONE(zone);
17102 }
17103
17104 void
17105 dns_zone_setrequeststats(dns_zone_t *zone, isc_stats_t *stats) {
17106
17107 REQUIRE(DNS_ZONE_VALID(zone));
17108
17109 LOCK_ZONE(zone);
17110 if (zone->requeststats_on && stats == NULL)
17111 zone->requeststats_on = ISC_FALSE;
17112 else if (!zone->requeststats_on && stats != NULL) {
17113 if (zone->requeststats == NULL) {
17114 isc_stats_attach(stats, &zone->requeststats);
17115 zone->requeststats_on = ISC_TRUE;
17116 }
17117 }
17118 UNLOCK_ZONE(zone);
17119 }
17120
17121 void
17122 dns_zone_setrcvquerystats(dns_zone_t *zone, dns_stats_t *stats) {
17123
17124 REQUIRE(DNS_ZONE_VALID(zone));
17125
17126 LOCK_ZONE(zone);
17127 if (zone->requeststats_on && stats != NULL) {
17128 if (zone->rcvquerystats == NULL) {
17129 dns_stats_attach(stats, &zone->rcvquerystats);
17130 zone->requeststats_on = ISC_TRUE;
17131 }
17132 }
17133 UNLOCK_ZONE(zone);
17134 }
17135
17136 isc_stats_t *
17137 dns_zone_getrequeststats(dns_zone_t *zone) {
17138 /*
17139 * We don't lock zone for efficiency reason. This is not catastrophic
17140 * because requeststats must always be valid when requeststats_on is
17141 * true.
17142 * Some counters may be incremented while requeststats_on is becoming
17143 * false, or some cannot be incremented just after the statistics are
17144 * installed, but it shouldn't matter much in practice.
17145 */
17146 if (zone->requeststats_on)
17147 return (zone->requeststats);
17148 else
17149 return (NULL);
17150 }
17151
17152 /*
17153 * Return the received query stats bucket
17154 * see note from dns_zone_getrequeststats()
17155 */
17156 dns_stats_t *
17157 dns_zone_getrcvquerystats(dns_zone_t *zone) {
17158 if (zone->requeststats_on)
17159 return (zone->rcvquerystats);
17160 else
17161 return (NULL);
17162 }
17163
17164 void
17165 dns_zone_dialup(dns_zone_t *zone) {
17166
17167 REQUIRE(DNS_ZONE_VALID(zone));
17168
17169 zone_debuglog(zone, "dns_zone_dialup", 3,
17170 "notify = %d, refresh = %d",
17171 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY),
17172 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH));
17173
17174 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALNOTIFY))
17175 dns_zone_notify(zone);
17176 if (zone->type != dns_zone_master && zone->masters != NULL &&
17177 DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH))
17178 dns_zone_refresh(zone);
17179 }
17180
17181 void
17182 dns_zone_setdialup(dns_zone_t *zone, dns_dialuptype_t dialup) {
17183 REQUIRE(DNS_ZONE_VALID(zone));
17184
17185 LOCK_ZONE(zone);
17186 DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DIALNOTIFY |
17187 DNS_ZONEFLG_DIALREFRESH |
17188 DNS_ZONEFLG_NOREFRESH);
17189 switch (dialup) {
17190 case dns_dialuptype_no:
17191 break;
17192 case dns_dialuptype_yes:
17193 DNS_ZONE_SETFLAG(zone, (DNS_ZONEFLG_DIALNOTIFY |
17194 DNS_ZONEFLG_DIALREFRESH |
17195 DNS_ZONEFLG_NOREFRESH));
17196 break;
17197 case dns_dialuptype_notify:
17198 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17199 break;
17200 case dns_dialuptype_notifypassive:
17201 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALNOTIFY);
17202 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17203 break;
17204 case dns_dialuptype_refresh:
17205 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DIALREFRESH);
17206 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17207 break;
17208 case dns_dialuptype_passive:
17209 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOREFRESH);
17210 break;
17211 default:
17212 INSIST(0);
17213 }
17214 UNLOCK_ZONE(zone);
17215 }
17216
17217 isc_result_t
17218 dns_zone_setkeydirectory(dns_zone_t *zone, const char *directory) {
17219 isc_result_t result = ISC_R_SUCCESS;
17220
17221 REQUIRE(DNS_ZONE_VALID(zone));
17222
17223 LOCK_ZONE(zone);
17224 result = dns_zone_setstring(zone, &zone->keydirectory, directory);
17225 UNLOCK_ZONE(zone);
17226
17227 return (result);
17228 }
17229
17230 const char *
17231 dns_zone_getkeydirectory(dns_zone_t *zone) {
17232 REQUIRE(DNS_ZONE_VALID(zone));
17233
17234 return (zone->keydirectory);
17235 }
17236
17237 unsigned int
17238 dns_zonemgr_getcount(dns_zonemgr_t *zmgr, int state) {
17239 dns_zone_t *zone;
17240 unsigned int count = 0;
17241
17242 REQUIRE(DNS_ZONEMGR_VALID(zmgr));
17243
17244 RWLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17245 switch (state) {
17246 case DNS_ZONESTATE_XFERRUNNING:
17247 for (zone = ISC_LIST_HEAD(zmgr->xfrin_in_progress);
17248 zone != NULL;
17249 zone = ISC_LIST_NEXT(zone, statelink))
17250 count++;
17251 break;
17252 case DNS_ZONESTATE_XFERDEFERRED:
17253 for (zone = ISC_LIST_HEAD(zmgr->waiting_for_xfrin);
17254 zone != NULL;
17255 zone = ISC_LIST_NEXT(zone, statelink))
17256 count++;
17257 break;
17258 case DNS_ZONESTATE_SOAQUERY:
17259 for (zone = ISC_LIST_HEAD(zmgr->zones);
17260 zone != NULL;
17261 zone = ISC_LIST_NEXT(zone, link))
17262 if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_REFRESH))
17263 count++;
17264 break;
17265 case DNS_ZONESTATE_ANY:
17266 for (zone = ISC_LIST_HEAD(zmgr->zones);
17267 zone != NULL;
17268 zone = ISC_LIST_NEXT(zone, link)) {
17269 dns_view_t *view = zone->view;
17270 if (view != NULL && strcmp(view->name, "_bind") == 0)
17271 continue;
17272 count++;
17273 }
17274 break;
17275 case DNS_ZONESTATE_AUTOMATIC:
17276 for (zone = ISC_LIST_HEAD(zmgr->zones);
17277 zone != NULL;
17278 zone = ISC_LIST_NEXT(zone, link)) {
17279 dns_view_t *view = zone->view;
17280 if (view != NULL && strcmp(view->name, "_bind") == 0)
17281 continue;
17282 if (zone->automatic)
17283 count++;
17284 }
17285 break;
17286 default:
17287 INSIST(0);
17288 }
17289
17290 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read);
17291
17292 return (count);
17293 }
17294
17295 isc_result_t
17296 dns_zone_checknames(dns_zone_t *zone, const dns_name_t *name,
17297 dns_rdata_t *rdata)
17298 {
17299 isc_boolean_t ok = ISC_TRUE;
17300 isc_boolean_t fail = ISC_FALSE;
17301 char namebuf[DNS_NAME_FORMATSIZE];
17302 char namebuf2[DNS_NAME_FORMATSIZE];
17303 char typebuf[DNS_RDATATYPE_FORMATSIZE];
17304 int level = ISC_LOG_WARNING;
17305 dns_name_t bad;
17306
17307 REQUIRE(DNS_ZONE_VALID(zone));
17308
17309 if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES) &&
17310 rdata->type != dns_rdatatype_nsec3)
17311 return (ISC_R_SUCCESS);
17312
17313 if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL) ||
17314 rdata->type == dns_rdatatype_nsec3) {
17315 level = ISC_LOG_ERROR;
17316 fail = ISC_TRUE;
17317 }
17318
17319 ok = dns_rdata_checkowner(name, rdata->rdclass, rdata->type, ISC_TRUE);
17320 if (!ok) {
17321 dns_name_format(name, namebuf, sizeof(namebuf));
17322 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17323 dns_zone_log(zone, level, "%s/%s: %s", namebuf, typebuf,
17324 dns_result_totext(DNS_R_BADOWNERNAME));
17325 if (fail)
17326 return (DNS_R_BADOWNERNAME);
17327 }
17328
17329 dns_name_init(&bad, NULL);
17330 ok = dns_rdata_checknames(rdata, name, &bad);
17331 if (!ok) {
17332 dns_name_format(name, namebuf, sizeof(namebuf));
17333 dns_name_format(&bad, namebuf2, sizeof(namebuf2));
17334 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
17335 dns_zone_log(zone, level, "%s/%s: %s: %s ", namebuf, typebuf,
17336 namebuf2, dns_result_totext(DNS_R_BADNAME));
17337 if (fail)
17338 return (DNS_R_BADNAME);
17339 }
17340
17341 return (ISC_R_SUCCESS);
17342 }
17343
17344 void
17345 dns_zone_setcheckmx(dns_zone_t *zone, dns_checkmxfunc_t checkmx) {
17346 REQUIRE(DNS_ZONE_VALID(zone));
17347 zone->checkmx = checkmx;
17348 }
17349
17350 void
17351 dns_zone_setchecksrv(dns_zone_t *zone, dns_checksrvfunc_t checksrv) {
17352 REQUIRE(DNS_ZONE_VALID(zone));
17353 zone->checksrv = checksrv;
17354 }
17355
17356 void
17357 dns_zone_setcheckns(dns_zone_t *zone, dns_checknsfunc_t checkns) {
17358 REQUIRE(DNS_ZONE_VALID(zone));
17359 zone->checkns = checkns;
17360 }
17361
17362 void
17363 dns_zone_setisself(dns_zone_t *zone, dns_isselffunc_t isself, void *arg) {
17364 REQUIRE(DNS_ZONE_VALID(zone));
17365
17366 LOCK_ZONE(zone);
17367 zone->isself = isself;
17368 zone->isselfarg = arg;
17369 UNLOCK_ZONE(zone);
17370 }
17371
17372 void
17373 dns_zone_setnotifydelay(dns_zone_t *zone, isc_uint32_t delay) {
17374 REQUIRE(DNS_ZONE_VALID(zone));
17375
17376 LOCK_ZONE(zone);
17377 zone->notifydelay = delay;
17378 UNLOCK_ZONE(zone);
17379 }
17380
17381 isc_uint32_t
17382 dns_zone_getnotifydelay(dns_zone_t *zone) {
17383 REQUIRE(DNS_ZONE_VALID(zone));
17384
17385 return (zone->notifydelay);
17386 }
17387
17388 isc_result_t
17389 dns_zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm,
17390 isc_uint16_t keyid, isc_boolean_t deleteit)
17391 {
17392 isc_result_t result;
17393 REQUIRE(DNS_ZONE_VALID(zone));
17394
17395 dns_zone_log(zone, ISC_LOG_NOTICE,
17396 "dns_zone_signwithkey(algorithm=%u, keyid=%u)",
17397 algorithm, keyid);
17398 LOCK_ZONE(zone);
17399 result = zone_signwithkey(zone, algorithm, keyid, deleteit);
17400 UNLOCK_ZONE(zone);
17401
17402 return (result);
17403 }
17404
17405 /*
17406 * Called when a dynamic update for an NSEC3PARAM record is received.
17407 *
17408 * If set, transform the NSEC3 salt into human-readable form so that it can be
17409 * logged. Then call zone_addnsec3chain(), passing NSEC3PARAM RDATA to it.
17410 */
17411 isc_result_t
17412 dns_zone_addnsec3chain(dns_zone_t *zone, dns_rdata_nsec3param_t *nsec3param) {
17413 isc_result_t result;
17414 char salt[255*2+1];
17415
17416 REQUIRE(DNS_ZONE_VALID(zone));
17417
17418 result = dns_nsec3param_salttotext(nsec3param, salt, sizeof(salt));
17419 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17420 dns_zone_log(zone, ISC_LOG_NOTICE,
17421 "dns_zone_addnsec3chain(hash=%u, iterations=%u, salt=%s)",
17422 nsec3param->hash, nsec3param->iterations,
17423 salt);
17424 LOCK_ZONE(zone);
17425 result = zone_addnsec3chain(zone, nsec3param);
17426 UNLOCK_ZONE(zone);
17427
17428 return (result);
17429 }
17430
17431 void
17432 dns_zone_setnodes(dns_zone_t *zone, isc_uint32_t nodes) {
17433 REQUIRE(DNS_ZONE_VALID(zone));
17434
17435 if (nodes == 0)
17436 nodes = 1;
17437 zone->nodes = nodes;
17438 }
17439
17440 void
17441 dns_zone_setsignatures(dns_zone_t *zone, isc_uint32_t signatures) {
17442 REQUIRE(DNS_ZONE_VALID(zone));
17443
17444 /*
17445 * We treat signatures as a signed value so explicitly
17446 * limit its range here.
17447 */
17448 if (signatures > ISC_INT32_MAX)
17449 signatures = ISC_INT32_MAX;
17450 else if (signatures == 0)
17451 signatures = 1;
17452 zone->signatures = signatures;
17453 }
17454
17455 isc_uint32_t
17456 dns_zone_getsignatures(dns_zone_t *zone) {
17457 REQUIRE(DNS_ZONE_VALID(zone));
17458 return (zone->signatures);
17459 }
17460
17461 void
17462 dns_zone_setprivatetype(dns_zone_t *zone, dns_rdatatype_t type) {
17463 REQUIRE(DNS_ZONE_VALID(zone));
17464 zone->privatetype = type;
17465 }
17466
17467 dns_rdatatype_t
17468 dns_zone_getprivatetype(dns_zone_t *zone) {
17469 REQUIRE(DNS_ZONE_VALID(zone));
17470 return (zone->privatetype);
17471 }
17472
17473 static isc_result_t
17474 zone_signwithkey(dns_zone_t *zone, dns_secalg_t algorithm, isc_uint16_t keyid,
17475 isc_boolean_t deleteit)
17476 {
17477 dns_signing_t *signing;
17478 dns_signing_t *current;
17479 isc_result_t result = ISC_R_SUCCESS;
17480 isc_time_t now;
17481 dns_db_t *db = NULL;
17482
17483 signing = isc_mem_get(zone->mctx, sizeof *signing);
17484 if (signing == NULL)
17485 return (ISC_R_NOMEMORY);
17486
17487 signing->magic = 0;
17488 signing->db = NULL;
17489 signing->dbiterator = NULL;
17490 signing->algorithm = algorithm;
17491 signing->keyid = keyid;
17492 signing->deleteit = deleteit;
17493 signing->done = ISC_FALSE;
17494
17495 TIME_NOW(&now);
17496
17497 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
17498 if (zone->db != NULL)
17499 dns_db_attach(zone->db, &db);
17500 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
17501
17502 if (db == NULL) {
17503 result = ISC_R_NOTFOUND;
17504 goto cleanup;
17505 }
17506
17507 dns_db_attach(db, &signing->db);
17508
17509 for (current = ISC_LIST_HEAD(zone->signing);
17510 current != NULL;
17511 current = ISC_LIST_NEXT(current, link)) {
17512 if (current->db == signing->db &&
17513 current->algorithm == signing->algorithm &&
17514 current->keyid == signing->keyid) {
17515 if (current->deleteit != signing->deleteit)
17516 current->done = ISC_TRUE;
17517 else
17518 goto cleanup;
17519 }
17520 }
17521
17522 result = dns_db_createiterator(signing->db, 0,
17523 &signing->dbiterator);
17524
17525 if (result == ISC_R_SUCCESS)
17526 result = dns_dbiterator_first(signing->dbiterator);
17527 if (result == ISC_R_SUCCESS) {
17528 dns_dbiterator_pause(signing->dbiterator);
17529 ISC_LIST_INITANDAPPEND(zone->signing, signing, link);
17530 signing = NULL;
17531 if (isc_time_isepoch(&zone->signingtime)) {
17532 zone->signingtime = now;
17533 if (zone->task != NULL)
17534 zone_settimer(zone, &now);
17535 }
17536 }
17537
17538 cleanup:
17539 if (signing != NULL) {
17540 if (signing->db != NULL)
17541 dns_db_detach(&signing->db);
17542 if (signing->dbiterator != NULL)
17543 dns_dbiterator_destroy(&signing->dbiterator);
17544 isc_mem_put(zone->mctx, signing, sizeof *signing);
17545 }
17546 if (db != NULL)
17547 dns_db_detach(&db);
17548 return (result);
17549 }
17550
17551 static void
17552 logmsg(const char *format, ...) {
17553 va_list args;
17554 va_start(args, format);
17555 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_ZONE,
17556 ISC_LOG_DEBUG(1), format, args);
17557 va_end(args);
17558 }
17559
17560 static void
17561 clear_keylist(dns_dnsseckeylist_t *list, isc_mem_t *mctx) {
17562 dns_dnsseckey_t *key;
17563 while (!ISC_LIST_EMPTY(*list)) {
17564 key = ISC_LIST_HEAD(*list);
17565 ISC_LIST_UNLINK(*list, key, link);
17566 dns_dnsseckey_destroy(mctx, &key);
17567 }
17568 }
17569
17570 /* Called once; *timep should be set to the current time. */
17571 static isc_result_t
17572 next_keyevent(dst_key_t *key, isc_stdtime_t *timep) {
17573 isc_result_t result;
17574 isc_stdtime_t now, then = 0, event;
17575 int i;
17576
17577 now = *timep;
17578
17579 for (i = 0; i <= DST_MAX_TIMES; i++) {
17580 result = dst_key_gettime(key, i, &event);
17581 if (result == ISC_R_SUCCESS && event > now &&
17582 (then == 0 || event < then))
17583 then = event;
17584 }
17585
17586 if (then != 0) {
17587 *timep = then;
17588 return (ISC_R_SUCCESS);
17589 }
17590
17591 return (ISC_R_NOTFOUND);
17592 }
17593
17594 static isc_result_t
17595 rr_exists(dns_db_t *db, dns_dbversion_t *ver, dns_name_t *name,
17596 const dns_rdata_t *rdata, isc_boolean_t *flag)
17597 {
17598 dns_rdataset_t rdataset;
17599 dns_dbnode_t *node = NULL;
17600 isc_result_t result;
17601
17602 dns_rdataset_init(&rdataset);
17603 if (rdata->type == dns_rdatatype_nsec3)
17604 CHECK(dns_db_findnsec3node(db, name, ISC_FALSE, &node));
17605 else
17606 CHECK(dns_db_findnode(db, name, ISC_FALSE, &node));
17607 result = dns_db_findrdataset(db, node, ver, rdata->type, 0,
17608 (isc_stdtime_t) 0, &rdataset, NULL);
17609 if (result == ISC_R_NOTFOUND) {
17610 *flag = ISC_FALSE;
17611 result = ISC_R_SUCCESS;
17612 goto failure;
17613 }
17614
17615 for (result = dns_rdataset_first(&rdataset);
17616 result == ISC_R_SUCCESS;
17617 result = dns_rdataset_next(&rdataset)) {
17618 dns_rdata_t myrdata = DNS_RDATA_INIT;
17619 dns_rdataset_current(&rdataset, &myrdata);
17620 if (!dns_rdata_compare(&myrdata, rdata))
17621 break;
17622 }
17623 dns_rdataset_disassociate(&rdataset);
17624 if (result == ISC_R_SUCCESS) {
17625 *flag = ISC_TRUE;
17626 } else if (result == ISC_R_NOMORE) {
17627 *flag = ISC_FALSE;
17628 result = ISC_R_SUCCESS;
17629 }
17630
17631 failure:
17632 if (node != NULL)
17633 dns_db_detachnode(db, &node);
17634 return (result);
17635 }
17636
17637 /*
17638 * Add records to signal the state of signing or of key removal.
17639 */
17640 static isc_result_t
17641 add_signing_records(dns_db_t *db, dns_rdatatype_t privatetype,
17642 dns_dbversion_t *ver, dns_diff_t *diff,
17643 isc_boolean_t sign_all)
17644 {
17645 dns_difftuple_t *tuple, *newtuple = NULL;
17646 dns_rdata_dnskey_t dnskey;
17647 dns_rdata_t rdata = DNS_RDATA_INIT;
17648 isc_boolean_t flag;
17649 isc_region_t r;
17650 isc_result_t result = ISC_R_SUCCESS;
17651 isc_uint16_t keyid;
17652 unsigned char buf[5];
17653 dns_name_t *name = dns_db_origin(db);
17654
17655 for (tuple = ISC_LIST_HEAD(diff->tuples);
17656 tuple != NULL;
17657 tuple = ISC_LIST_NEXT(tuple, link)) {
17658 if (tuple->rdata.type != dns_rdatatype_dnskey)
17659 continue;
17660
17661 result = dns_rdata_tostruct(&tuple->rdata, &dnskey, NULL);
17662 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17663 if ((dnskey.flags &
17664 (DNS_KEYFLAG_OWNERMASK|DNS_KEYTYPE_NOAUTH))
17665 != DNS_KEYOWNER_ZONE)
17666 continue;
17667
17668 dns_rdata_toregion(&tuple->rdata, &r);
17669
17670 keyid = dst_region_computeid(&r, dnskey.algorithm);
17671
17672 buf[0] = dnskey.algorithm;
17673 buf[1] = (keyid & 0xff00) >> 8;
17674 buf[2] = (keyid & 0xff);
17675 buf[3] = (tuple->op == DNS_DIFFOP_ADD) ? 0 : 1;
17676 buf[4] = 0;
17677 rdata.data = buf;
17678 rdata.length = sizeof(buf);
17679 rdata.type = privatetype;
17680 rdata.rdclass = tuple->rdata.rdclass;
17681
17682 if (sign_all || tuple->op == DNS_DIFFOP_DEL) {
17683 CHECK(rr_exists(db, ver, name, &rdata, &flag));
17684 if (flag)
17685 continue;
17686 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_ADD,
17687 name, 0, &rdata, &newtuple));
17688 CHECK(do_one_tuple(&newtuple, db, ver, diff));
17689 INSIST(newtuple == NULL);
17690 }
17691
17692 /*
17693 * Remove any record which says this operation has already
17694 * completed.
17695 */
17696 buf[4] = 1;
17697 CHECK(rr_exists(db, ver, name, &rdata, &flag));
17698 if (flag) {
17699 CHECK(dns_difftuple_create(diff->mctx, DNS_DIFFOP_DEL,
17700 name, 0, &rdata, &newtuple));
17701 CHECK(do_one_tuple(&newtuple, db, ver, diff));
17702 INSIST(newtuple == NULL);
17703 }
17704 }
17705 failure:
17706 return (result);
17707 }
17708
17709 static isc_result_t
17710 sign_apex(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17711 isc_stdtime_t now, dns_diff_t *diff, dns__zonediff_t *zonediff)
17712 {
17713 isc_result_t result;
17714 isc_stdtime_t inception, soaexpire;
17715 isc_boolean_t check_ksk, keyset_kskonly;
17716 dst_key_t *zone_keys[DNS_MAXZONEKEYS];
17717 unsigned int nkeys = 0, i;
17718 dns_difftuple_t *tuple;
17719
17720 result = dns__zone_findkeys(zone, db, ver, now, zone->mctx,
17721 DNS_MAXZONEKEYS, zone_keys, &nkeys);
17722 if (result != ISC_R_SUCCESS) {
17723 dns_zone_log(zone, ISC_LOG_ERROR,
17724 "sign_apex:dns__zone_findkeys -> %s",
17725 dns_result_totext(result));
17726 return (result);
17727 }
17728
17729 inception = now - 3600; /* Allow for clock skew. */
17730 soaexpire = now + dns_zone_getsigvalidityinterval(zone);
17731
17732 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
17733 keyset_kskonly = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_DNSKEYKSKONLY);
17734
17735 /*
17736 * See if dns__zone_updatesigs() will update DNSKEY signature and if
17737 * not cause them to sign so that newly activated keys are used.
17738 */
17739 for (tuple = ISC_LIST_HEAD(diff->tuples);
17740 tuple != NULL;
17741 tuple = ISC_LIST_NEXT(tuple, link)) {
17742 if (tuple->rdata.type == dns_rdatatype_dnskey &&
17743 dns_name_equal(&tuple->name, &zone->origin))
17744 break;
17745 }
17746
17747 if (tuple == NULL) {
17748 result = del_sigs(zone, db, ver, &zone->origin,
17749 dns_rdatatype_dnskey, zonediff,
17750 zone_keys, nkeys, now, ISC_FALSE);
17751 if (result != ISC_R_SUCCESS) {
17752 dns_zone_log(zone, ISC_LOG_ERROR,
17753 "sign_apex:del_sigs -> %s",
17754 dns_result_totext(result));
17755 goto failure;
17756 }
17757 result = add_sigs(db, ver, &zone->origin, dns_rdatatype_dnskey,
17758 zonediff->diff, zone_keys, nkeys, zone->mctx,
17759 inception, soaexpire, check_ksk,
17760 keyset_kskonly);
17761 if (result != ISC_R_SUCCESS) {
17762 dns_zone_log(zone, ISC_LOG_ERROR,
17763 "sign_apex:add_sigs -> %s",
17764 dns_result_totext(result));
17765 goto failure;
17766 }
17767 }
17768
17769 result = dns__zone_updatesigs(diff, db, ver, zone_keys, nkeys, zone,
17770 inception, soaexpire, now, check_ksk,
17771 keyset_kskonly, zonediff);
17772 if (result != ISC_R_SUCCESS) {
17773 dns_zone_log(zone, ISC_LOG_ERROR,
17774 "sign_apex:dns__zone_updatesigs -> %s",
17775 dns_result_totext(result));
17776 goto failure;
17777 }
17778
17779 failure:
17780 for (i = 0; i < nkeys; i++)
17781 dst_key_free(&zone_keys[i]);
17782 return (result);
17783 }
17784
17785 /*
17786 * Prevent the zone entering a inconsistent state where
17787 * NSEC only DNSKEYs are present with NSEC3 chains.
17788 * See update.c:check_dnssec()
17789 */
17790 static isc_boolean_t
17791 dnskey_sane(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17792 dns_diff_t *diff)
17793 {
17794 isc_result_t result;
17795 dns_difftuple_t *tuple;
17796 isc_boolean_t nseconly = ISC_FALSE, nsec3 = ISC_FALSE;
17797 dns_rdatatype_t privatetype = dns_zone_getprivatetype(zone);
17798
17799 /* Scan the tuples for an NSEC-only DNSKEY */
17800 for (tuple = ISC_LIST_HEAD(diff->tuples);
17801 tuple != NULL;
17802 tuple = ISC_LIST_NEXT(tuple, link)) {
17803 isc_uint8_t alg;
17804 if (tuple->rdata.type != dns_rdatatype_dnskey ||
17805 tuple->op != DNS_DIFFOP_ADD)
17806 continue;
17807
17808 alg = tuple->rdata.data[3];
17809 if (alg == DST_ALG_RSAMD5 || alg == DST_ALG_RSASHA1 ||
17810 alg == DST_ALG_DSA || alg == DST_ALG_ECC) {
17811 nseconly = ISC_TRUE;
17812 break;
17813 }
17814 }
17815
17816 /* Check existing DB for NSEC-only DNSKEY */
17817 if (!nseconly) {
17818 result = dns_nsec_nseconly(db, ver, &nseconly);
17819 if (result == ISC_R_NOTFOUND)
17820 result = ISC_R_SUCCESS;
17821 CHECK(result);
17822 }
17823
17824 /* Check existing DB for NSEC3 */
17825 if (!nsec3)
17826 CHECK(dns_nsec3_activex(db, ver, ISC_FALSE,
17827 privatetype, &nsec3));
17828
17829 /* Refuse to allow NSEC3 with NSEC-only keys */
17830 if (nseconly && nsec3) {
17831 dns_zone_log(zone, ISC_LOG_ERROR,
17832 "NSEC only DNSKEYs and NSEC3 chains not allowed");
17833 goto failure;
17834 }
17835
17836 return (ISC_TRUE);
17837
17838 failure:
17839 return (ISC_FALSE);
17840 }
17841
17842 static isc_result_t
17843 clean_nsec3param(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17844 dns_diff_t *diff)
17845 {
17846 isc_result_t result;
17847 dns_dbnode_t *node = NULL;
17848 dns_rdataset_t rdataset;
17849
17850 dns_rdataset_init(&rdataset);
17851 CHECK(dns_db_getoriginnode(db, &node));
17852
17853 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
17854 dns_rdatatype_none, 0, &rdataset, NULL);
17855 if (dns_rdataset_isassociated(&rdataset))
17856 dns_rdataset_disassociate(&rdataset);
17857 if (result != ISC_R_NOTFOUND)
17858 goto failure;
17859
17860 result = dns_nsec3param_deletechains(db, ver, zone, ISC_TRUE, diff);
17861
17862 failure:
17863 if (node != NULL)
17864 dns_db_detachnode(db, &node);
17865 return (result);
17866 }
17867
17868 /*
17869 * Given an RRSIG rdataset and an algorithm, determine whether there
17870 * are any signatures using that algorithm.
17871 */
17872 static isc_boolean_t
17873 signed_with_alg(dns_rdataset_t *rdataset, dns_secalg_t alg) {
17874 dns_rdata_t rdata = DNS_RDATA_INIT;
17875 dns_rdata_rrsig_t rrsig;
17876 isc_result_t result;
17877
17878 REQUIRE(rdataset == NULL || rdataset->type == dns_rdatatype_rrsig);
17879 if (rdataset == NULL || !dns_rdataset_isassociated(rdataset)) {
17880 return (ISC_FALSE);
17881 }
17882
17883 for (result = dns_rdataset_first(rdataset);
17884 result == ISC_R_SUCCESS;
17885 result = dns_rdataset_next(rdataset))
17886 {
17887 dns_rdataset_current(rdataset, &rdata);
17888 result = dns_rdata_tostruct(&rdata, &rrsig, NULL);
17889 RUNTIME_CHECK(result == ISC_R_SUCCESS);
17890 dns_rdata_reset(&rdata);
17891 if (rrsig.algorithm == alg)
17892 return (ISC_TRUE);
17893 }
17894
17895 return (ISC_FALSE);
17896 }
17897
17898 static isc_result_t
17899 add_chains(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *ver,
17900 dns_diff_t *diff)
17901 {
17902 dns_name_t *origin;
17903 isc_boolean_t build_nsec3;
17904 isc_result_t result;
17905
17906 origin = dns_db_origin(db);
17907 CHECK(dns_private_chains(db, ver, zone->privatetype, NULL,
17908 &build_nsec3));
17909 if (build_nsec3)
17910 CHECK(dns_nsec3_addnsec3sx(db, ver, origin, zone->minimum,
17911 ISC_FALSE, zone->privatetype, diff));
17912 CHECK(updatesecure(db, ver, origin, zone->minimum, ISC_TRUE, diff));
17913
17914 failure:
17915 return (result);
17916 }
17917
17918 static void
17919 zone_rekey(dns_zone_t *zone) {
17920 isc_result_t result;
17921 dns_db_t *db = NULL;
17922 dns_dbnode_t *node = NULL;
17923 dns_dbversion_t *ver = NULL;
17924 dns_rdataset_t cdsset, soaset, soasigs, keyset, keysigs, cdnskeyset;
17925 dns_dnsseckeylist_t dnskeys, keys, rmkeys;
17926 dns_dnsseckey_t *key;
17927 dns_diff_t diff, _sig_diff;
17928 dns__zonediff_t zonediff;
17929 isc_boolean_t commit = ISC_FALSE, newactive = ISC_FALSE;
17930 isc_boolean_t newalg = ISC_FALSE;
17931 isc_boolean_t fullsign;
17932 dns_ttl_t ttl = 3600;
17933 const char *dir;
17934 isc_mem_t *mctx;
17935 isc_stdtime_t now;
17936 isc_time_t timenow;
17937 isc_interval_t ival;
17938 char timebuf[80];
17939
17940 REQUIRE(DNS_ZONE_VALID(zone));
17941
17942 ISC_LIST_INIT(dnskeys);
17943 ISC_LIST_INIT(keys);
17944 ISC_LIST_INIT(rmkeys);
17945 dns_rdataset_init(&soaset);
17946 dns_rdataset_init(&soasigs);
17947 dns_rdataset_init(&keyset);
17948 dns_rdataset_init(&keysigs);
17949 dns_rdataset_init(&cdsset);
17950 dns_rdataset_init(&cdnskeyset);
17951 dir = dns_zone_getkeydirectory(zone);
17952 mctx = zone->mctx;
17953 dns_diff_init(mctx, &diff);
17954 dns_diff_init(mctx, &_sig_diff);
17955 zonediff_init(&zonediff, &_sig_diff);
17956
17957 CHECK(dns_zone_getdb(zone, &db));
17958 CHECK(dns_db_newversion(db, &ver));
17959 CHECK(dns_db_getoriginnode(db, &node));
17960
17961 TIME_NOW(&timenow);
17962 now = isc_time_seconds(&timenow);
17963
17964 dns_zone_log(zone, ISC_LOG_INFO, "reconfiguring zone keys");
17965
17966 /* Get the SOA record's TTL */
17967 CHECK(dns_db_findrdataset(db, node, ver, dns_rdatatype_soa,
17968 dns_rdatatype_none, 0, &soaset, &soasigs));
17969 ttl = soaset.ttl;
17970 dns_rdataset_disassociate(&soaset);
17971
17972 /* Get the DNSKEY rdataset */
17973 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_dnskey,
17974 dns_rdatatype_none, 0, &keyset, &keysigs);
17975 if (result == ISC_R_SUCCESS) {
17976 ttl = keyset.ttl;
17977 CHECK(dns_dnssec_keylistfromrdataset(&zone->origin, dir,
17978 mctx, &keyset,
17979 &keysigs, &soasigs,
17980 ISC_FALSE, ISC_FALSE,
17981 &dnskeys));
17982 } else if (result != ISC_R_NOTFOUND)
17983 goto failure;
17984
17985
17986 /* Get the CDS rdataset */
17987 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cds,
17988 dns_rdatatype_none, 0, &cdsset, NULL);
17989 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdsset))
17990 dns_rdataset_disassociate(&cdsset);
17991
17992 /* Get the CDNSKEY rdataset */
17993 result = dns_db_findrdataset(db, node, ver, dns_rdatatype_cdnskey,
17994 dns_rdatatype_none, 0, &cdnskeyset, NULL);
17995 if (result != ISC_R_SUCCESS && dns_rdataset_isassociated(&cdnskeyset))
17996 dns_rdataset_disassociate(&cdnskeyset);
17997
17998 /*
17999 * True when called from "rndc sign". Indicates the zone should be
18000 * fully signed now.
18001 */
18002 fullsign = ISC_TF(DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_FULLSIGN) != 0);
18003
18004 result = dns_dnssec_findmatchingkeys2(&zone->origin, dir, now, mctx,
18005 &keys);
18006 if (result == ISC_R_SUCCESS) {
18007 isc_boolean_t check_ksk;
18008 check_ksk = DNS_ZONE_OPTION(zone, DNS_ZONEOPT_UPDATECHECKKSK);
18009
18010 result = dns_dnssec_updatekeys(&dnskeys, &keys, &rmkeys,
18011 &zone->origin, ttl, &diff,
18012 ISC_TF(!check_ksk),
18013 mctx, logmsg);
18014 /*
18015 * Keys couldn't be updated for some reason;
18016 * try again later.
18017 */
18018 if (result != ISC_R_SUCCESS) {
18019 dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
18020 "couldn't update zone keys: %s",
18021 isc_result_totext(result));
18022 goto failure;
18023 }
18024
18025 /*
18026 * Update CDS / CDNSKEY records.
18027 */
18028 result = dns_dnssec_syncupdate(&dnskeys, &rmkeys, &cdsset,
18029 &cdnskeyset, now, ttl,
18030 &diff, mctx);
18031 if (result != ISC_R_SUCCESS) {
18032 dns_zone_log(zone, ISC_LOG_ERROR, "zone_rekey:"
18033 "couldn't update CDS/CDNSKEY: %s",
18034 isc_result_totext(result));
18035 goto failure;
18036 }
18037
18038 /*
18039 * See if any pre-existing keys have newly become active;
18040 * also, see if any new key is for a new algorithm, as in that
18041 * event, we need to sign the zone fully. (If there's a new
18042 * key, but it's for an already-existing algorithm, then
18043 * the zone signing can be handled incrementally.)
18044 */
18045 for (key = ISC_LIST_HEAD(dnskeys);
18046 key != NULL;
18047 key = ISC_LIST_NEXT(key, link)) {
18048 if (!key->first_sign)
18049 continue;
18050
18051 newactive = ISC_TRUE;
18052
18053 if (!dns_rdataset_isassociated(&keysigs)) {
18054 newalg = ISC_TRUE;
18055 break;
18056 }
18057
18058 if (signed_with_alg(&keysigs, dst_key_alg(key->key))) {
18059 /*
18060 * This isn't a new algorithm; clear
18061 * first_sign so we won't sign the
18062 * whole zone with this key later
18063 */
18064 key->first_sign = ISC_FALSE;
18065 } else {
18066 newalg = ISC_TRUE;
18067 break;
18068 }
18069 }
18070
18071 if ((newactive || fullsign || !ISC_LIST_EMPTY(diff.tuples)) &&
18072 dnskey_sane(zone, db, ver, &diff)) {
18073 CHECK(dns_diff_apply(&diff, db, ver));
18074 CHECK(clean_nsec3param(zone, db, ver, &diff));
18075 CHECK(add_signing_records(db, zone->privatetype,
18076 ver, &diff,
18077 ISC_TF(newalg || fullsign)));
18078 CHECK(update_soa_serial(db, ver, &diff, mctx,
18079 zone->updatemethod));
18080 CHECK(add_chains(zone, db, ver, &diff));
18081 CHECK(sign_apex(zone, db, ver, now, &diff, &zonediff));
18082 CHECK(zone_journal(zone, zonediff.diff, NULL,
18083 "zone_rekey"));
18084 commit = ISC_TRUE;
18085 }
18086 }
18087
18088 dns_db_closeversion(db, &ver, ISC_TRUE);
18089
18090 if (commit) {
18091 dns_difftuple_t *tuple;
18092
18093 LOCK_ZONE(zone);
18094 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDNOTIFY);
18095
18096 zone_needdump(zone, DNS_DUMP_DELAY);
18097
18098 zone_settimer(zone, &timenow);
18099
18100 /* Remove any signatures from removed keys. */
18101 if (!ISC_LIST_EMPTY(rmkeys)) {
18102 for (key = ISC_LIST_HEAD(rmkeys);
18103 key != NULL;
18104 key = ISC_LIST_NEXT(key, link)) {
18105 result = zone_signwithkey(zone,
18106 dst_key_alg(key->key),
18107 dst_key_id(key->key),
18108 ISC_TRUE);
18109 if (result != ISC_R_SUCCESS) {
18110 dns_zone_log(zone, ISC_LOG_ERROR,
18111 "zone_signwithkey failed: %s",
18112 dns_result_totext(result));
18113 }
18114 }
18115 }
18116
18117 if (fullsign) {
18118 /*
18119 * "rndc sign" was called, so we now sign the zone
18120 * with all active keys, whether they're new or not.
18121 */
18122 for (key = ISC_LIST_HEAD(dnskeys);
18123 key != NULL;
18124 key = ISC_LIST_NEXT(key, link)) {
18125 if (!key->force_sign && !key->hint_sign)
18126 continue;
18127
18128 result = zone_signwithkey(zone,
18129 dst_key_alg(key->key),
18130 dst_key_id(key->key),
18131 ISC_FALSE);
18132 if (result != ISC_R_SUCCESS) {
18133 dns_zone_log(zone, ISC_LOG_ERROR,
18134 "zone_signwithkey failed: %s",
18135 dns_result_totext(result));
18136 }
18137 }
18138 } else if (newalg) {
18139 /*
18140 * We haven't been told to sign fully, but a new
18141 * algorithm was added to the DNSKEY. We sign
18142 * the full zone, but only with newly active
18143 * keys.
18144 */
18145 for (key = ISC_LIST_HEAD(dnskeys);
18146 key != NULL;
18147 key = ISC_LIST_NEXT(key, link)) {
18148 if (!key->first_sign)
18149 continue;
18150
18151 result = zone_signwithkey(zone,
18152 dst_key_alg(key->key),
18153 dst_key_id(key->key),
18154 ISC_FALSE);
18155 if (result != ISC_R_SUCCESS) {
18156 dns_zone_log(zone, ISC_LOG_ERROR,
18157 "zone_signwithkey failed: %s",
18158 dns_result_totext(result));
18159 }
18160 }
18161 }
18162
18163 /*
18164 * Clear fullsign flag, if it was set, so we don't do
18165 * another full signing next time
18166 */
18167 zone->keyopts &= ~DNS_ZONEKEY_FULLSIGN;
18168
18169 /*
18170 * Cause the zone to add/delete NSEC3 chains for the
18171 * deferred NSEC3PARAM changes.
18172 */
18173 for (tuple = ISC_LIST_HEAD(zonediff.diff->tuples);
18174 tuple != NULL;
18175 tuple = ISC_LIST_NEXT(tuple, link)) {
18176 unsigned char buf[DNS_NSEC3PARAM_BUFFERSIZE];
18177 dns_rdata_t rdata = DNS_RDATA_INIT;
18178 dns_rdata_nsec3param_t nsec3param;
18179
18180 if (tuple->rdata.type != zone->privatetype ||
18181 tuple->op != DNS_DIFFOP_ADD)
18182 continue;
18183
18184 if (!dns_nsec3param_fromprivate(&tuple->rdata, &rdata,
18185 buf, sizeof(buf)))
18186 continue;
18187 result = dns_rdata_tostruct(&rdata, &nsec3param, NULL);
18188 RUNTIME_CHECK(result == ISC_R_SUCCESS);
18189 if (nsec3param.flags == 0)
18190 continue;
18191
18192 result = zone_addnsec3chain(zone, &nsec3param);
18193 if (result != ISC_R_SUCCESS) {
18194 dns_zone_log(zone, ISC_LOG_ERROR,
18195 "zone_addnsec3chain failed: %s",
18196 dns_result_totext(result));
18197 }
18198 }
18199
18200 /*
18201 * Activate any NSEC3 chain updates that may have
18202 * been scheduled before this rekey.
18203 */
18204 if (fullsign || newalg)
18205 resume_addnsec3chain(zone);
18206
18207 /*
18208 * Schedule the next resigning event
18209 */
18210 set_resigntime(zone);
18211 UNLOCK_ZONE(zone);
18212 }
18213
18214 isc_time_settoepoch(&zone->refreshkeytime);
18215
18216 /*
18217 * If we're doing key maintenance, set the key refresh timer to
18218 * the next scheduled key event or to 'dnssec-loadkeys-interval'
18219 * seconds in the future, whichever is sooner.
18220 */
18221 if (DNS_ZONEKEY_OPTION(zone, DNS_ZONEKEY_MAINTAIN)) {
18222 isc_time_t timethen;
18223 isc_stdtime_t then;
18224
18225 LOCK_ZONE(zone);
18226 DNS_ZONE_TIME_ADD(&timenow, zone->refreshkeyinterval,
18227 &timethen);
18228 zone->refreshkeytime = timethen;
18229 UNLOCK_ZONE(zone);
18230
18231 for (key = ISC_LIST_HEAD(dnskeys);
18232 key != NULL;
18233 key = ISC_LIST_NEXT(key, link)) {
18234 then = now;
18235 result = next_keyevent(key->key, &then);
18236 if (result != ISC_R_SUCCESS)
18237 continue;
18238
18239 DNS_ZONE_TIME_ADD(&timenow, then - now, &timethen);
18240 LOCK_ZONE(zone);
18241 if (isc_time_compare(&timethen,
18242 &zone->refreshkeytime) < 0) {
18243 zone->refreshkeytime = timethen;
18244 }
18245 UNLOCK_ZONE(zone);
18246 }
18247
18248 zone_settimer(zone, &timenow);
18249
18250 isc_time_formattimestamp(&zone->refreshkeytime, timebuf, 80);
18251 dns_zone_log(zone, ISC_LOG_INFO, "next key event: %s", timebuf);
18252 }
18253
18254 done:
18255 dns_diff_clear(&diff);
18256 dns_diff_clear(&_sig_diff);
18257
18258 clear_keylist(&dnskeys, mctx);
18259 clear_keylist(&keys, mctx);
18260 clear_keylist(&rmkeys, mctx);
18261
18262 if (ver != NULL)
18263 dns_db_closeversion(db, &ver, ISC_FALSE);
18264 if (dns_rdataset_isassociated(&cdsset))
18265 dns_rdataset_disassociate(&cdsset);
18266 if (dns_rdataset_isassociated(&keyset))
18267 dns_rdataset_disassociate(&keyset);
18268 if (dns_rdataset_isassociated(&keysigs))
18269 dns_rdataset_disassociate(&keysigs);
18270 if (dns_rdataset_isassociated(&soasigs))
18271 dns_rdataset_disassociate(&soasigs);
18272 if (dns_rdataset_isassociated(&cdnskeyset))
18273 dns_rdataset_disassociate(&cdnskeyset);
18274 if (node != NULL)
18275 dns_db_detachnode(db, &node);
18276 if (db != NULL)
18277 dns_db_detach(&db);
18278
18279 INSIST(ver == NULL);
18280 return;
18281
18282 failure:
18283 /*
18284 * Something went wrong; try again in ten minutes or
18285 * after a key refresh interval, whichever is shorter.
18286 */
18287 isc_interval_set(&ival, ISC_MIN(zone->refreshkeyinterval, 600), 0);
18288 isc_time_nowplusinterval(&zone->refreshkeytime, &ival);
18289 goto done;
18290 }
18291
18292 void
18293 dns_zone_rekey(dns_zone_t *zone, isc_boolean_t fullsign) {
18294 isc_time_t now;
18295
18296 if (zone->type == dns_zone_master && zone->task != NULL) {
18297 LOCK_ZONE(zone);
18298
18299 if (fullsign)
18300 zone->keyopts |= DNS_ZONEKEY_FULLSIGN;
18301
18302 TIME_NOW(&now);
18303 zone->refreshkeytime = now;
18304 zone_settimer(zone, &now);
18305
18306 UNLOCK_ZONE(zone);
18307 }
18308 }
18309
18310 isc_result_t
18311 dns_zone_nscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version,
18312 unsigned int *errors)
18313 {
18314 isc_result_t result;
18315 dns_dbnode_t *node = NULL;
18316
18317 REQUIRE(DNS_ZONE_VALID(zone));
18318 REQUIRE(errors != NULL);
18319
18320 result = dns_db_getoriginnode(db, &node);
18321 if (result != ISC_R_SUCCESS)
18322 return (result);
18323 result = zone_count_ns_rr(zone, db, node, version, NULL, errors,
18324 ISC_FALSE);
18325 dns_db_detachnode(db, &node);
18326 return (result);
18327 }
18328
18329 isc_result_t
18330 dns_zone_cdscheck(dns_zone_t *zone, dns_db_t *db, dns_dbversion_t *version) {
18331 isc_result_t result;
18332 dns_dbnode_t *node = NULL;
18333 dns_rdataset_t dnskey, cds, cdnskey;
18334 unsigned char buffer[DNS_DS_BUFFERSIZE];
18335 unsigned char algorithms[256];
18336 unsigned int i;
18337
18338 REQUIRE(DNS_ZONE_VALID(zone));
18339
18340 result = dns_db_getoriginnode(db, &node);
18341 if (result != ISC_R_SUCCESS)
18342 return (result);
18343
18344 dns_rdataset_init(&cds);
18345 dns_rdataset_init(&dnskey);
18346 dns_rdataset_init(&cdnskey);
18347
18348 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cds,
18349 dns_rdatatype_none, 0, &cds, NULL);
18350 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18351 goto failure;
18352
18353 result = dns_db_findrdataset(db, node, version, dns_rdatatype_cdnskey,
18354 dns_rdatatype_none, 0, &cdnskey, NULL);
18355 if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND)
18356 goto failure;
18357
18358 if (!dns_rdataset_isassociated(&cds) &&
18359 !dns_rdataset_isassociated(&cdnskey)) {
18360 result = ISC_R_SUCCESS;
18361 goto failure;
18362 }
18363
18364 result = dns_db_findrdataset(db, node, version, dns_rdatatype_dnskey,
18365 dns_rdatatype_none, 0, &dnskey, NULL);
18366 if (result == ISC_R_NOTFOUND) {
18367 if (dns_rdataset_isassociated(&cds))
18368 result = DNS_R_BADCDS;
18369 else
18370 result = DNS_R_BADCDNSKEY;
18371 goto failure;
18372 }
18373 if (result != ISC_R_SUCCESS)
18374 goto failure;
18375
18376 /*
18377 * For each DNSSEC algorithm in the CDS RRset there must be
18378 * a matching DNSKEY record.
18379 */
18380 if (dns_rdataset_isassociated(&cds)) {
18381 memset(algorithms, 0, sizeof(algorithms));
18382 for (result = dns_rdataset_first(&cds);
18383 result == ISC_R_SUCCESS;
18384 result = dns_rdataset_next(&cds)) {
18385 dns_rdata_t crdata = DNS_RDATA_INIT;
18386 dns_rdata_cds_t structcds;
18387
18388 dns_rdataset_current(&cds, &crdata);
18389 CHECK(dns_rdata_tostruct(&crdata, &structcds, NULL));
18390 if (algorithms[structcds.algorithm] == 0)
18391 algorithms[structcds.algorithm] = 1;
18392 for (result = dns_rdataset_first(&dnskey);
18393 result == ISC_R_SUCCESS;
18394 result = dns_rdataset_next(&dnskey)) {
18395 dns_rdata_t rdata = DNS_RDATA_INIT;
18396 dns_rdata_t dsrdata = DNS_RDATA_INIT;
18397
18398 dns_rdataset_current(&dnskey, &rdata);
18399 CHECK(dns_ds_buildrdata(&zone->origin, &rdata,
18400 structcds.digest_type,
18401 buffer, &dsrdata));
18402 if (crdata.length == dsrdata.length &&
18403 memcmp(crdata.data, dsrdata.data,
18404 dsrdata.length) == 0) {
18405 algorithms[structcds.algorithm] = 2;
18406 }
18407 }
18408 if (result != ISC_R_NOMORE)
18409 goto failure;
18410 }
18411 for (i = 0; i < sizeof(algorithms); i++) {
18412 if (algorithms[i] == 1) {
18413 result = DNS_R_BADCDNSKEY;
18414 goto failure;
18415 }
18416 }
18417 }
18418
18419 /*
18420 * For each DNSSEC algorithm in the CDNSKEY RRset there must be
18421 * a matching DNSKEY record.
18422 */
18423 if (dns_rdataset_isassociated(&cdnskey)) {
18424 memset(algorithms, 0, sizeof(algorithms));
18425 for (result = dns_rdataset_first(&cdnskey);
18426 result == ISC_R_SUCCESS;
18427 result = dns_rdataset_next(&cdnskey)) {
18428 dns_rdata_t crdata = DNS_RDATA_INIT;
18429 dns_rdata_cdnskey_t structcdnskey;
18430
18431 dns_rdataset_current(&cdnskey, &crdata);
18432 CHECK(dns_rdata_tostruct(&crdata, &structcdnskey,
18433 NULL));
18434 if (algorithms[structcdnskey.algorithm] == 0)
18435 algorithms[structcdnskey.algorithm] = 1;
18436 for (result = dns_rdataset_first(&dnskey);
18437 result == ISC_R_SUCCESS;
18438 result = dns_rdataset_next(&dnskey)) {
18439 dns_rdata_t rdata = DNS_RDATA_INIT;
18440
18441 dns_rdataset_current(&dnskey, &rdata);
18442 if (crdata.length == rdata.length &&
18443 memcmp(crdata.data, rdata.data,
18444 rdata.length) == 0) {
18445 algorithms[structcdnskey.algorithm] = 2;
18446 }
18447 }
18448 if (result != ISC_R_NOMORE)
18449 goto failure;
18450 }
18451 for (i = 0; i < sizeof(algorithms); i++) {
18452 if (algorithms[i] == 1) {
18453 result = DNS_R_BADCDS;
18454 goto failure;
18455 }
18456 }
18457 }
18458 result = ISC_R_SUCCESS;
18459
18460 failure:
18461 if (dns_rdataset_isassociated(&cds))
18462 dns_rdataset_disassociate(&cds);
18463 if (dns_rdataset_isassociated(&dnskey))
18464 dns_rdataset_disassociate(&dnskey);
18465 if (dns_rdataset_isassociated(&cdnskey))
18466 dns_rdataset_disassociate(&cdnskey);
18467 dns_db_detachnode(db, &node);
18468 return (result);
18469 }
18470
18471 void
18472 dns_zone_setautomatic(dns_zone_t *zone, isc_boolean_t automatic) {
18473 REQUIRE(DNS_ZONE_VALID(zone));
18474
18475 LOCK_ZONE(zone);
18476 zone->automatic = automatic;
18477 UNLOCK_ZONE(zone);
18478 }
18479
18480 isc_boolean_t
18481 dns_zone_getautomatic(dns_zone_t *zone) {
18482 REQUIRE(DNS_ZONE_VALID(zone));
18483 return (zone->automatic);
18484 }
18485
18486 void
18487 dns_zone_setadded(dns_zone_t *zone, isc_boolean_t added) {
18488 REQUIRE(DNS_ZONE_VALID(zone));
18489
18490 LOCK_ZONE(zone);
18491 zone->added = added;
18492 UNLOCK_ZONE(zone);
18493 }
18494
18495 isc_boolean_t
18496 dns_zone_getadded(dns_zone_t *zone) {
18497 REQUIRE(DNS_ZONE_VALID(zone));
18498 return (zone->added);
18499 }
18500
18501 isc_result_t
18502 dns_zone_dlzpostload(dns_zone_t *zone, dns_db_t *db)
18503 {
18504 isc_time_t loadtime;
18505 isc_result_t result;
18506 dns_zone_t *secure = NULL;
18507
18508 TIME_NOW(&loadtime);
18509
18510 /*
18511 * Lock hierarchy: zmgr, zone, raw.
18512 */
18513 again:
18514 LOCK_ZONE(zone);
18515 INSIST(zone != zone->raw);
18516 if (inline_secure(zone))
18517 LOCK_ZONE(zone->raw);
18518 else if (inline_raw(zone)) {
18519 secure = zone->secure;
18520 TRYLOCK_ZONE(result, secure);
18521 if (result != ISC_R_SUCCESS) {
18522 UNLOCK_ZONE(zone);
18523 secure = NULL;
18524 #if ISC_PLATFORM_USETHREADS
18525 isc_thread_yield();
18526 #endif
18527 goto again;
18528 }
18529 }
18530 result = zone_postload(zone, db, loadtime, ISC_R_SUCCESS);
18531 if (inline_secure(zone))
18532 UNLOCK_ZONE(zone->raw);
18533 else if (secure != NULL)
18534 UNLOCK_ZONE(secure);
18535 UNLOCK_ZONE(zone);
18536 return result;
18537 }
18538
18539 isc_result_t
18540 dns_zone_setrefreshkeyinterval(dns_zone_t *zone, isc_uint32_t interval) {
18541 REQUIRE(DNS_ZONE_VALID(zone));
18542 if (interval == 0)
18543 return (ISC_R_RANGE);
18544 /* Maximum value: 24 hours (3600 minutes) */
18545 if (interval > (24 * 60))
18546 interval = (24 * 60);
18547 /* Multiply by 60 for seconds */
18548 zone->refreshkeyinterval = interval * 60;
18549 return (ISC_R_SUCCESS);
18550 }
18551
18552 void
18553 dns_zone_setrequestixfr(dns_zone_t *zone, isc_boolean_t flag) {
18554 REQUIRE(DNS_ZONE_VALID(zone));
18555 zone->requestixfr = flag;
18556 }
18557
18558 isc_boolean_t
18559 dns_zone_getrequestixfr(dns_zone_t *zone) {
18560 REQUIRE(DNS_ZONE_VALID(zone));
18561 return (zone->requestixfr);
18562 }
18563
18564 void
18565 dns_zone_setrequestexpire(dns_zone_t *zone, isc_boolean_t flag) {
18566 REQUIRE(DNS_ZONE_VALID(zone));
18567 zone->requestexpire = flag;
18568 }
18569
18570 isc_boolean_t
18571 dns_zone_getrequestexpire(dns_zone_t *zone) {
18572 REQUIRE(DNS_ZONE_VALID(zone));
18573 return (zone->requestexpire);
18574 }
18575
18576 void
18577 dns_zone_setserialupdatemethod(dns_zone_t *zone, dns_updatemethod_t method) {
18578 REQUIRE(DNS_ZONE_VALID(zone));
18579 zone->updatemethod = method;
18580 }
18581
18582 dns_updatemethod_t
18583 dns_zone_getserialupdatemethod(dns_zone_t *zone) {
18584 REQUIRE(DNS_ZONE_VALID(zone));
18585 return(zone->updatemethod);
18586 }
18587
18588 /*
18589 * Lock hierarchy: zmgr, zone, raw.
18590 */
18591 isc_result_t
18592 dns_zone_link(dns_zone_t *zone, dns_zone_t *raw) {
18593 isc_result_t result;
18594 dns_zonemgr_t *zmgr;
18595
18596 REQUIRE(DNS_ZONE_VALID(zone));
18597 REQUIRE(zone->zmgr != NULL);
18598 REQUIRE(zone->task != NULL);
18599 REQUIRE(zone->loadtask != NULL);
18600 REQUIRE(zone->raw == NULL);
18601
18602 REQUIRE(DNS_ZONE_VALID(raw));
18603 REQUIRE(raw->zmgr == NULL);
18604 REQUIRE(raw->task == NULL);
18605 REQUIRE(raw->loadtask == NULL);
18606 REQUIRE(raw->secure == NULL);
18607
18608 REQUIRE(zone != raw);
18609
18610 /*
18611 * Lock hierarchy: zmgr, zone, raw.
18612 */
18613 zmgr = zone->zmgr;
18614 RWLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18615 LOCK_ZONE(zone);
18616 LOCK_ZONE(raw);
18617
18618 result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive,
18619 NULL, NULL, zone->task, zone_timer, raw,
18620 &raw->timer);
18621 if (result != ISC_R_SUCCESS)
18622 goto unlock;
18623
18624 /*
18625 * The timer "holds" a iref.
18626 */
18627 raw->irefs++;
18628 INSIST(raw->irefs != 0);
18629
18630
18631 /* dns_zone_attach(raw, &zone->raw); */
18632 isc_refcount_increment(&raw->erefs, NULL);
18633 zone->raw = raw;
18634
18635 /* dns_zone_iattach(zone, &raw->secure); */
18636 zone_iattach(zone, &raw->secure);
18637
18638 isc_task_attach(zone->task, &raw->task);
18639 isc_task_attach(zone->loadtask, &raw->loadtask);
18640
18641 ISC_LIST_APPEND(zmgr->zones, raw, link);
18642 raw->zmgr = zmgr;
18643 zmgr->refs++;
18644
18645 unlock:
18646 UNLOCK_ZONE(raw);
18647 UNLOCK_ZONE(zone);
18648 RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write);
18649 return (result);
18650 }
18651
18652 void
18653 dns_zone_getraw(dns_zone_t *zone, dns_zone_t **raw) {
18654 REQUIRE(DNS_ZONE_VALID(zone));
18655 REQUIRE(raw != NULL && *raw == NULL);
18656
18657 LOCK(&zone->lock);
18658 INSIST(zone != zone->raw);
18659 if (zone->raw != NULL)
18660 dns_zone_attach(zone->raw, raw);
18661 UNLOCK(&zone->lock);
18662 }
18663
18664 struct keydone {
18665 isc_event_t event;
18666 isc_boolean_t all;
18667 unsigned char data[5];
18668 };
18669
18670 #define PENDINGFLAGS (DNS_NSEC3FLAG_CREATE|DNS_NSEC3FLAG_INITIAL)
18671
18672 static void
18673 keydone(isc_task_t *task, isc_event_t *event) {
18674 const char *me = "keydone";
18675 isc_boolean_t commit = ISC_FALSE;
18676 isc_result_t result;
18677 dns_rdata_t rdata = DNS_RDATA_INIT;
18678 dns_dbversion_t *oldver = NULL, *newver = NULL;
18679 dns_zone_t *zone;
18680 dns_db_t *db = NULL;
18681 dns_dbnode_t *node = NULL;
18682 dns_rdataset_t rdataset;
18683 dns_diff_t diff;
18684 struct keydone *kd = (struct keydone *)event;
18685 dns_update_log_t log = { update_log_cb, NULL };
18686 isc_boolean_t clear_pending = ISC_FALSE;
18687
18688 UNUSED(task);
18689
18690 zone = event->ev_arg;
18691 INSIST(DNS_ZONE_VALID(zone));
18692
18693 ENTER;
18694
18695 dns_rdataset_init(&rdataset);
18696 dns_diff_init(zone->mctx, &diff);
18697
18698 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18699 if (zone->db != NULL)
18700 dns_db_attach(zone->db, &db);
18701 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18702 if (db == NULL)
18703 goto failure;
18704
18705 dns_db_currentversion(db, &oldver);
18706 result = dns_db_newversion(db, &newver);
18707 if (result != ISC_R_SUCCESS) {
18708 dns_zone_log(zone, ISC_LOG_ERROR,
18709 "keydone:dns_db_newversion -> %s",
18710 dns_result_totext(result));
18711 goto failure;
18712 }
18713
18714 result = dns_db_getoriginnode(db, &node);
18715 if (result != ISC_R_SUCCESS)
18716 goto failure;
18717
18718 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
18719 dns_rdatatype_none, 0, &rdataset, NULL);
18720 if (result == ISC_R_NOTFOUND) {
18721 INSIST(!dns_rdataset_isassociated(&rdataset));
18722 goto failure;
18723 }
18724 if (result != ISC_R_SUCCESS) {
18725 INSIST(!dns_rdataset_isassociated(&rdataset));
18726 goto failure;
18727 }
18728
18729 for (result = dns_rdataset_first(&rdataset);
18730 result == ISC_R_SUCCESS;
18731 result = dns_rdataset_next(&rdataset)) {
18732 isc_boolean_t found = ISC_FALSE;
18733
18734 dns_rdataset_current(&rdataset, &rdata);
18735
18736 if (kd->all) {
18737 if (rdata.length == 5 && rdata.data[0] != 0 &&
18738 rdata.data[3] == 0 && rdata.data[4] == 1)
18739 found = ISC_TRUE;
18740 else if (rdata.data[0] == 0 &&
18741 (rdata.data[2] & PENDINGFLAGS) != 0) {
18742 found = ISC_TRUE;
18743 clear_pending = ISC_TRUE;
18744 }
18745 } else if (rdata.length == 5 &&
18746 memcmp(rdata.data, kd->data, 5) == 0)
18747 found = ISC_TRUE;
18748
18749 if (found)
18750 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_DEL,
18751 &zone->origin, rdataset.ttl,
18752 &rdata));
18753 dns_rdata_reset(&rdata);
18754 }
18755
18756 if (!ISC_LIST_EMPTY(diff.tuples)) {
18757 /* Write changes to journal file. */
18758 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
18759 zone->updatemethod));
18760
18761 result = dns_update_signatures(&log, zone, db,
18762 oldver, newver, &diff,
18763 zone->sigvalidityinterval);
18764 if (!clear_pending)
18765 CHECK(result);
18766
18767 CHECK(zone_journal(zone, &diff, NULL, "keydone"));
18768 commit = ISC_TRUE;
18769
18770 LOCK_ZONE(zone);
18771 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
18772 zone_needdump(zone, 30);
18773 UNLOCK_ZONE(zone);
18774 }
18775
18776 failure:
18777 if (dns_rdataset_isassociated(&rdataset))
18778 dns_rdataset_disassociate(&rdataset);
18779 if (db != NULL) {
18780 if (node != NULL)
18781 dns_db_detachnode(db, &node);
18782 if (oldver != NULL)
18783 dns_db_closeversion(db, &oldver, ISC_FALSE);
18784 if (newver != NULL)
18785 dns_db_closeversion(db, &newver, commit);
18786 dns_db_detach(&db);
18787 }
18788 dns_diff_clear(&diff);
18789 isc_event_free(&event);
18790 dns_zone_idetach(&zone);
18791
18792 INSIST(oldver == NULL);
18793 INSIST(newver == NULL);
18794 }
18795
18796 isc_result_t
18797 dns_zone_keydone(dns_zone_t *zone, const char *keystr) {
18798 isc_result_t result = ISC_R_SUCCESS;
18799 isc_event_t *e;
18800 isc_buffer_t b;
18801 dns_zone_t *dummy = NULL;
18802 struct keydone *kd;
18803
18804 REQUIRE(DNS_ZONE_VALID(zone));
18805
18806 LOCK_ZONE(zone);
18807
18808 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_KEYDONE, keydone,
18809 zone, sizeof(struct keydone));
18810 if (e == NULL) {
18811 result = ISC_R_NOMEMORY;
18812 goto failure;
18813 }
18814
18815 kd = (struct keydone *) e;
18816 if (strcasecmp(keystr, "all") == 0)
18817 kd->all = ISC_TRUE;
18818 else {
18819 isc_textregion_t r;
18820 const char *algstr;
18821 dns_keytag_t keyid;
18822 dns_secalg_t alg;
18823 size_t n;
18824
18825 kd->all = ISC_FALSE;
18826
18827 n = sscanf(keystr, "%hu/", &keyid);
18828 if (n == 0U)
18829 CHECK(ISC_R_FAILURE);
18830
18831 algstr = strchr(keystr, '/');
18832 if (algstr != NULL)
18833 algstr++;
18834 else
18835 CHECK(ISC_R_FAILURE);
18836
18837 n = sscanf(algstr, "%hhu", &alg);
18838 if (n == 0U) {
18839 DE_CONST(algstr, r.base);
18840 r.length = strlen(algstr);
18841 CHECK(dns_secalg_fromtext(&alg, &r));
18842 }
18843
18844 /* construct a private-type rdata */
18845 isc_buffer_init(&b, kd->data, sizeof(kd->data));
18846 isc_buffer_putuint8(&b, alg);
18847 isc_buffer_putuint8(&b, (keyid & 0xff00) >> 8);
18848 isc_buffer_putuint8(&b, (keyid & 0xff));
18849 isc_buffer_putuint8(&b, 0);
18850 isc_buffer_putuint8(&b, 1);
18851 }
18852
18853 zone_iattach(zone, &dummy);
18854 isc_task_send(zone->task, &e);
18855
18856 failure:
18857 if (e != NULL)
18858 isc_event_free(&e);
18859 UNLOCK_ZONE(zone);
18860 return (result);
18861 }
18862
18863 /*
18864 * Called from the zone task's queue after the relevant event is posted by
18865 * dns_zone_setnsec3param().
18866 *
18867 * Check whether NSEC3 chain addition or removal specified by the private-type
18868 * record passed with the event was already queued (or even fully performed).
18869 * If not, modify the relevant private-type records at the zone apex and call
18870 * resume_addnsec3chain().
18871 */
18872 static void
18873 setnsec3param(isc_task_t *task, isc_event_t *event) {
18874 const char *me = "setnsec3param";
18875 isc_boolean_t commit = ISC_FALSE;
18876 isc_result_t result;
18877 dns_dbversion_t *oldver = NULL, *newver = NULL;
18878 dns_zone_t *zone;
18879 dns_db_t *db = NULL;
18880 dns_dbnode_t *node = NULL;
18881 dns_rdataset_t prdataset, nrdataset;
18882 dns_diff_t diff;
18883 struct np3event *npe = (struct np3event *)event;
18884 nsec3param_t *np;
18885 dns_update_log_t log = { update_log_cb, NULL };
18886 dns_rdata_t rdata;
18887 isc_boolean_t nseconly;
18888 isc_boolean_t exists = ISC_FALSE;
18889
18890 UNUSED(task);
18891
18892 zone = event->ev_arg;
18893 INSIST(DNS_ZONE_VALID(zone));
18894
18895 ENTER;
18896
18897 np = &npe->params;
18898
18899 dns_rdataset_init(&prdataset);
18900 dns_rdataset_init(&nrdataset);
18901 dns_diff_init(zone->mctx, &diff);
18902
18903 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
18904 if (zone->db != NULL)
18905 dns_db_attach(zone->db, &db);
18906 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18907 if (db == NULL)
18908 goto failure;
18909
18910 dns_db_currentversion(db, &oldver);
18911 result = dns_db_newversion(db, &newver);
18912 if (result != ISC_R_SUCCESS) {
18913 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
18914 dns_zone_log(zone, ISC_LOG_ERROR,
18915 "setnsec3param:dns_db_newversion -> %s",
18916 dns_result_totext(result));
18917 goto failure;
18918 }
18919
18920 CHECK(dns_db_getoriginnode(db, &node));
18921
18922 /*
18923 * Does a private-type record already exist for this chain?
18924 */
18925 result = dns_db_findrdataset(db, node, newver, zone->privatetype,
18926 dns_rdatatype_none, 0, &prdataset, NULL);
18927 if (result == ISC_R_SUCCESS) {
18928 for (result = dns_rdataset_first(&prdataset);
18929 result == ISC_R_SUCCESS;
18930 result = dns_rdataset_next(&prdataset)) {
18931 dns_rdata_init(&rdata);
18932 dns_rdataset_current(&prdataset, &rdata);
18933
18934 if (np->length == rdata.length &&
18935 memcmp(rdata.data, np->data, np->length) == 0) {
18936 exists = ISC_TRUE;
18937 break;
18938 }
18939 }
18940 } else if (result != ISC_R_NOTFOUND) {
18941 INSIST(!dns_rdataset_isassociated(&prdataset));
18942 goto failure;
18943 }
18944
18945 /*
18946 * Does the chain already exist?
18947 */
18948 result = dns_db_findrdataset(db, node, newver,
18949 dns_rdatatype_nsec3param,
18950 dns_rdatatype_none, 0, &nrdataset, NULL);
18951 if (result == ISC_R_SUCCESS) {
18952 for (result = dns_rdataset_first(&nrdataset);
18953 result == ISC_R_SUCCESS;
18954 result = dns_rdataset_next(&nrdataset)) {
18955 dns_rdata_init(&rdata);
18956 dns_rdataset_current(&nrdataset, &rdata);
18957
18958 if (np->length == (rdata.length + 1) &&
18959 memcmp(rdata.data, np->data + 1,
18960 np->length - 1) == 0)
18961 {
18962 exists = ISC_TRUE;
18963 break;
18964 }
18965 }
18966 } else if (result != ISC_R_NOTFOUND) {
18967 INSIST(!dns_rdataset_isassociated(&nrdataset));
18968 goto failure;
18969 }
18970
18971
18972 /*
18973 * We need to remove any existing NSEC3 chains if the supplied NSEC3
18974 * parameters are supposed to replace the current ones or if we are
18975 * switching to NSEC.
18976 */
18977 if (!exists && np->replace && (np->length != 0 || np->nsec))
18978 CHECK(dns_nsec3param_deletechains(db, newver, zone,
18979 !np->nsec, &diff));
18980
18981 if (!exists && np->length != 0) {
18982 /*
18983 * We're creating an NSEC3 chain. Add the private-type record
18984 * passed in the event handler's argument to the zone apex.
18985 *
18986 * If the zone is not currently capable of supporting an NSEC3
18987 * chain (due to the DNSKEY RRset at the zone apex not existing
18988 * or containing at least one key using an NSEC-only
18989 * algorithm), add the INITIAL flag, so these parameters can be
18990 * used later when NSEC3 becomes available.
18991 */
18992 dns_rdata_init(&rdata);
18993
18994 np->data[2] |= DNS_NSEC3FLAG_CREATE;
18995 result = dns_nsec_nseconly(db, newver, &nseconly);
18996 if (result == ISC_R_NOTFOUND || nseconly)
18997 np->data[2] |= DNS_NSEC3FLAG_INITIAL;
18998
18999 rdata.length = np->length;
19000 rdata.data = np->data;
19001 rdata.type = zone->privatetype;
19002 rdata.rdclass = zone->rdclass;
19003 CHECK(update_one_rr(db, newver, &diff, DNS_DIFFOP_ADD,
19004 &zone->origin, 0, &rdata));
19005 }
19006
19007 /*
19008 * If we changed anything in the zone, write changes to journal file
19009 * and set commit to ISC_TRUE so that resume_addnsec3chain() will be
19010 * called below in order to kick off adding/removing relevant NSEC3
19011 * records.
19012 */
19013 if (!ISC_LIST_EMPTY(diff.tuples)) {
19014 CHECK(update_soa_serial(db, newver, &diff, zone->mctx,
19015 zone->updatemethod));
19016 result = dns_update_signatures(&log, zone, db,
19017 oldver, newver, &diff,
19018 zone->sigvalidityinterval);
19019 if (result != ISC_R_NOTFOUND)
19020 CHECK(result);
19021 CHECK(zone_journal(zone, &diff, NULL, "setnsec3param"));
19022 commit = ISC_TRUE;
19023
19024 LOCK_ZONE(zone);
19025 DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED);
19026 zone_needdump(zone, 30);
19027 UNLOCK_ZONE(zone);
19028 }
19029
19030 failure:
19031 if (dns_rdataset_isassociated(&prdataset))
19032 dns_rdataset_disassociate(&prdataset);
19033 if (dns_rdataset_isassociated(&nrdataset))
19034 dns_rdataset_disassociate(&nrdataset);
19035 if (node != NULL)
19036 dns_db_detachnode(db, &node);
19037 if (oldver != NULL)
19038 dns_db_closeversion(db, &oldver, ISC_FALSE);
19039 if (newver != NULL)
19040 dns_db_closeversion(db, &newver, commit);
19041 if (db != NULL)
19042 dns_db_detach(&db);
19043 if (commit) {
19044 LOCK_ZONE(zone);
19045 resume_addnsec3chain(zone);
19046 UNLOCK_ZONE(zone);
19047 }
19048 dns_diff_clear(&diff);
19049 isc_event_free(&event);
19050 dns_zone_idetach(&zone);
19051
19052 INSIST(oldver == NULL);
19053 INSIST(newver == NULL);
19054 }
19055
19056 /*
19057 * Called when an "rndc signing -nsec3param ..." command is received.
19058 *
19059 * Allocate and prepare an nsec3param_t structure which holds information about
19060 * the NSEC3 changes requested for the zone:
19061 *
19062 * - if NSEC3 is to be disabled ("-nsec3param none"), only set the "nsec"
19063 * field of the structure to ISC_TRUE and the "replace" field to the value
19064 * of the "replace" argument, leaving other fields initialized to zeros, to
19065 * signal that the zone should be signed using NSEC instead of NSEC3,
19066 *
19067 * - otherwise, prepare NSEC3PARAM RDATA that will eventually be inserted at
19068 * the zone apex, convert it to a private-type record and store the latter
19069 * in the "data" field of the nsec3param_t structure.
19070 *
19071 * Once the nsec3param_t structure is prepared, post an event to the zone's
19072 * task which will cause setnsec3param() to be called with the prepared
19073 * structure passed as an argument.
19074 */
19075 isc_result_t
19076 dns_zone_setnsec3param(dns_zone_t *zone, isc_uint8_t hash, isc_uint8_t flags,
19077 isc_uint16_t iter, isc_uint8_t saltlen,
19078 unsigned char *salt, isc_boolean_t replace)
19079 {
19080 isc_result_t result = ISC_R_SUCCESS;
19081 dns_rdata_nsec3param_t param;
19082 dns_rdata_t nrdata = DNS_RDATA_INIT;
19083 dns_rdata_t prdata = DNS_RDATA_INIT;
19084 unsigned char nbuf[DNS_NSEC3PARAM_BUFFERSIZE];
19085 struct np3event *npe;
19086 nsec3param_t *np;
19087 dns_zone_t *dummy = NULL;
19088 isc_buffer_t b;
19089 isc_event_t *e;
19090
19091 REQUIRE(DNS_ZONE_VALID(zone));
19092 REQUIRE(salt != NULL);
19093
19094 LOCK_ZONE(zone);
19095
19096 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETNSEC3PARAM,
19097 setnsec3param, zone, sizeof(struct np3event));
19098 if (e == NULL) {
19099 result = ISC_R_NOMEMORY;
19100 goto failure;
19101 }
19102
19103 npe = (struct np3event *) e;
19104 np = &npe->params;
19105
19106 np->replace = replace;
19107 if (hash == 0) {
19108 np->length = 0;
19109 np->nsec = ISC_TRUE;
19110 } else {
19111 param.common.rdclass = zone->rdclass;
19112 param.common.rdtype = dns_rdatatype_nsec3param;
19113 ISC_LINK_INIT(¶m.common, link);
19114 param.mctx = NULL;
19115 param.hash = hash;
19116 param.flags = flags;
19117 param.iterations = iter;
19118 param.salt_length = saltlen;
19119 param.salt = salt;
19120 isc_buffer_init(&b, nbuf, sizeof(nbuf));
19121 CHECK(dns_rdata_fromstruct(&nrdata, zone->rdclass,
19122 dns_rdatatype_nsec3param,
19123 ¶m, &b));
19124 dns_nsec3param_toprivate(&nrdata, &prdata, zone->privatetype,
19125 np->data, sizeof(np->data));
19126 np->length = prdata.length;
19127 np->nsec = ISC_FALSE;
19128 }
19129
19130 zone_iattach(zone, &dummy);
19131 isc_task_send(zone->task, &e);
19132
19133 failure:
19134 if (e != NULL)
19135 isc_event_free(&e);
19136 UNLOCK_ZONE(zone);
19137 return (result);
19138 }
19139
19140 isc_result_t
19141 dns_zone_getloadtime(dns_zone_t *zone, isc_time_t *loadtime) {
19142 REQUIRE(DNS_ZONE_VALID(zone));
19143 REQUIRE(loadtime != NULL);
19144
19145 LOCK_ZONE(zone);
19146 *loadtime = zone->loadtime;
19147 UNLOCK_ZONE(zone);
19148 return (ISC_R_SUCCESS);
19149 }
19150
19151 isc_result_t
19152 dns_zone_getexpiretime(dns_zone_t *zone, isc_time_t *expiretime) {
19153 REQUIRE(DNS_ZONE_VALID(zone));
19154 REQUIRE(expiretime != NULL);
19155
19156 LOCK_ZONE(zone);
19157 *expiretime = zone->expiretime;
19158 UNLOCK_ZONE(zone);
19159 return (ISC_R_SUCCESS);
19160 }
19161
19162 isc_result_t
19163 dns_zone_getrefreshtime(dns_zone_t *zone, isc_time_t *refreshtime) {
19164 REQUIRE(DNS_ZONE_VALID(zone));
19165 REQUIRE(refreshtime != NULL);
19166
19167 LOCK_ZONE(zone);
19168 *refreshtime = zone->refreshtime;
19169 UNLOCK_ZONE(zone);
19170 return (ISC_R_SUCCESS);
19171 }
19172
19173 isc_result_t
19174 dns_zone_getrefreshkeytime(dns_zone_t *zone, isc_time_t *refreshkeytime) {
19175 REQUIRE(DNS_ZONE_VALID(zone));
19176 REQUIRE(refreshkeytime != NULL);
19177
19178 LOCK_ZONE(zone);
19179 *refreshkeytime = zone->refreshkeytime;
19180 UNLOCK_ZONE(zone);
19181 return (ISC_R_SUCCESS);
19182 }
19183
19184 unsigned int
19185 dns_zone_getincludes(dns_zone_t *zone, char ***includesp) {
19186 dns_include_t *include;
19187 char **array = NULL;
19188 unsigned int n = 0;
19189
19190 REQUIRE(DNS_ZONE_VALID(zone));
19191 REQUIRE(includesp != NULL && *includesp == NULL);
19192
19193 LOCK_ZONE(zone);
19194 if (zone->nincludes == 0)
19195 goto done;
19196
19197 array = isc_mem_allocate(zone->mctx, sizeof(char *) * zone->nincludes);
19198 if (array == NULL)
19199 goto done;
19200 for (include = ISC_LIST_HEAD(zone->includes);
19201 include != NULL;
19202 include = ISC_LIST_NEXT(include, link)) {
19203 INSIST(n < zone->nincludes);
19204 array[n++] = isc_mem_strdup(zone->mctx, include->name);
19205 }
19206 INSIST(n == zone->nincludes);
19207 *includesp = array;
19208
19209 done:
19210 UNLOCK_ZONE(zone);
19211 return (n);
19212 }
19213
19214 void
19215 dns_zone_setstatlevel(dns_zone_t *zone, dns_zonestat_level_t level) {
19216 REQUIRE(DNS_ZONE_VALID(zone));
19217
19218 zone->statlevel = level;
19219 }
19220
19221 dns_zonestat_level_t
19222 dns_zone_getstatlevel(dns_zone_t *zone) {
19223 REQUIRE(DNS_ZONE_VALID(zone));
19224
19225 return (zone->statlevel);
19226 }
19227
19228 static void
19229 setserial(isc_task_t *task, isc_event_t *event) {
19230 isc_uint32_t oldserial, desired;
19231 const char *me = "setserial";
19232 isc_boolean_t commit = ISC_FALSE;
19233 isc_result_t result;
19234 dns_dbversion_t *oldver = NULL, *newver = NULL;
19235 dns_zone_t *zone;
19236 dns_db_t *db = NULL;
19237 dns_diff_t diff;
19238 struct ssevent *sse = (struct ssevent *)event;
19239 dns_update_log_t log = { update_log_cb, NULL };
19240 dns_difftuple_t *oldtuple = NULL, *newtuple = NULL;
19241
19242 UNUSED(task);
19243
19244 zone = event->ev_arg;
19245 INSIST(DNS_ZONE_VALID(zone));
19246
19247 ENTER;
19248
19249 if (zone->update_disabled)
19250 goto failure;
19251
19252 desired = sse->serial;
19253
19254 dns_diff_init(zone->mctx, &diff);
19255
19256 ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
19257 if (zone->db != NULL)
19258 dns_db_attach(zone->db, &db);
19259 ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
19260 if (db == NULL)
19261 goto failure;
19262
19263 dns_db_currentversion(db, &oldver);
19264 result = dns_db_newversion(db, &newver);
19265 if (result != ISC_R_SUCCESS) {
19266 dns_zone_log(zone, ISC_LOG_ERROR,
19267 "setserial:dns_db_newversion -> %s",
19268 dns_result_totext(result));
19269 goto failure;
19270 }
19271
19272 CHECK(dns_db_createsoatuple(db, oldver, diff.mctx,
19273 DNS_DIFFOP_DEL, &oldtuple));
19274 CHECK(dns_difftuple_copy(oldtuple, &newtuple));
19275 newtuple->op = DNS_DIFFOP_ADD;
19276
19277 oldserial = dns_soa_getserial(&oldtuple->rdata);
19278 if (desired == 0U)
19279 desired = 1;
19280 if (!isc_serial_gt(desired, oldserial)) {
19281 if (desired != oldserial)
19282 dns_zone_log(zone, ISC_LOG_INFO,
19283 "setserial: desired serial (%u) "
19284 "out of range (%u-%u)", desired,
19285 oldserial + 1, (oldserial + 0x7fffffff));
19286 goto failure;
19287 }
19288
19289 dns_soa_setserial(desired, &newtuple->rdata);
19290 CHECK(do_one_tuple(&oldtuple, db, newver, &diff));
19291 CHECK(do_one_tuple(&newtuple, db, newver, &diff));
19292 result = dns_update_signatures(&log, zone, db,
19293 oldver, newver, &diff,
19294 zone->sigvalidityinterval);
19295 if (result != ISC_R_NOTFOUND)
19296 CHECK(result);
19297
19298 /* Write changes to journal file. */
19299 CHECK(zone_journal(zone, &diff, NULL, "setserial"));
19300 commit = ISC_TRUE;
19301
19302 LOCK_ZONE(zone);
19303 zone_needdump(zone, 30);
19304 UNLOCK_ZONE(zone);
19305
19306 failure:
19307 if (oldtuple != NULL)
19308 dns_difftuple_free(&oldtuple);
19309 if (newtuple != NULL)
19310 dns_difftuple_free(&newtuple);
19311 if (oldver != NULL)
19312 dns_db_closeversion(db, &oldver, ISC_FALSE);
19313 if (newver != NULL)
19314 dns_db_closeversion(db, &newver, commit);
19315 if (db != NULL)
19316 dns_db_detach(&db);
19317 dns_diff_clear(&diff);
19318 isc_event_free(&event);
19319 dns_zone_idetach(&zone);
19320
19321 INSIST(oldver == NULL);
19322 INSIST(newver == NULL);
19323 }
19324
19325 isc_result_t
19326 dns_zone_setserial(dns_zone_t *zone, isc_uint32_t serial) {
19327 isc_result_t result = ISC_R_SUCCESS;
19328 dns_zone_t *dummy = NULL;
19329 isc_event_t *e = NULL;
19330 struct ssevent *sse;
19331
19332 REQUIRE(DNS_ZONE_VALID(zone));
19333
19334 LOCK_ZONE(zone);
19335
19336 if (!inline_secure(zone)) {
19337 if (!dns_zone_isdynamic(zone, ISC_TRUE)) {
19338 result = DNS_R_NOTDYNAMIC;
19339 goto failure;
19340 }
19341 }
19342
19343 if (zone->update_disabled) {
19344 result = DNS_R_FROZEN;
19345 goto failure;
19346 }
19347
19348 e = isc_event_allocate(zone->mctx, zone, DNS_EVENT_SETSERIAL,
19349 setserial, zone, sizeof(struct ssevent));
19350 if (e == NULL) {
19351 result = ISC_R_NOMEMORY;
19352 goto failure;
19353 }
19354
19355 sse = (struct ssevent *)e;
19356 sse->serial = serial;
19357
19358 zone_iattach(zone, &dummy);
19359 isc_task_send(zone->task, &e);
19360
19361 failure:
19362 if (e != NULL)
19363 isc_event_free(&e);
19364 UNLOCK_ZONE(zone);
19365 return (result);
19366 }
19367
19368 isc_stats_t *
19369 dns_zone_getgluecachestats(dns_zone_t *zone) {
19370 REQUIRE(DNS_ZONE_VALID(zone));
19371
19372 return (zone->gluecachestats);
19373 }
19374