1 /* $NetBSD: sdlz.c,v 1.9 2015/07/08 17:28:59 christos Exp $ */
4 * Portions Copyright (C) 2005-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2001 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
21 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
23 * Permission to use, copy, modify, and distribute this software for any
24 * purpose with or without fee is hereby granted, provided that the
25 * above copyright notice and this permission notice appear in all
28 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
29 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
31 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
32 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
33 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
34 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
35 * USE OR PERFORMANCE OF THIS SOFTWARE.
37 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
38 * conceived and contributed by Rob Butler.
40 * Permission to use, copy, modify, and distribute this software for any
41 * purpose with or without fee is hereby granted, provided that the
42 * above copyright notice and this permission notice appear in all
45 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
46 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
48 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
49 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
50 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
51 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
52 * USE OR PERFORMANCE OF THIS SOFTWARE.
62 #include <isc/buffer.h>
65 #include <isc/rwlock.h>
66 #include <isc/string.h>
68 #include <isc/magic.h>
71 #include <isc/print.h>
72 #include <isc/region.h>
74 #include <dns/callbacks.h>
76 #include <dns/dbiterator.h>
78 #include <dns/fixedname.h>
80 #include <dns/rdata.h>
81 #include <dns/rdatalist.h>
82 #include <dns/rdataset.h>
83 #include <dns/rdatasetiter.h>
84 #include <dns/rdatatype.h>
85 #include <dns/result.h>
86 #include <dns/master.h>
88 #include <dns/types.h>
90 #include "rdatalist_p.h"
96 struct dns_sdlzimplementation
{
97 const dns_sdlzmethods_t
*methods
;
101 isc_mutex_t driverlock
;
102 dns_dlzimplementation_t
*dlz_imp
;
109 dns_sdlzimplementation_t
*dlzimp
;
110 isc_mutex_t refcnt_lock
;
112 unsigned int references
;
113 dns_dbversion_t
*future_version
;
117 struct dns_sdlzlookup
{
121 ISC_LIST(dns_rdatalist_t
) lists
;
122 ISC_LIST(isc_buffer_t
) buffers
;
124 ISC_LINK(dns_sdlzlookup_t
) link
;
126 dns_rdatacallbacks_t callbacks
;
128 unsigned int references
;
131 typedef struct dns_sdlzlookup dns_sdlznode_t
;
133 struct dns_sdlzallnodes
{
134 dns_dbiterator_t common
;
135 ISC_LIST(dns_sdlznode_t
) nodelist
;
136 dns_sdlznode_t
*current
;
137 dns_sdlznode_t
*origin
;
140 typedef dns_sdlzallnodes_t sdlz_dbiterator_t
;
142 typedef struct sdlz_rdatasetiter
{
143 dns_rdatasetiter_t common
;
144 dns_rdatalist_t
*current
;
145 } sdlz_rdatasetiter_t
;
148 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
151 * Note that "impmagic" is not the first four bytes of the struct, so
152 * ISC_MAGIC_VALID cannot be used.
155 #define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \
156 (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
158 #define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L')
159 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
160 #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)
162 /* These values are taken from RFC 1537 */
163 #define SDLZ_DEFAULT_REFRESH (60 * 60 * 8)
164 #define SDLZ_DEFAULT_RETRY (60 * 60 * 2)
165 #define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
166 #define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24)
168 /* This is a reasonable value */
169 #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
172 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
173 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
175 #define MAYBE_LOCK(imp) \
177 unsigned int flags = imp->flags; \
178 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
179 LOCK(&imp->driverlock); \
180 } while (/*CONSTCOND*/0)
182 #define MAYBE_UNLOCK(imp) \
184 unsigned int flags = imp->flags; \
185 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
186 UNLOCK(&imp->driverlock); \
187 } while (/*CONSTCOND*/0)
191 * Forward references. Try to keep these to a minimum.
194 static void list_tordataset(dns_rdatalist_t
*rdatalist
,
195 dns_db_t
*db
, dns_dbnode_t
*node
,
196 dns_rdataset_t
*rdataset
);
198 static void detachnode(dns_db_t
*db
, dns_dbnode_t
**targetp
);
200 static void dbiterator_destroy(dns_dbiterator_t
**iteratorp
);
201 static isc_result_t
dbiterator_first(dns_dbiterator_t
*iterator
);
202 static isc_result_t
dbiterator_last(dns_dbiterator_t
*iterator
);
203 static isc_result_t
dbiterator_seek(dns_dbiterator_t
*iterator
,
205 static isc_result_t
dbiterator_prev(dns_dbiterator_t
*iterator
);
206 static isc_result_t
dbiterator_next(dns_dbiterator_t
*iterator
);
207 static isc_result_t
dbiterator_current(dns_dbiterator_t
*iterator
,
208 dns_dbnode_t
**nodep
,
210 static isc_result_t
dbiterator_pause(dns_dbiterator_t
*iterator
);
211 static isc_result_t
dbiterator_origin(dns_dbiterator_t
*iterator
,
214 static dns_dbiteratormethods_t dbiterator_methods
= {
231 * Log a message at the given level
234 sdlz_log(int level
, const char *fmt
, ...) {
237 isc_log_vwrite(dns_lctx
, DNS_LOGCATEGORY_DATABASE
,
238 DNS_LOGMODULE_DLZ
, ISC_LOG_DEBUG(level
),
243 /*% Converts the input string to lowercase, in place. */
245 dns_sdlz_tolower(char *str
) {
246 unsigned int len
= strlen(str
);
249 for (i
= 0; i
< len
; i
++) {
250 if (str
[i
] >= 'A' && str
[i
] <= 'Z')
255 static inline unsigned int
256 initial_size(const char *data
) {
257 unsigned int len
= (strlen(data
) / 64) + 1;
258 return (len
* 64 + 64);
262 * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
263 * driver interface. See the SDB driver interface documentation for more info.
267 rdatasetiter_destroy(dns_rdatasetiter_t
**iteratorp
) {
268 sdlz_rdatasetiter_t
*sdlziterator
=
269 (sdlz_rdatasetiter_t
*)(*iteratorp
);
271 detachnode(sdlziterator
->common
.db
, &sdlziterator
->common
.node
);
272 isc_mem_put(sdlziterator
->common
.db
->mctx
, sdlziterator
,
273 sizeof(sdlz_rdatasetiter_t
));
278 rdatasetiter_first(dns_rdatasetiter_t
*iterator
) {
279 sdlz_rdatasetiter_t
*sdlziterator
= (sdlz_rdatasetiter_t
*)iterator
;
280 dns_sdlznode_t
*sdlznode
= (dns_sdlznode_t
*)iterator
->node
;
282 if (ISC_LIST_EMPTY(sdlznode
->lists
))
283 return (ISC_R_NOMORE
);
284 sdlziterator
->current
= ISC_LIST_HEAD(sdlznode
->lists
);
285 return (ISC_R_SUCCESS
);
289 rdatasetiter_next(dns_rdatasetiter_t
*iterator
) {
290 sdlz_rdatasetiter_t
*sdlziterator
= (sdlz_rdatasetiter_t
*)iterator
;
292 sdlziterator
->current
= ISC_LIST_NEXT(sdlziterator
->current
, link
);
293 if (sdlziterator
->current
== NULL
)
294 return (ISC_R_NOMORE
);
296 return (ISC_R_SUCCESS
);
300 rdatasetiter_current(dns_rdatasetiter_t
*iterator
, dns_rdataset_t
*rdataset
) {
301 sdlz_rdatasetiter_t
*sdlziterator
= (sdlz_rdatasetiter_t
*)iterator
;
303 list_tordataset(sdlziterator
->current
, iterator
->db
, iterator
->node
,
307 static dns_rdatasetitermethods_t rdatasetiter_methods
= {
308 rdatasetiter_destroy
,
315 * DB routines. These methods were "borrowed" from the SDB driver interface.
316 * See the SDB driver interface documentation for more info.
320 attach(dns_db_t
*source
, dns_db_t
**targetp
) {
321 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*) source
;
323 REQUIRE(VALID_SDLZDB(sdlz
));
325 LOCK(&sdlz
->refcnt_lock
);
326 REQUIRE(sdlz
->references
> 0);
328 UNLOCK(&sdlz
->refcnt_lock
);
334 destroy(dns_sdlz_db_t
*sdlz
) {
336 mctx
= sdlz
->common
.mctx
;
338 sdlz
->common
.magic
= 0;
339 sdlz
->common
.impmagic
= 0;
341 (void)isc_mutex_destroy(&sdlz
->refcnt_lock
);
343 dns_name_free(&sdlz
->common
.origin
, mctx
);
345 isc_mem_put(mctx
, sdlz
, sizeof(dns_sdlz_db_t
));
346 isc_mem_detach(&mctx
);
350 detach(dns_db_t
**dbp
) {
351 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)(*dbp
);
352 isc_boolean_t need_destroy
= ISC_FALSE
;
354 REQUIRE(VALID_SDLZDB(sdlz
));
355 LOCK(&sdlz
->refcnt_lock
);
356 REQUIRE(sdlz
->references
> 0);
358 if (sdlz
->references
== 0)
359 need_destroy
= ISC_TRUE
;
360 UNLOCK(&sdlz
->refcnt_lock
);
369 beginload(dns_db_t
*db
, dns_rdatacallbacks_t
*callbacks
) {
372 return (ISC_R_NOTIMPLEMENTED
);
376 endload(dns_db_t
*db
, dns_rdatacallbacks_t
*callbacks
) {
379 return (ISC_R_NOTIMPLEMENTED
);
383 dump(dns_db_t
*db
, dns_dbversion_t
*version
, const char *filename
,
384 dns_masterformat_t masterformat
)
389 UNUSED(masterformat
);
390 return (ISC_R_NOTIMPLEMENTED
);
394 currentversion(dns_db_t
*db
, dns_dbversion_t
**versionp
) {
395 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
396 REQUIRE(VALID_SDLZDB(sdlz
));
397 REQUIRE(versionp
!= NULL
&& *versionp
== NULL
);
399 *versionp
= (void *) &sdlz
->dummy_version
;
404 newversion(dns_db_t
*db
, dns_dbversion_t
**versionp
) {
405 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
406 char origin
[DNS_NAME_MAXTEXT
+ 1];
409 REQUIRE(VALID_SDLZDB(sdlz
));
411 if (sdlz
->dlzimp
->methods
->newversion
== NULL
)
412 return (ISC_R_NOTIMPLEMENTED
);
414 dns_name_format(&sdlz
->common
.origin
, origin
, sizeof(origin
));
416 result
= sdlz
->dlzimp
->methods
->newversion(origin
,
417 sdlz
->dlzimp
->driverarg
,
418 sdlz
->dbdata
, versionp
);
419 if (result
!= ISC_R_SUCCESS
) {
420 sdlz_log(ISC_LOG_ERROR
,
421 "sdlz newversion on origin %s failed : %s",
422 origin
, isc_result_totext(result
));
426 sdlz
->future_version
= *versionp
;
427 return (ISC_R_SUCCESS
);
431 attachversion(dns_db_t
*db
, dns_dbversion_t
*source
,
432 dns_dbversion_t
**targetp
)
434 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
436 REQUIRE(VALID_SDLZDB(sdlz
));
437 REQUIRE(source
!= NULL
&& source
== (void *)&sdlz
->dummy_version
);
443 closeversion(dns_db_t
*db
, dns_dbversion_t
**versionp
, isc_boolean_t commit
) {
444 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
445 char origin
[DNS_NAME_MAXTEXT
+ 1];
447 REQUIRE(VALID_SDLZDB(sdlz
));
448 REQUIRE(versionp
!= NULL
);
450 if (*versionp
== (void *)&sdlz
->dummy_version
) {
455 REQUIRE(*versionp
== sdlz
->future_version
);
456 REQUIRE(sdlz
->dlzimp
->methods
->closeversion
!= NULL
);
458 dns_name_format(&sdlz
->common
.origin
, origin
, sizeof(origin
));
460 sdlz
->dlzimp
->methods
->closeversion(origin
, commit
,
461 sdlz
->dlzimp
->driverarg
,
462 sdlz
->dbdata
, versionp
);
463 if (*versionp
!= NULL
)
464 sdlz_log(ISC_LOG_ERROR
,
465 "sdlz closeversion on origin %s failed", origin
);
467 sdlz
->future_version
= NULL
;
471 createnode(dns_sdlz_db_t
*sdlz
, dns_sdlznode_t
**nodep
) {
472 dns_sdlznode_t
*node
;
476 node
= isc_mem_get(sdlz
->common
.mctx
, sizeof(dns_sdlznode_t
));
478 return (ISC_R_NOMEMORY
);
483 attach(sdlzv
, tdlzv
);
484 ISC_LIST_INIT(node
->lists
);
485 ISC_LIST_INIT(node
->buffers
);
486 ISC_LINK_INIT(node
, link
);
488 result
= isc_mutex_init(&node
->lock
);
489 if (result
!= ISC_R_SUCCESS
) {
490 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
491 "isc_mutex_init() failed: %s",
492 isc_result_totext(result
));
493 isc_mem_put(sdlz
->common
.mctx
, node
, sizeof(dns_sdlznode_t
));
494 return (ISC_R_UNEXPECTED
);
496 dns_rdatacallbacks_init(&node
->callbacks
);
497 node
->references
= 1;
498 node
->magic
= SDLZLOOKUP_MAGIC
;
501 return (ISC_R_SUCCESS
);
505 destroynode(dns_sdlznode_t
*node
) {
506 dns_rdatalist_t
*list
;
514 mctx
= sdlz
->common
.mctx
;
516 while (!ISC_LIST_EMPTY(node
->lists
)) {
517 list
= ISC_LIST_HEAD(node
->lists
);
518 while (!ISC_LIST_EMPTY(list
->rdata
)) {
519 rdata
= ISC_LIST_HEAD(list
->rdata
);
520 ISC_LIST_UNLINK(list
->rdata
, rdata
, link
);
521 isc_mem_put(mctx
, rdata
, sizeof(dns_rdata_t
));
523 ISC_LIST_UNLINK(node
->lists
, list
, link
);
524 isc_mem_put(mctx
, list
, sizeof(dns_rdatalist_t
));
527 while (!ISC_LIST_EMPTY(node
->buffers
)) {
528 b
= ISC_LIST_HEAD(node
->buffers
);
529 ISC_LIST_UNLINK(node
->buffers
, b
, link
);
533 if (node
->name
!= NULL
) {
534 dns_name_free(node
->name
, mctx
);
535 isc_mem_put(mctx
, node
->name
, sizeof(dns_name_t
));
537 DESTROYLOCK(&node
->lock
);
539 isc_mem_put(mctx
, node
, sizeof(dns_sdlznode_t
));
545 findnodeext(dns_db_t
*db
, dns_name_t
*name
, isc_boolean_t create
,
546 dns_clientinfomethods_t
*methods
, dns_clientinfo_t
*clientinfo
,
547 dns_dbnode_t
**nodep
)
549 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
550 dns_sdlznode_t
*node
= NULL
;
553 char namestr
[DNS_NAME_MAXTEXT
+ 1];
555 char zonestr
[DNS_NAME_MAXTEXT
+ 1];
556 isc_boolean_t isorigin
;
557 dns_sdlzauthorityfunc_t authority
;
559 REQUIRE(VALID_SDLZDB(sdlz
));
560 REQUIRE(nodep
!= NULL
&& *nodep
== NULL
);
562 if (sdlz
->dlzimp
->methods
->newversion
== NULL
) {
563 REQUIRE(create
== ISC_FALSE
);
566 isc_buffer_init(&b
, namestr
, sizeof(namestr
));
567 if ((sdlz
->dlzimp
->flags
& DNS_SDLZFLAG_RELATIVEOWNER
) != 0) {
571 labels
= dns_name_countlabels(name
) -
572 dns_name_countlabels(&db
->origin
);
573 dns_name_init(&relname
, NULL
);
574 dns_name_getlabelsequence(name
, 0, labels
, &relname
);
575 result
= dns_name_totext(&relname
, ISC_TRUE
, &b
);
576 if (result
!= ISC_R_SUCCESS
)
579 result
= dns_name_totext(name
, ISC_TRUE
, &b
);
580 if (result
!= ISC_R_SUCCESS
)
583 isc_buffer_putuint8(&b
, 0);
585 isc_buffer_init(&b2
, zonestr
, sizeof(zonestr
));
586 result
= dns_name_totext(&sdlz
->common
.origin
, ISC_TRUE
, &b2
);
587 if (result
!= ISC_R_SUCCESS
)
589 isc_buffer_putuint8(&b2
, 0);
591 result
= createnode(sdlz
, &node
);
592 if (result
!= ISC_R_SUCCESS
)
595 isorigin
= dns_name_equal(name
, &sdlz
->common
.origin
);
597 /* make sure strings are always lowercase */
598 dns_sdlz_tolower(zonestr
);
599 dns_sdlz_tolower(namestr
);
601 MAYBE_LOCK(sdlz
->dlzimp
);
603 /* try to lookup the host (namestr) */
604 result
= sdlz
->dlzimp
->methods
->lookup(zonestr
, namestr
,
605 sdlz
->dlzimp
->driverarg
,
607 methods
, clientinfo
);
610 * if the host (namestr) was not found, try to lookup a
613 if (result
== ISC_R_NOTFOUND
&& !create
)
614 result
= sdlz
->dlzimp
->methods
->lookup(zonestr
, "*",
615 sdlz
->dlzimp
->driverarg
,
617 methods
, clientinfo
);
619 MAYBE_UNLOCK(sdlz
->dlzimp
);
621 if (result
== ISC_R_NOTFOUND
&& (isorigin
|| create
))
622 result
= ISC_R_SUCCESS
;
624 if (result
!= ISC_R_SUCCESS
) {
629 if (isorigin
&& sdlz
->dlzimp
->methods
->authority
!= NULL
) {
630 MAYBE_LOCK(sdlz
->dlzimp
);
631 authority
= sdlz
->dlzimp
->methods
->authority
;
632 result
= (*authority
)(zonestr
, sdlz
->dlzimp
->driverarg
,
634 MAYBE_UNLOCK(sdlz
->dlzimp
);
635 if (result
!= ISC_R_SUCCESS
&&
636 result
!= ISC_R_NOTIMPLEMENTED
)
643 if (node
->name
== NULL
) {
644 node
->name
= isc_mem_get(sdlz
->common
.mctx
,
646 if (node
->name
== NULL
) {
648 return (ISC_R_NOMEMORY
);
650 dns_name_init(node
->name
, NULL
);
651 result
= dns_name_dup(name
, sdlz
->common
.mctx
, node
->name
);
652 if (result
!= ISC_R_SUCCESS
) {
653 isc_mem_put(sdlz
->common
.mctx
, node
->name
,
661 return (ISC_R_SUCCESS
);
665 findnode(dns_db_t
*db
, dns_name_t
*name
, isc_boolean_t create
,
666 dns_dbnode_t
**nodep
)
668 return (findnodeext(db
, name
, create
, NULL
, NULL
, nodep
));
672 findzonecut(dns_db_t
*db
, dns_name_t
*name
, unsigned int options
,
673 isc_stdtime_t now
, dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
674 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
685 return (ISC_R_NOTIMPLEMENTED
);
689 attachnode(dns_db_t
*db
, dns_dbnode_t
*source
, dns_dbnode_t
**targetp
) {
690 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
691 dns_sdlznode_t
*node
= (dns_sdlznode_t
*)source
;
693 REQUIRE(VALID_SDLZDB(sdlz
));
698 INSIST(node
->references
> 0);
700 INSIST(node
->references
!= 0); /* Catch overflow. */
707 detachnode(dns_db_t
*db
, dns_dbnode_t
**targetp
) {
708 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
709 dns_sdlznode_t
*node
;
710 isc_boolean_t need_destroy
= ISC_FALSE
;
712 REQUIRE(VALID_SDLZDB(sdlz
));
713 REQUIRE(targetp
!= NULL
&& *targetp
!= NULL
);
717 node
= (dns_sdlznode_t
*)(*targetp
);
720 INSIST(node
->references
> 0);
722 if (node
->references
== 0)
723 need_destroy
= ISC_TRUE
;
733 expirenode(dns_db_t
*db
, dns_dbnode_t
*node
, isc_stdtime_t now
) {
738 return (ISC_R_UNEXPECTED
);
742 printnode(dns_db_t
*db
, dns_dbnode_t
*node
, FILE *out
) {
750 createiterator(dns_db_t
*db
, unsigned int options
, dns_dbiterator_t
**iteratorp
)
752 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
753 sdlz_dbiterator_t
*sdlziter
;
756 char zonestr
[DNS_NAME_MAXTEXT
+ 1];
758 REQUIRE(VALID_SDLZDB(sdlz
));
760 if (sdlz
->dlzimp
->methods
->allnodes
== NULL
)
761 return (ISC_R_NOTIMPLEMENTED
);
763 if ((options
& DNS_DB_NSEC3ONLY
) != 0 ||
764 (options
& DNS_DB_NONSEC3
) != 0)
765 return (ISC_R_NOTIMPLEMENTED
);
767 isc_buffer_init(&b
, zonestr
, sizeof(zonestr
));
768 result
= dns_name_totext(&sdlz
->common
.origin
, ISC_TRUE
, &b
);
769 if (result
!= ISC_R_SUCCESS
)
771 isc_buffer_putuint8(&b
, 0);
773 sdlziter
= isc_mem_get(sdlz
->common
.mctx
, sizeof(sdlz_dbiterator_t
));
774 if (sdlziter
== NULL
)
775 return (ISC_R_NOMEMORY
);
777 sdlziter
->common
.methods
= &dbiterator_methods
;
778 sdlziter
->common
.db
= NULL
;
779 dns_db_attach(db
, &sdlziter
->common
.db
);
780 sdlziter
->common
.relative_names
= ISC_TF(options
& DNS_DB_RELATIVENAMES
);
781 sdlziter
->common
.magic
= DNS_DBITERATOR_MAGIC
;
782 ISC_LIST_INIT(sdlziter
->nodelist
);
783 sdlziter
->current
= NULL
;
784 sdlziter
->origin
= NULL
;
786 /* make sure strings are always lowercase */
787 dns_sdlz_tolower(zonestr
);
789 MAYBE_LOCK(sdlz
->dlzimp
);
790 result
= sdlz
->dlzimp
->methods
->allnodes(zonestr
,
791 sdlz
->dlzimp
->driverarg
,
792 sdlz
->dbdata
, sdlziter
);
793 MAYBE_UNLOCK(sdlz
->dlzimp
);
794 if (result
!= ISC_R_SUCCESS
) {
795 dns_dbiterator_t
*iter
= &sdlziter
->common
;
796 dbiterator_destroy(&iter
);
800 if (sdlziter
->origin
!= NULL
) {
801 ISC_LIST_UNLINK(sdlziter
->nodelist
, sdlziter
->origin
, link
);
802 ISC_LIST_PREPEND(sdlziter
->nodelist
, sdlziter
->origin
, link
);
805 *iteratorp
= (dns_dbiterator_t
*)sdlziter
;
807 return (ISC_R_SUCCESS
);
811 findrdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
812 dns_rdatatype_t type
, dns_rdatatype_t covers
,
813 isc_stdtime_t now
, dns_rdataset_t
*rdataset
,
814 dns_rdataset_t
*sigrdataset
)
816 dns_rdatalist_t
*list
;
817 dns_sdlznode_t
*sdlznode
= (dns_sdlznode_t
*)node
;
819 REQUIRE(VALID_SDLZNODE(node
));
827 if (type
== dns_rdatatype_sig
|| type
== dns_rdatatype_rrsig
)
828 return (ISC_R_NOTIMPLEMENTED
);
830 list
= ISC_LIST_HEAD(sdlznode
->lists
);
831 while (list
!= NULL
) {
832 if (list
->type
== type
)
834 list
= ISC_LIST_NEXT(list
, link
);
837 return (ISC_R_NOTFOUND
);
839 list_tordataset(list
, db
, node
, rdataset
);
841 return (ISC_R_SUCCESS
);
845 findext(dns_db_t
*db
, dns_name_t
*name
, dns_dbversion_t
*version
,
846 dns_rdatatype_t type
, unsigned int options
, isc_stdtime_t now
,
847 dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
848 dns_clientinfomethods_t
*methods
, dns_clientinfo_t
*clientinfo
,
849 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
851 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
852 dns_dbnode_t
*node
= NULL
;
853 dns_fixedname_t fname
;
854 dns_rdataset_t xrdataset
;
856 unsigned int nlabels
, olabels
;
860 REQUIRE(VALID_SDLZDB(sdlz
));
861 REQUIRE(nodep
== NULL
|| *nodep
== NULL
);
862 REQUIRE(version
== NULL
|| version
== (void*)&sdlz
->dummy_version
);
867 if (!dns_name_issubdomain(name
, &db
->origin
))
868 return (DNS_R_NXDOMAIN
);
870 olabels
= dns_name_countlabels(&db
->origin
);
871 nlabels
= dns_name_countlabels(name
);
873 dns_fixedname_init(&fname
);
874 xname
= dns_fixedname_name(&fname
);
876 if (rdataset
== NULL
) {
877 dns_rdataset_init(&xrdataset
);
878 rdataset
= &xrdataset
;
881 result
= DNS_R_NXDOMAIN
;
883 for (i
= olabels
; i
<= nlabels
; i
++) {
885 * Look up the next label.
887 dns_name_getlabelsequence(name
, nlabels
- i
, i
, xname
);
888 result
= findnodeext(db
, xname
, ISC_FALSE
,
889 methods
, clientinfo
, &node
);
890 if (result
== ISC_R_NOTFOUND
) {
891 result
= DNS_R_NXDOMAIN
;
893 } else if (result
!= ISC_R_SUCCESS
)
897 * Look for a DNAME at the current label, unless this is
901 result
= findrdataset(db
, node
, version
,
902 dns_rdatatype_dname
, 0, now
,
903 rdataset
, sigrdataset
);
904 if (result
== ISC_R_SUCCESS
) {
905 result
= DNS_R_DNAME
;
911 * Look for an NS at the current label, unless this is the
912 * origin or glue is ok.
914 if (i
!= olabels
&& (options
& DNS_DBFIND_GLUEOK
) == 0) {
915 result
= findrdataset(db
, node
, version
,
916 dns_rdatatype_ns
, 0, now
,
917 rdataset
, sigrdataset
);
918 if (result
== ISC_R_SUCCESS
) {
919 if (i
== nlabels
&& type
== dns_rdatatype_any
)
921 result
= DNS_R_ZONECUT
;
922 dns_rdataset_disassociate(rdataset
);
923 if (sigrdataset
!= NULL
&&
924 dns_rdataset_isassociated
926 dns_rdataset_disassociate
930 result
= DNS_R_DELEGATION
;
936 * If the current name is not the qname, add another label
946 * If we're looking for ANY, we're done.
948 if (type
== dns_rdatatype_any
) {
949 result
= ISC_R_SUCCESS
;
954 * Look for the qtype.
956 result
= findrdataset(db
, node
, version
, type
, 0, now
,
957 rdataset
, sigrdataset
);
958 if (result
== ISC_R_SUCCESS
)
964 if (type
!= dns_rdatatype_cname
) {
965 result
= findrdataset(db
, node
, version
,
966 dns_rdatatype_cname
, 0, now
,
967 rdataset
, sigrdataset
);
968 if (result
== ISC_R_SUCCESS
) {
969 result
= DNS_R_CNAME
;
974 result
= DNS_R_NXRRSET
;
978 if (rdataset
== &xrdataset
&& dns_rdataset_isassociated(rdataset
))
979 dns_rdataset_disassociate(rdataset
);
981 if (foundname
!= NULL
) {
982 isc_result_t xresult
;
984 xresult
= dns_name_copy(xname
, foundname
, NULL
);
985 if (xresult
!= ISC_R_SUCCESS
) {
988 if (dns_rdataset_isassociated(rdataset
))
989 dns_rdataset_disassociate(rdataset
);
990 return (DNS_R_BADDB
);
996 else if (node
!= NULL
)
997 detachnode(db
, &node
);
1003 find(dns_db_t
*db
, dns_name_t
*name
, dns_dbversion_t
*version
,
1004 dns_rdatatype_t type
, unsigned int options
, isc_stdtime_t now
,
1005 dns_dbnode_t
**nodep
, dns_name_t
*foundname
,
1006 dns_rdataset_t
*rdataset
, dns_rdataset_t
*sigrdataset
)
1008 return (findext(db
, name
, version
, type
, options
, now
, nodep
,
1009 foundname
, NULL
, NULL
, rdataset
, sigrdataset
));
1013 allrdatasets(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
1014 isc_stdtime_t now
, dns_rdatasetiter_t
**iteratorp
)
1016 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*) db
;
1017 sdlz_rdatasetiter_t
*iterator
;
1019 REQUIRE(VALID_SDLZDB(sdlz
));
1021 REQUIRE(version
== NULL
||
1022 version
== (void*)&sdlz
->dummy_version
||
1023 version
== sdlz
->future_version
);
1028 iterator
= isc_mem_get(db
->mctx
, sizeof(sdlz_rdatasetiter_t
));
1029 if (iterator
== NULL
)
1030 return (ISC_R_NOMEMORY
);
1032 iterator
->common
.magic
= DNS_RDATASETITER_MAGIC
;
1033 iterator
->common
.methods
= &rdatasetiter_methods
;
1034 iterator
->common
.db
= db
;
1035 iterator
->common
.node
= NULL
;
1036 attachnode(db
, node
, &iterator
->common
.node
);
1037 iterator
->common
.version
= version
;
1038 iterator
->common
.now
= now
;
1040 *iteratorp
= (dns_rdatasetiter_t
*)iterator
;
1042 return (ISC_R_SUCCESS
);
1046 modrdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
1047 dns_rdataset_t
*rdataset
, unsigned int options
,
1048 dns_sdlzmodrdataset_t mod_function
)
1050 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
1051 dns_master_style_t
*style
= NULL
;
1052 isc_result_t result
;
1053 isc_buffer_t
*buffer
= NULL
;
1055 dns_sdlznode_t
*sdlznode
;
1056 char *rdatastr
= NULL
;
1057 char name
[DNS_NAME_MAXTEXT
+ 1];
1059 REQUIRE(VALID_SDLZDB(sdlz
));
1061 if (mod_function
== NULL
)
1062 return (ISC_R_NOTIMPLEMENTED
);
1064 sdlznode
= (dns_sdlznode_t
*)node
;
1068 dns_name_format(sdlznode
->name
, name
, sizeof(name
));
1070 mctx
= sdlz
->common
.mctx
;
1072 result
= isc_buffer_allocate(mctx
, &buffer
, 1024);
1073 if (result
!= ISC_R_SUCCESS
)
1076 result
= dns_master_stylecreate(&style
, 0, 0, 0, 0, 0, 0, 1, mctx
);
1077 if (result
!= ISC_R_SUCCESS
)
1080 result
= dns_master_rdatasettotext(sdlznode
->name
, rdataset
,
1082 if (result
!= ISC_R_SUCCESS
)
1085 if (isc_buffer_usedlength(buffer
) < 1) {
1086 result
= ISC_R_BADADDRESSFORM
;
1090 rdatastr
= isc_buffer_base(buffer
);
1091 if (rdatastr
== NULL
) {
1092 result
= ISC_R_NOMEMORY
;
1095 rdatastr
[isc_buffer_usedlength(buffer
) - 1] = 0;
1097 MAYBE_LOCK(sdlz
->dlzimp
);
1098 result
= mod_function(name
, rdatastr
, sdlz
->dlzimp
->driverarg
,
1099 sdlz
->dbdata
, version
);
1100 MAYBE_UNLOCK(sdlz
->dlzimp
);
1103 isc_buffer_free(&buffer
);
1105 dns_master_styledestroy(&style
, mctx
);
1111 addrdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
1112 isc_stdtime_t now
, dns_rdataset_t
*rdataset
, unsigned int options
,
1113 dns_rdataset_t
*addedrdataset
)
1115 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
1116 isc_result_t result
;
1119 UNUSED(addedrdataset
);
1120 REQUIRE(VALID_SDLZDB(sdlz
));
1122 if (sdlz
->dlzimp
->methods
->addrdataset
== NULL
)
1123 return (ISC_R_NOTIMPLEMENTED
);
1125 result
= modrdataset(db
, node
, version
, rdataset
, options
,
1126 sdlz
->dlzimp
->methods
->addrdataset
);
1132 subtractrdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
1133 dns_rdataset_t
*rdataset
, unsigned int options
,
1134 dns_rdataset_t
*newrdataset
)
1136 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
1137 isc_result_t result
;
1139 UNUSED(newrdataset
);
1140 REQUIRE(VALID_SDLZDB(sdlz
));
1142 if (sdlz
->dlzimp
->methods
->subtractrdataset
== NULL
) {
1143 return (ISC_R_NOTIMPLEMENTED
);
1146 result
= modrdataset(db
, node
, version
, rdataset
, options
,
1147 sdlz
->dlzimp
->methods
->subtractrdataset
);
1152 deleterdataset(dns_db_t
*db
, dns_dbnode_t
*node
, dns_dbversion_t
*version
,
1153 dns_rdatatype_t type
, dns_rdatatype_t covers
)
1155 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
1156 char name
[DNS_NAME_MAXTEXT
+ 1];
1157 char b_type
[DNS_RDATATYPE_FORMATSIZE
];
1158 dns_sdlznode_t
*sdlznode
;
1159 isc_result_t result
;
1163 REQUIRE(VALID_SDLZDB(sdlz
));
1165 if (sdlz
->dlzimp
->methods
->delrdataset
== NULL
)
1166 return (ISC_R_NOTIMPLEMENTED
);
1168 sdlznode
= (dns_sdlznode_t
*)node
;
1169 dns_name_format(sdlznode
->name
, name
, sizeof(name
));
1170 dns_rdatatype_format(type
, b_type
, sizeof(b_type
));
1172 MAYBE_LOCK(sdlz
->dlzimp
);
1173 result
= sdlz
->dlzimp
->methods
->delrdataset(name
, b_type
,
1174 sdlz
->dlzimp
->driverarg
,
1175 sdlz
->dbdata
, version
);
1176 MAYBE_UNLOCK(sdlz
->dlzimp
);
1181 static isc_boolean_t
1182 issecure(dns_db_t
*db
) {
1189 nodecount(dns_db_t
*db
) {
1195 static isc_boolean_t
1196 ispersistent(dns_db_t
*db
) {
1202 overmem(dns_db_t
*db
, isc_boolean_t overmem
) {
1208 settask(dns_db_t
*db
, isc_task_t
*task
) {
1214 * getoriginnode() is used by the update code to find the
1215 * dns_rdatatype_dnskey record for a zone
1218 getoriginnode(dns_db_t
*db
, dns_dbnode_t
**nodep
) {
1219 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)db
;
1220 isc_result_t result
;
1222 REQUIRE(VALID_SDLZDB(sdlz
));
1223 if (sdlz
->dlzimp
->methods
->newversion
== NULL
)
1224 return (ISC_R_NOTIMPLEMENTED
);
1226 result
= findnodeext(db
, &sdlz
->common
.origin
, ISC_FALSE
,
1228 if (result
!= ISC_R_SUCCESS
)
1229 sdlz_log(ISC_LOG_ERROR
, "sdlz getoriginnode failed: %s",
1230 isc_result_totext(result
));
1234 static dns_dbmethods_t sdlzdb_methods
= {
1264 NULL
, /* transfernode */
1265 NULL
, /* getnsec3parameters */
1266 NULL
, /* findnsec3node */
1267 NULL
, /* setsigningtime */
1268 NULL
, /* getsigningtime */
1269 NULL
, /* resigned */
1270 NULL
, /* isdnssec */
1271 NULL
, /* getrrsetstats */
1272 NULL
, /* rpz_attach */
1273 NULL
, /* rpz_ready */
1276 NULL
, /* setcachestats */
1281 * Database Iterator Methods. These methods were "borrowed" from the SDB
1282 * driver interface. See the SDB driver interface documentation for more info.
1286 dbiterator_destroy(dns_dbiterator_t
**iteratorp
) {
1287 sdlz_dbiterator_t
*sdlziter
= (sdlz_dbiterator_t
*)(*iteratorp
);
1288 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)sdlziter
->common
.db
;
1290 while (!ISC_LIST_EMPTY(sdlziter
->nodelist
)) {
1291 dns_sdlznode_t
*node
;
1292 node
= ISC_LIST_HEAD(sdlziter
->nodelist
);
1293 ISC_LIST_UNLINK(sdlziter
->nodelist
, node
, link
);
1297 dns_db_detach(&sdlziter
->common
.db
);
1298 isc_mem_put(sdlz
->common
.mctx
, sdlziter
, sizeof(sdlz_dbiterator_t
));
1304 dbiterator_first(dns_dbiterator_t
*iterator
) {
1305 sdlz_dbiterator_t
*sdlziter
= (sdlz_dbiterator_t
*)iterator
;
1307 sdlziter
->current
= ISC_LIST_HEAD(sdlziter
->nodelist
);
1308 if (sdlziter
->current
== NULL
)
1309 return (ISC_R_NOMORE
);
1311 return (ISC_R_SUCCESS
);
1315 dbiterator_last(dns_dbiterator_t
*iterator
) {
1316 sdlz_dbiterator_t
*sdlziter
= (sdlz_dbiterator_t
*)iterator
;
1318 sdlziter
->current
= ISC_LIST_TAIL(sdlziter
->nodelist
);
1319 if (sdlziter
->current
== NULL
)
1320 return (ISC_R_NOMORE
);
1322 return (ISC_R_SUCCESS
);
1326 dbiterator_seek(dns_dbiterator_t
*iterator
, dns_name_t
*name
) {
1327 sdlz_dbiterator_t
*sdlziter
= (sdlz_dbiterator_t
*)iterator
;
1329 sdlziter
->current
= ISC_LIST_HEAD(sdlziter
->nodelist
);
1330 while (sdlziter
->current
!= NULL
) {
1331 if (dns_name_equal(sdlziter
->current
->name
, name
))
1332 return (ISC_R_SUCCESS
);
1333 sdlziter
->current
= ISC_LIST_NEXT(sdlziter
->current
, link
);
1335 return (ISC_R_NOTFOUND
);
1339 dbiterator_prev(dns_dbiterator_t
*iterator
) {
1340 sdlz_dbiterator_t
*sdlziter
= (sdlz_dbiterator_t
*)iterator
;
1342 sdlziter
->current
= ISC_LIST_PREV(sdlziter
->current
, link
);
1343 if (sdlziter
->current
== NULL
)
1344 return (ISC_R_NOMORE
);
1346 return (ISC_R_SUCCESS
);
1350 dbiterator_next(dns_dbiterator_t
*iterator
) {
1351 sdlz_dbiterator_t
*sdlziter
= (sdlz_dbiterator_t
*)iterator
;
1353 sdlziter
->current
= ISC_LIST_NEXT(sdlziter
->current
, link
);
1354 if (sdlziter
->current
== NULL
)
1355 return (ISC_R_NOMORE
);
1357 return (ISC_R_SUCCESS
);
1361 dbiterator_current(dns_dbiterator_t
*iterator
, dns_dbnode_t
**nodep
,
1364 sdlz_dbiterator_t
*sdlziter
= (sdlz_dbiterator_t
*)iterator
;
1366 attachnode(iterator
->db
, sdlziter
->current
, nodep
);
1368 return (dns_name_copy(sdlziter
->current
->name
, name
, NULL
));
1369 return (ISC_R_SUCCESS
);
1373 dbiterator_pause(dns_dbiterator_t
*iterator
) {
1375 return (ISC_R_SUCCESS
);
1379 dbiterator_origin(dns_dbiterator_t
*iterator
, dns_name_t
*name
) {
1381 return (dns_name_copy(dns_rootname
, name
, NULL
));
1385 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1386 * interface. See the SDB driver interface documentation for more info.
1390 disassociate(dns_rdataset_t
*rdataset
) {
1391 dns_dbnode_t
*node
= rdataset
->private5
;
1392 dns_sdlznode_t
*sdlznode
= (dns_sdlznode_t
*) node
;
1393 dns_db_t
*db
= (dns_db_t
*) sdlznode
->sdlz
;
1395 detachnode(db
, &node
);
1396 isc__rdatalist_disassociate(rdataset
);
1400 rdataset_clone(dns_rdataset_t
*source
, dns_rdataset_t
*target
) {
1401 dns_dbnode_t
*node
= source
->private5
;
1402 dns_sdlznode_t
*sdlznode
= (dns_sdlznode_t
*) node
;
1403 dns_db_t
*db
= (dns_db_t
*) sdlznode
->sdlz
;
1404 dns_dbnode_t
*tempdb
= NULL
;
1406 isc__rdatalist_clone(source
, target
);
1407 attachnode(db
, node
, &tempdb
);
1408 source
->private5
= tempdb
;
1411 static dns_rdatasetmethods_t rdataset_methods
= {
1413 isc__rdatalist_first
,
1414 isc__rdatalist_next
,
1415 isc__rdatalist_current
,
1417 isc__rdatalist_count
,
1418 isc__rdatalist_addnoqname
,
1419 isc__rdatalist_getnoqname
,
1431 list_tordataset(dns_rdatalist_t
*rdatalist
,
1432 dns_db_t
*db
, dns_dbnode_t
*node
,
1433 dns_rdataset_t
*rdataset
)
1436 * The sdlz rdataset is an rdatalist with some additions.
1437 * - private1 & private2 are used by the rdatalist.
1438 * - private3 & private 4 are unused.
1439 * - private5 is the node.
1442 /* This should never fail. */
1443 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist
, rdataset
) ==
1446 rdataset
->methods
= &rdataset_methods
;
1447 dns_db_attachnode(db
, node
, &rdataset
->private5
);
1451 * SDLZ core methods. This is the core of the new DLZ functionality.
1455 * Build a 'bind' database driver structure to be returned by
1456 * either the find zone or the allow zone transfer method.
1457 * This method is only available in this source file, it is
1458 * not made available anywhere else.
1462 dns_sdlzcreateDBP(isc_mem_t
*mctx
, void *driverarg
, void *dbdata
,
1463 dns_name_t
*name
, dns_rdataclass_t rdclass
, dns_db_t
**dbp
)
1465 isc_result_t result
;
1466 dns_sdlz_db_t
*sdlzdb
;
1467 dns_sdlzimplementation_t
*imp
;
1469 /* check that things are as we expect */
1470 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
1471 REQUIRE(name
!= NULL
);
1473 imp
= (dns_sdlzimplementation_t
*) driverarg
;
1475 /* allocate and zero memory for driver structure */
1476 sdlzdb
= isc_mem_get(mctx
, sizeof(dns_sdlz_db_t
));
1478 return (ISC_R_NOMEMORY
);
1479 memset(sdlzdb
, 0, sizeof(dns_sdlz_db_t
));
1481 /* initialize and set origin */
1482 dns_name_init(&sdlzdb
->common
.origin
, NULL
);
1483 result
= dns_name_dupwithoffsets(name
, mctx
, &sdlzdb
->common
.origin
);
1484 if (result
!= ISC_R_SUCCESS
)
1487 /* initialize the reference count mutex */
1488 result
= isc_mutex_init(&sdlzdb
->refcnt_lock
);
1489 if (result
!= ISC_R_SUCCESS
)
1492 /* set the rest of the database structure attributes */
1493 sdlzdb
->dlzimp
= imp
;
1494 sdlzdb
->common
.methods
= &sdlzdb_methods
;
1495 sdlzdb
->common
.attributes
= 0;
1496 sdlzdb
->common
.rdclass
= rdclass
;
1497 sdlzdb
->common
.mctx
= NULL
;
1498 sdlzdb
->dbdata
= dbdata
;
1499 sdlzdb
->references
= 1;
1501 /* attach to the memory context */
1502 isc_mem_attach(mctx
, &sdlzdb
->common
.mctx
);
1504 /* mark structure as valid */
1505 sdlzdb
->common
.magic
= DNS_DB_MAGIC
;
1506 sdlzdb
->common
.impmagic
= SDLZDB_MAGIC
;
1507 *dbp
= (dns_db_t
*) sdlzdb
;
1512 * reference count mutex could not be initialized, clean up
1516 dns_name_free(&sdlzdb
->common
.origin
, mctx
);
1518 isc_mem_put(mctx
, sdlzdb
, sizeof(dns_sdlz_db_t
));
1523 dns_sdlzallowzonexfr(void *driverarg
, void *dbdata
, isc_mem_t
*mctx
,
1524 dns_rdataclass_t rdclass
, dns_name_t
*name
,
1525 isc_sockaddr_t
*clientaddr
, dns_db_t
**dbp
)
1529 char namestr
[DNS_NAME_MAXTEXT
+ 1];
1530 char clientstr
[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1532 isc_netaddr_t netaddr
;
1533 isc_result_t result
;
1534 dns_sdlzimplementation_t
*imp
;
1537 * Perform checks to make sure data is as we expect it to be.
1539 REQUIRE(driverarg
!= NULL
);
1540 REQUIRE(name
!= NULL
);
1541 REQUIRE(clientaddr
!= NULL
);
1542 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
1544 imp
= (dns_sdlzimplementation_t
*) driverarg
;
1546 /* Convert DNS name to ascii text */
1547 isc_buffer_init(&b
, namestr
, sizeof(namestr
));
1548 result
= dns_name_totext(name
, ISC_TRUE
, &b
);
1549 if (result
!= ISC_R_SUCCESS
)
1551 isc_buffer_putuint8(&b
, 0);
1553 /* convert client address to ascii text */
1554 isc_buffer_init(&b2
, clientstr
, sizeof(clientstr
));
1555 isc_netaddr_fromsockaddr(&netaddr
, clientaddr
);
1556 result
= isc_netaddr_totext(&netaddr
, &b2
);
1557 if (result
!= ISC_R_SUCCESS
)
1559 isc_buffer_putuint8(&b2
, 0);
1561 /* make sure strings are always lowercase */
1562 dns_sdlz_tolower(namestr
);
1563 dns_sdlz_tolower(clientstr
);
1565 /* Call SDLZ driver's find zone method */
1566 if (imp
->methods
->allowzonexfr
!= NULL
) {
1568 result
= imp
->methods
->allowzonexfr(imp
->driverarg
, dbdata
,
1569 namestr
, clientstr
);
1572 * if zone is supported and transfers allowed build a 'bind'
1575 if (result
== ISC_R_SUCCESS
)
1576 result
= dns_sdlzcreateDBP(mctx
, driverarg
, dbdata
,
1577 name
, rdclass
, dbp
);
1581 return (ISC_R_NOTIMPLEMENTED
);
1585 dns_sdlzcreate(isc_mem_t
*mctx
, const char *dlzname
, unsigned int argc
,
1586 char *argv
[], void *driverarg
, void **dbdata
)
1588 dns_sdlzimplementation_t
*imp
;
1589 isc_result_t result
= ISC_R_NOTFOUND
;
1591 /* Write debugging message to log */
1592 sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1595 * Performs checks to make sure data is as we expect it to be.
1597 REQUIRE(driverarg
!= NULL
);
1598 REQUIRE(dlzname
!= NULL
);
1599 REQUIRE(dbdata
!= NULL
);
1604 /* If the create method exists, call it. */
1605 if (imp
->methods
->create
!= NULL
) {
1607 result
= imp
->methods
->create(dlzname
, argc
, argv
,
1608 imp
->driverarg
, dbdata
);
1612 /* Write debugging message to log */
1613 if (result
== ISC_R_SUCCESS
) {
1614 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1616 sdlz_log(ISC_LOG_ERROR
, "SDLZ driver failed to load.");
1623 dns_sdlzdestroy(void *driverdata
, void **dbdata
) {
1624 dns_sdlzimplementation_t
*imp
;
1626 /* Write debugging message to log */
1627 sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1631 /* If the destroy method exists, call it. */
1632 if (imp
->methods
->destroy
!= NULL
) {
1634 imp
->methods
->destroy(imp
->driverarg
, dbdata
);
1640 dns_sdlzfindzone(void *driverarg
, void *dbdata
, isc_mem_t
*mctx
,
1641 dns_rdataclass_t rdclass
, dns_name_t
*name
,
1642 dns_clientinfomethods_t
*methods
,
1643 dns_clientinfo_t
*clientinfo
,
1647 char namestr
[DNS_NAME_MAXTEXT
+ 1];
1648 isc_result_t result
;
1649 dns_sdlzimplementation_t
*imp
;
1652 * Perform checks to make sure data is as we expect it to be.
1654 REQUIRE(driverarg
!= NULL
);
1655 REQUIRE(name
!= NULL
);
1656 REQUIRE(dbp
!= NULL
&& *dbp
== NULL
);
1658 imp
= (dns_sdlzimplementation_t
*) driverarg
;
1660 /* Convert DNS name to ascii text */
1661 isc_buffer_init(&b
, namestr
, sizeof(namestr
));
1662 result
= dns_name_totext(name
, ISC_TRUE
, &b
);
1663 if (result
!= ISC_R_SUCCESS
)
1665 isc_buffer_putuint8(&b
, 0);
1667 /* make sure strings are always lowercase */
1668 dns_sdlz_tolower(namestr
);
1670 /* Call SDLZ driver's find zone method */
1672 result
= imp
->methods
->findzone(imp
->driverarg
, dbdata
, namestr
,
1673 methods
, clientinfo
);
1677 * if zone is supported build a 'bind' database driver
1678 * structure to return
1680 if (result
== ISC_R_SUCCESS
)
1681 result
= dns_sdlzcreateDBP(mctx
, driverarg
, dbdata
, name
,
1689 dns_sdlzconfigure(void *driverarg
, void *dbdata
,
1690 dns_view_t
*view
, dns_dlzdb_t
*dlzdb
)
1692 isc_result_t result
;
1693 dns_sdlzimplementation_t
*imp
;
1695 REQUIRE(driverarg
!= NULL
);
1697 imp
= (dns_sdlzimplementation_t
*) driverarg
;
1699 /* Call SDLZ driver's configure method */
1700 if (imp
->methods
->configure
!= NULL
) {
1702 result
= imp
->methods
->configure(view
, dlzdb
,
1703 imp
->driverarg
, dbdata
);
1706 result
= ISC_R_SUCCESS
;
1712 static isc_boolean_t
1713 dns_sdlzssumatch(dns_name_t
*signer
, dns_name_t
*name
, isc_netaddr_t
*tcpaddr
,
1714 dns_rdatatype_t type
, const dst_key_t
*key
, void *driverarg
,
1717 dns_sdlzimplementation_t
*imp
;
1718 char b_signer
[DNS_NAME_FORMATSIZE
];
1719 char b_name
[DNS_NAME_FORMATSIZE
];
1720 char b_addr
[ISC_NETADDR_FORMATSIZE
];
1721 char b_type
[DNS_RDATATYPE_FORMATSIZE
];
1722 char b_key
[DST_KEY_FORMATSIZE
];
1723 isc_buffer_t
*tkey_token
= NULL
;
1724 isc_region_t token_region
;
1725 isc_uint32_t token_len
= 0;
1728 REQUIRE(driverarg
!= NULL
);
1730 imp
= (dns_sdlzimplementation_t
*) driverarg
;
1731 if (imp
->methods
->ssumatch
== NULL
)
1735 * Format the request elements. sdlz operates on strings, not
1739 dns_name_format(signer
, b_signer
, sizeof(b_signer
));
1743 dns_name_format(name
, b_name
, sizeof(b_name
));
1745 if (tcpaddr
!= NULL
)
1746 isc_netaddr_format(tcpaddr
, b_addr
, sizeof(b_addr
));
1750 dns_rdatatype_format(type
, b_type
, sizeof(b_type
));
1753 dst_key_format(key
, b_key
, sizeof(b_key
));
1754 tkey_token
= dst_key_tkeytoken(key
);
1758 if (tkey_token
!= NULL
) {
1759 isc_buffer_region(tkey_token
, &token_region
);
1760 token_len
= token_region
.length
;
1764 ret
= imp
->methods
->ssumatch(b_signer
, b_name
, b_addr
, b_type
, b_key
,
1766 token_len
!= 0 ? token_region
.base
: NULL
,
1767 imp
->driverarg
, dbdata
);
1772 static dns_dlzmethods_t sdlzmethods
= {
1776 dns_sdlzallowzonexfr
,
1786 dns_sdlz_putrr(dns_sdlzlookup_t
*lookup
, const char *type
, dns_ttl_t ttl
,
1789 dns_rdatalist_t
*rdatalist
;
1791 dns_rdatatype_t typeval
;
1792 isc_consttextregion_t r
;
1794 isc_buffer_t
*rdatabuf
= NULL
;
1796 isc_result_t result
;
1801 REQUIRE(VALID_SDLZLOOKUP(lookup
));
1802 REQUIRE(type
!= NULL
);
1803 REQUIRE(data
!= NULL
);
1805 mctx
= lookup
->sdlz
->common
.mctx
;
1808 r
.length
= strlen(type
);
1809 result
= dns_rdatatype_fromtext(&typeval
, (void *) &r
);
1810 if (result
!= ISC_R_SUCCESS
)
1813 rdatalist
= ISC_LIST_HEAD(lookup
->lists
);
1814 while (rdatalist
!= NULL
) {
1815 if (rdatalist
->type
== typeval
)
1817 rdatalist
= ISC_LIST_NEXT(rdatalist
, link
);
1820 if (rdatalist
== NULL
) {
1821 rdatalist
= isc_mem_get(mctx
, sizeof(dns_rdatalist_t
));
1822 if (rdatalist
== NULL
)
1823 return (ISC_R_NOMEMORY
);
1824 rdatalist
->rdclass
= lookup
->sdlz
->common
.rdclass
;
1825 rdatalist
->type
= typeval
;
1826 rdatalist
->covers
= 0;
1827 rdatalist
->ttl
= ttl
;
1828 ISC_LIST_INIT(rdatalist
->rdata
);
1829 ISC_LINK_INIT(rdatalist
, link
);
1830 ISC_LIST_APPEND(lookup
->lists
, rdatalist
, link
);
1832 if (rdatalist
->ttl
> ttl
) {
1834 * BIND9 doesn't enforce all RRs in an RRset
1835 * having the same TTL, as per RFC 2136,
1836 * section 7.12. If a DLZ backend has
1837 * different TTLs, then the best
1838 * we can do is return the lowest.
1840 rdatalist
->ttl
= ttl
;
1843 rdata
= isc_mem_get(mctx
, sizeof(dns_rdata_t
));
1845 return (ISC_R_NOMEMORY
);
1846 dns_rdata_init(rdata
);
1848 if ((lookup
->sdlz
->dlzimp
->flags
& DNS_SDLZFLAG_RELATIVERDATA
) != 0)
1849 origin
= &lookup
->sdlz
->common
.origin
;
1851 origin
= dns_rootname
;
1854 result
= isc_lex_create(mctx
, 64, &lex
);
1855 if (result
!= ISC_R_SUCCESS
)
1858 size
= initial_size(data
);
1860 isc_buffer_constinit(&b
, data
, strlen(data
));
1861 isc_buffer_add(&b
, strlen(data
));
1863 result
= isc_lex_openbuffer(lex
, &b
);
1864 if (result
!= ISC_R_SUCCESS
)
1868 result
= isc_buffer_allocate(mctx
, &rdatabuf
, size
);
1869 if (result
!= ISC_R_SUCCESS
)
1872 result
= dns_rdata_fromtext(rdata
, rdatalist
->rdclass
,
1873 rdatalist
->type
, lex
,
1876 &lookup
->callbacks
);
1877 if (result
!= ISC_R_SUCCESS
)
1878 isc_buffer_free(&rdatabuf
);
1884 } while (result
== ISC_R_NOSPACE
);
1886 if (result
!= ISC_R_SUCCESS
)
1889 ISC_LIST_APPEND(rdatalist
->rdata
, rdata
, link
);
1890 ISC_LIST_APPEND(lookup
->buffers
, rdatabuf
, link
);
1893 isc_lex_destroy(&lex
);
1895 return (ISC_R_SUCCESS
);
1898 if (rdatabuf
!= NULL
)
1899 isc_buffer_free(&rdatabuf
);
1901 isc_lex_destroy(&lex
);
1902 isc_mem_put(mctx
, rdata
, sizeof(dns_rdata_t
));
1908 dns_sdlz_putnamedrr(dns_sdlzallnodes_t
*allnodes
, const char *name
,
1909 const char *type
, dns_ttl_t ttl
, const char *data
)
1911 dns_name_t
*newname
, *origin
;
1912 dns_fixedname_t fnewname
;
1913 dns_sdlz_db_t
*sdlz
= (dns_sdlz_db_t
*)allnodes
->common
.db
;
1914 dns_sdlznode_t
*sdlznode
;
1915 isc_mem_t
*mctx
= sdlz
->common
.mctx
;
1917 isc_result_t result
;
1919 dns_fixedname_init(&fnewname
);
1920 newname
= dns_fixedname_name(&fnewname
);
1922 if ((sdlz
->dlzimp
->flags
& DNS_SDLZFLAG_RELATIVERDATA
) != 0)
1923 origin
= &sdlz
->common
.origin
;
1925 origin
= dns_rootname
;
1926 isc_buffer_constinit(&b
, name
, strlen(name
));
1927 isc_buffer_add(&b
, strlen(name
));
1929 result
= dns_name_fromtext(newname
, &b
, origin
, 0, NULL
);
1930 if (result
!= ISC_R_SUCCESS
)
1933 if (allnodes
->common
.relative_names
) {
1934 /* All names are relative to the root */
1935 unsigned int nlabels
= dns_name_countlabels(newname
);
1936 dns_name_getlabelsequence(newname
, 0, nlabels
- 1, newname
);
1939 sdlznode
= ISC_LIST_HEAD(allnodes
->nodelist
);
1940 if (sdlznode
== NULL
|| !dns_name_equal(sdlznode
->name
, newname
)) {
1942 result
= createnode(sdlz
, &sdlznode
);
1943 if (result
!= ISC_R_SUCCESS
)
1945 sdlznode
->name
= isc_mem_get(mctx
, sizeof(dns_name_t
));
1946 if (sdlznode
->name
== NULL
) {
1947 destroynode(sdlznode
);
1948 return (ISC_R_NOMEMORY
);
1950 dns_name_init(sdlznode
->name
, NULL
);
1951 result
= dns_name_dup(newname
, mctx
, sdlznode
->name
);
1952 if (result
!= ISC_R_SUCCESS
) {
1953 isc_mem_put(mctx
, sdlznode
->name
, sizeof(dns_name_t
));
1954 destroynode(sdlznode
);
1957 ISC_LIST_PREPEND(allnodes
->nodelist
, sdlznode
, link
);
1958 if (allnodes
->origin
== NULL
&&
1959 dns_name_equal(newname
, &sdlz
->common
.origin
))
1960 allnodes
->origin
= sdlznode
;
1962 return (dns_sdlz_putrr(sdlznode
, type
, ttl
, data
));
1967 dns_sdlz_putsoa(dns_sdlzlookup_t
*lookup
, const char *mname
, const char *rname
,
1968 isc_uint32_t serial
)
1970 char str
[2 * DNS_NAME_MAXTEXT
+ 5 * (sizeof("2147483647")) + 7];
1973 REQUIRE(mname
!= NULL
);
1974 REQUIRE(rname
!= NULL
);
1976 n
= snprintf(str
, sizeof str
, "%s %s %u %u %u %u %u",
1977 mname
, rname
, serial
,
1978 SDLZ_DEFAULT_REFRESH
, SDLZ_DEFAULT_RETRY
,
1979 SDLZ_DEFAULT_EXPIRE
, SDLZ_DEFAULT_MINIMUM
);
1980 if (n
>= (int)sizeof(str
) || n
< 0)
1981 return (ISC_R_NOSPACE
);
1982 return (dns_sdlz_putrr(lookup
, "SOA", SDLZ_DEFAULT_TTL
, str
));
1986 dns_sdlzregister(const char *drivername
, const dns_sdlzmethods_t
*methods
,
1987 void *driverarg
, unsigned int flags
, isc_mem_t
*mctx
,
1988 dns_sdlzimplementation_t
**sdlzimp
)
1991 dns_sdlzimplementation_t
*imp
;
1992 isc_result_t result
;
1995 * Performs checks to make sure data is as we expect it to be.
1997 REQUIRE(drivername
!= NULL
);
1998 REQUIRE(methods
!= NULL
);
1999 REQUIRE(methods
->findzone
!= NULL
);
2000 REQUIRE(methods
->lookup
!= NULL
);
2001 REQUIRE(mctx
!= NULL
);
2002 REQUIRE(sdlzimp
!= NULL
&& *sdlzimp
== NULL
);
2003 REQUIRE((flags
& ~(DNS_SDLZFLAG_RELATIVEOWNER
|
2004 DNS_SDLZFLAG_RELATIVERDATA
|
2005 DNS_SDLZFLAG_THREADSAFE
)) == 0);
2007 /* Write debugging message to log */
2008 sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername
);
2011 * Allocate memory for a sdlz_implementation object. Error if
2014 imp
= isc_mem_get(mctx
, sizeof(dns_sdlzimplementation_t
));
2016 return (ISC_R_NOMEMORY
);
2018 /* Make sure memory region is set to all 0's */
2019 memset(imp
, 0, sizeof(dns_sdlzimplementation_t
));
2021 /* Store the data passed into this method */
2022 imp
->methods
= methods
;
2023 imp
->driverarg
= driverarg
;
2027 /* attach the new sdlz_implementation object to a memory context */
2028 isc_mem_attach(mctx
, &imp
->mctx
);
2031 * initialize the driver lock, error if we cannot
2032 * (used if a driver does not support multiple threads)
2034 result
= isc_mutex_init(&imp
->driverlock
);
2035 if (result
!= ISC_R_SUCCESS
) {
2036 UNEXPECTED_ERROR(__FILE__
, __LINE__
,
2037 "isc_mutex_init() failed: %s",
2038 isc_result_totext(result
));
2042 imp
->dlz_imp
= NULL
;
2045 * register the DLZ driver. Pass in our "extra" sdlz information as
2046 * a driverarg. (that's why we stored the passed in driver arg in our
2047 * sdlz_implementation structure) Also, store the dlz_implementation
2048 * structure in our sdlz_implementation.
2050 result
= dns_dlzregister(drivername
, &sdlzmethods
, imp
, mctx
,
2053 /* if registration fails, cleanup and get outta here. */
2054 if (result
!= ISC_R_SUCCESS
)
2059 return (ISC_R_SUCCESS
);
2062 /* destroy the driver lock, we don't need it anymore */
2063 DESTROYLOCK(&imp
->driverlock
);
2067 * return the memory back to the available memory pool and
2068 * remove it from the memory context.
2070 isc_mem_put(mctx
, imp
, sizeof(dns_sdlzimplementation_t
));
2071 isc_mem_detach(&mctx
);
2076 dns_sdlzunregister(dns_sdlzimplementation_t
**sdlzimp
) {
2077 dns_sdlzimplementation_t
*imp
;
2080 /* Write debugging message to log */
2081 sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2084 * Performs checks to make sure data is as we expect it to be.
2086 REQUIRE(sdlzimp
!= NULL
&& *sdlzimp
!= NULL
);
2090 /* Unregister the DLZ driver implementation */
2091 dns_dlzunregister(&imp
->dlz_imp
);
2093 /* destroy the driver lock, we don't need it anymore */
2094 DESTROYLOCK(&imp
->driverlock
);
2099 * return the memory back to the available memory pool and
2100 * remove it from the memory context.
2102 isc_mem_put(mctx
, imp
, sizeof(dns_sdlzimplementation_t
));
2103 isc_mem_detach(&mctx
);
2110 dns_sdlz_setdb(dns_dlzdb_t
*dlzdatabase
, dns_rdataclass_t rdclass
,
2111 dns_name_t
*name
, dns_db_t
**dbp
)
2113 isc_result_t result
;
2115 result
= dns_sdlzcreateDBP(dlzdatabase
->mctx
,
2116 dlzdatabase
->implementation
->driverarg
,
2117 dlzdatabase
->dbdata
, name
, rdclass
, dbp
);