Coverage Report

Created: 2022-03-10 07:56

/src/bind9/lib/dns/db.c
Line
Count
Source (jump to first uncovered line)
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
/***
17
 *** Imports
18
 ***/
19
20
#include <inttypes.h>
21
#include <stdbool.h>
22
23
#include <isc/buffer.h>
24
#include <isc/mem.h>
25
#include <isc/once.h>
26
#include <isc/result.h>
27
#include <isc/rwlock.h>
28
#include <isc/string.h>
29
#include <isc/util.h>
30
31
#include <dns/callbacks.h>
32
#include <dns/clientinfo.h>
33
#include <dns/db.h>
34
#include <dns/dbiterator.h>
35
#include <dns/log.h>
36
#include <dns/master.h>
37
#include <dns/rdata.h>
38
#include <dns/rdataset.h>
39
#include <dns/rdatasetiter.h>
40
41
/***
42
 *** Private Types
43
 ***/
44
45
struct dns_dbimplementation {
46
  const char *name;
47
  dns_dbcreatefunc_t create;
48
  isc_mem_t *mctx;
49
  void *driverarg;
50
  ISC_LINK(dns_dbimplementation_t) link;
51
};
52
53
/***
54
 *** Supported DB Implementations Registry
55
 ***/
56
57
/*
58
 * Built in database implementations are registered here.
59
 */
60
61
#include "rbtdb.h"
62
63
unsigned int dns_pps = 0U;
64
65
static ISC_LIST(dns_dbimplementation_t) implementations;
66
static isc_rwlock_t implock;
67
static isc_once_t once = ISC_ONCE_INIT;
68
69
static dns_dbimplementation_t rbtimp;
70
71
static void
72
1
initialize(void) {
73
1
  isc_rwlock_init(&implock, 0, 0);
74
75
1
  rbtimp.name = "rbt";
76
1
  rbtimp.create = dns_rbtdb_create;
77
1
  rbtimp.mctx = NULL;
78
1
  rbtimp.driverarg = NULL;
79
1
  ISC_LINK_INIT(&rbtimp, link);
80
81
1
  ISC_LIST_INIT(implementations);
82
1
  ISC_LIST_APPEND(implementations, &rbtimp, link);
83
1
}
84
85
static inline dns_dbimplementation_t *
86
9.67k
impfind(const char *name) {
87
9.67k
  dns_dbimplementation_t *imp;
88
89
9.67k
  for (imp = ISC_LIST_HEAD(implementations); imp != NULL;
90
9.67k
       imp = ISC_LIST_NEXT(imp, link))
91
9.67k
  {
92
9.67k
    if (strcasecmp(name, imp->name) == 0) {
93
9.67k
      return (imp);
94
9.67k
    }
95
9.67k
  }
96
0
  return (NULL);
97
9.67k
}
98
99
/***
100
 *** Basic DB Methods
101
 ***/
102
103
isc_result_t
104
dns_db_create(isc_mem_t *mctx, const char *db_type, const dns_name_t *origin,
105
        dns_dbtype_t type, dns_rdataclass_t rdclass, unsigned int argc,
106
9.67k
        char *argv[], dns_db_t **dbp) {
107
9.67k
  dns_dbimplementation_t *impinfo;
108
109
9.67k
  RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
110
111
  /*
112
   * Create a new database using implementation 'db_type'.
113
   */
114
115
9.67k
  REQUIRE(dbp != NULL && *dbp == NULL);
116
9.67k
  REQUIRE(dns_name_isabsolute(origin));
117
118
9.67k
  RWLOCK(&implock, isc_rwlocktype_read);
119
0
  impinfo = impfind(db_type);
120
9.67k
  if (impinfo != NULL) {
121
9.67k
    isc_result_t result;
122
9.67k
    result = ((impinfo->create)(mctx, origin, type, rdclass, argc,
123
9.67k
              argv, impinfo->driverarg, dbp));
124
9.67k
    RWUNLOCK(&implock, isc_rwlocktype_read);
125
0
    return (result);
126
9.67k
  }
127
128
0
  RWUNLOCK(&implock, isc_rwlocktype_read);
129
130
0
  isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DB,
131
0
          ISC_LOG_ERROR, "unsupported database type '%s'", db_type);
132
133
0
  return (ISC_R_NOTFOUND);
