Coverage Report

Created: 2026-08-31 07:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/view.c
Line
Count
Source
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
/*! \file */
15
16
#include <inttypes.h>
17
#include <limits.h>
18
#include <lmdb.h>
19
#include <stdbool.h>
20
21
#include <isc/async.h>
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/md.h>
28
#include <isc/result.h>
29
#include <isc/stats.h>
30
#include <isc/string.h>
31
#include <isc/urcu.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/forward.h>
44
#include <dns/keytable.h>
45
#include <dns/keyvalues.h>
46
#include <dns/master.h>
47
#include <dns/masterdump.h>
48
#include <dns/nametree.h>
49
#include <dns/nta.h>
50
#include <dns/order.h>
51
#include <dns/peer.h>
52
#include <dns/rdata.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/unreachcache.h>
63
#include <dns/view.h>
64
#include <dns/zone.h>
65
#include <dns/zoneproperties.h>
66
#include <dns/zt.h>
67
68
#define DNS_VIEW_DELONLYHASH 111
69
70
/*%
71
 * Default maximum number of chained queries before we give up
72
 * to prevent CNAME loops.
73
 */
74
2
#define DEFAULT_MAX_RESTARTS 11
75
76
/*%
77
 * Default EDNS0 buffer size
78
 */
79
2
#define DEFAULT_EDNS_BUFSIZE 1232
80
81
/* Exponental backoff from 10 seconds to 640 seconds */
82
4
#define UNREACH_HOLD_TIME_INITIAL_SEC ((uint16_t)10)
83
2
#define UNREACH_HOLD_TIME_MAX_SEC     (UNREACH_HOLD_TIME_INITIAL_SEC << 6)
84
2
#define UNREACH_BACKOFF_ELIGIBLE_SEC  ((uint16_t)120)
85
86
void
87
dns_view_create(isc_mem_t *mctx, dns_dispatchmgr_t *dispatchmgr,
88
    dns_rdataclass_t rdclass, const char *name,
89
2
    dns_view_t **viewp) {
90
2
  dns_view_t *view = NULL;
91
2
  isc_result_t result;
92
2
  char buffer[1024];
93
94
2
  REQUIRE(name != NULL);
95
2
  REQUIRE(viewp != NULL && *viewp == NULL);
96
97
2
  switch (rdclass) {
98
2
  case dns_rdataclass_in:
99
2
    break;
100
0
  case dns_rdataclass_chaos:
101
0
    if (strcmp(name, "_bind") == 0) {
102
      /* allowed */
103
0
      break;
104
0
    }
105
0
    FALLTHROUGH;
106
0
  default:
107
0
    UNREACHABLE();
108
2
  }
109
110
2
  result = isc_file_sanitize(NULL, name, "nta", buffer, sizeof(buffer));
111
2
  RUNTIME_CHECK(result == ISC_R_SUCCESS);
112
113
2
  view = isc_mem_get(mctx, sizeof(*view));
114
2
  *view = (dns_view_t){
115
2
    .rdclass = rdclass,
116
2
    .name = isc_mem_strdup(mctx, name),
117
2
    .nta_file = isc_mem_strdup(mctx, buffer),
118
2
    .recursion = true,
119
2
    .enablevalidation = true,
120
2
    .minimalresponses = dns_minimal_no,
121
2
    .transfer_format = dns_one_answer,
122
2
    .msgcompression = true,
123
2
    .provideixfr = true,
124
2
    .maxcachettl = 7 * 24 * 3600,
125
2
    .maxncachettl = 3 * 3600,
126
2
    .dstport = 53,
127
2
    .staleanswerttl = 1,
128
2
    .staleanswersok = dns_stale_answer_conf,
129
2
    .sendcookie = true,
130
2
    .synthfromdnssec = true,
131
2
    .trust_anchor_telemetry = true,
132
2
    .root_key_sentinel = true,
133
2
    .udpsize = DEFAULT_EDNS_BUFSIZE,
134
2
    .max_restarts = DEFAULT_MAX_RESTARTS,
135
2
  };
136
137
2
  isc_refcount_init(&view->references, 1);
138
2
  isc_refcount_init(&view->weakrefs, 1);
139
140
2
  dns_fixedname_init(&view->redirectfixed);
141
142
2
  ISC_LIST_INIT(view->dlz_searched);
143
2
  ISC_LIST_INIT(view->dlz_unsearched);
144
2
  ISC_LIST_INIT(view->dns64);
145
146
2
  ISC_LINK_INIT(view, link);
147
148
2
  isc_mem_attach(mctx, &view->mctx);
149
150
2
  if (dispatchmgr != NULL) {
151
0
    dns_dispatchmgr_attach(dispatchmgr, &view->dispatchmgr);
152
0
  }
153
154
2
  isc_mutex_init(&view->lock);
155
156
2
  dns_zt_create(mctx, view, &view->zonetable);
157
158
2
  dns_fwdtable_create(mctx, view, &view->fwdtable);
159
160
2
  dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
161
162
2
  view->failcache = dns_badcache_new(view->mctx);
163
164
2
  view->unreachcache = dns_unreachcache_new(
165
2
    view->mctx, UNREACH_HOLD_TIME_INITIAL_SEC,
166
2
    UNREACH_HOLD_TIME_MAX_SEC, UNREACH_BACKOFF_ELIGIBLE_SEC);
167
168
2
  isc_mutex_init(&view->newzone.lock);
169
170
2
  dns_order_create(view->mctx, &view->order);
171
172
2
  dns_peerlist_new(view->mctx, &view->peers);
173
174
2
  dns_aclenv_create(view->mctx, &view->aclenv);
175
176
2
  dns_nametree_create(view->mctx, DNS_NAMETREE_COUNT, "sfd", &view->sfd);
177
178
2
  view->magic = DNS_VIEW_MAGIC;
179
2
  *viewp = view;
180
2
}
181
182
static void
183
0
destroy(dns_view_t *view) {
184
0
  dns_dns64_t *dns64 = NULL;
185
186
0
  REQUIRE(!ISC_LINK_LINKED(view, link));
187
188
0
  isc_refcount_destroy(&view->references);
189
0
  isc_refcount_destroy(&view->weakrefs);
190
191
0
  if (view->deleg != NULL) {
192
0
    dns_delegdb_detach(&view->deleg);
193
0
  }
194
195
0
  if (view->order != NULL) {
196
0
    dns_order_detach(&view->order);
197
0
  }
198
0
  if (view->peers != NULL) {
199
0
    dns_peerlist_detach(&view->peers);
200
0
  }
201
202
0
  if (view->dynamickeys != NULL) {
203
0
    isc_result_t result;
204
0
    char template[PATH_MAX];
205
0
    char keyfile[PATH_MAX];
206
0
    FILE *fp = NULL;
207
208
0
    result = isc_file_mktemplate(NULL, template, sizeof(template));
209
0
    if (result == ISC_R_SUCCESS) {
210
0
      (void)isc_file_openuniqueprivate(template, &fp);
211
0
    }
212
0
    if (fp != NULL) {
213
0
      result = dns_tsigkeyring_dump(view->dynamickeys, fp);
214
0
      if (result == ISC_R_SUCCESS) {
215
0
        if (fclose(fp) == 0) {
216
0
          result = isc_file_sanitize(
217
0
            NULL, view->name, "tsigkeys",
218
0
            keyfile, sizeof(keyfile));
219
0
          if (result == ISC_R_SUCCESS) {
220
0
            result = isc_file_rename(
221
0
              template, keyfile);
222
0
          }
223
0
        }
224
0
        if (result != ISC_R_SUCCESS) {
225
0
          (void)remove(template);
226
0
        }
227
0
      } else {
228
0
        (void)fclose(fp);
229
0
        (void)remove(template);
230
0
      }
231
0
    }
232
0
    dns_tsigkeyring_detach(&view->dynamickeys);
233
0
  }
234
0
  if (view->transports != NULL) {
235
0
    dns_transport_list_detach(&view->transports);
236
0
  }
237
0
  if (view->statickeys != NULL) {
238
0
    dns_tsigkeyring_detach(&view->statickeys);
239
0
  }
240
241
  /* These must have been detached in dns_view_detach() */
242
0
  INSIST(view->adb == NULL);
243
0
  INSIST(view->resolver == NULL);
244
0
  INSIST(view->requestmgr == NULL);
245
246
0
  dns_rrl_view_destroy(view);
247
0
  if (view->rpzs != NULL) {
248
0
    dns_rpz_zones_shutdown(view->rpzs);
249
0
    dns_rpz_zones_detach(&view->rpzs);
250
0
  }
251
0
  if (view->catzs != NULL) {
252
0
    dns_catz_zones_shutdown(view->catzs);
253
0
    dns_catz_zones_detach(&view->catzs);
254
0
  }
255
0
  ISC_LIST_FOREACH(view->dlz_searched, dlzdb, link) {
256
0
    ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link);
257
0
    dns_dlzdestroy(&dlzdb);
258
0
  }
259
0
  ISC_LIST_FOREACH(view->dlz_unsearched, dlzdb, link) {
260
0
    ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link);
261
0
    dns_dlzdestroy(&dlzdb);
262
0
  }
263
0
  if (view->cachedb != NULL) {
264
0
    dns_db_detach(&view->cachedb);
265
0
  }
266
0
  if (view->cache != NULL) {
267
0
    dns_cache_detach(&view->cache);
268
0
  }
269
0
  if (view->nocasecompress != NULL) {
270
0
    dns_acl_detach(&view->nocasecompress);
271
0
  }
272
0
  if (view->matchclients != NULL) {
273
0
    dns_acl_detach(&view->matchclients);
274
0
  }
275
0
  if (view->matchdestinations != NULL) {
276
0
    dns_acl_detach(&view->matchdestinations);
277
0
  }
278
0
  if (view->cacheacl != NULL) {
279
0
    dns_acl_detach(&view->cacheacl);
280
0
  }
281
0
  if (view->cacheonacl != NULL) {
282
0
    dns_acl_detach(&view->cacheonacl);
283
0
  }
284
0
  if (view->queryacl != NULL) {
285
0
    dns_acl_detach(&view->queryacl);
286
0
  }
287
0
  if (view->queryonacl != NULL) {
288
0
    dns_acl_detach(&view->queryonacl);
289
0
  }
290
0
  if (view->recursionacl != NULL) {
291
0
    dns_acl_detach(&view->recursionacl);
292
0
  }
293
0
  if (view->recursiononacl != NULL) {
294
0
    dns_acl_detach(&view->recursiononacl);
295
0
  }
