sdlz.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2005-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 1999-2001  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*
00019  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
00020  *
00021  * Permission to use, copy, modify, and distribute this software for any
00022  * purpose with or without fee is hereby granted, provided that the
00023  * above copyright notice and this permission notice appear in all
00024  * copies.
00025  *
00026  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
00027  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
00028  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
00029  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
00030  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00031  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00032  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
00033  * USE OR PERFORMANCE OF THIS SOFTWARE.
00034  *
00035  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
00036  * conceived and contributed by Rob Butler.
00037  *
00038  * Permission to use, copy, modify, and distribute this software for any
00039  * purpose with or without fee is hereby granted, provided that the
00040  * above copyright notice and this permission notice appear in all
00041  * copies.
00042  *
00043  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
00044  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
00045  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
00046  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
00047  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
00048  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00049  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
00050  * USE OR PERFORMANCE OF THIS SOFTWARE.
00051  */
00052 
00053 /* $Id$ */
00054 
00055 /*! \file */
00056 
00057 #include <config.h>
00058 #include <string.h>
00059 
00060 #include <isc/buffer.h>
00061 #include <isc/lex.h>
00062 #include <isc/log.h>
00063 #include <isc/rwlock.h>
00064 #include <isc/string.h>
00065 #include <isc/util.h>
00066 #include <isc/magic.h>
00067 #include <isc/mem.h>
00068 #include <isc/once.h>
00069 #include <isc/print.h>
00070 #include <isc/region.h>
00071 
00072 #include <dns/callbacks.h>
00073 #include <dns/db.h>
00074 #include <dns/dbiterator.h>
00075 #include <dns/dlz.h>
00076 #include <dns/fixedname.h>
00077 #include <dns/log.h>
00078 #include <dns/rdata.h>
00079 #include <dns/rdatalist.h>
00080 #include <dns/rdataset.h>
00081 #include <dns/rdatasetiter.h>
00082 #include <dns/rdatatype.h>
00083 #include <dns/result.h>
00084 #include <dns/master.h>
00085 #include <dns/sdlz.h>
00086 #include <dns/types.h>
00087 
00088 #include "rdatalist_p.h"
00089 
00090 /*
00091  * Private Types
00092  */
00093 
00094 struct dns_sdlzimplementation {
00095         const dns_sdlzmethods_t         *methods;
00096         isc_mem_t                       *mctx;
00097         void                            *driverarg;
00098         unsigned int                    flags;
00099         isc_mutex_t                     driverlock;
00100         dns_dlzimplementation_t         *dlz_imp;
00101 };
00102 
00103 struct dns_sdlz_db {
00104         /* Unlocked */
00105         dns_db_t                        common;
00106         void                            *dbdata;
00107         dns_sdlzimplementation_t        *dlzimp;
00108         isc_mutex_t                     refcnt_lock;
00109         /* Locked */
00110         unsigned int                    references;
00111         dns_dbversion_t                 *future_version;
00112         int                             dummy_version;
00113 };
00114 
00115 struct dns_sdlzlookup {
00116         /* Unlocked */
00117         unsigned int                    magic;
00118         dns_sdlz_db_t                   *sdlz;
00119         ISC_LIST(dns_rdatalist_t)       lists;
00120         ISC_LIST(isc_buffer_t)          buffers;
00121         dns_name_t                      *name;
00122         ISC_LINK(dns_sdlzlookup_t)      link;
00123         isc_mutex_t                     lock;
00124         dns_rdatacallbacks_t            callbacks;
00125         /* Locked */
00126         unsigned int                    references;
00127 };
00128 
00129 typedef struct dns_sdlzlookup dns_sdlznode_t;
00130 
00131 struct dns_sdlzallnodes {
00132         dns_dbiterator_t                common;
00133         ISC_LIST(dns_sdlznode_t)        nodelist;
00134         dns_sdlznode_t                  *current;
00135         dns_sdlznode_t                  *origin;
00136 };
00137 
00138 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
00139 
00140 typedef struct sdlz_rdatasetiter {
00141         dns_rdatasetiter_t              common;
00142         dns_rdatalist_t                 *current;
00143 } sdlz_rdatasetiter_t;
00144 
00145 
00146 #define SDLZDB_MAGIC            ISC_MAGIC('D', 'L', 'Z', 'S')
00147 
00148 /*
00149  * Note that "impmagic" is not the first four bytes of the struct, so
00150  * ISC_MAGIC_VALID cannot be used.
00151  */
00152 
00153 #define VALID_SDLZDB(sdlzdb)    ((sdlzdb) != NULL && \
00154                                  (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
00155 
00156 #define SDLZLOOKUP_MAGIC        ISC_MAGIC('D','L','Z','L')
00157 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
00158 #define VALID_SDLZNODE(sdlzn)   VALID_SDLZLOOKUP(sdlzn)
00159 
00160 /* These values are taken from RFC 1537 */
00161 #define SDLZ_DEFAULT_REFRESH    (60 * 60 * 8)
00162 #define SDLZ_DEFAULT_RETRY      (60 * 60 * 2)
00163 #define SDLZ_DEFAULT_EXPIRE     (60 * 60 * 24 * 7)
00164 #define SDLZ_DEFAULT_MINIMUM    (60 * 60 * 24)
00165 
00166 /* This is a reasonable value */
00167 #define SDLZ_DEFAULT_TTL        (60 * 60 * 24)
00168 
00169 #ifdef __COVERITY__
00170 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
00171 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
00172 #else
00173 #define MAYBE_LOCK(imp) \
00174         do { \
00175                 unsigned int flags = imp->flags; \
00176                 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
00177                         LOCK(&imp->driverlock); \
00178         } while (0)
00179 
00180 #define MAYBE_UNLOCK(imp) \
00181         do { \
00182                 unsigned int flags = imp->flags; \
00183                 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
00184                         UNLOCK(&imp->driverlock); \
00185         } while (0)
00186 #endif
00187 
00188 /*
00189  * Forward references.
00190  */
00191 static isc_result_t getnodedata(dns_db_t *db, dns_name_t *name,
00192                                 isc_boolean_t create, unsigned int options,
00193                                 dns_clientinfomethods_t *methods,
00194                                 dns_clientinfo_t *clientinfo,
00195                                 dns_dbnode_t **nodep);
00196 
00197 static void list_tordataset(dns_rdatalist_t *rdatalist,
00198                             dns_db_t *db, dns_dbnode_t *node,
00199                             dns_rdataset_t *rdataset);
00200 
00201 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
00202 
00203 static void             dbiterator_destroy(dns_dbiterator_t **iteratorp);
00204 static isc_result_t     dbiterator_first(dns_dbiterator_t *iterator);
00205 static isc_result_t     dbiterator_last(dns_dbiterator_t *iterator);
00206 static isc_result_t     dbiterator_seek(dns_dbiterator_t *iterator,
00207                                         dns_name_t *name);
00208 static isc_result_t     dbiterator_prev(dns_dbiterator_t *iterator);
00209 static isc_result_t     dbiterator_next(dns_dbiterator_t *iterator);
00210 static isc_result_t     dbiterator_current(dns_dbiterator_t *iterator,
00211                                            dns_dbnode_t **nodep,
00212                                            dns_name_t *name);
00213 static isc_result_t     dbiterator_pause(dns_dbiterator_t *iterator);
00214 static isc_result_t     dbiterator_origin(dns_dbiterator_t *iterator,
00215                                           dns_name_t *name);
00216 
00217 static dns_dbiteratormethods_t dbiterator_methods = {
00218         dbiterator_destroy,
00219         dbiterator_first,
00220         dbiterator_last,
00221         dbiterator_seek,
00222         dbiterator_prev,
00223         dbiterator_next,
00224         dbiterator_current,
00225         dbiterator_pause,
00226         dbiterator_origin
00227 };
00228 
00229 /*
00230  * Utility functions
00231  */
00232 
00233 /*
00234  * Log a message at the given level
00235  */
00236 static void
00237 sdlz_log(int level, const char *fmt, ...) {
00238         va_list ap;
00239         va_start(ap, fmt);
00240         isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE,
00241                        DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(level),
00242                        fmt, ap);
00243         va_end(ap);
00244 }
00245 
00246 /*% Converts the input string to lowercase, in place. */
00247 static void
00248 dns_sdlz_tolower(char *str) {
00249         unsigned int len = strlen(str);
00250         unsigned int i;
00251 
00252         for (i = 0; i < len; i++) {
00253                 if (str[i] >= 'A' && str[i] <= 'Z')
00254                         str[i] += 32;
00255         }
00256 }
00257 
00258 static inline unsigned int
00259 initial_size(const char *data) {
00260         unsigned int len = (strlen(data) / 64) + 1;
00261         return (len * 64 + 64);
00262 }
00263 
00264 /*
00265  * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
00266  * driver interface.  See the SDB driver interface documentation for more info.
00267  */
00268 
00269 static void
00270 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
00271         sdlz_rdatasetiter_t *sdlziterator =
00272                 (sdlz_rdatasetiter_t *)(*iteratorp);
00273 
00274         detachnode(sdlziterator->common.db, &sdlziterator->common.node);
00275         isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
00276                     sizeof(sdlz_rdatasetiter_t));
00277         *iteratorp = NULL;
00278 }
00279 
00280 static isc_result_t
00281 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
00282         sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
00283         dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
00284 
00285         if (ISC_LIST_EMPTY(sdlznode->lists))
00286                 return (ISC_R_NOMORE);
00287         sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
00288         return (ISC_R_SUCCESS);
00289 }
00290 
00291 static isc_result_t
00292 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
00293         sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
00294 
00295         sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
00296         if (sdlziterator->current == NULL)
00297                 return (ISC_R_NOMORE);
00298         else
00299                 return (ISC_R_SUCCESS);
00300 }
00301 
00302 static void
00303 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
00304         sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
00305 
00306         list_tordataset(sdlziterator->current, iterator->db, iterator->node,
00307                         rdataset);
00308 }
00309 
00310 static dns_rdatasetitermethods_t rdatasetiter_methods = {
00311         rdatasetiter_destroy,
00312         rdatasetiter_first,
00313         rdatasetiter_next,
00314         rdatasetiter_current
00315 };
00316 
00317 /*
00318  * DB routines. These methods were "borrowed" from the SDB driver interface.
00319  * See the SDB driver interface documentation for more info.
00320  */
00321 
00322 static void
00323 attach(dns_db_t *source, dns_db_t **targetp) {
00324         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source;
00325 
00326         REQUIRE(VALID_SDLZDB(sdlz));
00327 
00328         LOCK(&sdlz->refcnt_lock);
00329         REQUIRE(sdlz->references > 0);
00330         sdlz->references++;
00331         UNLOCK(&sdlz->refcnt_lock);
00332 
00333         *targetp = source;
00334 }
00335 
00336 static void
00337 destroy(dns_sdlz_db_t *sdlz) {
00338         isc_mem_t *mctx;
00339         mctx = sdlz->common.mctx;
00340 
00341         sdlz->common.magic = 0;
00342         sdlz->common.impmagic = 0;
00343 
00344         (void)isc_mutex_destroy(&sdlz->refcnt_lock);
00345 
00346         dns_name_free(&sdlz->common.origin, mctx);
00347 
00348         isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
00349         isc_mem_detach(&mctx);
00350 }
00351 
00352 static void
00353 detach(dns_db_t **dbp) {
00354         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
00355         isc_boolean_t need_destroy = ISC_FALSE;
00356 
00357         REQUIRE(VALID_SDLZDB(sdlz));
00358         LOCK(&sdlz->refcnt_lock);
00359         REQUIRE(sdlz->references > 0);
00360         sdlz->references--;
00361         if (sdlz->references == 0)
00362                 need_destroy = ISC_TRUE;
00363         UNLOCK(&sdlz->refcnt_lock);
00364 
00365         if (need_destroy)
00366                 destroy(sdlz);
00367 
00368         *dbp = NULL;
00369 }
00370 
00371 static isc_result_t
00372 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
00373         UNUSED(db);
00374         UNUSED(callbacks);
00375         return (ISC_R_NOTIMPLEMENTED);
00376 }
00377 
00378 static isc_result_t
00379 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
00380         UNUSED(db);
00381         UNUSED(callbacks);
00382         return (ISC_R_NOTIMPLEMENTED);
00383 }
00384 
00385 static isc_result_t
00386 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
00387      dns_masterformat_t masterformat)
00388 {
00389         UNUSED(db);
00390         UNUSED(version);
00391         UNUSED(filename);
00392         UNUSED(masterformat);
00393         return (ISC_R_NOTIMPLEMENTED);
00394 }
00395 
00396 static void
00397 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
00398         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00399         REQUIRE(VALID_SDLZDB(sdlz));
00400         REQUIRE(versionp != NULL && *versionp == NULL);
00401 
00402         *versionp = (void *) &sdlz->dummy_version;
00403         return;
00404 }
00405 
00406 static isc_result_t
00407 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
00408         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00409         char origin[DNS_NAME_MAXTEXT + 1];
00410         isc_result_t result;
00411 
00412         REQUIRE(VALID_SDLZDB(sdlz));
00413 
00414         if (sdlz->dlzimp->methods->newversion == NULL)
00415                 return (ISC_R_NOTIMPLEMENTED);
00416 
00417         dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
00418 
00419         result = sdlz->dlzimp->methods->newversion(origin,
00420                                                    sdlz->dlzimp->driverarg,
00421                                                    sdlz->dbdata, versionp);
00422         if (result != ISC_R_SUCCESS) {
00423                 sdlz_log(ISC_LOG_ERROR,
00424                          "sdlz newversion on origin %s failed : %s",
00425                          origin, isc_result_totext(result));
00426                 return (result);
00427         }
00428 
00429         sdlz->future_version = *versionp;
00430         return (ISC_R_SUCCESS);
00431 }
00432 
00433 static void
00434 attachversion(dns_db_t *db, dns_dbversion_t *source, dns_dbversion_t **targetp)
00435 {
00436         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00437 
00438         REQUIRE(VALID_SDLZDB(sdlz));
00439         REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
00440 
00441         *targetp = source;
00442 }
00443 
00444 static void
00445 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
00446         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00447         char origin[DNS_NAME_MAXTEXT + 1];
00448 
00449         REQUIRE(VALID_SDLZDB(sdlz));
00450         REQUIRE(versionp != NULL);
00451 
00452         if (*versionp == (void *)&sdlz->dummy_version) {
00453                 *versionp = NULL;
00454                 return;
00455         }
00456 
00457         REQUIRE(*versionp == sdlz->future_version);
00458         REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
00459 
00460         dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
00461 
00462         sdlz->dlzimp->methods->closeversion(origin, commit,
00463                                             sdlz->dlzimp->driverarg,
00464                                             sdlz->dbdata, versionp);
00465         if (*versionp != NULL)
00466                 sdlz_log(ISC_LOG_ERROR,
00467                         "sdlz closeversion on origin %s failed", origin);
00468 
00469         sdlz->future_version = NULL;
00470 }
00471 
00472 static isc_result_t
00473 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
00474         dns_sdlznode_t *node;
00475         isc_result_t result;
00476 
00477         node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
00478         if (node == NULL)
00479                 return (ISC_R_NOMEMORY);
00480 
00481         node->sdlz = NULL;
00482         attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
00483         ISC_LIST_INIT(node->lists);
00484         ISC_LIST_INIT(node->buffers);
00485         ISC_LINK_INIT(node, link);
00486         node->name = NULL;
00487         result = isc_mutex_init(&node->lock);
00488         if (result != ISC_R_SUCCESS) {
00489                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00490                                  "isc_mutex_init() failed: %s",
00491                                  isc_result_totext(result));
00492                 isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t));
00493                 return (ISC_R_UNEXPECTED);
00494         }
00495         dns_rdatacallbacks_init(&node->callbacks);
00496         node->references = 1;
00497         node->magic = SDLZLOOKUP_MAGIC;
00498 
00499         *nodep = node;
00500         return (ISC_R_SUCCESS);
00501 }
00502 
00503 static void
00504 destroynode(dns_sdlznode_t *node) {
00505         dns_rdatalist_t *list;
00506         dns_rdata_t *rdata;
00507         isc_buffer_t *b;
00508         dns_sdlz_db_t *sdlz;
00509         dns_db_t *db;
00510         isc_mem_t *mctx;
00511 
00512         sdlz = node->sdlz;
00513         mctx = sdlz->common.mctx;
00514 
00515         while (!ISC_LIST_EMPTY(node->lists)) {
00516                 list = ISC_LIST_HEAD(node->lists);
00517                 while (!ISC_LIST_EMPTY(list->rdata)) {
00518                         rdata = ISC_LIST_HEAD(list->rdata);
00519                         ISC_LIST_UNLINK(list->rdata, rdata, link);
00520                         isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
00521                 }
00522                 ISC_LIST_UNLINK(node->lists, list, link);
00523                 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
00524         }
00525 
00526         while (!ISC_LIST_EMPTY(node->buffers)) {
00527                 b = ISC_LIST_HEAD(node->buffers);
00528                 ISC_LIST_UNLINK(node->buffers, b, link);
00529                 isc_buffer_free(&b);
00530         }
00531 
00532         if (node->name != NULL) {
00533                 dns_name_free(node->name, mctx);
00534                 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
00535         }
00536         DESTROYLOCK(&node->lock);
00537         node->magic = 0;
00538         isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
00539         db = &sdlz->common;
00540         detach(&db);
00541 }
00542 
00543 static isc_result_t
00544 getnodedata(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
00545             unsigned int options, dns_clientinfomethods_t *methods,
00546             dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep)
00547 {
00548         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00549         dns_sdlznode_t *node = NULL;
00550         isc_result_t result;
00551         isc_buffer_t b;
00552         char namestr[DNS_NAME_MAXTEXT + 1];
00553         isc_buffer_t b2;
00554         char zonestr[DNS_NAME_MAXTEXT + 1];
00555         isc_boolean_t isorigin;
00556         dns_sdlzauthorityfunc_t authority;
00557 
00558         REQUIRE(VALID_SDLZDB(sdlz));
00559         REQUIRE(nodep != NULL && *nodep == NULL);
00560 
00561         if (sdlz->dlzimp->methods->newversion == NULL) {
00562                 REQUIRE(create == ISC_FALSE);
00563         }
00564 
00565         isc_buffer_init(&b, namestr, sizeof(namestr));
00566         if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
00567                 dns_name_t relname;
00568                 unsigned int labels;
00569 
00570                 labels = dns_name_countlabels(name) -
00571                          dns_name_countlabels(&sdlz->common.origin);
00572                 dns_name_init(&relname, NULL);
00573                 dns_name_getlabelsequence(name, 0, labels, &relname);
00574                 result = dns_name_totext(&relname, ISC_TRUE, &b);
00575                 if (result != ISC_R_SUCCESS)
00576                         return (result);
00577         } else {
00578                 result = dns_name_totext(name, ISC_TRUE, &b);
00579                 if (result != ISC_R_SUCCESS)
00580                         return (result);
00581         }
00582         isc_buffer_putuint8(&b, 0);
00583 
00584         isc_buffer_init(&b2, zonestr, sizeof(zonestr));
00585         result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2);
00586         if (result != ISC_R_SUCCESS)
00587                 return (result);
00588         isc_buffer_putuint8(&b2, 0);
00589 
00590         result = createnode(sdlz, &node);
00591         if (result != ISC_R_SUCCESS)
00592                 return (result);
00593 
00594         isorigin = dns_name_equal(name, &sdlz->common.origin);
00595 
00596         /* make sure strings are always lowercase */
00597         dns_sdlz_tolower(zonestr);
00598         dns_sdlz_tolower(namestr);
00599 
00600         MAYBE_LOCK(sdlz->dlzimp);
00601 
00602         /* try to lookup the host (namestr) */
00603         result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
00604                                                sdlz->dlzimp->driverarg,
00605                                                sdlz->dbdata, node,
00606                                                methods, clientinfo);
00607 
00608         /*
00609          * If the name was not found and DNS_DBFIND_NOWILD is not
00610          * set, then we try to find a wildcard entry.
00611          *
00612          * If DNS_DBFIND_NOZONECUT is set and there are multiple
00613          * levels between the host and the zone origin, we also look
00614          * for wildcards at each level.
00615          */
00616         if (result == ISC_R_NOTFOUND && !create &&
00617             (options & DNS_DBFIND_NOWILD) == 0)
00618         {
00619                 unsigned int i, dlabels, nlabels;
00620 
00621                 nlabels = dns_name_countlabels(name);
00622                 dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
00623                 for (i = 0; i < dlabels; i++) {
00624                         char wildstr[DNS_NAME_MAXTEXT + 1];
00625                         dns_fixedname_t fixed;
00626                         dns_name_t *wild;
00627 
00628                         dns_fixedname_init(&fixed);
00629                         if (i == dlabels)
00630                                 wild = dns_wildcardname;
00631                         else {
00632                                 wild = dns_fixedname_name(&fixed);
00633                                 dns_name_getlabelsequence(name, i + 1,
00634                                                           dlabels - i - 1,
00635                                                           wild);
00636                                 result = dns_name_concatenate(dns_wildcardname,
00637                                                               wild, wild, NULL);
00638                                 if (result != ISC_R_SUCCESS)
00639                                         return (result);
00640                         }
00641 
00642                         isc_buffer_init(&b, wildstr, sizeof(wildstr));
00643                         result = dns_name_totext(wild, ISC_TRUE, &b);
00644                         if (result != ISC_R_SUCCESS)
00645                                 return (result);
00646                         isc_buffer_putuint8(&b, 0);
00647 
00648                         result = sdlz->dlzimp->methods->lookup(zonestr, wildstr,
00649                                                        sdlz->dlzimp->driverarg,
00650                                                        sdlz->dbdata, node,
00651                                                        methods, clientinfo);
00652                         if (result == ISC_R_SUCCESS)
00653                                 break;
00654                 }
00655         }
00656 
00657         MAYBE_UNLOCK(sdlz->dlzimp);
00658 
00659         if (result == ISC_R_NOTFOUND && (isorigin || create))
00660                 result = ISC_R_SUCCESS;
00661 
00662         if (result != ISC_R_SUCCESS) {
00663                 destroynode(node);
00664                 return (result);
00665         }
00666 
00667         if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
00668                 MAYBE_LOCK(sdlz->dlzimp);
00669                 authority = sdlz->dlzimp->methods->authority;
00670                 result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
00671                                       sdlz->dbdata, node);
00672                 MAYBE_UNLOCK(sdlz->dlzimp);
00673                 if (result != ISC_R_SUCCESS &&
00674                     result != ISC_R_NOTIMPLEMENTED)
00675                 {
00676                         destroynode(node);
00677                         return (result);
00678                 }
00679         }
00680 
00681         if (node->name == NULL) {
00682                 node->name = isc_mem_get(sdlz->common.mctx,
00683                                          sizeof(dns_name_t));
00684                 if (node->name == NULL) {
00685                         destroynode(node);
00686                         return (ISC_R_NOMEMORY);
00687                 }
00688                 dns_name_init(node->name, NULL);
00689                 result = dns_name_dup(name, sdlz->common.mctx, node->name);
00690                 if (result != ISC_R_SUCCESS) {
00691                         isc_mem_put(sdlz->common.mctx, node->name,
00692                                     sizeof(dns_name_t));
00693                         destroynode(node);
00694                         return (result);
00695                 }
00696         }
00697 
00698         *nodep = node;
00699         return (ISC_R_SUCCESS);
00700 }
00701 
00702 static isc_result_t
00703 findnodeext(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
00704             dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
00705             dns_dbnode_t **nodep)
00706 {
00707         return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
00708 }
00709 
00710 static isc_result_t
00711 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
00712          dns_dbnode_t **nodep)
00713 {
00714         return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
00715 }
00716 
00717 static isc_result_t
00718 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
00719             isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
00720             dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
00721 {
00722         UNUSED(db);
00723         UNUSED(name);
00724         UNUSED(options);
00725         UNUSED(now);
00726         UNUSED(nodep);
00727         UNUSED(foundname);
00728         UNUSED(rdataset);
00729         UNUSED(sigrdataset);
00730 
00731         return (ISC_R_NOTIMPLEMENTED);
00732 }
00733 
00734 static void
00735 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
00736         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00737         dns_sdlznode_t *node = (dns_sdlznode_t *)source;
00738 
00739         REQUIRE(VALID_SDLZDB(sdlz));
00740 
00741         UNUSED(sdlz);
00742 
00743         LOCK(&node->lock);
00744         INSIST(node->references > 0);
00745         node->references++;
00746         INSIST(node->references != 0);          /* Catch overflow. */
00747         UNLOCK(&node->lock);
00748 
00749         *targetp = source;
00750 }
00751 
00752 static void
00753 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
00754         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00755         dns_sdlznode_t *node;
00756         isc_boolean_t need_destroy = ISC_FALSE;
00757 
00758         REQUIRE(VALID_SDLZDB(sdlz));
00759         REQUIRE(targetp != NULL && *targetp != NULL);
00760 
00761         UNUSED(sdlz);
00762 
00763         node = (dns_sdlznode_t *)(*targetp);
00764 
00765         LOCK(&node->lock);
00766         INSIST(node->references > 0);
00767         node->references--;
00768         if (node->references == 0)
00769                 need_destroy = ISC_TRUE;
00770         UNLOCK(&node->lock);
00771 
00772         if (need_destroy)
00773                 destroynode(node);
00774 
00775         *targetp = NULL;
00776 }
00777 
00778 static isc_result_t
00779 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
00780         UNUSED(db);
00781         UNUSED(node);
00782         UNUSED(now);
00783         INSIST(0);
00784         return (ISC_R_UNEXPECTED);
00785 }
00786 
00787 static void
00788 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
00789         UNUSED(db);
00790         UNUSED(node);
00791         UNUSED(out);
00792         return;
00793 }
00794 
00795 static isc_result_t
00796 createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
00797 {
00798         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00799         sdlz_dbiterator_t *sdlziter;
00800         isc_result_t result;
00801         isc_buffer_t b;
00802         char zonestr[DNS_NAME_MAXTEXT + 1];
00803 
00804         REQUIRE(VALID_SDLZDB(sdlz));
00805 
00806         if (sdlz->dlzimp->methods->allnodes == NULL)
00807                 return (ISC_R_NOTIMPLEMENTED);
00808 
00809         if ((options & DNS_DB_NSEC3ONLY) != 0 ||
00810             (options & DNS_DB_NONSEC3) != 0)
00811                  return (ISC_R_NOTIMPLEMENTED);
00812 
00813         isc_buffer_init(&b, zonestr, sizeof(zonestr));
00814         result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
00815         if (result != ISC_R_SUCCESS)
00816                 return (result);
00817         isc_buffer_putuint8(&b, 0);
00818 
00819         sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
00820         if (sdlziter == NULL)
00821                 return (ISC_R_NOMEMORY);
00822 
00823         sdlziter->common.methods = &dbiterator_methods;
00824         sdlziter->common.db = NULL;
00825         dns_db_attach(db, &sdlziter->common.db);
00826         sdlziter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
00827         sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
00828         ISC_LIST_INIT(sdlziter->nodelist);
00829         sdlziter->current = NULL;
00830         sdlziter->origin = NULL;
00831 
00832         /* make sure strings are always lowercase */
00833         dns_sdlz_tolower(zonestr);
00834 
00835         MAYBE_LOCK(sdlz->dlzimp);
00836         result = sdlz->dlzimp->methods->allnodes(zonestr,
00837                                                  sdlz->dlzimp->driverarg,
00838                                                  sdlz->dbdata, sdlziter);
00839         MAYBE_UNLOCK(sdlz->dlzimp);
00840         if (result != ISC_R_SUCCESS) {
00841                 dns_dbiterator_t *iter = &sdlziter->common;
00842                 dbiterator_destroy(&iter);
00843                 return (result);
00844         }
00845 
00846         if (sdlziter->origin != NULL) {
00847                 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
00848                 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
00849         }
00850 
00851         *iteratorp = (dns_dbiterator_t *)sdlziter;
00852 
00853         return (ISC_R_SUCCESS);
00854 }
00855 
00856 static isc_result_t
00857 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
00858              dns_rdatatype_t type, dns_rdatatype_t covers,
00859              isc_stdtime_t now, dns_rdataset_t *rdataset,
00860              dns_rdataset_t *sigrdataset)
00861 {
00862         dns_rdatalist_t *list;
00863         dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
00864 
00865         REQUIRE(VALID_SDLZNODE(node));
00866 
00867         UNUSED(db);
00868         UNUSED(version);
00869         UNUSED(covers);
00870         UNUSED(now);
00871         UNUSED(sigrdataset);
00872 
00873         if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
00874                 return (ISC_R_NOTIMPLEMENTED);
00875 
00876         list = ISC_LIST_HEAD(sdlznode->lists);
00877         while (list != NULL) {
00878                 if (list->type == type)
00879                         break;
00880                 list = ISC_LIST_NEXT(list, link);
00881         }
00882         if (list == NULL)
00883                 return (ISC_R_NOTFOUND);
00884 
00885         list_tordataset(list, db, node, rdataset);
00886 
00887         return (ISC_R_SUCCESS);
00888 }
00889 
00890 static isc_result_t
00891 findext(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
00892         dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
00893         dns_dbnode_t **nodep, dns_name_t *foundname,
00894         dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
00895         dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
00896 {
00897         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
00898         dns_dbnode_t *node = NULL;
00899         dns_fixedname_t fname;
00900         dns_rdataset_t xrdataset;
00901         dns_name_t *xname;
00902         unsigned int nlabels, olabels;
00903         isc_result_t result;
00904         unsigned int i;
00905 
00906         REQUIRE(VALID_SDLZDB(sdlz));
00907         REQUIRE(nodep == NULL || *nodep == NULL);
00908         REQUIRE(version == NULL ||
00909                 version == (void*)&sdlz->dummy_version ||
00910                 version == sdlz->future_version);
00911 
00912         UNUSED(sdlz);
00913 
00914         if (!dns_name_issubdomain(name, &db->origin))
00915                 return (DNS_R_NXDOMAIN);
00916 
00917         olabels = dns_name_countlabels(&db->origin);
00918         nlabels = dns_name_countlabels(name);
00919 
00920         dns_fixedname_init(&fname);
00921         xname = dns_fixedname_name(&fname);
00922 
00923         if (rdataset == NULL) {
00924                 dns_rdataset_init(&xrdataset);
00925                 rdataset = &xrdataset;
00926         }
00927 
00928         result = DNS_R_NXDOMAIN;
00929 
00930         /*
00931          * If we're not walking down searching for zone
00932          * cuts, we can cut straight to the chase
00933          */
00934         if ((options & DNS_DBFIND_NOZONECUT) != 0) {
00935                 i = nlabels;
00936                 goto search;
00937         }
00938 
00939         for (i = olabels; i <= nlabels; i++) {
00940  search:
00941                 /*
00942                  * Look up the next label.
00943                  */
00944                 dns_name_getlabelsequence(name, nlabels - i, i, xname);
00945                 result = getnodedata(db, xname, ISC_FALSE, options,
00946                                      methods, clientinfo, &node);
00947                 if (result == ISC_R_NOTFOUND) {
00948                         result = DNS_R_NXDOMAIN;
00949                         continue;
00950                 } else if (result != ISC_R_SUCCESS)
00951                         break;
00952 
00953                 /*
00954                  * Look for a DNAME at the current label, unless this is
00955                  * the qname.
00956                  */
00957                 if (i < nlabels) {
00958                         result = findrdataset(db, node, version,
00959                                               dns_rdatatype_dname, 0, now,
00960                                               rdataset, sigrdataset);
00961                         if (result == ISC_R_SUCCESS) {
00962                                 result = DNS_R_DNAME;
00963                                 break;
00964                         }
00965                 }
00966 
00967                 /*
00968                  * Look for an NS at the current label, unless this is the
00969                  * origin, glue is ok, or there are known to be no zone cuts.
00970                  */
00971                 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
00972                     (options & DNS_DBFIND_NOZONECUT) == 0)
00973                 {
00974                         result = findrdataset(db, node, version,
00975                                               dns_rdatatype_ns, 0, now,
00976                                               rdataset, sigrdataset);
00977 
00978                         if (result == ISC_R_SUCCESS &&
00979                             i == nlabels && type == dns_rdatatype_any)
00980                         {
00981                                 result = DNS_R_ZONECUT;
00982                                 dns_rdataset_disassociate(rdataset);
00983                                 if (sigrdataset != NULL &&
00984                                     dns_rdataset_isassociated(sigrdataset))
00985                                         dns_rdataset_disassociate(sigrdataset);
00986                                 break;
00987                         } else if (result == ISC_R_SUCCESS) {
00988                                 result = DNS_R_DELEGATION;
00989                                 break;
00990                         }
00991                 }
00992 
00993                 /*
00994                  * If the current name is not the qname, add another label
00995                  * and try again.
00996                  */
00997                 if (i < nlabels) {
00998                         destroynode(node);
00999                         node = NULL;
01000                         continue;
01001                 }
01002 
01003                 /*
01004                  * If we're looking for ANY, we're done.
01005                  */
01006                 if (type == dns_rdatatype_any) {
01007                         result = ISC_R_SUCCESS;
01008                         break;
01009                 }
01010 
01011                 /*
01012                  * Look for the qtype.
01013                  */
01014                 result = findrdataset(db, node, version, type, 0, now,
01015                                       rdataset, sigrdataset);
01016                 if (result == ISC_R_SUCCESS)
01017                         break;
01018 
01019                 /*
01020                  * Look for a CNAME
01021                  */
01022                 if (type != dns_rdatatype_cname) {
01023                         result = findrdataset(db, node, version,
01024                                               dns_rdatatype_cname, 0, now,
01025                                               rdataset, sigrdataset);
01026                         if (result == ISC_R_SUCCESS) {
01027                                 result = DNS_R_CNAME;
01028                                 break;
01029                         }
01030                 }
01031 
01032                 result = DNS_R_NXRRSET;
01033                 break;
01034         }
01035 
01036         if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
01037                 dns_rdataset_disassociate(rdataset);
01038 
01039         if (foundname != NULL) {
01040                 isc_result_t xresult;
01041 
01042                 xresult = dns_name_copy(xname, foundname, NULL);
01043                 if (xresult != ISC_R_SUCCESS) {
01044                         if (node != NULL)
01045                                 destroynode(node);
01046                         if (dns_rdataset_isassociated(rdataset))
01047                                 dns_rdataset_disassociate(rdataset);
01048                         return (DNS_R_BADDB);
01049                 }
01050         }
01051 
01052         if (nodep != NULL)
01053                 *nodep = node;
01054         else if (node != NULL)
01055                 detachnode(db, &node);
01056 
01057         return (result);
01058 }
01059 
01060 static isc_result_t
01061 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
01062      dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
01063      dns_dbnode_t **nodep, dns_name_t *foundname,
01064      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
01065 {
01066         return (findext(db, name, version, type, options, now, nodep,
01067                         foundname, NULL, NULL, rdataset, sigrdataset));
01068 }
01069 
01070 static isc_result_t
01071 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01072              isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
01073 {
01074         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
01075         sdlz_rdatasetiter_t *iterator;
01076 
01077         REQUIRE(VALID_SDLZDB(sdlz));
01078 
01079         REQUIRE(version == NULL ||
01080                 version == (void*)&sdlz->dummy_version ||
01081                 version == sdlz->future_version);
01082 
01083         UNUSED(version);
01084         UNUSED(now);
01085 
01086         iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
01087         if (iterator == NULL)
01088                 return (ISC_R_NOMEMORY);
01089 
01090         iterator->common.magic = DNS_RDATASETITER_MAGIC;
01091         iterator->common.methods = &rdatasetiter_methods;
01092         iterator->common.db = db;
01093         iterator->common.node = NULL;
01094         attachnode(db, node, &iterator->common.node);
01095         iterator->common.version = version;
01096         iterator->common.now = now;
01097 
01098         *iteratorp = (dns_rdatasetiter_t *)iterator;
01099 
01100         return (ISC_R_SUCCESS);
01101 }
01102 
01103 static isc_result_t
01104 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01105             dns_rdataset_t *rdataset, unsigned int options,
01106             dns_sdlzmodrdataset_t mod_function)
01107 {
01108         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
01109         dns_master_style_t *style = NULL;
01110         isc_result_t result;
01111         isc_buffer_t *buffer = NULL;
01112         isc_mem_t *mctx;
01113         dns_sdlznode_t *sdlznode;
01114         char *rdatastr = NULL;
01115         char name[DNS_NAME_MAXTEXT + 1];
01116 
01117         REQUIRE(VALID_SDLZDB(sdlz));
01118 
01119         if (mod_function == NULL)
01120                 return (ISC_R_NOTIMPLEMENTED);
01121 
01122         sdlznode = (dns_sdlznode_t *)node;
01123 
01124         UNUSED(options);
01125 
01126         dns_name_format(sdlznode->name, name, sizeof(name));
01127 
01128         mctx = sdlz->common.mctx;
01129 
01130         result = isc_buffer_allocate(mctx, &buffer, 1024);
01131         if (result != ISC_R_SUCCESS)
01132                 return (result);
01133 
01134         result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, mctx);
01135         if (result != ISC_R_SUCCESS)
01136                 goto cleanup;
01137 
01138         result = dns_master_rdatasettotext(sdlznode->name, rdataset,
01139                                            style, buffer);
01140         if (result != ISC_R_SUCCESS)
01141                 goto cleanup;
01142 
01143         if (isc_buffer_usedlength(buffer) < 1) {
01144                 result = ISC_R_BADADDRESSFORM;
01145                 goto cleanup;
01146         }
01147 
01148         rdatastr = isc_buffer_base(buffer);
01149         if (rdatastr == NULL) {
01150                 result = ISC_R_NOMEMORY;
01151                 goto cleanup;
01152         }
01153         rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
01154 
01155         MAYBE_LOCK(sdlz->dlzimp);
01156         result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
01157                               sdlz->dbdata, version);
01158         MAYBE_UNLOCK(sdlz->dlzimp);
01159 
01160 cleanup:
01161         isc_buffer_free(&buffer);
01162         if (style != NULL)
01163                 dns_master_styledestroy(&style, mctx);
01164 
01165         return (result);
01166 }
01167 
01168 static isc_result_t
01169 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01170             isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
01171             dns_rdataset_t *addedrdataset)
01172 {
01173         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
01174         isc_result_t result;
01175 
01176         UNUSED(now);
01177         UNUSED(addedrdataset);
01178         REQUIRE(VALID_SDLZDB(sdlz));
01179 
01180         if (sdlz->dlzimp->methods->addrdataset == NULL)
01181                 return (ISC_R_NOTIMPLEMENTED);
01182 
01183         result = modrdataset(db, node, version, rdataset, options,
01184                              sdlz->dlzimp->methods->addrdataset);
01185         return (result);
01186 }
01187 
01188 
01189 static isc_result_t
01190 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01191                  dns_rdataset_t *rdataset, unsigned int options,
01192                  dns_rdataset_t *newrdataset)
01193 {
01194         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
01195         isc_result_t result;
01196 
01197         UNUSED(newrdataset);
01198         REQUIRE(VALID_SDLZDB(sdlz));
01199 
01200         if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
01201                 return (ISC_R_NOTIMPLEMENTED);
01202         }
01203 
01204         result = modrdataset(db, node, version, rdataset, options,
01205                              sdlz->dlzimp->methods->subtractrdataset);
01206         return (result);
01207 }
01208 
01209 static isc_result_t
01210 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
01211                dns_rdatatype_t type, dns_rdatatype_t covers)
01212 {
01213         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
01214         char name[DNS_NAME_MAXTEXT + 1];
01215         char b_type[DNS_RDATATYPE_FORMATSIZE];
01216         dns_sdlznode_t *sdlznode;
01217         isc_result_t result;
01218 
01219         UNUSED(covers);
01220 
01221         REQUIRE(VALID_SDLZDB(sdlz));
01222 
01223         if (sdlz->dlzimp->methods->delrdataset == NULL)
01224                 return (ISC_R_NOTIMPLEMENTED);
01225 
01226         sdlznode = (dns_sdlznode_t *)node;
01227         dns_name_format(sdlznode->name, name, sizeof(name));
01228         dns_rdatatype_format(type, b_type, sizeof(b_type));
01229 
01230         MAYBE_LOCK(sdlz->dlzimp);
01231         result = sdlz->dlzimp->methods->delrdataset(name, b_type,
01232                                                     sdlz->dlzimp->driverarg,
01233                                                     sdlz->dbdata, version);
01234         MAYBE_UNLOCK(sdlz->dlzimp);
01235 
01236         return (result);
01237 }
01238 
01239 static isc_boolean_t
01240 issecure(dns_db_t *db) {
01241         UNUSED(db);
01242 
01243         return (ISC_FALSE);
01244 }
01245 
01246 static unsigned int
01247 nodecount(dns_db_t *db) {
01248         UNUSED(db);
01249 
01250         return (0);
01251 }
01252 
01253 static isc_boolean_t
01254 ispersistent(dns_db_t *db) {
01255         UNUSED(db);
01256         return (ISC_TRUE);
01257 }
01258 
01259 static void
01260 overmem(dns_db_t *db, isc_boolean_t over) {
01261         UNUSED(db);
01262         UNUSED(over);
01263 }
01264 
01265 static void
01266 settask(dns_db_t *db, isc_task_t *task) {
01267         UNUSED(db);
01268         UNUSED(task);
01269 }
01270 
01271 /*
01272  * getoriginnode() is used by the update code to find the
01273  * dns_rdatatype_dnskey record for a zone
01274  */
01275 static isc_result_t
01276 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
01277         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
01278         isc_result_t result;
01279 
01280         REQUIRE(VALID_SDLZDB(sdlz));
01281         if (sdlz->dlzimp->methods->newversion == NULL)
01282                 return (ISC_R_NOTIMPLEMENTED);
01283 
01284         result = getnodedata(db, &sdlz->common.origin, ISC_FALSE,
01285                              0, NULL, NULL, nodep);
01286         if (result != ISC_R_SUCCESS)
01287                 sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
01288                          isc_result_totext(result));
01289         return (result);
01290 }
01291 
01292 static dns_dbmethods_t sdlzdb_methods = {
01293         attach,
01294         detach,
01295         beginload,
01296         endload,
01297         NULL,
01298         dump,
01299         currentversion,
01300         newversion,
01301         attachversion,
01302         closeversion,
01303         findnode,
01304         find,
01305         findzonecut,
01306         attachnode,
01307         detachnode,
01308         expirenode,
01309         printnode,
01310         createiterator,
01311         findrdataset,
01312         allrdatasets,
01313         addrdataset,
01314         subtractrdataset,
01315         deleterdataset,
01316         issecure,
01317         nodecount,
01318         ispersistent,
01319         overmem,
01320         settask,
01321         getoriginnode,
01322         NULL,                   /* transfernode */
01323         NULL,                   /* getnsec3parameters */
01324         NULL,                   /* findnsec3node */
01325         NULL,                   /* setsigningtime */
01326         NULL,                   /* getsigningtime */
01327         NULL,                   /* resigned */
01328         NULL,                   /* isdnssec */
01329         NULL,                   /* getrrsetstats */
01330         NULL,                   /* rpz_attach */
01331         NULL,                   /* rpz_ready */
01332         findnodeext,
01333         findext,
01334         NULL,                   /* setcachestats */
01335         NULL                    /* hashsize */
01336 };
01337 
01338 /*
01339  * Database Iterator Methods.  These methods were "borrowed" from the SDB
01340  * driver interface.  See the SDB driver interface documentation for more info.
01341  */
01342 
01343 static void
01344 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
01345         sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
01346         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
01347 
01348         while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
01349                 dns_sdlznode_t *node;
01350                 node = ISC_LIST_HEAD(sdlziter->nodelist);
01351                 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
01352                 destroynode(node);
01353         }
01354 
01355         dns_db_detach(&sdlziter->common.db);
01356         isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
01357 
01358         *iteratorp = NULL;
01359 }
01360 
01361 static isc_result_t
01362 dbiterator_first(dns_dbiterator_t *iterator) {
01363         sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
01364 
01365         sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
01366         if (sdlziter->current == NULL)
01367                 return (ISC_R_NOMORE);
01368         else
01369                 return (ISC_R_SUCCESS);
01370 }
01371 
01372 static isc_result_t
01373 dbiterator_last(dns_dbiterator_t *iterator) {
01374         sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
01375 
01376         sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
01377         if (sdlziter->current == NULL)
01378                 return (ISC_R_NOMORE);
01379         else
01380                 return (ISC_R_SUCCESS);
01381 }
01382 
01383 static isc_result_t
01384 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
01385         sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
01386 
01387         sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
01388         while (sdlziter->current != NULL) {
01389                 if (dns_name_equal(sdlziter->current->name, name))
01390                         return (ISC_R_SUCCESS);
01391                 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
01392         }
01393         return (ISC_R_NOTFOUND);
01394 }
01395 
01396 static isc_result_t
01397 dbiterator_prev(dns_dbiterator_t *iterator) {
01398         sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
01399 
01400         sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
01401         if (sdlziter->current == NULL)
01402                 return (ISC_R_NOMORE);
01403         else
01404                 return (ISC_R_SUCCESS);
01405 }
01406 
01407 static isc_result_t
01408 dbiterator_next(dns_dbiterator_t *iterator) {
01409         sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
01410 
01411         sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
01412         if (sdlziter->current == NULL)
01413                 return (ISC_R_NOMORE);
01414         else
01415                 return (ISC_R_SUCCESS);
01416 }
01417 
01418 static isc_result_t
01419 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
01420                    dns_name_t *name)
01421 {
01422         sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
01423 
01424         attachnode(iterator->db, sdlziter->current, nodep);
01425         if (name != NULL)
01426                 return (dns_name_copy(sdlziter->current->name, name, NULL));
01427         return (ISC_R_SUCCESS);
01428 }
01429 
01430 static isc_result_t
01431 dbiterator_pause(dns_dbiterator_t *iterator) {
01432         UNUSED(iterator);
01433         return (ISC_R_SUCCESS);
01434 }
01435 
01436 static isc_result_t
01437 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
01438         UNUSED(iterator);
01439         return (dns_name_copy(dns_rootname, name, NULL));
01440 }
01441 
01442 /*
01443  * Rdataset Methods. These methods were "borrowed" from the SDB driver
01444  * interface.  See the SDB driver interface documentation for more info.
01445  */
01446 
01447 static void
01448 disassociate(dns_rdataset_t *rdataset) {
01449         dns_dbnode_t *node = rdataset->private5;
01450         dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
01451         dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
01452 
01453         detachnode(db, &node);
01454         isc__rdatalist_disassociate(rdataset);
01455 }
01456 
01457 static void
01458 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
01459         dns_dbnode_t *node = source->private5;
01460         dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
01461         dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
01462         dns_dbnode_t *tempdb = NULL;
01463 
01464         isc__rdatalist_clone(source, target);
01465         attachnode(db, node, &tempdb);
01466         source->private5 = tempdb;
01467 }
01468 
01469 static dns_rdatasetmethods_t rdataset_methods = {
01470         disassociate,
01471         isc__rdatalist_first,
01472         isc__rdatalist_next,
01473         isc__rdatalist_current,
01474         rdataset_clone,
01475         isc__rdatalist_count,
01476         isc__rdatalist_addnoqname,
01477         isc__rdatalist_getnoqname,
01478         NULL,
01479         NULL,
01480         NULL,
01481         NULL,
01482         NULL,
01483         NULL,
01484         NULL,
01485         NULL,
01486         NULL,
01487         NULL
01488 };
01489 
01490 static void
01491 list_tordataset(dns_rdatalist_t *rdatalist,
01492                 dns_db_t *db, dns_dbnode_t *node,
01493                 dns_rdataset_t *rdataset)
01494 {
01495         /*
01496          * The sdlz rdataset is an rdatalist with some additions.
01497          *      - private1 & private2 are used by the rdatalist.
01498          *      - private3 & private 4 are unused.
01499          *      - private5 is the node.
01500          */
01501 
01502         /* This should never fail. */
01503         RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
01504                       ISC_R_SUCCESS);
01505 
01506         rdataset->methods = &rdataset_methods;
01507         dns_db_attachnode(db, node, &rdataset->private5);
01508 }
01509 
01510 /*
01511  * SDLZ core methods. This is the core of the new DLZ functionality.
01512  */
01513 
01514 /*%
01515  * Build a 'bind' database driver structure to be returned by
01516  * either the find zone or the allow zone transfer method.
01517  * This method is only available in this source file, it is
01518  * not made available anywhere else.
01519  */
01520 
01521 static isc_result_t
01522 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
01523                   dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
01524 {
01525         isc_result_t result;
01526         dns_sdlz_db_t *sdlzdb;
01527         dns_sdlzimplementation_t *imp;
01528 
01529         /* check that things are as we expect */
01530         REQUIRE(dbp != NULL && *dbp == NULL);
01531         REQUIRE(name != NULL);
01532 
01533         imp = (dns_sdlzimplementation_t *) driverarg;
01534 
01535         /* allocate and zero memory for driver structure */
01536         sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
01537         if (sdlzdb == NULL)
01538                 return (ISC_R_NOMEMORY);
01539         memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
01540 
01541         /* initialize and set origin */
01542         dns_name_init(&sdlzdb->common.origin, NULL);
01543         result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
01544         if (result != ISC_R_SUCCESS)
01545                 goto mem_cleanup;
01546 
01547         /* initialize the reference count mutex */
01548         result = isc_mutex_init(&sdlzdb->refcnt_lock);
01549         if (result != ISC_R_SUCCESS)
01550                 goto name_cleanup;
01551 
01552         /* set the rest of the database structure attributes */
01553         sdlzdb->dlzimp = imp;
01554         sdlzdb->common.methods = &sdlzdb_methods;
01555         sdlzdb->common.attributes = 0;
01556         sdlzdb->common.rdclass = rdclass;
01557         sdlzdb->common.mctx = NULL;
01558         sdlzdb->dbdata = dbdata;
01559         sdlzdb->references = 1;
01560 
01561         /* attach to the memory context */
01562         isc_mem_attach(mctx, &sdlzdb->common.mctx);
01563 
01564         /* mark structure as valid */
01565         sdlzdb->common.magic = DNS_DB_MAGIC;
01566         sdlzdb->common.impmagic = SDLZDB_MAGIC;
01567         *dbp = (dns_db_t *) sdlzdb;
01568 
01569         return (result);
01570 
01571         /*
01572          * reference count mutex could not be initialized, clean up
01573          * name memory
01574          */
01575  name_cleanup:
01576         dns_name_free(&sdlzdb->common.origin, mctx);
01577  mem_cleanup:
01578         isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
01579         return (result);
01580 }
01581 
01582 static isc_result_t
01583 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
01584                      dns_rdataclass_t rdclass, dns_name_t *name,
01585                      isc_sockaddr_t *clientaddr, dns_db_t **dbp)
01586 {
01587         isc_buffer_t b;
01588         isc_buffer_t b2;
01589         char namestr[DNS_NAME_MAXTEXT + 1];
01590         char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
01591                        + 1];
01592         isc_netaddr_t netaddr;
01593         isc_result_t result;
01594         dns_sdlzimplementation_t *imp;
01595 
01596         /*
01597          * Perform checks to make sure data is as we expect it to be.
01598          */
01599         REQUIRE(driverarg != NULL);
01600         REQUIRE(name != NULL);
01601         REQUIRE(clientaddr != NULL);
01602         REQUIRE(dbp != NULL && *dbp == NULL);
01603 
01604         imp = (dns_sdlzimplementation_t *) driverarg;
01605 
01606         /* Convert DNS name to ascii text */
01607         isc_buffer_init(&b, namestr, sizeof(namestr));
01608         result = dns_name_totext(name, ISC_TRUE, &b);
01609         if (result != ISC_R_SUCCESS)
01610                 return (result);
01611         isc_buffer_putuint8(&b, 0);
01612 
01613         /* convert client address to ascii text */
01614         isc_buffer_init(&b2, clientstr, sizeof(clientstr));
01615         isc_netaddr_fromsockaddr(&netaddr, clientaddr);
01616         result = isc_netaddr_totext(&netaddr, &b2);
01617         if (result != ISC_R_SUCCESS)
01618                 return (result);
01619         isc_buffer_putuint8(&b2, 0);
01620 
01621         /* make sure strings are always lowercase */
01622         dns_sdlz_tolower(namestr);
01623         dns_sdlz_tolower(clientstr);
01624 
01625         /* Call SDLZ driver's find zone method */
01626         if (imp->methods->allowzonexfr != NULL) {
01627                 MAYBE_LOCK(imp);
01628                 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
01629                                                     namestr, clientstr);
01630                 MAYBE_UNLOCK(imp);
01631                 /*
01632                  * if zone is supported and transfers allowed build a 'bind'
01633                  * database driver
01634                  */
01635                 if (result == ISC_R_SUCCESS)
01636                         result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
01637                                                    name, rdclass, dbp);
01638                 return (result);
01639         }
01640 
01641         return (ISC_R_NOTIMPLEMENTED);
01642 }
01643 
01644 static isc_result_t
01645 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
01646                char *argv[], void *driverarg, void **dbdata)
01647 {
01648         dns_sdlzimplementation_t *imp;
01649         isc_result_t result = ISC_R_NOTFOUND;
01650 
01651         /* Write debugging message to log */
01652         sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
01653 
01654         /*
01655          * Performs checks to make sure data is as we expect it to be.
01656          */
01657         REQUIRE(driverarg != NULL);
01658         REQUIRE(dlzname != NULL);
01659         REQUIRE(dbdata != NULL);
01660         UNUSED(mctx);
01661 
01662         imp = driverarg;
01663 
01664         /* If the create method exists, call it. */
01665         if (imp->methods->create != NULL) {
01666                 MAYBE_LOCK(imp);
01667                 result = imp->methods->create(dlzname, argc, argv,
01668                                               imp->driverarg, dbdata);
01669                 MAYBE_UNLOCK(imp);
01670         }
01671 
01672         /* Write debugging message to log */
01673         if (result == ISC_R_SUCCESS) {
01674                 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
01675         } else {
01676                 sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
01677         }
01678 
01679         return (result);
01680 }
01681 
01682 static void
01683 dns_sdlzdestroy(void *driverdata, void **dbdata) {
01684         dns_sdlzimplementation_t *imp;
01685 
01686         /* Write debugging message to log */
01687         sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
01688 
01689         imp = driverdata;
01690 
01691         /* If the destroy method exists, call it. */
01692         if (imp->methods->destroy != NULL) {
01693                 MAYBE_LOCK(imp);
01694                 imp->methods->destroy(imp->driverarg, dbdata);
01695                 MAYBE_UNLOCK(imp);
01696         }
01697 }
01698 
01699 static isc_result_t
01700 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
01701                  dns_rdataclass_t rdclass, dns_name_t *name,
01702                  dns_clientinfomethods_t *methods,
01703                  dns_clientinfo_t *clientinfo,
01704                  dns_db_t **dbp)
01705 {
01706         isc_buffer_t b;
01707         char namestr[DNS_NAME_MAXTEXT + 1];
01708         isc_result_t result;
01709         dns_sdlzimplementation_t *imp;
01710 
01711         /*
01712          * Perform checks to make sure data is as we expect it to be.
01713          */
01714         REQUIRE(driverarg != NULL);
01715         REQUIRE(name != NULL);
01716         REQUIRE(dbp != NULL && *dbp == NULL);
01717 
01718         imp = (dns_sdlzimplementation_t *) driverarg;
01719 
01720         /* Convert DNS name to ascii text */
01721         isc_buffer_init(&b, namestr, sizeof(namestr));
01722         result = dns_name_totext(name, ISC_TRUE, &b);
01723         if (result != ISC_R_SUCCESS)
01724                 return (result);
01725         isc_buffer_putuint8(&b, 0);
01726 
01727         /* make sure strings are always lowercase */
01728         dns_sdlz_tolower(namestr);
01729 
01730         /* Call SDLZ driver's find zone method */
01731         MAYBE_LOCK(imp);
01732         result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
01733                                         methods, clientinfo);
01734         MAYBE_UNLOCK(imp);
01735 
01736         /*
01737          * if zone is supported build a 'bind' database driver
01738          * structure to return
01739          */
01740         if (result == ISC_R_SUCCESS)
01741                 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
01742                                            rdclass, dbp);
01743 
01744         return (result);
01745 }
01746 
01747 
01748 static isc_result_t
01749 dns_sdlzconfigure(void *driverarg, void *dbdata,
01750                   dns_view_t *view, dns_dlzdb_t *dlzdb)
01751 {
01752         isc_result_t result;
01753         dns_sdlzimplementation_t *imp;
01754 
01755         REQUIRE(driverarg != NULL);
01756 
01757         imp = (dns_sdlzimplementation_t *) driverarg;
01758 
01759         /* Call SDLZ driver's configure method */
01760         if (imp->methods->configure != NULL) {
01761                 MAYBE_LOCK(imp);
01762                 result = imp->methods->configure(view, dlzdb,
01763                                                  imp->driverarg, dbdata);
01764                 MAYBE_UNLOCK(imp);
01765         } else {
01766                 result = ISC_R_SUCCESS;
01767         }
01768 
01769         return (result);
01770 }
01771 
01772 static isc_boolean_t
01773 dns_sdlzssumatch(dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
01774                  dns_rdatatype_t type, const dst_key_t *key, void *driverarg,
01775                  void *dbdata)
01776 {
01777         dns_sdlzimplementation_t *imp;
01778         char b_signer[DNS_NAME_FORMATSIZE];
01779         char b_name[DNS_NAME_FORMATSIZE];
01780         char b_addr[ISC_NETADDR_FORMATSIZE];
01781         char b_type[DNS_RDATATYPE_FORMATSIZE];
01782         char b_key[DST_KEY_FORMATSIZE];
01783         isc_buffer_t *tkey_token = NULL;
01784         isc_region_t token_region;
01785         isc_uint32_t token_len = 0;
01786         isc_boolean_t ret;
01787 
01788         REQUIRE(driverarg != NULL);
01789 
01790         imp = (dns_sdlzimplementation_t *) driverarg;
01791         if (imp->methods->ssumatch == NULL)
01792                 return (ISC_FALSE);
01793 
01794         /*
01795          * Format the request elements. sdlz operates on strings, not
01796          * structures
01797          */
01798         if (signer != NULL)
01799                 dns_name_format(signer, b_signer, sizeof(b_signer));
01800         else
01801                 b_signer[0] = 0;
01802 
01803         dns_name_format(name, b_name, sizeof(b_name));
01804 
01805         if (tcpaddr != NULL)
01806                 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
01807         else
01808                 b_addr[0] = 0;
01809 
01810         dns_rdatatype_format(type, b_type, sizeof(b_type));
01811 
01812         if (key != NULL) {
01813                 dst_key_format(key, b_key, sizeof(b_key));
01814                 tkey_token = dst_key_tkeytoken(key);
01815         } else
01816                 b_key[0] = 0;
01817 
01818         if (tkey_token != NULL) {
01819                 isc_buffer_region(tkey_token, &token_region);
01820                 token_len = token_region.length;
01821         }
01822 
01823         MAYBE_LOCK(imp);
01824         ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
01825                                      token_len,
01826                                      token_len != 0 ? token_region.base : NULL,
01827                                      imp->driverarg, dbdata);
01828         MAYBE_UNLOCK(imp);
01829         return (ret);
01830 }
01831 
01832 static dns_dlzmethods_t sdlzmethods = {
01833         dns_sdlzcreate,
01834         dns_sdlzdestroy,
01835         dns_sdlzfindzone,
01836         dns_sdlzallowzonexfr,
01837         dns_sdlzconfigure,
01838         dns_sdlzssumatch
01839 };
01840 
01841 /*
01842  * Public functions.
01843  */
01844 
01845 isc_result_t
01846 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
01847                const char *data)
01848 {
01849         dns_rdatalist_t *rdatalist;
01850         dns_rdata_t *rdata;
01851         dns_rdatatype_t typeval;
01852         isc_consttextregion_t r;
01853         isc_buffer_t b;
01854         isc_buffer_t *rdatabuf = NULL;
01855         isc_lex_t *lex;
01856         isc_result_t result;
01857         unsigned int size;
01858         isc_mem_t *mctx;
01859         dns_name_t *origin;
01860 
01861         REQUIRE(VALID_SDLZLOOKUP(lookup));
01862         REQUIRE(type != NULL);
01863         REQUIRE(data != NULL);
01864 
01865         mctx = lookup->sdlz->common.mctx;
01866 
01867         r.base = type;
01868         r.length = strlen(type);
01869         result = dns_rdatatype_fromtext(&typeval, (void *) &r);
01870         if (result != ISC_R_SUCCESS)
01871                 return (result);
01872 
01873         rdatalist = ISC_LIST_HEAD(lookup->lists);
01874         while (rdatalist != NULL) {
01875                 if (rdatalist->type == typeval)
01876                         break;
01877                 rdatalist = ISC_LIST_NEXT(rdatalist, link);
01878         }
01879 
01880         if (rdatalist == NULL) {
01881                 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
01882                 if (rdatalist == NULL)
01883                         return (ISC_R_NOMEMORY);
01884                 dns_rdatalist_init(rdatalist);
01885                 rdatalist->rdclass = lookup->sdlz->common.rdclass;
01886                 rdatalist->type = typeval;
01887                 rdatalist->ttl = ttl;
01888                 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
01889         } else
01890                 if (rdatalist->ttl > ttl) {
01891                         /*
01892                          * BIND9 doesn't enforce all RRs in an RRset
01893                          * having the same TTL, as per RFC 2136,
01894                          * section 7.12. If a DLZ backend has
01895                          * different TTLs, then the best
01896                          * we can do is return the lowest.
01897                         */
01898                         rdatalist->ttl = ttl;
01899                 }
01900 
01901         rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
01902         if (rdata == NULL)
01903                 return (ISC_R_NOMEMORY);
01904         dns_rdata_init(rdata);
01905 
01906         if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
01907                 origin = &lookup->sdlz->common.origin;
01908         else
01909                 origin = dns_rootname;
01910 
01911         lex = NULL;
01912         result = isc_lex_create(mctx, 64, &lex);
01913         if (result != ISC_R_SUCCESS)
01914                 goto failure;
01915 
01916         size = initial_size(data);
01917         do {
01918                 isc_buffer_constinit(&b, data, strlen(data));
01919                 isc_buffer_add(&b, strlen(data));
01920 
01921                 result = isc_lex_openbuffer(lex, &b);
01922                 if (result != ISC_R_SUCCESS)
01923                         goto failure;
01924 
01925                 rdatabuf = NULL;
01926                 result = isc_buffer_allocate(mctx, &rdatabuf, size);
01927                 if (result != ISC_R_SUCCESS)
01928                         goto failure;
01929 
01930                 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
01931                                             rdatalist->type, lex,
01932                                             origin, ISC_FALSE,
01933                                             mctx, rdatabuf,
01934                                             &lookup->callbacks);
01935                 if (result != ISC_R_SUCCESS)
01936                         isc_buffer_free(&rdatabuf);
01937                 if (size >= 65535)
01938                         break;
01939                 size *= 2;
01940                 if (size >= 65535)
01941                         size = 65535;
01942         } while (result == ISC_R_NOSPACE);
01943 
01944         if (result != ISC_R_SUCCESS)
01945                 goto failure;
01946 
01947         ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
01948         ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
01949 
01950         if (lex != NULL)
01951                 isc_lex_destroy(&lex);
01952 
01953         return (ISC_R_SUCCESS);
01954 
01955  failure:
01956         if (rdatabuf != NULL)
01957                 isc_buffer_free(&rdatabuf);
01958         if (lex != NULL)
01959                 isc_lex_destroy(&lex);
01960         isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
01961 
01962         return (result);
01963 }
01964 
01965 isc_result_t
01966 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
01967                     const char *type, dns_ttl_t ttl, const char *data)
01968 {
01969         dns_name_t *newname, *origin;
01970         dns_fixedname_t fnewname;
01971         dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
01972         dns_sdlznode_t *sdlznode;
01973         isc_mem_t *mctx = sdlz->common.mctx;
01974         isc_buffer_t b;
01975         isc_result_t result;
01976 
01977         dns_fixedname_init(&fnewname);
01978         newname = dns_fixedname_name(&fnewname);
01979 
01980         if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
01981                 origin = &sdlz->common.origin;
01982         else
01983                 origin = dns_rootname;
01984         isc_buffer_constinit(&b, name, strlen(name));
01985         isc_buffer_add(&b, strlen(name));
01986 
01987         result = dns_name_fromtext(newname, &b, origin, 0, NULL);
01988         if (result != ISC_R_SUCCESS)
01989                 return (result);
01990 
01991         if (allnodes->common.relative_names) {
01992                 /* All names are relative to the root */
01993                 unsigned int nlabels = dns_name_countlabels(newname);
01994                 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
01995         }
01996 
01997         sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
01998         if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
01999                 sdlznode = NULL;
02000                 result = createnode(sdlz, &sdlznode);
02001                 if (result != ISC_R_SUCCESS)
02002                         return (result);
02003                 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
02004                 if (sdlznode->name == NULL) {
02005                         destroynode(sdlznode);
02006                         return (ISC_R_NOMEMORY);
02007                 }
02008                 dns_name_init(sdlznode->name, NULL);
02009                 result = dns_name_dup(newname, mctx, sdlznode->name);
02010                 if (result != ISC_R_SUCCESS) {
02011                         isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
02012                         destroynode(sdlznode);
02013                         return (result);
02014                 }
02015                 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
02016                 if (allnodes->origin == NULL &&
02017                     dns_name_equal(newname, &sdlz->common.origin))
02018                         allnodes->origin = sdlznode;
02019         }
02020         return (dns_sdlz_putrr(sdlznode, type, ttl, data));
02021 
02022 }
02023 
02024 isc_result_t
02025 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
02026                 isc_uint32_t serial)
02027 {
02028         char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
02029         int n;
02030 
02031         REQUIRE(mname != NULL);
02032         REQUIRE(rname != NULL);
02033 
02034         n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
02035                      mname, rname, serial,
02036                      SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
02037                      SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
02038         if (n >= (int)sizeof(str) || n < 0)
02039                 return (ISC_R_NOSPACE);
02040         return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
02041 }
02042 
02043 isc_result_t
02044 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
02045                  void *driverarg, unsigned int flags, isc_mem_t *mctx,
02046                  dns_sdlzimplementation_t **sdlzimp)
02047 {
02048 
02049         dns_sdlzimplementation_t *imp;
02050         isc_result_t result;
02051 
02052         /*
02053          * Performs checks to make sure data is as we expect it to be.
02054          */
02055         REQUIRE(drivername != NULL);
02056         REQUIRE(methods != NULL);
02057         REQUIRE(methods->findzone != NULL);
02058         REQUIRE(methods->lookup != NULL);
02059         REQUIRE(mctx != NULL);
02060         REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
02061         REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
02062                            DNS_SDLZFLAG_RELATIVERDATA |
02063                            DNS_SDLZFLAG_THREADSAFE)) == 0);
02064 
02065         /* Write debugging message to log */
02066         sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
02067 
02068         /*
02069          * Allocate memory for a sdlz_implementation object.  Error if
02070          * we cannot.
02071          */
02072         imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
02073         if (imp == NULL)
02074                 return (ISC_R_NOMEMORY);
02075 
02076         /* Make sure memory region is set to all 0's */
02077         memset(imp, 0, sizeof(dns_sdlzimplementation_t));
02078 
02079         /* Store the data passed into this method */
02080         imp->methods = methods;
02081         imp->driverarg = driverarg;
02082         imp->flags = flags;
02083         imp->mctx = NULL;
02084 
02085         /* attach the new sdlz_implementation object to a memory context */
02086         isc_mem_attach(mctx, &imp->mctx);
02087 
02088         /*
02089          * initialize the driver lock, error if we cannot
02090          * (used if a driver does not support multiple threads)
02091          */
02092         result = isc_mutex_init(&imp->driverlock);
02093         if (result != ISC_R_SUCCESS) {
02094                 UNEXPECTED_ERROR(__FILE__, __LINE__,
02095                                  "isc_mutex_init() failed: %s",
02096                                  isc_result_totext(result));
02097                 goto cleanup_mctx;
02098         }
02099 
02100         imp->dlz_imp = NULL;
02101 
02102         /*
02103          * register the DLZ driver.  Pass in our "extra" sdlz information as
02104          * a driverarg.  (that's why we stored the passed in driver arg in our
02105          * sdlz_implementation structure)  Also, store the dlz_implementation
02106          * structure in our sdlz_implementation.
02107          */
02108         result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
02109                                  &imp->dlz_imp);
02110 
02111         /* if registration fails, cleanup and get outta here. */
02112         if (result != ISC_R_SUCCESS)
02113                 goto cleanup_mutex;
02114 
02115         *sdlzimp = imp;
02116 
02117         return (ISC_R_SUCCESS);
02118 
02119  cleanup_mutex:
02120         /* destroy the driver lock, we don't need it anymore */
02121         DESTROYLOCK(&imp->driverlock);
02122 
02123  cleanup_mctx:
02124         /*
02125          * return the memory back to the available memory pool and
02126          * remove it from the memory context.
02127          */
02128         isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
02129         isc_mem_detach(&mctx);
02130         return (result);
02131 }
02132 
02133 void
02134 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
02135         dns_sdlzimplementation_t *imp;
02136         isc_mem_t *mctx;
02137 
02138         /* Write debugging message to log */
02139         sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
02140 
02141         /*
02142          * Performs checks to make sure data is as we expect it to be.
02143          */
02144         REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
02145 
02146         imp = *sdlzimp;
02147 
02148         /* Unregister the DLZ driver implementation */
02149         dns_dlzunregister(&imp->dlz_imp);
02150 
02151         /* destroy the driver lock, we don't need it anymore */
02152         DESTROYLOCK(&imp->driverlock);
02153 
02154         mctx = imp->mctx;
02155 
02156         /*
02157          * return the memory back to the available memory pool and
02158          * remove it from the memory context.
02159          */
02160         isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
02161         isc_mem_detach(&mctx);
02162 
02163         *sdlzimp = NULL;
02164 }
02165 
02166 
02167 isc_result_t
02168 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
02169                dns_name_t *name, dns_db_t **dbp)
02170 {
02171         isc_result_t result;
02172 
02173         result = dns_sdlzcreateDBP(dlzdatabase->mctx,
02174                                    dlzdatabase->implementation->driverarg,
02175                                    dlzdatabase->dbdata, name, rdclass, dbp);
02176         return (result);
02177 }

Generated on Tue Apr 28 17:41:01 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha