Patrick Welche <prlw1@cam.ac.uk>
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / sdlz.c
blobc0bcfa46bf2b1bdf4344d975f47a2799e5c209c9
1 /* $NetBSD$ */
3 /*
4 * Portions Copyright (C) 2005-2009 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
26 * copies.
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
43 * copies.
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.
55 /* Id: sdlz.c,v 1.22 2009/09/01 00:22:26 jinmei Exp */
57 /*! \file */
59 #include <config.h>
60 #include <string.h>
62 #include <isc/buffer.h>
63 #include <isc/lex.h>
64 #include <isc/log.h>
65 #include <isc/rwlock.h>
66 #include <isc/string.h>
67 #include <isc/util.h>
68 #include <isc/magic.h>
69 #include <isc/mem.h>
70 #include <isc/once.h>
71 #include <isc/print.h>
72 #include <isc/region.h>
74 #include <dns/callbacks.h>
75 #include <dns/db.h>
76 #include <dns/dbiterator.h>
77 #include <dns/dlz.h>
78 #include <dns/fixedname.h>
79 #include <dns/log.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>
87 #include <dns/sdlz.h>
88 #include <dns/types.h>
90 #include "rdatalist_p.h"
93 * Private Types
96 struct dns_sdlzimplementation {
97 const dns_sdlzmethods_t *methods;
98 isc_mem_t *mctx;
99 void *driverarg;
100 unsigned int flags;
101 isc_mutex_t driverlock;
102 dns_dlzimplementation_t *dlz_imp;
105 struct dns_sdlz_db {
106 /* Unlocked */
107 dns_db_t common;
108 void *dbdata;
109 dns_sdlzimplementation_t *dlzimp;
110 isc_mutex_t refcnt_lock;
111 /* Locked */
112 unsigned int references;
115 struct dns_sdlzlookup {
116 /* Unlocked */
117 unsigned int magic;
118 dns_sdlz_db_t *sdlz;
119 ISC_LIST(dns_rdatalist_t) lists;
120 ISC_LIST(isc_buffer_t) buffers;
121 dns_name_t *name;
122 ISC_LINK(dns_sdlzlookup_t) link;
123 isc_mutex_t lock;
124 dns_rdatacallbacks_t callbacks;
125 /* Locked */
126 unsigned int references;
129 typedef struct dns_sdlzlookup dns_sdlznode_t;
131 struct dns_sdlzallnodes {
132 dns_dbiterator_t common;
133 ISC_LIST(dns_sdlznode_t) nodelist;
134 dns_sdlznode_t *current;
135 dns_sdlznode_t *origin;
138 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
140 typedef struct sdlz_rdatasetiter {
141 dns_rdatasetiter_t common;
142 dns_rdatalist_t *current;
143 } sdlz_rdatasetiter_t;
146 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
149 * Note that "impmagic" is not the first four bytes of the struct, so
150 * ISC_MAGIC_VALID cannot be used.
153 #define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \
154 (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
156 #define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L')
157 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
158 #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)
160 /* These values are taken from RFC 1537 */
161 #define SDLZ_DEFAULT_REFRESH (60 * 60 * 8)
162 #define SDLZ_DEFAULT_RETRY (60 * 60 * 2)
163 #define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
164 #define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24)
166 /* This is a reasonable value */
167 #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
169 static int dummy;
171 #ifdef __COVERITY__
172 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
173 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
174 #else
175 #define MAYBE_LOCK(imp) \
176 do { \
177 unsigned int flags = imp->flags; \
178 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
179 LOCK(&imp->driverlock); \
180 } while (0)
182 #define MAYBE_UNLOCK(imp) \
183 do { \
184 unsigned int flags = imp->flags; \
185 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
186 UNLOCK(&imp->driverlock); \
187 } while (0)
188 #endif
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,
204 dns_name_t *name);
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,
209 dns_name_t *name);
210 static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
211 static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
212 dns_name_t *name);
214 static dns_dbiteratormethods_t dbiterator_methods = {
215 dbiterator_destroy,
216 dbiterator_first,
217 dbiterator_last,
218 dbiterator_seek,
219 dbiterator_prev,
220 dbiterator_next,
221 dbiterator_current,
222 dbiterator_pause,
223 dbiterator_origin
227 * Utility functions
230 /*% Converts the input string to lowercase, in place. */
232 static void
233 dns_sdlz_tolower(char *str) {
235 unsigned int len = strlen(str);
236 unsigned int i;
238 for (i = 0; i < len; i++) {
239 if (str[i] >= 'A' && str[i] <= 'Z')
240 str[i] += 32;
245 static inline unsigned int
246 initial_size(const char *data) {
247 unsigned int len = (strlen(data) / 64) + 1;
248 return (len * 64 + 64);
252 * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
253 * driver interface. See the SDB driver interface documentation for more info.
256 static void
257 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
258 sdlz_rdatasetiter_t *sdlziterator =
259 (sdlz_rdatasetiter_t *)(*iteratorp);
261 detachnode(sdlziterator->common.db, &sdlziterator->common.node);
262 isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
263 sizeof(sdlz_rdatasetiter_t));
264 *iteratorp = NULL;
267 static isc_result_t
268 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
269 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
270 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
272 if (ISC_LIST_EMPTY(sdlznode->lists))
273 return (ISC_R_NOMORE);
274 sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
275 return (ISC_R_SUCCESS);
278 static isc_result_t
279 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
280 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
282 sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
283 if (sdlziterator->current == NULL)
284 return (ISC_R_NOMORE);
285 else
286 return (ISC_R_SUCCESS);
289 static void
290 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
291 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
293 list_tordataset(sdlziterator->current, iterator->db, iterator->node,
294 rdataset);
297 static dns_rdatasetitermethods_t rdatasetiter_methods = {
298 rdatasetiter_destroy,
299 rdatasetiter_first,
300 rdatasetiter_next,
301 rdatasetiter_current
305 * DB routines. These methods were "borrowed" from the SDB driver interface.
306 * See the SDB driver interface documentation for more info.
309 static void
310 attach(dns_db_t *source, dns_db_t **targetp) {
311 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source;
313 REQUIRE(VALID_SDLZDB(sdlz));
315 LOCK(&sdlz->refcnt_lock);
316 REQUIRE(sdlz->references > 0);
317 sdlz->references++;
318 UNLOCK(&sdlz->refcnt_lock);
320 *targetp = source;
323 static void
324 destroy(dns_sdlz_db_t *sdlz) {
325 isc_mem_t *mctx;
326 mctx = sdlz->common.mctx;
328 sdlz->common.magic = 0;
329 sdlz->common.impmagic = 0;
331 isc_mutex_destroy(&sdlz->refcnt_lock);
333 dns_name_free(&sdlz->common.origin, mctx);
335 isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
336 isc_mem_detach(&mctx);
339 static void
340 detach(dns_db_t **dbp) {
341 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
342 isc_boolean_t need_destroy = ISC_FALSE;
344 REQUIRE(VALID_SDLZDB(sdlz));
345 LOCK(&sdlz->refcnt_lock);
346 REQUIRE(sdlz->references > 0);
347 sdlz->references--;
348 if (sdlz->references == 0)
349 need_destroy = ISC_TRUE;
350 UNLOCK(&sdlz->refcnt_lock);
352 if (need_destroy)
353 destroy(sdlz);
355 *dbp = NULL;
358 static isc_result_t
359 beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
360 UNUSED(db);
361 UNUSED(addp);
362 UNUSED(dbloadp);
363 return (ISC_R_NOTIMPLEMENTED);
366 static isc_result_t
367 endload(dns_db_t *db, dns_dbload_t **dbloadp) {
368 UNUSED(db);
369 UNUSED(dbloadp);
370 return (ISC_R_NOTIMPLEMENTED);
373 static isc_result_t
374 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
375 dns_masterformat_t masterformat)
377 UNUSED(db);
378 UNUSED(version);
379 UNUSED(filename);
380 UNUSED(masterformat);
381 return (ISC_R_NOTIMPLEMENTED);
384 static void
385 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
386 REQUIRE(versionp != NULL && *versionp == NULL);
388 UNUSED(db);
390 *versionp = (void *) &dummy;
391 return;
394 static isc_result_t
395 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
396 UNUSED(db);
397 UNUSED(versionp);
399 return (ISC_R_NOTIMPLEMENTED);
402 static void
403 attachversion(dns_db_t *db, dns_dbversion_t *source,
404 dns_dbversion_t **targetp)
406 REQUIRE(source != NULL && source == (void *) &dummy);
408 UNUSED(db);
409 UNUSED(source);
410 UNUSED(targetp);
411 *targetp = source;
414 static void
415 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
416 REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
417 REQUIRE(commit == ISC_FALSE);
419 UNUSED(db);
420 UNUSED(commit);
422 *versionp = NULL;
425 static isc_result_t
426 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
427 dns_sdlznode_t *node;
428 isc_result_t result;
430 node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
431 if (node == NULL)
432 return (ISC_R_NOMEMORY);
434 node->sdlz = NULL;
435 attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
436 ISC_LIST_INIT(node->lists);
437 ISC_LIST_INIT(node->buffers);
438 ISC_LINK_INIT(node, link);
439 node->name = NULL;
440 result = isc_mutex_init(&node->lock);
441 if (result != ISC_R_SUCCESS) {
442 UNEXPECTED_ERROR(__FILE__, __LINE__,
443 "isc_mutex_init() failed: %s",
444 isc_result_totext(result));
445 isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t));
446 return (ISC_R_UNEXPECTED);
448 dns_rdatacallbacks_init(&node->callbacks);
449 node->references = 1;
450 node->magic = SDLZLOOKUP_MAGIC;
452 *nodep = node;
453 return (ISC_R_SUCCESS);
456 static void
457 destroynode(dns_sdlznode_t *node) {
458 dns_rdatalist_t *list;
459 dns_rdata_t *rdata;
460 isc_buffer_t *b;
461 dns_sdlz_db_t *sdlz;
462 dns_db_t *db;
463 isc_mem_t *mctx;
465 sdlz = node->sdlz;
466 mctx = sdlz->common.mctx;
468 while (!ISC_LIST_EMPTY(node->lists)) {
469 list = ISC_LIST_HEAD(node->lists);
470 while (!ISC_LIST_EMPTY(list->rdata)) {
471 rdata = ISC_LIST_HEAD(list->rdata);
472 ISC_LIST_UNLINK(list->rdata, rdata, link);
473 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
475 ISC_LIST_UNLINK(node->lists, list, link);
476 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
479 while (!ISC_LIST_EMPTY(node->buffers)) {
480 b = ISC_LIST_HEAD(node->buffers);
481 ISC_LIST_UNLINK(node->buffers, b, link);
482 isc_buffer_free(&b);
485 if (node->name != NULL) {
486 dns_name_free(node->name, mctx);
487 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
489 DESTROYLOCK(&node->lock);
490 node->magic = 0;
491 isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
492 db = &sdlz->common;
493 detach(&db);
496 static isc_result_t
497 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
498 dns_dbnode_t **nodep)
500 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
501 dns_sdlznode_t *node = NULL;
502 isc_result_t result;
503 isc_buffer_t b;
504 char namestr[DNS_NAME_MAXTEXT + 1];
505 isc_buffer_t b2;
506 char zonestr[DNS_NAME_MAXTEXT + 1];
507 isc_boolean_t isorigin;
508 dns_sdlzauthorityfunc_t authority;
510 REQUIRE(VALID_SDLZDB(sdlz));
511 REQUIRE(create == ISC_FALSE);
512 REQUIRE(nodep != NULL && *nodep == NULL);
514 UNUSED(name);
515 UNUSED(create);
517 isc_buffer_init(&b, namestr, sizeof(namestr));
518 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
519 dns_name_t relname;
520 unsigned int labels;
522 labels = dns_name_countlabels(name) -
523 dns_name_countlabels(&db->origin);
524 dns_name_init(&relname, NULL);
525 dns_name_getlabelsequence(name, 0, labels, &relname);
526 result = dns_name_totext(&relname, ISC_TRUE, &b);
527 if (result != ISC_R_SUCCESS)
528 return (result);
529 } else {
530 result = dns_name_totext(name, ISC_TRUE, &b);
531 if (result != ISC_R_SUCCESS)
532 return (result);
534 isc_buffer_putuint8(&b, 0);
536 isc_buffer_init(&b2, zonestr, sizeof(zonestr));
537 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2);
538 if (result != ISC_R_SUCCESS)
539 return (result);
540 isc_buffer_putuint8(&b2, 0);
542 result = createnode(sdlz, &node);
543 if (result != ISC_R_SUCCESS)
544 return (result);
546 isorigin = dns_name_equal(name, &sdlz->common.origin);
548 /* make sure strings are always lowercase */
549 dns_sdlz_tolower(zonestr);
550 dns_sdlz_tolower(namestr);
552 MAYBE_LOCK(sdlz->dlzimp);
554 /* try to lookup the host (namestr) */
555 result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
556 sdlz->dlzimp->driverarg,
557 sdlz->dbdata, node);
560 * if the host (namestr) was not found, try to lookup a
561 * "wildcard" host.
563 if (result != ISC_R_SUCCESS) {
564 result = sdlz->dlzimp->methods->lookup(zonestr, "*",
565 sdlz->dlzimp->driverarg,
566 sdlz->dbdata, node);
569 MAYBE_UNLOCK(sdlz->dlzimp);
571 if (result != ISC_R_SUCCESS && !isorigin) {
572 destroynode(node);
573 return (result);
576 if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
577 MAYBE_LOCK(sdlz->dlzimp);
578 authority = sdlz->dlzimp->methods->authority;
579 result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
580 sdlz->dbdata, node);
581 MAYBE_UNLOCK(sdlz->dlzimp);
582 if (result != ISC_R_SUCCESS &&
583 result != ISC_R_NOTIMPLEMENTED) {
584 destroynode(node);
585 return (result);
589 *nodep = node;
590 return (ISC_R_SUCCESS);
593 static isc_result_t
594 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
595 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
596 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
598 UNUSED(db);
599 UNUSED(name);
600 UNUSED(options);
601 UNUSED(now);
602 UNUSED(nodep);
603 UNUSED(foundname);
604 UNUSED(rdataset);
605 UNUSED(sigrdataset);
607 return (ISC_R_NOTIMPLEMENTED);
610 static void
611 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
612 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
613 dns_sdlznode_t *node = (dns_sdlznode_t *)source;
615 REQUIRE(VALID_SDLZDB(sdlz));
617 UNUSED(sdlz);
619 LOCK(&node->lock);
620 INSIST(node->references > 0);
621 node->references++;
622 INSIST(node->references != 0); /* Catch overflow. */
623 UNLOCK(&node->lock);
625 *targetp = source;
628 static void
629 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
630 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
631 dns_sdlznode_t *node;
632 isc_boolean_t need_destroy = ISC_FALSE;
634 REQUIRE(VALID_SDLZDB(sdlz));
635 REQUIRE(targetp != NULL && *targetp != NULL);
637 UNUSED(sdlz);
639 node = (dns_sdlznode_t *)(*targetp);
641 LOCK(&node->lock);
642 INSIST(node->references > 0);
643 node->references--;
644 if (node->references == 0)
645 need_destroy = ISC_TRUE;
646 UNLOCK(&node->lock);
648 if (need_destroy)
649 destroynode(node);
651 *targetp = NULL;
654 static isc_result_t
655 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
656 UNUSED(db);
657 UNUSED(node);
658 UNUSED(now);
659 INSIST(0);
660 return (ISC_R_UNEXPECTED);
663 static void
664 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
665 UNUSED(db);
666 UNUSED(node);
667 UNUSED(out);
668 return;
671 static isc_result_t
672 createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
674 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
675 sdlz_dbiterator_t *sdlziter;
676 isc_result_t result;
677 isc_buffer_t b;
678 char zonestr[DNS_NAME_MAXTEXT + 1];
680 REQUIRE(VALID_SDLZDB(sdlz));
682 if (sdlz->dlzimp->methods->allnodes == NULL)
683 return (ISC_R_NOTIMPLEMENTED);
685 if ((options & DNS_DB_NSEC3ONLY) != 0 ||
686 (options & DNS_DB_NONSEC3) != 0)
687 return (ISC_R_NOTIMPLEMENTED);
689 isc_buffer_init(&b, zonestr, sizeof(zonestr));
690 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
691 if (result != ISC_R_SUCCESS)
692 return (result);
693 isc_buffer_putuint8(&b, 0);
695 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
696 if (sdlziter == NULL)
697 return (ISC_R_NOMEMORY);
699 sdlziter->common.methods = &dbiterator_methods;
700 sdlziter->common.db = NULL;
701 dns_db_attach(db, &sdlziter->common.db);
702 sdlziter->common.relative_names = ISC_TF(options & DNS_DB_RELATIVENAMES);
703 sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
704 ISC_LIST_INIT(sdlziter->nodelist);
705 sdlziter->current = NULL;
706 sdlziter->origin = NULL;
708 /* make sure strings are always lowercase */
709 dns_sdlz_tolower(zonestr);
711 MAYBE_LOCK(sdlz->dlzimp);
712 result = sdlz->dlzimp->methods->allnodes(zonestr,
713 sdlz->dlzimp->driverarg,
714 sdlz->dbdata, sdlziter);
715 MAYBE_UNLOCK(sdlz->dlzimp);
716 if (result != ISC_R_SUCCESS) {
717 dns_dbiterator_t *iter = &sdlziter->common;
718 dbiterator_destroy(&iter);
719 return (result);
722 if (sdlziter->origin != NULL) {
723 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
724 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
727 *iteratorp = (dns_dbiterator_t *)sdlziter;
729 return (ISC_R_SUCCESS);
732 static isc_result_t
733 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
734 dns_rdatatype_t type, dns_rdatatype_t covers,
735 isc_stdtime_t now, dns_rdataset_t *rdataset,
736 dns_rdataset_t *sigrdataset)
738 dns_rdatalist_t *list;
739 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
741 REQUIRE(VALID_SDLZNODE(node));
743 UNUSED(db);
744 UNUSED(version);
745 UNUSED(covers);
746 UNUSED(now);
747 UNUSED(sigrdataset);
749 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
750 return (ISC_R_NOTIMPLEMENTED);
752 list = ISC_LIST_HEAD(sdlznode->lists);
753 while (list != NULL) {
754 if (list->type == type)
755 break;
756 list = ISC_LIST_NEXT(list, link);
758 if (list == NULL)
759 return (ISC_R_NOTFOUND);
761 list_tordataset(list, db, node, rdataset);
763 return (ISC_R_SUCCESS);
766 static isc_result_t
767 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
768 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
769 dns_dbnode_t **nodep, dns_name_t *foundname,
770 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
772 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
773 dns_dbnode_t *node = NULL;
774 dns_fixedname_t fname;
775 dns_rdataset_t xrdataset;
776 dns_name_t *xname;
777 unsigned int nlabels, olabels;
778 isc_result_t result;
779 unsigned int i;
781 REQUIRE(VALID_SDLZDB(sdlz));
782 REQUIRE(nodep == NULL || *nodep == NULL);
783 REQUIRE(version == NULL || version == (void *) &dummy);
785 UNUSED(options);
786 UNUSED(sdlz);
788 if (!dns_name_issubdomain(name, &db->origin))
789 return (DNS_R_NXDOMAIN);
791 olabels = dns_name_countlabels(&db->origin);
792 nlabels = dns_name_countlabels(name);
794 dns_fixedname_init(&fname);
795 xname = dns_fixedname_name(&fname);
797 if (rdataset == NULL) {
798 dns_rdataset_init(&xrdataset);
799 rdataset = &xrdataset;
802 result = DNS_R_NXDOMAIN;
804 for (i = olabels; i <= nlabels; i++) {
806 * Unless this is an explicit lookup at the origin, don't
807 * look at the origin.
809 if (i == olabels && i != nlabels)
810 continue;
813 * Look up the next label.
815 dns_name_getlabelsequence(name, nlabels - i, i, xname);
816 result = findnode(db, xname, ISC_FALSE, &node);
817 if (result != ISC_R_SUCCESS) {
818 result = DNS_R_NXDOMAIN;
819 continue;
823 * Look for a DNAME at the current label, unless this is
824 * the qname.
826 if (i < nlabels) {
827 result = findrdataset(db, node, version,
828 dns_rdatatype_dname,
829 0, now, rdataset, sigrdataset);
830 if (result == ISC_R_SUCCESS) {
831 result = DNS_R_DNAME;
832 break;
837 * Look for an NS at the current label, unless this is the
838 * origin or glue is ok.
840 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
841 result = findrdataset(db, node, version,
842 dns_rdatatype_ns,
843 0, now, rdataset, sigrdataset);
844 if (result == ISC_R_SUCCESS) {
845 if (i == nlabels && type == dns_rdatatype_any)
847 result = DNS_R_ZONECUT;
848 dns_rdataset_disassociate(rdataset);
849 if (sigrdataset != NULL &&
850 dns_rdataset_isassociated
851 (sigrdataset)) {
852 dns_rdataset_disassociate
853 (sigrdataset);
855 } else
856 result = DNS_R_DELEGATION;
857 break;
862 * If the current name is not the qname, add another label
863 * and try again.
865 if (i < nlabels) {
866 destroynode(node);
867 node = NULL;
868 continue;
872 * If we're looking for ANY, we're done.
874 if (type == dns_rdatatype_any) {
875 result = ISC_R_SUCCESS;
876 break;
880 * Look for the qtype.
882 result = findrdataset(db, node, version, type,
883 0, now, rdataset, sigrdataset);
884 if (result == ISC_R_SUCCESS)
885 break;
888 * Look for a CNAME
890 if (type != dns_rdatatype_cname) {
891 result = findrdataset(db, node, version,
892 dns_rdatatype_cname,
893 0, now, rdataset, sigrdataset);
894 if (result == ISC_R_SUCCESS) {
895 result = DNS_R_CNAME;
896 break;
900 result = DNS_R_NXRRSET;
901 break;
904 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
905 dns_rdataset_disassociate(rdataset);
907 if (foundname != NULL) {
908 isc_result_t xresult;
910 xresult = dns_name_copy(xname, foundname, NULL);
911 if (xresult != ISC_R_SUCCESS) {
912 if (node != NULL)
913 destroynode(node);
914 if (dns_rdataset_isassociated(rdataset))
915 dns_rdataset_disassociate(rdataset);
916 return (DNS_R_BADDB);
920 if (nodep != NULL)
921 *nodep = node;
922 else if (node != NULL)
923 detachnode(db, &node);
925 return (result);
928 static isc_result_t
929 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
930 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
932 sdlz_rdatasetiter_t *iterator;
934 REQUIRE(version == NULL || version == &dummy);
936 UNUSED(version);
937 UNUSED(now);
939 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
940 if (iterator == NULL)
941 return (ISC_R_NOMEMORY);
943 iterator->common.magic = DNS_RDATASETITER_MAGIC;
944 iterator->common.methods = &rdatasetiter_methods;
945 iterator->common.db = db;
946 iterator->common.node = NULL;
947 attachnode(db, node, &iterator->common.node);
948 iterator->common.version = version;
949 iterator->common.now = now;
951 *iteratorp = (dns_rdatasetiter_t *)iterator;
953 return (ISC_R_SUCCESS);
956 static isc_result_t
957 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
958 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
959 dns_rdataset_t *addedrdataset)
961 UNUSED(db);
962 UNUSED(node);
963 UNUSED(version);
964 UNUSED(now);
965 UNUSED(rdataset);
966 UNUSED(options);
967 UNUSED(addedrdataset);
969 return (ISC_R_NOTIMPLEMENTED);
972 static isc_result_t
973 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
974 dns_rdataset_t *rdataset, unsigned int options,
975 dns_rdataset_t *newrdataset)
977 UNUSED(db);
978 UNUSED(node);
979 UNUSED(version);
980 UNUSED(rdataset);
981 UNUSED(options);
982 UNUSED(newrdataset);
984 return (ISC_R_NOTIMPLEMENTED);
987 static isc_result_t
988 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
989 dns_rdatatype_t type, dns_rdatatype_t covers)
991 UNUSED(db);
992 UNUSED(node);
993 UNUSED(version);
994 UNUSED(type);
995 UNUSED(covers);
997 return (ISC_R_NOTIMPLEMENTED);
1000 static isc_boolean_t
1001 issecure(dns_db_t *db) {
1002 UNUSED(db);
1004 return (ISC_FALSE);
1007 static unsigned int
1008 nodecount(dns_db_t *db) {
1009 UNUSED(db);
1011 return (0);
1014 static isc_boolean_t
1015 ispersistent(dns_db_t *db) {
1016 UNUSED(db);
1017 return (ISC_TRUE);
1020 static void
1021 overmem(dns_db_t *db, isc_boolean_t overmem) {
1022 UNUSED(db);
1023 UNUSED(overmem);
1026 static void
1027 settask(dns_db_t *db, isc_task_t *task) {
1028 UNUSED(db);
1029 UNUSED(task);
1033 static dns_dbmethods_t sdlzdb_methods = {
1034 attach,
1035 detach,
1036 beginload,
1037 endload,
1038 dump,
1039 currentversion,
1040 newversion,
1041 attachversion,
1042 closeversion,
1043 findnode,
1044 find,
1045 findzonecut,
1046 attachnode,
1047 detachnode,
1048 expirenode,
1049 printnode,
1050 createiterator,
1051 findrdataset,
1052 allrdatasets,
1053 addrdataset,
1054 subtractrdataset,
1055 deleterdataset,
1056 issecure,
1057 nodecount,
1058 ispersistent,
1059 overmem,
1060 settask,
1061 NULL,
1062 NULL,
1063 NULL,
1064 NULL,
1065 NULL,
1066 NULL,
1067 NULL,
1068 NULL,
1069 NULL
1073 * Database Iterator Methods. These methods were "borrowed" from the SDB
1074 * driver interface. See the SDB driver interface documentation for more info.
1077 static void
1078 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1079 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1080 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1082 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1083 dns_sdlznode_t *node;
1084 node = ISC_LIST_HEAD(sdlziter->nodelist);
1085 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1086 destroynode(node);
1089 dns_db_detach(&sdlziter->common.db);
1090 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1092 *iteratorp = NULL;
1095 static isc_result_t
1096 dbiterator_first(dns_dbiterator_t *iterator) {
1097 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1099 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1100 if (sdlziter->current == NULL)
1101 return (ISC_R_NOMORE);
1102 else
1103 return (ISC_R_SUCCESS);
1106 static isc_result_t
1107 dbiterator_last(dns_dbiterator_t *iterator) {
1108 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1110 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1111 if (sdlziter->current == NULL)
1112 return (ISC_R_NOMORE);
1113 else
1114 return (ISC_R_SUCCESS);
1117 static isc_result_t
1118 dbiterator_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1119 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1121 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1122 while (sdlziter->current != NULL) {
1123 if (dns_name_equal(sdlziter->current->name, name))
1124 return (ISC_R_SUCCESS);
1125 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1127 return (ISC_R_NOTFOUND);
1130 static isc_result_t
1131 dbiterator_prev(dns_dbiterator_t *iterator) {
1132 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1134 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1135 if (sdlziter->current == NULL)
1136 return (ISC_R_NOMORE);
1137 else
1138 return (ISC_R_SUCCESS);
1141 static isc_result_t
1142 dbiterator_next(dns_dbiterator_t *iterator) {
1143 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1145 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1146 if (sdlziter->current == NULL)
1147 return (ISC_R_NOMORE);
1148 else
1149 return (ISC_R_SUCCESS);
1152 static isc_result_t
1153 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1154 dns_name_t *name)
1156 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1158 attachnode(iterator->db, sdlziter->current, nodep);
1159 if (name != NULL)
1160 return (dns_name_copy(sdlziter->current->name, name, NULL));
1161 return (ISC_R_SUCCESS);
1164 static isc_result_t
1165 dbiterator_pause(dns_dbiterator_t *iterator) {
1166 UNUSED(iterator);
1167 return (ISC_R_SUCCESS);
1170 static isc_result_t
1171 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1172 UNUSED(iterator);
1173 return (dns_name_copy(dns_rootname, name, NULL));
1177 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1178 * interface. See the SDB driver interface documentation for more info.
1181 static void
1182 disassociate(dns_rdataset_t *rdataset) {
1183 dns_dbnode_t *node = rdataset->private5;
1184 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1185 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1187 detachnode(db, &node);
1188 isc__rdatalist_disassociate(rdataset);
1191 static void
1192 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1193 dns_dbnode_t *node = source->private5;
1194 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1195 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1196 dns_dbnode_t *tempdb = NULL;
1198 isc__rdatalist_clone(source, target);
1199 attachnode(db, node, &tempdb);
1200 source->private5 = tempdb;
1203 static dns_rdatasetmethods_t rdataset_methods = {
1204 disassociate,
1205 isc__rdatalist_first,
1206 isc__rdatalist_next,
1207 isc__rdatalist_current,
1208 rdataset_clone,
1209 isc__rdatalist_count,
1210 isc__rdatalist_addnoqname,
1211 isc__rdatalist_getnoqname,
1212 NULL,
1213 NULL,
1214 NULL,
1215 NULL,
1216 NULL
1219 static void
1220 list_tordataset(dns_rdatalist_t *rdatalist,
1221 dns_db_t *db, dns_dbnode_t *node,
1222 dns_rdataset_t *rdataset)
1225 * The sdlz rdataset is an rdatalist with some additions.
1226 * - private1 & private2 are used by the rdatalist.
1227 * - private3 & private 4 are unused.
1228 * - private5 is the node.
1231 /* This should never fail. */
1232 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1233 ISC_R_SUCCESS);
1235 rdataset->methods = &rdataset_methods;
1236 dns_db_attachnode(db, node, &rdataset->private5);
1240 * SDLZ core methods. This is the core of the new DLZ functionality.
1244 * Build a 'bind' database driver structure to be returned by
1245 * either the find zone or the allow zone transfer method.
1246 * This method is only available in this source file, it is
1247 * not made available anywhere else.
1250 static isc_result_t
1251 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1252 dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
1254 isc_result_t result;
1255 dns_sdlz_db_t *sdlzdb;
1256 dns_sdlzimplementation_t *imp;
1258 /* check that things are as we expect */
1259 REQUIRE(dbp != NULL && *dbp == NULL);
1260 REQUIRE(name != NULL);
1262 imp = (dns_sdlzimplementation_t *) driverarg;
1264 /* allocate and zero memory for driver structure */
1265 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1266 if (sdlzdb == NULL)
1267 return (ISC_R_NOMEMORY);
1268 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1270 /* initialize and set origin */
1271 dns_name_init(&sdlzdb->common.origin, NULL);
1272 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1273 if (result != ISC_R_SUCCESS)
1274 goto mem_cleanup;
1276 /* initialize the reference count mutex */
1277 result = isc_mutex_init(&sdlzdb->refcnt_lock);
1278 if (result != ISC_R_SUCCESS)
1279 goto name_cleanup;
1281 /* set the rest of the database structure attributes */
1282 sdlzdb->dlzimp = imp;
1283 sdlzdb->common.methods = &sdlzdb_methods;
1284 sdlzdb->common.attributes = 0;
1285 sdlzdb->common.rdclass = rdclass;
1286 sdlzdb->common.mctx = NULL;
1287 sdlzdb->dbdata = dbdata;
1288 sdlzdb->references = 1;
1290 /* attach to the memory context */
1291 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1293 /* mark structure as valid */
1294 sdlzdb->common.magic = DNS_DB_MAGIC;
1295 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1296 *dbp = (dns_db_t *) sdlzdb;
1298 return (result);
1301 * reference count mutex could not be initialized, clean up
1302 * name memory
1304 name_cleanup:
1305 dns_name_free(&sdlzdb->common.origin, mctx);
1306 mem_cleanup:
1307 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1308 return (result);
1311 static isc_result_t
1312 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1313 dns_rdataclass_t rdclass, dns_name_t *name,
1314 isc_sockaddr_t *clientaddr, dns_db_t **dbp)
1316 isc_buffer_t b;
1317 isc_buffer_t b2;
1318 char namestr[DNS_NAME_MAXTEXT + 1];
1319 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1320 + 1];
1321 isc_netaddr_t netaddr;
1322 isc_result_t result;
1323 dns_sdlzimplementation_t *imp;
1326 * Perform checks to make sure data is as we expect it to be.
1328 REQUIRE(driverarg != NULL);
1329 REQUIRE(name != NULL);
1330 REQUIRE(clientaddr != NULL);
1331 REQUIRE(dbp != NULL && *dbp == NULL);
1333 imp = (dns_sdlzimplementation_t *) driverarg;
1335 /* Convert DNS name to ascii text */
1336 isc_buffer_init(&b, namestr, sizeof(namestr));
1337 result = dns_name_totext(name, ISC_TRUE, &b);
1338 if (result != ISC_R_SUCCESS)
1339 return (result);
1340 isc_buffer_putuint8(&b, 0);
1342 /* convert client address to ascii text */
1343 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1344 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1345 result = isc_netaddr_totext(&netaddr, &b2);
1346 if (result != ISC_R_SUCCESS)
1347 return (result);
1348 isc_buffer_putuint8(&b2, 0);
1350 /* make sure strings are always lowercase */
1351 dns_sdlz_tolower(namestr);
1352 dns_sdlz_tolower(clientstr);
1354 /* Call SDLZ driver's find zone method */
1355 if (imp->methods->allowzonexfr != NULL) {
1356 MAYBE_LOCK(imp);
1357 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1358 namestr, clientstr);
1359 MAYBE_UNLOCK(imp);
1361 * if zone is supported and transfers allowed build a 'bind'
1362 * database driver
1364 if (result == ISC_R_SUCCESS)
1365 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1366 name, rdclass, dbp);
1367 return (result);
1370 return (ISC_R_NOTIMPLEMENTED);
1373 static isc_result_t
1374 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1375 char *argv[], void *driverarg, void **dbdata)
1377 dns_sdlzimplementation_t *imp;
1378 isc_result_t result = ISC_R_NOTFOUND;
1380 /* Write debugging message to log */
1381 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1382 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1383 "Loading SDLZ driver.");
1386 * Performs checks to make sure data is as we expect it to be.
1388 REQUIRE(driverarg != NULL);
1389 REQUIRE(dlzname != NULL);
1390 REQUIRE(dbdata != NULL);
1391 UNUSED(mctx);
1393 imp = driverarg;
1395 /* If the create method exists, call it. */
1396 if (imp->methods->create != NULL) {
1397 MAYBE_LOCK(imp);
1398 result = imp->methods->create(dlzname, argc, argv,
1399 imp->driverarg, dbdata);
1400 MAYBE_UNLOCK(imp);
1403 /* Write debugging message to log */
1404 if (result == ISC_R_SUCCESS) {
1405 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1406 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1407 "SDLZ driver loaded successfully.");
1408 } else {
1409 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1410 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1411 "SDLZ driver failed to load.");
1414 return (result);
1417 static void
1418 dns_sdlzdestroy(void *driverdata, void **dbdata)
1421 dns_sdlzimplementation_t *imp;
1423 /* Write debugging message to log */
1424 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1425 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1426 "Unloading SDLZ driver.");
1428 imp = driverdata;
1430 /* If the destroy method exists, call it. */
1431 if (imp->methods->destroy != NULL) {
1432 MAYBE_LOCK(imp);
1433 imp->methods->destroy(imp->driverarg, dbdata);
1434 MAYBE_UNLOCK(imp);
1438 static isc_result_t
1439 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1440 dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
1442 isc_buffer_t b;
1443 char namestr[DNS_NAME_MAXTEXT + 1];
1444 isc_result_t result;
1445 dns_sdlzimplementation_t *imp;
1448 * Perform checks to make sure data is as we expect it to be.
1450 REQUIRE(driverarg != NULL);
1451 REQUIRE(name != NULL);
1452 REQUIRE(dbp != NULL && *dbp == NULL);
1454 imp = (dns_sdlzimplementation_t *) driverarg;
1456 /* Convert DNS name to ascii text */
1457 isc_buffer_init(&b, namestr, sizeof(namestr));
1458 result = dns_name_totext(name, ISC_TRUE, &b);
1459 if (result != ISC_R_SUCCESS)
1460 return (result);
1461 isc_buffer_putuint8(&b, 0);
1463 /* make sure strings are always lowercase */
1464 dns_sdlz_tolower(namestr);
1466 /* Call SDLZ driver's find zone method */
1467 MAYBE_LOCK(imp);
1468 result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
1469 MAYBE_UNLOCK(imp);
1472 * if zone is supported build a 'bind' database driver
1473 * structure to return
1475 if (result == ISC_R_SUCCESS)
1476 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1477 rdclass, dbp);
1479 return (result);
1482 static dns_dlzmethods_t sdlzmethods = {
1483 dns_sdlzcreate,
1484 dns_sdlzdestroy,
1485 dns_sdlzfindzone,
1486 dns_sdlzallowzonexfr
1490 * Public functions.
1493 isc_result_t
1494 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1495 const char *data)
1497 dns_rdatalist_t *rdatalist;
1498 dns_rdata_t *rdata;
1499 dns_rdatatype_t typeval;
1500 isc_consttextregion_t r;
1501 isc_buffer_t b;
1502 isc_buffer_t *rdatabuf = NULL;
1503 isc_lex_t *lex;
1504 isc_result_t result;
1505 unsigned int size;
1506 isc_mem_t *mctx;
1507 dns_name_t *origin;
1509 REQUIRE(VALID_SDLZLOOKUP(lookup));
1510 REQUIRE(type != NULL);
1511 REQUIRE(data != NULL);
1513 mctx = lookup->sdlz->common.mctx;
1515 r.base = type;
1516 r.length = strlen(type);
1517 result = dns_rdatatype_fromtext(&typeval, (void *) &r);
1518 if (result != ISC_R_SUCCESS)
1519 return (result);
1521 rdatalist = ISC_LIST_HEAD(lookup->lists);
1522 while (rdatalist != NULL) {
1523 if (rdatalist->type == typeval)
1524 break;
1525 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1528 if (rdatalist == NULL) {
1529 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1530 if (rdatalist == NULL)
1531 return (ISC_R_NOMEMORY);
1532 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1533 rdatalist->type = typeval;
1534 rdatalist->covers = 0;
1535 rdatalist->ttl = ttl;
1536 ISC_LIST_INIT(rdatalist->rdata);
1537 ISC_LINK_INIT(rdatalist, link);
1538 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1539 } else
1540 if (rdatalist->ttl != ttl)
1541 return (DNS_R_BADTTL);
1543 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1544 if (rdata == NULL)
1545 return (ISC_R_NOMEMORY);
1546 dns_rdata_init(rdata);
1548 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1549 origin = &lookup->sdlz->common.origin;
1550 else
1551 origin = dns_rootname;
1553 lex = NULL;
1554 result = isc_lex_create(mctx, 64, &lex);
1555 if (result != ISC_R_SUCCESS)
1556 goto failure;
1558 size = initial_size(data);
1559 do {
1560 isc_buffer_init(&b, data, strlen(data));
1561 isc_buffer_add(&b, strlen(data));
1563 result = isc_lex_openbuffer(lex, &b);
1564 if (result != ISC_R_SUCCESS)
1565 goto failure;
1567 rdatabuf = NULL;
1568 result = isc_buffer_allocate(mctx, &rdatabuf, size);
1569 if (result != ISC_R_SUCCESS)
1570 goto failure;
1572 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1573 rdatalist->type, lex,
1574 origin, ISC_FALSE,
1575 mctx, rdatabuf,
1576 &lookup->callbacks);
1577 if (result != ISC_R_SUCCESS)
1578 isc_buffer_free(&rdatabuf);
1579 size *= 2;
1580 } while (result == ISC_R_NOSPACE);
1582 if (result != ISC_R_SUCCESS)
1583 goto failure;
1585 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1586 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1588 if (lex != NULL)
1589 isc_lex_destroy(&lex);
1591 return (ISC_R_SUCCESS);
1593 failure:
1594 if (rdatabuf != NULL)
1595 isc_buffer_free(&rdatabuf);
1596 if (lex != NULL)
1597 isc_lex_destroy(&lex);
1598 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1600 return (result);
1603 isc_result_t
1604 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1605 const char *type, dns_ttl_t ttl, const char *data)
1607 dns_name_t *newname, *origin;
1608 dns_fixedname_t fnewname;
1609 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1610 dns_sdlznode_t *sdlznode;
1611 isc_mem_t *mctx = sdlz->common.mctx;
1612 isc_buffer_t b;
1613 isc_result_t result;
1615 dns_fixedname_init(&fnewname);
1616 newname = dns_fixedname_name(&fnewname);
1618 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1619 origin = &sdlz->common.origin;
1620 else
1621 origin = dns_rootname;
1622 isc_buffer_init(&b, name, strlen(name));
1623 isc_buffer_add(&b, strlen(name));
1625 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1626 if (result != ISC_R_SUCCESS)
1627 return (result);
1629 if (allnodes->common.relative_names) {
1630 /* All names are relative to the root */
1631 unsigned int nlabels = dns_name_countlabels(newname);
1632 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1635 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1636 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1637 sdlznode = NULL;
1638 result = createnode(sdlz, &sdlznode);
1639 if (result != ISC_R_SUCCESS)
1640 return (result);
1641 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1642 if (sdlznode->name == NULL) {
1643 destroynode(sdlznode);
1644 return (ISC_R_NOMEMORY);
1646 dns_name_init(sdlznode->name, NULL);
1647 result = dns_name_dup(newname, mctx, sdlznode->name);
1648 if (result != ISC_R_SUCCESS) {
1649 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
1650 destroynode(sdlznode);
1651 return (result);
1653 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1654 if (allnodes->origin == NULL &&
1655 dns_name_equal(newname, &sdlz->common.origin))
1656 allnodes->origin = sdlznode;
1658 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1662 isc_result_t
1663 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1664 isc_uint32_t serial)
1666 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1667 int n;
1669 REQUIRE(mname != NULL);
1670 REQUIRE(rname != NULL);
1672 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
1673 mname, rname, serial,
1674 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1675 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1676 if (n >= (int)sizeof(str) || n < 0)
1677 return (ISC_R_NOSPACE);
1678 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1681 isc_result_t
1682 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1683 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1684 dns_sdlzimplementation_t **sdlzimp)
1687 dns_sdlzimplementation_t *imp;
1688 isc_result_t result;
1691 * Performs checks to make sure data is as we expect it to be.
1693 REQUIRE(drivername != NULL);
1694 REQUIRE(methods != NULL);
1695 REQUIRE(methods->findzone != NULL);
1696 REQUIRE(methods->lookup != NULL);
1697 REQUIRE(mctx != NULL);
1698 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
1699 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
1700 DNS_SDLZFLAG_RELATIVERDATA |
1701 DNS_SDLZFLAG_THREADSAFE)) == 0);
1703 /* Write debugging message to log */
1704 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1705 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1706 "Registering SDLZ driver '%s'", drivername);
1709 * Allocate memory for a sdlz_implementation object. Error if
1710 * we cannot.
1712 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
1713 if (imp == NULL)
1714 return (ISC_R_NOMEMORY);
1716 /* Make sure memory region is set to all 0's */
1717 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
1719 /* Store the data passed into this method */
1720 imp->methods = methods;
1721 imp->driverarg = driverarg;
1722 imp->flags = flags;
1723 imp->mctx = NULL;
1725 /* attach the new sdlz_implementation object to a memory context */
1726 isc_mem_attach(mctx, &imp->mctx);
1729 * initialize the driver lock, error if we cannot
1730 * (used if a driver does not support multiple threads)
1732 result = isc_mutex_init(&imp->driverlock);
1733 if (result != ISC_R_SUCCESS) {
1734 UNEXPECTED_ERROR(__FILE__, __LINE__,
1735 "isc_mutex_init() failed: %s",
1736 isc_result_totext(result));
1737 goto cleanup_mctx;
1740 imp->dlz_imp = NULL;
1743 * register the DLZ driver. Pass in our "extra" sdlz information as
1744 * a driverarg. (that's why we stored the passed in driver arg in our
1745 * sdlz_implementation structure) Also, store the dlz_implementation
1746 * structure in our sdlz_implementation.
1748 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
1749 &imp->dlz_imp);
1751 /* if registration fails, cleanup and get outta here. */
1752 if (result != ISC_R_SUCCESS)
1753 goto cleanup_mutex;
1755 *sdlzimp = imp;
1757 return (ISC_R_SUCCESS);
1759 cleanup_mutex:
1760 /* destroy the driver lock, we don't need it anymore */
1761 DESTROYLOCK(&imp->driverlock);
1763 cleanup_mctx:
1765 * return the memory back to the available memory pool and
1766 * remove it from the memory context.
1768 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1769 isc_mem_detach(&mctx);
1770 return (result);
1773 void
1774 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
1775 dns_sdlzimplementation_t *imp;
1776 isc_mem_t *mctx;
1778 /* Write debugging message to log */
1779 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1780 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1781 "Unregistering SDLZ driver.");
1784 * Performs checks to make sure data is as we expect it to be.
1786 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
1788 imp = *sdlzimp;
1790 /* Unregister the DLZ driver implementation */
1791 dns_dlzunregister(&imp->dlz_imp);
1793 /* destroy the driver lock, we don't need it anymore */
1794 DESTROYLOCK(&imp->driverlock);
1796 mctx = imp->mctx;
1799 * return the memory back to the available memory pool and
1800 * remove it from the memory context.
1802 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1803 isc_mem_detach(&mctx);
1805 *sdlzimp = NULL;