296
0
  if (view->transferacl != NULL) {
297
0
    dns_acl_detach(&view->transferacl);
298
0
  }
299
0
  if (view->notifyacl != NULL) {
300
0
    dns_acl_detach(&view->notifyacl);
301
0
  }
302
0
  if (view->updateacl != NULL) {
303
0
    dns_acl_detach(&view->updateacl);
304
0
  }
305
0
  if (view->upfwdacl != NULL) {
306
0
    dns_acl_detach(&view->upfwdacl);
307
0
  }
308
0
  if (view->denyansweracl != NULL) {
309
0
    dns_acl_detach(&view->denyansweracl);
310
0
  }
311
0
  if (view->pad_acl != NULL) {
312
0
    dns_acl_detach(&view->pad_acl);
313
0
  }
314
0
  if (view->proxyacl != NULL) {
315
0
    dns_acl_detach(&view->proxyacl);
316
0
  }
317
0
  if (view->proxyonacl != NULL) {
318
0
    dns_acl_detach(&view->proxyonacl);
319
0
  }
320
0
  if (view->answeracl_exclude != NULL) {
321
0
    dns_nametree_detach(&view->answeracl_exclude);
322
0
  }
323
0
  if (view->denyanswernames != NULL) {
324
0
    dns_nametree_detach(&view->denyanswernames);
325
0
  }
326
0
  if (view->answernames_exclude != NULL) {
327
0
    dns_nametree_detach(&view->answernames_exclude);
328
0
  }
329
0
  if (view->sfd != NULL) {
330
0
    dns_nametree_detach(&view->sfd);
331
0
  }
332
0
  if (view->secroots_priv != NULL) {
333
0
    dns_keytable_detach(&view->secroots_priv);
334
0
  }
335
0
  if (view->ntatable_priv != NULL) {
336
0
    dns_ntatable_detach(&view->ntatable_priv);
337
0
  }
338
0
  for (dns64 = ISC_LIST_HEAD(view->dns64); dns64 != NULL;
339
0
       dns64 = ISC_LIST_HEAD(view->dns64))
340
0
  {
341
0
    dns_dns64_destroy(&view->dns64, &dns64);
342
0
  }
343
0
  if (view->managed_keys != NULL) {
344
0
    dns_zone_detach(&view->managed_keys);
345
0
  }
346
0
  if (view->redirect != NULL) {
347
0
    dns_zone_detach(&view->redirect);
348
0
  }
349
#ifdef HAVE_DNSTAP
350
  if (view->dtenv != NULL) {
351
    dns_dtenv_detach(&view->dtenv);
352
  }
353
#endif /* HAVE_DNSTAP */
354
0
  if (view->newzone.cleanup != NULL) {
355
0
    view->newzone.cleanup(view);
356
0
  }
357
0
  if (view->newzone.dbenv != NULL) {
358
0
    mdb_env_close((MDB_env *)view->newzone.dbenv);
359
0
    view->newzone.dbenv = NULL;
360
0
  }
361
0
  if (view->newzone.db != NULL) {
362
0
    isc_mem_free(view->mctx, view->newzone.db);
363
0
  }
364
0
  dns_fwdtable_destroy(&view->fwdtable);
365
0
  dns_aclenv_detach(&view->aclenv);
366
0
  if (view->failcache != NULL) {
367
0
    dns_badcache_destroy(&view->failcache);
368
0
  }
369
0
  if (view->unreachcache != NULL) {
370
0
    dns_unreachcache_destroy(&view->unreachcache);
371
0
  }
372
0
  isc_mutex_destroy(&view->newzone.lock);
373
0
  isc_mutex_destroy(&view->lock);
374
0
  isc_refcount_destroy(&view->references);
375
0
  isc_refcount_destroy(&view->weakrefs);
376
0
  isc_mem_free(view->mctx, view->nta_file);
377
0
  isc_mem_free(view->mctx, view->name);
378
0
  if (view->hooktable != NULL && view->hooktable_free != NULL) {
379
0
    view->hooktable_free(view->mctx, &view->hooktable);
380
0
  }
381
0
  if (view->plugins != NULL && view->plugins_free != NULL) {
382
0
    view->plugins_free(view->mctx, &view->plugins);
383
0
  }
384
0
  isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
385
0
}
386
387
void
388
0
dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
389
0
  REQUIRE(DNS_VIEW_VALID(source));
390
0
  REQUIRE(targetp != NULL && *targetp == NULL);
391
392
0
  isc_refcount_increment(&source->references);
393
394
0
  *targetp = source;
395
0
}
396
397
static void
398
0
shutdown_view(dns_view_t *view) {
399
0
  dns_zone_t *mkzone = NULL, *rdzone = NULL;
400
0
  dns_zt_t *zonetable = NULL;
401
0
  dns_resolver_t *resolver = NULL;
402
0
  dns_adb_t *adb = NULL;
403
0
  dns_requestmgr_t *requestmgr = NULL;
404
0
  dns_dispatchmgr_t *dispatchmgr = NULL;
405
406
0
  isc_refcount_destroy(&view->references);
407
408
  /* Shutdown the attached objects first */
409
0
  if (view->resolver != NULL) {
410
0
    dns_resolver_shutdown(view->resolver);
411
0
  }
412
413
0
  rcu_read_lock();
414
0
  adb = rcu_dereference(view->adb);
415
0
  if (adb != NULL) {
416
0
    dns_adb_shutdown(adb);
417
0
  }
418
0
  rcu_read_unlock();
419
420
0
  if (view->requestmgr != NULL) {
421
0
    dns_requestmgr_shutdown(view->requestmgr);
422
0
  }
423
424
  /* Swap the pointers under the lock */
425
0
  LOCK(&view->lock);
426
427
0
  if (view->resolver != NULL) {
428
0
    resolver = view->resolver;
429
0
    view->resolver = NULL;
430
0
  }
431
432
0
  rcu_read_lock();
433
0
  zonetable = rcu_xchg_pointer(&view->zonetable, NULL);
434
0
  if (zonetable != NULL) {
435
0
    if (view->flush) {
436
0
      dns_zt_flush(zonetable);
437
0
    }
438
0
  }
439
0
  adb = rcu_xchg_pointer(&view->adb, NULL);
440
0
  dispatchmgr = rcu_xchg_pointer(&view->dispatchmgr, NULL);
441
0
  rcu_read_unlock();
442
443
0
  if (view->requestmgr != NULL) {
444
0
    requestmgr = view->requestmgr;
445
0
    view->requestmgr = NULL;
446
0
  }
447
0
  if (view->managed_keys != NULL) {
448
0
    mkzone = view->managed_keys;
449
0
    view->managed_keys = NULL;
450
0
    if (view->flush) {
451
0
      dns_zone_flush(mkzone);
452
0
    }
453
0
  }
454
0
  if (view->redirect != NULL) {
455
0
    rdzone = view->redirect;
456
0
    view->redirect = NULL;
457
0
    if (view->flush) {
458
0
      dns_zone_flush(rdzone);
459
0
    }
460
0
  }
461
0
  if (view->catzs != NULL) {
462
0
    dns_catz_zones_shutdown(view->catzs);
463
0
    dns_catz_zones_detach(&view->catzs);
464
0
  }
465
0
  if (view->ntatable_priv != NULL) {
466
0
    dns_ntatable_shutdown(view->ntatable_priv);
467
0
  }
468
0
  UNLOCK(&view->lock);
469
470
  /* Detach outside view lock */
471
0
  if (resolver != NULL) {
472
0
    dns_resolver_detach(&resolver);
473
0
  }
474
475
0
  synchronize_rcu();
476
0
  if (dispatchmgr != NULL) {
477
0
    dns_dispatchmgr_detach(&dispatchmgr);
478
0
  }
479
0
  if (adb != NULL) {
480
0
    dns_adb_detach(&adb);
481
0
  }
482
0
  if (zonetable != NULL) {
483
0
    dns_zt_detach(&zonetable);
484
0
  }
485
0
  if (requestmgr != NULL) {
486
0
    dns_requestmgr_detach(&requestmgr);
487
0
  }
488
0
  if (mkzone != NULL) {
489
0
    dns_zone_detach(&mkzone);
490
0
  }
491
0
  if (rdzone != NULL) {
492
0
    dns_zone_detach(&rdzone);
493
0
  }
494
495
0
  dns_view_weakdetach(&view);
496
0
}
497
498
void
499
0
dns_view_detach(dns_view_t **viewp) {
500
0
  dns_view_t *view = NULL;
501
502
0
  REQUIRE(viewp != NULL && DNS_VIEW_VALID(*viewp));
503
504
0
  view = *viewp;
505
0
  *viewp = NULL;
506
507
0
  if (isc_refcount_decrement(&view->references) == 1) {
508
0
    shutdown_view(view);
509
0
  }
510
0
}
511
512
void
513
2
dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
514
2
  REQUIRE(DNS_VIEW_VALID(source));
515
2
  REQUIRE(targetp != NULL && *targetp == NULL);
516
517
2
  isc_refcount_increment(&source->weakrefs);
518
519
2
  *targetp = source;
