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