134
9.67k
}
135
136
void
137
0
dns_db_attach(dns_db_t *source, dns_db_t **targetp) {
138
  /*
139
   * Attach *targetp to source.
140
   */
141
142
0
  REQUIRE(DNS_DB_VALID(source));
143
0
  REQUIRE(targetp != NULL && *targetp == NULL);
144
145
0
  (source->methods->attach)(source, targetp);
146
147
0
  ENSURE(*targetp == source);
148
0
}
149
150
void
151
9.67k
dns_db_detach(dns_db_t **dbp) {
152
  /*
153
   * Detach *dbp from its database.
154
   */
155
156
9.67k
  REQUIRE(dbp != NULL);
157
9.67k
  REQUIRE(DNS_DB_VALID(*dbp));
158
159
0
  ((*dbp)->methods->detach)(dbp);
160
161
9.67k
  ENSURE(*dbp == NULL);
162
9.67k
}
163
164
bool
165
0
dns_db_iscache(dns_db_t *db) {
166
  /*
167
   * Does 'db' have cache semantics?
168
   */
169
170
0
  REQUIRE(DNS_DB_VALID(db));
171
172
0
  if ((db->attributes & DNS_DBATTR_CACHE) != 0) {
173
0
    return (true);
174
0
  }
175
176
0
  return (false);
177
0
}
178
179
bool
180
0
dns_db_iszone(dns_db_t *db) {
181
  /*
182
   * Does 'db' have zone semantics?
183
   */
184
185
0
  REQUIRE(DNS_DB_VALID(db));
186
187
0
  if ((db->attributes & (DNS_DBATTR_CACHE | DNS_DBATTR_STUB)) == 0) {
188
0
    return (true);
189
0
  }
190
191
0
  return (false);
192
0
}
193
194
bool
195
0
dns_db_isstub(dns_db_t *db) {
196
  /*
197
   * Does 'db' have stub semantics?
198
   */
199
200
0
  REQUIRE(DNS_DB_VALID(db));
201
202
0
  if ((db->attributes & DNS_DBATTR_STUB) != 0) {
203
0
    return (true);
204
0
  }
205
206
0
  return (false);
207
0
}
208
209
bool
210
0
dns_db_isdnssec(dns_db_t *db) {
211
  /*
212
   * Is 'db' secure or partially secure?
213
   */
214
215
0
  REQUIRE(DNS_DB_VALID(db));
216
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
217
218
0
  if (db->methods->isdnssec != NULL) {
219
0
    return ((db->methods->isdnssec)(db));
220
0
  }
221
0
  return ((db->methods->issecure)(db));
222
0
}
223
224
bool
225
0
dns_db_issecure(dns_db_t *db) {
226
  /*
227
   * Is 'db' secure?
228
   */
229
230
0
  REQUIRE(DNS_DB_VALID(db));
231
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
232
233
0
  return ((db->methods->issecure)(db));
234
0
}
235
236
bool
237
0
dns_db_ispersistent(dns_db_t *db) {
238
  /*
239
   * Is 'db' persistent?
240
   */
241
242
0
  REQUIRE(DNS_DB_VALID(db));
243
244
0
  return ((db->methods->ispersistent)(db));
245
0
}
246
247
dns_name_t *
248
0
dns_db_origin(dns_db_t *db) {
249
  /*
250
   * The origin of the database.
251
   */
252
253
0
  REQUIRE(DNS_DB_VALID(db));
254
255
0
  return (&db->origin);
256
0
}
257
258
dns_rdataclass_t
259
0
dns_db_class(dns_db_t *db) {
260
  /*
261
   * The class of the database.
262
   */
263
264
0
  REQUIRE(DNS_DB_VALID(db));
265
266
0
  return (db->rdclass);
267
0
}
268
269
isc_result_t
270
9.67k
dns_db_beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
271
  /*
272
   * Begin loading 'db'.
273
   */
274
275
9.67k
  REQUIRE(DNS_DB_VALID(db));
276
9.67k
  REQUIRE(DNS_CALLBACK_VALID(callbacks));
277
278
0
  return ((db->methods->beginload)(db, callbacks));
279
9.67k
}
280
281
isc_result_t
282
9.67k
dns_db_endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
283
9.67k
  dns_dbonupdatelistener_t *listener;
284
285
  /*
286
   * Finish loading 'db'.
287
   */
288
289
9.67k
  REQUIRE(DNS_DB_VALID(db));
290
9.67k
  REQUIRE(DNS_CALLBACK_VALID(callbacks));
291
9.67k
  REQUIRE(callbacks->add_private != NULL);
292
293
9.67k
  for (listener = ISC_LIST_HEAD(db->update_listeners); listener != NULL;
294
9.67k
       listener = ISC_LIST_NEXT(listener, link))
295
0
  {
296
0
    listener->onupdate(db, listener->onupdate_arg);
297
0
  }
298
299
9.67k
  return ((db->methods->endload)(db, callbacks));
300
9.67k
}
301
302
isc_result_t
303
dns_db_load(dns_db_t *db, const char *filename, dns_masterformat_t format,
304
0
      unsigned int options) {
305
0
  isc_result_t result, eresult;
306
0
  dns_rdatacallbacks_t callbacks;
307
308
  /*
309
   * Load master file 'filename' into 'db'.
310
   */
311
312
0
  REQUIRE(DNS_DB_VALID(db));
313
314
0
  if ((db->attributes & DNS_DBATTR_CACHE) != 0) {
315
0
    options |= DNS_MASTER_AGETTL;
316
0
  }
317
318
0
  dns_rdatacallbacks_init(&callbacks);
319
0
  result = dns_db_beginload(db, &callbacks);
320
0
  if (result != ISC_R_SUCCESS) {
321
0
    return (result);
322
0
  }
323
0
  result = dns_master_loadfile(filename, &db->origin, &db->origin,
324
0
             db->rdclass, options, 0, &callbacks, NULL,
325
0
             NULL, db->mctx, format, 0);
326
0
  eresult = dns_db_endload(db, &callbacks);
327
  /*
328
   * We always call dns_db_endload(), but we only want to return its
329
   * result if dns_master_loadfile() succeeded.  If dns_master_loadfile()
330
   * failed, we want to return the result code it gave us.
331
   */
332
0
  if (eresult != ISC_R_SUCCESS &&
333
0
      (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE))
334
0
  {
335
0
    result = eresult;
336
0
  }
337
338
0
  return (result);
339
0
}
340
341
isc_result_t
342
0
dns_db_dump(dns_db_t *db, dns_dbversion_t *version, const char *filename) {
343
0
  return ((db->methods->dump)(db, version, filename,
344
0
            dns_masterformat_text));
345
0
}
346
347
/***
348
 *** Version Methods
349
 ***/