520
2
}
521
522
void
523
0
dns_view_weakdetach(dns_view_t **viewp) {
524
0
  dns_view_t *view = NULL;
525
526
0
  REQUIRE(viewp != NULL);
527
528
0
  view = *viewp;
529
0
  *viewp = NULL;
530
531
0
  REQUIRE(DNS_VIEW_VALID(view));
532
533
0
  if (isc_refcount_decrement(&view->weakrefs) == 1) {
534
0
    destroy(view);
535
0
  }
536
0
}
537
538
isc_result_t
539
dns_view_createresolver(dns_view_t *view, unsigned int options,
540
      isc_tlsctx_cache_t *tlsctx_cache,
541
      dns_dispatch_t *dispatchv4,
542
0
      dns_dispatch_t *dispatchv6) {
543
0
  isc_result_t result;
544
0
  isc_mem_t *mctx = NULL;
545
546
0
  REQUIRE(DNS_VIEW_VALID(view));
547
0
  REQUIRE(!view->frozen);
548
0
  REQUIRE(view->resolver == NULL);
549
0
  REQUIRE(view->dispatchmgr != NULL);
550
551
0
  RETERR(dns_resolver_create(view, options, tlsctx_cache, dispatchv4,
552
0
           dispatchv6, &view->resolver));
553
554
0
  isc_mem_create("ADB", &mctx);
555
0
  dns_adb_create(mctx, view, &view->adb);
556
0
  isc_mem_detach(&mctx);
557
558
0
  result = dns_requestmgr_create(view->mctx, view->dispatchmgr,
559
0
               dispatchv4, dispatchv6,
560
0
               &view->requestmgr);
561
0
  if (result != ISC_R_SUCCESS) {
562
0
    goto cleanup_adb;
563
0
  }
564
565
0
  return ISC_R_SUCCESS;
566
567
0
cleanup_adb:
568
0
  dns_adb_shutdown(view->adb);
569
0
  dns_adb_detach(&view->adb);
570
571
0
  dns_resolver_shutdown(view->resolver);
572
0
  dns_resolver_detach(&view->resolver);
573
574
0
  return result;
575
0
}
576
577
void
578
0
dns_view_setcache(dns_view_t *view, dns_cache_t *cache, bool shared) {
579
0
  REQUIRE(DNS_VIEW_VALID(view));
580
0
  REQUIRE(!view->frozen);
581
582
0
  view->cacheshared = shared;
583
0
  if (view->cache != NULL) {
584
0
    dns_db_detach(&view->cachedb);
585
0
    dns_cache_detach(&view->cache);
586
0
  }
587
0
  dns_cache_attach(cache, &view->cache);
588
0
  dns_cache_attachdb(cache, &view->cachedb);
589
0
  INSIST(DNS_DB_VALID(view->cachedb));
590
591
0
  dns_cache_setmaxrrperset(view->cache, view->maxrrperset);
592
0
  dns_cache_setmaxtypepername(view->cache, view->maxtypepername);
593
0
}
594
595
bool
596
0
dns_view_iscacheshared(dns_view_t *view) {
597
0
  REQUIRE(DNS_VIEW_VALID(view));
598
599
0
  return view->cacheshared;
600
0
}
601
602
void
603
0
dns_view_settransports(dns_view_t *view, dns_transport_list_t *list) {
604
0
  REQUIRE(DNS_VIEW_VALID(view));
605
0
  REQUIRE(list != NULL);
606
0
  if (view->transports != NULL) {
607
0
    dns_transport_list_detach(&view->transports);
608
0
  }
609
0
  dns_transport_list_attach(list, &view->transports);
610
0
}
611
612
void
613
1.16k
dns_view_setkeyring(dns_view_t *view, dns_tsigkeyring_t *ring) {
614
1.16k
  REQUIRE(DNS_VIEW_VALID(view));
615
1.16k
  REQUIRE(ring != NULL);
616
1.16k
  if (view->statickeys != NULL) {
617
1.16k
    dns_tsigkeyring_detach(&view->statickeys);
618
1.16k
  }
619
1.16k
  dns_tsigkeyring_attach(ring, &view->statickeys);
620
1.16k
}
621
622
void
623
0
dns_view_setdynamickeyring(dns_view_t *view, dns_tsigkeyring_t *ring) {
624
0
  REQUIRE(DNS_VIEW_VALID(view));
625
0
  REQUIRE(ring != NULL);
626
0
  if (view->dynamickeys != NULL) {
627
0
    dns_tsigkeyring_detach(&view->dynamickeys);
628
0
  }
629
0
  dns_tsigkeyring_attach(ring, &view->dynamickeys);
630
0
}
631
632
void
633
0
dns_view_getdynamickeyring(dns_view_t *view, dns_tsigkeyring_t **ringp) {
634
0
  REQUIRE(DNS_VIEW_VALID(view));
635
0
  REQUIRE(ringp != NULL && *ringp == NULL);
636
0
  if (view->dynamickeys != NULL) {
637
0
    dns_tsigkeyring_attach(view->dynamickeys, ringp);
638
0
  }
639
0
}
640
641
void
642
0
dns_view_restorekeyring(dns_view_t *view) {
643
0
  FILE *fp;
644
0
  char keyfile[PATH_MAX];
645
0
  isc_result_t result;
646
647
0
  REQUIRE(DNS_VIEW_VALID(view));
648
649
0
  if (view->dynamickeys != NULL) {
650
0
    result = isc_file_sanitize(NULL, view->name, "tsigkeys",
651
0
             keyfile, sizeof(keyfile));
652
0
    if (result == ISC_R_SUCCESS) {
653
0
      fp = fopen(keyfile, "r");
654
0
      if (fp != NULL) {
655
0
        dns_tsigkeyring_restore(view->dynamickeys, fp);
656
0
        (void)fclose(fp);
657
0
      }
658
0
    }
659
0
  }
660
0
}
661
662
void
663
0
dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
664
0
  REQUIRE(DNS_VIEW_VALID(view));
665
0
  view->dstport = dstport;
666
0
}
667
668
void
669
2
dns_view_freeze(dns_view_t *view) {
670
2
  REQUIRE(DNS_VIEW_VALID(view));
671
2
  REQUIRE(!view->frozen);
672
673
2
  if (view->resolver != NULL) {
674
0
    INSIST(view->cachedb != NULL);
675
0
    dns_resolver_freeze(view->resolver);
676
0
  }
677
2
  view->frozen = true;
678
2
}
679
680
void
681
0
dns_view_thaw(dns_view_t *view) {
682
0
  REQUIRE(DNS_VIEW_VALID(view));
683
0
  REQUIRE(view->frozen);
684
685
0
  view->frozen = false;
686
0
}
687
688
isc_result_t
689
2
dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
690
2
  isc_result_t result;
691
2
  dns_zt_t *zonetable = NULL;
692
693
2
  REQUIRE(DNS_VIEW_VALID(view));
694
2
  REQUIRE(!view->frozen);
695
696
2
  rcu_read_lock();
697
2
  zonetable = rcu_dereference(view->zonetable);
698
2
  if (zonetable != NULL) {
699
2
    result = dns_zt_mount(zonetable, zone);
700
2
  } else {
701
0
    result = ISC_R_SHUTTINGDOWN;
702
0
  }
703
2
  rcu_read_unlock();
704
705
2
  return result;
706
2
}
707
708
isc_result_t
709
0
dns_view_delzone(dns_view_t *view, dns_zone_t *zone) {
710
0
  isc_result_t result;
711
0
  dns_zt_t *zonetable = NULL;
712
713
0
  REQUIRE(DNS_VIEW_VALID(view));
714
715
0
  dns_zone_prepare_shutdown(zone);
716
717
0
  rcu_read_lock();
718
0
  zonetable = rcu_dereference(view->zonetable);
719
0
  if (zonetable != NULL) {
720
0
    result = dns_zt_unmount(zonetable, zone);
721
0
  } else {
722
0
    result = ISC_R_SUCCESS;
723
0
  }
724
0
  rcu_read_unlock();
725
726
0
  return result;
727
0
}
728
729
isc_result_t
730
dns_view_findzone(dns_view_t *view, const dns_name_t *name,
731
0
      unsigned int options, dns_zone_t **zonep) {
732
0
  isc_result_t result;
733
0
  dns_zt_t *zonetable = NULL;
734
735
0
  REQUIRE(DNS_VIEW_VALID(view));
736
737
0
  rcu_read_lock();
738
0
  zonetable = rcu_dereference(view->zonetable);
739
0
  if (zonetable != NULL) {
740
0
    result = dns_zt_find(zonetable, name, options, zonep);
741
0
  } else {
742
0
    result = ISC_R_NOTFOUND;
743
0
  }
744
0
  rcu_read_unlock();
745
746
0
  return result;
747
0
}
748
749
isc_result_t
750
dns_view_find(dns_view_t *view, const dns_name_t *name, dns_rdatatype_t type,
751
        isc_stdtime_t now, unsigned int options, bool use_static_stub,
752
        dns_db_t **dbp, dns_name_t *foundname, dns_rdataset_t *rdataset,
753
421
        dns_rdataset_t *sigrdataset) {
754
421
  isc_result_t result;
755
421
  dns_db_t *db = NULL, *zdb = NULL;
756
421
  bool is_cache, is_staticstub_zone;
757
421
  dns_rdataset_t zrdataset, zsigrdataset;
758
421
  dns_zone_t *zone = NULL;
759
421
  dns_zt_t *zonetable = NULL;
760
761
  /*
762
   * Find an rdataset whose owner name is 'name', and whose type is
763
   * 'type'.
764
   */
765
766
421
  REQUIRE(DNS_VIEW_VALID(view));
767
421
  REQUIRE(view->frozen);
768
421
  REQUIRE(type != dns_rdatatype_rrsig);
769
421
  REQUIRE(rdataset != NULL); /* XXXBEW - remove this */
770
771
  /*
772
   * Initialize.
773
   */
774
421
  dns_rdataset_init(&zrdataset);
775
421
  dns_rdataset_init(&zsigrdataset);
776
777
  /*
778
   * Find a database to answer the query.
779
   */
780
421
  is_staticstub_zone = false;
781
421
  rcu_read_lock();
782
421
  zonetable = rcu_dereference(view->zonetable);
783
421
  if (zonetable != NULL) {
784
421
    result = dns_zt_find(zonetable, name, DNS_ZTFIND_MIRROR, &zone);
785
421
  } else {
786
0
    result = ISC_R_SHUTTINGDOWN;
787
0
  }
788
421
  rcu_read_unlock();
789
421
  if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
790
0
      !use_static_stub)
791
0
  {
792
0
    result = ISC_R_NOTFOUND;
793
0
  }
794
421
  if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
795
210
    result = dns_zone_getdb(zone, &db);
796
210
    if (result != ISC_R_SUCCESS && view->cachedb != NULL) {
797
0
      dns_db_attach(view->cachedb, &db);
798
210
    } else if (result != ISC_R_SUCCESS) {
799
0
      goto cleanup;
800
0
    }
801
210
    if (dns_zone_gettype(zone) == dns_zone_staticstub &&
802
0
        dns_name_equal(name, dns_zone_getorigin(zone)))
803
0
    {
804
0
      is_staticstub_zone = true;
805
0
    }
806
211
  } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL) {
807
0
    dns_db_attach(view->cachedb, &db);
808
211
  } else {
809
211
    goto cleanup;
810
211
  }
811
812
210
  is_cache = dns_db_iscache(db);
813
814
210
db_find:
815
  /*
816
   * Now look for an answer in the database.
817
   */
818
210
  result = dns_db_find(db, name, NULL, type, options, now, foundname,
819
210
           rdataset, sigrdataset);
820
821
210
  if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
822
0
    dns_rdataset_cleanup(rdataset);
823
0
    dns_rdataset_cleanup(sigrdataset);
