2 * Portions Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
19 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
21 * Permission to use, copy, modify, and distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the
23 * above copyright notice and this permission notice appear in all
26 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
27 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
29 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
30 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
31 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
32 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
33 * USE OR PERFORMANCE OF THIS SOFTWARE.
35 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
36 * conceived and contributed by Rob Butler.
38 * Permission to use, copy, modify, and distribute this software for any
39 * purpose with or without fee is hereby granted, provided that the
40 * above copyright notice and this permission notice appear in all
43 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
44 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
46 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
47 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
48 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
49 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
50 * USE OR PERFORMANCE OF THIS SOFTWARE.
53 /* $Id: sdlz.c,v 1.2.2.9 2007/02/14 23:45:43 marka Exp $ */
60 #include <isc/buffer.h>
63 #include <isc/rwlock.h>
64 #include <isc/string.h>
66 #include <isc/magic.h>
69 #include <isc/print.h>
70 #include <isc/region.h>
72 #include <dns/callbacks.h>
74 #include <dns/dbiterator.h>
76 #include <dns/fixedname.h>
78 #include <dns/rdata.h>
79 #include <dns/rdatalist.h>
80 #include <dns/rdataset.h>
81 #include <dns/rdatasetiter.h>
82 #include <dns/rdatatype.h>
83 #include <dns/result.h>
84 #include <dns/master.h>
86 #include <dns/types.h>
88 #include "rdatalist_p.h"
94 struct dns_sdlzimplementation {
95 const dns_sdlzmethods_t *methods;
99 isc_mutex_t driverlock;
100 dns_dlzimplementation_t *dlz_imp;
107 dns_sdlzimplementation_t *dlzimp;
108 isc_mutex_t refcnt_lock;
110 unsigned int references;
113 struct dns_sdlzlookup {
117 ISC_LIST(dns_rdatalist_t) lists;
118 ISC_LIST(isc_buffer_t) buffers;
120 ISC_LINK(dns_sdlzlookup_t) link;
122 dns_rdatacallbacks_t callbacks;
124 unsigned int references;
127 typedef struct dns_sdlzlookup dns_sdlznode_t;
129 struct dns_sdlzallnodes {
130 dns_dbiterator_t common;
131 ISC_LIST(dns_sdlznode_t) nodelist;
132 dns_sdlznode_t *current;
133 dns_sdlznode_t *origin;
136 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
138 typedef struct sdlz_rdatasetiter {
139 dns_rdatasetiter_t common;
140 dns_rdatalist_t *current;
141 } sdlz_rdatasetiter_t;
144 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
147 * Note that "impmagic" is not the first four bytes of the struct, so
148 * ISC_MAGIC_VALID cannot be used.
151 #define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \
152 (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
154 #define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L')
155 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
156 #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)
158 /* These values are taken from RFC 1537 */
159 #define SDLZ_DEFAULT_REFRESH (60 * 60 * 8)
160 #define SDLZ_DEFAULT_RETRY (60 * 60 * 2)
161 #define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
162 #define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24)
164 /* This is a reasonable value */
165 #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
169 #define MAYBE_LOCK(imp) \
171 unsigned int flags = imp->flags; \
172 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
173 LOCK(&imp->driverlock); \
176 #define MAYBE_UNLOCK(imp) \
178 unsigned int flags = imp->flags; \
179 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
180 UNLOCK(&imp->driverlock); \
184 * Forward references. Try to keep these to a minimum.
187 static void list_tordataset(dns_rdatalist_t *rdatalist,
188 dns_db_t *db, dns_dbnode_t *node,
189 dns_rdataset_t *rdataset);
191 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
193 static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
194 static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
195 static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
196 static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
198 static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
199 static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
200 static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
201 dns_dbnode_t **nodep,
203 static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
204 static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
207 static dns_dbiteratormethods_t dbiterator_methods = {
223 /*% Converts the input string to lowercase, in place. */
226 dns_sdlz_tolower(char *str) {
228 unsigned int len = strlen(str);
231 for (i = 0; i < len; i++) {
232 if (str[i] >= 'A' && str[i] <= 'Z')
238 static inline unsigned int
239 initial_size(const char *data) {
240 unsigned int len = (strlen(data) / 64) + 1;
241 return (len * 64 + 64);
245 * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
246 * driver interface. See the SDB driver interface documentation for more info.
250 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
251 sdlz_rdatasetiter_t *sdlziterator =
252 (sdlz_rdatasetiter_t *)(*iteratorp);
254 detachnode(sdlziterator->common.db, &sdlziterator->common.node);
255 isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
256 sizeof(sdlz_rdatasetiter_t));
261 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
262 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
263 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
265 if (ISC_LIST_EMPTY(sdlznode->lists))
266 return (ISC_R_NOMORE);
267 sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
268 return (ISC_R_SUCCESS);
272 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
273 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
275 sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
276 if (sdlziterator->current == NULL)
277 return (ISC_R_NOMORE);
279 return (ISC_R_SUCCESS);
283 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
284 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
286 list_tordataset(sdlziterator->current, iterator->db, iterator->node,
290 static dns_rdatasetitermethods_t rdatasetiter_methods = {
291 rdatasetiter_destroy,
298 * DB routines. These methods were "borrowed" from the SDB driver interface.
299 * See the SDB driver interface documentation for more info.
303 attach(dns_db_t *source, dns_db_t **targetp) {
304 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source;
306 REQUIRE(VALID_SDLZDB(sdlz));
308 LOCK(&sdlz->refcnt_lock);
309 REQUIRE(sdlz->references > 0);
311 UNLOCK(&sdlz->refcnt_lock);
317 destroy(dns_sdlz_db_t *sdlz) {
319 mctx = sdlz->common.mctx;
321 sdlz->common.magic = 0;
322 sdlz->common.impmagic = 0;
324 isc_mutex_destroy(&sdlz->refcnt_lock);
326 dns_name_free(&sdlz->common.origin, mctx);
328 isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
329 isc_mem_detach(&mctx);
333 detach(dns_db_t **dbp) {
334 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
335 isc_boolean_t need_destroy = ISC_FALSE;
337 REQUIRE(VALID_SDLZDB(sdlz));
338 LOCK(&sdlz->refcnt_lock);
339 REQUIRE(sdlz->references > 0);
341 if (sdlz->references == 0)
342 need_destroy = ISC_TRUE;
343 UNLOCK(&sdlz->refcnt_lock);
352 beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
356 return (ISC_R_NOTIMPLEMENTED);
360 endload(dns_db_t *db, dns_dbload_t **dbloadp) {
363 return (ISC_R_NOTIMPLEMENTED);
367 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
368 dns_masterformat_t masterformat)
373 UNUSED(masterformat);
374 return (ISC_R_NOTIMPLEMENTED);
378 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
379 REQUIRE(versionp != NULL && *versionp == NULL);
383 *versionp = (void *) &dummy;
388 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
392 return (ISC_R_NOTIMPLEMENTED);
396 attachversion(dns_db_t *db, dns_dbversion_t *source,
397 dns_dbversion_t **targetp)
399 REQUIRE(source != NULL && source == (void *) &dummy);
408 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
409 REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
410 REQUIRE(commit == ISC_FALSE);
419 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
420 dns_sdlznode_t *node;
423 node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
425 return (ISC_R_NOMEMORY);
428 attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
429 ISC_LIST_INIT(node->lists);
430 ISC_LIST_INIT(node->buffers);
431 ISC_LINK_INIT(node, link);
433 result = isc_mutex_init(&node->lock);
434 if (result != ISC_R_SUCCESS) {
435 UNEXPECTED_ERROR(__FILE__, __LINE__,
436 "isc_mutex_init() failed: %s",
437 isc_result_totext(result));
438 isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t));
439 return (ISC_R_UNEXPECTED);
441 dns_rdatacallbacks_init(&node->callbacks);
442 node->references = 1;
443 node->magic = SDLZLOOKUP_MAGIC;
446 return (ISC_R_SUCCESS);
450 destroynode(dns_sdlznode_t *node) {
451 dns_rdatalist_t *list;
459 mctx = sdlz->common.mctx;
461 while (!ISC_LIST_EMPTY(node->lists)) {
462 list = ISC_LIST_HEAD(node->lists);
463 while (!ISC_LIST_EMPTY(list->rdata)) {
464 rdata = ISC_LIST_HEAD(list->rdata);
465 ISC_LIST_UNLINK(list->rdata, rdata, link);
466 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
468 ISC_LIST_UNLINK(node->lists, list, link);
469 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
472 while (!ISC_LIST_EMPTY(node->buffers)) {
473 b = ISC_LIST_HEAD(node->buffers);
474 ISC_LIST_UNLINK(node->buffers, b, link);
478 if (node->name != NULL) {
479 dns_name_free(node->name, mctx);
480 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
482 DESTROYLOCK(&node->lock);
484 isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
490 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
491 dns_dbnode_t **nodep)
493 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
494 dns_sdlznode_t *node = NULL;
497 char namestr[DNS_NAME_MAXTEXT + 1];
499 char zonestr[DNS_NAME_MAXTEXT + 1];
500 isc_boolean_t isorigin;
501 dns_sdlzauthorityfunc_t authority;
503 REQUIRE(VALID_SDLZDB(sdlz));
504 REQUIRE(create == ISC_FALSE);
505 REQUIRE(nodep != NULL && *nodep == NULL);
510 isc_buffer_init(&b, namestr, sizeof(namestr));
511 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
515 labels = dns_name_countlabels(name) -
516 dns_name_countlabels(&db->origin);
517 dns_name_init(&relname, NULL);
518 dns_name_getlabelsequence(name, 0, labels, &relname);
519 result = dns_name_totext(&relname, ISC_TRUE, &b);
520 if (result != ISC_R_SUCCESS)
523 result = dns_name_totext(name, ISC_TRUE, &b);
524 if (result != ISC_R_SUCCESS)
527 isc_buffer_putuint8(&b, 0);
529 isc_buffer_init(&b2, zonestr, sizeof(zonestr));
530 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2);
531 if (result != ISC_R_SUCCESS)
533 isc_buffer_putuint8(&b2, 0);
535 result = createnode(sdlz, &node);
536 if (result != ISC_R_SUCCESS)
539 isorigin = dns_name_equal(name, &sdlz->common.origin);
541 /* make sure strings are always lowercase */
542 dns_sdlz_tolower(zonestr);
543 dns_sdlz_tolower(namestr);
545 MAYBE_LOCK(sdlz->dlzimp);
547 /* try to lookup the host (namestr) */
548 result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
549 sdlz->dlzimp->driverarg,
553 * if the host (namestr) was not found, try to lookup a
556 if (result != ISC_R_SUCCESS) {
557 result = sdlz->dlzimp->methods->lookup(zonestr, "*",
558 sdlz->dlzimp->driverarg,
562 MAYBE_UNLOCK(sdlz->dlzimp);
564 if (result != ISC_R_SUCCESS && !isorigin) {
569 if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
570 MAYBE_LOCK(sdlz->dlzimp);
571 authority = sdlz->dlzimp->methods->authority;
572 result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
574 MAYBE_UNLOCK(sdlz->dlzimp);
575 if (result != ISC_R_SUCCESS &&
576 result != ISC_R_NOTIMPLEMENTED) {
583 return (ISC_R_SUCCESS);
587 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
588 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
589 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
600 return (ISC_R_NOTIMPLEMENTED);
604 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
605 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
606 dns_sdlznode_t *node = (dns_sdlznode_t *)source;
608 REQUIRE(VALID_SDLZDB(sdlz));
613 INSIST(node->references > 0);
615 INSIST(node->references != 0); /* Catch overflow. */
622 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
623 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
624 dns_sdlznode_t *node;
625 isc_boolean_t need_destroy = ISC_FALSE;
627 REQUIRE(VALID_SDLZDB(sdlz));
628 REQUIRE(targetp != NULL && *targetp != NULL);
632 node = (dns_sdlznode_t *)(*targetp);
635 INSIST(node->references > 0);
637 if (node->references == 0)
638 need_destroy = ISC_TRUE;
648 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
653 return (ISC_R_UNEXPECTED);
657 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
665 createiterator(dns_db_t *db, isc_boolean_t relative_names,
666 dns_dbiterator_t **iteratorp)
668 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
669 sdlz_dbiterator_t *sdlziter;
672 char zonestr[DNS_NAME_MAXTEXT + 1];
674 REQUIRE(VALID_SDLZDB(sdlz));
676 if (sdlz->dlzimp->methods->allnodes == NULL)
677 return (ISC_R_NOTIMPLEMENTED);
679 isc_buffer_init(&b, zonestr, sizeof(zonestr));
680 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
681 if (result != ISC_R_SUCCESS)
683 isc_buffer_putuint8(&b, 0);
685 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
686 if (sdlziter == NULL)
687 return (ISC_R_NOMEMORY);
689 sdlziter->common.methods = &dbiterator_methods;
690 sdlziter->common.db = NULL;
691 dns_db_attach(db, &sdlziter->common.db);
692 sdlziter->common.relative_names = relative_names;
693 sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
694 ISC_LIST_INIT(sdlziter->nodelist);
695 sdlziter->current = NULL;
696 sdlziter->origin = NULL;
698 /* make sure strings are always lowercase */
699 dns_sdlz_tolower(zonestr);
701 MAYBE_LOCK(sdlz->dlzimp);
702 result = sdlz->dlzimp->methods->allnodes(zonestr,
703 sdlz->dlzimp->driverarg,
704 sdlz->dbdata, sdlziter);
705 MAYBE_UNLOCK(sdlz->dlzimp);
706 if (result != ISC_R_SUCCESS) {
707 dns_dbiterator_t *iter = &sdlziter->common;
708 dbiterator_destroy(&iter);
712 if (sdlziter->origin != NULL) {
713 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
714 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
717 *iteratorp = (dns_dbiterator_t *)sdlziter;
719 return (ISC_R_SUCCESS);
723 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
724 dns_rdatatype_t type, dns_rdatatype_t covers,
725 isc_stdtime_t now, dns_rdataset_t *rdataset,
726 dns_rdataset_t *sigrdataset)
728 dns_rdatalist_t *list;
729 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
731 REQUIRE(VALID_SDLZNODE(node));
739 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
740 return (ISC_R_NOTIMPLEMENTED);
742 list = ISC_LIST_HEAD(sdlznode->lists);
743 while (list != NULL) {
744 if (list->type == type)
746 list = ISC_LIST_NEXT(list, link);
749 return (ISC_R_NOTFOUND);
751 list_tordataset(list, db, node, rdataset);
753 return (ISC_R_SUCCESS);
757 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
758 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
759 dns_dbnode_t **nodep, dns_name_t *foundname,
760 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
762 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
763 dns_dbnode_t *node = NULL;
764 dns_fixedname_t fname;
765 dns_rdataset_t xrdataset;
767 unsigned int nlabels, olabels;
771 REQUIRE(VALID_SDLZDB(sdlz));
772 REQUIRE(nodep == NULL || *nodep == NULL);
773 REQUIRE(version == NULL || version == (void *) &dummy);
778 if (!dns_name_issubdomain(name, &db->origin))
779 return (DNS_R_NXDOMAIN);
781 olabels = dns_name_countlabels(&db->origin);
782 nlabels = dns_name_countlabels(name);
784 dns_fixedname_init(&fname);
785 xname = dns_fixedname_name(&fname);
787 if (rdataset == NULL) {
788 dns_rdataset_init(&xrdataset);
789 rdataset = &xrdataset;
792 result = DNS_R_NXDOMAIN;
794 for (i = olabels; i <= nlabels; i++) {
796 * Unless this is an explicit lookup at the origin, don't
797 * look at the origin.
799 if (i == olabels && i != nlabels)
803 * Look up the next label.
805 dns_name_getlabelsequence(name, nlabels - i, i, xname);
806 result = findnode(db, xname, ISC_FALSE, &node);
807 if (result != ISC_R_SUCCESS) {
808 result = DNS_R_NXDOMAIN;
813 * Look for a DNAME at the current label, unless this is
817 result = findrdataset(db, node, version,
819 0, now, rdataset, sigrdataset);
820 if (result == ISC_R_SUCCESS) {
821 result = DNS_R_DNAME;
827 * Look for an NS at the current label, unless this is the
828 * origin or glue is ok.
830 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
831 result = findrdataset(db, node, version,
833 0, now, rdataset, sigrdataset);
834 if (result == ISC_R_SUCCESS) {
835 if (i == nlabels && type == dns_rdatatype_any)
837 result = DNS_R_ZONECUT;
838 dns_rdataset_disassociate(rdataset);
839 if (sigrdataset != NULL)
840 dns_rdataset_disassociate
843 result = DNS_R_DELEGATION;
849 * If the current name is not the qname, add another label
859 * If we're looking for ANY, we're done.
861 if (type == dns_rdatatype_any) {
862 result = ISC_R_SUCCESS;
867 * Look for the qtype.
869 result = findrdataset(db, node, version, type,
870 0, now, rdataset, sigrdataset);
871 if (result == ISC_R_SUCCESS)
877 if (type != dns_rdatatype_cname) {
878 result = findrdataset(db, node, version,
880 0, now, rdataset, sigrdataset);
881 if (result == ISC_R_SUCCESS) {
882 result = DNS_R_CNAME;
887 result = DNS_R_NXRRSET;
891 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
892 dns_rdataset_disassociate(rdataset);
894 if (foundname != NULL) {
895 isc_result_t xresult;
897 xresult = dns_name_copy(xname, foundname, NULL);
898 if (xresult != ISC_R_SUCCESS) {
901 if (dns_rdataset_isassociated(rdataset))
902 dns_rdataset_disassociate(rdataset);
903 return (DNS_R_BADDB);
909 else if (node != NULL)
910 detachnode(db, &node);
916 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
917 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
919 sdlz_rdatasetiter_t *iterator;
921 REQUIRE(version == NULL || version == &dummy);
926 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
927 if (iterator == NULL)
928 return (ISC_R_NOMEMORY);
930 iterator->common.magic = DNS_RDATASETITER_MAGIC;
931 iterator->common.methods = &rdatasetiter_methods;
932 iterator->common.db = db;
933 iterator->common.node = NULL;
934 attachnode(db, node, &iterator->common.node);
935 iterator->common.version = version;
936 iterator->common.now = now;
938 *iteratorp = (dns_rdatasetiter_t *)iterator;
940 return (ISC_R_SUCCESS);
944 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
945 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
946 dns_rdataset_t *addedrdataset)
954 UNUSED(addedrdataset);
956 return (ISC_R_NOTIMPLEMENTED);
960 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
961 dns_rdataset_t *rdataset, unsigned int options,
962 dns_rdataset_t *newrdataset)
971 return (ISC_R_NOTIMPLEMENTED);
975 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
976 dns_rdatatype_t type, dns_rdatatype_t covers)
984 return (ISC_R_NOTIMPLEMENTED);
988 issecure(dns_db_t *db) {
995 nodecount(dns_db_t *db) {
1001 static isc_boolean_t
1002 ispersistent(dns_db_t *db) {
1008 overmem(dns_db_t *db, isc_boolean_t overmem) {
1014 settask(dns_db_t *db, isc_task_t *task) {
1020 static dns_dbmethods_t sdlzdb_methods = {
1052 * Database Iterator Methods. These methods were "borrowed" from the SDB
1053 * driver interface. See the SDB driver interface documentation for more info.
1057 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1058 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1059 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1061 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1062 dns_sdlznode_t *node;
1063 node = ISC_LIST_HEAD(sdlziter->nodelist);
1064 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1068 dns_db_detach(&sdlziter->common.db);
1069 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1075 dbiterator_first(dns_dbiterator_t *iterator) {
1076 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1078 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1079 if (sdlziter->current == NULL)
1080 return (ISC_R_NOMORE);
1082 return (ISC_R_SUCCESS);
1086 dbiterator_last(dns_dbiterator_t *iterator) {
1087 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1089 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1090 if (sdlziter->current == NULL)
1091 return (ISC_R_NOMORE);
1093 return (ISC_R_SUCCESS);
1097 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1098 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1100 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1101 while (sdlziter->current != NULL)
1102 if (dns_name_equal(sdlziter->current->name, name))
1103 return (ISC_R_SUCCESS);
1104 return (ISC_R_NOTFOUND);
1108 dbiterator_prev(dns_dbiterator_t *iterator) {
1109 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1111 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1112 if (sdlziter->current == NULL)
1113 return (ISC_R_NOMORE);
1115 return (ISC_R_SUCCESS);
1119 dbiterator_next(dns_dbiterator_t *iterator) {
1120 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1122 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1123 if (sdlziter->current == NULL)
1124 return (ISC_R_NOMORE);
1126 return (ISC_R_SUCCESS);
1130 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1133 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1135 attachnode(iterator->db, sdlziter->current, nodep);
1137 return (dns_name_copy(sdlziter->current->name, name, NULL));
1138 return (ISC_R_SUCCESS);
1142 dbiterator_pause(dns_dbiterator_t *iterator) {
1144 return (ISC_R_SUCCESS);
1148 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1150 return (dns_name_copy(dns_rootname, name, NULL));
1154 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1155 * interface. See the SDB driver interface documentation for more info.
1159 disassociate(dns_rdataset_t *rdataset) {
1160 dns_dbnode_t *node = rdataset->private5;
1161 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1162 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1164 detachnode(db, &node);
1165 isc__rdatalist_disassociate(rdataset);
1169 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1170 dns_dbnode_t *node = source->private5;
1171 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1172 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1173 dns_dbnode_t *tempdb = NULL;
1175 isc__rdatalist_clone(source, target);
1176 attachnode(db, node, &tempdb);
1177 source->private5 = tempdb;
1180 static dns_rdatasetmethods_t rdataset_methods = {
1182 isc__rdatalist_first,
1183 isc__rdatalist_next,
1184 isc__rdatalist_current,
1186 isc__rdatalist_count,
1187 isc__rdatalist_addnoqname,
1188 isc__rdatalist_getnoqname,
1195 list_tordataset(dns_rdatalist_t *rdatalist,
1196 dns_db_t *db, dns_dbnode_t *node,
1197 dns_rdataset_t *rdataset)
1200 * The sdlz rdataset is an rdatalist with some additions.
1201 * - private1 & private2 are used by the rdatalist.
1202 * - private3 & private 4 are unused.
1203 * - private5 is the node.
1206 /* This should never fail. */
1207 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1210 rdataset->methods = &rdataset_methods;
1211 dns_db_attachnode(db, node, &rdataset->private5);
1215 * SDLZ core methods. This is the core of the new DLZ functionality.
1219 * Build a 'bind' database driver structure to be returned by
1220 * either the find zone or the allow zone transfer method.
1221 * This method is only available in this source file, it is
1222 * not made available anywhere else.
1226 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1227 dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
1229 isc_result_t result;
1230 dns_sdlz_db_t *sdlzdb;
1231 dns_sdlzimplementation_t *imp;
1233 /* check that things are as we expect */
1234 REQUIRE(dbp != NULL && *dbp == NULL);
1235 REQUIRE(name != NULL);
1237 imp = (dns_sdlzimplementation_t *) driverarg;
1239 /* allocate and zero memory for driver structure */
1240 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1242 return (ISC_R_NOMEMORY);
1243 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1245 /* initialize and set origin */
1246 dns_name_init(&sdlzdb->common.origin, NULL);
1247 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1248 if (result != ISC_R_SUCCESS)
1251 /* initialize the reference count mutex */
1252 result = isc_mutex_init(&sdlzdb->refcnt_lock);
1253 if (result != ISC_R_SUCCESS)
1256 /* set the rest of the database structure attributes */
1257 sdlzdb->dlzimp = imp;
1258 sdlzdb->common.methods = &sdlzdb_methods;
1259 sdlzdb->common.attributes = 0;
1260 sdlzdb->common.rdclass = rdclass;
1261 sdlzdb->common.mctx = NULL;
1262 sdlzdb->dbdata = dbdata;
1263 sdlzdb->references = 1;
1265 /* attach to the memory context */
1266 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1268 /* mark structure as valid */
1269 sdlzdb->common.magic = DNS_DB_MAGIC;
1270 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1271 *dbp = (dns_db_t *) sdlzdb;
1276 * reference count mutex could not be initialized, clean up
1280 dns_name_free(&sdlzdb->common.origin, mctx);
1282 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1287 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1288 dns_rdataclass_t rdclass, dns_name_t *name,
1289 isc_sockaddr_t *clientaddr, dns_db_t **dbp)
1293 char namestr[DNS_NAME_MAXTEXT + 1];
1294 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1296 isc_netaddr_t netaddr;
1297 isc_result_t result;
1298 dns_sdlzimplementation_t *imp;
1301 * Perform checks to make sure data is as we expect it to be.
1303 REQUIRE(driverarg != NULL);
1304 REQUIRE(name != NULL);
1305 REQUIRE(clientaddr != NULL);
1306 REQUIRE(dbp != NULL && *dbp == NULL);
1308 imp = (dns_sdlzimplementation_t *) driverarg;
1310 /* Convert DNS name to ascii text */
1311 isc_buffer_init(&b, namestr, sizeof(namestr));
1312 result = dns_name_totext(name, ISC_TRUE, &b);
1313 if (result != ISC_R_SUCCESS)
1315 isc_buffer_putuint8(&b, 0);
1317 /* convert client address to ascii text */
1318 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1319 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1320 result = isc_netaddr_totext(&netaddr, &b2);
1321 if (result != ISC_R_SUCCESS)
1323 isc_buffer_putuint8(&b2, 0);
1325 /* make sure strings are always lowercase */
1326 dns_sdlz_tolower(namestr);
1327 dns_sdlz_tolower(clientstr);
1329 /* Call SDLZ driver's find zone method */
1330 if (imp->methods->allowzonexfr != NULL) {
1332 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1333 namestr, clientstr);
1336 * if zone is supported and transfers allowed build a 'bind'
1339 if (result == ISC_R_SUCCESS)
1340 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1341 name, rdclass, dbp);
1345 return (ISC_R_NOTIMPLEMENTED);
1349 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1350 char *argv[], void *driverarg, void **dbdata)
1352 dns_sdlzimplementation_t *imp;
1353 isc_result_t result = ISC_R_NOTFOUND;
1355 /* Write debugging message to log */
1356 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1357 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1358 "Loading SDLZ driver.");
1361 * Performs checks to make sure data is as we expect it to be.
1363 REQUIRE(driverarg != NULL);
1364 REQUIRE(dlzname != NULL);
1365 REQUIRE(dbdata != NULL);
1370 /* If the create method exists, call it. */
1371 if (imp->methods->create != NULL) {
1373 result = imp->methods->create(dlzname, argc, argv,
1374 imp->driverarg, dbdata);
1378 /* Write debugging message to log */
1379 if (result == ISC_R_SUCCESS) {
1380 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1381 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1382 "SDLZ driver loaded successfully.");
1384 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1385 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1386 "SDLZ driver failed to load.");
1393 dns_sdlzdestroy(void *driverdata, void **dbdata)
1396 dns_sdlzimplementation_t *imp;
1398 /* Write debugging message to log */
1399 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1400 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1401 "Unloading SDLZ driver.");
1405 /* If the destroy method exists, call it. */
1406 if (imp->methods->destroy != NULL) {
1408 imp->methods->destroy(imp->driverarg, dbdata);
1414 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1415 dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
1418 char namestr[DNS_NAME_MAXTEXT + 1];
1419 isc_result_t result;
1420 dns_sdlzimplementation_t *imp;
1423 * Perform checks to make sure data is as we expect it to be.
1425 REQUIRE(driverarg != NULL);
1426 REQUIRE(name != NULL);
1427 REQUIRE(dbp != NULL && *dbp == NULL);
1429 imp = (dns_sdlzimplementation_t *) driverarg;
1431 /* Convert DNS name to ascii text */
1432 isc_buffer_init(&b, namestr, sizeof(namestr));
1433 result = dns_name_totext(name, ISC_TRUE, &b);
1434 if (result != ISC_R_SUCCESS)
1436 isc_buffer_putuint8(&b, 0);
1438 /* make sure strings are always lowercase */
1439 dns_sdlz_tolower(namestr);
1441 /* Call SDLZ driver's find zone method */
1443 result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
1447 * if zone is supported build a 'bind' database driver
1448 * structure to return
1450 if (result == ISC_R_SUCCESS)
1451 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1457 static dns_dlzmethods_t sdlzmethods = {
1461 dns_sdlzallowzonexfr
1469 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1472 dns_rdatalist_t *rdatalist;
1474 dns_rdatatype_t typeval;
1475 isc_consttextregion_t r;
1477 isc_buffer_t *rdatabuf = NULL;
1479 isc_result_t result;
1484 REQUIRE(VALID_SDLZLOOKUP(lookup));
1485 REQUIRE(type != NULL);
1486 REQUIRE(data != NULL);
1488 mctx = lookup->sdlz->common.mctx;
1491 r.length = strlen(type);
1492 result = dns_rdatatype_fromtext(&typeval, (void *) &r);
1493 if (result != ISC_R_SUCCESS)
1496 rdatalist = ISC_LIST_HEAD(lookup->lists);
1497 while (rdatalist != NULL) {
1498 if (rdatalist->type == typeval)
1500 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1503 if (rdatalist == NULL) {
1504 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1505 if (rdatalist == NULL)
1506 return (ISC_R_NOMEMORY);
1507 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1508 rdatalist->type = typeval;
1509 rdatalist->covers = 0;
1510 rdatalist->ttl = ttl;
1511 ISC_LIST_INIT(rdatalist->rdata);
1512 ISC_LINK_INIT(rdatalist, link);
1513 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1515 if (rdatalist->ttl != ttl)
1516 return (DNS_R_BADTTL);
1518 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1520 return (ISC_R_NOMEMORY);
1521 dns_rdata_init(rdata);
1523 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1524 origin = &lookup->sdlz->common.origin;
1526 origin = dns_rootname;
1529 result = isc_lex_create(mctx, 64, &lex);
1530 if (result != ISC_R_SUCCESS)
1533 size = initial_size(data);
1535 isc_buffer_init(&b, data, strlen(data));
1536 isc_buffer_add(&b, strlen(data));
1538 result = isc_lex_openbuffer(lex, &b);
1539 if (result != ISC_R_SUCCESS)
1543 result = isc_buffer_allocate(mctx, &rdatabuf, size);
1544 if (result != ISC_R_SUCCESS)
1547 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1548 rdatalist->type, lex,
1551 &lookup->callbacks);
1552 if (result != ISC_R_SUCCESS)
1553 isc_buffer_free(&rdatabuf);
1555 } while (result == ISC_R_NOSPACE);
1557 if (result != ISC_R_SUCCESS)
1560 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1561 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1564 isc_lex_destroy(&lex);
1566 return (ISC_R_SUCCESS);
1569 if (rdatabuf != NULL)
1570 isc_buffer_free(&rdatabuf);
1572 isc_lex_destroy(&lex);
1573 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1579 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1580 const char *type, dns_ttl_t ttl, const char *data)
1582 dns_name_t *newname, *origin;
1583 dns_fixedname_t fnewname;
1584 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1585 dns_sdlznode_t *sdlznode;
1586 isc_mem_t *mctx = sdlz->common.mctx;
1588 isc_result_t result;
1590 dns_fixedname_init(&fnewname);
1591 newname = dns_fixedname_name(&fnewname);
1593 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1594 origin = &sdlz->common.origin;
1596 origin = dns_rootname;
1597 isc_buffer_init(&b, name, strlen(name));
1598 isc_buffer_add(&b, strlen(name));
1600 result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
1601 if (result != ISC_R_SUCCESS)
1604 if (allnodes->common.relative_names) {
1605 /* All names are relative to the root */
1606 unsigned int nlabels = dns_name_countlabels(newname);
1607 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1610 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1611 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1613 result = createnode(sdlz, &sdlznode);
1614 if (result != ISC_R_SUCCESS)
1616 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1617 if (sdlznode->name == NULL) {
1618 destroynode(sdlznode);
1619 return (ISC_R_NOMEMORY);
1621 dns_name_init(sdlznode->name, NULL);
1622 result = dns_name_dup(newname, mctx, sdlznode->name);
1623 if (result != ISC_R_SUCCESS) {
1624 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
1625 destroynode(sdlznode);
1628 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1629 if (allnodes->origin == NULL &&
1630 dns_name_equal(newname, &sdlz->common.origin))
1631 allnodes->origin = sdlznode;
1633 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1638 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1639 isc_uint32_t serial)
1641 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1644 REQUIRE(mname != NULL);
1645 REQUIRE(rname != NULL);
1647 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
1648 mname, rname, serial,
1649 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1650 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1651 if (n >= (int)sizeof(str) || n < 0)
1652 return (ISC_R_NOSPACE);
1653 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1657 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1658 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1659 dns_sdlzimplementation_t **sdlzimp)
1662 dns_sdlzimplementation_t *imp;
1663 isc_result_t result;
1666 * Performs checks to make sure data is as we expect it to be.
1668 REQUIRE(drivername != NULL);
1669 REQUIRE(methods != NULL);
1670 REQUIRE(methods->findzone != NULL);
1671 REQUIRE(methods->lookup != NULL);
1672 REQUIRE(mctx != NULL);
1673 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
1674 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
1675 DNS_SDLZFLAG_RELATIVERDATA |
1676 DNS_SDLZFLAG_THREADSAFE)) == 0);
1678 /* Write debugging message to log */
1679 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1680 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1681 "Registering SDLZ driver '%s'", drivername);
1684 * Allocate memory for a sdlz_implementation object. Error if
1687 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
1689 return (ISC_R_NOMEMORY);
1691 /* Make sure memory region is set to all 0's */
1692 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
1694 /* Store the data passed into this method */
1695 imp->methods = methods;
1696 imp->driverarg = driverarg;
1700 /* attach the new sdlz_implementation object to a memory context */
1701 isc_mem_attach(mctx, &imp->mctx);
1704 * initialize the driver lock, error if we cannot
1705 * (used if a driver does not support multiple threads)
1707 result = isc_mutex_init(&imp->driverlock);
1708 if (result != ISC_R_SUCCESS) {
1709 UNEXPECTED_ERROR(__FILE__, __LINE__,
1710 "isc_mutex_init() failed: %s",
1711 isc_result_totext(result));
1715 imp->dlz_imp = NULL;
1718 * register the DLZ driver. Pass in our "extra" sdlz information as
1719 * a driverarg. (that's why we stored the passed in driver arg in our
1720 * sdlz_implementation structure) Also, store the dlz_implementation
1721 * structure in our sdlz_implementation.
1723 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
1726 /* if registration fails, cleanup and get outta here. */
1727 if (result != ISC_R_SUCCESS)
1732 return (ISC_R_SUCCESS);
1735 /* destroy the driver lock, we don't need it anymore */
1736 DESTROYLOCK(&imp->driverlock);
1740 * return the memory back to the available memory pool and
1741 * remove it from the memory context.
1743 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1744 isc_mem_detach(&mctx);
1749 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
1750 dns_sdlzimplementation_t *imp;
1753 /* Write debugging message to log */
1754 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1755 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1756 "Unregistering SDLZ driver.");
1759 * Performs checks to make sure data is as we expect it to be.
1761 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
1765 /* Unregister the DLZ driver implementation */
1766 dns_dlzunregister(&imp->dlz_imp);
1768 /* destroy the driver lock, we don't need it anymore */
1769 DESTROYLOCK(&imp->driverlock);
1774 * return the memory back to the available memory pool and
1775 * remove it from the memory context.
1777 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1778 isc_mem_detach(&mctx);