Coverage Report

Created: 2025-11-24 06:17

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