824
0
    if (!is_cache) {
825
0
      dns_db_detach(&db);
826
0
      if (view->cachedb != NULL && !is_staticstub_zone) {
827
        /*
828
         * Either the answer is in the cache, or we
829
         * don't know it.
830
         * Note that if the result comes from a
831
         * static-stub zone we stop the search here
832
         * (see the function description in view.h).
833
         */
834
0
        is_cache = true;
835
0
        dns_db_attach(view->cachedb, &db);
836
0
        goto db_find;
837
0
      }
838
0
    } else {
839
      /*
840
       * We don't have the data in the cache.  If we've got
841
       * glue from the zone, use it.
842
       */
843
0
      if (dns_rdataset_isassociated(&zrdataset)) {
844
0
        dns_rdataset_clone(&zrdataset, rdataset);
845
0
        if (sigrdataset != NULL &&
846
0
            dns_rdataset_isassociated(&zsigrdataset))
847
0
        {
848
0
          dns_rdataset_clone(&zsigrdataset,
849
0
                 sigrdataset);
850
0
        }
851
0
        result = DNS_R_GLUE;
852
0
        if (db != NULL) {
853
0
          dns_db_detach(&db);
854
0
        }
855
0
        dns_db_attach(zdb, &db);
856
0
        goto cleanup;
857
0
      }
858
0
    }
859
    /*
860
     * We don't know the answer.
861
     */
862
0
    result = ISC_R_NOTFOUND;
863
210
  } else if (result == DNS_R_GLUE) {
864
    /*
865
     * Glue is the answer wanted.
866
     */
867
0
    result = ISC_R_SUCCESS;
868
0
  }
869
870
421
cleanup:
871
421
  dns_rdataset_cleanup(&zrdataset);
872
421
  dns_rdataset_cleanup(&zsigrdataset);
873
874
421
  if (zdb != NULL) {
875
0
    dns_db_detach(&zdb);
876
0
  }
877
878
421
  if (db != NULL) {
879
210
    if (dbp != NULL) {
880
0
      *dbp = db;
881
210
    } else {
882
210
      dns_db_detach(&db);
883
210
    }
884
210
  }
885
886
421
  if (zone != NULL) {
887
210
    dns_zone_detach(&zone);
888
210
  }
889
890
421
  return result;
891
210
}
892
893
isc_result_t
894
dns_view_simplefind(dns_view_t *view, const dns_name_t *name,
895
        dns_rdatatype_t type, isc_stdtime_t now,
896
        unsigned int options, dns_rdataset_t *rdataset,
897
421
        dns_rdataset_t *sigrdataset) {
898
421
  isc_result_t result;
899
421
  dns_fixedname_t foundname;
900
901
421
  dns_fixedname_init(&foundname);
902
421
  result = dns_view_find(view, name, type, now, options, false, NULL,
903
421
             dns_fixedname_name(&foundname), rdataset,
904
421
             sigrdataset);
905
421
  if (result == DNS_R_NXDOMAIN) {
906
    /*
907
     * The rdataset and sigrdataset of the relevant NSEC record
908
     * may be returned, but the caller cannot use them because
909
     * foundname is not returned by this simplified API.  We
910
     * disassociate them here to prevent any misuse by the caller.
911
     */
912
79
    dns_rdataset_cleanup(rdataset);
913
79
    dns_rdataset_cleanup(sigrdataset);
914
342
  } else if (result != ISC_R_SUCCESS && result != DNS_R_GLUE &&
915
211
       result != DNS_R_HINT && result != DNS_R_NCACHENXDOMAIN &&
916
211
       result != DNS_R_NCACHENXRRSET && result != DNS_R_NXRRSET &&
917
211
       result != DNS_R_HINTNXRRSET && result != ISC_R_NOTFOUND)
918
0
  {
919
0
    dns_rdataset_cleanup(rdataset);
920
0
    dns_rdataset_cleanup(sigrdataset);
921
0
    result = ISC_R_NOTFOUND;
922
0
  }
923
924
421
  return result;
925
421
}
926
927
static isc_result_t
928
bestzonecut_zone(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
929
     dns_name_t *dcname, isc_stdtime_t now, unsigned int options,
930
0
     dns_rdataset_t *rdataset) {
931
0
  dns_db_t *db = NULL;
932
0
  dns_zone_t *zone = NULL;
933
0
  unsigned int ztoptions = DNS_ZTFIND_MIRROR;
934
0
  isc_result_t result;
935
936
0
  if ((options & DNS_DBFIND_ABOVE) != 0) {
937
0
    ztoptions |= DNS_ZTFIND_NOEXACT;
938
0
  }
939
940
0
  result = dns_view_findzone(view, name, ztoptions, &zone);
941
0
  if (result != ISC_R_SUCCESS && result != DNS_R_PARTIALMATCH) {
942
    /*
943
     * There is no matching zone configured locally.
944
     */
945
0
    CLEANUP(DNS_R_NXDOMAIN);
946
0
  }
947
948
0
  result = dns_zone_getdb(zone, &db);
949
0
  if (result != ISC_R_SUCCESS) {
950
    /*
951
     * A matching zone is configured locally, but its database
952
     * isn't loaded. We return ISC_R_NOTFOUND to differentiate
953
     * from the case where the zone doesn't exist, so the
954
     * caller won't try the cache or hints.
955
     */
956
0
    CLEANUP(ISC_R_NOTFOUND);
957
0
  }
958
959
0
  result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options, now,
960
0
           fname, rdataset, NULL);
961
0
  if (result != DNS_R_DELEGATION && result != ISC_R_SUCCESS) {
962
    /*
963
     * The zone exists, but there is no delegation. Here again
964
     * we use ISC_R_NOTFOUND, to differentiate from the case where
965
     * the zone doesn't exist.
966
     */
967
0
    CLEANUP(ISC_R_NOTFOUND);
968
0
  }
969
970
  /*
971
   * Tag static stub NS RRset so that when we look for
972
   * addresses we use the configured server addresses.
973
   */
974
0
  if (dns_zone_gettype(zone) == dns_zone_staticstub) {
975
0
    rdataset->attributes.staticstub = true;
976
0
  }
977
978
0
  if (dcname != NULL) {
979
0
    dns_name_copy(fname, dcname);
980
0
  }
981
982
0
  result = ISC_R_SUCCESS;
983
984
0
cleanup:
985
0
  if (result != ISC_R_SUCCESS) {
986
0
    dns_rdataset_cleanup(rdataset);
987
0
  }
988
989
0
  if (db != NULL) {
990
0
    dns_db_detach(&db);
991
0
  }
992
993
0
  if (zone != NULL) {
994
0
    dns_zone_detach(&zone);
995
0
  }
996
997
0
  return result;
