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