350
351
void
352
0
dns_db_currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
353
  /*
354
   * Open the current version for reading.
355
   */
356
357
0
  REQUIRE(DNS_DB_VALID(db));
358
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
359
0
  REQUIRE(versionp != NULL && *versionp == NULL);
360
361
0
  (db->methods->currentversion)(db, versionp);
362
0
}
363
364
isc_result_t
365
0
dns_db_newversion(dns_db_t *db, dns_dbversion_t **versionp) {
366
  /*
367
   * Open a new version for reading and writing.
368
   */
369
370
0
  REQUIRE(DNS_DB_VALID(db));
371
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
372
0
  REQUIRE(versionp != NULL && *versionp == NULL);
373
374
0
  return ((db->methods->newversion)(db, versionp));
375
0
}
376
377
void
378
dns_db_attachversion(dns_db_t *db, dns_dbversion_t *source,
379
0
         dns_dbversion_t **targetp) {
380
  /*
381
   * Attach '*targetp' to 'source'.
382
   */
383
384
0
  REQUIRE(DNS_DB_VALID(db));
385
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
386
0
  REQUIRE(source != NULL);
387
0
  REQUIRE(targetp != NULL && *targetp == NULL);
388
389
0
  (db->methods->attachversion)(db, source, targetp);
390
391
0
  ENSURE(*targetp != NULL);
392
0
}
393
394
void
395
0
dns_db_closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
396
0
  dns_dbonupdatelistener_t *listener;
397
398
  /*
399
   * Close version '*versionp'.
400
   */
401
402
0
  REQUIRE(DNS_DB_VALID(db));
403
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0);
404
0
  REQUIRE(versionp != NULL && *versionp != NULL);
405
406
0
  (db->methods->closeversion)(db, versionp, commit);
407
408
0
  if (commit) {
409
0
    for (listener = ISC_LIST_HEAD(db->update_listeners);
410
0
         listener != NULL; listener = ISC_LIST_NEXT(listener, link))
411
0
    {
412
0
      listener->onupdate(db, listener->onupdate_arg);
413
0
    }
414
0
  }
415
416
0
  ENSURE(*versionp == NULL);
417
0
}
418
419
/***
420
 *** Node Methods
421
 ***/
422
423
isc_result_t
424
dns_db_findnode(dns_db_t *db, const dns_name_t *name, bool create,
425
0
    dns_dbnode_t **nodep) {
426
  /*
427
   * Find the node with name 'name'.
428
   */
429
430
0
  REQUIRE(DNS_DB_VALID(db));
431
0
  REQUIRE(nodep != NULL && *nodep == NULL);
432
433
0
  if (db->methods->findnode != NULL) {
434
0
    return ((db->methods->findnode)(db, name, create, nodep));
435
0
  } else {
436
0
    return ((db->methods->findnodeext)(db, name, create, NULL, NULL,
437
0
               nodep));
438
0
  }
439
0
}
440
441
isc_result_t
442
dns_db_findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
443
       dns_clientinfomethods_t *methods,
444
0
       dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) {
445
  /*
446
   * Find the node with name 'name', passing 'arg' to the database
447
   * implementation.
448
   */
449
450
0
  REQUIRE(DNS_DB_VALID(db));
451
0
  REQUIRE(nodep != NULL && *nodep == NULL);
452
453
0
  if (db->methods->findnodeext != NULL) {
454
0
    return ((db->methods->findnodeext)(db, name, create, methods,
455
0
               clientinfo, nodep));
456
0
  } else {
457
0
    return ((db->methods->findnode)(db, name, create, nodep));
458
0
  }
459
0
}
460
461
isc_result_t
462
dns_db_findnsec3node(dns_db_t *db, const dns_name_t *name, bool create,
463
0
         dns_dbnode_t **nodep) {
464
  /*
465
   * Find the node with name 'name'.
466
   */
467
468
0
  REQUIRE(DNS_DB_VALID(db));
469
0
  REQUIRE(nodep != NULL && *nodep == NULL);
470
471
0
  return ((db->methods->findnsec3node)(db, name, create, nodep));
472
0
}
473
474
isc_result_t
475
dns_db_find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
476
      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
477
      dns_dbnode_t **nodep, dns_name_t *foundname,
478
0
      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
479
  /*
480
   * Find the best match for 'name' and 'type' in version 'version'
481
   * of 'db'.
482
   */