998
0
}
999
1000
static isc_result_t
1001
bestzonecut_delegdb(dns_view_t *view, const dns_name_t *name, dns_name_t *fname,
1002
        dns_name_t *dcname, isc_stdtime_t now, unsigned int options,
1003
0
        dns_delegset_t **delegsetp) {
1004
0
  isc_result_t result = DNS_R_NXDOMAIN;
1005
1006
0
  if (view->deleg != NULL) {
1007
0
    result = dns_delegdb_lookup(view->deleg, name, now, options,
1008
0
              fname, dcname, delegsetp);
1009
0
  }
1010
1011
0
  if (result == DNS_R_EXPIRED) {
1012
0
    dns_resolver_t *res = NULL;
1013
1014
0
    INSIST((options & DNS_DBFIND_HINTOK) != 0);
1015
0
    if (dns_view_getresolver(view, &res) == ISC_R_SUCCESS) {
1016
0
      dns_resolver_prime(res);
1017
0
      dns_resolver_detach(&res);
1018
0
    }
1019
1020
0
    result = ISC_R_SUCCESS;
1021
0
  }
1022
1023
  /*
1024
   * Cache miss returns ISC_R_NOTFOUND, but to not confuse it
1025
   * with a zone found without delegation matching `name` (nor partial),
1026
   * keep DNS_R_NXDOMAIN, so the hints can be checked.
1027
   */
1028
0
  if (result != ISC_R_SUCCESS) {
1029
0
    result = DNS_R_NXDOMAIN;
1030
0
  }
1031
0
  return result;
1032
0
}
1033
1034
static void
1035
bestzonecut_zoneorcache(dns_view_t *view, const dns_name_t *name,
1036
      dns_name_t *fname, dns_name_t *dcname,
1037
      isc_stdtime_t now, unsigned int options,
1038
0
      dns_rdataset_t *rdataset, dns_delegset_t **delegsetp) {
1039
0
  isc_result_t result;
1040
0
  dns_fixedname_t f, dc;
1041
0
  dns_name_t *cfname = dns_fixedname_initname(&f);
1042
0
  dns_name_t *cdcname = dns_fixedname_initname(&dc);
1043
1044
0
  result = bestzonecut_delegdb(view, name, cfname, cdcname, now, options,
1045
0
             delegsetp);
1046
0
  if (result != ISC_R_SUCCESS) {
1047
0
    return;
1048
0
  }
1049
1050
0
  bool cacheclosest = dns_name_issubdomain(cfname, fname);
1051
0
  bool staticstub = rdataset->attributes.staticstub &&
1052
0
        dns_name_equal(fname, cfname);
1053
1054
0
  if (cacheclosest && !staticstub) {
1055
0
    dns_rdataset_cleanup(rdataset);
1056
1057
0
    dns_name_copy(cfname, fname);
1058
0
    if (dcname != NULL) {
1059
0
      dns_name_copy(cdcname, dcname);
1060
0
    }
1061
0
  } else {
1062
0
    dns_delegset_detach(delegsetp);
1063
0
  }
1064
0
}
1065
1066
isc_result_t
1067
dns_view_bestzonecut(dns_view_t *view, const dns_name_t *name,
1068
         dns_name_t *fname, dns_name_t *dcname, isc_stdtime_t now,
1069
         unsigned int options, bool usehints, bool usecache,
1070
0
         dns_delegset_t **delegsetp) {
1071
0
  isc_result_t result;
1072
0
  dns_rdataset_t rdataset = DNS_RDATASET_INIT;
1073
1074
0
  REQUIRE(DNS_VIEW_VALID(view));
1075
0
  REQUIRE(view->frozen);
1076
0
  REQUIRE(delegsetp == NULL || *delegsetp == NULL);
1077
1078
0
  if (usehints) {
1079
0
    options |= DNS_DBFIND_HINTOK;
1080
0
  }
1081
1082
0
  result = bestzonecut_zone(view, name, fname, dcname, now, options,
1083
0
          &rdataset);
1084
1085
0
  if (result == DNS_R_NXDOMAIN && usecache) {
1086
    /*
1087
     * No local zone matches `name`, but the cache might have a
1088
     * delegation.
1089
     */
1090
0
    result = bestzonecut_delegdb(view, name, fname, dcname, now,
1091
0
               options, delegsetp);
1092
0
  } else if (result == ISC_R_SUCCESS && usecache) {
1093
    /*
1094
     * A zone with a (possibly partial) delegation match but the
1095
     * cache can have a more precise delegation.
1096
     *
1097
     * No need to look for hints in this case: we have something
1098
     * better in a local zone.
1099
     */
1100
0
    options &= ~DNS_DBFIND_HINTOK;
1101
0
    bestzonecut_zoneorcache(view, name, fname, dcname, now, options,
1102
0
          &rdataset, delegsetp);
1103
0
  }
1104
1105
0
  if (result != ISC_R_SUCCESS) {
1106
0
    result = DNS_R_NXDOMAIN;
1107
0
  } else {
1108
    /*
1109
     * The rdataset came either from a local zone or a hint. Either
1110
     * way, we only considering the NS rdataset here, so if there
1111
     * are glues, they'll be ignored. This is okay: the delegation
1112
     * type will be DNS_DELEGSET_NS_NAMES, so ADB will do a NS name
1113
     * lookup but immediately find the results locally (because this
1114
     * came from a local zone or hint). So the resolution will be
1115
     * the same, and this avoid adding extra code here to extract
1116
     * A/AAAA rdataset if any.
1117
     */
1118
0
    dns_delegset_fromnsrdataset(view->mctx, &rdataset, delegsetp);
1119
0
  }
1120
1121
0
  dns_rdataset_cleanup(&rdataset);
1122
0
  return result;
1123
0
}
1124
1125
isc_result_t
1126
dns_viewlist_find(dns_viewlist_t *list, const char *name,
1127
0
      dns_rdataclass_t rdclass, dns_view_t **viewp) {
1128
0
  REQUIRE(list != NULL);
1129
1130
0
  ISC_LIST_FOREACH(*list, view, link) {
1131
0
    if (strcmp(view->name, name) == 0 && view->rdclass == rdclass) {
1132
0
      dns_view_attach(view, viewp);
1133
0
      return ISC_R_SUCCESS;
1134
0
    }
1135
0
  }
1136
1137
0
  return ISC_R_NOTFOUND;
1138
0
}
1139
1140
isc_result_t
1141
dns_viewlist_findzone(dns_viewlist_t *list, const dns_name_t *name,
1142
          bool allclasses, dns_rdataclass_t rdclass,
1143
0
          dns_zone_t **zonep) {
1144
0
  isc_result_t result;
1145
0
  dns_zone_t *zone1 = NULL, *zone2 = NULL;
1146
1147
0
  REQUIRE(list != NULL);
1148
0
  REQUIRE(zonep != NULL && *zonep == NULL);
1149
1150
0
  ISC_LIST_FOREACH(*list, view, link) {
1151
0
    dns_zt_t *zonetable = NULL;
1152
0
    if (!allclasses && view->rdclass != rdclass) {
1153
0
      continue;
1154
0
    }
1155
0
    rcu_read_lock();
1156
0
    zonetable = rcu_dereference(view->zonetable);
1157
0
    if (zonetable != NULL) {
1158
0
      result = dns_zt_find(zonetable, name, DNS_ZTFIND_EXACT,
1159
0
               (zone1 == NULL) ? &zone1 : &zone2);
1160
0
    } else {
1161
0
      result = ISC_R_NOTFOUND;
1162
0
    }
1163
0
    rcu_read_unlock();
1164
0
    INSIST(result == ISC_R_SUCCESS || result == ISC_R_NOTFOUND);
1165
0
    if (zone2 != NULL) {
1166
0
      dns_zone_detach(&zone1);
1167
0
      dns_zone_detach(&zone2);
1168
0
      return ISC_R_MULTIPLE;
1169
0
    }
1170
0
  }
1171
1172
0
  if (zone1 != NULL) {
1173
0
    dns_zone_attach(zone1, zonep);
1174
0
    dns_zone_detach(&zone1);
1175
0
    return ISC_R_SUCCESS;
1176
0
  }
1177
1178
0
  return ISC_R_NOTFOUND;
1179
0
}
1180
1181
isc_result_t
1182
dns_view_asyncload(dns_view_t *view, bool newonly, dns_zt_callback_t *callback,
1183
0
       void *arg) {
1184
0
  isc_result_t result;
1185
0
  dns_zt_t *zonetable = NULL;
1186
1187
0
  REQUIRE(DNS_VIEW_VALID(view));
1188
1189
0
  rcu_read_lock();
1190
0
  zonetable = rcu_dereference(view->zonetable);
1191
0
  if (zonetable != NULL) {
1192
0
    result = dns_zt_asyncload(zonetable, newonly, callback, arg);
1193
0
  } else {
1194
0
    result = ISC_R_SUCCESS;
1195
0
  }
1196
0
  rcu_read_unlock();
1197
0
  return result;
1198
0
}
1199
1200
isc_result_t
1201
dns_view_gettsig(dns_view_t *view, const dns_name_t *keyname,
1202
0
     dns_tsigkey_t **keyp) {
1203
0
  isc_result_t result;
1204
0
  REQUIRE(keyp != NULL && *keyp == NULL);
1205
1206
0
  result = dns_tsigkey_find(keyp, keyname, NULL, view->statickeys);
1207
0
  if (result == ISC_R_NOTFOUND) {
1208
0
    result = dns_tsigkey_find(keyp, keyname, NULL,
1209
0
            view->dynamickeys);
1210
0
  }
1211
0
  return result;
1212
0
}
1213
1214
isc_result_t
1215
dns_view_gettransport(dns_view_t *view, const dns_transport_type_t type,
1216
0
          const dns_name_t *name, dns_transport_t **transportp) {
1217
0
  REQUIRE(DNS_VIEW_VALID(view));
1218
0
  REQUIRE(transportp != NULL && *transportp == NULL);
1219
1220
0
  dns_transport_t *transport = dns_transport_find(type, name,
1221
0
              view->transports);
1222
0
  if (transport == NULL) {
1223
0
    return ISC_R_NOTFOUND;
1224
0
  }
1225
1226
0
  *transportp = transport;
1227
0
  return ISC_R_SUCCESS;
1228
0
}
1229
1230
isc_result_t
1231
dns_view_getpeertsig(dns_view_t *view, const isc_netaddr_t *peeraddr,
1232
0
         dns_tsigkey_t **keyp) {
1233
0
  isc_result_t result;
1234
0
  dns_name_t *keyname = NULL;
1235
0
  dns_peer_t *peer = NULL;
1236
1237
0
  RETERR(dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer));
1238
1239
0
  RETERR(dns_peer_getkey(peer, &keyname));
1240
1241
0
  result = dns_view_gettsig(view, keyname, keyp);
1242
0
  return (result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result;
1243
0
}
1244
1245
isc_result_t
1246
425
dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
1247
425
  REQUIRE(DNS_VIEW_VALID(view));
1248
425
  REQUIRE(source != NULL);
1249
1250
425
  return dns_tsig_verify(source, msg, view->statickeys,
1251
425
             view->dynamickeys);
1252
425
}
1253
1254
isc_result_t
1255
0
dns_view_flushcache(dns_view_t *view, bool fixuponly) {
1256
0
  dns_adb_t *adb = NULL;
1257
1258
0
  REQUIRE(DNS_VIEW_VALID(view));
1259
1260
0
  if (view->cachedb == NULL) {
1261
0
    return ISC_R_SUCCESS;
1262
0
  }
1263
0
  if (!fixuponly) {
1264
0
    RETERR(dns_cache_flush(view->cache));
1265
0
  }
1266
0
  dns_db_detach(&view->cachedb);
1267
0
  dns_cache_attachdb(view->cache, &view->cachedb);
1268
0
  if (view->failcache != NULL) {
1269
0
    dns_badcache_flush(view->failcache);
1270
0
  }
1271
0
  if (view->unreachcache != NULL) {
1272
0
    dns_unreachcache_flush(view->unreachcache);
1273
0
  }
1274
1275
0
  rcu_read_lock();
1276
0
  adb = rcu_dereference(view->adb);
1277
0
  if (adb != NULL) {
1278
0
    dns_adb_flush(adb);
1279
0
  }
1280
0
  rcu_read_unlock();
1281
1282
0
  return ISC_R_SUCCESS;
1283
0
}
1284
1285
isc_result_t
1286
0
dns_view_flushname(dns_view_t *view, const dns_name_t *name) {
1287
0
  return dns_view_flushnode(view, name, false);
1288
0
}
1289
1290
isc_result_t
1291
0
dns_view_flushnode(dns_view_t *view, const dns_name_t *name, bool tree) {
1292
0
  isc_result_t result = ISC_R_SUCCESS;
1293
0
  dns_adb_t *adb = NULL;
1294
1295
0
  REQUIRE(DNS_VIEW_VALID(view));
1296
1297
0
  if (tree) {
1298
0
    rcu_read_lock();
1299
0
    adb = rcu_dereference(view->adb);
1300
0
    if (adb != NULL) {
1301
0
      dns_adb_flushnames(adb, name);
1302
0
    }
1303
0
    rcu_read_unlock();
1304
0
    if (view->failcache != NULL) {
1305
0
      dns_badcache_flushtree(view->failcache, name);
1306
0
    }
1307
0
  } else {
1308
0
    rcu_read_lock();
1309
0
    adb = rcu_dereference(view->adb);
1310
0
    if (adb != NULL) {
1311
0
      dns_adb_flushname(adb, name);
1312
0
    }
1313
0
    rcu_read_unlock();
1314
0
    if (view->failcache != NULL) {
1315
0
      dns_badcache_flushname(view->failcache, name);
1316
0
    }
1317
0
  }
1318
1319
0
  if (view->cache != NULL) {
1320
0
    result = dns_cache_flushnode(view->cache, name, tree);
1321
0
  }
1322
1323
0
  return result;
1324
0
}
1325
1326
isc_result_t
1327
0
dns_view_freezezones(dns_view_t *view, bool value) {
1328
0
  isc_result_t result;
1329
0
  dns_zt_t *zonetable = NULL;
1330
1331
0
  REQUIRE(DNS_VIEW_VALID(view));
1332
1333
0
  rcu_read_lock();
1334
0
  zonetable = rcu_dereference(view->zonetable);
1335
0
  if (zonetable != NULL) {
1336
0
    result = dns_zt_freezezones(zonetable, view, value);
1337
0
  } else {
1338
0
    result = ISC_R_SUCCESS;
1339
0
  }
1340
0
  rcu_read_unlock();
1341
1342
0
  return result;
1343
0
}
1344
1345
void
1346
0
dns_view_initntatable(dns_view_t *view) {
1347
0
  REQUIRE(DNS_VIEW_VALID(view));
1348
0
  if (view->ntatable_priv != NULL) {
1349
0
    dns_ntatable_detach(&view->ntatable_priv);
1350
0
  }
1351
0
  dns_ntatable_create(view, &view->ntatable_priv);
1352
0
}
1353
1354
isc_result_t
1355
0
dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) {
1356
0
  REQUIRE(DNS_VIEW_VALID(view));
1357
0
  REQUIRE(ntp != NULL && *ntp == NULL);
1358
0
  if (view->ntatable_priv == NULL) {
1359
0
    return ISC_R_NOTFOUND;
1360
0
  }
1361
0
  dns_ntatable_attach(view->ntatable_priv, ntp);
1362
0
  return ISC_R_SUCCESS;
1363
0
}
1364
1365
void
1366
0
dns_view_initsecroots(dns_view_t *view) {
1367
0
  REQUIRE(DNS_VIEW_VALID(view));
1368
0
  if (view->secroots_priv != NULL) {
1369
0
    dns_keytable_detach(&view->secroots_priv);
1370
0
  }
1371
0
  dns_keytable_create(view, &view->secroots_priv);
1372
0
}
1373
1374
isc_result_t
1375
0
dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
1376
0
  REQUIRE(DNS_VIEW_VALID(view));
