1 /* $NetBSD: db.c,v 1.3 2019/01/09 16:55:02 christos Exp $ */ 2 3 /* 4 * Database API implementation. The interface is defined in lib/dns/db.h. 5 * 6 * dns_db_*() calls on database instances backed by this driver use 7 * struct sampledb_methods to find appropriate function implementation. 8 * 9 * This example re-uses RBT DB implementation from original BIND and blindly 10 * proxies most of dns_db_*() calls to this underlying RBT DB. 11 * See struct sampledb below. 12 * 13 * Copyright (C) 2009-2015 Red Hat ; see COPYRIGHT for license 14 */ 15 #include <config.h> 16 17 #include <inttypes.h> 18 #include <stdbool.h> 19 20 #include <isc/string.h> 21 #include <isc/util.h> 22 23 #include <dns/db.h> 24 #include <dns/diff.h> 25 #include <dns/enumclass.h> 26 #include <dns/rbt.h> 27 #include <dns/rdatalist.h> 28 #include <dns/rdatastruct.h> 29 #include <dns/soa.h> 30 #include <dns/types.h> 31 32 #include "db.h" 33 #include "instance.h" 34 #include "syncptr.h" 35 #include "util.h" 36 37 #define SAMPLEDB_MAGIC ISC_MAGIC('S', 'M', 'D', 'B') 38 #define VALID_SAMPLEDB(sampledb) \ 39 ((sampledb) != NULL && (sampledb)->common.impmagic == SAMPLEDB_MAGIC) 40 41 struct sampledb { 42 dns_db_t common; 43 isc_refcount_t refs; 44 sample_instance_t *inst; 45 46 /* 47 * Internal RBT database implementation provided by BIND. 48 * Most dns_db_* calls (find(), createiterator(), etc.) 49 * are blindly forwarded to this RBT DB. 50 */ 51 dns_db_t *rbtdb; 52 }; 53 54 typedef struct sampledb sampledb_t; 55 56 /* 57 * Get full DNS name from the node. 58 * 59 * @warning 60 * The code silently expects that "node" came from RBTDB and thus 61 * assumption dns_dbnode_t (from RBTDB) == dns_rbtnode_t is correct. 62 * 63 * This should work as long as we use only RBTDB and nothing else. 64 */ 65 static isc_result_t 66 sample_name_fromnode(dns_dbnode_t *node, dns_name_t *name) { 67 dns_rbtnode_t *rbtnode = (dns_rbtnode_t *) node; 68 return (dns_rbt_fullnamefromnode(rbtnode, name)); 69 } 70 71 static void 72 attach(dns_db_t *source, dns_db_t **targetp) { 73 sampledb_t *sampledb = (sampledb_t *)source; 74 75 REQUIRE(VALID_SAMPLEDB(sampledb)); 76 77 isc_refcount_increment(&sampledb->refs); 78 *targetp = source; 79 } 80 81 static void 82 free_sampledb(sampledb_t *sampledb) { 83 REQUIRE(VALID_SAMPLEDB(sampledb)); 84 85 dns_db_detach(&sampledb->rbtdb); 86 dns_name_free(&sampledb->common.origin, sampledb->common.mctx); 87 isc_mem_putanddetach(&sampledb->common.mctx, sampledb, sizeof(*sampledb)); 88 } 89 90 static void 91 detach(dns_db_t **dbp) { 92 REQUIRE(dbp != NULL && VALID_SAMPLEDB((sampledb_t *)(*dbp))); 93 sampledb_t *sampledb = (sampledb_t *)(*dbp); 94 *dbp = NULL; 95 96 if (isc_refcount_decrement(&sampledb->refs) == 1) { 97 free_sampledb(sampledb); 98 } 99 } 100 101 /* 102 * This method should never be called, because DB is "persistent". 103 * See ispersistent() function. It means that database do not need to be 104 * loaded in the usual sense. 105 */ 106 static isc_result_t 107 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 108 UNUSED(db); 109 UNUSED(callbacks); 110 111 fatal_error("current implementation should never call beginload()"); 112 113 /* Not reached */ 114 return (ISC_R_SUCCESS); 115 } 116 117 /* 118 * This method should never be called, because DB is "persistent". 119 * See ispersistent() function. It means that database do not need to be 120 * loaded in the usual sense. 121 */ 122 static isc_result_t 123 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) { 124 UNUSED(db); 125 UNUSED(callbacks); 126 127 fatal_error("current implementation should never call endload()"); 128 129 /* Not reached */ 130 return (ISC_R_SUCCESS); 131 } 132 133 static isc_result_t 134 serialize(dns_db_t *db, dns_dbversion_t *version, FILE *file) { 135 sampledb_t *sampledb = (sampledb_t *) db; 136 137 REQUIRE(VALID_SAMPLEDB(sampledb)); 138 139 return (dns_db_serialize(sampledb->rbtdb, version, file)); 140 } 141 142 static isc_result_t 143 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename, 144 dns_masterformat_t masterformat) 145 { 146 147 UNUSED(db); 148 UNUSED(version); 149 UNUSED(filename); 150 UNUSED(masterformat); 151 152 fatal_error("current implementation should never call dump()"); 153 154 /* Not reached */ 155 return (ISC_R_SUCCESS); 156 } 157 158 static void 159 currentversion(dns_db_t *db, dns_dbversion_t **versionp) { 160 sampledb_t *sampledb = (sampledb_t *)db; 161 162 REQUIRE(VALID_SAMPLEDB(sampledb)); 163 164 dns_db_currentversion(sampledb->rbtdb, versionp); 165 } 166 167 static isc_result_t 168 newversion(dns_db_t *db, dns_dbversion_t **versionp) { 169 sampledb_t *sampledb = (sampledb_t *)db; 170 171 REQUIRE(VALID_SAMPLEDB(sampledb)); 172 173 return (dns_db_newversion(sampledb->rbtdb, versionp)); 174 } 175 176 static void 177 attachversion(dns_db_t *db, dns_dbversion_t *source, 178 dns_dbversion_t **targetp) 179 { 180 sampledb_t *sampledb = (sampledb_t *)db; 181 182 REQUIRE(VALID_SAMPLEDB(sampledb)); 183 184 dns_db_attachversion(sampledb->rbtdb, source, targetp); 185 } 186 187 static void 188 closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) { 189 sampledb_t *sampledb = (sampledb_t *)db; 190 191 REQUIRE(VALID_SAMPLEDB(sampledb)); 192 193 dns_db_closeversion(sampledb->rbtdb, versionp, commit); 194 } 195 196 static isc_result_t 197 findnode(dns_db_t *db, const dns_name_t *name, bool create, 198 dns_dbnode_t **nodep) 199 { 200 sampledb_t *sampledb = (sampledb_t *) db; 201 202 REQUIRE(VALID_SAMPLEDB(sampledb)); 203 204 return (dns_db_findnode(sampledb->rbtdb, name, create, nodep)); 205 } 206 207 static isc_result_t 208 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 209 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 210 dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, 211 dns_rdataset_t *sigrdataset) 212 { 213 sampledb_t *sampledb = (sampledb_t *) db; 214 215 REQUIRE(VALID_SAMPLEDB(sampledb)); 216 217 return (dns_db_find(sampledb->rbtdb, name, version, type, 218 options, now, nodep, foundname, 219 rdataset, sigrdataset)); 220 } 221 222 static isc_result_t 223 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options, 224 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname, 225 dns_name_t *dcname, dns_rdataset_t *rdataset, 226 dns_rdataset_t *sigrdataset) 227 { 228 sampledb_t *sampledb = (sampledb_t *) db; 229 230 REQUIRE(VALID_SAMPLEDB(sampledb)); 231 232 return (dns_db_findzonecut(sampledb->rbtdb, name, options, 233 now, nodep, foundname, dcname, rdataset, 234 sigrdataset)); 235 } 236 237 static void 238 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) { 239 sampledb_t *sampledb = (sampledb_t *) db; 240 241 REQUIRE(VALID_SAMPLEDB(sampledb)); 242 243 dns_db_attachnode(sampledb->rbtdb, source, targetp); 244 245 } 246 247 static void 248 detachnode(dns_db_t *db, dns_dbnode_t **targetp) { 249 sampledb_t *sampledb = (sampledb_t *) db; 250 251 REQUIRE(VALID_SAMPLEDB(sampledb)); 252 253 dns_db_detachnode(sampledb->rbtdb, targetp); 254 } 255 256 static isc_result_t 257 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) { 258 sampledb_t *sampledb = (sampledb_t *) db; 259 260 REQUIRE(VALID_SAMPLEDB(sampledb)); 261 262 return (dns_db_expirenode(sampledb->rbtdb, node, now)); 263 } 264 265 static void 266 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) { 267 sampledb_t *sampledb = (sampledb_t *) db; 268 269 REQUIRE(VALID_SAMPLEDB(sampledb)); 270 271 dns_db_printnode(sampledb->rbtdb, node, out); 272 } 273 274 static isc_result_t 275 createiterator(dns_db_t *db, unsigned int options, 276 dns_dbiterator_t **iteratorp) 277 { 278 sampledb_t *sampledb = (sampledb_t *) db; 279 280 REQUIRE(VALID_SAMPLEDB(sampledb)); 281 282 return (dns_db_createiterator(sampledb->rbtdb, options, iteratorp)); 283 } 284 285 static isc_result_t 286 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 287 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, 288 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 289 { 290 sampledb_t *sampledb = (sampledb_t *) db; 291 292 REQUIRE(VALID_SAMPLEDB(sampledb)); 293 294 return (dns_db_findrdataset(sampledb->rbtdb, node, version, type, 295 covers, now, rdataset, sigrdataset)); 296 } 297 298 static isc_result_t 299 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 300 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) 301 { 302 sampledb_t *sampledb = (sampledb_t *) db; 303 304 REQUIRE(VALID_SAMPLEDB(sampledb)); 305 306 return (dns_db_allrdatasets(sampledb->rbtdb, node, version, 307 now, iteratorp)); 308 } 309 310 static isc_result_t 311 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 312 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 313 dns_rdataset_t *addedrdataset) 314 { 315 sampledb_t *sampledb = (sampledb_t *) db; 316 isc_result_t result; 317 dns_fixedname_t name; 318 319 REQUIRE(VALID_SAMPLEDB(sampledb)); 320 321 dns_fixedname_init(&name); 322 CHECK(dns_db_addrdataset(sampledb->rbtdb, node, version, now, 323 rdataset, options, addedrdataset)); 324 if (rdataset->type == dns_rdatatype_a || 325 rdataset->type == dns_rdatatype_aaaa) { 326 CHECK(sample_name_fromnode(node, dns_fixedname_name(&name))); 327 CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), 328 rdataset, DNS_DIFFOP_ADD)); 329 } 330 331 cleanup: 332 return (result); 333 } 334 335 static isc_result_t 336 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 337 dns_rdataset_t *rdataset, unsigned int options, 338 dns_rdataset_t *newrdataset) 339 { 340 sampledb_t *sampledb = (sampledb_t *) db; 341 isc_result_t result; 342 dns_fixedname_t name; 343 344 REQUIRE(VALID_SAMPLEDB(sampledb)); 345 346 dns_fixedname_init(&name); 347 result = dns_db_subtractrdataset(sampledb->rbtdb, node, version, 348 rdataset, options, newrdataset); 349 if (result != ISC_R_SUCCESS && result != DNS_R_NXRRSET) 350 goto cleanup; 351 352 if (rdataset->type == dns_rdatatype_a || 353 rdataset->type == dns_rdatatype_aaaa) { 354 CHECK(sample_name_fromnode(node, dns_fixedname_name(&name))); 355 CHECK(syncptrs(sampledb->inst, dns_fixedname_name(&name), 356 rdataset, DNS_DIFFOP_DEL)); 357 } 358 359 cleanup: 360 return (result); 361 } 362 363 /* 364 * deleterdataset() function is not used during DNS update processing so syncptr 365 * implementation is left as an exercise to the reader. 366 */ 367 static isc_result_t 368 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 369 dns_rdatatype_t type, dns_rdatatype_t covers) 370 { 371 sampledb_t *sampledb = (sampledb_t *) db; 372 373 REQUIRE(VALID_SAMPLEDB(sampledb)); 374 375 return (dns_db_deleterdataset(sampledb->rbtdb, node, version, 376 type, covers)); 377 } 378 379 static bool 380 issecure(dns_db_t *db) { 381 sampledb_t *sampledb = (sampledb_t *) db; 382 383 REQUIRE(VALID_SAMPLEDB(sampledb)); 384 385 return (dns_db_issecure(sampledb->rbtdb)); 386 } 387 388 static unsigned int 389 nodecount(dns_db_t *db) { 390 sampledb_t *sampledb = (sampledb_t *) db; 391 392 REQUIRE(VALID_SAMPLEDB(sampledb)); 393 394 return (dns_db_nodecount(sampledb->rbtdb)); 395 } 396 397 /* 398 * The database does not need to be loaded from disk or written to disk. 399 * Always return true. 400 */ 401 static bool 402 ispersistent(dns_db_t *db) { 403 UNUSED(db); 404 405 return (true); 406 } 407 408 static void 409 overmem(dns_db_t *db, bool over) { 410 sampledb_t *sampledb = (sampledb_t *) db; 411 412 REQUIRE(VALID_SAMPLEDB(sampledb)); 413 414 dns_db_overmem(sampledb->rbtdb, over); 415 } 416 417 static void 418 settask(dns_db_t *db, isc_task_t *task) { 419 sampledb_t *sampledb = (sampledb_t *) db; 420 421 REQUIRE(VALID_SAMPLEDB(sampledb)); 422 423 dns_db_settask(sampledb->rbtdb, task); 424 } 425 426 static isc_result_t 427 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) { 428 sampledb_t *sampledb = (sampledb_t *) db; 429 430 REQUIRE(VALID_SAMPLEDB(sampledb)); 431 432 return (dns_db_getoriginnode(sampledb->rbtdb, nodep)); 433 } 434 435 static void 436 transfernode(dns_db_t *db, dns_dbnode_t **sourcep, dns_dbnode_t **targetp) { 437 sampledb_t *sampledb = (sampledb_t *) db; 438 439 REQUIRE(VALID_SAMPLEDB(sampledb)); 440 441 dns_db_transfernode(sampledb->rbtdb, sourcep, targetp); 442 443 } 444 445 static isc_result_t 446 getnsec3parameters(dns_db_t *db, dns_dbversion_t *version, 447 dns_hash_t *hash, uint8_t *flags, 448 uint16_t *iterations, 449 unsigned char *salt, size_t *salt_length) 450 { 451 sampledb_t *sampledb = (sampledb_t *) db; 452 453 REQUIRE(VALID_SAMPLEDB(sampledb)); 454 455 return (dns_db_getnsec3parameters(sampledb->rbtdb, version, 456 hash, flags, iterations, 457 salt, salt_length)); 458 459 } 460 461 static isc_result_t 462 findnsec3node(dns_db_t *db, const dns_name_t *name, bool create, 463 dns_dbnode_t **nodep) 464 { 465 sampledb_t *sampledb = (sampledb_t *) db; 466 467 REQUIRE(VALID_SAMPLEDB(sampledb)); 468 469 return (dns_db_findnsec3node(sampledb->rbtdb, name, create, nodep)); 470 } 471 472 static isc_result_t 473 setsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, isc_stdtime_t resign) { 474 sampledb_t *sampledb = (sampledb_t *) db; 475 476 REQUIRE(VALID_SAMPLEDB(sampledb)); 477 478 return (dns_db_setsigningtime(sampledb->rbtdb, rdataset, resign)); 479 } 480 481 static isc_result_t 482 getsigningtime(dns_db_t *db, dns_rdataset_t *rdataset, dns_name_t *name) { 483 sampledb_t *sampledb = (sampledb_t *) db; 484 485 REQUIRE(VALID_SAMPLEDB(sampledb)); 486 487 return (dns_db_getsigningtime(sampledb->rbtdb, rdataset, name)); 488 } 489 490 static void 491 resigned(dns_db_t *db, dns_rdataset_t *rdataset, dns_dbversion_t *version) { 492 sampledb_t *sampledb = (sampledb_t *) db; 493 494 REQUIRE(VALID_SAMPLEDB(sampledb)); 495 496 dns_db_resigned(sampledb->rbtdb, rdataset, version); 497 } 498 499 static bool 500 isdnssec(dns_db_t *db) { 501 sampledb_t *sampledb = (sampledb_t *) db; 502 503 REQUIRE(VALID_SAMPLEDB(sampledb)); 504 505 return (dns_db_isdnssec(sampledb->rbtdb)); 506 } 507 508 static dns_stats_t * 509 getrrsetstats(dns_db_t *db) { 510 sampledb_t *sampledb = (sampledb_t *) db; 511 512 REQUIRE(VALID_SAMPLEDB(sampledb)); 513 514 return (dns_db_getrrsetstats(sampledb->rbtdb)); 515 516 } 517 518 static isc_result_t 519 findnodeext(dns_db_t *db, const dns_name_t *name, 520 bool create, dns_clientinfomethods_t *methods, 521 dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) 522 { 523 sampledb_t *sampledb = (sampledb_t *) db; 524 525 REQUIRE(VALID_SAMPLEDB(sampledb)); 526 527 return (dns_db_findnodeext(sampledb->rbtdb, name, create, 528 methods, clientinfo, nodep)); 529 } 530 531 static isc_result_t 532 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 533 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 534 dns_dbnode_t **nodep, dns_name_t *foundname, 535 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 536 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) 537 { 538 sampledb_t *sampledb = (sampledb_t *) db; 539 540 REQUIRE(VALID_SAMPLEDB(sampledb)); 541 542 return (dns_db_findext(sampledb->rbtdb, name, version, type, 543 options, now, nodep, foundname, methods, 544 clientinfo, rdataset, sigrdataset)); 545 } 546 547 static isc_result_t 548 setcachestats(dns_db_t *db, isc_stats_t *stats) { 549 sampledb_t *sampledb = (sampledb_t *) db; 550 551 REQUIRE(VALID_SAMPLEDB(sampledb)); 552 553 return (dns_db_setcachestats(sampledb->rbtdb, stats)); 554 } 555 556 static size_t 557 hashsize(dns_db_t *db) { 558 sampledb_t *sampledb = (sampledb_t *) db; 559 560 REQUIRE(VALID_SAMPLEDB(sampledb)); 561 562 return (dns_db_hashsize(sampledb->rbtdb)); 563 } 564 565 /* 566 * DB interface definition. Database driver uses this structure to 567 * determine which implementation of dns_db_*() function to call. 568 */ 569 static dns_dbmethods_t sampledb_methods = { 570 attach, 571 detach, 572 beginload, 573 endload, 574 serialize, 575 dump, 576 currentversion, 577 newversion, 578 attachversion, 579 closeversion, 580 findnode, 581 find, 582 findzonecut, 583 attachnode, 584 detachnode, 585 expirenode, 586 printnode, 587 createiterator, 588 findrdataset, 589 allrdatasets, 590 addrdataset, 591 subtractrdataset, 592 deleterdataset, 593 issecure, 594 nodecount, 595 ispersistent, 596 overmem, 597 settask, 598 getoriginnode, 599 transfernode, 600 getnsec3parameters, 601 findnsec3node, 602 setsigningtime, 603 getsigningtime, 604 resigned, 605 isdnssec, 606 getrrsetstats, 607 NULL, /* rpz_attach */ 608 NULL, /* rpz_ready */ 609 findnodeext, 610 findext, 611 setcachestats, 612 hashsize, 613 NULL, /* nodefullname */ 614 NULL, /* getsize */ 615 NULL, /* setservestalettl */ 616 NULL, /* getservestalettl */ 617 NULL /* setgluecachestats */ 618 }; 619 620 /* Auxiliary driver functions. */ 621 622 /* 623 * Auxiliary functions add_*() create minimal database which can be loaded. 624 * This is necessary because this driver create empty 'fake' zone which 625 * is not loaded from disk so there is no way for user to supply SOA, NS and A 626 * records. 627 * 628 * Following functions were copied from BIND 9.10.2rc1 named/server.c, 629 * credit goes to ISC. 630 */ 631 static isc_result_t 632 add_soa(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 633 const dns_name_t *origin, const dns_name_t *contact) 634 { 635 dns_dbnode_t *node = NULL; 636 dns_rdata_t rdata = DNS_RDATA_INIT; 637 dns_rdatalist_t rdatalist; 638 dns_rdataset_t rdataset; 639 isc_result_t result; 640 unsigned char buf[DNS_SOA_BUFFERSIZE]; 641 642 dns_rdataset_init(&rdataset); 643 dns_rdatalist_init(&rdatalist); 644 CHECK(dns_soa_buildrdata(origin, contact, dns_db_class(db), 645 0, 28800, 7200, 604800, 86400, buf, &rdata)); 646 rdatalist.type = rdata.type; 647 rdatalist.covers = 0; 648 rdatalist.rdclass = rdata.rdclass; 649 rdatalist.ttl = 86400; 650 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 651 CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); 652 CHECK(dns_db_findnode(db, name, true, &node)); 653 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 654 cleanup: 655 if (node != NULL) 656 dns_db_detachnode(db, &node); 657 return (result); 658 } 659 660 661 static isc_result_t 662 add_ns(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 663 const dns_name_t *nsname) 664 { 665 dns_dbnode_t *node = NULL; 666 dns_rdata_ns_t ns; 667 dns_rdata_t rdata = DNS_RDATA_INIT; 668 dns_rdatalist_t rdatalist; 669 dns_rdataset_t rdataset; 670 isc_result_t result; 671 isc_buffer_t b; 672 unsigned char buf[DNS_NAME_MAXWIRE]; 673 674 isc_buffer_init(&b, buf, sizeof(buf)); 675 676 dns_rdataset_init(&rdataset); 677 dns_rdatalist_init(&rdatalist); 678 ns.common.rdtype = dns_rdatatype_ns; 679 ns.common.rdclass = dns_db_class(db); 680 ns.mctx = NULL; 681 dns_name_init(&ns.name, NULL); 682 dns_name_clone(nsname, &ns.name); 683 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_ns, 684 &ns, &b)); 685 rdatalist.type = rdata.type; 686 rdatalist.covers = 0; 687 rdatalist.rdclass = rdata.rdclass; 688 rdatalist.ttl = 86400; 689 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 690 CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); 691 CHECK(dns_db_findnode(db, name, true, &node)); 692 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 693 cleanup: 694 if (node != NULL) 695 dns_db_detachnode(db, &node); 696 return (result); 697 } 698 699 static isc_result_t 700 add_a(dns_db_t *db, dns_dbversion_t *version, const dns_name_t *name, 701 struct in_addr addr) 702 { 703 dns_dbnode_t *node = NULL; 704 dns_rdata_in_a_t a; 705 dns_rdata_t rdata = DNS_RDATA_INIT; 706 dns_rdatalist_t rdatalist; 707 dns_rdataset_t rdataset; 708 isc_result_t result; 709 isc_buffer_t b; 710 unsigned char buf[DNS_NAME_MAXWIRE]; 711 712 isc_buffer_init(&b, buf, sizeof(buf)); 713 714 dns_rdataset_init(&rdataset); 715 dns_rdatalist_init(&rdatalist); 716 a.common.rdtype = dns_rdatatype_a; 717 a.common.rdclass = dns_db_class(db); 718 a.in_addr = addr; 719 CHECK(dns_rdata_fromstruct(&rdata, dns_db_class(db), dns_rdatatype_a, 720 &a, &b)); 721 rdatalist.type = rdata.type; 722 rdatalist.covers = 0; 723 rdatalist.rdclass = rdata.rdclass; 724 rdatalist.ttl = 86400; 725 ISC_LIST_APPEND(rdatalist.rdata, &rdata, link); 726 CHECK(dns_rdatalist_tordataset(&rdatalist, &rdataset)); 727 CHECK(dns_db_findnode(db, name, true, &node)); 728 CHECK(dns_db_addrdataset(db, node, version, 0, &rdataset, 0, NULL)); 729 cleanup: 730 if (node != NULL) 731 dns_db_detachnode(db, &node); 732 return (result); 733 } 734 735 /* 736 * Driver-specific implementation of dns_db_create(). 737 * 738 * @param[in] argv Database-specific parameters from dns_db_create(). 739 * @param[in] driverarg Driver-specific parameter from dns_db_register(). 740 */ 741 isc_result_t 742 create_db(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type, 743 dns_rdataclass_t rdclass, unsigned int argc, char *argv[], 744 void *driverarg, dns_db_t **dbp) 745 { 746 sampledb_t *sampledb = NULL; 747 isc_result_t result; 748 dns_dbversion_t *version = NULL; 749 struct in_addr a_addr; 750 751 REQUIRE(type == dns_dbtype_zone); 752 REQUIRE(rdclass == dns_rdataclass_in); 753 REQUIRE(argc == 0); 754 REQUIRE(argv != NULL); 755 REQUIRE(driverarg != NULL); /* pointer to driver instance */ 756 REQUIRE(dbp != NULL && *dbp == NULL); 757 758 UNUSED(driverarg); /* no driver-specific configuration */ 759 760 a_addr.s_addr = 0x0100007fU; 761 762 CHECKED_MEM_GET_PTR(mctx, sampledb); 763 ZERO_PTR(sampledb); 764 765 isc_mem_attach(mctx, &sampledb->common.mctx); 766 dns_name_init(&sampledb->common.origin, NULL); 767 768 sampledb->common.magic = DNS_DB_MAGIC; 769 sampledb->common.impmagic = SAMPLEDB_MAGIC; 770 771 sampledb->common.methods = &sampledb_methods; 772 sampledb->common.attributes = 0; 773 sampledb->common.rdclass = rdclass; 774 775 CHECK(dns_name_dupwithoffsets(origin, mctx, &sampledb->common.origin)); 776 777 isc_refcount_init(&sampledb->refs, 1); 778 779 /* Translate instance name to instance pointer. */ 780 sampledb->inst = driverarg; 781 782 /* Create internal instance of RBT DB implementation from BIND. */ 783 CHECK(dns_db_create(mctx, "rbt", origin, dns_dbtype_zone, 784 dns_rdataclass_in, 0, NULL, &sampledb->rbtdb)); 785 786 /* Create fake SOA, NS, and A records to make database loadable. */ 787 CHECK(dns_db_newversion(sampledb->rbtdb, &version)); 788 CHECK(add_soa(sampledb->rbtdb, version, origin, origin, origin)); 789 CHECK(add_ns(sampledb->rbtdb, version, origin, origin)); 790 CHECK(add_a(sampledb->rbtdb, version, origin, a_addr)); 791 dns_db_closeversion(sampledb->rbtdb, &version, true); 792 793 *dbp = (dns_db_t *)sampledb; 794 795 return (ISC_R_SUCCESS); 796 797 cleanup: 798 if (sampledb != NULL) { 799 if (dns_name_dynamic(&sampledb->common.origin)) 800 dns_name_free(&sampledb->common.origin, mctx); 801 802 isc_mem_putanddetach(&sampledb->common.mctx, sampledb, 803 sizeof(*sampledb)); 804 } 805 806 return (result); 807 } 808