1/* 2 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl. 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the 6 * above copyright notice and this permission notice appear in all 7 * copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET 10 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 11 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 12 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 14 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 15 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 16 * USE OR PERFORMANCE OF THIS SOFTWARE. 17 * 18 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was 19 * conceived and contributed by Rob Butler. 20 * 21 * Permission to use, copy, modify, and distribute this software for any 22 * purpose with or without fee is hereby granted, provided that the 23 * above copyright notice and this permission notice appear in all 24 * copies. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER 27 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 29 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 30 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 31 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 32 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 33 * USE OR PERFORMANCE OF THIS SOFTWARE. 34 */ 35 36/* 37 * Copyright (C) 1999-2001 Internet Software Consortium. 38 * 39 * Permission to use, copy, modify, and distribute this software for any 40 * purpose with or without fee is hereby granted, provided that the above 41 * copyright notice and this permission notice appear in all copies. 42 * 43 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM 44 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 46 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 47 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 48 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 49 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 50 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 51 */ 52 53#ifdef DLZ_BDB 54 55#include <config.h> 56#include <stdio.h> 57#include <string.h> 58#include <stdlib.h> 59 60#include <dns/log.h> 61#include <dns/sdlz.h> 62#include <dns/result.h> 63 64#include <isc/mem.h> 65#include <isc/print.h> 66#include <isc/result.h> 67#include <isc/util.h> 68 69#include <named/globals.h> 70 71#include <dlz/dlz_bdbhpt_driver.h> 72 73#include <db.h> 74 75static dns_sdlzimplementation_t *dlz_bdbhpt = NULL; 76 77/* should the bdb driver use threads. */ 78#ifdef ISC_PLATFORM_USETHREADS 79#define bdbhpt_threads DB_THREAD 80#else 81#define bdbhpt_threads 0 82#endif 83 84/* bdbhpt database names */ 85#define dlz_data "dns_data" 86#define dlz_zone "dns_zone" 87#define dlz_xfr "dns_xfr" 88#define dlz_client "dns_client" 89 90 /* This structure contains all the Berkeley DB handles 91 * for this instance of the bdbhpt driver. 92 */ 93 94typedef struct bdbhpt_instance { 95 DB_ENV *dbenv; /*%< bdbhpt environment */ 96 DB *data; /*%< dns_data database handle */ 97 DB *zone; /*%< zone database handle */ 98 DB *xfr; /*%< zone xfr database handle */ 99 DB *client; /*%< client database handle */ 100 isc_mem_t *mctx; /*%< memory context */ 101 102} bdbhpt_instance_t; 103 104typedef struct bdbhpt_parsed_data { 105 char *host; 106 char *type; 107 int ttl; 108 char *data; 109} bdbhpt_parsed_data_t; 110 111 112/* forward reference */ 113 114static isc_result_t 115bdbhpt_findzone(void *driverarg, void *dbdata, const char *name); 116 117/*% 118 * Reverses a string in place. 119 */ 120 121static char *bdbhpt_strrev(char *str) 122{ 123 char *p1, *p2; 124 125 if (! str || ! *str) 126 return str; 127 for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) 128 { 129 *p1 ^= *p2; 130 *p2 ^= *p1; 131 *p1 ^= *p2; 132 } 133 return str; 134} 135 136/*% 137 * Parses the DBT from the Berkeley DB into a parsed_data record 138 * The parsed_data record should be allocated before and passed into the 139 * bdbhpt_parse_data function. The char (type & data) fields should not 140 * be "free"d as that memory is part of the DBT data field. It will be 141 * "free"d when the DBT is freed. 142 */ 143 144static isc_result_t 145bdbhpt_parse_data(char *in, bdbhpt_parsed_data_t *pd) { 146 147 char *endp, *ttlStr; 148 char *tmp = in; 149 char *lastchar = (char *) &tmp[strlen(tmp)]; 150 151 /*% 152 * String should be formated as: 153 * replication_id 154 * (a space) 155 * host_name 156 * (a space) 157 * ttl 158 * (a space) 159 * type 160 * (a space) 161 * remaining data 162 * 163 * examples: 164 * 165 * 9191 host 10 A 127.0.0.1 166 * server1_212 host 10 A 127.0.0.2 167 * {xxxx-xxxx-xxxx-xxxx-xxxx} host 10 MX 20 mail.example.com 168 */ 169 170 /* 171 * we don't need the replication id, so don't 172 * bother saving a pointer to it. 173 */ 174 175 /* find space after replication id */ 176 tmp = strchr(tmp, ' '); 177 /* verify we found a space */ 178 if (tmp == NULL) 179 return ISC_R_FAILURE; 180 /* make sure it is safe to increment pointer */ 181 if (++tmp > lastchar) 182 return ISC_R_FAILURE; 183 184 /* save pointer to host */ 185 pd->host = tmp; 186 187 /* find space after host and change it to a '\0' */ 188 tmp = strchr(tmp, ' '); 189 /* verify we found a space */ 190 if (tmp == NULL) 191 return ISC_R_FAILURE; 192 /* change the space to a null (string terminator) */ 193 tmp[0] = '\0'; 194 /* make sure it is safe to increment pointer */ 195 if (++tmp > lastchar) 196 return ISC_R_FAILURE; 197 198 /* save pointer to ttl string */ 199 ttlStr = tmp; 200 201 /* find space after ttl and change it to a '\0' */ 202 tmp = strchr(tmp, ' '); 203 /* verify we found a space */ 204 if (tmp == NULL) 205 return ISC_R_FAILURE; 206 /* change the space to a null (string terminator) */ 207 tmp[0] = '\0'; 208 /* make sure it is safe to increment pointer */ 209 if (++tmp > lastchar) 210 return ISC_R_FAILURE; 211 212 /* save pointer to dns type */ 213 pd->type = tmp; 214 215 /* find space after type and change it to a '\0' */ 216 tmp = strchr(tmp, ' '); 217 /* verify we found a space */ 218 if (tmp == NULL) 219 return ISC_R_FAILURE; 220 /* change the space to a null (string terminator) */ 221 tmp[0] = '\0'; 222 /* make sure it is safe to increment pointer */ 223 if (++tmp > lastchar) 224 return ISC_R_FAILURE; 225 226 /* save pointer to remainder of DNS data */ 227 pd->data = tmp; 228 229 /* convert ttl string to integer */ 230 pd->ttl = strtol(ttlStr, &endp, 10); 231 if (*endp != '\0' || pd->ttl < 0) { 232 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 233 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 234 "bdbhpt driver ttl must be a postive number"); 235 return ISC_R_FAILURE; 236 } 237 238 /* if we get this far everything should have worked. */ 239 return ISC_R_SUCCESS; 240} 241 242/* 243 * DLZ methods 244 */ 245 246static isc_result_t 247bdbhpt_allowzonexfr(void *driverarg, void *dbdata, const char *name, 248 const char *client) 249{ 250 isc_result_t result; 251 bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata; 252 DBT key, data; 253 254 /* check to see if we are authoritative for the zone first. */ 255 result = bdbhpt_findzone(driverarg, dbdata, name); 256 if (result != ISC_R_SUCCESS) 257 return (ISC_R_NOTFOUND); 258 259 memset(&key, 0, sizeof(DBT)); 260 key.flags = DB_DBT_MALLOC; 261 key.data = strdup(name); 262 if (key.data == NULL) { 263 result = ISC_R_NOMEMORY; 264 goto xfr_cleanup; 265 } 266 key.size = strlen(key.data); 267 268 memset(&data, 0, sizeof(DBT)); 269 data.flags = DB_DBT_MALLOC; 270 data.data = strdup(client); 271 if (data.data == NULL) { 272 result = ISC_R_NOMEMORY; 273 goto xfr_cleanup; 274 } 275 data.size = strlen(data.data); 276 277 switch(db->client->get(db->client, NULL, &key, &data, DB_GET_BOTH)) { 278 case DB_NOTFOUND: 279 result = ISC_R_NOTFOUND; 280 break; 281 case 0: 282 result = ISC_R_SUCCESS; 283 break; 284 default: 285 result = ISC_R_FAILURE; 286 } 287 288 xfr_cleanup: 289 290 /* free any memory duplicate string in the key field */ 291 if (key.data != NULL) 292 free(key.data); 293 294 /* free any memory allocated to the data field. */ 295 if (data.data != NULL) 296 free(data.data); 297 298 return result; 299 300} 301 302/*% 303 * BDB does not allow a secondary index on a database that allows 304 * duplicates. We have a few options: 305 * 306 * 1) kill speed by having lookup method use a secondary db which 307 * is associated to the primary DB with the DNS data. Then have 308 * another secondary db for zone transfer which also points to 309 * the dns_data primary. NO - The point of this driver is 310 * lookup performance. 311 * 312 * 2) Blow up database size by storing DNS data twice. Once for 313 * the lookup (dns_data) database, and a second time for the zone 314 * transfer (dns_xfr) database. NO - That would probably require 315 * a larger cache to provide good performance. Also, that would 316 * make the DB larger on disk potentially slowing it as well. 317 * 318 * 3) Loop through the dns_xfr database with a cursor to get 319 * all the different hosts in a zone. Then use the zone & host 320 * together to lookup the data in the dns_data database. YES - 321 * This may slow down zone xfr's a little, but that's ok they 322 * don't happen as often and don't need to be as fast. We can 323 * also use this table when deleting a zone (The BDB driver 324 * is read only - the delete would be used during replication 325 * updates by a separate process). 326 */ 327 328static isc_result_t 329bdbhpt_allnodes(const char *zone, void *driverarg, void *dbdata, 330 dns_sdlzallnodes_t *allnodes) 331{ 332 333 isc_result_t result = ISC_R_NOTFOUND; 334 bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata; 335 DBC *xfr_cursor = NULL; 336 DBC *dns_cursor = NULL; 337 DBT xfr_key, xfr_data, dns_key, dns_data; 338 int xfr_flags; 339 int dns_flags; 340 int bdbhptres; 341 bdbhpt_parsed_data_t pd; 342 char *tmp = NULL, *tmp_zone, *tmp_zone_host = NULL; 343 344 UNUSED(driverarg); 345 346 memset(&xfr_key, 0, sizeof(DBT)); 347 memset(&xfr_data, 0, sizeof(DBT)); 348 memset(&dns_key, 0, sizeof(DBT)); 349 memset(&dns_data, 0, sizeof(DBT)); 350 351 xfr_key.data = tmp_zone = strdup(zone); 352 if (xfr_key.data == NULL) 353 return (ISC_R_NOMEMORY); 354 355 xfr_key.size = strlen(xfr_key.data); 356 357 /* get a cursor to loop through dns_xfr table */ 358 if (db->xfr->cursor(db->xfr, NULL, &xfr_cursor, 0) != 0) { 359 result = ISC_R_FAILURE; 360 goto allnodes_cleanup; 361 } 362 363 /* get a cursor to loop through dns_data table */ 364 if (db->data->cursor(db->data, NULL, &dns_cursor, 0) != 0) { 365 result = ISC_R_FAILURE; 366 goto allnodes_cleanup; 367 } 368 369 xfr_flags = DB_SET; 370 371 /* loop through xfr table for specified zone. */ 372 while ((bdbhptres = xfr_cursor->c_get(xfr_cursor, &xfr_key, &xfr_data, 373 xfr_flags)) == 0) { 374 375 xfr_flags = DB_NEXT_DUP; 376 377 /* +1 to allow for space between zone and host names */ 378 dns_key.size = xfr_data.size + xfr_key.size + 1; 379 380 /* +1 to allow for null term at end of string. */ 381 dns_key.data = tmp_zone_host = malloc(dns_key.size + 1); 382 if (dns_key.data == NULL) 383 goto allnodes_cleanup; 384 385 /* 386 * construct search key for dns_data. 387 * zone_name(a space)host_name 388 */ 389 strcpy(dns_key.data, zone); 390 strcat(dns_key.data, " "); 391 strncat(dns_key.data, xfr_data.data, xfr_data.size); 392 393 dns_flags = DB_SET; 394 395 while ((bdbhptres = dns_cursor->c_get(dns_cursor, &dns_key, 396 &dns_data, 397 dns_flags)) == 0) { 398 399 dns_flags = DB_NEXT_DUP; 400 401 /* +1 to allow for null term at end of string. */ 402 tmp = realloc(tmp, dns_data.size + 1); 403 if (tmp == NULL) 404 goto allnodes_cleanup; 405 406 /* copy data to tmp string, and append null term. */ 407 strncpy(tmp, dns_data.data, dns_data.size); 408 tmp[dns_data.size] = '\0'; 409 410 /* split string into dns data parts. */ 411 if (bdbhpt_parse_data(tmp, &pd) != ISC_R_SUCCESS) 412 goto allnodes_cleanup; 413 414 result = dns_sdlz_putnamedrr(allnodes, pd.host, 415 pd.type, pd.ttl, pd.data); 416 if (result != ISC_R_SUCCESS) 417 goto allnodes_cleanup; 418 419 } /* end inner while loop */ 420 421 /* clean up memory */ 422 if (tmp_zone_host != NULL) { 423 free(tmp_zone_host); 424 tmp_zone_host = NULL; 425 } 426 } /* end outer while loop */ 427 428 allnodes_cleanup: 429 430 /* free any memory */ 431 if (tmp != NULL) 432 free(tmp); 433 434 if (tmp_zone_host != NULL) 435 free(tmp_zone_host); 436 437 if (tmp_zone != NULL) 438 free(tmp_zone); 439 440 /* get rid of cursors */ 441 if (xfr_cursor != NULL) 442 xfr_cursor->c_close(xfr_cursor); 443 444 if (dns_cursor != NULL) 445 dns_cursor->c_close(dns_cursor); 446 447 return result; 448} 449 450/*% 451 * Performs bdbhpt cleanup. 452 * Used by bdbhpt_create if there is an error starting up. 453 * Used by bdbhpt_destroy when the driver is shutting down. 454 */ 455 456static void 457bdbhpt_cleanup(bdbhpt_instance_t *db) { 458 459 isc_mem_t *mctx; 460 461 /* close databases */ 462 if (db->data != NULL) 463 db->data->close(db->data, 0); 464 if (db->xfr != NULL) 465 db->xfr->close(db->xfr, 0); 466 if (db->zone != NULL) 467 db->zone->close(db->zone, 0); 468 if (db->client != NULL) 469 db->client->close(db->client, 0); 470 471 /* close environment */ 472 if (db->dbenv != NULL) 473 db->dbenv->close(db->dbenv, 0); 474 475 /* cleanup memory */ 476 if (db->mctx != NULL) { 477 /* save mctx for later */ 478 mctx = db->mctx; 479 /* return, and detach the memory */ 480 isc_mem_put(mctx, db, sizeof(bdbhpt_instance_t)); 481 isc_mem_detach(&mctx); 482 } 483} 484 485static isc_result_t 486bdbhpt_findzone(void *driverarg, void *dbdata, const char *name) 487{ 488 489 isc_result_t result; 490 bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata; 491 DBT key, data; 492 493 UNUSED(driverarg); 494 495 memset(&key, 0, sizeof(DBT)); 496 memset(&data, 0, sizeof(DBT)); 497 data.flags = DB_DBT_MALLOC; 498 499 key.data = strdup(name); 500 501 if (key.data == NULL) 502 return (ISC_R_NOMEMORY); 503 504 /* 505 * reverse string to take advantage of BDB locality of reference 506 * if we need futher lookups because the zone doesn't match the 507 * first time. 508 */ 509 key.data = bdbhpt_strrev(key.data); 510 key.size = strlen(key.data); 511 512 switch(db->zone->get(db->zone, NULL, &key, &data, 0)) { 513 case DB_NOTFOUND: 514 result = ISC_R_NOTFOUND; 515 break; 516 case 0: 517 result = ISC_R_SUCCESS; 518 break; 519 default: 520 result = ISC_R_FAILURE; 521 } 522 523 /* free any memory duplicate string in the key field */ 524 if (key.data != NULL) 525 free(key.data); 526 527 /* free any memory allocated to the data field. */ 528 if (data.data != NULL) 529 free(data.data); 530 531 return result; 532} 533 534static isc_result_t 535bdbhpt_lookup(const char *zone, const char *name, void *driverarg, 536 void *dbdata, dns_sdlzlookup_t *lookup) 537{ 538 539 isc_result_t result = ISC_R_NOTFOUND; 540 bdbhpt_instance_t *db = (bdbhpt_instance_t *) dbdata; 541 DBC *data_cursor = NULL; 542 DBT key, data; 543 int bdbhptres; 544 int flags; 545 546 bdbhpt_parsed_data_t pd; 547 char *tmp = NULL; 548 char *keyStr = NULL; 549 550 UNUSED(driverarg); 551 552 memset(&key, 0, sizeof(DBT)); 553 memset(&data, 0, sizeof(DBT)); 554 555 key.size = strlen(zone) + strlen(name) + 1; 556 557 /* allocate mem for key */ 558 key.data = keyStr = malloc((key.size + 1) * sizeof(char)); 559 560 if (keyStr == NULL) 561 return ISC_R_NOMEMORY; 562 563 strcpy(keyStr, zone); 564 strcat(keyStr, " "); 565 strcat(keyStr, name); 566 567 /* get a cursor to loop through data */ 568 if (db->data->cursor(db->data, NULL, &data_cursor, 0) != 0) { 569 result = ISC_R_FAILURE; 570 goto lookup_cleanup; 571 } 572 573 result = ISC_R_NOTFOUND; 574 575 flags = DB_SET; 576 while ((bdbhptres = data_cursor->c_get(data_cursor, &key, &data, 577 flags)) == 0) { 578 579 flags = DB_NEXT_DUP; 580 tmp = realloc(tmp, data.size + 1); 581 if (tmp == NULL) 582 goto lookup_cleanup; 583 584 strncpy(tmp, data.data, data.size); 585 tmp[data.size] = '\0'; 586 587 if (bdbhpt_parse_data(tmp, &pd) != ISC_R_SUCCESS) 588 goto lookup_cleanup; 589 590 result = dns_sdlz_putrr(lookup, pd.type, pd.ttl, pd.data); 591 592 if (result != ISC_R_SUCCESS) 593 goto lookup_cleanup; 594 } /* end while loop */ 595 596 lookup_cleanup: 597 598 /* get rid of cursor */ 599 if (data_cursor != NULL) 600 data_cursor->c_close(data_cursor); 601 602 if (keyStr != NULL) 603 free(keyStr); 604 if (tmp != NULL) 605 free(tmp); 606 607 return result; 608} 609 610/*% Initializes, sets flags and then opens Berkeley databases. */ 611 612static isc_result_t 613bdbhpt_opendb(DB_ENV *db_env, DBTYPE db_type, DB **db, const char *db_name, 614 char *db_file, int flags) { 615 616 int result; 617 618 /* Initialize the database. */ 619 if ((result = db_create(db, db_env, 0)) != 0) { 620 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 621 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 622 "bdbhpt could not initialize %s database. " 623 "bdbhpt error: %s", 624 db_name, db_strerror(result)); 625 return ISC_R_FAILURE; 626 } 627 628 /* set database flags. */ 629 if ((result = (*db)->set_flags(*db, flags)) != 0) { 630 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 631 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 632 "bdbhpt could not set flags for %s database. " 633 "bdbhpt error: %s", 634 db_name, db_strerror(result)); 635 return ISC_R_FAILURE; 636 } 637 638 /* open the database. */ 639 if ((result = (*db)->open(*db, NULL, db_file, db_name, db_type, 640 DB_RDONLY | bdbhpt_threads, 0)) != 0) { 641 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 642 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 643 "bdbhpt could not open %s database in %s. " 644 "bdbhpt error: %s", 645 db_name, db_file, db_strerror(result)); 646 return ISC_R_FAILURE; 647 } 648 649 return ISC_R_SUCCESS; 650} 651 652static isc_result_t 653bdbhpt_create(const char *dlzname, unsigned int argc, char *argv[], 654 void *driverarg, void **dbdata) 655{ 656 isc_result_t result; 657 int bdbhptres; 658 int bdbFlags = 0; 659 bdbhpt_instance_t *db = NULL; 660 661 UNUSED(dlzname); 662 UNUSED(driverarg); 663 664 /* verify we have 4 arg's passed to the driver */ 665 if (argc != 4) { 666 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 667 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 668 "bdbhpt driver requires at least " 669 "3 command line args."); 670 return (ISC_R_FAILURE); 671 } 672 673 switch((char) *argv[1]) { 674 /* 675 * Transactional mode. Highest safety - lowest speed. 676 */ 677 case 'T': 678 case 't': 679 bdbFlags = DB_INIT_MPOOL | DB_INIT_LOCK | 680 DB_INIT_LOG | DB_INIT_TXN; 681 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 682 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), 683 "bdbhpt driver using transactional mode."); 684 break; 685 /* 686 * Concurrent mode. Lower safety (no rollback) - 687 * higher speed. 688 */ 689 case 'C': 690 case 'c': 691 bdbFlags = DB_INIT_CDB | DB_INIT_MPOOL; 692 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 693 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), 694 "bdbhpt driver using concurrent mode."); 695 break; 696 /* 697 * Private mode. No inter-process communication & no locking. 698 * Lowest saftey - highest speed. 699 */ 700 case 'P': 701 case 'p': 702 bdbFlags = DB_PRIVATE | DB_INIT_MPOOL; 703 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 704 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), 705 "bdbhpt driver using private mode."); 706 break; 707 default: 708 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 709 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 710 "bdbhpt driver requires the operating mode " 711 "be set to P or C or T. You specified '%s'", 712 argv[1]); 713 return (ISC_R_FAILURE); 714 } 715 716 /* allocate and zero memory for driver structure */ 717 db = isc_mem_get(ns_g_mctx, sizeof(bdbhpt_instance_t)); 718 if (db == NULL) { 719 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 720 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 721 "Could not allocate memory for " 722 "database instance object."); 723 return (ISC_R_NOMEMORY); 724 } 725 memset(db, 0, sizeof(bdbhpt_instance_t)); 726 727 /* attach to the memory context */ 728 isc_mem_attach(ns_g_mctx, &db->mctx); 729 730 /* 731 * create bdbhpt environment 732 * Basically bdbhpt allocates and assigns memory to db->dbenv 733 */ 734 bdbhptres = db_env_create(&db->dbenv, 0); 735 if (bdbhptres != 0) { 736 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 737 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 738 "bdbhpt environment could not be created. " 739 "bdbhpt error: %s", 740 db_strerror(bdbhptres)); 741 result = ISC_R_FAILURE; 742 goto init_cleanup; 743 } 744 745 /* open bdbhpt environment */ 746 bdbhptres = db->dbenv->open(db->dbenv, argv[2], 747 bdbFlags | bdbhpt_threads | DB_CREATE, 0); 748 if (bdbhptres != 0) { 749 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 750 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, 751 "bdbhpt environment at '%s' could not be opened." 752 " bdbhpt error: %s", 753 argv[2], db_strerror(bdbhptres)); 754 result = ISC_R_FAILURE; 755 goto init_cleanup; 756 } 757 758 /* open dlz_data database. */ 759 result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->data, 760 dlz_data, argv[3], DB_DUP | DB_DUPSORT); 761 if (result != ISC_R_SUCCESS) 762 goto init_cleanup; 763 764 /* open dlz_xfr database. */ 765 result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->xfr, 766 dlz_xfr, argv[3], DB_DUP | DB_DUPSORT); 767 if (result != ISC_R_SUCCESS) 768 goto init_cleanup; 769 770 /* open dlz_zone database. */ 771 result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->zone, 772 dlz_zone, argv[3], 0); 773 if (result != ISC_R_SUCCESS) 774 goto init_cleanup; 775 776 /* open dlz_client database. */ 777 result = bdbhpt_opendb(db->dbenv, DB_UNKNOWN, &db->client, 778 dlz_client, argv[3], DB_DUP | DB_DUPSORT); 779 if (result != ISC_R_SUCCESS) 780 goto init_cleanup; 781 782 *dbdata = db; 783 784 return(ISC_R_SUCCESS); 785 786 init_cleanup: 787 788 bdbhpt_cleanup(db); 789 return result; 790} 791 792static void 793bdbhpt_destroy(void *driverarg, void *dbdata) 794{ 795 UNUSED(driverarg); 796 797 bdbhpt_cleanup((bdbhpt_instance_t *) dbdata); 798} 799 800/* 801 * bdbhpt_authority not needed as authority data is returned by lookup 802 */ 803static dns_sdlzmethods_t dlz_bdbhpt_methods = { 804 bdbhpt_create, 805 bdbhpt_destroy, 806 bdbhpt_findzone, 807 bdbhpt_lookup, 808 NULL, 809 bdbhpt_allnodes, 810 bdbhpt_allowzonexfr, 811 NULL, 812 NULL, 813 NULL, 814 NULL, 815 NULL, 816 NULL, 817 NULL, 818}; 819 820/*% 821 * Wrapper around dns_sdlzregister(). 822 */ 823isc_result_t 824dlz_bdbhpt_init(void) { 825 isc_result_t result; 826 827 /* 828 * Write debugging message to log 829 */ 830 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 831 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 832 "Registering DLZ bdbhpt driver."); 833 834 result = dns_sdlzregister("bdbhpt", &dlz_bdbhpt_methods, NULL, 835 DNS_SDLZFLAG_RELATIVEOWNER | 836 DNS_SDLZFLAG_RELATIVERDATA | 837 DNS_SDLZFLAG_THREADSAFE, 838 ns_g_mctx, &dlz_bdbhpt); 839 if (result != ISC_R_SUCCESS) { 840 UNEXPECTED_ERROR(__FILE__, __LINE__, 841 "dns_sdlzregister() failed: %s", 842 isc_result_totext(result)); 843 result = ISC_R_UNEXPECTED; 844 } 845 846 847 return result; 848} 849 850/*% 851 * Wrapper around dns_sdlzunregister(). 852 */ 853void 854dlz_bdbhpt_clear(void) { 855 856 /* 857 * Write debugging message to log 858 */ 859 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, 860 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), 861 "Unregistering DLZ bdbhpt driver."); 862 863 if (dlz_bdbhpt != NULL) 864 dns_sdlzunregister(&dlz_bdbhpt); 865} 866 867#endif 868