1377
0
  REQUIRE(ktp != NULL && *ktp == NULL);
1378
0
  if (view->secroots_priv == NULL) {
1379
0
    return ISC_R_NOTFOUND;
1380
0
  }
1381
0
  dns_keytable_attach(view->secroots_priv, ktp);
1382
0
  return ISC_R_SUCCESS;
1383
0
}
1384
1385
bool
1386
dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now, const dns_name_t *name,
1387
0
       const dns_name_t *anchor) {
1388
0
  REQUIRE(DNS_VIEW_VALID(view));
1389
1390
0
  if (view->ntatable_priv == NULL) {
1391
0
    return false;
1392
0
  }
1393
1394
0
  return dns_ntatable_covered(view->ntatable_priv, now, name, anchor);
1395
0
}
1396
1397
bool
1398
dns_view_issecuredomain(dns_view_t *view, const dns_name_t *name,
1399
0
      isc_stdtime_t now, bool checknta, bool *ntap) {
1400
0
  bool secure = false;
1401
0
  dns_fixedname_t fn;
1402
0
  dns_name_t *anchor;
1403
1404
0
  REQUIRE(DNS_VIEW_VALID(view));
1405
1406
0
  if (!view->enablevalidation || view->secroots_priv == NULL) {
1407
0
    return false;
1408
0
  }
1409
1410
0
  anchor = dns_fixedname_initname(&fn);
1411
0
  secure = dns_keytable_issecuredomain(view->secroots_priv, name, anchor);
1412
1413
0
  SET_IF_NOT_NULL(ntap, false);
1414
0
  if (checknta && secure && view->ntatable_priv != NULL &&
1415
0
      dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
1416
0
  {
1417
0
    SET_IF_NOT_NULL(ntap, true);
1418
0
    secure = false;
1419
0
  }
1420
1421
0
  return secure;
1422
0
}
1423
1424
void
1425
dns_view_untrust(dns_view_t *view, const dns_name_t *keyname,
1426
0
     const dns_rdata_dnskey_t *dnskey) {
1427
0
  isc_result_t result;
1428
0
  dns_keytable_t *sr = NULL;
1429
0
  dns_rdata_dnskey_t tmpkey;
1430
1431
0
  REQUIRE(DNS_VIEW_VALID(view));
1432
0
  REQUIRE(keyname != NULL);
1433
0
  REQUIRE(dnskey != NULL);
1434
1435
0
  result = dns_view_getsecroots(view, &sr);
1436
0
  if (result != ISC_R_SUCCESS) {
1437
0
    return;
1438
0
  }
1439
1440
  /*
1441
   * Clear the revoke bit, if set, so that the key will match what's
1442
   * in secroots now.
1443
   */
1444
0
  tmpkey = *dnskey;
1445
0
  tmpkey.flags &= ~DNS_KEYFLAG_REVOKE;
1446
1447
0
  result = dns_keytable_deletekey(sr, keyname, &tmpkey);
1448
0
  if (result == ISC_R_SUCCESS) {
1449
    /*
1450
     * If key was found in secroots, then it was a
1451
     * configured trust anchor, and we want to fail
1452
     * secure. If there are no other configured keys,
1453
     * then leave a null key so that we can't validate
1454
     * anymore.
1455
     */
1456
0
    dns_keytable_marksecure(sr, keyname);
1457
0
  }
1458
1459
0
  dns_keytable_detach(&sr);
1460
0
}
1461
1462
bool
1463
dns_view_istrusted(dns_view_t *view, const dns_name_t *keyname,
1464
0
       const dns_rdata_dnskey_t *dnskey) {
1465
0
  isc_result_t result;
1466
0
  dns_keytable_t *sr = NULL;
1467
0
  dns_keynode_t *knode = NULL;
1468
0
  bool answer = false;
1469
0
  dns_rdataset_t dsset;
1470
1471
0
  REQUIRE(DNS_VIEW_VALID(view));
1472
0
  REQUIRE(keyname != NULL);
1473
0
  REQUIRE(dnskey != NULL);
1474
1475
0
  result = dns_view_getsecroots(view, &sr);
1476
0
  if (result != ISC_R_SUCCESS) {
1477
0
    return false;
1478
0
  }
1479
1480
0
  dns_rdataset_init(&dsset);
1481
0
  result = dns_keytable_find(sr, keyname, &knode);
1482
0
  if (result == ISC_R_SUCCESS) {
1483
0
    if (dns_keynode_dsset(knode, &dsset)) {
1484
0
      dns_rdata_t rdata = DNS_RDATA_INIT;
1485
0
      unsigned char data[DNS_RDATA_MAXLENGTH];
1486
0
      unsigned char digest[DNS_DS_BUFFERSIZE];
1487
0
      dns_rdata_dnskey_t tmpkey = *dnskey;
1488
0
      dns_rdata_ds_t ds;
1489
0
      isc_buffer_t b;
1490
0
      dns_rdataclass_t rdclass = tmpkey.common.rdclass;
1491
1492
      /*
1493
       * Clear the revoke bit, if set, so that the key
1494
       * will match what's in secroots now.
1495
       */
1496
0
      tmpkey.flags &= ~DNS_KEYFLAG_REVOKE;
1497
1498
0
      isc_buffer_init(&b, data, sizeof(data));
1499
0
      result = dns_rdata_fromstruct(&rdata, rdclass,
1500
0
                  dns_rdatatype_dnskey,
1501
0
                  &tmpkey, &b);
1502
0
      if (result != ISC_R_SUCCESS) {
1503
0
        goto finish;
1504
0
      }
1505
1506
0
      result = dns_ds_fromkeyrdata(
1507
0
        keyname, &rdata, DNS_DSDIGEST_SHA256, digest,
1508
0
        sizeof(digest), &ds);
1509
0
      if (result != ISC_R_SUCCESS) {
1510
0
        goto finish;
1511
0
      }
1512
1513
0
      dns_rdata_reset(&rdata);
1514
0
      isc_buffer_init(&b, data, sizeof(data));
1515
0
      result = dns_rdata_fromstruct(
1516
0
        &rdata, rdclass, dns_rdatatype_ds, &ds, &b);
1517
0
      if (result != ISC_R_SUCCESS) {
1518
0
        goto finish;
1519
0
      }
1520
1521
0
      DNS_RDATASET_FOREACH(&dsset) {
1522
0
        dns_rdata_t this = DNS_RDATA_INIT;
1523
0
        dns_rdataset_current(&dsset, &this);
1524
0
        if (dns_rdata_compare(&rdata, &this) == 0) {
1525
0
          answer = true;
1526
0
          break;
1527
0
        }
1528
0
      }
1529
0
    }
1530
0
  }
1531
1532
0
finish:
1533
0
  dns_rdataset_cleanup(&dsset);
1534
0
  if (knode != NULL) {
1535
0
    dns_keynode_detach(&knode);
1536
0
  }
1537
0
  dns_keytable_detach(&sr);
1538
0
  return answer;
1539
0
}
1540
1541
isc_result_t
1542
dns_view_searchdlz(dns_view_t *view, const dns_name_t *name,
1543
       unsigned int minlabels, dns_clientinfomethods_t *methods,
1544
0
       dns_clientinfo_t *clientinfo, dns_db_t **dbp) {
1545
0
  dns_fixedname_t fname;
1546
0
  dns_name_t *zonename;
1547
0
  unsigned int namelabels;
1548
0
  unsigned int i;
1549
0
  isc_result_t result;
1550
0
  dns_dlzfindzone_t findzone;
1551
0
  dns_db_t *db, *best = NULL;
1552
1553
  /*
1554
   * Performs checks to make sure data is as we expect it to be.
1555
   */
1556
0
  REQUIRE(DNS_VIEW_VALID(view));
1557
0
  REQUIRE(name != NULL);
1558
0
  REQUIRE(dbp != NULL && *dbp == NULL);
1559
1560
  /* setup a "fixed" dns name */
1561
0
  zonename = dns_fixedname_initname(&fname);
1562
1563
  /* count the number of labels in the name */
1564
0
  namelabels = dns_name_countlabels(name);
1565
1566
0
  ISC_LIST_FOREACH(view->dlz_searched, dlzdb, link) {
1567
0
    REQUIRE(DNS_DLZ_VALID(dlzdb));
1568
1569
    /*
1570
     * loop through starting with the longest domain name and
1571
     * trying shorter names portions of the name until we find a
1572
     * match, have an error, or are below the 'minlabels'
1573
     * threshold.  minlabels is 0, if neither the standard
1574
     * database nor any previous DLZ database had a zone name
1575
     * match. Otherwise minlabels is the number of labels
1576
     * in that name.  We need to beat that for a "better"
1577
     * match for this DLZ database to be authoritative.
1578
     */
1579
0
    for (i = namelabels; i > minlabels && i > 1; i--) {
1580
0
      if (i == namelabels) {
1581
0
        dns_name_copy(name, zonename);
1582
0
      } else {
1583
0
        dns_name_split(name, i, NULL, zonename);
1584
0
      }
1585
1586
      /* ask SDLZ driver if the zone is supported */
1587
0
      db = NULL;
1588
0
      findzone = dlzdb->implementation->methods->findzone;
1589
0
      result = (*findzone)(dlzdb->implementation->driverarg,
1590
0
               dlzdb->dbdata, dlzdb->mctx,
1591
0
               view->rdclass, zonename, methods,
1592
0
               clientinfo, &db);
1593
1594
0
      if (result != ISC_R_NOTFOUND) {
1595
0
        if (best != NULL) {
1596
0
          dns_db_detach(&best);
1597
0
        }
1598
0
        if (result == ISC_R_SUCCESS) {
1599
0
          INSIST(db != NULL);
1600
0
          dns_db_attach(db, &best);
1601
0
          dns_db_detach(&db);
1602
0
          minlabels = i;
1603
0
        } else {
1604
0
          if (db != NULL) {
1605
0
            dns_db_detach(&db);
1606
0
          }
1607
0
          break;
1608
0
        }
1609
0
      } else if (db != NULL) {
1610
0
        dns_db_detach(&db);
1611
0
      }
1612
0
    }
1613
0
  }
1614
1615
0
  if (best != NULL) {
1616
0
    dns_db_attach(best, dbp);
1617
0
    dns_db_detach(&best);
1618
0
    return ISC_R_SUCCESS;
1619
0
  }
1620
1621
0
  return ISC_R_NOTFOUND;
1622
0
}
1623
1624
uint32_t
1625
0
dns_view_getfailttl(dns_view_t *view) {
1626
0
  REQUIRE(DNS_VIEW_VALID(view));
1627
0
  return view->fail_ttl;
1628
0
}
1629
1630
void
1631
0
dns_view_setfailttl(dns_view_t *view, uint32_t fail_ttl) {
1632
0
  REQUIRE(DNS_VIEW_VALID(view));
1633
0
  view->fail_ttl = fail_ttl;
1634
0
}
1635
1636
isc_result_t
1637
0
dns_view_saventa(dns_view_t *view) {
1638
0
  isc_result_t result;
1639
0
  bool removefile = false;
1640
0
  dns_ntatable_t *ntatable = NULL;
1641
0
  FILE *fp = NULL;
1642
1643
0
  REQUIRE(DNS_VIEW_VALID(view));
1644
1645
0
  if (view->nta_lifetime == 0) {
1646
0
    return ISC_R_SUCCESS;
1647
0
  }
1648
1649
  /* Open NTA save file for overwrite. */
1650
0
  CHECK(isc_stdio_open(view->nta_file, "w", &fp));
1651
1652
0
  result = dns_view_getntatable(view, &ntatable);
1653
0
  if (result == ISC_R_NOTFOUND) {
1654
0
    removefile = true;
1655
0
    result = ISC_R_SUCCESS;
1656
0
    goto cleanup;
1657
0
  } else {
1658
0
    CHECK(result);
1659
0
  }
1660
1661
0
  result = dns_ntatable_save(ntatable, fp);
1662
0
  if (result == ISC_R_NOTFOUND) {
1663
0
    removefile = true;
1664
0
    result = ISC_R_SUCCESS;
1665
0
  } else if (result == ISC_R_SUCCESS) {
1666
0
    result = isc_stdio_close(fp);
1667
0
    fp = NULL;
1668
0
  }
1669
1670
0
cleanup:
1671
0
  if (ntatable != NULL) {
1672
0
    dns_ntatable_detach(&ntatable);
1673
0
  }
1674
1675
0
  if (fp != NULL) {
1676
0
    (void)isc_stdio_close(fp);
1677
0
  }
1678
1679
  /* Don't leave half-baked NTA save files lying around. */
1680
0
  if (result != ISC_R_SUCCESS || removefile) {
1681
0
    (void)isc_file_remove(view->nta_file);
1682
0
  }
1683
1684
0
  return result;
1685
0
}
1686
1687
0
#define TSTR(t) ((t).value.as_textregion.base)
1688
0
#define TLEN(t) ((t).value.as_textregion.length)
1689
1690
isc_result_t
1691
0
dns_view_loadnta(dns_view_t *view) {
1692
0
  isc_result_t result;
1693
0
  dns_ntatable_t *ntatable = NULL;
1694
0
  isc_lex_t *lex = NULL;
1695
0
  isc_token_t token;
1696
0
  isc_stdtime_t now = isc_stdtime_now();
1697
1698
0
  REQUIRE(DNS_VIEW_VALID(view));
1699
1700
0
  if (view->nta_lifetime == 0) {
1701
0
    return ISC_R_SUCCESS;
1702
0
  }
1703
1704
0
  isc_lex_create(view->mctx, 1025, &lex);
1705
0
  CHECK(isc_lex_openfile(lex, view->nta_file));
1706
0
  CHECK(dns_view_getntatable(view, &ntatable));
1707
1708
0
  for (;;) {
1709
0
    int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF);
1710
0
    char *name, *type, *timestamp;
1711
0
    size_t len;
1712
0
    dns_fixedname_t fn;
1713
0
    const dns_name_t *ntaname;
1714
0
    isc_buffer_t b;
1715
0
    isc_stdtime_t t;
1716
0
    bool forced;
1717
1718
0
    CHECK(isc_lex_gettoken(lex, options, &token));
1719
0
    if (token.type == isc_tokentype_eof) {
1720
0
      break;
1721
0
    } else if (token.type != isc_tokentype_string) {
1722
0
      CLEANUP(ISC_R_UNEXPECTEDTOKEN);
1723
0
    }
1724
0
    name = TSTR(token);
1725
0
    len = TLEN(token);
1726
1727
0
    if (strcmp(name, ".") == 0) {
1728
0
      ntaname = dns_rootname;
1729
0
    } else {
1730
0
      dns_name_t *fname;
1731
0
      fname = dns_fixedname_initname(&fn);
1732
1733
0
      isc_buffer_init(&b, name, (unsigned int)len);
1734
0
      isc_buffer_add(&b, (unsigned int)len);
1735
0
      CHECK(dns_name_fromtext(fname, &b, dns_rootname, 0));
1736
0
      ntaname = fname;
1737
0
    }
1738
1739
0
    CHECK(isc_lex_gettoken(lex, options, &token));
1740
0
    if (token.type != isc_tokentype_string) {
1741
0
      CLEANUP(ISC_R_UNEXPECTEDTOKEN);
1742
0
    }
1743
0
    type = TSTR(token);
1744
1745
0
    if (strcmp(type, "regular") == 0) {
1746
0
      forced = false;
1747
0
    } else if (strcmp(type, "forced") == 0) {
1748
0
      forced = true;
1749
0
    } else {
1750
0
      CLEANUP(ISC_R_UNEXPECTEDTOKEN);
1751
0
    }
1752
1753
0
    CHECK(isc_lex_gettoken(lex, options, &token));
1754
0
    if (token.type != isc_tokentype_string) {
1755
0
      CLEANUP(ISC_R_UNEXPECTEDTOKEN);
1756
0
    }
1757
0
    timestamp = TSTR(token);
1758
0
    CHECK(dns_time32_fromtext(timestamp, &t));
1759
1760
0
    CHECK(isc_lex_gettoken(lex, options, &token));
1761
0
    if (token.type != isc_tokentype_eol &&
1762
0
        token.type != isc_tokentype_eof)
1763
0
    {
1764
0
      CLEANUP(ISC_R_UNEXPECTEDTOKEN);
1765
0
    }
1766
1767
0
    if (now <= t) {
1768
0
      if (t > (now + 604800)) {
1769
0
        t = now + 604800;
1770
0
      }
1771
1772
0
      (void)dns_ntatable_add(ntatable, ntaname, forced, 0, t);
1773
0
    } else {
1774
0
      char nb[DNS_NAME_FORMATSIZE];
1775
0
      dns_name_format(ntaname, nb, sizeof(nb));
1776
0
      isc_log_write(DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_NTA,
1777
0
              ISC_LOG_INFO,
1778
0
              "ignoring expired NTA at %s", nb);
1779
0
    }
1780
0
  }
1781
1782
0
cleanup:
1783
0
  if (ntatable != NULL) {
1784
0
    dns_ntatable_detach(&ntatable);
1785
0
  }
1786
1787
0
  if (lex != NULL) {
1788
0
    isc_lex_close(lex);
1789
0
    isc_lex_destroy(&lex);
1790
0
  }
1791
1792
0
  return result;
1793
0
}
1794
1795
void
1796
0
dns_view_setviewcommit(dns_view_t *view) {
1797
0
  dns_zone_t *redirect = NULL, *managed_keys = NULL;
1798
0
  dns_zt_t *zonetable = NULL;
1799
1800
0
  REQUIRE(DNS_VIEW_VALID(view));
1801
1802
0
  LOCK(&view->lock);
1803
1804
0
  if (view->redirect != NULL) {
1805
0
    dns_zone_attach(view->redirect, &redirect);
1806
0
  }
1807
0
  if (view->managed_keys != NULL) {
1808
0
    dns_zone_attach(view->managed_keys, &managed_keys);
1809
0
  }
1810
1811
0
  UNLOCK(&view->lock);
1812
1813
0
  rcu_read_lock();
1814
0
  zonetable = rcu_dereference(view->zonetable);
1815
0
  if (zonetable != NULL) {
1816
0
    dns_zt_setviewcommit(zonetable);
1817
0
  }
1818
0
  rcu_read_unlock();
1819
1820
0
  if (redirect != NULL) {
1821
0
    dns_zone_setviewcommit(redirect);
1822
0
    dns_zone_detach(&redirect);
1823
0
  }
1824
0
  if (managed_keys != NULL) {
1825
0
    dns_zone_setviewcommit(managed_keys);
1826
0
    dns_zone_detach(&managed_keys);
1827
0
  }
1828
0
}
1829
1830
void
1831
0
dns_view_setviewrevert(dns_view_t *view) {
1832
0
  dns_zone_t *redirect = NULL, *managed_keys = NULL;
1833
0
  dns_zt_t *zonetable = NULL;
1834
1835
0
  REQUIRE(DNS_VIEW_VALID(view));
1836
1837
  /*
1838
   * dns_zt_setviewrevert() attempts to lock this view, so we must
1839
   * release the lock.
1840
   */
1841
0
  LOCK(&view->lock);
1842
0
  if (view->redirect != NULL) {
1843
0
    dns_zone_attach(view->redirect, &redirect);
1844
0
  }
1845
0
  if (view->managed_keys != NULL) {
1846
0
    dns_zone_attach(view->managed_keys, &managed_keys);
1847
0
  }
1848
0
  UNLOCK(&view->lock);
1849
1850
0
  if (redirect != NULL) {
1851
0
    dns_zone_setviewrevert(redirect);
1852
0
    dns_zone_detach(&redirect);
1853
0
  }
1854
0
  if (managed_keys != NULL) {
1855
0
    dns_zone_setviewrevert(managed_keys);
1856
0
    dns_zone_detach(&managed_keys);
1857
0
  }
1858
0
  rcu_read_lock();
1859
0
  zonetable = rcu_dereference(view->zonetable);
1860
0
  if (zonetable != NULL) {
1861
0
    dns_zt_setviewrevert(zonetable);
1862
0
  }
1863
0
  rcu_read_unlock();
1864
0
}
1865
1866
bool
1867
0
dns_view_staleanswerenabled(dns_view_t *view) {
1868
0
  uint32_t stale_ttl = 0;
1869
0
  bool result = false;
1870
1871
0
  REQUIRE(DNS_VIEW_VALID(view));
1872
1873
0
  if (dns_db_getservestalettl(view->cachedb, &stale_ttl) != ISC_R_SUCCESS)
1874
0
  {
1875
0
    return false;
1876
0
  }
1877
0
  if (stale_ttl > 0) {
1878
0
    if (view->staleanswersok == dns_stale_answer_yes) {
1879
0
      result = true;
1880
0
    } else if (view->staleanswersok == dns_stale_answer_conf) {
1881
0
      result = view->staleanswersenable;
1882
0
    }
1883
0
  }
1884
1885
0
  return result;
1886
0
}
1887
1888
void
1889
0
dns_view_flushonshutdown(dns_view_t *view, bool flush) {
1890
0
  REQUIRE(DNS_VIEW_VALID(view));
1891
1892
0
  view->flush = flush;
1893
0
}
1894
1895
void
1896
2
dns_view_sfd_add(dns_view_t *view, const dns_name_t *name) {
1897
2
  isc_result_t result;
1898
1899
2
  REQUIRE(DNS_VIEW_VALID(view));
1900
1901
2
  result = dns_nametree_add(view->sfd, name, 0);
1902
2
  RUNTIME_CHECK(result == ISC_R_SUCCESS);
1903
2
}
1904
1905
void
1906
0
dns_view_sfd_del(dns_view_t *view, const dns_name_t *name) {
1907
0
  REQUIRE(DNS_VIEW_VALID(view));
1908
1909
0
  dns_nametree_delete(view->sfd, name);
1910
0
}
1911
1912
void
1913
dns_view_sfd_find(dns_view_t *view, const dns_name_t *name,
1914
0
      dns_name_t *foundname) {
1915
0
  REQUIRE(DNS_VIEW_VALID(view));
1916
1917
0
  if (!dns_nametree_covered(view->sfd, name, foundname, 0)) {
1918
0
    dns_name_copy(dns_rootname, foundname);
1919
0
  }
1920
0
}
1921
1922
isc_result_t
1923
0
dns_view_getresolver(dns_view_t *view, dns_resolver_t **resolverp) {
1924
0
  isc_result_t result;
1925
0
  REQUIRE(DNS_VIEW_VALID(view));
1926
0
  REQUIRE(resolverp != NULL && *resolverp == NULL);
1927
0
  LOCK(&view->lock);
1928
0
  if (view->resolver != NULL) {
1929
0
    dns_resolver_attach(view->resolver, resolverp);
1930
0
    result = ISC_R_SUCCESS;
1931
0
  } else {
1932
0
    result = ISC_R_SHUTTINGDOWN;
1933
0
  }
1934
0
  UNLOCK(&view->lock);
1935
0
  return result;
1936
0
}
1937
1938
void
1939
0
dns_view_setmaxrrperset(dns_view_t *view, uint32_t value) {
1940
0
  REQUIRE(DNS_VIEW_VALID(view));
1941
0
  view->maxrrperset = value;
1942
0
  if (view->cache != NULL) {
1943
0
    dns_cache_setmaxrrperset(view->cache, value);
1944
0
  }
1945
0
}
1946
1947
void
1948
0
dns_view_setmaxtypepername(dns_view_t *view, uint32_t value) {
1949
0
  REQUIRE(DNS_VIEW_VALID(view));
1950
0
  view->maxtypepername = value;
1951
0
  if (view->cache != NULL) {
1952
0
    dns_cache_setmaxtypepername(view->cache, value);
1953
0
  }
1954
0
}
1955
1956
void
1957
0
dns_view_setudpsize(dns_view_t *view, uint16_t udpsize) {
1958
0
  REQUIRE(DNS_VIEW_VALID(view));
1959
0
  view->udpsize = udpsize;
1960
0
}
1961
1962
uint16_t
1963
0
dns_view_getudpsize(dns_view_t *view) {
1964
0
  REQUIRE(DNS_VIEW_VALID(view));
1965
0
  return view->udpsize;
1966
0
}
1967
1968
dns_dispatchmgr_t *
1969
0
dns_view_getdispatchmgr(dns_view_t *view) {
1970
0
  REQUIRE(DNS_VIEW_VALID(view));
1971
1972
0
  rcu_read_lock();
1973
0
  dns_dispatchmgr_t *dispatchmgr = rcu_dereference(view->dispatchmgr);
1974
0
  if (dispatchmgr != NULL) {
1975
0
    dns_dispatchmgr_ref(dispatchmgr);
1976
0
  }
1977
0
  rcu_read_unlock();
1978
1979
0
  return dispatchmgr;
1980
0
}
1981
1982
isc_result_t
1983
dns_view_addtrustedkey(dns_view_t *view, dns_rdatatype_t rdtype,
1984
0
           const dns_name_t *keyname, isc_buffer_t *databuf) {
1985
0
  isc_result_t result;
1986
0
  dns_name_t *name = UNCONST(keyname);
1987
0
  char rdatabuf[DNS_RDATA_MAXLENGTH];
1988
0
  unsigned char digest[DNS_DS_BUFFERSIZE];
1989
0
  dns_rdata_ds_t ds;
1990
0
  dns_rdata_t rdata;
1991
0
  isc_buffer_t b;
1992
1993
0
  REQUIRE(DNS_VIEW_VALID(view));
1994
0
  REQUIRE(view->rdclass == dns_rdataclass_in);
1995
1996
0
  if (rdtype != dns_rdatatype_dnskey && rdtype != dns_rdatatype_ds) {
1997
0
    CLEANUP(ISC_R_NOTIMPLEMENTED);
1998
0
  }
1999
2000
0
  isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
2001
0
  dns_rdata_init(&rdata);
2002
0
  isc_buffer_setactive(databuf, isc_buffer_usedlength(databuf));
2003
0
  CHECK(dns_rdata_fromwire(&rdata, view->rdclass, rdtype, databuf,
2004
0
         DNS_DECOMPRESS_NEVER, &b));
2005
2006
0
  if (rdtype == dns_rdatatype_ds) {
2007
0
    CHECK(dns_rdata_tostruct(&rdata, &ds, NULL));
2008
0
  } else {
2009
0
    CHECK(dns_ds_fromkeyrdata(name, &rdata, DNS_DSDIGEST_SHA256,
2010
0
            digest, sizeof(digest), &ds));
2011
0
  }
2012
2013
0
  CHECK(dns_keytable_add(view->secroots_priv, false, false, name, &ds,
2014
0
             NULL, NULL));
2015
2016
0
cleanup:
2017
0
  return result;
2018
0
}
2019
2020
isc_result_t
2021
dns_view_apply(dns_view_t *view, bool stop, isc_result_t *sub,
2022
0
         isc_result_t (*action)(dns_zone_t *, void *), void *uap) {
2023
0
  isc_result_t result;
2024
0
  dns_zt_t *zonetable = NULL;
2025
2026
0
  REQUIRE(DNS_VIEW_VALID(view));
2027
2028
0
  rcu_read_lock();
2029
0
  zonetable = rcu_dereference(view->zonetable);
2030
0
  if (zonetable != NULL) {
2031
0
    result = dns_zt_apply(zonetable, stop, sub, action, uap);
2032
0
  } else {
2033
0
    result = ISC_R_SHUTTINGDOWN;
2034
0
  }
2035
0
  rcu_read_unlock();
2036
0
  return result;
2037
0
}
2038
2039
void
2040
0
dns_view_getadb(dns_view_t *view, dns_adb_t **adbp) {
2041
0
  dns_adb_t *adb = NULL;
2042
2043
0
  REQUIRE(DNS_VIEW_VALID(view));
2044
0
  REQUIRE(adbp != NULL && *adbp == NULL);
2045
2046
0
  rcu_read_lock();
2047
0
  adb = rcu_dereference(view->adb);
2048
0
  if (adb != NULL) {
2049
0
    dns_adb_attach(adb, adbp);
2050
0
  }
2051
0
  rcu_read_unlock();
2052
0
}
2053
2054
void
2055
0
dns_view_setmaxrestarts(dns_view_t *view, uint8_t max_restarts) {
2056
0
  REQUIRE(DNS_VIEW_VALID(view));
2057
0
  REQUIRE(max_restarts > 0);
2058
2059
0
  view->max_restarts = max_restarts;
2060
0
}
2061
2062
void
2063
0
dns_view_setmaxqueries(dns_view_t *view, uint16_t max_queries) {
2064
0
  REQUIRE(DNS_VIEW_VALID(view));
2065
0
  REQUIRE(max_queries > 0);
2066
2067
0
  view->max_queries = max_queries;
2068
0
}
2069
2070
isc_result_t
2071
0
dns_view_setmaxdelegationservers(dns_view_t *view, uint32_t max_servers) {
2072
0
  REQUIRE(DNS_VIEW_VALID(view));
2073
2074
0
  if (max_servers < 1 || max_servers > MAX_DELEGATION_SERVERS) {
2075
0
    return ISC_R_RANGE;
2076
0
  }
2077
2078
0
  view->max_delegation_servers = max_servers;
2079
2080
0
  return ISC_R_SUCCESS;
2081
0
}