1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 /*! \file */
13
14 #include <inttypes.h>
15 #include <limits.h>
16 #include <stdbool.h>
17
18 #ifdef HAVE_LMDB
19 #include <lmdb.h>
20 #endif /* ifdef HAVE_LMDB */
21
22 #include <isc/atomic.h>
23 #include <isc/dir.h>
24 #include <isc/file.h>
25 #include <isc/hash.h>
26 #include <isc/lex.h>
27 #include <isc/print.h>
28 #include <isc/result.h>
29 #include <isc/stats.h>
30 #include <isc/string.h> /* Required for HP/UX (and others?) */
31 #include <isc/task.h>
32 #include <isc/util.h>
33
34 #include <dns/acl.h>
35 #include <dns/adb.h>
36 #include <dns/badcache.h>
37 #include <dns/cache.h>
38 #include <dns/db.h>
39 #include <dns/dispatch.h>
40 #include <dns/dlz.h>
41 #include <dns/dns64.h>
42 #include <dns/dnssec.h>
43 #include <dns/events.h>
44 #include <dns/forward.h>
45 #include <dns/keytable.h>
46 #include <dns/keyvalues.h>
47 #include <dns/master.h>
48 #include <dns/masterdump.h>
49 #include <dns/nta.h>
50 #include <dns/order.h>
51 #include <dns/peer.h>
52 #include <dns/rbt.h>
53 #include <dns/rdataset.h>
54 #include <dns/request.h>
55 #include <dns/resolver.h>
56 #include <dns/rpz.h>
57 #include <dns/rrl.h>
58 #include <dns/stats.h>
59 #include <dns/time.h>
60 #include <dns/transport.h>
61 #include <dns/tsig.h>
62 #include <dns/zone.h>
63 #include <dns/zt.h>
64
65 #define CHECK(op) \
66 do { \
67 result = (op); \
68 if (result != ISC_R_SUCCESS) \
69 goto cleanup; \
70 } while (0)
71
72 #define RESSHUTDOWN(v) \
73 ((atomic_load(&(v)->attributes) & DNS_VIEWATTR_RESSHUTDOWN) != 0)
74 #define ADBSHUTDOWN(v) \
75 ((atomic_load(&(v)->attributes) & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
76 #define REQSHUTDOWN(v) \
77 ((atomic_load(&(v)->attributes) & DNS_VIEWATTR_REQSHUTDOWN) != 0)
78
79 #define DNS_VIEW_DELONLYHASH 111
80 #define DNS_VIEW_FAILCACHESIZE 1021
81
82 static void
83 resolver_shutdown(isc_task_t *task, isc_event_t *event);
84 static void
85 adb_shutdown(isc_task_t *task, isc_event_t *event);
86 static void
87 req_shutdown(isc_task_t *task, isc_event_t *event);
88
89 isc_result_t
dns_view_create(isc_mem_t * mctx,dns_rdataclass_t rdclass,const char * name,dns_view_t ** viewp)90 dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name,
91 dns_view_t **viewp) {
92 dns_view_t *view;
93 isc_result_t result;
94 char buffer[1024];
95
96 /*
97 * Create a view.
98 */
99
100 REQUIRE(name != NULL);
101 REQUIRE(viewp != NULL && *viewp == NULL);
102
103 view = isc_mem_get(mctx, sizeof(*view));
104
105 view->nta_file = NULL;
106 view->mctx = NULL;
107 isc_mem_attach(mctx, &view->mctx);
108 view->name = isc_mem_strdup(mctx, name);
109
110 result = isc_file_sanitize(NULL, view->name, "nta", buffer,
111 sizeof(buffer));
112 if (result != ISC_R_SUCCESS) {
113 goto cleanup_name;
114 }
115 view->nta_file = isc_mem_strdup(mctx, buffer);
116
117 isc_mutex_init(&view->lock);
118
119 view->zonetable = NULL;
120 result = dns_zt_create(mctx, rdclass, &view->zonetable);
121 if (result != ISC_R_SUCCESS) {
122 UNEXPECTED_ERROR(__FILE__, __LINE__,
123 "dns_zt_create() failed: %s",
124 isc_result_totext(result));
125 result = ISC_R_UNEXPECTED;
126 goto cleanup_mutex;
127 }
128
129 view->secroots_priv = NULL;
130 view->ntatable_priv = NULL;
131 view->fwdtable = NULL;
132 result = dns_fwdtable_create(mctx, &view->fwdtable);
133 if (result != ISC_R_SUCCESS) {
134 UNEXPECTED_ERROR(__FILE__, __LINE__,
135 "dns_fwdtable_create() failed: %s",
136 isc_result_totext(result));
137 result = ISC_R_UNEXPECTED;
138 goto cleanup_zt;
139 }
140
141 view->cache = NULL;
142 view->cachedb = NULL;
143 ISC_LIST_INIT(view->dlz_searched);
144 ISC_LIST_INIT(view->dlz_unsearched);
145 view->hints = NULL;
146 view->resolver = NULL;
147 view->adb = NULL;
148 view->requestmgr = NULL;
149 view->rdclass = rdclass;
150 view->frozen = false;
151 view->task = NULL;
152 isc_refcount_init(&view->references, 1);
153 isc_refcount_init(&view->weakrefs, 1);
154 atomic_init(&view->attributes,
155 (DNS_VIEWATTR_RESSHUTDOWN | DNS_VIEWATTR_ADBSHUTDOWN |
156 DNS_VIEWATTR_REQSHUTDOWN));
157 view->transports = NULL;
158 view->statickeys = NULL;
159 view->dynamickeys = NULL;
160 view->matchclients = NULL;
161 view->matchdestinations = NULL;
162 view->matchrecursiveonly = false;
163 result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
164 if (result != ISC_R_SUCCESS) {
165 goto cleanup_weakrefs;
166 }
167 view->peers = NULL;
168 view->order = NULL;
169 view->delonly = NULL;
170 view->rootdelonly = false;
171 view->rootexclude = NULL;
172 view->adbstats = NULL;
173 view->resstats = NULL;
174 view->resquerystats = NULL;
175 view->cacheshared = false;
176 ISC_LIST_INIT(view->dns64);
177 view->dns64cnt = 0;
178
179 /*
180 * Initialize configuration data with default values.
181 */
182 view->recursion = true;
183 view->qminimization = false;
184 view->qmin_strict = false;
185 view->auth_nxdomain = false; /* Was true in BIND 8 */
186 view->enablevalidation = true;
187 view->acceptexpired = false;
188 view->use_glue_cache = false;
189 view->minimal_any = false;
190 view->minimalresponses = dns_minimal_no;
191 view->transfer_format = dns_one_answer;
192 view->cacheacl = NULL;
193 view->cacheonacl = NULL;
194 view->checknames = false;
195 view->queryacl = NULL;
196 view->queryonacl = NULL;
197 view->recursionacl = NULL;
198 view->recursiononacl = NULL;
199 view->sortlist = NULL;
200 view->transferacl = NULL;
201 view->notifyacl = NULL;
202 view->updateacl = NULL;
203 view->upfwdacl = NULL;
204 view->denyansweracl = NULL;
205 view->nocasecompress = NULL;
206 view->msgcompression = true;
207 view->answeracl_exclude = NULL;
208 view->denyanswernames = NULL;
209 view->answernames_exclude = NULL;
210 view->rrl = NULL;
211 view->provideixfr = true;
212 view->maxcachettl = 7 * 24 * 3600;
213 view->maxncachettl = 3 * 3600;
214 view->mincachettl = 0;
215 view->minncachettl = 0;
216 view->nta_lifetime = 0;
217 view->nta_recheck = 0;
218 view->prefetch_eligible = 0;
219 view->prefetch_trigger = 0;
220 view->dstport = 53;
221 view->preferred_glue = 0;
222 view->flush = false;
223 view->maxudp = 0;
224 view->staleanswerttl = 1;
225 view->staleanswersok = dns_stale_answer_conf;
226 view->staleanswersenable = false;
227 view->nocookieudp = 0;
228 view->padding = 0;
229 view->pad_acl = NULL;
230 view->maxbits = 0;
231 view->rpzs = NULL;
232 view->catzs = NULL;
233 view->managed_keys = NULL;
234 view->redirect = NULL;
235 view->redirectzone = NULL;
236 dns_fixedname_init(&view->redirectfixed);
237 view->requestnsid = false;
238 view->sendcookie = true;
239 view->requireservercookie = false;
240 view->synthfromdnssec = true;
241 view->trust_anchor_telemetry = true;
242 view->root_key_sentinel = true;
243 view->new_zone_dir = NULL;
244 view->new_zone_file = NULL;
245 view->new_zone_db = NULL;
246 view->new_zone_dbenv = NULL;
247 view->new_zone_mapsize = 0ULL;
248 view->new_zone_config = NULL;
249 view->cfg_destroy = NULL;
250 view->fail_ttl = 0;
251 view->failcache = NULL;
252 result = dns_badcache_init(view->mctx, DNS_VIEW_FAILCACHESIZE,
253 &view->failcache);
254 if (result != ISC_R_SUCCESS) {
255 goto cleanup_dynkeys;
256 }
257 view->v6bias = 0;
258 view->dtenv = NULL;
259 view->dttypes = 0;
260
261 view->plugins = NULL;
262 view->plugins_free = NULL;
263 view->hooktable = NULL;
264 view->hooktable_free = NULL;
265
266 isc_mutex_init(&view->new_zone_lock);
267
268 result = dns_order_create(view->mctx, &view->order);
269 if (result != ISC_R_SUCCESS) {
270 goto cleanup_new_zone_lock;
271 }
272
273 result = dns_peerlist_new(view->mctx, &view->peers);
274 if (result != ISC_R_SUCCESS) {
275 goto cleanup_order;
276 }
277
278 result = dns_aclenv_create(view->mctx, &view->aclenv);
279 if (result != ISC_R_SUCCESS) {
280 goto cleanup_peerlist;
281 }
282
283 ISC_LINK_INIT(view, link);
284 ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
285 DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, view, NULL,
286 NULL, NULL);
287 ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
288 DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, view, NULL,
289 NULL, NULL);
290 ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
291 DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, view, NULL,
292 NULL, NULL);
293 view->viewlist = NULL;
294 view->magic = DNS_VIEW_MAGIC;
295
296 *viewp = view;
297
298 return (ISC_R_SUCCESS);
299
300 cleanup_peerlist:
301 if (view->peers != NULL) {
302 dns_peerlist_detach(&view->peers);
303 }
304
305 cleanup_order:
306 if (view->order != NULL) {
307 dns_order_detach(&view->order);
308 }
309
310 cleanup_new_zone_lock:
311 isc_mutex_destroy(&view->new_zone_lock);
312
313 dns_badcache_destroy(&view->failcache);
314
315 cleanup_dynkeys:
316 if (view->dynamickeys != NULL) {
317 dns_tsigkeyring_detach(&view->dynamickeys);
318 }
319
320 cleanup_weakrefs:
321 isc_refcount_decrementz(&view->weakrefs);
322 isc_refcount_destroy(&view->weakrefs);
323
324 isc_refcount_decrementz(&view->references);
325 isc_refcount_destroy(&view->references);
326
327 if (view->fwdtable != NULL) {
328 dns_fwdtable_destroy(&view->fwdtable);
329 }
330
331 cleanup_zt:
332 if (view->zonetable != NULL) {
333 dns_zt_detach(&view->zonetable);
334 }
335
336 cleanup_mutex:
337 isc_mutex_destroy(&view->lock);
338
339 if (view->nta_file != NULL) {
340 isc_mem_free(mctx, view->nta_file);
341 }
342
343 cleanup_name:
344 isc_mem_free(mctx, view->name);
345 isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
346
347 return (result);
348 }
349
350 static inline void
destroy(dns_view_t * view)351 destroy(dns_view_t *view) {
352 dns_dns64_t *dns64;
353 dns_dlzdb_t *dlzdb;
354
355 REQUIRE(!ISC_LINK_LINKED(view, link));
356 REQUIRE(RESSHUTDOWN(view));
357 REQUIRE(ADBSHUTDOWN(view));
358 REQUIRE(REQSHUTDOWN(view));
359
360 isc_refcount_destroy(&view->references);
361 isc_refcount_destroy(&view->weakrefs);
362
363 if (view->order != NULL) {
364 dns_order_detach(&view->order);
365 }
366 if (view->peers != NULL) {
367 dns_peerlist_detach(&view->peers);
368 }
369
370 if (view->dynamickeys != NULL) {
371 isc_result_t result;
372 char template[PATH_MAX];
373 char keyfile[PATH_MAX];
374 FILE *fp = NULL;
375
376 result = isc_file_mktemplate(NULL, template, sizeof(template));
377 if (result == ISC_R_SUCCESS) {
378 (void)isc_file_openuniqueprivate(template, &fp);
379 }
380 if (fp == NULL) {
381 dns_tsigkeyring_detach(&view->dynamickeys);
382 } else {
383 result = dns_tsigkeyring_dumpanddetach(
384 &view->dynamickeys, fp);
385 if (result == ISC_R_SUCCESS) {
386 if (fclose(fp) == 0) {
387 result = isc_file_sanitize(
388 NULL, view->name, "tsigkeys",
389 keyfile, sizeof(keyfile));
390 if (result == ISC_R_SUCCESS) {
391 result = isc_file_rename(
392 template, keyfile);
393 }
394 }
395 if (result != ISC_R_SUCCESS) {
396 (void)remove(template);
397 }
398 } else {
399 (void)fclose(fp);
400 (void)remove(template);
401 }
402 }
403 }
404 if (view->transports != NULL) {
405 dns_transport_list_detach(&view->transports);
406 }
407 if (view->statickeys != NULL) {
408 dns_tsigkeyring_detach(&view->statickeys);
409 }
410 if (view->adb != NULL) {
411 dns_adb_detach(&view->adb);
412 }
413 if (view->resolver != NULL) {
414 dns_resolver_detach(&view->resolver);
415 }
416 dns_rrl_view_destroy(view);
417 if (view->rpzs != NULL) {
418 dns_rpz_detach_rpzs(&view->rpzs);
419 }
420 if (view->catzs != NULL) {
421 dns_catz_catzs_detach(&view->catzs);
422 }
423 for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL;
424 dlzdb = ISC_LIST_HEAD(view->dlz_searched))
425 {
426 ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link);
427 dns_dlzdestroy(&dlzdb);
428 }
429 for (dlzdb = ISC_LIST_HEAD(view->dlz_unsearched); dlzdb != NULL;
430 dlzdb = ISC_LIST_HEAD(view->dlz_unsearched))
431 {
432 ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link);
433 dns_dlzdestroy(&dlzdb);
434 }
435 if (view->requestmgr != NULL) {
436 dns_requestmgr_detach(&view->requestmgr);
437 }
438 if (view->task != NULL) {
439 isc_task_detach(&view->task);
440 }
441 if (view->hints != NULL) {
442 dns_db_detach(&view->hints);
443 }
444 if (view->cachedb != NULL) {
445 dns_db_detach(&view->cachedb);
446 }
447 if (view->cache != NULL) {
448 dns_cache_detach(&view->cache);
449 }
450 if (view->nocasecompress != NULL) {
451 dns_acl_detach(&view->nocasecompress);
452 }
453 if (view->matchclients != NULL) {
454 dns_acl_detach(&view->matchclients);
455 }
456 if (view->matchdestinations != NULL) {
457 dns_acl_detach(&view->matchdestinations);
458 }
459 if (view->cacheacl != NULL) {
460 dns_acl_detach(&view->cacheacl);
461 }
462 if (view->cacheonacl != NULL) {
463 dns_acl_detach(&view->cacheonacl);
464 }
465 if (view->queryacl != NULL) {
466 dns_acl_detach(&view->queryacl);
467 }
468 if (view->queryonacl != NULL) {
469 dns_acl_detach(&view->queryonacl);
470 }
471 if (view->recursionacl != NULL) {
472 dns_acl_detach(&view->recursionacl);
473 }
474 if (view->recursiononacl != NULL) {
475 dns_acl_detach(&view->recursiononacl);
476 }
477 if (view->sortlist != NULL) {
478 dns_acl_detach(&view->sortlist);
479 }
480 if (view->transferacl != NULL) {
481 dns_acl_detach(&view->transferacl);
482 }
483 if (view->notifyacl != NULL) {
484 dns_acl_detach(&view->notifyacl);
485 }
486 if (view->updateacl != NULL) {
487 dns_acl_detach(&view->updateacl);
488 }
489 if (view->upfwdacl != NULL) {
490 dns_acl_detach(&view->upfwdacl);
491 }
492 if (view->denyansweracl != NULL) {
493 dns_acl_detach(&view->denyansweracl);
494 }
495 if (view->pad_acl != NULL) {
496 dns_acl_detach(&view->pad_acl);
497 }
498 if (view->answeracl_exclude != NULL) {
499 dns_rbt_destroy(&view->answeracl_exclude);
500 }
501 if (view->denyanswernames != NULL) {
502 dns_rbt_destroy(&view->denyanswernames);
503 }
504 if (view->answernames_exclude != NULL) {
505 dns_rbt_destroy(&view->answernames_exclude);
506 }
507 if (view->delonly != NULL) {
508 dns_name_t *name;
509 int i;
510
511 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
512 name = ISC_LIST_HEAD(view->delonly[i]);
513 while (name != NULL) {
514 ISC_LIST_UNLINK(view->delonly[i], name, link);
515 dns_name_free(name, view->mctx);
516 isc_mem_put(view->mctx, name, sizeof(*name));
517 name = ISC_LIST_HEAD(view->delonly[i]);
518 }
519 }
520 isc_mem_put(view->mctx, view->delonly,
521 sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
522 view->delonly = NULL;
523 }
524 if (view->rootexclude != NULL) {
525 dns_name_t *name;
526 int i;
527
528 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
529 name = ISC_LIST_HEAD(view->rootexclude[i]);
530 while (name != NULL) {
531 ISC_LIST_UNLINK(view->rootexclude[i], name,
532 link);
533 dns_name_free(name, view->mctx);
534 isc_mem_put(view->mctx, name, sizeof(*name));
535 name = ISC_LIST_HEAD(view->rootexclude[i]);
536 }
537 }
538 isc_mem_put(view->mctx, view->rootexclude,
539 sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
540 view->rootexclude = NULL;
541 }
542 if (view->adbstats != NULL) {
543 isc_stats_detach(&view->adbstats);
544 }
545 if (view->resstats != NULL) {
546 isc_stats_detach(&view->resstats);
547 }
548 if (view->resquerystats != NULL) {
549 dns_stats_detach(&view->resquerystats);
550 }
551 if (view->secroots_priv != NULL) {
552 dns_keytable_detach(&view->secroots_priv);
553 }
554 if (view->ntatable_priv != NULL) {
555 dns_ntatable_detach(&view->ntatable_priv);
556 }
557 for (dns64 = ISC_LIST_HEAD(view->dns64); dns64 != NULL;
558 dns64 = ISC_LIST_HEAD(view->dns64))
559 {
560 dns_dns64_unlink(&view->dns64, dns64);
561 dns_dns64_destroy(&dns64);
562 }
563 if (view->managed_keys != NULL) {
564 dns_zone_detach(&view->managed_keys);
565 }
566 if (view->redirect != NULL) {
567 dns_zone_detach(&view->redirect);
568 }
569 #ifdef HAVE_DNSTAP
570 if (view->dtenv != NULL) {
571 dns_dt_detach(&view->dtenv);
572 }
573 #endif /* HAVE_DNSTAP */
574 dns_view_setnewzones(view, false, NULL, NULL, 0ULL);
575 if (view->new_zone_file != NULL) {
576 isc_mem_free(view->mctx, view->new_zone_file);
577 view->new_zone_file = NULL;
578 }
579 if (view->new_zone_dir != NULL) {
580 isc_mem_free(view->mctx, view->new_zone_dir);
581 view->new_zone_dir = NULL;
582 }
583 #ifdef HAVE_LMDB
584 if (view->new_zone_dbenv != NULL) {
585 mdb_env_close((MDB_env *)view->new_zone_dbenv);
586 view->new_zone_dbenv = NULL;
587 }
588 if (view->new_zone_db != NULL) {
589 isc_mem_free(view->mctx, view->new_zone_db);
590 view->new_zone_db = NULL;
591 }
592 #endif /* HAVE_LMDB */
593 dns_fwdtable_destroy(&view->fwdtable);
594 dns_aclenv_detach(&view->aclenv);
595 if (view->failcache != NULL) {
596 dns_badcache_destroy(&view->failcache);
597 }
598 isc_mutex_destroy(&view->new_zone_lock);
599 isc_mutex_destroy(&view->lock);
600 isc_refcount_destroy(&view->references);
601 isc_refcount_destroy(&view->weakrefs);
602 isc_mem_free(view->mctx, view->nta_file);
603 isc_mem_free(view->mctx, view->name);
604 if (view->hooktable != NULL && view->hooktable_free != NULL) {
605 view->hooktable_free(view->mctx, &view->hooktable);
606 }
607 if (view->plugins != NULL && view->plugins_free != NULL) {
608 view->plugins_free(view->mctx, &view->plugins);
609 }
610 isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
611 }
612
613 void
dns_view_attach(dns_view_t * source,dns_view_t ** targetp)614 dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
615 REQUIRE(DNS_VIEW_VALID(source));
616 REQUIRE(targetp != NULL && *targetp == NULL);
617
618 isc_refcount_increment(&source->references);
619
620 *targetp = source;
621 }
622
623 static void
view_flushanddetach(dns_view_t ** viewp,bool flush)624 view_flushanddetach(dns_view_t **viewp, bool flush) {
625 REQUIRE(viewp != NULL && DNS_VIEW_VALID(*viewp));
626 dns_view_t *view = *viewp;
627 *viewp = NULL;
628
629 if (flush) {
630 view->flush = flush;
631 }
632
633 if (isc_refcount_decrement(&view->references) == 1) {
634 dns_zone_t *mkzone = NULL, *rdzone = NULL;
635
636 isc_refcount_destroy(&view->references);
637
638 if (!RESSHUTDOWN(view)) {
639 dns_resolver_shutdown(view->resolver);
640 }
641 if (!ADBSHUTDOWN(view)) {
642 dns_adb_shutdown(view->adb);
643 }
644 if (!REQSHUTDOWN(view)) {
645 dns_requestmgr_shutdown(view->requestmgr);
646 }
647
648 if (view->zonetable != NULL && view->flush) {
649 dns_zt_flushanddetach(&view->zonetable);
650 } else if (view->zonetable != NULL) {
651 dns_zt_detach(&view->zonetable);
652 }
653
654 LOCK(&view->lock);
655 if (view->managed_keys != NULL) {
656 mkzone = view->managed_keys;
657 view->managed_keys = NULL;
658 if (view->flush) {
659 dns_zone_flush(mkzone);
660 }
661 }
662 if (view->redirect != NULL) {
663 rdzone = view->redirect;
664 view->redirect = NULL;
665 if (view->flush) {
666 dns_zone_flush(rdzone);
667 }
668 }
669 if (view->catzs != NULL) {
670 dns_catz_catzs_detach(&view->catzs);
671 }
672 if (view->ntatable_priv != NULL) {
673 dns_ntatable_shutdown(view->ntatable_priv);
674 }
675 UNLOCK(&view->lock);
676
677 /* Need to detach zones outside view lock */
678 if (mkzone != NULL) {
679 dns_zone_detach(&mkzone);
680 }
681
682 if (rdzone != NULL) {
683 dns_zone_detach(&rdzone);
684 }
685
686 dns_view_weakdetach(&view);
687 }
688 }
689
690 void
dns_view_flushanddetach(dns_view_t ** viewp)691 dns_view_flushanddetach(dns_view_t **viewp) {
692 view_flushanddetach(viewp, true);
693 }
694
695 void
dns_view_detach(dns_view_t ** viewp)696 dns_view_detach(dns_view_t **viewp) {
697 view_flushanddetach(viewp, false);
698 }
699
700 static isc_result_t
dialup(dns_zone_t * zone,void * dummy)701 dialup(dns_zone_t *zone, void *dummy) {
702 UNUSED(dummy);
703 dns_zone_dialup(zone);
704 return (ISC_R_SUCCESS);
705 }
706
707 void
dns_view_dialup(dns_view_t * view)708 dns_view_dialup(dns_view_t *view) {
709 REQUIRE(DNS_VIEW_VALID(view));
710 REQUIRE(view->zonetable != NULL);
711
712 (void)dns_zt_apply(view->zonetable, false, NULL, dialup, NULL);
713 }
714
715 void
dns_view_weakattach(dns_view_t * source,dns_view_t ** targetp)716 dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
717 REQUIRE(DNS_VIEW_VALID(source));
718 REQUIRE(targetp != NULL && *targetp == NULL);
719
720 isc_refcount_increment(&source->weakrefs);
721
722 *targetp = source;
723 }
724
725 void
dns_view_weakdetach(dns_view_t ** viewp)726 dns_view_weakdetach(dns_view_t **viewp) {
727 dns_view_t *view;
728
729 REQUIRE(viewp != NULL);
730 view = *viewp;
731 *viewp = NULL;
732 REQUIRE(DNS_VIEW_VALID(view));
733
734 if (isc_refcount_decrement(&view->weakrefs) == 1) {
735 destroy(view);
736 }
737 }
738
739 static void
resolver_shutdown(isc_task_t * task,isc_event_t * event)740 resolver_shutdown(isc_task_t *task, isc_event_t *event) {
741 dns_view_t *view = event->ev_arg;
742
743 REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
744 REQUIRE(DNS_VIEW_VALID(view));
745 REQUIRE(view->task == task);
746
747 UNUSED(task);
748
749 isc_event_free(&event);
750
751 atomic_fetch_or(&view->attributes, DNS_VIEWATTR_RESSHUTDOWN);
752 dns_view_weakdetach(&view);
753 }
754
755 static void
adb_shutdown(isc_task_t * task,isc_event_t * event)756 adb_shutdown(isc_task_t *task, isc_event_t *event) {
757 dns_view_t *view = event->ev_arg;
758
759 REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
760 REQUIRE(DNS_VIEW_VALID(view));
761 REQUIRE(view->task == task);
762
763 UNUSED(task);
764
765 isc_event_free(&event);
766
767 atomic_fetch_or(&view->attributes, DNS_VIEWATTR_ADBSHUTDOWN);
768
769 dns_view_weakdetach(&view);
770 }
771
772 static void
req_shutdown(isc_task_t * task,isc_event_t * event)773 req_shutdown(isc_task_t *task, isc_event_t *event) {
774 dns_view_t *view = event->ev_arg;
775
776 REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
777 REQUIRE(DNS_VIEW_VALID(view));
778 REQUIRE(view->task == task);
779
780 UNUSED(task);
781
782 isc_event_free(&event);
783
784 atomic_fetch_or(&view->attributes, DNS_VIEWATTR_REQSHUTDOWN);
785
786 dns_view_weakdetach(&view);
787 }
788
789 isc_result_t
dns_view_createzonetable(dns_view_t * view)790 dns_view_createzonetable(dns_view_t *view) {
791 REQUIRE(DNS_VIEW_VALID(view));
792 REQUIRE(!view->frozen);
793 REQUIRE(view->zonetable == NULL);
794
795 return (dns_zt_create(view->mctx, view->rdclass, &view->zonetable));
796 }
797
798 isc_result_t
dns_view_createresolver(dns_view_t * view,isc_taskmgr_t * taskmgr,unsigned int ntasks,unsigned int ndisp,isc_nm_t * nm,isc_timermgr_t * timermgr,unsigned int options,dns_dispatchmgr_t * dispatchmgr,dns_dispatch_t * dispatchv4,dns_dispatch_t * dispatchv6)799 dns_view_createresolver(dns_view_t *view, isc_taskmgr_t *taskmgr,
800 unsigned int ntasks, unsigned int ndisp, isc_nm_t *nm,
801 isc_timermgr_t *timermgr, unsigned int options,
802 dns_dispatchmgr_t *dispatchmgr,
803 dns_dispatch_t *dispatchv4,
804 dns_dispatch_t *dispatchv6) {
805 isc_result_t result;
806 isc_event_t *event;
807 isc_mem_t *mctx = NULL;
808
809 REQUIRE(DNS_VIEW_VALID(view));
810 REQUIRE(!view->frozen);
811 REQUIRE(view->resolver == NULL);
812
813 result = isc_task_create(taskmgr, 0, &view->task);
814 if (result != ISC_R_SUCCESS) {
815 return (result);
816 }
817 isc_task_setname(view->task, "view", view);
818
819 result = dns_resolver_create(view, taskmgr, ntasks, ndisp, nm, timermgr,
820 options, dispatchmgr, dispatchv4,
821 dispatchv6, &view->resolver);
822 if (result != ISC_R_SUCCESS) {
823 isc_task_detach(&view->task);
824 return (result);
825 }
826 event = &view->resevent;
827 dns_resolver_whenshutdown(view->resolver, view->task, &event);
828 atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_RESSHUTDOWN);
829 isc_refcount_increment(&view->weakrefs);
830
831 isc_mem_create(&mctx);
832
833 result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
834 isc_mem_setname(mctx, "ADB");
835 isc_mem_detach(&mctx);
836 if (result != ISC_R_SUCCESS) {
837 dns_resolver_shutdown(view->resolver);
838 return (result);
839 }
840 event = &view->adbevent;
841 dns_adb_whenshutdown(view->adb, view->task, &event);
842 atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_ADBSHUTDOWN);
843 isc_refcount_increment(&view->weakrefs);
844
845 result = dns_requestmgr_create(
846 view->mctx, dns_resolver_taskmgr(view->resolver),
847 dns_resolver_dispatchmgr(view->resolver), dispatchv4,
848 dispatchv6, &view->requestmgr);
849 if (result != ISC_R_SUCCESS) {
850 dns_adb_shutdown(view->adb);
851 dns_resolver_shutdown(view->resolver);
852 return (result);
853 }
854 event = &view->reqevent;
855 dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
856 atomic_fetch_and(&view->attributes, ~DNS_VIEWATTR_REQSHUTDOWN);
857 isc_refcount_increment(&view->weakrefs);
858
859 return (ISC_R_SUCCESS);
860 }
861
862 void
dns_view_setcache(dns_view_t * view,dns_cache_t * cache,bool shared)863 dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
864 REQUIRE(DNS_VIEW_VALID(view));
865 REQUIRE(!view->frozen);
866
867 view->cacheshared = shared;
868 if (view->cache != NULL) {
869 dns_db_detach(&view->cachedb);
870 dns_cache_detach(&view->cache);
871 }
872 dns_cache_attach(cache, &view->cache);
873 dns_cache_attachdb(cache, &view->cachedb);
874 INSIST(DNS_DB_VALID(view->cachedb));
875 }
876
877 bool
dns_view_iscacheshared(dns_view_t * view)878 dns_view_iscacheshared(dns_view_t *view) {
879 REQUIRE(DNS_VIEW_VALID(view));
880
881 return (view->cacheshared);
882 }
883
884 void
dns_view_sethints(dns_view_t * view,dns_db_t * hints)885 dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
886 REQUIRE(DNS_VIEW_VALID(view));
887 REQUIRE(!view->frozen);
888 REQUIRE(view->hints == NULL);
889 REQUIRE(dns_db_iszone(hints));
890
891 dns_db_attach(hints, &view->hints);
892 }
893
894 void
dns_view_settransports(dns_view_t * view,dns_transport_list_t * list)895 dns_view_settransports(dns_view_t *view, dns_transport_list_t *list) {
896 REQUIRE(DNS_VIEW_VALID(view));
897 REQUIRE(list != NULL);
898 if (view->transports != NULL) {
899 dns_transport_list_detach(&view->transports);
900 }
901 dns_transport_list_attach(list, &view->transports);
902 }
903
904 void
dns_view_setkeyring(dns_view_t * view,dns_tsig_keyring_t * ring)905 dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
906 REQUIRE(DNS_VIEW_VALID(view));
907 REQUIRE(ring != NULL);
908 if (view->statickeys != NULL) {
909 dns_tsigkeyring_detach(&view->statickeys);
910 }
911 dns_tsigkeyring_attach(ring, &view->statickeys);
912 }
913
914 void
dns_view_setdynamickeyring(dns_view_t * view,dns_tsig_keyring_t * ring)915 dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
916 REQUIRE(DNS_VIEW_VALID(view));
917 REQUIRE(ring != NULL);
918 if (view->dynamickeys != NULL) {
919 dns_tsigkeyring_detach(&view->dynamickeys);
920 }
921 dns_tsigkeyring_attach(ring, &view->dynamickeys);
922 }
923
924 void
dns_view_getdynamickeyring(dns_view_t * view,dns_tsig_keyring_t ** ringp)925 dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) {
926 REQUIRE(DNS_VIEW_VALID(view));
927 REQUIRE(ringp != NULL && *ringp == NULL);
928 if (view->dynamickeys != NULL) {
929 dns_tsigkeyring_attach(view->dynamickeys, ringp);
930 }
931 }
932
933 void
dns_view_restorekeyring(dns_view_t * view)934 dns_view_restorekeyring(dns_view_t *view) {
935 FILE *fp;
936 char keyfile[PATH_MAX];
937 isc_result_t result;
938
939 REQUIRE(DNS_VIEW_VALID(view));
940
941 if (view->dynamickeys != NULL) {
942 result = isc_file_sanitize(NULL, view->name, "tsigkeys",
943 keyfile, sizeof(keyfile));
944 if (result == ISC_R_SUCCESS) {
945 fp = fopen(keyfile, "r");
946 if (fp != NULL) {
947 dns_keyring_restore(view->dynamickeys, fp);
948 (void)fclose(fp);
949 }
950 }
951 }
952 }
953
954 void
dns_view_setdstport(dns_view_t * view,in_port_t dstport)955 dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
956 REQUIRE(DNS_VIEW_VALID(view));
957 view->dstport = dstport;
958 }
959
960 void
dns_view_freeze(dns_view_t * view)961 dns_view_freeze(dns_view_t *view) {
962 REQUIRE(DNS_VIEW_VALID(view));
963 REQUIRE(!view->frozen);
964
965 if (view->resolver != NULL) {
966 INSIST(view->cachedb != NULL);
967 dns_resolver_freeze(view->resolver);
968 }
969 view->frozen = true;
970 }
971
972 void
dns_view_thaw(dns_view_t * view)973 dns_view_thaw(dns_view_t *view) {
974 REQUIRE(DNS_VIEW_VALID(view));
975 REQUIRE(view->frozen);
976
977 view->frozen = false;
978 }
979
980 isc_result_t
dns_view_addzone(dns_view_t * view,dns_zone_t * zone)981 dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
982 isc_result_t result;
983
984 REQUIRE(DNS_VIEW_VALID(view));
985 REQUIRE(!view->frozen);
986 REQUIRE(view->zonetable != NULL);
987
988 result = dns_zt_mount(view->zonetable, zone);
989
990 return (result);
991 }
992
993 isc_result_t
dns_view_findzone(dns_view_t * view,const dns_name_t * name,dns_zone_t ** zonep)994 dns_view_findzone(dns_view_t *view, const dns_name_t *name,
995 dns_zone_t **zonep) {
996 isc_result_t result;
997
998 REQUIRE(DNS_VIEW_VALID(view));
999
1000 LOCK(&view->lock);
1001 if (view->zonetable != NULL) {
1002 result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
1003 if (result == DNS_R_PARTIALMATCH) {
1004 dns_zone_detach(zonep);
1005 result = ISC_R_NOTFOUND;
1006 }
1007 } else {
1008 result = ISC_R_NOTFOUND;
1009 }
1010 UNLOCK(&view->lock);
1011
1012 return (result);
1013 }
1014
1015 isc_result_t
dns_view_find(dns_view_t * view,const dns_name_t * name,dns_rdatatype_t type,isc_stdtime_t now,unsigned int options,bool use_hints,bool use_static_stub,dns_db_t ** dbp,dns_dbnode_t ** nodep,dns_name_t * foundname,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1016 dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
1017 isc_stdtime_t now, unsigned int options, bool use_hints,
1018 bool use_static_stub, dns_db_t **dbp, dns_dbnode_t **nodep,
1019 dns_name_t *foundname, dns_rdataset_t *rdataset,
1020 dns_rdataset_t *sigrdataset) {
1021 isc_result_t result;
1022 dns_db_t *db, *zdb;
1023 dns_dbnode_t *node, *znode;
1024 bool is_cache, is_staticstub_zone;
1025 dns_rdataset_t zrdataset, zsigrdataset;
1026 dns_zone_t *zone;
1027
1028 /*
1029 * Find an rdataset whose owner name is 'name', and whose type is
1030 * 'type'.
1031 */
1032
1033 REQUIRE(DNS_VIEW_VALID(view));
1034 REQUIRE(view->frozen);
1035 REQUIRE(type != dns_rdatatype_rrsig);
1036 REQUIRE(rdataset != NULL); /* XXXBEW - remove this */
1037 REQUIRE(nodep == NULL || *nodep == NULL);
1038
1039 /*
1040 * Initialize.
1041 */
1042 dns_rdataset_init(&zrdataset);
1043 dns_rdataset_init(&zsigrdataset);
1044 zdb = NULL;
1045 znode = NULL;
1046
1047 /*
1048 * Find a database to answer the query.
1049 */
1050 db = NULL;
1051 node = NULL;
1052 is_staticstub_zone = false;
1053 zone = NULL;
1054 LOCK(&view->lock);
1055 if (view->zonetable != NULL) {
1056 result = dns_zt_find(view->zonetable, name, DNS_ZTFIND_MIRROR,
1057 NULL, &zone);
1058 } else {
1059 result = ISC_R_NOTFOUND;
1060 }
1061 UNLOCK(&view->lock);
1062 if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
1063 !use_static_stub)
1064 {
1065 result = ISC_R_NOTFOUND;
1066 }
1067 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
1068 result = dns_zone_getdb(zone, &db);
1069 if (result != ISC_R_SUCCESS && view->cachedb != NULL) {
1070 dns_db_attach(view->cachedb, &db);
1071 } else if (result != ISC_R_SUCCESS) {
1072 goto cleanup;
1073 }
1074 if (dns_zone_gettype(zone) == dns_zone_staticstub &&
1075 dns_name_equal(name, dns_zone_getorigin(zone)))
1076 {
1077 is_staticstub_zone = true;
1078 }
1079 } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) {
1080 dns_db_attach(view->cachedb, &db);
1081 } else {
1082 goto cleanup;
1083 }
1084
1085 is_cache = dns_db_iscache(db);
1086
1087 db_find:
1088 /*
1089 * Now look for an answer in the database.
1090 */
1091 result = dns_db_find(db, name, NULL, type, options, now, &node,
1092 foundname, rdataset, sigrdataset);
1093
1094 if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
1095 if (dns_rdataset_isassociated(rdataset)) {
1096 dns_rdataset_disassociate(rdataset);
1097 }
1098 if (sigrdataset != NULL &&
1099 dns_rdataset_isassociated(sigrdataset)) {
1100 dns_rdataset_disassociate(sigrdataset);
1101 }
1102 if (node != NULL) {
1103 dns_db_detachnode(db, &node);
1104 }
1105 if (!is_cache) {
1106 dns_db_detach(&db);
1107 if (view->cachedb != NULL && !is_staticstub_zone) {
1108 /*
1109 * Either the answer is in the cache, or we
1110 * don't know it.
1111 * Note that if the result comes from a
1112 * static-stub zone we stop the search here
1113 * (see the function description in view.h).
1114 */
1115 is_cache = true;
1116 dns_db_attach(view->cachedb, &db);
1117 goto db_find;
1118 }
1119 } else {
1120 /*
1121 * We don't have the data in the cache. If we've got
1122 * glue from the zone, use it.
1123 */
1124 if (dns_rdataset_isassociated(&zrdataset)) {
1125 dns_rdataset_clone(&zrdataset, rdataset);
1126 if (sigrdataset != NULL &&
1127 dns_rdataset_isassociated(&zsigrdataset)) {
1128 dns_rdataset_clone(&zsigrdataset,
1129 sigrdataset);
1130 }
1131 result = DNS_R_GLUE;
1132 if (db != NULL) {
1133 dns_db_detach(&db);
1134 }
1135 dns_db_attach(zdb, &db);
1136 dns_db_attachnode(db, znode, &node);
1137 goto cleanup;
1138 }
1139 }
1140 /*
1141 * We don't know the answer.
1142 */
1143 result = ISC_R_NOTFOUND;
1144 } else if (result == DNS_R_GLUE) {
1145 if (view->cachedb != NULL && !is_staticstub_zone) {
1146 /*
1147 * We found an answer, but the cache may be better.
1148 * Remember what we've got and go look in the cache.
1149 */
1150 is_cache = true;
1151 dns_rdataset_clone(rdataset, &zrdataset);
1152 dns_rdataset_disassociate(rdataset);
1153 if (sigrdataset != NULL &&
1154 dns_rdataset_isassociated(sigrdataset)) {
1155 dns_rdataset_clone(sigrdataset, &zsigrdataset);
1156 dns_rdataset_disassociate(sigrdataset);
1157 }
1158 dns_db_attach(db, &zdb);
1159 dns_db_attachnode(zdb, node, &znode);
1160 dns_db_detachnode(db, &node);
1161 dns_db_detach(&db);
1162 dns_db_attach(view->cachedb, &db);
1163 goto db_find;
1164 }
1165 /*
1166 * Otherwise, the glue is the best answer.
1167 */
1168 result = ISC_R_SUCCESS;
1169 }
1170
1171 if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
1172 if (dns_rdataset_isassociated(rdataset)) {
1173 dns_rdataset_disassociate(rdataset);
1174 }
1175 if (sigrdataset != NULL &&
1176 dns_rdataset_isassociated(sigrdataset)) {
1177 dns_rdataset_disassociate(sigrdataset);
1178 }
1179 if (db != NULL) {
1180 if (node != NULL) {
1181 dns_db_detachnode(db, &node);
1182 }
1183 dns_db_detach(&db);
1184 }
1185 result = dns_db_find(view->hints, name, NULL, type, options,
1186 now, &node, foundname, rdataset,
1187 sigrdataset);
1188 if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
1189 /*
1190 * We just used a hint. Let the resolver know it
1191 * should consider priming.
1192 */
1193 dns_resolver_prime(view->resolver);
1194 dns_db_attach(view->hints, &db);
1195 result = DNS_R_HINT;
1196 } else if (result == DNS_R_NXRRSET) {
1197 dns_db_attach(view->hints, &db);
1198 result = DNS_R_HINTNXRRSET;
1199 } else if (result == DNS_R_NXDOMAIN) {
1200 result = ISC_R_NOTFOUND;
1201 }
1202
1203 /*
1204 * Cleanup if non-standard hints are used.
1205 */
1206 if (db == NULL && node != NULL) {
1207 dns_db_detachnode(view->hints, &node);
1208 }
1209 }
1210
1211 cleanup:
1212 if (dns_rdataset_isassociated(&zrdataset)) {
1213 dns_rdataset_disassociate(&zrdataset);
1214 if (dns_rdataset_isassociated(&zsigrdataset)) {
1215 dns_rdataset_disassociate(&zsigrdataset);
1216 }
1217 }
1218
1219 if (zdb != NULL) {
1220 if (znode != NULL) {
1221 dns_db_detachnode(zdb, &znode);
1222 }
1223 dns_db_detach(&zdb);
1224 }
1225
1226 if (db != NULL) {
1227 if (node != NULL) {
1228 if (nodep != NULL) {
1229 *nodep = node;
1230 } else {
1231 dns_db_detachnode(db, &node);
1232 }
1233 }
1234 if (dbp != NULL) {
1235 *dbp = db;
1236 } else {
1237 dns_db_detach(&db);
1238 }
1239 } else {
1240 INSIST(node == NULL);
1241 }
1242
1243 if (zone != NULL) {
1244 dns_zone_detach(&zone);
1245 }
1246
1247 return (result);
1248 }
1249
1250 isc_result_t
dns_view_simplefind(dns_view_t * view,const dns_name_t * name,dns_rdatatype_t type,isc_stdtime_t now,unsigned int options,bool use_hints,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1251 dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
1252 dns_rdatatype_t type, isc_stdtime_t now,
1253 unsigned int options, bool use_hints,
1254 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1255 isc_result_t result;
1256 dns_fixedname_t foundname;
1257
1258 dns_fixedname_init(&foundname);
1259 result = dns_view_find(view, name, type, now, options, use_hints, false,
1260 NULL, NULL, dns_fixedname_name(&foundname),
1261 rdataset, sigrdataset);
1262 if (result == DNS_R_NXDOMAIN) {
1263 /*
1264 * The rdataset and sigrdataset of the relevant NSEC record
1265 * may be returned, but the caller cannot use them because
1266 * foundname is not returned by this simplified API. We
1267 * disassociate them here to prevent any misuse by the caller.
1268 */
1269 if (dns_rdataset_isassociated(rdataset)) {
1270 dns_rdataset_disassociate(rdataset);
1271 }
1272 if (sigrdataset != NULL &&
1273 dns_rdataset_isassociated(sigrdataset)) {
1274 dns_rdataset_disassociate(sigrdataset);
1275 }
1276 } else if (result != ISC_R_SUCCESS && result != DNS_R_GLUE &&
1277 result != DNS_R_HINT && result != DNS_R_NCACHENXDOMAIN &&
1278 result != DNS_R_NCACHENXRRSET && result != DNS_R_NXRRSET &&
1279 result != DNS_R_HINTNXRRSET && result != ISC_R_NOTFOUND)
1280 {
1281 if (dns_rdataset_isassociated(rdataset)) {
1282 dns_rdataset_disassociate(rdataset);
1283 }
1284 if (sigrdataset != NULL &&
1285 dns_rdataset_isassociated(sigrdataset)) {
1286 dns_rdataset_disassociate(sigrdataset);
1287 }
1288 result = ISC_R_NOTFOUND;
1289 }
1290
1291 return (result);
1292 }
1293
1294 isc_result_t
dns_view_findzonecut(dns_view_t * view,const dns_name_t * name,dns_name_t * fname,dns_name_t * dcname,isc_stdtime_t now,unsigned int options,bool use_hints,bool use_cache,dns_rdataset_t * rdataset,dns_rdataset_t * sigrdataset)1295 dns_view_findzonecut(dns_view_t *view, const dns_name_t *name,
1296 dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
1297 unsigned int options, bool use_hints, bool use_cache,
1298 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1299 isc_result_t result;
1300 dns_db_t *db;
1301 bool is_cache, use_zone, try_hints;
1302 dns_zone_t *zone;
1303 dns_name_t *zfname;
1304 dns_rdataset_t zrdataset, zsigrdataset;
1305 dns_fixedname_t zfixedname;
1306 unsigned int ztoptions = DNS_ZTFIND_MIRROR;
1307
1308 REQUIRE(DNS_VIEW_VALID(view));
1309 REQUIRE(view->frozen);
1310
1311 db = NULL;
1312 use_zone = false;
1313 try_hints = false;
1314 zfname = NULL;
1315
1316 /*
1317 * Initialize.
1318 */
1319 dns_fixedname_init(&zfixedname);
1320 dns_rdataset_init(&zrdataset);
1321 dns_rdataset_init(&zsigrdataset);
1322
1323 /*
1324 * Find the right database.
1325 */
1326 zone = NULL;
1327 LOCK(&view->lock);
1328 if (view->zonetable != NULL) {
1329 if ((options & DNS_DBFIND_NOEXACT) != 0) {
1330 ztoptions |= DNS_ZTFIND_NOEXACT;
1331 }
1332 result = dns_zt_find(view->zonetable, name, ztoptions, NULL,
1333 &zone);
1334 } else {
1335 result = ISC_R_NOTFOUND;
1336 }
1337 UNLOCK(&view->lock);
1338 if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
1339 result = dns_zone_getdb(zone, &db);
1340 }
1341 if (result == ISC_R_NOTFOUND) {
1342 /*
1343 * We're not directly authoritative for this query name, nor
1344 * is it a subdomain of any zone for which we're
1345 * authoritative.
1346 */
1347 if (use_cache && view->cachedb != NULL) {
1348 /*
1349 * We have a cache; try it.
1350 */
1351 dns_db_attach(view->cachedb, &db);
1352 } else if (use_hints && view->hints != NULL) {
1353 /*
1354 * Maybe we have hints...
1355 */
1356 try_hints = true;
1357 goto finish;
1358 } else {
1359 result = DNS_R_NXDOMAIN;
1360 goto cleanup;
1361 }
1362 } else if (result != ISC_R_SUCCESS) {
1363 /*
1364 * Something is broken.
1365 */
1366 goto cleanup;
1367 }
1368 is_cache = dns_db_iscache(db);
1369
1370 db_find:
1371 /*
1372 * Look for the zonecut.
1373 */
1374 if (!is_cache) {
1375 result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
1376 now, NULL, fname, rdataset, sigrdataset);
1377 if (result == DNS_R_DELEGATION) {
1378 result = ISC_R_SUCCESS;
1379 } else if (result != ISC_R_SUCCESS) {
1380 goto cleanup;
1381 }
1382
1383 if (use_cache && view->cachedb != NULL && db != view->hints) {
1384 /*
1385 * We found an answer, but the cache may be better.
1386 */
1387 zfname = dns_fixedname_name(&zfixedname);
1388 dns_name_copy(fname, zfname);
1389 dns_rdataset_clone(rdataset, &zrdataset);
1390 dns_rdataset_disassociate(rdataset);
1391 if (sigrdataset != NULL &&
1392 dns_rdataset_isassociated(sigrdataset)) {
1393 dns_rdataset_clone(sigrdataset, &zsigrdataset);
1394 dns_rdataset_disassociate(sigrdataset);
1395 }
1396 dns_db_detach(&db);
1397 dns_db_attach(view->cachedb, &db);
1398 is_cache = true;
1399 goto db_find;
1400 }
1401 } else {
1402 result = dns_db_findzonecut(db, name, options, now, NULL, fname,
1403 dcname, rdataset, sigrdataset);
1404 if (result == ISC_R_SUCCESS) {
1405 if (zfname != NULL &&
1406 (!dns_name_issubdomain(fname, zfname) ||
1407 (dns_zone_gettype(zone) == dns_zone_staticstub &&
1408 dns_name_equal(fname, zfname))))
1409 {
1410 /*
1411 * We found a zonecut in the cache, but our
1412 * zone delegation is better.
1413 */
1414 use_zone = true;
1415 }
1416 } else if (result == ISC_R_NOTFOUND) {
1417 if (zfname != NULL) {
1418 /*
1419 * We didn't find anything in the cache, but we
1420 * have a zone delegation, so use it.
1421 */
1422 use_zone = true;
1423 result = ISC_R_SUCCESS;
1424 } else if (use_hints && view->hints != NULL) {
1425 /*
1426 * Maybe we have hints...
1427 */
1428 try_hints = true;
1429 result = ISC_R_SUCCESS;
1430 } else {
1431 result = DNS_R_NXDOMAIN;
1432 }
1433 } else {
1434 /*
1435 * Something bad happened.
1436 */
1437 goto cleanup;
1438 }
1439 }
1440
1441 finish:
1442 if (use_zone) {
1443 if (dns_rdataset_isassociated(rdataset)) {
1444 dns_rdataset_disassociate(rdataset);
1445 if (sigrdataset != NULL &&
1446 dns_rdataset_isassociated(sigrdataset)) {
1447 dns_rdataset_disassociate(sigrdataset);
1448 }
1449 }
1450 dns_name_copy(zfname, fname);
1451 if (dcname != NULL) {
1452 dns_name_copy(zfname, dcname);
1453 }
1454 dns_rdataset_clone(&zrdataset, rdataset);
1455 if (sigrdataset != NULL &&
1456 dns_rdataset_isassociated(&zrdataset)) {
1457 dns_rdataset_clone(&zsigrdataset, sigrdataset);
1458 }
1459 } else if (try_hints) {
1460 /*
1461 * We've found nothing so far, but we have hints.
1462 */
1463 result = dns_db_find(view->hints, dns_rootname, NULL,
1464 dns_rdatatype_ns, 0, now, NULL, fname,
1465 rdataset, NULL);
1466 if (result != ISC_R_SUCCESS) {
1467 /*
1468 * We can't even find the hints for the root
1469 * nameservers!
1470 */
1471 if (dns_rdataset_isassociated(rdataset)) {
1472 dns_rdataset_disassociate(rdataset);
1473 }
1474 result = ISC_R_NOTFOUND;
1475 } else if (dcname != NULL) {
1476 dns_name_copy(fname, dcname);
1477 }
1478 }
1479
1480 cleanup:
1481 if (dns_rdataset_isassociated(&zrdataset)) {
1482 dns_rdataset_disassociate(&zrdataset);
1483 if (dns_rdataset_isassociated(&zsigrdataset)) {
1484 dns_rdataset_disassociate(&zsigrdataset);
1485 }
1486 }
1487 if (db != NULL) {
1488 dns_db_detach(&db);
1489 }
1490 if (zone != NULL) {
1491 dns_zone_detach(&zone);
1492 }
1493
1494 return (result);
1495 }
1496
1497 isc_result_t
dns_viewlist_find(dns_viewlist_t * list,const char * name,dns_rdataclass_t rdclass,dns_view_t ** viewp)1498 dns_viewlist_find(dns_viewlist_t *list, const char *name,
1499 dns_rdataclass_t rdclass, dns_view_t **viewp) {
1500 dns_view_t *view;
1501
1502 REQUIRE(list != NULL);
1503
1504 for (view = ISC_LIST_HEAD(*list); view != NULL;
1505 view = ISC_LIST_NEXT(view, link))
1506 {
1507 if (strcmp(view->name, name) == 0 && view->rdclass == rdclass) {
1508 break;
1509 }
1510 }
1511 if (view == NULL) {
1512 return (ISC_R_NOTFOUND);
1513 }
1514
1515 dns_view_attach(view, viewp);
1516
1517 return (ISC_R_SUCCESS);
1518 }
1519
1520 isc_result_t
dns_viewlist_findzone(dns_viewlist_t * list,const dns_name_t * name,bool allclasses,dns_rdataclass_t rdclass,dns_zone_t ** zonep)1521 dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
1522 bool allclasses, dns_rdataclass_t rdclass,
1523 dns_zone_t **zonep) {
1524 dns_view_t *view;
1525 isc_result_t result;
1526 dns_zone_t *zone1 = NULL, *zone2 = NULL;
1527 dns_zone_t **zp = NULL;
1528
1529 REQUIRE(list != NULL);
1530 REQUIRE(zonep != NULL && *zonep == NULL);
1531
1532 for (view = ISC_LIST_HEAD(*list); view != NULL;
1533 view = ISC_LIST_NEXT(view, link))
1534 {
1535 if (!allclasses && view->rdclass != rdclass) {
1536 continue;
1537 }
1538
1539 /*
1540 * If the zone is defined in more than one view,
1541 * treat it as not found.
1542 */
1543 zp = (zone1 == NULL) ? &zone1 : &zone2;
1544 LOCK(&view->lock);
1545 if (view->zonetable != NULL) {
1546 result = dns_zt_find(view->zonetable, name, 0, NULL,
1547 zp);
1548 } else {
1549 result = ISC_R_NOTFOUND;
1550 }
1551 UNLOCK(&view->lock);
1552 INSIST(result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND ||
1553 result == DNS_R_PARTIALMATCH);
1554
1555 /* Treat a partial match as no match */
1556 if (result == DNS_R_PARTIALMATCH) {
1557 dns_zone_detach(zp);
1558 result = ISC_R_NOTFOUND;
1559 POST(result);
1560 }
1561
1562 if (zone2 != NULL) {
1563 dns_zone_detach(&zone1);
1564 dns_zone_detach(&zone2);
1565 return (ISC_R_MULTIPLE);
1566 }
1567 }
1568
1569 if (zone1 != NULL) {
1570 dns_zone_attach(zone1, zonep);
1571 dns_zone_detach(&zone1);
1572 return (ISC_R_SUCCESS);
1573 }
1574
1575 return (ISC_R_NOTFOUND);
1576 }
1577
1578 isc_result_t
dns_view_load(dns_view_t * view,bool stop,bool newonly)1579 dns_view_load(dns_view_t *view, bool stop, bool newonly) {
1580 REQUIRE(DNS_VIEW_VALID(view));
1581 REQUIRE(view->zonetable != NULL);
1582
1583 return (dns_zt_load(view->zonetable, stop, newonly));
1584 }
1585
1586 isc_result_t
dns_view_asyncload(dns_view_t * view,bool newonly,dns_zt_allloaded_t callback,void * arg)1587 dns_view_asyncload(dns_view_t *view, bool newonly, dns_zt_allloaded_t callback,
1588 void *arg) {
1589 REQUIRE(DNS_VIEW_VALID(view));
1590 REQUIRE(view->zonetable != NULL);
1591
1592 return (dns_zt_asyncload(view->zonetable, newonly, callback, arg));
1593 }
1594
1595 isc_result_t
dns_view_gettsig(dns_view_t * view,const dns_name_t * keyname,dns_tsigkey_t ** keyp)1596 dns_view_gettsig(dns_view_t *view, const dns_name_t *keyname,
1597 dns_tsigkey_t **keyp) {
1598 isc_result_t result;
1599 REQUIRE(keyp != NULL && *keyp == NULL);
1600
1601 result = dns_tsigkey_find(keyp, keyname, NULL, view->statickeys);
1602 if (result == ISC_R_NOTFOUND) {
1603 result = dns_tsigkey_find(keyp, keyname, NULL,
1604 view->dynamickeys);
1605 }
1606 return (result);
1607 }
1608
1609 isc_result_t
dns_view_gettransport(dns_view_t * view,const dns_transport_type_t type,const dns_name_t * name,dns_transport_t ** transportp)1610 dns_view_gettransport(dns_view_t *view, const dns_transport_type_t type,
1611 const dns_name_t *name, dns_transport_t **transportp) {
1612 REQUIRE(DNS_VIEW_VALID(view));
1613 REQUIRE(transportp != NULL && *transportp == NULL);
1614
1615 dns_transport_t *transport = dns_transport_find(type, name,
1616 view->transports);
1617 if (transport == NULL) {
1618 return (ISC_R_NOTFOUND);
1619 }
1620
1621 *transportp = transport;
1622 return (ISC_R_SUCCESS);
1623 }
1624
1625 isc_result_t
dns_view_getpeertsig(dns_view_t * view,const isc_netaddr_t * peeraddr,dns_tsigkey_t ** keyp)1626 dns_view_getpeertsig(dns_view_t *view, const isc_netaddr_t *peeraddr,
1627 dns_tsigkey_t **keyp) {
1628 isc_result_t result;
1629 dns_name_t *keyname = NULL;
1630 dns_peer_t *peer = NULL;
1631
1632 result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
1633 if (result != ISC_R_SUCCESS) {
1634 return (result);
1635 }
1636
1637 result = dns_peer_getkey(peer, &keyname);
1638 if (result != ISC_R_SUCCESS) {
1639 return (result);
1640 }
1641
1642 result = dns_view_gettsig(view, keyname, keyp);
1643 return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result);
1644 }
1645
1646 isc_result_t
dns_view_checksig(dns_view_t * view,isc_buffer_t * source,dns_message_t * msg)1647 dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
1648 REQUIRE(DNS_VIEW_VALID(view));
1649 REQUIRE(source != NULL);
1650
1651 return (dns_tsig_verify(source, msg, view->statickeys,
1652 view->dynamickeys));
1653 }
1654
1655 isc_result_t
dns_view_dumpdbtostream(dns_view_t * view,FILE * fp)1656 dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
1657 isc_result_t result;
1658
1659 REQUIRE(DNS_VIEW_VALID(view));
1660
1661 (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
1662 result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
1663 &dns_master_style_cache,
1664 dns_masterformat_text, NULL, fp);
1665 if (result != ISC_R_SUCCESS) {
1666 return (result);
1667 }
1668 dns_adb_dump(view->adb, fp);
1669 dns_resolver_printbadcache(view->resolver, fp);
1670 dns_badcache_print(view->failcache, "SERVFAIL cache", fp);
1671 return (ISC_R_SUCCESS);
1672 }
1673
1674 isc_result_t
dns_view_flushcache(dns_view_t * view,bool fixuponly)1675 dns_view_flushcache(dns_view_t *view, bool fixuponly) {
1676 isc_result_t result;
1677
1678 REQUIRE(DNS_VIEW_VALID(view));
1679
1680 if (view->cachedb == NULL) {
1681 return (ISC_R_SUCCESS);
1682 }
1683 if (!fixuponly) {
1684 result = dns_cache_flush(view->cache);
1685 if (result != ISC_R_SUCCESS) {
1686 return (result);
1687 }
1688 }
1689 dns_db_detach(&view->cachedb);
1690 dns_cache_attachdb(view->cache, &view->cachedb);
1691 if (view->resolver != NULL) {
1692 dns_resolver_flushbadcache(view->resolver, NULL);
1693 }
1694 if (view->failcache != NULL) {
1695 dns_badcache_flush(view->failcache);
1696 }
1697
1698 dns_adb_flush(view->adb);
1699 return (ISC_R_SUCCESS);
1700 }
1701
1702 isc_result_t
dns_view_flushname(dns_view_t * view,const dns_name_t * name)1703 dns_view_flushname(dns_view_t *view, const dns_name_t *name) {
1704 return (dns_view_flushnode(view, name, false));
1705 }
1706
1707 isc_result_t
dns_view_flushnode(dns_view_t * view,const dns_name_t * name,bool tree)1708 dns_view_flushnode(dns_view_t *view, const dns_name_t *name, bool tree) {
1709 isc_result_t result = ISC_R_SUCCESS;
1710
1711 REQUIRE(DNS_VIEW_VALID(view));
1712
1713 if (tree) {
1714 if (view->adb != NULL) {
1715 dns_adb_flushnames(view->adb, name);
1716 }
1717 if (view->resolver != NULL) {
1718 dns_resolver_flushbadnames(view->resolver, name);
1719 }
1720 if (view->failcache != NULL) {
1721 dns_badcache_flushtree(view->failcache, name);
1722 }
1723 } else {
1724 if (view->adb != NULL) {
1725 dns_adb_flushname(view->adb, name);
1726 }
1727 if (view->resolver != NULL) {
1728 dns_resolver_flushbadcache(view->resolver, name);
1729 }
1730 if (view->failcache != NULL) {
1731 dns_badcache_flushname(view->failcache, name);
1732 }
1733 }
1734
1735 if (view->cache != NULL) {
1736 result = dns_cache_flushnode(view->cache, name, tree);
1737 }
1738
1739 return (result);
1740 }
1741
1742 isc_result_t
dns_view_adddelegationonly(dns_view_t * view,const dns_name_t * name)1743 dns_view_adddelegationonly(dns_view_t *view, const dns_name_t *name) {
1744 dns_name_t *item;
1745 unsigned int hash;
1746
1747 REQUIRE(DNS_VIEW_VALID(view));
1748
1749 if (view->delonly == NULL) {
1750 view->delonly = isc_mem_get(view->mctx,
1751 sizeof(dns_namelist_t) *
1752 DNS_VIEW_DELONLYHASH);
1753 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) {
1754 ISC_LIST_INIT(view->delonly[hash]);
1755 }
1756 }
1757 hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
1758 item = ISC_LIST_HEAD(view->delonly[hash]);
1759 while (item != NULL && !dns_name_equal(item, name)) {
1760 item = ISC_LIST_NEXT(item, link);
1761 }
1762 if (item != NULL) {
1763 return (ISC_R_SUCCESS);
1764 }
1765 item = isc_mem_get(view->mctx, sizeof(*item));
1766 dns_name_init(item, NULL);
1767 dns_name_dup(name, view->mctx, item);
1768 ISC_LIST_APPEND(view->delonly[hash], item, link);
1769 return (ISC_R_SUCCESS);
1770 }
1771
1772 isc_result_t
dns_view_excludedelegationonly(dns_view_t * view,const dns_name_t * name)1773 dns_view_excludedelegationonly(dns_view_t *view, const dns_name_t *name) {
1774 dns_name_t *item;
1775 unsigned int hash;
1776
1777 REQUIRE(DNS_VIEW_VALID(view));
1778
1779 if (view->rootexclude == NULL) {
1780 view->rootexclude = isc_mem_get(view->mctx,
1781 sizeof(dns_namelist_t) *
1782 DNS_VIEW_DELONLYHASH);
1783 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++) {
1784 ISC_LIST_INIT(view->rootexclude[hash]);
1785 }
1786 }
1787 hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
1788 item = ISC_LIST_HEAD(view->rootexclude[hash]);
1789 while (item != NULL && !dns_name_equal(item, name)) {
1790 item = ISC_LIST_NEXT(item, link);
1791 }
1792 if (item != NULL) {
1793 return (ISC_R_SUCCESS);
1794 }
1795 item = isc_mem_get(view->mctx, sizeof(*item));
1796 dns_name_init(item, NULL);
1797 dns_name_dup(name, view->mctx, item);
1798 ISC_LIST_APPEND(view->rootexclude[hash], item, link);
1799 return (ISC_R_SUCCESS);
1800 }
1801
1802 bool
dns_view_isdelegationonly(dns_view_t * view,const dns_name_t * name)1803 dns_view_isdelegationonly(dns_view_t *view, const dns_name_t *name) {
1804 dns_name_t *item;
1805 unsigned int hash;
1806
1807 REQUIRE(DNS_VIEW_VALID(view));
1808
1809 if (!view->rootdelonly && view->delonly == NULL) {
1810 return (false);
1811 }
1812
1813 hash = dns_name_hash(name, false) % DNS_VIEW_DELONLYHASH;
1814 if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
1815 if (view->rootexclude == NULL) {
1816 return (true);
1817 }
1818 item = ISC_LIST_HEAD(view->rootexclude[hash]);
1819 while (item != NULL && !dns_name_equal(item, name)) {
1820 item = ISC_LIST_NEXT(item, link);
1821 }
1822 if (item == NULL) {
1823 return (true);
1824 }
1825 }
1826
1827 if (view->delonly == NULL) {
1828 return (false);
1829 }
1830
1831 item = ISC_LIST_HEAD(view->delonly[hash]);
1832 while (item != NULL && !dns_name_equal(item, name)) {
1833 item = ISC_LIST_NEXT(item, link);
1834 }
1835 if (item == NULL) {
1836 return (false);
1837 }
1838 return (true);
1839 }
1840
1841 void
dns_view_setrootdelonly(dns_view_t * view,bool value)1842 dns_view_setrootdelonly(dns_view_t *view, bool value) {
1843 REQUIRE(DNS_VIEW_VALID(view));
1844 view->rootdelonly = value;
1845 }
1846
1847 bool
dns_view_getrootdelonly(dns_view_t * view)1848 dns_view_getrootdelonly(dns_view_t *view) {
1849 REQUIRE(DNS_VIEW_VALID(view));
1850 return (view->rootdelonly);
1851 }
1852
1853 isc_result_t
dns_view_freezezones(dns_view_t * view,bool value)1854 dns_view_freezezones(dns_view_t *view, bool value) {
1855 REQUIRE(DNS_VIEW_VALID(view));
1856 REQUIRE(view->zonetable != NULL);
1857
1858 return (dns_zt_freezezones(view->zonetable, view, value));
1859 }
1860
1861 void
dns_view_setadbstats(dns_view_t * view,isc_stats_t * stats)1862 dns_view_setadbstats(dns_view_t *view, isc_stats_t *stats) {
1863 REQUIRE(DNS_VIEW_VALID(view));
1864 REQUIRE(!view->frozen);
1865 REQUIRE(view->adbstats == NULL);
1866
1867 isc_stats_attach(stats, &view->adbstats);
1868 }
1869
1870 void
dns_view_getadbstats(dns_view_t * view,isc_stats_t ** statsp)1871 dns_view_getadbstats(dns_view_t *view, isc_stats_t **statsp) {
1872 REQUIRE(DNS_VIEW_VALID(view));
1873 REQUIRE(statsp != NULL && *statsp == NULL);
1874
1875 if (view->adbstats != NULL) {
1876 isc_stats_attach(view->adbstats, statsp);
1877 }
1878 }
1879
1880 void
dns_view_setresstats(dns_view_t * view,isc_stats_t * stats)1881 dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
1882 REQUIRE(DNS_VIEW_VALID(view));
1883 REQUIRE(!view->frozen);
1884 REQUIRE(view->resstats == NULL);
1885
1886 isc_stats_attach(stats, &view->resstats);
1887 }
1888
1889 void
dns_view_getresstats(dns_view_t * view,isc_stats_t ** statsp)1890 dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) {
1891 REQUIRE(DNS_VIEW_VALID(view));
1892 REQUIRE(statsp != NULL && *statsp == NULL);
1893
1894 if (view->resstats != NULL) {
1895 isc_stats_attach(view->resstats, statsp);
1896 }
1897 }
1898
1899 void
dns_view_setresquerystats(dns_view_t * view,dns_stats_t * stats)1900 dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
1901 REQUIRE(DNS_VIEW_VALID(view));
1902 REQUIRE(!view->frozen);
1903 REQUIRE(view->resquerystats == NULL);
1904
1905 dns_stats_attach(stats, &view->resquerystats);
1906 }
1907
1908 void
dns_view_getresquerystats(dns_view_t * view,dns_stats_t ** statsp)1909 dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
1910 REQUIRE(DNS_VIEW_VALID(view));
1911 REQUIRE(statsp != NULL && *statsp == NULL);
1912
1913 if (view->resquerystats != NULL) {
1914 dns_stats_attach(view->resquerystats, statsp);
1915 }
1916 }
1917
1918 isc_result_t
dns_view_initntatable(dns_view_t * view,isc_taskmgr_t * taskmgr,isc_timermgr_t * timermgr)1919 dns_view_initntatable(dns_view_t *view, isc_taskmgr_t *taskmgr,
1920 isc_timermgr_t *timermgr) {
1921 REQUIRE(DNS_VIEW_VALID(view));
1922 if (view->ntatable_priv != NULL) {
1923 dns_ntatable_detach(&view->ntatable_priv);
1924 }
1925 return (dns_ntatable_create(view, taskmgr, timermgr,
1926 &view->ntatable_priv));
1927 }
1928
1929 isc_result_t
dns_view_getntatable(dns_view_t * view,dns_ntatable_t ** ntp)1930 dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) {
1931 REQUIRE(DNS_VIEW_VALID(view));
1932 REQUIRE(ntp != NULL && *ntp == NULL);
1933 if (view->ntatable_priv == NULL) {
1934 return (ISC_R_NOTFOUND);
1935 }
1936 dns_ntatable_attach(view->ntatable_priv, ntp);
1937 return (ISC_R_SUCCESS);
1938 }
1939
1940 isc_result_t
dns_view_initsecroots(dns_view_t * view,isc_mem_t * mctx)1941 dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
1942 REQUIRE(DNS_VIEW_VALID(view));
1943 if (view->secroots_priv != NULL) {
1944 dns_keytable_detach(&view->secroots_priv);
1945 }
1946 return (dns_keytable_create(mctx, &view->secroots_priv));
1947 }
1948
1949 isc_result_t
dns_view_getsecroots(dns_view_t * view,dns_keytable_t ** ktp)1950 dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
1951 REQUIRE(DNS_VIEW_VALID(view));
1952 REQUIRE(ktp != NULL && *ktp == NULL);
1953 if (view->secroots_priv == NULL) {
1954 return (ISC_R_NOTFOUND);
1955 }
1956 dns_keytable_attach(view->secroots_priv, ktp);
1957 return (ISC_R_SUCCESS);
1958 }
1959
1960 bool
dns_view_ntacovers(dns_view_t * view,isc_stdtime_t now,const dns_name_t * name,const dns_name_t * anchor)1961 dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, const dns_name_t *name,
1962 const dns_name_t *anchor) {
1963 REQUIRE(DNS_VIEW_VALID(view));
1964
1965 if (view->ntatable_priv == NULL) {
1966 return (false);
1967 }
1968
1969 return (dns_ntatable_covered(view->ntatable_priv, now, name, anchor));
1970 }
1971
1972 isc_result_t
dns_view_issecuredomain(dns_view_t * view,const dns_name_t * name,isc_stdtime_t now,bool checknta,bool * ntap,bool * secure_domain)1973 dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
1974 isc_stdtime_t now, bool checknta, bool *ntap,
1975 bool *secure_domain) {
1976 isc_result_t result;
1977 bool secure = false;
1978 dns_fixedname_t fn;
1979 dns_name_t *anchor;
1980
1981 REQUIRE(DNS_VIEW_VALID(view));
1982
1983 if (view->secroots_priv == NULL) {
1984 return (ISC_R_NOTFOUND);
1985 }
1986
1987 anchor = dns_fixedname_initname(&fn);
1988
1989 result = dns_keytable_issecuredomain(view->secroots_priv, name, anchor,
1990 &secure);
1991 if (result != ISC_R_SUCCESS) {
1992 return (result);
1993 }
1994
1995 if (ntap != NULL) {
1996 *ntap = false;
1997 }
1998 if (checknta && secure && view->ntatable_priv != NULL &&
1999 dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
2000 {
2001 if (ntap != NULL) {
2002 *ntap = true;
2003 }
2004 secure = false;
2005 }
2006
2007 *secure_domain = secure;
2008 return (ISC_R_SUCCESS);
2009 }
2010
2011 void
dns_view_untrust(dns_view_t * view,const dns_name_t * keyname,dns_rdata_dnskey_t * dnskey)2012 dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
2013 dns_rdata_dnskey_t *dnskey) {
2014 isc_result_t result;
2015 dns_keytable_t *sr = NULL;
2016
2017 REQUIRE(DNS_VIEW_VALID(view));
2018 REQUIRE(keyname != NULL);
2019 REQUIRE(dnskey != NULL);
2020
2021 /*
2022 * Clear the revoke bit, if set, so that the key will match what's
2023 * in secroots now.
2024 */
2025 dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
2026
2027 result = dns_view_getsecroots(view, &sr);
2028 if (result != ISC_R_SUCCESS) {
2029 return;
2030 }
2031
2032 result = dns_keytable_deletekey(sr, keyname, dnskey);
2033 if (result == ISC_R_SUCCESS) {
2034 /*
2035 * If key was found in secroots, then it was a
2036 * configured trust anchor, and we want to fail
2037 * secure. If there are no other configured keys,
2038 * then leave a null key so that we can't validate
2039 * anymore.
2040 */
2041 dns_keytable_marksecure(sr, keyname);
2042 }
2043
2044 dns_keytable_detach(&sr);
2045 }
2046
2047 /*
2048 * Create path to a directory and a filename constructed from viewname.
2049 * This is a front-end to isc_file_sanitize(), allowing backward
2050 * compatibility to older versions when a file couldn't be expected
2051 * to be in the specified directory but might be in the current working
2052 * directory instead.
2053 *
2054 * It first tests for the existence of a file <viewname>.<suffix> in
2055 * 'directory'. If the file does not exist, it checks again in the
2056 * current working directory. If it does not exist there either,
2057 * return the path inside the directory.
2058 *
2059 * Returns ISC_R_SUCCESS if a path to an existing file is found or
2060 * a new path is created; returns ISC_R_NOSPACE if the path won't
2061 * fit in 'buflen'.
2062 */
2063
2064 static isc_result_t
nz_legacy(const char * directory,const char * viewname,const char * suffix,char * buffer,size_t buflen)2065 nz_legacy(const char *directory, const char *viewname, const char *suffix,
2066 char *buffer, size_t buflen) {
2067 isc_result_t result;
2068 char newbuf[PATH_MAX];
2069
2070 result = isc_file_sanitize(directory, viewname, suffix, buffer, buflen);
2071 if (result != ISC_R_SUCCESS) {
2072 return (result);
2073 } else if (directory == NULL || isc_file_exists(buffer)) {
2074 return (ISC_R_SUCCESS);
2075 } else {
2076 /* Save buffer */
2077 strlcpy(newbuf, buffer, sizeof(newbuf));
2078 }
2079
2080 /*
2081 * It isn't in the specified directory; check CWD.
2082 */
2083 result = isc_file_sanitize(NULL, viewname, suffix, buffer, buflen);
2084 if (result != ISC_R_SUCCESS || isc_file_exists(buffer)) {
2085 return (result);
2086 }
2087
2088 /*
2089 * File does not exist in either 'directory' or CWD,
2090 * so use the path in 'directory'.
2091 */
2092 strlcpy(buffer, newbuf, buflen);
2093 return (ISC_R_SUCCESS);
2094 }
2095
2096 isc_result_t
dns_view_setnewzones(dns_view_t * view,bool allow,void * cfgctx,void (* cfg_destroy)(void **),uint64_t mapsize)2097 dns_view_setnewzones(dns_view_t *view, bool allow, void *cfgctx,
2098 void (*cfg_destroy)(void **), uint64_t mapsize) {
2099 isc_result_t result = ISC_R_SUCCESS;
2100 char buffer[1024];
2101 #ifdef HAVE_LMDB
2102 MDB_env *env = NULL;
2103 int status;
2104 #endif /* ifdef HAVE_LMDB */
2105
2106 #ifndef HAVE_LMDB
2107 UNUSED(mapsize);
2108 #endif /* ifndef HAVE_LMDB */
2109
2110 REQUIRE(DNS_VIEW_VALID(view));
2111 REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
2112
2113 if (view->new_zone_file != NULL) {
2114 isc_mem_free(view->mctx, view->new_zone_file);
2115 view->new_zone_file = NULL;
2116 }
2117
2118 #ifdef HAVE_LMDB
2119 if (view->new_zone_dbenv != NULL) {
2120 mdb_env_close((MDB_env *)view->new_zone_dbenv);
2121 view->new_zone_dbenv = NULL;
2122 }
2123
2124 if (view->new_zone_db != NULL) {
2125 isc_mem_free(view->mctx, view->new_zone_db);
2126 view->new_zone_db = NULL;
2127 }
2128 #endif /* HAVE_LMDB */
2129
2130 if (view->new_zone_config != NULL) {
2131 view->cfg_destroy(&view->new_zone_config);
2132 view->cfg_destroy = NULL;
2133 }
2134
2135 if (!allow) {
2136 return (ISC_R_SUCCESS);
2137 }
2138
2139 CHECK(nz_legacy(view->new_zone_dir, view->name, "nzf", buffer,
2140 sizeof(buffer)));
2141
2142 view->new_zone_file = isc_mem_strdup(view->mctx, buffer);
2143
2144 #ifdef HAVE_LMDB
2145 CHECK(nz_legacy(view->new_zone_dir, view->name, "nzd", buffer,
2146 sizeof(buffer)));
2147
2148 view->new_zone_db = isc_mem_strdup(view->mctx, buffer);
2149
2150 status = mdb_env_create(&env);
2151 if (status != MDB_SUCCESS) {
2152 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2153 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
2154 "mdb_env_create failed: %s",
2155 mdb_strerror(status));
2156 CHECK(ISC_R_FAILURE);
2157 }
2158
2159 if (mapsize != 0ULL) {
2160 status = mdb_env_set_mapsize(env, mapsize);
2161 if (status != MDB_SUCCESS) {
2162 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2163 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
2164 "mdb_env_set_mapsize failed: %s",
2165 mdb_strerror(status));
2166 CHECK(ISC_R_FAILURE);
2167 }
2168 view->new_zone_mapsize = mapsize;
2169 }
2170
2171 status = mdb_env_open(env, view->new_zone_db, DNS_LMDB_FLAGS, 0600);
2172 if (status != MDB_SUCCESS) {
2173 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
2174 ISC_LOGMODULE_OTHER, ISC_LOG_ERROR,
2175 "mdb_env_open of '%s' failed: %s",
2176 view->new_zone_db, mdb_strerror(status));
2177 CHECK(ISC_R_FAILURE);
2178 }
2179
2180 view->new_zone_dbenv = env;
2181 env = NULL;
2182 #endif /* HAVE_LMDB */
2183
2184 view->new_zone_config = cfgctx;
2185 view->cfg_destroy = cfg_destroy;
2186
2187 cleanup:
2188 if (result != ISC_R_SUCCESS) {
2189 if (view->new_zone_file != NULL) {
2190 isc_mem_free(view->mctx, view->new_zone_file);
2191 view->new_zone_file = NULL;
2192 }
2193
2194 #ifdef HAVE_LMDB
2195 if (view->new_zone_db != NULL) {
2196 isc_mem_free(view->mctx, view->new_zone_db);
2197 view->new_zone_db = NULL;
2198 }
2199 if (env != NULL) {
2200 mdb_env_close(env);
2201 }
2202 #endif /* HAVE_LMDB */
2203 view->new_zone_config = NULL;
2204 view->cfg_destroy = NULL;
2205 }
2206
2207 return (result);
2208 }
2209
2210 void
dns_view_setnewzonedir(dns_view_t * view,const char * dir)2211 dns_view_setnewzonedir(dns_view_t *view, const char *dir) {
2212 REQUIRE(DNS_VIEW_VALID(view));
2213
2214 if (view->new_zone_dir != NULL) {
2215 isc_mem_free(view->mctx, view->new_zone_dir);
2216 view->new_zone_dir = NULL;
2217 }
2218
2219 if (dir == NULL) {
2220 return;
2221 }
2222
2223 view->new_zone_dir = isc_mem_strdup(view->mctx, dir);
2224 }
2225
2226 const char *
dns_view_getnewzonedir(dns_view_t * view)2227 dns_view_getnewzonedir(dns_view_t *view) {
2228 REQUIRE(DNS_VIEW_VALID(view));
2229
2230 return (view->new_zone_dir);
2231 }
2232
2233 isc_result_t
dns_view_searchdlz(dns_view_t * view,const dns_name_t * name,unsigned int minlabels,dns_clientinfomethods_t * methods,dns_clientinfo_t * clientinfo,dns_db_t ** dbp)2234 dns_view_searchdlz(dns_view_t *view, const dns_name_t *name,
2235 unsigned int minlabels, dns_clientinfomethods_t *methods,
2236 dns_clientinfo_t *clientinfo, dns_db_t **dbp) {
2237 dns_fixedname_t fname;
2238 dns_name_t *zonename;
2239 unsigned int namelabels;
2240 unsigned int i;
2241 isc_result_t result;
2242 dns_dlzfindzone_t findzone;
2243 dns_dlzdb_t *dlzdb;
2244 dns_db_t *db, *best = NULL;
2245
2246 /*
2247 * Performs checks to make sure data is as we expect it to be.
2248 */
2249 REQUIRE(DNS_VIEW_VALID(view));
2250 REQUIRE(name != NULL);
2251 REQUIRE(dbp != NULL && *dbp == NULL);
2252
2253 /* setup a "fixed" dns name */
2254 zonename = dns_fixedname_initname(&fname);
2255
2256 /* count the number of labels in the name */
2257 namelabels = dns_name_countlabels(name);
2258
2259 for (dlzdb = ISC_LIST_HEAD(view->dlz_searched); dlzdb != NULL;
2260 dlzdb = ISC_LIST_NEXT(dlzdb, link))
2261 {
2262 REQUIRE(DNS_DLZ_VALID(dlzdb));
2263
2264 /*
2265 * loop through starting with the longest domain name and
2266 * trying shorter names portions of the name until we find a
2267 * match, have an error, or are below the 'minlabels'
2268 * threshold. minlabels is 0, if neither the standard
2269 * database nor any previous DLZ database had a zone name
2270 * match. Otherwise minlabels is the number of labels
2271 * in that name. We need to beat that for a "better"
2272 * match for this DLZ database to be authoritative.
2273 */
2274 for (i = namelabels; i > minlabels && i > 1; i--) {
2275 if (i == namelabels) {
2276 dns_name_copy(name, zonename);
2277 } else {
2278 dns_name_split(name, i, NULL, zonename);
2279 }
2280
2281 /* ask SDLZ driver if the zone is supported */
2282 db = NULL;
2283 findzone = dlzdb->implementation->methods->findzone;
2284 result = (*findzone)(dlzdb->implementation->driverarg,
2285 dlzdb->dbdata, dlzdb->mctx,
2286 view->rdclass, zonename, methods,
2287 clientinfo, &db);
2288
2289 if (result != ISC_R_NOTFOUND) {
2290 if (best != NULL) {
2291 dns_db_detach(&best);
2292 }
2293 if (result == ISC_R_SUCCESS) {
2294 INSIST(db != NULL);
2295 dns_db_attach(db, &best);
2296 dns_db_detach(&db);
2297 minlabels = i;
2298 } else {
2299 if (db != NULL) {
2300 dns_db_detach(&db);
2301 }
2302 break;
2303 }
2304 } else if (db != NULL) {
2305 dns_db_detach(&db);
2306 }
2307 }
2308 }
2309
2310 if (best != NULL) {
2311 dns_db_attach(best, dbp);
2312 dns_db_detach(&best);
2313 return (ISC_R_SUCCESS);
2314 }
2315
2316 return (ISC_R_NOTFOUND);
2317 }
2318
2319 uint32_t
dns_view_getfailttl(dns_view_t * view)2320 dns_view_getfailttl(dns_view_t *view) {
2321 REQUIRE(DNS_VIEW_VALID(view));
2322 return (view->fail_ttl);
2323 }
2324
2325 void
dns_view_setfailttl(dns_view_t * view,uint32_t fail_ttl)2326 dns_view_setfailttl(dns_view_t *view, uint32_t fail_ttl) {
2327 REQUIRE(DNS_VIEW_VALID(view));
2328 view->fail_ttl = fail_ttl;
2329 }
2330
2331 isc_result_t
dns_view_saventa(dns_view_t * view)2332 dns_view_saventa(dns_view_t *view) {
2333 isc_result_t result;
2334 bool removefile = false;
2335 dns_ntatable_t *ntatable = NULL;
2336 FILE *fp = NULL;
2337
2338 REQUIRE(DNS_VIEW_VALID(view));
2339
2340 if (view->nta_lifetime == 0) {
2341 return (ISC_R_SUCCESS);
2342 }
2343
2344 /* Open NTA save file for overwrite. */
2345 CHECK(isc_stdio_open(view->nta_file, "w", &fp));
2346
2347 result = dns_view_getntatable(view, &ntatable);
2348 if (result == ISC_R_NOTFOUND) {
2349 removefile = true;
2350 result = ISC_R_SUCCESS;
2351 goto cleanup;
2352 } else {
2353 CHECK(result);
2354 }
2355
2356 result = dns_ntatable_save(ntatable, fp);
2357 if (result == ISC_R_NOTFOUND) {
2358 removefile = true;
2359 result = ISC_R_SUCCESS;
2360 } else if (result == ISC_R_SUCCESS) {
2361 result = isc_stdio_close(fp);
2362 fp = NULL;
2363 }
2364
2365 cleanup:
2366 if (ntatable != NULL) {
2367 dns_ntatable_detach(&ntatable);
2368 }
2369
2370 if (fp != NULL) {
2371 (void)isc_stdio_close(fp);
2372 }
2373
2374 /* Don't leave half-baked NTA save files lying around. */
2375 if (result != ISC_R_SUCCESS || removefile) {
2376 (void)isc_file_remove(view->nta_file);
2377 }
2378
2379 return (result);
2380 }
2381
2382 #define TSTR(t) ((t).value.as_textregion.base)
2383 #define TLEN(t) ((t).value.as_textregion.length)
2384
2385 isc_result_t
dns_view_loadnta(dns_view_t * view)2386 dns_view_loadnta(dns_view_t *view) {
2387 isc_result_t result;
2388 dns_ntatable_t *ntatable = NULL;
2389 isc_lex_t *lex = NULL;
2390 isc_token_t token;
2391 isc_stdtime_t now;
2392
2393 REQUIRE(DNS_VIEW_VALID(view));
2394
2395 if (view->nta_lifetime == 0) {
2396 return (ISC_R_SUCCESS);
2397 }
2398
2399 CHECK(isc_lex_create(view->mctx, 1025, &lex));
2400 CHECK(isc_lex_openfile(lex, view->nta_file));
2401 CHECK(dns_view_getntatable(view, &ntatable));
2402 isc_stdtime_get(&now);
2403
2404 for (;;) {
2405 int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF);
2406 char *name, *type, *timestamp;
2407 size_t len;
2408 dns_fixedname_t fn;
2409 const dns_name_t *ntaname;
2410 isc_buffer_t b;
2411 isc_stdtime_t t;
2412 bool forced;
2413
2414 CHECK(isc_lex_gettoken(lex, options, &token));
2415 if (token.type == isc_tokentype_eof) {
2416 break;
2417 } else if (token.type != isc_tokentype_string) {
2418 CHECK(ISC_R_UNEXPECTEDTOKEN);
2419 }
2420 name = TSTR(token);
2421 len = TLEN(token);
2422
2423 if (strcmp(name, ".") == 0) {
2424 ntaname = dns_rootname;
2425 } else {
2426 dns_name_t *fname;
2427 fname = dns_fixedname_initname(&fn);
2428
2429 isc_buffer_init(&b, name, (unsigned int)len);
2430 isc_buffer_add(&b, (unsigned int)len);
2431 CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0,
2432 NULL));
2433 ntaname = fname;
2434 }
2435
2436 CHECK(isc_lex_gettoken(lex, options, &token));
2437 if (token.type != isc_tokentype_string) {
2438 CHECK(ISC_R_UNEXPECTEDTOKEN);
2439 }
2440 type = TSTR(token);
2441
2442 if (strcmp(type, "regular") == 0) {
2443 forced = false;
2444 } else if (strcmp(type, "forced") == 0) {
2445 forced = true;
2446 } else {
2447 CHECK(ISC_R_UNEXPECTEDTOKEN);
2448 }
2449
2450 CHECK(isc_lex_gettoken(lex, options, &token));
2451 if (token.type != isc_tokentype_string) {
2452 CHECK(ISC_R_UNEXPECTEDTOKEN);
2453 }
2454 timestamp = TSTR(token);
2455 CHECK(dns_time32_fromtext(timestamp, &t));
2456
2457 CHECK(isc_lex_gettoken(lex, options, &token));
2458 if (token.type != isc_tokentype_eol &&
2459 token.type != isc_tokentype_eof) {
2460 CHECK(ISC_R_UNEXPECTEDTOKEN);
2461 }
2462
2463 if (now <= t) {
2464 if (t > (now + 604800)) {
2465 t = now + 604800;
2466 }
2467
2468 (void)dns_ntatable_add(ntatable, ntaname, forced, 0, t);
2469 } else {
2470 char nb[DNS_NAME_FORMATSIZE];
2471 dns_name_format(ntaname, nb, sizeof(nb));
2472 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
2473 DNS_LOGMODULE_NTA, ISC_LOG_INFO,
2474 "ignoring expired NTA at %s", nb);
2475 }
2476 }
2477
2478 cleanup:
2479 if (ntatable != NULL) {
2480 dns_ntatable_detach(&ntatable);
2481 }
2482
2483 if (lex != NULL) {
2484 isc_lex_close(lex);
2485 isc_lex_destroy(&lex);
2486 }
2487
2488 return (result);
2489 }
2490
2491 void
dns_view_setviewcommit(dns_view_t * view)2492 dns_view_setviewcommit(dns_view_t *view) {
2493 dns_zone_t *redirect = NULL, *managed_keys = NULL;
2494
2495 REQUIRE(DNS_VIEW_VALID(view));
2496
2497 LOCK(&view->lock);
2498
2499 if (view->redirect != NULL) {
2500 dns_zone_attach(view->redirect, &redirect);
2501 }
2502 if (view->managed_keys != NULL) {
2503 dns_zone_attach(view->managed_keys, &managed_keys);
2504 }
2505
2506 UNLOCK(&view->lock);
2507
2508 if (view->zonetable != NULL) {
2509 dns_zt_setviewcommit(view->zonetable);
2510 }
2511 if (redirect != NULL) {
2512 dns_zone_setviewcommit(redirect);
2513 dns_zone_detach(&redirect);
2514 }
2515 if (managed_keys != NULL) {
2516 dns_zone_setviewcommit(managed_keys);
2517 dns_zone_detach(&managed_keys);
2518 }
2519 }
2520
2521 void
dns_view_setviewrevert(dns_view_t * view)2522 dns_view_setviewrevert(dns_view_t *view) {
2523 dns_zone_t *redirect = NULL, *managed_keys = NULL;
2524 dns_zt_t *zonetable;
2525
2526 REQUIRE(DNS_VIEW_VALID(view));
2527
2528 /*
2529 * dns_zt_setviewrevert() attempts to lock this view, so we must
2530 * release the lock.
2531 */
2532 LOCK(&view->lock);
2533 if (view->redirect != NULL) {
2534 dns_zone_attach(view->redirect, &redirect);
2535 }
2536 if (view->managed_keys != NULL) {
2537 dns_zone_attach(view->managed_keys, &managed_keys);
2538 }
2539 zonetable = view->zonetable;
2540 UNLOCK(&view->lock);
2541
2542 if (redirect != NULL) {
2543 dns_zone_setviewrevert(redirect);
2544 dns_zone_detach(&redirect);
2545 }
2546 if (managed_keys != NULL) {
2547 dns_zone_setviewrevert(managed_keys);
2548 dns_zone_detach(&managed_keys);
2549 }
2550 if (zonetable != NULL) {
2551 dns_zt_setviewrevert(zonetable);
2552 }
2553 }
2554
2555 bool
dns_view_staleanswerenabled(dns_view_t * view)2556 dns_view_staleanswerenabled(dns_view_t *view) {
2557 uint32_t stale_ttl = 0;
2558 bool result = false;
2559
2560 REQUIRE(DNS_VIEW_VALID(view));
2561
2562 if (dns_db_getservestalettl(view->cachedb, &stale_ttl) != ISC_R_SUCCESS)
2563 {
2564 return (false);
2565 }
2566 if (stale_ttl > 0) {
2567 if (view->staleanswersok == dns_stale_answer_yes) {
2568 result = true;
2569 } else if (view->staleanswersok == dns_stale_answer_conf) {
2570 result = view->staleanswersenable;
2571 }
2572 }
2573
2574 return (result);
2575 }
2576