483
484
0
  REQUIRE(DNS_DB_VALID(db));
485
0
  REQUIRE(type != dns_rdatatype_rrsig);
486
0
  REQUIRE(nodep == NULL || *nodep == NULL);
487
0
  REQUIRE(dns_name_hasbuffer(foundname));
488
0
  REQUIRE(rdataset == NULL || (DNS_RDATASET_VALID(rdataset) &&
489
0
             !dns_rdataset_isassociated(rdataset)));
490
0
  REQUIRE(sigrdataset == NULL ||
491
0
    (DNS_RDATASET_VALID(sigrdataset) &&
492
0
     !dns_rdataset_isassociated(sigrdataset)));
493
494
0
  if (db->methods->find != NULL) {
495
0
    return ((db->methods->find)(db, name, version, type, options,
496
0
              now, nodep, foundname, rdataset,
497
0
              sigrdataset));
498
0
  } else {
499
0
    return ((db->methods->findext)(db, name, version, type, options,
500
0
                 now, nodep, foundname, NULL,
501
0
                 NULL, rdataset, sigrdataset));
502
0
  }
503
0
}
504
505
isc_result_t
506
dns_db_findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
507
         dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
508
         dns_dbnode_t **nodep, dns_name_t *foundname,
509
         dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
510
0
         dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
511
  /*
512
   * Find the best match for 'name' and 'type' in version 'version'
513
   * of 'db', passing in 'arg'.
514
   */
515
516
0
  REQUIRE(DNS_DB_VALID(db));
517
0
  REQUIRE(type != dns_rdatatype_rrsig);
518
0
  REQUIRE(nodep == NULL || *nodep == NULL);
519
0
  REQUIRE(dns_name_hasbuffer(foundname));
520
0
  REQUIRE(rdataset == NULL || (DNS_RDATASET_VALID(rdataset) &&
521
0
             !dns_rdataset_isassociated(rdataset)));
522
0
  REQUIRE(sigrdataset == NULL ||
523
0
    (DNS_RDATASET_VALID(sigrdataset) &&
524
0
     !dns_rdataset_isassociated(sigrdataset)));
525
526
0
  if (db->methods->findext != NULL) {
527
0
    return ((db->methods->findext)(
528
0
      db, name, version, type, options, now, nodep, foundname,
529
0
      methods, clientinfo, rdataset, sigrdataset));
530
0
  } else {
531
0
    return ((db->methods->find)(db, name, version, type, options,
532
0
              now, nodep, foundname, rdataset,
533
0
              sigrdataset));
534
0
  }
535
0
}
536
537
isc_result_t
538
dns_db_findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
539
       isc_stdtime_t now, dns_dbnode_t **nodep,
540
       dns_name_t *foundname, dns_name_t *dcname,
541
0
       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
542
  /*
543
   * Find the deepest known zonecut which encloses 'name' in 'db'.
544
   * foundname is the zonecut, dcname is the deepest name we have
545
   * in database that is part of queried name.
546
   */
547
548
0
  REQUIRE(DNS_DB_VALID(db));
549
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
550
0
  REQUIRE(nodep == NULL || *nodep == NULL);
551
0
  REQUIRE(dns_name_hasbuffer(foundname));
552
0
  REQUIRE(sigrdataset == NULL ||
553
0
    (DNS_RDATASET_VALID(sigrdataset) &&
554
0
     !dns_rdataset_isassociated(sigrdataset)));
555
556
0
  return ((db->methods->findzonecut)(db, name, options, now, nodep,
557
0
             foundname, dcname, rdataset,
558
0
             sigrdataset));
559
0
}
560
561
void
562
0
dns_db_attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
563
  /*
564
   * Attach *targetp to source.
565
   */
566
567
0
  REQUIRE(DNS_DB_VALID(db));
568
0
  REQUIRE(source != NULL);
569
0
  REQUIRE(targetp != NULL && *targetp == NULL);
570
571
0
  (db->methods->attachnode)(db, source, targetp);
572
0
}
573
574
void
575
0
dns_db_detachnode(dns_db_t *db, dns_dbnode_t **nodep) {
576
  /*
577
   * Detach *nodep from its node.
578
   */
579
580
0
  REQUIRE(DNS_DB_VALID(db));
581
0
  REQUIRE(nodep != NULL && *nodep != NULL);
582
583
0
  (db->methods->detachnode)(db, nodep);
584
585
0
  ENSURE(*nodep == NULL);
586
0
}
587
588
void
589
dns_db_transfernode(dns_db_t *db, dns_dbnode_t **sourcep,
590
0
        dns_dbnode_t **targetp) {
591
0
  REQUIRE(DNS_DB_VALID(db));
592
0
  REQUIRE(targetp != NULL && *targetp == NULL);
593
  /*
594
   * This doesn't check the implementation magic.  If we find that
595
   * we need such checks in future then this will be done in the
596
   * method.
597
   */
598
0
  REQUIRE(sourcep != NULL && *sourcep != NULL);
599
600
0
  UNUSED(db);
601
602
0
  if (db->methods->transfernode == NULL) {
603
0
    *targetp = *sourcep;
604
0
    *sourcep = NULL;
605
0
  } else {
606
0
    (db->methods->transfernode)(db, sourcep, targetp);
607
0
  }
608
609
0
  ENSURE(*sourcep == NULL);
610
0
}
611
612
isc_result_t
613
0
dns_db_expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
614
  /*
615
   * Mark as stale all records at 'node' which expire at or before 'now'.
616
   */
