1 1.12 christos /* $NetBSD: sdlz.c,v 1.15 2026/01/29 18:37:50 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.10 christos * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 1.10 christos * 6 1.10 christos * SPDX-License-Identifier: MPL-2.0 AND ISC 7 1.1 christos * 8 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public 9 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this 10 1.8 christos * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 1.1 christos * 12 1.1 christos * See the COPYRIGHT file distributed with this work for additional 13 1.1 christos * information regarding copyright ownership. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos /* 17 1.1 christos * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting (at) nlnet.nl. 18 1.1 christos * 19 1.1 christos * Permission to use, copy, modify, and distribute this software for any 20 1.1 christos * purpose with or without fee is hereby granted, provided that the 21 1.1 christos * above copyright notice and this permission notice appear in all 22 1.1 christos * copies. 23 1.1 christos * 24 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET 25 1.1 christos * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 26 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 27 1.1 christos * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 28 1.1 christos * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 29 1.1 christos * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 30 1.1 christos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 31 1.1 christos * USE OR PERFORMANCE OF THIS SOFTWARE. 32 1.1 christos * 33 1.1 christos * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was 34 1.1 christos * conceived and contributed by Rob Butler. 35 1.1 christos * 36 1.1 christos * Permission to use, copy, modify, and distribute this software for any 37 1.1 christos * purpose with or without fee is hereby granted, provided that the 38 1.1 christos * above copyright notice and this permission notice appear in all 39 1.1 christos * copies. 40 1.1 christos * 41 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER 42 1.1 christos * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL 43 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 44 1.1 christos * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 45 1.1 christos * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 46 1.1 christos * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 47 1.1 christos * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE 48 1.1 christos * USE OR PERFORMANCE OF THIS SOFTWARE. 49 1.1 christos */ 50 1.1 christos 51 1.1 christos /*! \file */ 52 1.1 christos 53 1.3 christos #include <inttypes.h> 54 1.3 christos #include <stdbool.h> 55 1.1 christos #include <string.h> 56 1.1 christos 57 1.14 christos #include <isc/ascii.h> 58 1.1 christos #include <isc/buffer.h> 59 1.1 christos #include <isc/lex.h> 60 1.1 christos #include <isc/log.h> 61 1.1 christos #include <isc/magic.h> 62 1.1 christos #include <isc/mem.h> 63 1.1 christos #include <isc/once.h> 64 1.1 christos #include <isc/region.h> 65 1.12 christos #include <isc/result.h> 66 1.6 christos #include <isc/rwlock.h> 67 1.6 christos #include <isc/string.h> 68 1.6 christos #include <isc/util.h> 69 1.1 christos 70 1.1 christos #include <dns/callbacks.h> 71 1.1 christos #include <dns/db.h> 72 1.1 christos #include <dns/dbiterator.h> 73 1.1 christos #include <dns/dlz.h> 74 1.1 christos #include <dns/fixedname.h> 75 1.1 christos #include <dns/log.h> 76 1.6 christos #include <dns/master.h> 77 1.1 christos #include <dns/rdata.h> 78 1.1 christos #include <dns/rdatalist.h> 79 1.1 christos #include <dns/rdataset.h> 80 1.1 christos #include <dns/rdatasetiter.h> 81 1.1 christos #include <dns/rdatatype.h> 82 1.1 christos #include <dns/sdlz.h> 83 1.1 christos #include <dns/types.h> 84 1.1 christos 85 1.1 christos /* 86 1.1 christos * Private Types 87 1.1 christos */ 88 1.1 christos 89 1.1 christos struct dns_sdlzimplementation { 90 1.6 christos const dns_sdlzmethods_t *methods; 91 1.6 christos isc_mem_t *mctx; 92 1.6 christos void *driverarg; 93 1.6 christos unsigned int flags; 94 1.6 christos isc_mutex_t driverlock; 95 1.6 christos dns_dlzimplementation_t *dlz_imp; 96 1.1 christos }; 97 1.1 christos 98 1.1 christos struct dns_sdlz_db { 99 1.1 christos /* Unlocked */ 100 1.6 christos dns_db_t common; 101 1.6 christos void *dbdata; 102 1.6 christos dns_sdlzimplementation_t *dlzimp; 103 1.6 christos 104 1.1 christos /* Locked */ 105 1.6 christos dns_dbversion_t *future_version; 106 1.6 christos int dummy_version; 107 1.1 christos }; 108 1.1 christos 109 1.1 christos struct dns_sdlzlookup { 110 1.1 christos /* Unlocked */ 111 1.6 christos unsigned int magic; 112 1.6 christos dns_sdlz_db_t *sdlz; 113 1.6 christos ISC_LIST(dns_rdatalist_t) lists; 114 1.6 christos ISC_LIST(isc_buffer_t) buffers; 115 1.6 christos dns_name_t *name; 116 1.6 christos ISC_LINK(dns_sdlzlookup_t) link; 117 1.6 christos dns_rdatacallbacks_t callbacks; 118 1.6 christos 119 1.6 christos /* Atomic */ 120 1.6 christos isc_refcount_t references; 121 1.1 christos }; 122 1.1 christos 123 1.1 christos typedef struct dns_sdlzlookup dns_sdlznode_t; 124 1.1 christos 125 1.1 christos struct dns_sdlzallnodes { 126 1.6 christos dns_dbiterator_t common; 127 1.6 christos ISC_LIST(dns_sdlznode_t) nodelist; 128 1.6 christos dns_sdlznode_t *current; 129 1.6 christos dns_sdlznode_t *origin; 130 1.1 christos }; 131 1.1 christos 132 1.1 christos typedef dns_sdlzallnodes_t sdlz_dbiterator_t; 133 1.1 christos 134 1.1 christos typedef struct sdlz_rdatasetiter { 135 1.6 christos dns_rdatasetiter_t common; 136 1.6 christos dns_rdatalist_t *current; 137 1.1 christos } sdlz_rdatasetiter_t; 138 1.1 christos 139 1.6 christos #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S') 140 1.1 christos 141 1.1 christos /* 142 1.1 christos * Note that "impmagic" is not the first four bytes of the struct, so 143 1.1 christos * ISC_MAGIC_VALID cannot be used. 144 1.1 christos */ 145 1.1 christos 146 1.6 christos #define VALID_SDLZDB(sdlzdb) \ 147 1.6 christos ((sdlzdb) != NULL && (sdlzdb)->common.impmagic == SDLZDB_MAGIC) 148 1.1 christos 149 1.6 christos #define SDLZLOOKUP_MAGIC ISC_MAGIC('D', 'L', 'Z', 'L') 150 1.6 christos #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC) 151 1.1 christos #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn) 152 1.1 christos 153 1.1 christos /* These values are taken from RFC 1537 */ 154 1.6 christos #define SDLZ_DEFAULT_REFRESH 28800U /* 8 hours */ 155 1.6 christos #define SDLZ_DEFAULT_RETRY 7200U /* 2 hours */ 156 1.6 christos #define SDLZ_DEFAULT_EXPIRE 604800U /* 7 days */ 157 1.6 christos #define SDLZ_DEFAULT_MINIMUM 86400U /* 1 day */ 158 1.1 christos 159 1.1 christos /* This is a reasonable value */ 160 1.6 christos #define SDLZ_DEFAULT_TTL (60 * 60 * 24) 161 1.1 christos 162 1.1 christos #ifdef __COVERITY__ 163 1.6 christos #define MAYBE_LOCK(imp) LOCK(&imp->driverlock) 164 1.1 christos #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock) 165 1.6 christos #else /* ifdef __COVERITY__ */ 166 1.6 christos #define MAYBE_LOCK(imp) \ 167 1.6 christos do { \ 168 1.6 christos unsigned int flags = imp->flags; \ 169 1.1 christos if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \ 170 1.6 christos LOCK(&imp->driverlock); \ 171 1.9 rillig } while (0) 172 1.1 christos 173 1.6 christos #define MAYBE_UNLOCK(imp) \ 174 1.6 christos do { \ 175 1.6 christos unsigned int flags = imp->flags; \ 176 1.1 christos if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \ 177 1.6 christos UNLOCK(&imp->driverlock); \ 178 1.9 rillig } while (0) 179 1.6 christos #endif /* ifdef __COVERITY__ */ 180 1.1 christos 181 1.1 christos /* 182 1.1 christos * Forward references. 183 1.1 christos */ 184 1.6 christos static isc_result_t 185 1.6 christos getnodedata(dns_db_t *db, const dns_name_t *name, bool create, 186 1.6 christos unsigned int options, dns_clientinfomethods_t *methods, 187 1.6 christos dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep); 188 1.6 christos 189 1.6 christos static void 190 1.6 christos list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 191 1.6 christos dns_rdataset_t *rdataset); 192 1.6 christos 193 1.6 christos static void 194 1.14 christos detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG); 195 1.6 christos 196 1.6 christos static void 197 1.14 christos dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG); 198 1.6 christos static isc_result_t 199 1.14 christos dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG); 200 1.6 christos static isc_result_t 201 1.14 christos dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG); 202 1.6 christos static isc_result_t 203 1.14 christos dbiterator_seek(dns_dbiterator_t *iterator, 204 1.14 christos const dns_name_t *name DNS__DB_FLARG); 205 1.6 christos static isc_result_t 206 1.15 christos dbiterator_seek3(dns_dbiterator_t *iterator, 207 1.15 christos const dns_name_t *name DNS__DB_FLARG); 208 1.15 christos static isc_result_t 209 1.14 christos dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG); 210 1.6 christos static isc_result_t 211 1.14 christos dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG); 212 1.6 christos static isc_result_t 213 1.6 christos dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 214 1.14 christos dns_name_t *name DNS__DB_FLARG); 215 1.6 christos static isc_result_t 216 1.6 christos dbiterator_pause(dns_dbiterator_t *iterator); 217 1.6 christos static isc_result_t 218 1.6 christos dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name); 219 1.1 christos 220 1.1 christos static dns_dbiteratormethods_t dbiterator_methods = { 221 1.15 christos dbiterator_destroy, dbiterator_first, dbiterator_last, 222 1.15 christos dbiterator_seek, dbiterator_seek3, dbiterator_prev, 223 1.15 christos dbiterator_next, dbiterator_current, dbiterator_pause, 224 1.15 christos dbiterator_origin 225 1.1 christos }; 226 1.1 christos 227 1.1 christos /* 228 1.1 christos * Utility functions 229 1.1 christos */ 230 1.1 christos 231 1.1 christos /* 232 1.1 christos * Log a message at the given level 233 1.1 christos */ 234 1.1 christos static void 235 1.1 christos sdlz_log(int level, const char *fmt, ...) { 236 1.1 christos va_list ap; 237 1.1 christos va_start(ap, fmt); 238 1.6 christos isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, 239 1.6 christos ISC_LOG_DEBUG(level), fmt, ap); 240 1.1 christos va_end(ap); 241 1.1 christos } 242 1.1 christos 243 1.10 christos static unsigned int 244 1.1 christos initial_size(const char *data) { 245 1.1 christos unsigned int len = (strlen(data) / 64) + 1; 246 1.14 christos return len * 64 + 64; 247 1.1 christos } 248 1.1 christos 249 1.1 christos /* 250 1.1 christos * Rdataset Iterator Methods. These methods were "borrowed" from the SDB 251 1.1 christos * driver interface. See the SDB driver interface documentation for more info. 252 1.1 christos */ 253 1.1 christos 254 1.1 christos static void 255 1.14 christos rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) { 256 1.6 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)(*iteratorp); 257 1.1 christos 258 1.14 christos detachnode(sdlziterator->common.db, 259 1.14 christos &sdlziterator->common.node DNS__DB_FLARG_PASS); 260 1.1 christos isc_mem_put(sdlziterator->common.db->mctx, sdlziterator, 261 1.1 christos sizeof(sdlz_rdatasetiter_t)); 262 1.1 christos *iteratorp = NULL; 263 1.1 christos } 264 1.1 christos 265 1.1 christos static isc_result_t 266 1.14 christos rdatasetiter_first(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { 267 1.1 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 268 1.1 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node; 269 1.1 christos 270 1.6 christos if (ISC_LIST_EMPTY(sdlznode->lists)) { 271 1.14 christos return ISC_R_NOMORE; 272 1.6 christos } 273 1.1 christos sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists); 274 1.14 christos return ISC_R_SUCCESS; 275 1.1 christos } 276 1.1 christos 277 1.1 christos static isc_result_t 278 1.14 christos rdatasetiter_next(dns_rdatasetiter_t *iterator DNS__DB_FLARG) { 279 1.1 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 280 1.1 christos 281 1.1 christos sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link); 282 1.6 christos if (sdlziterator->current == NULL) { 283 1.14 christos return ISC_R_NOMORE; 284 1.6 christos } else { 285 1.14 christos return ISC_R_SUCCESS; 286 1.6 christos } 287 1.1 christos } 288 1.1 christos 289 1.1 christos static void 290 1.14 christos rdatasetiter_current(dns_rdatasetiter_t *iterator, 291 1.14 christos dns_rdataset_t *rdataset DNS__DB_FLARG) { 292 1.1 christos sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator; 293 1.1 christos 294 1.1 christos list_tordataset(sdlziterator->current, iterator->db, iterator->node, 295 1.1 christos rdataset); 296 1.1 christos } 297 1.1 christos 298 1.1 christos static dns_rdatasetitermethods_t rdatasetiter_methods = { 299 1.6 christos rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next, 300 1.1 christos rdatasetiter_current 301 1.1 christos }; 302 1.1 christos 303 1.1 christos /* 304 1.1 christos * DB routines. These methods were "borrowed" from the SDB driver interface. 305 1.1 christos * See the SDB driver interface documentation for more info. 306 1.1 christos */ 307 1.1 christos 308 1.1 christos static void 309 1.14 christos destroy(dns_db_t *db) { 310 1.14 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 311 1.1 christos 312 1.1 christos sdlz->common.magic = 0; 313 1.1 christos sdlz->common.impmagic = 0; 314 1.1 christos 315 1.6 christos dns_name_free(&sdlz->common.origin, sdlz->common.mctx); 316 1.1 christos 317 1.14 christos isc_refcount_destroy(&sdlz->common.references); 318 1.6 christos isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t)); 319 1.1 christos } 320 1.1 christos 321 1.1 christos static void 322 1.1 christos currentversion(dns_db_t *db, dns_dbversion_t **versionp) { 323 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 324 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 325 1.1 christos REQUIRE(versionp != NULL && *versionp == NULL); 326 1.1 christos 327 1.6 christos *versionp = (void *)&sdlz->dummy_version; 328 1.1 christos return; 329 1.1 christos } 330 1.1 christos 331 1.1 christos static isc_result_t 332 1.1 christos newversion(dns_db_t *db, dns_dbversion_t **versionp) { 333 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 334 1.1 christos char origin[DNS_NAME_MAXTEXT + 1]; 335 1.1 christos isc_result_t result; 336 1.1 christos 337 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 338 1.1 christos 339 1.6 christos if (sdlz->dlzimp->methods->newversion == NULL) { 340 1.14 christos return ISC_R_NOTIMPLEMENTED; 341 1.6 christos } 342 1.1 christos 343 1.1 christos dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); 344 1.1 christos 345 1.6 christos result = sdlz->dlzimp->methods->newversion( 346 1.6 christos origin, sdlz->dlzimp->driverarg, sdlz->dbdata, versionp); 347 1.1 christos if (result != ISC_R_SUCCESS) { 348 1.1 christos sdlz_log(ISC_LOG_ERROR, 349 1.6 christos "sdlz newversion on origin %s failed : %s", origin, 350 1.6 christos isc_result_totext(result)); 351 1.14 christos return result; 352 1.1 christos } 353 1.1 christos 354 1.1 christos sdlz->future_version = *versionp; 355 1.14 christos return ISC_R_SUCCESS; 356 1.1 christos } 357 1.1 christos 358 1.1 christos static void 359 1.6 christos attachversion(dns_db_t *db, dns_dbversion_t *source, 360 1.6 christos dns_dbversion_t **targetp) { 361 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 362 1.1 christos 363 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 364 1.1 christos REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version); 365 1.1 christos 366 1.1 christos *targetp = source; 367 1.1 christos } 368 1.1 christos 369 1.1 christos static void 370 1.14 christos closeversion(dns_db_t *db, dns_dbversion_t **versionp, 371 1.14 christos bool commit DNS__DB_FLARG) { 372 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 373 1.1 christos char origin[DNS_NAME_MAXTEXT + 1]; 374 1.1 christos 375 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 376 1.1 christos REQUIRE(versionp != NULL); 377 1.1 christos 378 1.1 christos if (*versionp == (void *)&sdlz->dummy_version) { 379 1.1 christos *versionp = NULL; 380 1.1 christos return; 381 1.1 christos } 382 1.1 christos 383 1.1 christos REQUIRE(*versionp == sdlz->future_version); 384 1.1 christos REQUIRE(sdlz->dlzimp->methods->closeversion != NULL); 385 1.1 christos 386 1.1 christos dns_name_format(&sdlz->common.origin, origin, sizeof(origin)); 387 1.1 christos 388 1.1 christos sdlz->dlzimp->methods->closeversion(origin, commit, 389 1.1 christos sdlz->dlzimp->driverarg, 390 1.1 christos sdlz->dbdata, versionp); 391 1.6 christos if (*versionp != NULL) { 392 1.6 christos sdlz_log(ISC_LOG_ERROR, "sdlz closeversion on origin %s failed", 393 1.6 christos origin); 394 1.6 christos } 395 1.1 christos 396 1.1 christos sdlz->future_version = NULL; 397 1.1 christos } 398 1.1 christos 399 1.1 christos static isc_result_t 400 1.1 christos createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) { 401 1.1 christos dns_sdlznode_t *node; 402 1.1 christos 403 1.1 christos node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t)); 404 1.1 christos 405 1.1 christos node->sdlz = NULL; 406 1.14 christos dns_db_attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz); 407 1.1 christos ISC_LIST_INIT(node->lists); 408 1.1 christos ISC_LIST_INIT(node->buffers); 409 1.1 christos ISC_LINK_INIT(node, link); 410 1.1 christos node->name = NULL; 411 1.1 christos dns_rdatacallbacks_init(&node->callbacks); 412 1.6 christos 413 1.6 christos isc_refcount_init(&node->references, 1); 414 1.1 christos node->magic = SDLZLOOKUP_MAGIC; 415 1.1 christos 416 1.1 christos *nodep = node; 417 1.14 christos return ISC_R_SUCCESS; 418 1.1 christos } 419 1.1 christos 420 1.1 christos static void 421 1.1 christos destroynode(dns_sdlznode_t *node) { 422 1.1 christos dns_rdatalist_t *list; 423 1.1 christos dns_rdata_t *rdata; 424 1.1 christos isc_buffer_t *b; 425 1.1 christos dns_sdlz_db_t *sdlz; 426 1.1 christos dns_db_t *db; 427 1.1 christos isc_mem_t *mctx; 428 1.1 christos 429 1.6 christos isc_refcount_destroy(&node->references); 430 1.6 christos 431 1.1 christos sdlz = node->sdlz; 432 1.1 christos mctx = sdlz->common.mctx; 433 1.1 christos 434 1.1 christos while (!ISC_LIST_EMPTY(node->lists)) { 435 1.1 christos list = ISC_LIST_HEAD(node->lists); 436 1.1 christos while (!ISC_LIST_EMPTY(list->rdata)) { 437 1.1 christos rdata = ISC_LIST_HEAD(list->rdata); 438 1.1 christos ISC_LIST_UNLINK(list->rdata, rdata, link); 439 1.1 christos isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 440 1.1 christos } 441 1.1 christos ISC_LIST_UNLINK(node->lists, list, link); 442 1.1 christos isc_mem_put(mctx, list, sizeof(dns_rdatalist_t)); 443 1.1 christos } 444 1.1 christos 445 1.1 christos while (!ISC_LIST_EMPTY(node->buffers)) { 446 1.1 christos b = ISC_LIST_HEAD(node->buffers); 447 1.1 christos ISC_LIST_UNLINK(node->buffers, b, link); 448 1.1 christos isc_buffer_free(&b); 449 1.1 christos } 450 1.1 christos 451 1.1 christos if (node->name != NULL) { 452 1.1 christos dns_name_free(node->name, mctx); 453 1.1 christos isc_mem_put(mctx, node->name, sizeof(dns_name_t)); 454 1.1 christos } 455 1.6 christos 456 1.1 christos node->magic = 0; 457 1.1 christos isc_mem_put(mctx, node, sizeof(dns_sdlznode_t)); 458 1.1 christos db = &sdlz->common; 459 1.14 christos dns_db_detach(&db); 460 1.1 christos } 461 1.1 christos 462 1.1 christos static isc_result_t 463 1.3 christos getnodedata(dns_db_t *db, const dns_name_t *name, bool create, 464 1.1 christos unsigned int options, dns_clientinfomethods_t *methods, 465 1.6 christos dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) { 466 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 467 1.1 christos dns_sdlznode_t *node = NULL; 468 1.1 christos isc_result_t result; 469 1.1 christos isc_buffer_t b; 470 1.1 christos char namestr[DNS_NAME_MAXTEXT + 1]; 471 1.1 christos isc_buffer_t b2; 472 1.1 christos char zonestr[DNS_NAME_MAXTEXT + 1]; 473 1.3 christos bool isorigin; 474 1.1 christos dns_sdlzauthorityfunc_t authority; 475 1.1 christos 476 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 477 1.1 christos REQUIRE(nodep != NULL && *nodep == NULL); 478 1.1 christos 479 1.1 christos if (sdlz->dlzimp->methods->newversion == NULL) { 480 1.7 christos REQUIRE(!create); 481 1.1 christos } 482 1.1 christos 483 1.1 christos isc_buffer_init(&b, namestr, sizeof(namestr)); 484 1.1 christos if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) { 485 1.1 christos dns_name_t relname; 486 1.1 christos unsigned int labels; 487 1.1 christos 488 1.1 christos labels = dns_name_countlabels(name) - 489 1.1 christos dns_name_countlabels(&sdlz->common.origin); 490 1.1 christos dns_name_init(&relname, NULL); 491 1.1 christos dns_name_getlabelsequence(name, 0, labels, &relname); 492 1.14 christos result = dns_name_totext(&relname, DNS_NAME_OMITFINALDOT, &b); 493 1.6 christos if (result != ISC_R_SUCCESS) { 494 1.14 christos return result; 495 1.6 christos } 496 1.1 christos } else { 497 1.14 christos result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &b); 498 1.6 christos if (result != ISC_R_SUCCESS) { 499 1.14 christos return result; 500 1.6 christos } 501 1.1 christos } 502 1.1 christos isc_buffer_putuint8(&b, 0); 503 1.1 christos 504 1.1 christos isc_buffer_init(&b2, zonestr, sizeof(zonestr)); 505 1.14 christos result = dns_name_totext(&sdlz->common.origin, DNS_NAME_OMITFINALDOT, 506 1.14 christos &b2); 507 1.6 christos if (result != ISC_R_SUCCESS) { 508 1.14 christos return result; 509 1.6 christos } 510 1.1 christos isc_buffer_putuint8(&b2, 0); 511 1.1 christos 512 1.1 christos result = createnode(sdlz, &node); 513 1.6 christos if (result != ISC_R_SUCCESS) { 514 1.14 christos return result; 515 1.6 christos } 516 1.1 christos 517 1.1 christos isorigin = dns_name_equal(name, &sdlz->common.origin); 518 1.1 christos 519 1.1 christos /* make sure strings are always lowercase */ 520 1.14 christos isc_ascii_strtolower(zonestr); 521 1.14 christos isc_ascii_strtolower(namestr); 522 1.1 christos 523 1.1 christos MAYBE_LOCK(sdlz->dlzimp); 524 1.1 christos 525 1.1 christos /* try to lookup the host (namestr) */ 526 1.6 christos result = sdlz->dlzimp->methods->lookup( 527 1.6 christos zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node, 528 1.6 christos methods, clientinfo); 529 1.1 christos 530 1.1 christos /* 531 1.1 christos * If the name was not found and DNS_DBFIND_NOWILD is not 532 1.1 christos * set, then we try to find a wildcard entry. 533 1.1 christos * 534 1.1 christos * If DNS_DBFIND_NOZONECUT is set and there are multiple 535 1.1 christos * levels between the host and the zone origin, we also look 536 1.1 christos * for wildcards at each level. 537 1.1 christos */ 538 1.1 christos if (result == ISC_R_NOTFOUND && !create && 539 1.11 christos (options & DNS_DBFIND_NOWILD) == 0) 540 1.11 christos { 541 1.1 christos unsigned int i, dlabels, nlabels; 542 1.1 christos 543 1.1 christos nlabels = dns_name_countlabels(name); 544 1.1 christos dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin); 545 1.1 christos for (i = 0; i < dlabels; i++) { 546 1.1 christos char wildstr[DNS_NAME_MAXTEXT + 1]; 547 1.1 christos dns_fixedname_t fixed; 548 1.1 christos const dns_name_t *wild; 549 1.1 christos 550 1.1 christos dns_fixedname_init(&fixed); 551 1.4 christos if (i == dlabels - 1) { 552 1.1 christos wild = dns_wildcardname; 553 1.4 christos } else { 554 1.1 christos dns_name_t *fname; 555 1.1 christos fname = dns_fixedname_name(&fixed); 556 1.6 christos dns_name_getlabelsequence( 557 1.6 christos name, i + 1, dlabels - i - 1, fname); 558 1.6 christos result = dns_name_concatenate( 559 1.6 christos dns_wildcardname, fname, fname, NULL); 560 1.4 christos if (result != ISC_R_SUCCESS) { 561 1.4 christos MAYBE_UNLOCK(sdlz->dlzimp); 562 1.14 christos return result; 563 1.4 christos } 564 1.1 christos wild = fname; 565 1.1 christos } 566 1.1 christos 567 1.1 christos isc_buffer_init(&b, wildstr, sizeof(wildstr)); 568 1.14 christos result = dns_name_totext(wild, DNS_NAME_OMITFINALDOT, 569 1.14 christos &b); 570 1.4 christos if (result != ISC_R_SUCCESS) { 571 1.4 christos MAYBE_UNLOCK(sdlz->dlzimp); 572 1.14 christos return result; 573 1.4 christos } 574 1.1 christos isc_buffer_putuint8(&b, 0); 575 1.1 christos 576 1.6 christos result = sdlz->dlzimp->methods->lookup( 577 1.6 christos zonestr, wildstr, sdlz->dlzimp->driverarg, 578 1.6 christos sdlz->dbdata, node, methods, clientinfo); 579 1.6 christos if (result == ISC_R_SUCCESS) { 580 1.1 christos break; 581 1.6 christos } 582 1.1 christos } 583 1.1 christos } 584 1.1 christos 585 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp); 586 1.1 christos 587 1.6 christos if (result == ISC_R_NOTFOUND && (isorigin || create)) { 588 1.1 christos result = ISC_R_SUCCESS; 589 1.6 christos } 590 1.1 christos 591 1.1 christos if (result != ISC_R_SUCCESS) { 592 1.8 christos isc_refcount_decrementz(&node->references); 593 1.1 christos destroynode(node); 594 1.14 christos return result; 595 1.1 christos } 596 1.1 christos 597 1.1 christos if (isorigin && sdlz->dlzimp->methods->authority != NULL) { 598 1.1 christos MAYBE_LOCK(sdlz->dlzimp); 599 1.1 christos authority = sdlz->dlzimp->methods->authority; 600 1.1 christos result = (*authority)(zonestr, sdlz->dlzimp->driverarg, 601 1.1 christos sdlz->dbdata, node); 602 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp); 603 1.6 christos if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) { 604 1.8 christos isc_refcount_decrementz(&node->references); 605 1.1 christos destroynode(node); 606 1.14 christos return result; 607 1.1 christos } 608 1.1 christos } 609 1.1 christos 610 1.1 christos if (node->name == NULL) { 611 1.6 christos node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t)); 612 1.1 christos dns_name_init(node->name, NULL); 613 1.6 christos dns_name_dup(name, sdlz->common.mctx, node->name); 614 1.1 christos } 615 1.1 christos 616 1.1 christos *nodep = node; 617 1.14 christos return ISC_R_SUCCESS; 618 1.1 christos } 619 1.1 christos 620 1.1 christos static isc_result_t 621 1.3 christos findnodeext(dns_db_t *db, const dns_name_t *name, bool create, 622 1.1 christos dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 623 1.14 christos dns_dbnode_t **nodep DNS__DB_FLARG) { 624 1.14 christos return getnodedata(db, name, create, 0, methods, clientinfo, nodep); 625 1.1 christos } 626 1.1 christos 627 1.1 christos static isc_result_t 628 1.3 christos findnode(dns_db_t *db, const dns_name_t *name, bool create, 629 1.14 christos dns_dbnode_t **nodep DNS__DB_FLARG) { 630 1.14 christos return getnodedata(db, name, create, 0, NULL, NULL, nodep); 631 1.1 christos } 632 1.1 christos 633 1.1 christos static void 634 1.14 christos attachnode(dns_db_t *db, dns_dbnode_t *source, 635 1.14 christos dns_dbnode_t **targetp DNS__DB_FLARG) { 636 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 637 1.1 christos dns_sdlznode_t *node = (dns_sdlznode_t *)source; 638 1.14 christos uint_fast32_t refs; 639 1.1 christos 640 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 641 1.1 christos 642 1.1 christos UNUSED(sdlz); 643 1.1 christos 644 1.14 christos refs = isc_refcount_increment(&node->references); 645 1.14 christos #if DNS_DB_NODETRACE 646 1.14 christos fprintf(stderr, "incr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n", 647 1.14 christos func, file, line, node, refs + 1); 648 1.14 christos #else 649 1.14 christos UNUSED(refs); 650 1.14 christos #endif 651 1.1 christos 652 1.1 christos *targetp = source; 653 1.1 christos } 654 1.1 christos 655 1.1 christos static void 656 1.14 christos detachnode(dns_db_t *db, dns_dbnode_t **targetp DNS__DB_FLARG) { 657 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 658 1.1 christos dns_sdlznode_t *node; 659 1.14 christos uint_fast32_t refs; 660 1.1 christos 661 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 662 1.1 christos REQUIRE(targetp != NULL && *targetp != NULL); 663 1.1 christos 664 1.1 christos UNUSED(sdlz); 665 1.1 christos 666 1.1 christos node = (dns_sdlznode_t *)(*targetp); 667 1.6 christos *targetp = NULL; 668 1.1 christos 669 1.14 christos refs = isc_refcount_decrement(&node->references); 670 1.14 christos #if DNS_DB_NODETRACE 671 1.14 christos fprintf(stderr, "decr:node:%s:%s:%u:%p->references = %" PRIuFAST32 "\n", 672 1.14 christos func, file, line, node, refs - 1); 673 1.14 christos #else 674 1.14 christos UNUSED(refs); 675 1.14 christos #endif 676 1.14 christos 677 1.14 christos if (refs == 1) { 678 1.1 christos destroynode(node); 679 1.6 christos } 680 1.1 christos } 681 1.1 christos 682 1.1 christos static isc_result_t 683 1.6 christos createiterator(dns_db_t *db, unsigned int options, 684 1.6 christos dns_dbiterator_t **iteratorp) { 685 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 686 1.1 christos sdlz_dbiterator_t *sdlziter; 687 1.1 christos isc_result_t result; 688 1.1 christos isc_buffer_t b; 689 1.1 christos char zonestr[DNS_NAME_MAXTEXT + 1]; 690 1.1 christos 691 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 692 1.1 christos 693 1.6 christos if (sdlz->dlzimp->methods->allnodes == NULL) { 694 1.14 christos return ISC_R_NOTIMPLEMENTED; 695 1.6 christos } 696 1.1 christos 697 1.1 christos if ((options & DNS_DB_NSEC3ONLY) != 0 || 698 1.11 christos (options & DNS_DB_NONSEC3) != 0) 699 1.11 christos { 700 1.14 christos return ISC_R_NOTIMPLEMENTED; 701 1.6 christos } 702 1.1 christos 703 1.1 christos isc_buffer_init(&b, zonestr, sizeof(zonestr)); 704 1.14 christos result = dns_name_totext(&sdlz->common.origin, DNS_NAME_OMITFINALDOT, 705 1.14 christos &b); 706 1.6 christos if (result != ISC_R_SUCCESS) { 707 1.14 christos return result; 708 1.6 christos } 709 1.1 christos isc_buffer_putuint8(&b, 0); 710 1.1 christos 711 1.1 christos sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t)); 712 1.1 christos 713 1.1 christos sdlziter->common.methods = &dbiterator_methods; 714 1.1 christos sdlziter->common.db = NULL; 715 1.1 christos dns_db_attach(db, &sdlziter->common.db); 716 1.6 christos sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) != 717 1.6 christos 0); 718 1.1 christos sdlziter->common.magic = DNS_DBITERATOR_MAGIC; 719 1.1 christos ISC_LIST_INIT(sdlziter->nodelist); 720 1.1 christos sdlziter->current = NULL; 721 1.1 christos sdlziter->origin = NULL; 722 1.1 christos 723 1.1 christos /* make sure strings are always lowercase */ 724 1.14 christos isc_ascii_strtolower(zonestr); 725 1.1 christos 726 1.1 christos MAYBE_LOCK(sdlz->dlzimp); 727 1.6 christos result = sdlz->dlzimp->methods->allnodes( 728 1.6 christos zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter); 729 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp); 730 1.1 christos if (result != ISC_R_SUCCESS) { 731 1.1 christos dns_dbiterator_t *iter = &sdlziter->common; 732 1.14 christos dbiterator_destroy(&iter DNS__DB_FILELINE); 733 1.14 christos return result; 734 1.1 christos } 735 1.1 christos 736 1.1 christos if (sdlziter->origin != NULL) { 737 1.1 christos ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link); 738 1.1 christos ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link); 739 1.1 christos } 740 1.1 christos 741 1.1 christos *iteratorp = (dns_dbiterator_t *)sdlziter; 742 1.1 christos 743 1.14 christos return ISC_R_SUCCESS; 744 1.1 christos } 745 1.1 christos 746 1.1 christos static isc_result_t 747 1.1 christos findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 748 1.6 christos dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now, 749 1.14 christos dns_rdataset_t *rdataset, 750 1.14 christos dns_rdataset_t *sigrdataset DNS__DB_FLARG) { 751 1.6 christos REQUIRE(VALID_SDLZNODE(node)); 752 1.1 christos dns_rdatalist_t *list; 753 1.1 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 754 1.1 christos 755 1.1 christos UNUSED(db); 756 1.1 christos UNUSED(version); 757 1.1 christos UNUSED(covers); 758 1.1 christos UNUSED(now); 759 1.1 christos UNUSED(sigrdataset); 760 1.1 christos 761 1.6 christos if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) { 762 1.14 christos return ISC_R_NOTIMPLEMENTED; 763 1.6 christos } 764 1.1 christos 765 1.1 christos list = ISC_LIST_HEAD(sdlznode->lists); 766 1.1 christos while (list != NULL) { 767 1.6 christos if (list->type == type) { 768 1.1 christos break; 769 1.6 christos } 770 1.1 christos list = ISC_LIST_NEXT(list, link); 771 1.1 christos } 772 1.6 christos if (list == NULL) { 773 1.14 christos return ISC_R_NOTFOUND; 774 1.6 christos } 775 1.1 christos 776 1.1 christos list_tordataset(list, db, node, rdataset); 777 1.1 christos 778 1.14 christos return ISC_R_SUCCESS; 779 1.1 christos } 780 1.1 christos 781 1.1 christos static isc_result_t 782 1.1 christos findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 783 1.1 christos dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 784 1.1 christos dns_dbnode_t **nodep, dns_name_t *foundname, 785 1.1 christos dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 786 1.14 christos dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset DNS__DB_FLARG) { 787 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 788 1.1 christos dns_dbnode_t *node = NULL; 789 1.1 christos dns_fixedname_t fname; 790 1.1 christos dns_rdataset_t xrdataset; 791 1.1 christos dns_name_t *xname; 792 1.1 christos unsigned int nlabels, olabels; 793 1.1 christos isc_result_t result; 794 1.1 christos unsigned int i; 795 1.1 christos 796 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 797 1.1 christos REQUIRE(nodep == NULL || *nodep == NULL); 798 1.6 christos REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version || 799 1.1 christos version == sdlz->future_version); 800 1.1 christos 801 1.1 christos UNUSED(sdlz); 802 1.1 christos 803 1.6 christos if (!dns_name_issubdomain(name, &db->origin)) { 804 1.14 christos return DNS_R_NXDOMAIN; 805 1.6 christos } 806 1.1 christos 807 1.1 christos olabels = dns_name_countlabels(&db->origin); 808 1.1 christos nlabels = dns_name_countlabels(name); 809 1.1 christos 810 1.1 christos xname = dns_fixedname_initname(&fname); 811 1.1 christos 812 1.1 christos if (rdataset == NULL) { 813 1.1 christos dns_rdataset_init(&xrdataset); 814 1.1 christos rdataset = &xrdataset; 815 1.1 christos } 816 1.1 christos 817 1.1 christos result = DNS_R_NXDOMAIN; 818 1.1 christos 819 1.1 christos /* 820 1.1 christos * If we're not walking down searching for zone 821 1.1 christos * cuts, we can cut straight to the chase 822 1.1 christos */ 823 1.1 christos if ((options & DNS_DBFIND_NOZONECUT) != 0) { 824 1.1 christos i = nlabels; 825 1.1 christos goto search; 826 1.1 christos } 827 1.1 christos 828 1.1 christos for (i = olabels; i <= nlabels; i++) { 829 1.6 christos search: 830 1.1 christos /* 831 1.1 christos * Look up the next label. 832 1.1 christos */ 833 1.1 christos dns_name_getlabelsequence(name, nlabels - i, i, xname); 834 1.6 christos result = getnodedata(db, xname, false, options, methods, 835 1.6 christos clientinfo, &node); 836 1.1 christos if (result == ISC_R_NOTFOUND) { 837 1.1 christos result = DNS_R_NXDOMAIN; 838 1.1 christos continue; 839 1.6 christos } else if (result != ISC_R_SUCCESS) { 840 1.1 christos break; 841 1.6 christos } 842 1.1 christos 843 1.1 christos /* 844 1.1 christos * Look for a DNAME at the current label, unless this is 845 1.1 christos * the qname. 846 1.1 christos */ 847 1.1 christos if (i < nlabels) { 848 1.14 christos result = findrdataset( 849 1.14 christos db, node, version, dns_rdatatype_dname, 0, now, 850 1.14 christos rdataset, sigrdataset DNS__DB_FLARG_PASS); 851 1.1 christos if (result == ISC_R_SUCCESS) { 852 1.1 christos result = DNS_R_DNAME; 853 1.1 christos break; 854 1.1 christos } 855 1.1 christos } 856 1.1 christos 857 1.1 christos /* 858 1.1 christos * Look for an NS at the current label, unless this is the 859 1.1 christos * origin, glue is ok, or there are known to be no zone cuts. 860 1.1 christos */ 861 1.1 christos if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 && 862 1.1 christos (options & DNS_DBFIND_NOZONECUT) == 0) 863 1.1 christos { 864 1.14 christos result = findrdataset( 865 1.14 christos db, node, version, dns_rdatatype_ns, 0, now, 866 1.14 christos rdataset, sigrdataset DNS__DB_FLARG_PASS); 867 1.1 christos 868 1.6 christos if (result == ISC_R_SUCCESS && i == nlabels && 869 1.11 christos type == dns_rdatatype_any) 870 1.11 christos { 871 1.1 christos result = DNS_R_ZONECUT; 872 1.1 christos dns_rdataset_disassociate(rdataset); 873 1.1 christos if (sigrdataset != NULL && 874 1.11 christos dns_rdataset_isassociated(sigrdataset)) 875 1.11 christos { 876 1.1 christos dns_rdataset_disassociate(sigrdataset); 877 1.6 christos } 878 1.1 christos break; 879 1.1 christos } else if (result == ISC_R_SUCCESS) { 880 1.1 christos result = DNS_R_DELEGATION; 881 1.1 christos break; 882 1.1 christos } 883 1.1 christos } 884 1.1 christos 885 1.1 christos /* 886 1.1 christos * If the current name is not the qname, add another label 887 1.1 christos * and try again. 888 1.1 christos */ 889 1.1 christos if (i < nlabels) { 890 1.14 christos detachnode(db, &node DNS__DB_FLARG_PASS); 891 1.1 christos node = NULL; 892 1.1 christos continue; 893 1.1 christos } 894 1.1 christos 895 1.1 christos /* 896 1.1 christos * If we're looking for ANY, we're done. 897 1.1 christos */ 898 1.1 christos if (type == dns_rdatatype_any) { 899 1.1 christos result = ISC_R_SUCCESS; 900 1.1 christos break; 901 1.1 christos } 902 1.1 christos 903 1.1 christos /* 904 1.1 christos * Look for the qtype. 905 1.1 christos */ 906 1.6 christos result = findrdataset(db, node, version, type, 0, now, rdataset, 907 1.14 christos sigrdataset DNS__DB_FLARG_PASS); 908 1.6 christos if (result == ISC_R_SUCCESS) { 909 1.1 christos break; 910 1.6 christos } 911 1.1 christos 912 1.1 christos /* 913 1.1 christos * Look for a CNAME 914 1.1 christos */ 915 1.1 christos if (type != dns_rdatatype_cname) { 916 1.14 christos result = findrdataset( 917 1.14 christos db, node, version, dns_rdatatype_cname, 0, now, 918 1.14 christos rdataset, sigrdataset DNS__DB_FLARG_PASS); 919 1.1 christos if (result == ISC_R_SUCCESS) { 920 1.1 christos result = DNS_R_CNAME; 921 1.1 christos break; 922 1.1 christos } 923 1.1 christos } 924 1.1 christos 925 1.1 christos result = DNS_R_NXRRSET; 926 1.1 christos break; 927 1.1 christos } 928 1.1 christos 929 1.6 christos if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) { 930 1.1 christos dns_rdataset_disassociate(rdataset); 931 1.6 christos } 932 1.1 christos 933 1.1 christos if (foundname != NULL) { 934 1.12 christos dns_name_copy(xname, foundname); 935 1.1 christos } 936 1.1 christos 937 1.6 christos if (nodep != NULL) { 938 1.1 christos *nodep = node; 939 1.6 christos } else if (node != NULL) { 940 1.14 christos detachnode(db, &node DNS__DB_FLARG_PASS); 941 1.6 christos } 942 1.1 christos 943 1.14 christos return result; 944 1.1 christos } 945 1.1 christos 946 1.1 christos static isc_result_t 947 1.1 christos find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version, 948 1.1 christos dns_rdatatype_t type, unsigned int options, isc_stdtime_t now, 949 1.6 christos dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset, 950 1.14 christos dns_rdataset_t *sigrdataset DNS__DB_FLARG) { 951 1.14 christos return findext(db, name, version, type, options, now, nodep, foundname, 952 1.14 christos NULL, NULL, rdataset, sigrdataset DNS__DB_FLARG_PASS); 953 1.1 christos } 954 1.1 christos 955 1.1 christos static isc_result_t 956 1.1 christos allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 957 1.11 christos unsigned int options, isc_stdtime_t now, 958 1.14 christos dns_rdatasetiter_t **iteratorp DNS__DB_FLARG) { 959 1.6 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 960 1.1 christos sdlz_rdatasetiter_t *iterator; 961 1.1 christos 962 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 963 1.1 christos 964 1.6 christos REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version || 965 1.1 christos version == sdlz->future_version); 966 1.1 christos 967 1.1 christos UNUSED(version); 968 1.1 christos UNUSED(now); 969 1.1 christos 970 1.1 christos iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t)); 971 1.1 christos 972 1.1 christos iterator->common.magic = DNS_RDATASETITER_MAGIC; 973 1.1 christos iterator->common.methods = &rdatasetiter_methods; 974 1.1 christos iterator->common.db = db; 975 1.1 christos iterator->common.node = NULL; 976 1.14 christos attachnode(db, node, &iterator->common.node DNS__DB_FLARG_PASS); 977 1.1 christos iterator->common.version = version; 978 1.11 christos iterator->common.options = options; 979 1.1 christos iterator->common.now = now; 980 1.1 christos 981 1.1 christos *iteratorp = (dns_rdatasetiter_t *)iterator; 982 1.1 christos 983 1.14 christos return ISC_R_SUCCESS; 984 1.1 christos } 985 1.1 christos 986 1.1 christos static isc_result_t 987 1.1 christos modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 988 1.1 christos dns_rdataset_t *rdataset, unsigned int options, 989 1.6 christos dns_sdlzmodrdataset_t mod_function) { 990 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 991 1.1 christos dns_master_style_t *style = NULL; 992 1.1 christos isc_result_t result; 993 1.1 christos isc_buffer_t *buffer = NULL; 994 1.1 christos isc_mem_t *mctx; 995 1.1 christos dns_sdlznode_t *sdlznode; 996 1.1 christos char *rdatastr = NULL; 997 1.1 christos char name[DNS_NAME_MAXTEXT + 1]; 998 1.1 christos 999 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 1000 1.1 christos 1001 1.6 christos if (mod_function == NULL) { 1002 1.14 christos return ISC_R_NOTIMPLEMENTED; 1003 1.6 christos } 1004 1.1 christos 1005 1.1 christos sdlznode = (dns_sdlznode_t *)node; 1006 1.1 christos 1007 1.1 christos UNUSED(options); 1008 1.1 christos 1009 1.1 christos dns_name_format(sdlznode->name, name, sizeof(name)); 1010 1.1 christos 1011 1.1 christos mctx = sdlz->common.mctx; 1012 1.1 christos 1013 1.6 christos isc_buffer_allocate(mctx, &buffer, 1024); 1014 1.1 christos 1015 1.6 christos result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff, 1016 1.6 christos mctx); 1017 1.6 christos if (result != ISC_R_SUCCESS) { 1018 1.1 christos goto cleanup; 1019 1.6 christos } 1020 1.1 christos 1021 1.6 christos result = dns_master_rdatasettotext(sdlznode->name, rdataset, style, 1022 1.6 christos NULL, buffer); 1023 1.6 christos if (result != ISC_R_SUCCESS) { 1024 1.1 christos goto cleanup; 1025 1.6 christos } 1026 1.1 christos 1027 1.1 christos if (isc_buffer_usedlength(buffer) < 1) { 1028 1.1 christos result = ISC_R_BADADDRESSFORM; 1029 1.1 christos goto cleanup; 1030 1.1 christos } 1031 1.1 christos 1032 1.1 christos rdatastr = isc_buffer_base(buffer); 1033 1.1 christos if (rdatastr == NULL) { 1034 1.1 christos result = ISC_R_NOMEMORY; 1035 1.1 christos goto cleanup; 1036 1.1 christos } 1037 1.1 christos rdatastr[isc_buffer_usedlength(buffer) - 1] = 0; 1038 1.1 christos 1039 1.1 christos MAYBE_LOCK(sdlz->dlzimp); 1040 1.1 christos result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg, 1041 1.1 christos sdlz->dbdata, version); 1042 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp); 1043 1.1 christos 1044 1.1 christos cleanup: 1045 1.1 christos isc_buffer_free(&buffer); 1046 1.6 christos if (style != NULL) { 1047 1.1 christos dns_master_styledestroy(&style, mctx); 1048 1.6 christos } 1049 1.1 christos 1050 1.14 christos return result; 1051 1.1 christos } 1052 1.1 christos 1053 1.1 christos static isc_result_t 1054 1.1 christos addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1055 1.1 christos isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options, 1056 1.14 christos dns_rdataset_t *addedrdataset DNS__DB_FLARG) { 1057 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1058 1.1 christos isc_result_t result; 1059 1.1 christos 1060 1.1 christos UNUSED(now); 1061 1.1 christos UNUSED(addedrdataset); 1062 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 1063 1.1 christos 1064 1.6 christos if (sdlz->dlzimp->methods->addrdataset == NULL) { 1065 1.14 christos return ISC_R_NOTIMPLEMENTED; 1066 1.6 christos } 1067 1.1 christos 1068 1.1 christos result = modrdataset(db, node, version, rdataset, options, 1069 1.1 christos sdlz->dlzimp->methods->addrdataset); 1070 1.14 christos return result; 1071 1.1 christos } 1072 1.1 christos 1073 1.1 christos static isc_result_t 1074 1.1 christos subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1075 1.1 christos dns_rdataset_t *rdataset, unsigned int options, 1076 1.14 christos dns_rdataset_t *newrdataset DNS__DB_FLARG) { 1077 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1078 1.1 christos isc_result_t result; 1079 1.1 christos 1080 1.1 christos UNUSED(newrdataset); 1081 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 1082 1.1 christos 1083 1.1 christos if (sdlz->dlzimp->methods->subtractrdataset == NULL) { 1084 1.14 christos return ISC_R_NOTIMPLEMENTED; 1085 1.1 christos } 1086 1.1 christos 1087 1.1 christos result = modrdataset(db, node, version, rdataset, options, 1088 1.1 christos sdlz->dlzimp->methods->subtractrdataset); 1089 1.14 christos return result; 1090 1.1 christos } 1091 1.1 christos 1092 1.1 christos static isc_result_t 1093 1.1 christos deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, 1094 1.14 christos dns_rdatatype_t type, dns_rdatatype_t covers DNS__DB_FLARG) { 1095 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1096 1.1 christos char name[DNS_NAME_MAXTEXT + 1]; 1097 1.1 christos char b_type[DNS_RDATATYPE_FORMATSIZE]; 1098 1.1 christos dns_sdlznode_t *sdlznode; 1099 1.1 christos isc_result_t result; 1100 1.1 christos 1101 1.1 christos UNUSED(covers); 1102 1.1 christos 1103 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 1104 1.1 christos 1105 1.6 christos if (sdlz->dlzimp->methods->delrdataset == NULL) { 1106 1.14 christos return ISC_R_NOTIMPLEMENTED; 1107 1.6 christos } 1108 1.1 christos 1109 1.1 christos sdlznode = (dns_sdlznode_t *)node; 1110 1.1 christos dns_name_format(sdlznode->name, name, sizeof(name)); 1111 1.1 christos dns_rdatatype_format(type, b_type, sizeof(b_type)); 1112 1.1 christos 1113 1.1 christos MAYBE_LOCK(sdlz->dlzimp); 1114 1.6 christos result = sdlz->dlzimp->methods->delrdataset( 1115 1.6 christos name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version); 1116 1.1 christos MAYBE_UNLOCK(sdlz->dlzimp); 1117 1.1 christos 1118 1.14 christos return result; 1119 1.1 christos } 1120 1.1 christos 1121 1.3 christos static bool 1122 1.1 christos issecure(dns_db_t *db) { 1123 1.1 christos UNUSED(db); 1124 1.1 christos 1125 1.14 christos return false; 1126 1.1 christos } 1127 1.1 christos 1128 1.1 christos static unsigned int 1129 1.12 christos nodecount(dns_db_t *db, dns_dbtree_t tree) { 1130 1.1 christos UNUSED(db); 1131 1.12 christos UNUSED(tree); 1132 1.1 christos 1133 1.14 christos return 0; 1134 1.1 christos } 1135 1.1 christos 1136 1.1 christos static void 1137 1.14 christos setloop(dns_db_t *db, isc_loop_t *loop) { 1138 1.1 christos UNUSED(db); 1139 1.14 christos UNUSED(loop); 1140 1.1 christos } 1141 1.1 christos 1142 1.1 christos /* 1143 1.1 christos * getoriginnode() is used by the update code to find the 1144 1.1 christos * dns_rdatatype_dnskey record for a zone 1145 1.1 christos */ 1146 1.1 christos static isc_result_t 1147 1.14 christos getoriginnode(dns_db_t *db, dns_dbnode_t **nodep DNS__DB_FLARG) { 1148 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db; 1149 1.1 christos isc_result_t result; 1150 1.1 christos 1151 1.1 christos REQUIRE(VALID_SDLZDB(sdlz)); 1152 1.6 christos if (sdlz->dlzimp->methods->newversion == NULL) { 1153 1.14 christos return ISC_R_NOTIMPLEMENTED; 1154 1.6 christos } 1155 1.1 christos 1156 1.6 christos result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL, 1157 1.6 christos nodep); 1158 1.6 christos if (result != ISC_R_SUCCESS) { 1159 1.1 christos sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s", 1160 1.1 christos isc_result_totext(result)); 1161 1.6 christos } 1162 1.14 christos return result; 1163 1.1 christos } 1164 1.1 christos 1165 1.1 christos static dns_dbmethods_t sdlzdb_methods = { 1166 1.14 christos .destroy = destroy, 1167 1.14 christos .currentversion = currentversion, 1168 1.14 christos .newversion = newversion, 1169 1.14 christos .attachversion = attachversion, 1170 1.14 christos .closeversion = closeversion, 1171 1.14 christos .findnode = findnode, 1172 1.14 christos .find = find, 1173 1.14 christos .attachnode = attachnode, 1174 1.14 christos .detachnode = detachnode, 1175 1.14 christos .createiterator = createiterator, 1176 1.14 christos .findrdataset = findrdataset, 1177 1.14 christos .allrdatasets = allrdatasets, 1178 1.14 christos .addrdataset = addrdataset, 1179 1.14 christos .subtractrdataset = subtractrdataset, 1180 1.14 christos .deleterdataset = deleterdataset, 1181 1.14 christos .issecure = issecure, 1182 1.14 christos .nodecount = nodecount, 1183 1.14 christos .setloop = setloop, 1184 1.14 christos .getoriginnode = getoriginnode, 1185 1.14 christos .findnodeext = findnodeext, 1186 1.14 christos .findext = findext, 1187 1.1 christos }; 1188 1.1 christos 1189 1.1 christos /* 1190 1.1 christos * Database Iterator Methods. These methods were "borrowed" from the SDB 1191 1.1 christos * driver interface. See the SDB driver interface documentation for more info. 1192 1.1 christos */ 1193 1.1 christos 1194 1.1 christos static void 1195 1.14 christos dbiterator_destroy(dns_dbiterator_t **iteratorp DNS__DB_FLARG) { 1196 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp); 1197 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db; 1198 1.1 christos 1199 1.1 christos while (!ISC_LIST_EMPTY(sdlziter->nodelist)) { 1200 1.1 christos dns_sdlznode_t *node; 1201 1.1 christos node = ISC_LIST_HEAD(sdlziter->nodelist); 1202 1.1 christos ISC_LIST_UNLINK(sdlziter->nodelist, node, link); 1203 1.8 christos isc_refcount_decrementz(&node->references); 1204 1.1 christos destroynode(node); 1205 1.1 christos } 1206 1.1 christos 1207 1.1 christos dns_db_detach(&sdlziter->common.db); 1208 1.1 christos isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t)); 1209 1.1 christos 1210 1.1 christos *iteratorp = NULL; 1211 1.1 christos } 1212 1.1 christos 1213 1.1 christos static isc_result_t 1214 1.14 christos dbiterator_first(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1215 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1216 1.1 christos 1217 1.1 christos sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1218 1.6 christos if (sdlziter->current == NULL) { 1219 1.14 christos return ISC_R_NOMORE; 1220 1.6 christos } else { 1221 1.14 christos return ISC_R_SUCCESS; 1222 1.6 christos } 1223 1.1 christos } 1224 1.1 christos 1225 1.1 christos static isc_result_t 1226 1.14 christos dbiterator_last(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1227 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1228 1.1 christos 1229 1.1 christos sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist); 1230 1.6 christos if (sdlziter->current == NULL) { 1231 1.14 christos return ISC_R_NOMORE; 1232 1.6 christos } else { 1233 1.14 christos return ISC_R_SUCCESS; 1234 1.6 christos } 1235 1.1 christos } 1236 1.1 christos 1237 1.1 christos static isc_result_t 1238 1.14 christos dbiterator_seek(dns_dbiterator_t *iterator, 1239 1.14 christos const dns_name_t *name DNS__DB_FLARG) { 1240 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1241 1.1 christos 1242 1.1 christos sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist); 1243 1.1 christos while (sdlziter->current != NULL) { 1244 1.6 christos if (dns_name_equal(sdlziter->current->name, name)) { 1245 1.14 christos return ISC_R_SUCCESS; 1246 1.6 christos } 1247 1.1 christos sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); 1248 1.1 christos } 1249 1.14 christos return ISC_R_NOTFOUND; 1250 1.1 christos } 1251 1.1 christos 1252 1.1 christos static isc_result_t 1253 1.15 christos dbiterator_seek3(dns_dbiterator_t *iterator ISC_ATTR_UNUSED, 1254 1.15 christos const dns_name_t *name ISC_ATTR_UNUSED DNS__DB_FLARG) { 1255 1.15 christos return ISC_R_NOTIMPLEMENTED; 1256 1.15 christos } 1257 1.15 christos 1258 1.15 christos static isc_result_t 1259 1.14 christos dbiterator_prev(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1260 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1261 1.1 christos 1262 1.1 christos sdlziter->current = ISC_LIST_PREV(sdlziter->current, link); 1263 1.6 christos if (sdlziter->current == NULL) { 1264 1.14 christos return ISC_R_NOMORE; 1265 1.6 christos } else { 1266 1.14 christos return ISC_R_SUCCESS; 1267 1.6 christos } 1268 1.1 christos } 1269 1.1 christos 1270 1.1 christos static isc_result_t 1271 1.14 christos dbiterator_next(dns_dbiterator_t *iterator DNS__DB_FLARG) { 1272 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1273 1.1 christos 1274 1.1 christos sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link); 1275 1.6 christos if (sdlziter->current == NULL) { 1276 1.14 christos return ISC_R_NOMORE; 1277 1.6 christos } else { 1278 1.14 christos return ISC_R_SUCCESS; 1279 1.6 christos } 1280 1.1 christos } 1281 1.1 christos 1282 1.1 christos static isc_result_t 1283 1.1 christos dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep, 1284 1.14 christos dns_name_t *name DNS__DB_FLARG) { 1285 1.1 christos sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator; 1286 1.1 christos 1287 1.14 christos attachnode(iterator->db, sdlziter->current, nodep DNS__DB_FLARG_PASS); 1288 1.5 christos if (name != NULL) { 1289 1.12 christos dns_name_copy(sdlziter->current->name, name); 1290 1.14 christos return ISC_R_SUCCESS; 1291 1.5 christos } 1292 1.14 christos return ISC_R_SUCCESS; 1293 1.1 christos } 1294 1.1 christos 1295 1.1 christos static isc_result_t 1296 1.1 christos dbiterator_pause(dns_dbiterator_t *iterator) { 1297 1.1 christos UNUSED(iterator); 1298 1.14 christos return ISC_R_SUCCESS; 1299 1.1 christos } 1300 1.1 christos 1301 1.1 christos static isc_result_t 1302 1.1 christos dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) { 1303 1.1 christos UNUSED(iterator); 1304 1.12 christos dns_name_copy(dns_rootname, name); 1305 1.14 christos return ISC_R_SUCCESS; 1306 1.1 christos } 1307 1.1 christos 1308 1.1 christos /* 1309 1.1 christos * Rdataset Methods. These methods were "borrowed" from the SDB driver 1310 1.1 christos * interface. See the SDB driver interface documentation for more info. 1311 1.1 christos */ 1312 1.1 christos 1313 1.1 christos static void 1314 1.14 christos disassociate(dns_rdataset_t *rdataset DNS__DB_FLARG) { 1315 1.14 christos dns_dbnode_t *node = rdataset->rdlist.node; 1316 1.6 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 1317 1.6 christos dns_db_t *db = (dns_db_t *)sdlznode->sdlz; 1318 1.1 christos 1319 1.14 christos detachnode(db, &node DNS__DB_FLARG_PASS); 1320 1.14 christos dns_rdatalist_disassociate(rdataset DNS__DB_FLARG_PASS); 1321 1.1 christos } 1322 1.1 christos 1323 1.1 christos static void 1324 1.14 christos rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target DNS__DB_FLARG) { 1325 1.14 christos dns_dbnode_t *node = source->rdlist.node; 1326 1.6 christos dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node; 1327 1.6 christos dns_db_t *db = (dns_db_t *)sdlznode->sdlz; 1328 1.1 christos 1329 1.14 christos dns_rdatalist_clone(source, target DNS__DB_FLARG_PASS); 1330 1.14 christos attachnode(db, node, &target->rdlist.node DNS__DB_FLARG_PASS); 1331 1.1 christos } 1332 1.1 christos 1333 1.1 christos static dns_rdatasetmethods_t rdataset_methods = { 1334 1.14 christos .disassociate = disassociate, 1335 1.14 christos .first = dns_rdatalist_first, 1336 1.14 christos .next = dns_rdatalist_next, 1337 1.14 christos .current = dns_rdatalist_current, 1338 1.14 christos .clone = rdataset_clone, 1339 1.14 christos .count = dns_rdatalist_count, 1340 1.14 christos .addnoqname = dns_rdatalist_addnoqname, 1341 1.14 christos .getnoqname = dns_rdatalist_getnoqname, 1342 1.1 christos }; 1343 1.1 christos 1344 1.1 christos static void 1345 1.6 christos list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node, 1346 1.6 christos dns_rdataset_t *rdataset) { 1347 1.1 christos /* 1348 1.14 christos * The sdlz rdataset is an rdatalist, but additionally holds 1349 1.14 christos * a database node reference. 1350 1.1 christos */ 1351 1.1 christos 1352 1.14 christos dns_rdatalist_tordataset(rdatalist, rdataset); 1353 1.1 christos rdataset->methods = &rdataset_methods; 1354 1.14 christos dns_db_attachnode(db, node, &rdataset->rdlist.node); 1355 1.1 christos } 1356 1.1 christos 1357 1.1 christos /* 1358 1.1 christos * SDLZ core methods. This is the core of the new DLZ functionality. 1359 1.1 christos */ 1360 1.1 christos 1361 1.1 christos /*% 1362 1.1 christos * Build a 'bind' database driver structure to be returned by 1363 1.1 christos * either the find zone or the allow zone transfer method. 1364 1.1 christos * This method is only available in this source file, it is 1365 1.1 christos * not made available anywhere else. 1366 1.1 christos */ 1367 1.1 christos 1368 1.1 christos static isc_result_t 1369 1.1 christos dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata, 1370 1.1 christos const dns_name_t *name, dns_rdataclass_t rdclass, 1371 1.6 christos dns_db_t **dbp) { 1372 1.1 christos dns_sdlz_db_t *sdlzdb; 1373 1.1 christos dns_sdlzimplementation_t *imp; 1374 1.1 christos 1375 1.1 christos /* check that things are as we expect */ 1376 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL); 1377 1.1 christos REQUIRE(name != NULL); 1378 1.1 christos 1379 1.6 christos imp = (dns_sdlzimplementation_t *)driverarg; 1380 1.1 christos 1381 1.1 christos /* allocate and zero memory for driver structure */ 1382 1.14 christos sdlzdb = isc_mem_get(mctx, sizeof(*sdlzdb)); 1383 1.14 christos 1384 1.14 christos *sdlzdb = (dns_sdlz_db_t) { 1385 1.14 christos .dlzimp = imp, 1386 1.14 christos .common = { .methods = &sdlzdb_methods, 1387 1.14 christos .rdclass = rdclass, }, 1388 1.14 christos .dbdata = dbdata, 1389 1.14 christos }; 1390 1.1 christos 1391 1.1 christos /* initialize and set origin */ 1392 1.1 christos dns_name_init(&sdlzdb->common.origin, NULL); 1393 1.14 christos dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin); 1394 1.1 christos 1395 1.14 christos isc_refcount_init(&sdlzdb->common.references, 1); 1396 1.1 christos 1397 1.1 christos /* attach to the memory context */ 1398 1.1 christos isc_mem_attach(mctx, &sdlzdb->common.mctx); 1399 1.1 christos 1400 1.1 christos /* mark structure as valid */ 1401 1.1 christos sdlzdb->common.magic = DNS_DB_MAGIC; 1402 1.1 christos sdlzdb->common.impmagic = SDLZDB_MAGIC; 1403 1.6 christos *dbp = (dns_db_t *)sdlzdb; 1404 1.1 christos 1405 1.14 christos return ISC_R_SUCCESS; 1406 1.1 christos } 1407 1.1 christos 1408 1.1 christos static isc_result_t 1409 1.1 christos dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx, 1410 1.1 christos dns_rdataclass_t rdclass, const dns_name_t *name, 1411 1.6 christos const isc_sockaddr_t *clientaddr, dns_db_t **dbp) { 1412 1.1 christos isc_buffer_t b; 1413 1.1 christos isc_buffer_t b2; 1414 1.1 christos char namestr[DNS_NAME_MAXTEXT + 1]; 1415 1.6 christos char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255." 1416 1.6 christos "255") + 1417 1.6 christos 1]; 1418 1.1 christos isc_netaddr_t netaddr; 1419 1.1 christos isc_result_t result; 1420 1.1 christos dns_sdlzimplementation_t *imp; 1421 1.1 christos 1422 1.1 christos /* 1423 1.1 christos * Perform checks to make sure data is as we expect it to be. 1424 1.1 christos */ 1425 1.1 christos REQUIRE(driverarg != NULL); 1426 1.1 christos REQUIRE(name != NULL); 1427 1.1 christos REQUIRE(clientaddr != NULL); 1428 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL); 1429 1.1 christos 1430 1.6 christos imp = (dns_sdlzimplementation_t *)driverarg; 1431 1.1 christos 1432 1.1 christos /* Convert DNS name to ascii text */ 1433 1.1 christos isc_buffer_init(&b, namestr, sizeof(namestr)); 1434 1.14 christos result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &b); 1435 1.6 christos if (result != ISC_R_SUCCESS) { 1436 1.14 christos return result; 1437 1.6 christos } 1438 1.1 christos isc_buffer_putuint8(&b, 0); 1439 1.1 christos 1440 1.1 christos /* convert client address to ascii text */ 1441 1.1 christos isc_buffer_init(&b2, clientstr, sizeof(clientstr)); 1442 1.1 christos isc_netaddr_fromsockaddr(&netaddr, clientaddr); 1443 1.1 christos result = isc_netaddr_totext(&netaddr, &b2); 1444 1.6 christos if (result != ISC_R_SUCCESS) { 1445 1.14 christos return result; 1446 1.6 christos } 1447 1.1 christos isc_buffer_putuint8(&b2, 0); 1448 1.1 christos 1449 1.1 christos /* make sure strings are always lowercase */ 1450 1.14 christos isc_ascii_strtolower(namestr); 1451 1.14 christos isc_ascii_strtolower(clientstr); 1452 1.1 christos 1453 1.1 christos /* Call SDLZ driver's find zone method */ 1454 1.1 christos if (imp->methods->allowzonexfr != NULL) { 1455 1.6 christos isc_result_t rresult = ISC_R_SUCCESS; 1456 1.6 christos 1457 1.1 christos MAYBE_LOCK(imp); 1458 1.1 christos result = imp->methods->allowzonexfr(imp->driverarg, dbdata, 1459 1.1 christos namestr, clientstr); 1460 1.1 christos MAYBE_UNLOCK(imp); 1461 1.1 christos /* 1462 1.6 christos * if zone is supported and transfers are (or might be) 1463 1.6 christos * allowed, build a 'bind' database driver 1464 1.1 christos */ 1465 1.6 christos if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) { 1466 1.6 christos rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata, 1467 1.6 christos name, rdclass, dbp); 1468 1.6 christos } 1469 1.6 christos if (rresult != ISC_R_SUCCESS) { 1470 1.6 christos result = rresult; 1471 1.6 christos } 1472 1.14 christos return result; 1473 1.1 christos } 1474 1.1 christos 1475 1.14 christos return ISC_R_NOTIMPLEMENTED; 1476 1.1 christos } 1477 1.1 christos 1478 1.1 christos static isc_result_t 1479 1.1 christos dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc, 1480 1.6 christos char *argv[], void *driverarg, void **dbdata) { 1481 1.1 christos dns_sdlzimplementation_t *imp; 1482 1.1 christos isc_result_t result = ISC_R_NOTFOUND; 1483 1.1 christos 1484 1.1 christos /* Write debugging message to log */ 1485 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver."); 1486 1.1 christos 1487 1.1 christos /* 1488 1.1 christos * Performs checks to make sure data is as we expect it to be. 1489 1.1 christos */ 1490 1.1 christos REQUIRE(driverarg != NULL); 1491 1.1 christos REQUIRE(dlzname != NULL); 1492 1.1 christos REQUIRE(dbdata != NULL); 1493 1.1 christos UNUSED(mctx); 1494 1.1 christos 1495 1.1 christos imp = driverarg; 1496 1.1 christos 1497 1.1 christos /* If the create method exists, call it. */ 1498 1.1 christos if (imp->methods->create != NULL) { 1499 1.1 christos MAYBE_LOCK(imp); 1500 1.1 christos result = imp->methods->create(dlzname, argc, argv, 1501 1.1 christos imp->driverarg, dbdata); 1502 1.1 christos MAYBE_UNLOCK(imp); 1503 1.1 christos } 1504 1.1 christos 1505 1.1 christos /* Write debugging message to log */ 1506 1.1 christos if (result == ISC_R_SUCCESS) { 1507 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully."); 1508 1.1 christos } else { 1509 1.1 christos sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load."); 1510 1.1 christos } 1511 1.1 christos 1512 1.14 christos return result; 1513 1.1 christos } 1514 1.1 christos 1515 1.1 christos static void 1516 1.1 christos dns_sdlzdestroy(void *driverdata, void **dbdata) { 1517 1.1 christos dns_sdlzimplementation_t *imp; 1518 1.1 christos 1519 1.1 christos /* Write debugging message to log */ 1520 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver."); 1521 1.1 christos 1522 1.1 christos imp = driverdata; 1523 1.1 christos 1524 1.1 christos /* If the destroy method exists, call it. */ 1525 1.1 christos if (imp->methods->destroy != NULL) { 1526 1.1 christos MAYBE_LOCK(imp); 1527 1.1 christos imp->methods->destroy(imp->driverarg, dbdata); 1528 1.1 christos MAYBE_UNLOCK(imp); 1529 1.1 christos } 1530 1.1 christos } 1531 1.1 christos 1532 1.1 christos static isc_result_t 1533 1.1 christos dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx, 1534 1.1 christos dns_rdataclass_t rdclass, const dns_name_t *name, 1535 1.6 christos dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo, 1536 1.6 christos dns_db_t **dbp) { 1537 1.1 christos isc_buffer_t b; 1538 1.1 christos char namestr[DNS_NAME_MAXTEXT + 1]; 1539 1.1 christos isc_result_t result; 1540 1.1 christos dns_sdlzimplementation_t *imp; 1541 1.1 christos 1542 1.1 christos /* 1543 1.1 christos * Perform checks to make sure data is as we expect it to be. 1544 1.1 christos */ 1545 1.1 christos REQUIRE(driverarg != NULL); 1546 1.1 christos REQUIRE(name != NULL); 1547 1.1 christos REQUIRE(dbp != NULL && *dbp == NULL); 1548 1.1 christos 1549 1.6 christos imp = (dns_sdlzimplementation_t *)driverarg; 1550 1.1 christos 1551 1.1 christos /* Convert DNS name to ascii text */ 1552 1.1 christos isc_buffer_init(&b, namestr, sizeof(namestr)); 1553 1.14 christos result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &b); 1554 1.6 christos if (result != ISC_R_SUCCESS) { 1555 1.14 christos return result; 1556 1.6 christos } 1557 1.1 christos isc_buffer_putuint8(&b, 0); 1558 1.1 christos 1559 1.1 christos /* make sure strings are always lowercase */ 1560 1.14 christos isc_ascii_strtolower(namestr); 1561 1.1 christos 1562 1.1 christos /* Call SDLZ driver's find zone method */ 1563 1.1 christos MAYBE_LOCK(imp); 1564 1.1 christos result = imp->methods->findzone(imp->driverarg, dbdata, namestr, 1565 1.1 christos methods, clientinfo); 1566 1.1 christos MAYBE_UNLOCK(imp); 1567 1.1 christos 1568 1.1 christos /* 1569 1.1 christos * if zone is supported build a 'bind' database driver 1570 1.1 christos * structure to return 1571 1.1 christos */ 1572 1.6 christos if (result == ISC_R_SUCCESS) { 1573 1.1 christos result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name, 1574 1.1 christos rdclass, dbp); 1575 1.6 christos } 1576 1.1 christos 1577 1.14 christos return result; 1578 1.1 christos } 1579 1.1 christos 1580 1.1 christos static isc_result_t 1581 1.6 christos dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view, 1582 1.6 christos dns_dlzdb_t *dlzdb) { 1583 1.1 christos isc_result_t result; 1584 1.1 christos dns_sdlzimplementation_t *imp; 1585 1.1 christos 1586 1.1 christos REQUIRE(driverarg != NULL); 1587 1.1 christos 1588 1.6 christos imp = (dns_sdlzimplementation_t *)driverarg; 1589 1.1 christos 1590 1.1 christos /* Call SDLZ driver's configure method */ 1591 1.1 christos if (imp->methods->configure != NULL) { 1592 1.1 christos MAYBE_LOCK(imp); 1593 1.6 christos result = imp->methods->configure(view, dlzdb, imp->driverarg, 1594 1.6 christos dbdata); 1595 1.1 christos MAYBE_UNLOCK(imp); 1596 1.1 christos } else { 1597 1.1 christos result = ISC_R_SUCCESS; 1598 1.1 christos } 1599 1.1 christos 1600 1.14 christos return result; 1601 1.1 christos } 1602 1.1 christos 1603 1.3 christos static bool 1604 1.1 christos dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name, 1605 1.1 christos const isc_netaddr_t *tcpaddr, dns_rdatatype_t type, 1606 1.6 christos const dst_key_t *key, void *driverarg, void *dbdata) { 1607 1.1 christos dns_sdlzimplementation_t *imp; 1608 1.1 christos char b_signer[DNS_NAME_FORMATSIZE]; 1609 1.1 christos char b_name[DNS_NAME_FORMATSIZE]; 1610 1.1 christos char b_addr[ISC_NETADDR_FORMATSIZE]; 1611 1.1 christos char b_type[DNS_RDATATYPE_FORMATSIZE]; 1612 1.1 christos char b_key[DST_KEY_FORMATSIZE]; 1613 1.1 christos isc_buffer_t *tkey_token = NULL; 1614 1.1 christos isc_region_t token_region = { NULL, 0 }; 1615 1.3 christos uint32_t token_len = 0; 1616 1.3 christos bool ret; 1617 1.1 christos 1618 1.1 christos REQUIRE(driverarg != NULL); 1619 1.1 christos 1620 1.6 christos imp = (dns_sdlzimplementation_t *)driverarg; 1621 1.6 christos if (imp->methods->ssumatch == NULL) { 1622 1.14 christos return false; 1623 1.6 christos } 1624 1.1 christos 1625 1.1 christos /* 1626 1.1 christos * Format the request elements. sdlz operates on strings, not 1627 1.1 christos * structures 1628 1.1 christos */ 1629 1.6 christos if (signer != NULL) { 1630 1.1 christos dns_name_format(signer, b_signer, sizeof(b_signer)); 1631 1.6 christos } else { 1632 1.1 christos b_signer[0] = 0; 1633 1.6 christos } 1634 1.1 christos 1635 1.1 christos dns_name_format(name, b_name, sizeof(b_name)); 1636 1.1 christos 1637 1.6 christos if (tcpaddr != NULL) { 1638 1.1 christos isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr)); 1639 1.6 christos } else { 1640 1.1 christos b_addr[0] = 0; 1641 1.6 christos } 1642 1.1 christos 1643 1.1 christos dns_rdatatype_format(type, b_type, sizeof(b_type)); 1644 1.1 christos 1645 1.1 christos if (key != NULL) { 1646 1.1 christos dst_key_format(key, b_key, sizeof(b_key)); 1647 1.1 christos tkey_token = dst_key_tkeytoken(key); 1648 1.6 christos } else { 1649 1.1 christos b_key[0] = 0; 1650 1.6 christos } 1651 1.1 christos 1652 1.1 christos if (tkey_token != NULL) { 1653 1.1 christos isc_buffer_region(tkey_token, &token_region); 1654 1.1 christos token_len = token_region.length; 1655 1.1 christos } 1656 1.1 christos 1657 1.1 christos MAYBE_LOCK(imp); 1658 1.1 christos ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key, 1659 1.1 christos token_len, 1660 1.1 christos token_len != 0 ? token_region.base : NULL, 1661 1.1 christos imp->driverarg, dbdata); 1662 1.1 christos MAYBE_UNLOCK(imp); 1663 1.14 christos return ret; 1664 1.1 christos } 1665 1.1 christos 1666 1.6 christos static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy, 1667 1.6 christos dns_sdlzfindzone, dns_sdlzallowzonexfr, 1668 1.6 christos dns_sdlzconfigure, dns_sdlzssumatch }; 1669 1.1 christos 1670 1.1 christos /* 1671 1.1 christos * Public functions. 1672 1.1 christos */ 1673 1.1 christos 1674 1.1 christos isc_result_t 1675 1.1 christos dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl, 1676 1.6 christos const char *data) { 1677 1.1 christos dns_rdatalist_t *rdatalist; 1678 1.1 christos dns_rdata_t *rdata; 1679 1.1 christos dns_rdatatype_t typeval; 1680 1.1 christos isc_consttextregion_t r; 1681 1.1 christos isc_buffer_t b; 1682 1.1 christos isc_buffer_t *rdatabuf = NULL; 1683 1.1 christos isc_lex_t *lex; 1684 1.1 christos isc_result_t result; 1685 1.1 christos unsigned int size; 1686 1.1 christos isc_mem_t *mctx; 1687 1.1 christos const dns_name_t *origin; 1688 1.1 christos 1689 1.1 christos REQUIRE(VALID_SDLZLOOKUP(lookup)); 1690 1.1 christos REQUIRE(type != NULL); 1691 1.1 christos REQUIRE(data != NULL); 1692 1.1 christos 1693 1.1 christos mctx = lookup->sdlz->common.mctx; 1694 1.1 christos 1695 1.1 christos r.base = type; 1696 1.1 christos r.length = strlen(type); 1697 1.6 christos result = dns_rdatatype_fromtext(&typeval, (void *)&r); 1698 1.6 christos if (result != ISC_R_SUCCESS) { 1699 1.14 christos return result; 1700 1.6 christos } 1701 1.1 christos 1702 1.1 christos rdatalist = ISC_LIST_HEAD(lookup->lists); 1703 1.1 christos while (rdatalist != NULL) { 1704 1.6 christos if (rdatalist->type == typeval) { 1705 1.1 christos break; 1706 1.6 christos } 1707 1.1 christos rdatalist = ISC_LIST_NEXT(rdatalist, link); 1708 1.1 christos } 1709 1.1 christos 1710 1.1 christos if (rdatalist == NULL) { 1711 1.1 christos rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t)); 1712 1.1 christos dns_rdatalist_init(rdatalist); 1713 1.1 christos rdatalist->rdclass = lookup->sdlz->common.rdclass; 1714 1.1 christos rdatalist->type = typeval; 1715 1.1 christos rdatalist->ttl = ttl; 1716 1.1 christos ISC_LIST_APPEND(lookup->lists, rdatalist, link); 1717 1.6 christos } else if (rdatalist->ttl > ttl) { 1718 1.6 christos /* 1719 1.6 christos * BIND9 doesn't enforce all RRs in an RRset 1720 1.6 christos * having the same TTL, as per RFC 2136, 1721 1.6 christos * section 7.12. If a DLZ backend has 1722 1.6 christos * different TTLs, then the best 1723 1.6 christos * we can do is return the lowest. 1724 1.6 christos */ 1725 1.6 christos rdatalist->ttl = ttl; 1726 1.6 christos } 1727 1.1 christos 1728 1.1 christos rdata = isc_mem_get(mctx, sizeof(dns_rdata_t)); 1729 1.1 christos dns_rdata_init(rdata); 1730 1.1 christos 1731 1.6 christos if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) { 1732 1.1 christos origin = &lookup->sdlz->common.origin; 1733 1.6 christos } else { 1734 1.1 christos origin = dns_rootname; 1735 1.6 christos } 1736 1.1 christos 1737 1.1 christos lex = NULL; 1738 1.14 christos isc_lex_create(mctx, 64, &lex); 1739 1.1 christos 1740 1.1 christos size = initial_size(data); 1741 1.1 christos do { 1742 1.1 christos isc_buffer_constinit(&b, data, strlen(data)); 1743 1.1 christos isc_buffer_add(&b, strlen(data)); 1744 1.1 christos 1745 1.1 christos result = isc_lex_openbuffer(lex, &b); 1746 1.6 christos if (result != ISC_R_SUCCESS) { 1747 1.1 christos goto failure; 1748 1.6 christos } 1749 1.1 christos 1750 1.1 christos rdatabuf = NULL; 1751 1.6 christos isc_buffer_allocate(mctx, &rdatabuf, size); 1752 1.1 christos 1753 1.1 christos result = dns_rdata_fromtext(rdata, rdatalist->rdclass, 1754 1.6 christos rdatalist->type, lex, origin, false, 1755 1.6 christos mctx, rdatabuf, &lookup->callbacks); 1756 1.3 christos if (result != ISC_R_SUCCESS) { 1757 1.1 christos isc_buffer_free(&rdatabuf); 1758 1.3 christos } 1759 1.6 christos if (size >= 65535) { 1760 1.1 christos break; 1761 1.6 christos } 1762 1.1 christos size *= 2; 1763 1.6 christos if (size >= 65535) { 1764 1.1 christos size = 65535; 1765 1.6 christos } 1766 1.1 christos } while (result == ISC_R_NOSPACE); 1767 1.1 christos 1768 1.6 christos if (result != ISC_R_SUCCESS) { 1769 1.10 christos result = DNS_R_SERVFAIL; 1770 1.1 christos goto failure; 1771 1.6 christos } 1772 1.1 christos 1773 1.1 christos ISC_LIST_APPEND(rdatalist->rdata, rdata, link); 1774 1.1 christos ISC_LIST_APPEND(lookup->buffers, rdatabuf, link); 1775 1.1 christos 1776 1.6 christos if (lex != NULL) { 1777 1.1 christos isc_lex_destroy(&lex); 1778 1.6 christos } 1779 1.1 christos 1780 1.14 christos return ISC_R_SUCCESS; 1781 1.1 christos 1782 1.6 christos failure: 1783 1.6 christos if (rdatabuf != NULL) { 1784 1.1 christos isc_buffer_free(&rdatabuf); 1785 1.6 christos } 1786 1.6 christos if (lex != NULL) { 1787 1.1 christos isc_lex_destroy(&lex); 1788 1.6 christos } 1789 1.1 christos isc_mem_put(mctx, rdata, sizeof(dns_rdata_t)); 1790 1.1 christos 1791 1.14 christos return result; 1792 1.1 christos } 1793 1.1 christos 1794 1.1 christos isc_result_t 1795 1.1 christos dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name, 1796 1.6 christos const char *type, dns_ttl_t ttl, const char *data) { 1797 1.1 christos dns_name_t *newname; 1798 1.1 christos const dns_name_t *origin; 1799 1.1 christos dns_fixedname_t fnewname; 1800 1.1 christos dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db; 1801 1.1 christos dns_sdlznode_t *sdlznode; 1802 1.1 christos isc_mem_t *mctx = sdlz->common.mctx; 1803 1.1 christos isc_buffer_t b; 1804 1.1 christos isc_result_t result; 1805 1.1 christos 1806 1.1 christos newname = dns_fixedname_initname(&fnewname); 1807 1.1 christos 1808 1.6 christos if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) { 1809 1.1 christos origin = &sdlz->common.origin; 1810 1.6 christos } else { 1811 1.1 christos origin = dns_rootname; 1812 1.6 christos } 1813 1.1 christos isc_buffer_constinit(&b, name, strlen(name)); 1814 1.1 christos isc_buffer_add(&b, strlen(name)); 1815 1.1 christos 1816 1.1 christos result = dns_name_fromtext(newname, &b, origin, 0, NULL); 1817 1.6 christos if (result != ISC_R_SUCCESS) { 1818 1.14 christos return result; 1819 1.6 christos } 1820 1.1 christos 1821 1.1 christos if (allnodes->common.relative_names) { 1822 1.1 christos /* All names are relative to the root */ 1823 1.1 christos unsigned int nlabels = dns_name_countlabels(newname); 1824 1.1 christos dns_name_getlabelsequence(newname, 0, nlabels - 1, newname); 1825 1.1 christos } 1826 1.1 christos 1827 1.1 christos sdlznode = ISC_LIST_HEAD(allnodes->nodelist); 1828 1.1 christos if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) { 1829 1.1 christos sdlznode = NULL; 1830 1.1 christos result = createnode(sdlz, &sdlznode); 1831 1.6 christos if (result != ISC_R_SUCCESS) { 1832 1.14 christos return result; 1833 1.6 christos } 1834 1.1 christos sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t)); 1835 1.1 christos dns_name_init(sdlznode->name, NULL); 1836 1.6 christos dns_name_dup(newname, mctx, sdlznode->name); 1837 1.1 christos ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link); 1838 1.1 christos if (allnodes->origin == NULL && 1839 1.11 christos dns_name_equal(newname, &sdlz->common.origin)) 1840 1.11 christos { 1841 1.1 christos allnodes->origin = sdlznode; 1842 1.6 christos } 1843 1.1 christos } 1844 1.14 christos return dns_sdlz_putrr(sdlznode, type, ttl, data); 1845 1.1 christos } 1846 1.1 christos 1847 1.1 christos isc_result_t 1848 1.1 christos dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname, 1849 1.6 christos uint32_t serial) { 1850 1.1 christos char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7]; 1851 1.1 christos int n; 1852 1.1 christos 1853 1.1 christos REQUIRE(mname != NULL); 1854 1.1 christos REQUIRE(rname != NULL); 1855 1.1 christos 1856 1.6 christos n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname, 1857 1.6 christos serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY, 1858 1.1 christos SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM); 1859 1.6 christos if (n >= (int)sizeof(str) || n < 0) { 1860 1.14 christos return ISC_R_NOSPACE; 1861 1.6 christos } 1862 1.14 christos return dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str); 1863 1.1 christos } 1864 1.1 christos 1865 1.1 christos isc_result_t 1866 1.1 christos dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods, 1867 1.1 christos void *driverarg, unsigned int flags, isc_mem_t *mctx, 1868 1.6 christos dns_sdlzimplementation_t **sdlzimp) { 1869 1.1 christos dns_sdlzimplementation_t *imp; 1870 1.1 christos isc_result_t result; 1871 1.1 christos 1872 1.1 christos /* 1873 1.1 christos * Performs checks to make sure data is as we expect it to be. 1874 1.1 christos */ 1875 1.1 christos REQUIRE(drivername != NULL); 1876 1.1 christos REQUIRE(methods != NULL); 1877 1.1 christos REQUIRE(methods->findzone != NULL); 1878 1.1 christos REQUIRE(methods->lookup != NULL); 1879 1.1 christos REQUIRE(mctx != NULL); 1880 1.1 christos REQUIRE(sdlzimp != NULL && *sdlzimp == NULL); 1881 1.6 christos REQUIRE((flags & 1882 1.6 christos ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA | 1883 1.6 christos DNS_SDLZFLAG_THREADSAFE)) == 0); 1884 1.1 christos 1885 1.1 christos /* Write debugging message to log */ 1886 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername); 1887 1.1 christos 1888 1.1 christos /* 1889 1.1 christos * Allocate memory for a sdlz_implementation object. Error if 1890 1.1 christos * we cannot. 1891 1.1 christos */ 1892 1.14 christos imp = isc_mem_get(mctx, sizeof(*imp)); 1893 1.1 christos 1894 1.1 christos /* Store the data passed into this method */ 1895 1.14 christos *imp = (dns_sdlzimplementation_t){ 1896 1.14 christos .methods = methods, 1897 1.14 christos .driverarg = driverarg, 1898 1.14 christos .flags = flags, 1899 1.14 christos }; 1900 1.1 christos 1901 1.1 christos /* attach the new sdlz_implementation object to a memory context */ 1902 1.1 christos isc_mem_attach(mctx, &imp->mctx); 1903 1.1 christos 1904 1.1 christos /* 1905 1.1 christos * initialize the driver lock, error if we cannot 1906 1.1 christos * (used if a driver does not support multiple threads) 1907 1.1 christos */ 1908 1.3 christos isc_mutex_init(&imp->driverlock); 1909 1.1 christos 1910 1.1 christos /* 1911 1.1 christos * register the DLZ driver. Pass in our "extra" sdlz information as 1912 1.1 christos * a driverarg. (that's why we stored the passed in driver arg in our 1913 1.1 christos * sdlz_implementation structure) Also, store the dlz_implementation 1914 1.1 christos * structure in our sdlz_implementation. 1915 1.1 christos */ 1916 1.1 christos result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx, 1917 1.1 christos &imp->dlz_imp); 1918 1.1 christos 1919 1.1 christos /* if registration fails, cleanup and get outta here. */ 1920 1.6 christos if (result != ISC_R_SUCCESS) { 1921 1.1 christos goto cleanup_mutex; 1922 1.6 christos } 1923 1.1 christos 1924 1.1 christos *sdlzimp = imp; 1925 1.1 christos 1926 1.14 christos return ISC_R_SUCCESS; 1927 1.1 christos 1928 1.6 christos cleanup_mutex: 1929 1.1 christos /* destroy the driver lock, we don't need it anymore */ 1930 1.3 christos isc_mutex_destroy(&imp->driverlock); 1931 1.1 christos 1932 1.1 christos /* 1933 1.1 christos * return the memory back to the available memory pool and 1934 1.1 christos * remove it from the memory context. 1935 1.1 christos */ 1936 1.14 christos isc_mem_putanddetach(&imp->mctx, imp, sizeof(*imp)); 1937 1.14 christos return result; 1938 1.1 christos } 1939 1.1 christos 1940 1.1 christos void 1941 1.1 christos dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) { 1942 1.1 christos dns_sdlzimplementation_t *imp; 1943 1.1 christos 1944 1.1 christos /* Write debugging message to log */ 1945 1.1 christos sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver."); 1946 1.1 christos 1947 1.1 christos /* 1948 1.1 christos * Performs checks to make sure data is as we expect it to be. 1949 1.1 christos */ 1950 1.1 christos REQUIRE(sdlzimp != NULL && *sdlzimp != NULL); 1951 1.1 christos 1952 1.1 christos imp = *sdlzimp; 1953 1.6 christos *sdlzimp = NULL; 1954 1.1 christos 1955 1.1 christos /* Unregister the DLZ driver implementation */ 1956 1.1 christos dns_dlzunregister(&imp->dlz_imp); 1957 1.1 christos 1958 1.1 christos /* destroy the driver lock, we don't need it anymore */ 1959 1.3 christos isc_mutex_destroy(&imp->driverlock); 1960 1.1 christos 1961 1.1 christos /* 1962 1.1 christos * return the memory back to the available memory pool and 1963 1.1 christos * remove it from the memory context. 1964 1.1 christos */ 1965 1.6 christos isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t)); 1966 1.1 christos } 1967 1.1 christos 1968 1.1 christos isc_result_t 1969 1.1 christos dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass, 1970 1.6 christos const dns_name_t *name, dns_db_t **dbp) { 1971 1.1 christos isc_result_t result; 1972 1.1 christos 1973 1.1 christos result = dns_sdlzcreateDBP(dlzdatabase->mctx, 1974 1.1 christos dlzdatabase->implementation->driverarg, 1975 1.1 christos dlzdatabase->dbdata, name, rdclass, dbp); 1976 1.14 christos return result; 1977 1.1 christos } 1978