1/* 2 * Copyright (C) 2002 Nuno M. Rodrigues. 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 above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND NUNO M. RODRIGUES 9 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 10 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 11 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING 13 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 14 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 15 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id$ */ 19 20/* 21 * BIND 9.1.x simple database driver 22 * implementation, using Berkeley DB. 23 */ 24 25#include <errno.h> 26#include <stdio.h> 27#include <string.h> 28#include <stdlib.h> 29 30#include <isc/file.h> 31#include <isc/log.h> 32#include <isc/lib.h> 33#include <isc/mem.h> 34#include <isc/msgs.h> 35#include <isc/msgcat.h> 36#include <isc/region.h> 37#include <isc/result.h> 38#include <isc/types.h> 39#include <isc/util.h> 40 41#include <dns/sdb.h> 42#include <dns/log.h> 43#include <dns/lib.h> 44#include <dns/ttl.h> 45 46#include <named/bdb.h> 47#include <named/globals.h> 48#include <named/config.h> 49 50#include <db.h> 51 52#define DRIVERNAME "bdb" 53 54static dns_sdbimplementation_t *bdb_imp; 55 56static isc_result_t 57bdb_create(const char *zone, int argc, char **argv, 58 void *unused, void **dbdata) 59{ 60 int ret; 61 62 UNUSED(zone); 63 UNUSED(unused); 64 65 if (argc < 1) 66 return ISC_R_FAILURE; /* database path must be given */ 67 68 if (db_create((DB **)dbdata, NULL, 0) != 0) { 69 /* 70 * XXX Should use dns_msgcat et al 71 * but seems to be unavailable. 72 */ 73 isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, 74 DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL, isc_msgcat, 75 ISC_MSGSET_GENERAL, ISC_MSG_FATALERROR, 76 "db_create"); 77 return ISC_R_FAILURE; 78 } 79 80 if (isc_file_exists(*argv) != ISC_TRUE) { 81 isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, 82 DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL, isc_msgcat, 83 ISC_MSGSET_GENERAL, ISC_MSG_FATALERROR, 84 "isc_file_exists: %s", *argv); 85 return ISC_R_FAILURE; 86 } 87 88 if ((ret = (*(DB **)dbdata)->open(*(DB **)dbdata, *argv, NULL, DB_HASH, 89 DB_RDONLY, 0)) != 0) { 90 isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, 91 DNS_LOGMODULE_SDB, ISC_LOG_CRITICAL, 92 isc_msgcat, ISC_MSGSET_GENERAL, 93 ISC_MSG_FATALERROR, "DB->open: %s", 94 db_strerror(ret)); 95 return ISC_R_FAILURE; 96 } 97 return ISC_R_SUCCESS; 98} 99 100static isc_result_t 101bdb_lookup(const char *zone, const char *name, void *dbdata, 102 dns_sdblookup_t *l) 103{ 104 int ret; 105 char *type, *rdata; 106 dns_ttl_t ttl; 107 isc_consttextregion_t ttltext; 108 DBC *c; 109 DBT key, data; 110 111 UNUSED(zone); 112 113 if ((ret = ((DB *)dbdata)->cursor((DB *)dbdata, NULL, &c, 0)) != 0) { 114 isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, 115 DNS_LOGMODULE_SDB, ISC_LOG_ERROR, 116 isc_msgcat, ISC_MSGSET_GENERAL, 117 ISC_MSG_FAILED, "DB->cursor: %s", 118 db_strerror(ret)); 119 return ISC_R_FAILURE; 120 } 121 122 memset(&key, 0, sizeof(DBT)); 123 memset(&data, 0, sizeof(DBT)); 124 125 (const char *)key.data = name; 126 key.size = strlen(name); 127 128 ret = c->c_get(c, &key, &data, DB_SET); 129 while (ret == 0) { 130 ((char *)key.data)[key.size] = 0; 131 ((char *)data.data)[data.size] = 0; 132 ttltext.base = strtok((char *)data.data, " "); 133 ttltext.length = strlen(ttltext.base); 134 dns_ttl_fromtext((isc_textregion_t *)&ttltext, &ttl); 135 type = strtok(NULL, " "); 136 rdata = type + strlen(type) + 1; 137 138 if (dns_sdb_putrr(l, type, ttl, rdata) != ISC_R_SUCCESS) { 139 isc_log_iwrite(dns_lctx, 140 DNS_LOGCATEGORY_DATABASE, 141 DNS_LOGMODULE_SDB, ISC_LOG_ERROR, 142 isc_msgcat, ISC_MSGSET_GENERAL, 143 ISC_MSG_FAILED, "dns_sdb_putrr"); 144 return ISC_R_FAILURE; 145 } 146 ret = c->c_get(c, &key, &data, DB_NEXT_DUP); 147 } 148 149 c->c_close(c); 150 return ISC_R_SUCCESS; 151} 152 153static isc_result_t 154bdb_allnodes(const char *zone, void *dbdata, dns_sdballnodes_t *n) 155{ 156 int ret; 157 char *type, *rdata; 158 dns_ttl_t ttl; 159 isc_consttextregion_t ttltext; 160 DBC *c; 161 DBT key, data; 162 163 UNUSED(zone); 164 165 if ((ret = ((DB *)dbdata)->cursor((DB *)dbdata, NULL, &c, 0)) != 0) { 166 isc_log_iwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, 167 DNS_LOGMODULE_SDB, ISC_LOG_ERROR, 168 isc_msgcat, ISC_MSGSET_GENERAL, 169 ISC_MSG_FAILED, "DB->cursor: %s", 170 db_strerror(ret)); 171 return ISC_R_FAILURE; 172 } 173 174 memset(&key, 0, sizeof(DBT)); 175 memset(&data, 0, sizeof(DBT)); 176 177 while (c->c_get(c, &key, &data, DB_NEXT) == 0) { 178 ((char *)key.data)[key.size] = 0; 179 ((char *)data.data)[data.size] = 0; 180 ttltext.base = strtok((char *)data.data, " "); 181 ttltext.length = strlen(ttltext.base); 182 dns_ttl_fromtext((isc_textregion_t *)&ttltext, &ttl); 183 type = strtok(NULL, " "); 184 rdata = type + strlen(type) + 1; 185 186 if (dns_sdb_putnamedrr(n, key.data, type, ttl, rdata) != 187 ISC_R_SUCCESS) { 188 isc_log_iwrite(dns_lctx, 189 DNS_LOGCATEGORY_DATABASE, 190 DNS_LOGMODULE_SDB, ISC_LOG_ERROR, 191 isc_msgcat, ISC_MSGSET_GENERAL, 192 ISC_MSG_FAILED, "dns_sdb_putnamedrr"); 193 return ISC_R_FAILURE; 194 } 195 196 } 197 198 c->c_close(c); 199 return ISC_R_SUCCESS; 200} 201 202static isc_result_t 203bdb_destroy(const char *zone, void *unused, void **dbdata) 204{ 205 206 UNUSED(zone); 207 UNUSED(unused); 208 209 (*(DB **)dbdata)->close(*(DB **)dbdata, 0); 210 211 return ISC_R_SUCCESS; 212} 213 214isc_result_t 215bdb_init(void) 216{ 217 static dns_sdbmethods_t bdb_methods = { 218 bdb_lookup, 219 NULL, 220 bdb_allnodes, 221 bdb_create, 222 bdb_destroy 223 }; 224 225 return dns_sdb_register(DRIVERNAME, &bdb_methods, NULL, 0, ns_g_mctx, 226 &bdb_imp); 227} 228 229void 230bdb_clear(void) 231{ 232 233 if (bdb_imp != NULL) 234 dns_sdb_unregister(&bdb_imp); 235} 236