617
618
0
  REQUIRE(DNS_DB_VALID(db));
619
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
620
0
  REQUIRE(node != NULL);
621
622
0
  return ((db->methods->expirenode)(db, node, now));
623
0
}
624
625
void
626
0
dns_db_printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
627
  /*
628
   * Print a textual representation of the contents of the node to
629
   * 'out'.
630
   */
631
632
0
  REQUIRE(DNS_DB_VALID(db));
633
0
  REQUIRE(node != NULL);
634
635
0
  (db->methods->printnode)(db, node, out);
636
0
}
637
638
/***
639
 *** DB Iterator Creation
640
 ***/
641
642
isc_result_t
643
dns_db_createiterator(dns_db_t *db, unsigned int flags,
644
0
          dns_dbiterator_t **iteratorp) {
645
  /*
646
   * Create an iterator for version 'version' of 'db'.
647
   */
648
649
0
  REQUIRE(DNS_DB_VALID(db));
650
0
  REQUIRE(iteratorp != NULL && *iteratorp == NULL);
651
652
0
  return (db->methods->createiterator(db, flags, iteratorp));
653
0
}
654
655
/***
656
 *** Rdataset Methods
657
 ***/
658
659
isc_result_t
660
dns_db_findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
661
        dns_rdatatype_t type, dns_rdatatype_t covers,
662
        isc_stdtime_t now, dns_rdataset_t *rdataset,
663
9.69k
        dns_rdataset_t *sigrdataset) {
664
9.69k
  REQUIRE(DNS_DB_VALID(db));
665
9.69k
  REQUIRE(node != NULL);
666
9.69k
  REQUIRE(DNS_RDATASET_VALID(rdataset));
667
9.69k
  REQUIRE(!dns_rdataset_isassociated(rdataset));
668
9.69k
  REQUIRE(covers == 0 || type == dns_rdatatype_rrsig);
669
9.69k
  REQUIRE(type != dns_rdatatype_any);
670
9.69k
  REQUIRE(sigrdataset == NULL ||
671
0
    (DNS_RDATASET_VALID(sigrdataset) &&
672
0
     !dns_rdataset_isassociated(sigrdataset)));
673
674
0
  return ((db->methods->findrdataset)(db, node, version, type, covers,
675
9.69k
              now, rdataset, sigrdataset));
676
9.69k
}
677
678
isc_result_t
679
dns_db_allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
680
0
        isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) {
681
  /*
682
   * Make '*iteratorp' an rdataset iteratator for all rdatasets at
683
   * 'node' in version 'version' of 'db'.
684
   */
685
686
0
  REQUIRE(DNS_DB_VALID(db));
687
0
  REQUIRE(iteratorp != NULL && *iteratorp == NULL);
688
689
0
  return ((db->methods->allrdatasets)(db, node, version, now, iteratorp));
690
0
}
691
692
isc_result_t
693
dns_db_addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
694
       isc_stdtime_t now, dns_rdataset_t *rdataset,
695
0
       unsigned int options, dns_rdataset_t *addedrdataset) {
696
  /*
697
   * Add 'rdataset' to 'node' in version 'version' of 'db'.
698
   */
699
700
0
  REQUIRE(DNS_DB_VALID(db));
701
0
  REQUIRE(node != NULL);
702
0
  REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL) ||
703
0
    ((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL &&
704
0
     (options & DNS_DBADD_MERGE) == 0));
705
0
  REQUIRE((options & DNS_DBADD_EXACT) == 0 ||
706
0
    (options & DNS_DBADD_MERGE) != 0);
707
0
  REQUIRE(DNS_RDATASET_VALID(rdataset));
708
0
  REQUIRE(dns_rdataset_isassociated(rdataset));
709
0
  REQUIRE(rdataset->rdclass == db->rdclass);
710
0
  REQUIRE(addedrdataset == NULL ||
711
0
    (DNS_RDATASET_VALID(addedrdataset) &&
712
0
     !dns_rdataset_isassociated(addedrdataset)));
713
714
0
  return ((db->methods->addrdataset)(db, node, version, now, rdataset,
715
0
             options, addedrdataset));
716
0
}
717
718
isc_result_t
719
dns_db_subtractrdataset(dns_db_t *db, dns_dbnode_t *node,
720
      dns_dbversion_t *version, dns_rdataset_t *rdataset,
721
0
      unsigned int options, dns_rdataset_t *newrdataset) {
722
  /*
723
   * Remove any rdata in 'rdataset' from 'node' in version 'version' of
724
   * 'db'.
725
   */
726
727
0
  REQUIRE(DNS_DB_VALID(db));
728
0
  REQUIRE(node != NULL);
729
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL);
730
0
  REQUIRE(DNS_RDATASET_VALID(rdataset));
731
0
  REQUIRE(dns_rdataset_isassociated(rdataset));
732
0
  REQUIRE(rdataset->rdclass == db->rdclass);
733
0
  REQUIRE(newrdataset == NULL ||
734
0
    (DNS_RDATASET_VALID(newrdataset) &&
735
0
     !dns_rdataset_isassociated(newrdataset)));
736
737
0
  return ((db->methods->subtractrdataset)(db, node, version, rdataset,
738
0
            options, newrdataset));
739
0
}
740
741
isc_result_t
742
dns_db_deleterdataset(dns_db_t *db, dns_dbnode_t *node,
743
          dns_dbversion_t *version, dns_rdatatype_t type,
744
0
          dns_rdatatype_t covers) {
745
  /*
746
   * Make it so that no rdataset of type 'type' exists at 'node' in
747
   * version version 'version' of 'db'.
748
   */
749
750
0
  REQUIRE(DNS_DB_VALID(db));
751
0
  REQUIRE(node != NULL);
752
0
  REQUIRE(((db->attributes & DNS_DBATTR_CACHE) == 0 && version != NULL) ||
753
0
    ((db->attributes & DNS_DBATTR_CACHE) != 0 && version == NULL));
754
755
0
  return ((db->methods->deleterdataset)(db, node, version, type, covers));
756
0
}
757
758
void
759
0
dns_db_overmem(dns_db_t *db, bool overmem) {
760
0
  REQUIRE(DNS_DB_VALID(db));
761
762
0
  (db->methods->overmem)(db, overmem);
763
0
}
764
765
isc_result_t
766
0
dns_db_getsoaserial(dns_db_t *db, dns_dbversion_t *ver, uint32_t *serialp) {
767
0
  isc_result_t result;
768
0
  dns_dbnode_t *node = NULL;
769
0
  dns_rdataset_t rdataset;
770
0
  dns_rdata_t rdata = DNS_RDATA_INIT;
771
0
  isc_buffer_t buffer;
772
773
0
  REQUIRE(dns_db_iszone(db) || dns_db_isstub(db));
774
775
0
  result = dns_db_findnode(db, dns_db_origin(db), false, &node);
776
0
  if (result != ISC_R_SUCCESS) {
777
0
    return (result);
778
0
  }
779
780
0
  dns_rdataset_init(&rdataset);
781
0
  result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0,
782
0
             (isc_stdtime_t)0, &rdataset, NULL);
783
0
  if (result != ISC_R_SUCCESS) {
784
0
    goto freenode;
785
0
  }
786
787
0
  result = dns_rdataset_first(&rdataset);
788
0
  if (result != ISC_R_SUCCESS) {
789
0
    goto freerdataset;
790
0
  }
791
0
  dns_rdataset_current(&rdataset, &rdata);
792
0
  result = dns_rdataset_next(&rdataset);
793
0
  INSIST(result == ISC_R_NOMORE);
794
795
0
  INSIST(rdata.length > 20);
796
0
  isc_buffer_init(&buffer, rdata.data, rdata.length);
797
0
  isc_buffer_add(&buffer, rdata.length);
798
0
  isc_buffer_forward(&buffer, rdata.length - 20);
799
0
  *serialp = isc_buffer_getuint32(&buffer);
800
801
0
  result = ISC_R_SUCCESS;
802
803
0
freerdataset:
804
0
  dns_rdataset_disassociate(&rdataset);
805
806
0
freenode:
807
0
  dns_db_detachnode(db, &node);
808
0
  return (result);
809
0
}
810
811
unsigned int
812
0
dns_db_nodecount(dns_db_t *db, dns_dbtree_t tree) {
813
0
  REQUIRE(DNS_DB_VALID(db));
814
815
0
  return ((db->methods->nodecount)(db, tree));
816
0
}
817
818
size_t
819
0
dns_db_hashsize(dns_db_t *db) {
820
0
  REQUIRE(DNS_DB_VALID(db));
821
822
0
  if (db->methods->hashsize == NULL) {
823
0
    return (0);
824
0
  }
825
826
0
  return ((db->methods->hashsize)(db));
827
0
}
828
829
void
830
0
dns_db_settask(dns_db_t *db, isc_task_t *task) {
831
0
  REQUIRE(DNS_DB_VALID(db));
832
833
0
  (db->methods->settask)(db, task);
834
0
}
835
836
isc_result_t
837
dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg,
838
0
    isc_mem_t *mctx, dns_dbimplementation_t **dbimp) {
839
0
  dns_dbimplementation_t *imp;
840
841
0
  REQUIRE(name != NULL);
842
0
  REQUIRE(dbimp != NULL && *dbimp == NULL);
843
844
0
  RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
845
846
0
  RWLOCK(&implock, isc_rwlocktype_write);
847
0
  imp = impfind(name);
848
0
  if (imp != NULL) {
849
0
    RWUNLOCK(&implock, isc_rwlocktype_write);
850
0
    return (ISC_R_EXISTS);
851
0
  }
852
853
0
  imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t));
854
0
  imp->name = name;
855
0
  imp->create = create;
856
0
  imp->mctx = NULL;
857
0
  imp->driverarg = driverarg;
858
0
  isc_mem_attach(mctx, &imp->mctx);
859
0
  ISC_LINK_INIT(imp, link);
860
0
  ISC_LIST_APPEND(implementations, imp, link);
861
0
  RWUNLOCK(&implock, isc_rwlocktype_write);
862
863
0
  *dbimp = imp;
864
865
0
  return (ISC_R_SUCCESS);
866
0
}
867
868
void
869
0
dns_db_unregister(dns_dbimplementation_t **dbimp) {
870
0
  dns_dbimplementation_t *imp;
871
872
0
  REQUIRE(dbimp != NULL && *dbimp != NULL);
873
874
0
  RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
875
876
0
  imp = *dbimp;
877
0
  *dbimp = NULL;
878
0
  RWLOCK(&implock, isc_rwlocktype_write);
879
0
  ISC_LIST_UNLINK(implementations, imp, link);
880
0
  isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_dbimplementation_t));
881
0
  RWUNLOCK(&implock, isc_rwlocktype_write);
882
0
  ENSURE(*dbimp == NULL);
883
0
}
884
885
isc_result_t
886
0
dns_db_getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
887
0
  REQUIRE(DNS_DB_VALID(db));
888
0
  REQUIRE(dns_db_iszone(db));
889
0
  REQUIRE(nodep != NULL && *nodep == NULL);
890
891
0
  if (db->methods->getoriginnode != NULL) {
892
0
    return ((db->methods->getoriginnode)(db, nodep));
893
0
  }
894
895
0
  return (ISC_R_NOTFOUND);
896
0
}
897
898
dns_stats_t *
899
0
dns_db_getrrsetstats(dns_db_t *db) {
900
0
  REQUIRE(DNS_DB_VALID(db));
901
902
0
  if (db->methods->getrrsetstats != NULL) {
903
0
    return ((db->methods->getrrsetstats)(db));
904
0
  }
905
906
0
  return (NULL);
907
0
}
908
909
isc_result_t
910
0
dns_db_setcachestats(dns_db_t *db, isc_stats_t *stats) {
911
0
  REQUIRE(DNS_DB_VALID(db));
912
913
0
  if (db->methods->setcachestats != NULL) {
914
0
    return ((db->methods->setcachestats)(db, stats));
915
0
  }
916
917
0
  return (ISC_R_NOTIMPLEMENTED);
918
0
}
919
920
isc_result_t
921
dns_db_getnsec3parameters(dns_db_t *db, dns_dbversion_t *version,
922
        dns_hash_t *hash, uint8_t *flags,
923
        uint16_t *iterations, unsigned char *salt,
924
0
        size_t *salt_length) {
925
0
  REQUIRE(DNS_DB_VALID(db));
926
0
  REQUIRE(dns_db_iszone(db));
927
928
0
  if (db->methods->getnsec3parameters != NULL) {
929
0
    return ((db->methods->getnsec3parameters)(db, version, hash,
930
0
                flags, iterations,
931
0
                salt, salt_length));
932
0
  }
933
934
0
  return (ISC_R_NOTFOUND);
935
0
}
936
937
isc_result_t
938
dns_db_getsize(dns_db_t *db, dns_dbversion_t *version, uint64_t *records,
939
0
         uint64_t *bytes) {
940
0
  REQUIRE(DNS_DB_VALID(db));
941
0
  REQUIRE(dns_db_iszone(db));
942
943
0
  if (db->methods->getsize != NULL) {
944
0
    return ((db->methods->getsize)(db, version, records, bytes));
945
0
  }
946
947
0
  return (ISC_R_NOTFOUND);
948
0
}
949
950
isc_result_t
951
dns_db_setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
952
0
          isc_stdtime_t resign) {
953
0
  if (db->methods->setsigningtime != NULL) {
954
0
    return ((db->methods->setsigningtime)(db, rdataset, resign));
955
0
  }
956
0
  return (ISC_R_NOTIMPLEMENTED);
957
0
}
958
959
isc_result_t
960
dns_db_getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset,
961
0
          dns_name_t *name) {
962
0
  if (db->methods->getsigningtime != NULL) {
963
0
    return ((db->methods->getsigningtime)(db, rdataset, name));
964
0
  }
965
0
  return (ISC_R_NOTFOUND);
966
0
}
967
968
void
969
dns_db_resigned(dns_db_t *db, dns_rdataset_t *rdataset,
970
0
    dns_dbversion_t *version) {
971
0
  if (db->methods->resigned != NULL) {
972
0
    (db->methods->resigned)(db, rdataset, version);
973
0
  }
974
0
}
975
976
/*
977
 * Attach a database to policy zone databases.
978
 * This should only happen when the caller has already ensured that
979
 * it is dealing with a database that understands response policy zones.
980
 */
981
void
982
0
dns_db_rpz_attach(dns_db_t *db, void *rpzs, uint8_t rpz_num) {
983
0
  REQUIRE(db->methods->rpz_attach != NULL);
984
0
  (db->methods->rpz_attach)(db, rpzs, rpz_num);
985
0
}
986
987
/*
988
 * Finish loading a response policy zone.
989
 */
990
isc_result_t
991
0
dns_db_rpz_ready(dns_db_t *db) {
992
0
  if (db->methods->rpz_ready == NULL) {
993
0
    return (ISC_R_SUCCESS);
994
0
  }
995
0
  return ((db->methods->rpz_ready)(db));
996
0
}
997
998
/**
999
 * Attach a notify-on-update function the database
1000
 */
1001
isc_result_t
1002
dns_db_updatenotify_register(dns_db_t *db, dns_dbupdate_callback_t fn,
1003
0
           void *fn_arg) {
1004
0
  dns_dbonupdatelistener_t *listener;
1005
1006
0
  REQUIRE(db != NULL);
1007
0
  REQUIRE(fn != NULL);
1008
1009
0
  listener = isc_mem_get(db->mctx, sizeof(dns_dbonupdatelistener_t));
1010
1011
0
  listener->onupdate = fn;
1012
0
  listener->onupdate_arg = fn_arg;
1013
1014
0
  ISC_LINK_INIT(listener, link);
1015
0
  ISC_LIST_APPEND(db->update_listeners, listener, link);
1016
1017
0
  return (ISC_R_SUCCESS);
1018
0
}
1019
1020
isc_result_t
1021
dns_db_updatenotify_unregister(dns_db_t *db, dns_dbupdate_callback_t fn,
1022
0
             void *fn_arg) {
1023
0
  dns_dbonupdatelistener_t *listener;
1024
1025
0
  REQUIRE(db != NULL);
1026
1027
0
  for (listener = ISC_LIST_HEAD(db->update_listeners); listener != NULL;
1028
0
       listener = ISC_LIST_NEXT(listener, link))
1029
0
  {
1030
0
    if ((listener->onupdate == fn) &&
1031
0
        (listener->onupdate_arg == fn_arg)) {
1032
0
      ISC_LIST_UNLINK(db->update_listeners, listener, link);
1033
0
      isc_mem_put(db->mctx, listener,
1034
0
            sizeof(dns_dbonupdatelistener_t));
1035
0
      return (ISC_R_SUCCESS);
1036
0
    }
1037
0
  }
1038
1039
0
  return (ISC_R_NOTFOUND);
1040
0
}
1041
1042
isc_result_t
1043
0
dns_db_nodefullname(dns_db_t *db, dns_dbnode_t *node, dns_name_t *name) {
1044
0
  REQUIRE(db != NULL);
1045
0
  REQUIRE(node != NULL);
1046
0
  REQUIRE(name != NULL);
1047
1048
0
  if (db->methods->nodefullname == NULL) {
1049
0
    return (ISC_R_NOTIMPLEMENTED);
1050
0
  }
1051
0
  return ((db->methods->nodefullname)(db, node, name));
1052
0
}
1053
1054
isc_result_t
1055
0
dns_db_setservestalettl(dns_db_t *db, dns_ttl_t ttl) {
1056
0
  REQUIRE(DNS_DB_VALID(db));
1057
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
1058
1059
0
  if (db->methods->setservestalettl != NULL) {
1060
0
    return ((db->methods->setservestalettl)(db, ttl));
1061
0
  }
1062
0
  return (ISC_R_NOTIMPLEMENTED);
1063
0
}
1064
1065
isc_result_t
1066
0
dns_db_getservestalettl(dns_db_t *db, dns_ttl_t *ttl) {
1067
0
  REQUIRE(DNS_DB_VALID(db));
1068
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
1069
1070
0
  if (db->methods->getservestalettl != NULL) {
1071
0
    return ((db->methods->getservestalettl)(db, ttl));
1072
0
  }
1073
0
  return (ISC_R_NOTIMPLEMENTED);
1074
0
}
1075
1076
isc_result_t
1077
0
dns_db_setservestalerefresh(dns_db_t *db, uint32_t interval) {
1078
0
  REQUIRE(DNS_DB_VALID(db));
1079
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
1080
1081
0
  if (db->methods->setservestalerefresh != NULL) {
1082
0
    return ((db->methods->setservestalerefresh)(db, interval));
1083
0
  }
1084
0
  return (ISC_R_NOTIMPLEMENTED);
1085
0
}
1086
1087
isc_result_t
1088
0
dns_db_getservestalerefresh(dns_db_t *db, uint32_t *interval) {
1089
0
  REQUIRE(DNS_DB_VALID(db));
1090
0
  REQUIRE((db->attributes & DNS_DBATTR_CACHE) != 0);
1091
1092
0
  if (db->methods->getservestalerefresh != NULL) {
1093
0
    return ((db->methods->getservestalerefresh)(db, interval));
1094
0
  }
1095
0
  return (ISC_R_NOTIMPLEMENTED);
1096
0
}
1097
1098
isc_result_t
1099
0
dns_db_setgluecachestats(dns_db_t *db, isc_stats_t *stats) {
1100
0
  REQUIRE(dns_db_iszone(db));
1101
0
  REQUIRE(stats != NULL);
1102
1103
0
  if (db->methods->setgluecachestats != NULL) {
1104
0
    return ((db->methods->setgluecachestats)(db, stats));
1105
0
  }
1106
1107
0
  return (ISC_R_NOTIMPLEMENTED);
1108
0
}