vendor/BIND: Update to 9.5.2-P3
[dragonfly.git] / contrib / bind / lib / dns / sdlz.c
blob60fe69bd9e7eb2250c454f4fa075d13bff943e1e
1 /*
2 * Portions Copyright (C) 2005-2010 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2001 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
19 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
21 * Permission to use, copy, modify, and distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the
23 * above copyright notice and this permission notice appear in all
24 * copies.
26 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
27 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
29 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
30 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
31 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
32 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
33 * USE OR PERFORMANCE OF THIS SOFTWARE.
35 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
36 * conceived and contributed by Rob Butler.
38 * Permission to use, copy, modify, and distribute this software for any
39 * purpose with or without fee is hereby granted, provided that the
40 * above copyright notice and this permission notice appear in all
41 * copies.
43 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
44 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
46 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
47 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
48 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
49 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
50 * USE OR PERFORMANCE OF THIS SOFTWARE.
53 /* $Id: sdlz.c,v 1.14.94.6.2.2 2010/02/25 10:56:02 tbox Exp $ */
55 /*! \file */
57 #include <config.h>
58 #include <string.h>
60 #include <isc/buffer.h>
61 #include <isc/lex.h>
62 #include <isc/log.h>
63 #include <isc/rwlock.h>
64 #include <isc/string.h>
65 #include <isc/util.h>
66 #include <isc/magic.h>
67 #include <isc/mem.h>
68 #include <isc/once.h>
69 #include <isc/print.h>
70 #include <isc/region.h>
72 #include <dns/callbacks.h>
73 #include <dns/db.h>
74 #include <dns/dbiterator.h>
75 #include <dns/dlz.h>
76 #include <dns/fixedname.h>
77 #include <dns/log.h>
78 #include <dns/rdata.h>
79 #include <dns/rdatalist.h>
80 #include <dns/rdataset.h>
81 #include <dns/rdatasetiter.h>
82 #include <dns/rdatatype.h>
83 #include <dns/result.h>
84 #include <dns/master.h>
85 #include <dns/sdlz.h>
86 #include <dns/types.h>
88 #include "rdatalist_p.h"
91 * Private Types
94 struct dns_sdlzimplementation {
95 const dns_sdlzmethods_t *methods;
96 isc_mem_t *mctx;
97 void *driverarg;
98 unsigned int flags;
99 isc_mutex_t driverlock;
100 dns_dlzimplementation_t *dlz_imp;
103 struct dns_sdlz_db {
104 /* Unlocked */
105 dns_db_t common;
106 void *dbdata;
107 dns_sdlzimplementation_t *dlzimp;
108 isc_mutex_t refcnt_lock;
109 /* Locked */
110 unsigned int references;
113 struct dns_sdlzlookup {
114 /* Unlocked */
115 unsigned int magic;
116 dns_sdlz_db_t *sdlz;
117 ISC_LIST(dns_rdatalist_t) lists;
118 ISC_LIST(isc_buffer_t) buffers;
119 dns_name_t *name;
120 ISC_LINK(dns_sdlzlookup_t) link;
121 isc_mutex_t lock;
122 dns_rdatacallbacks_t callbacks;
123 /* Locked */
124 unsigned int references;
127 typedef struct dns_sdlzlookup dns_sdlznode_t;
129 struct dns_sdlzallnodes {
130 dns_dbiterator_t common;
131 ISC_LIST(dns_sdlznode_t) nodelist;
132 dns_sdlznode_t *current;
133 dns_sdlznode_t *origin;
136 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
138 typedef struct sdlz_rdatasetiter {
139 dns_rdatasetiter_t common;
140 dns_rdatalist_t *current;
141 } sdlz_rdatasetiter_t;
144 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
147 * Note that "impmagic" is not the first four bytes of the struct, so
148 * ISC_MAGIC_VALID cannot be used.
151 #define VALID_SDLZDB(sdlzdb) ((sdlzdb) != NULL && \
152 (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
154 #define SDLZLOOKUP_MAGIC ISC_MAGIC('D','L','Z','L')
155 #define VALID_SDLZLOOKUP(sdlzl) ISC_MAGIC_VALID(sdlzl, SDLZLOOKUP_MAGIC)
156 #define VALID_SDLZNODE(sdlzn) VALID_SDLZLOOKUP(sdlzn)
158 /* These values are taken from RFC 1537 */
159 #define SDLZ_DEFAULT_REFRESH (60 * 60 * 8)
160 #define SDLZ_DEFAULT_RETRY (60 * 60 * 2)
161 #define SDLZ_DEFAULT_EXPIRE (60 * 60 * 24 * 7)
162 #define SDLZ_DEFAULT_MINIMUM (60 * 60 * 24)
164 /* This is a reasonable value */
165 #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
167 static int dummy;
169 #ifdef __COVERITY__
170 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
171 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
172 #else
173 #define MAYBE_LOCK(imp) \
174 do { \
175 unsigned int flags = imp->flags; \
176 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
177 LOCK(&imp->driverlock); \
178 } while (0)
180 #define MAYBE_UNLOCK(imp) \
181 do { \
182 unsigned int flags = imp->flags; \
183 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
184 UNLOCK(&imp->driverlock); \
185 } while (0)
186 #endif
189 * Forward references. Try to keep these to a minimum.
192 static void list_tordataset(dns_rdatalist_t *rdatalist,
193 dns_db_t *db, dns_dbnode_t *node,
194 dns_rdataset_t *rdataset);
196 static void detachnode(dns_db_t *db, dns_dbnode_t **targetp);
198 static void dbiterator_destroy(dns_dbiterator_t **iteratorp);
199 static isc_result_t dbiterator_first(dns_dbiterator_t *iterator);
200 static isc_result_t dbiterator_last(dns_dbiterator_t *iterator);
201 static isc_result_t dbiterator_seek(dns_dbiterator_t *iterator,
202 dns_name_t *name);
203 static isc_result_t dbiterator_prev(dns_dbiterator_t *iterator);
204 static isc_result_t dbiterator_next(dns_dbiterator_t *iterator);
205 static isc_result_t dbiterator_current(dns_dbiterator_t *iterator,
206 dns_dbnode_t **nodep,
207 dns_name_t *name);
208 static isc_result_t dbiterator_pause(dns_dbiterator_t *iterator);
209 static isc_result_t dbiterator_origin(dns_dbiterator_t *iterator,
210 dns_name_t *name);
212 static dns_dbiteratormethods_t dbiterator_methods = {
213 dbiterator_destroy,
214 dbiterator_first,
215 dbiterator_last,
216 dbiterator_seek,
217 dbiterator_prev,
218 dbiterator_next,
219 dbiterator_current,
220 dbiterator_pause,
221 dbiterator_origin
225 * Utility functions
228 /*% Converts the input string to lowercase, in place. */
230 static void
231 dns_sdlz_tolower(char *str) {
233 unsigned int len = strlen(str);
234 unsigned int i;
236 for (i = 0; i < len; i++) {
237 if (str[i] >= 'A' && str[i] <= 'Z')
238 str[i] += 32;
243 static inline unsigned int
244 initial_size(const char *data) {
245 unsigned int len = (strlen(data) / 64) + 1;
246 return (len * 64 + 64);
250 * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
251 * driver interface. See the SDB driver interface documentation for more info.
254 static void
255 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
256 sdlz_rdatasetiter_t *sdlziterator =
257 (sdlz_rdatasetiter_t *)(*iteratorp);
259 detachnode(sdlziterator->common.db, &sdlziterator->common.node);
260 isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
261 sizeof(sdlz_rdatasetiter_t));
262 *iteratorp = NULL;
265 static isc_result_t
266 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
267 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
268 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
270 if (ISC_LIST_EMPTY(sdlznode->lists))
271 return (ISC_R_NOMORE);
272 sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
273 return (ISC_R_SUCCESS);
276 static isc_result_t
277 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
278 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
280 sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
281 if (sdlziterator->current == NULL)
282 return (ISC_R_NOMORE);
283 else
284 return (ISC_R_SUCCESS);
287 static void
288 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
289 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
291 list_tordataset(sdlziterator->current, iterator->db, iterator->node,
292 rdataset);
295 static dns_rdatasetitermethods_t rdatasetiter_methods = {
296 rdatasetiter_destroy,
297 rdatasetiter_first,
298 rdatasetiter_next,
299 rdatasetiter_current
303 * DB routines. These methods were "borrowed" from the SDB driver interface.
304 * See the SDB driver interface documentation for more info.
307 static void
308 attach(dns_db_t *source, dns_db_t **targetp) {
309 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) source;
311 REQUIRE(VALID_SDLZDB(sdlz));
313 LOCK(&sdlz->refcnt_lock);
314 REQUIRE(sdlz->references > 0);
315 sdlz->references++;
316 UNLOCK(&sdlz->refcnt_lock);
318 *targetp = source;
321 static void
322 destroy(dns_sdlz_db_t *sdlz) {
323 isc_mem_t *mctx;
324 mctx = sdlz->common.mctx;
326 sdlz->common.magic = 0;
327 sdlz->common.impmagic = 0;
329 isc_mutex_destroy(&sdlz->refcnt_lock);
331 dns_name_free(&sdlz->common.origin, mctx);
333 isc_mem_put(mctx, sdlz, sizeof(dns_sdlz_db_t));
334 isc_mem_detach(&mctx);
337 static void
338 detach(dns_db_t **dbp) {
339 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
340 isc_boolean_t need_destroy = ISC_FALSE;
342 REQUIRE(VALID_SDLZDB(sdlz));
343 LOCK(&sdlz->refcnt_lock);
344 REQUIRE(sdlz->references > 0);
345 sdlz->references--;
346 if (sdlz->references == 0)
347 need_destroy = ISC_TRUE;
348 UNLOCK(&sdlz->refcnt_lock);
350 if (need_destroy)
351 destroy(sdlz);
353 *dbp = NULL;
356 static isc_result_t
357 beginload(dns_db_t *db, dns_addrdatasetfunc_t *addp, dns_dbload_t **dbloadp) {
358 UNUSED(db);
359 UNUSED(addp);
360 UNUSED(dbloadp);
361 return (ISC_R_NOTIMPLEMENTED);
364 static isc_result_t
365 endload(dns_db_t *db, dns_dbload_t **dbloadp) {
366 UNUSED(db);
367 UNUSED(dbloadp);
368 return (ISC_R_NOTIMPLEMENTED);
371 static isc_result_t
372 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
373 dns_masterformat_t masterformat)
375 UNUSED(db);
376 UNUSED(version);
377 UNUSED(filename);
378 UNUSED(masterformat);
379 return (ISC_R_NOTIMPLEMENTED);
382 static void
383 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
384 REQUIRE(versionp != NULL && *versionp == NULL);
386 UNUSED(db);
388 *versionp = (void *) &dummy;
389 return;
392 static isc_result_t
393 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
394 UNUSED(db);
395 UNUSED(versionp);
397 return (ISC_R_NOTIMPLEMENTED);
400 static void
401 attachversion(dns_db_t *db, dns_dbversion_t *source,
402 dns_dbversion_t **targetp)
404 REQUIRE(source != NULL && source == (void *) &dummy);
406 UNUSED(db);
407 UNUSED(source);
408 UNUSED(targetp);
409 *targetp = source;
412 static void
413 closeversion(dns_db_t *db, dns_dbversion_t **versionp, isc_boolean_t commit) {
414 REQUIRE(versionp != NULL && *versionp == (void *) &dummy);
415 REQUIRE(commit == ISC_FALSE);
417 UNUSED(db);
418 UNUSED(commit);
420 *versionp = NULL;
423 static isc_result_t
424 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
425 dns_sdlznode_t *node;
426 isc_result_t result;
428 node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
429 if (node == NULL)
430 return (ISC_R_NOMEMORY);
432 node->sdlz = NULL;
433 attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
434 ISC_LIST_INIT(node->lists);
435 ISC_LIST_INIT(node->buffers);
436 ISC_LINK_INIT(node, link);
437 node->name = NULL;
438 result = isc_mutex_init(&node->lock);
439 if (result != ISC_R_SUCCESS) {
440 UNEXPECTED_ERROR(__FILE__, __LINE__,
441 "isc_mutex_init() failed: %s",
442 isc_result_totext(result));
443 isc_mem_put(sdlz->common.mctx, node, sizeof(dns_sdlznode_t));
444 return (ISC_R_UNEXPECTED);
446 dns_rdatacallbacks_init(&node->callbacks);
447 node->references = 1;
448 node->magic = SDLZLOOKUP_MAGIC;
450 *nodep = node;
451 return (ISC_R_SUCCESS);
454 static void
455 destroynode(dns_sdlznode_t *node) {
456 dns_rdatalist_t *list;
457 dns_rdata_t *rdata;
458 isc_buffer_t *b;
459 dns_sdlz_db_t *sdlz;
460 dns_db_t *db;
461 isc_mem_t *mctx;
463 sdlz = node->sdlz;
464 mctx = sdlz->common.mctx;
466 while (!ISC_LIST_EMPTY(node->lists)) {
467 list = ISC_LIST_HEAD(node->lists);
468 while (!ISC_LIST_EMPTY(list->rdata)) {
469 rdata = ISC_LIST_HEAD(list->rdata);
470 ISC_LIST_UNLINK(list->rdata, rdata, link);
471 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
473 ISC_LIST_UNLINK(node->lists, list, link);
474 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
477 while (!ISC_LIST_EMPTY(node->buffers)) {
478 b = ISC_LIST_HEAD(node->buffers);
479 ISC_LIST_UNLINK(node->buffers, b, link);
480 isc_buffer_free(&b);
483 if (node->name != NULL) {
484 dns_name_free(node->name, mctx);
485 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
487 DESTROYLOCK(&node->lock);
488 node->magic = 0;
489 isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
490 db = &sdlz->common;
491 detach(&db);
494 static isc_result_t
495 findnode(dns_db_t *db, dns_name_t *name, isc_boolean_t create,
496 dns_dbnode_t **nodep)
498 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
499 dns_sdlznode_t *node = NULL;
500 isc_result_t result;
501 isc_buffer_t b;
502 char namestr[DNS_NAME_MAXTEXT + 1];
503 isc_buffer_t b2;
504 char zonestr[DNS_NAME_MAXTEXT + 1];
505 isc_boolean_t isorigin;
506 dns_sdlzauthorityfunc_t authority;
508 REQUIRE(VALID_SDLZDB(sdlz));
509 REQUIRE(create == ISC_FALSE);
510 REQUIRE(nodep != NULL && *nodep == NULL);
512 UNUSED(name);
513 UNUSED(create);
515 isc_buffer_init(&b, namestr, sizeof(namestr));
516 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
517 dns_name_t relname;
518 unsigned int labels;
520 labels = dns_name_countlabels(name) -
521 dns_name_countlabels(&db->origin);
522 dns_name_init(&relname, NULL);
523 dns_name_getlabelsequence(name, 0, labels, &relname);
524 result = dns_name_totext(&relname, ISC_TRUE, &b);
525 if (result != ISC_R_SUCCESS)
526 return (result);
527 } else {
528 result = dns_name_totext(name, ISC_TRUE, &b);
529 if (result != ISC_R_SUCCESS)
530 return (result);
532 isc_buffer_putuint8(&b, 0);
534 isc_buffer_init(&b2, zonestr, sizeof(zonestr));
535 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b2);
536 if (result != ISC_R_SUCCESS)
537 return (result);
538 isc_buffer_putuint8(&b2, 0);
540 result = createnode(sdlz, &node);
541 if (result != ISC_R_SUCCESS)
542 return (result);
544 isorigin = dns_name_equal(name, &sdlz->common.origin);
546 /* make sure strings are always lowercase */
547 dns_sdlz_tolower(zonestr);
548 dns_sdlz_tolower(namestr);
550 MAYBE_LOCK(sdlz->dlzimp);
552 /* try to lookup the host (namestr) */
553 result = sdlz->dlzimp->methods->lookup(zonestr, namestr,
554 sdlz->dlzimp->driverarg,
555 sdlz->dbdata, node);
558 * if the host (namestr) was not found, try to lookup a
559 * "wildcard" host.
561 if (result != ISC_R_SUCCESS) {
562 result = sdlz->dlzimp->methods->lookup(zonestr, "*",
563 sdlz->dlzimp->driverarg,
564 sdlz->dbdata, node);
567 MAYBE_UNLOCK(sdlz->dlzimp);
569 if (result != ISC_R_SUCCESS && !isorigin) {
570 destroynode(node);
571 return (result);
574 if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
575 MAYBE_LOCK(sdlz->dlzimp);
576 authority = sdlz->dlzimp->methods->authority;
577 result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
578 sdlz->dbdata, node);
579 MAYBE_UNLOCK(sdlz->dlzimp);
580 if (result != ISC_R_SUCCESS &&
581 result != ISC_R_NOTIMPLEMENTED) {
582 destroynode(node);
583 return (result);
587 *nodep = node;
588 return (ISC_R_SUCCESS);
591 static isc_result_t
592 findzonecut(dns_db_t *db, dns_name_t *name, unsigned int options,
593 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
594 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
596 UNUSED(db);
597 UNUSED(name);
598 UNUSED(options);
599 UNUSED(now);
600 UNUSED(nodep);
601 UNUSED(foundname);
602 UNUSED(rdataset);
603 UNUSED(sigrdataset);
605 return (ISC_R_NOTIMPLEMENTED);
608 static void
609 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
610 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
611 dns_sdlznode_t *node = (dns_sdlznode_t *)source;
613 REQUIRE(VALID_SDLZDB(sdlz));
615 UNUSED(sdlz);
617 LOCK(&node->lock);
618 INSIST(node->references > 0);
619 node->references++;
620 INSIST(node->references != 0); /* Catch overflow. */
621 UNLOCK(&node->lock);
623 *targetp = source;
626 static void
627 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
628 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
629 dns_sdlznode_t *node;
630 isc_boolean_t need_destroy = ISC_FALSE;
632 REQUIRE(VALID_SDLZDB(sdlz));
633 REQUIRE(targetp != NULL && *targetp != NULL);
635 UNUSED(sdlz);
637 node = (dns_sdlznode_t *)(*targetp);
639 LOCK(&node->lock);
640 INSIST(node->references > 0);
641 node->references--;
642 if (node->references == 0)
643 need_destroy = ISC_TRUE;
644 UNLOCK(&node->lock);
646 if (need_destroy)
647 destroynode(node);
649 *targetp = NULL;
652 static isc_result_t
653 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
654 UNUSED(db);
655 UNUSED(node);
656 UNUSED(now);
657 INSIST(0);
658 return (ISC_R_UNEXPECTED);
661 static void
662 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
663 UNUSED(db);
664 UNUSED(node);
665 UNUSED(out);
666 return;
669 static isc_result_t
670 createiterator(dns_db_t *db, isc_boolean_t relative_names,
671 dns_dbiterator_t **iteratorp)
673 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
674 sdlz_dbiterator_t *sdlziter;
675 isc_result_t result;
676 isc_buffer_t b;
677 char zonestr[DNS_NAME_MAXTEXT + 1];
679 REQUIRE(VALID_SDLZDB(sdlz));
681 if (sdlz->dlzimp->methods->allnodes == NULL)
682 return (ISC_R_NOTIMPLEMENTED);
684 isc_buffer_init(&b, zonestr, sizeof(zonestr));
685 result = dns_name_totext(&sdlz->common.origin, ISC_TRUE, &b);
686 if (result != ISC_R_SUCCESS)
687 return (result);
688 isc_buffer_putuint8(&b, 0);
690 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
691 if (sdlziter == NULL)
692 return (ISC_R_NOMEMORY);
694 sdlziter->common.methods = &dbiterator_methods;
695 sdlziter->common.db = NULL;
696 dns_db_attach(db, &sdlziter->common.db);
697 sdlziter->common.relative_names = relative_names;
698 sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
699 ISC_LIST_INIT(sdlziter->nodelist);
700 sdlziter->current = NULL;
701 sdlziter->origin = NULL;
703 /* make sure strings are always lowercase */
704 dns_sdlz_tolower(zonestr);
706 MAYBE_LOCK(sdlz->dlzimp);
707 result = sdlz->dlzimp->methods->allnodes(zonestr,
708 sdlz->dlzimp->driverarg,
709 sdlz->dbdata, sdlziter);
710 MAYBE_UNLOCK(sdlz->dlzimp);
711 if (result != ISC_R_SUCCESS) {
712 dns_dbiterator_t *iter = &sdlziter->common;
713 dbiterator_destroy(&iter);
714 return (result);
717 if (sdlziter->origin != NULL) {
718 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
719 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
722 *iteratorp = (dns_dbiterator_t *)sdlziter;
724 return (ISC_R_SUCCESS);
727 static isc_result_t
728 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
729 dns_rdatatype_t type, dns_rdatatype_t covers,
730 isc_stdtime_t now, dns_rdataset_t *rdataset,
731 dns_rdataset_t *sigrdataset)
733 dns_rdatalist_t *list;
734 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
736 REQUIRE(VALID_SDLZNODE(node));
738 UNUSED(db);
739 UNUSED(version);
740 UNUSED(covers);
741 UNUSED(now);
742 UNUSED(sigrdataset);
744 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
745 return (ISC_R_NOTIMPLEMENTED);
747 list = ISC_LIST_HEAD(sdlznode->lists);
748 while (list != NULL) {
749 if (list->type == type)
750 break;
751 list = ISC_LIST_NEXT(list, link);
753 if (list == NULL)
754 return (ISC_R_NOTFOUND);
756 list_tordataset(list, db, node, rdataset);
758 return (ISC_R_SUCCESS);
761 static isc_result_t
762 find(dns_db_t *db, dns_name_t *name, dns_dbversion_t *version,
763 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
764 dns_dbnode_t **nodep, dns_name_t *foundname,
765 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
767 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
768 dns_dbnode_t *node = NULL;
769 dns_fixedname_t fname;
770 dns_rdataset_t xrdataset;
771 dns_name_t *xname;
772 unsigned int nlabels, olabels;
773 isc_result_t result;
774 unsigned int i;
776 REQUIRE(VALID_SDLZDB(sdlz));
777 REQUIRE(nodep == NULL || *nodep == NULL);
778 REQUIRE(version == NULL || version == (void *) &dummy);
780 UNUSED(options);
781 UNUSED(sdlz);
783 if (!dns_name_issubdomain(name, &db->origin))
784 return (DNS_R_NXDOMAIN);
786 olabels = dns_name_countlabels(&db->origin);
787 nlabels = dns_name_countlabels(name);
789 dns_fixedname_init(&fname);
790 xname = dns_fixedname_name(&fname);
792 if (rdataset == NULL) {
793 dns_rdataset_init(&xrdataset);
794 rdataset = &xrdataset;
797 result = DNS_R_NXDOMAIN;
799 for (i = olabels; i <= nlabels; i++) {
801 * Unless this is an explicit lookup at the origin, don't
802 * look at the origin.
804 if (i == olabels && i != nlabels)
805 continue;
808 * Look up the next label.
810 dns_name_getlabelsequence(name, nlabels - i, i, xname);
811 result = findnode(db, xname, ISC_FALSE, &node);
812 if (result != ISC_R_SUCCESS) {
813 result = DNS_R_NXDOMAIN;
814 continue;
818 * Look for a DNAME at the current label, unless this is
819 * the qname.
821 if (i < nlabels) {
822 result = findrdataset(db, node, version,
823 dns_rdatatype_dname,
824 0, now, rdataset, sigrdataset);
825 if (result == ISC_R_SUCCESS) {
826 result = DNS_R_DNAME;
827 break;
832 * Look for an NS at the current label, unless this is the
833 * origin or glue is ok.
835 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
836 result = findrdataset(db, node, version,
837 dns_rdatatype_ns,
838 0, now, rdataset, sigrdataset);
839 if (result == ISC_R_SUCCESS) {
840 if (i == nlabels && type == dns_rdatatype_any)
842 result = DNS_R_ZONECUT;
843 dns_rdataset_disassociate(rdataset);
844 if (sigrdataset != NULL &&
845 dns_rdataset_isassociated
846 (sigrdataset)) {
847 dns_rdataset_disassociate
848 (sigrdataset);
850 } else
851 result = DNS_R_DELEGATION;
852 break;
857 * If the current name is not the qname, add another label
858 * and try again.
860 if (i < nlabels) {
861 destroynode(node);
862 node = NULL;
863 continue;
867 * If we're looking for ANY, we're done.
869 if (type == dns_rdatatype_any) {
870 result = ISC_R_SUCCESS;
871 break;
875 * Look for the qtype.
877 result = findrdataset(db, node, version, type,
878 0, now, rdataset, sigrdataset);
879 if (result == ISC_R_SUCCESS)
880 break;
883 * Look for a CNAME
885 if (type != dns_rdatatype_cname) {
886 result = findrdataset(db, node, version,
887 dns_rdatatype_cname,
888 0, now, rdataset, sigrdataset);
889 if (result == ISC_R_SUCCESS) {
890 result = DNS_R_CNAME;
891 break;
895 result = DNS_R_NXRRSET;
896 break;
899 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
900 dns_rdataset_disassociate(rdataset);
902 if (foundname != NULL) {
903 isc_result_t xresult;
905 xresult = dns_name_copy(xname, foundname, NULL);
906 if (xresult != ISC_R_SUCCESS) {
907 if (node != NULL)
908 destroynode(node);
909 if (dns_rdataset_isassociated(rdataset))
910 dns_rdataset_disassociate(rdataset);
911 return (DNS_R_BADDB);
915 if (nodep != NULL)
916 *nodep = node;
917 else if (node != NULL)
918 detachnode(db, &node);
920 return (result);
923 static isc_result_t
924 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
925 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
927 sdlz_rdatasetiter_t *iterator;
929 REQUIRE(version == NULL || version == &dummy);
931 UNUSED(version);
932 UNUSED(now);
934 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
935 if (iterator == NULL)
936 return (ISC_R_NOMEMORY);
938 iterator->common.magic = DNS_RDATASETITER_MAGIC;
939 iterator->common.methods = &rdatasetiter_methods;
940 iterator->common.db = db;
941 iterator->common.node = NULL;
942 attachnode(db, node, &iterator->common.node);
943 iterator->common.version = version;
944 iterator->common.now = now;
946 *iteratorp = (dns_rdatasetiter_t *)iterator;
948 return (ISC_R_SUCCESS);
951 static isc_result_t
952 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
953 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
954 dns_rdataset_t *addedrdataset)
956 UNUSED(db);
957 UNUSED(node);
958 UNUSED(version);
959 UNUSED(now);
960 UNUSED(rdataset);
961 UNUSED(options);
962 UNUSED(addedrdataset);
964 return (ISC_R_NOTIMPLEMENTED);
967 static isc_result_t
968 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
969 dns_rdataset_t *rdataset, unsigned int options,
970 dns_rdataset_t *newrdataset)
972 UNUSED(db);
973 UNUSED(node);
974 UNUSED(version);
975 UNUSED(rdataset);
976 UNUSED(options);
977 UNUSED(newrdataset);
979 return (ISC_R_NOTIMPLEMENTED);
982 static isc_result_t
983 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
984 dns_rdatatype_t type, dns_rdatatype_t covers)
986 UNUSED(db);
987 UNUSED(node);
988 UNUSED(version);
989 UNUSED(type);
990 UNUSED(covers);
992 return (ISC_R_NOTIMPLEMENTED);
995 static isc_boolean_t
996 issecure(dns_db_t *db) {
997 UNUSED(db);
999 return (ISC_FALSE);
1002 static unsigned int
1003 nodecount(dns_db_t *db) {
1004 UNUSED(db);
1006 return (0);
1009 static isc_boolean_t
1010 ispersistent(dns_db_t *db) {
1011 UNUSED(db);
1012 return (ISC_TRUE);
1015 static void
1016 overmem(dns_db_t *db, isc_boolean_t overmem) {
1017 UNUSED(db);
1018 UNUSED(overmem);
1021 static void
1022 settask(dns_db_t *db, isc_task_t *task) {
1023 UNUSED(db);
1024 UNUSED(task);
1028 static dns_dbmethods_t sdlzdb_methods = {
1029 attach,
1030 detach,
1031 beginload,
1032 endload,
1033 dump,
1034 currentversion,
1035 newversion,
1036 attachversion,
1037 closeversion,
1038 findnode,
1039 find,
1040 findzonecut,
1041 attachnode,
1042 detachnode,
1043 expirenode,
1044 printnode,
1045 createiterator,
1046 findrdataset,
1047 allrdatasets,
1048 addrdataset,
1049 subtractrdataset,
1050 deleterdataset,
1051 issecure,
1052 nodecount,
1053 ispersistent,
1054 overmem,
1055 settask,
1056 NULL,
1057 NULL,
1058 NULL
1062 * Database Iterator Methods. These methods were "borrowed" from the SDB
1063 * driver interface. See the SDB driver interface documentation for more info.
1066 static void
1067 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1068 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1069 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1071 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1072 dns_sdlznode_t *node;
1073 node = ISC_LIST_HEAD(sdlziter->nodelist);
1074 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1075 destroynode(node);
1078 dns_db_detach(&sdlziter->common.db);
1079 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1081 *iteratorp = NULL;
1084 static isc_result_t
1085 dbiterator_first(dns_dbiterator_t *iterator) {
1086 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1088 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1089 if (sdlziter->current == NULL)
1090 return (ISC_R_NOMORE);
1091 else
1092 return (ISC_R_SUCCESS);
1095 static isc_result_t
1096 dbiterator_last(dns_dbiterator_t *iterator) {
1097 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1099 sdlziter->current = ISC_LIST_TAIL(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_seek(dns_dbiterator_t *iterator, dns_name_t *name) {
1108 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1110 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1111 while (sdlziter->current != NULL) {
1112 if (dns_name_equal(sdlziter->current->name, name))
1113 return (ISC_R_SUCCESS);
1114 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1116 return (ISC_R_NOTFOUND);
1119 static isc_result_t
1120 dbiterator_prev(dns_dbiterator_t *iterator) {
1121 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1123 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1124 if (sdlziter->current == NULL)
1125 return (ISC_R_NOMORE);
1126 else
1127 return (ISC_R_SUCCESS);
1130 static isc_result_t
1131 dbiterator_next(dns_dbiterator_t *iterator) {
1132 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1134 sdlziter->current = ISC_LIST_NEXT(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_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1143 dns_name_t *name)
1145 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1147 attachnode(iterator->db, sdlziter->current, nodep);
1148 if (name != NULL)
1149 return (dns_name_copy(sdlziter->current->name, name, NULL));
1150 return (ISC_R_SUCCESS);
1153 static isc_result_t
1154 dbiterator_pause(dns_dbiterator_t *iterator) {
1155 UNUSED(iterator);
1156 return (ISC_R_SUCCESS);
1159 static isc_result_t
1160 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1161 UNUSED(iterator);
1162 return (dns_name_copy(dns_rootname, name, NULL));
1166 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1167 * interface. See the SDB driver interface documentation for more info.
1170 static void
1171 disassociate(dns_rdataset_t *rdataset) {
1172 dns_dbnode_t *node = rdataset->private5;
1173 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1174 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1176 detachnode(db, &node);
1177 isc__rdatalist_disassociate(rdataset);
1180 static void
1181 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1182 dns_dbnode_t *node = source->private5;
1183 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1184 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1185 dns_dbnode_t *tempdb = NULL;
1187 isc__rdatalist_clone(source, target);
1188 attachnode(db, node, &tempdb);
1189 source->private5 = tempdb;
1192 static dns_rdatasetmethods_t rdataset_methods = {
1193 disassociate,
1194 isc__rdatalist_first,
1195 isc__rdatalist_next,
1196 isc__rdatalist_current,
1197 rdataset_clone,
1198 isc__rdatalist_count,
1199 isc__rdatalist_addnoqname,
1200 isc__rdatalist_getnoqname,
1201 NULL,
1202 NULL,
1203 NULL,
1204 NULL,
1205 NULL
1208 static void
1209 list_tordataset(dns_rdatalist_t *rdatalist,
1210 dns_db_t *db, dns_dbnode_t *node,
1211 dns_rdataset_t *rdataset)
1214 * The sdlz rdataset is an rdatalist with some additions.
1215 * - private1 & private2 are used by the rdatalist.
1216 * - private3 & private 4 are unused.
1217 * - private5 is the node.
1220 /* This should never fail. */
1221 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1222 ISC_R_SUCCESS);
1224 rdataset->methods = &rdataset_methods;
1225 dns_db_attachnode(db, node, &rdataset->private5);
1229 * SDLZ core methods. This is the core of the new DLZ functionality.
1233 * Build a 'bind' database driver structure to be returned by
1234 * either the find zone or the allow zone transfer method.
1235 * This method is only available in this source file, it is
1236 * not made available anywhere else.
1239 static isc_result_t
1240 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1241 dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
1243 isc_result_t result;
1244 dns_sdlz_db_t *sdlzdb;
1245 dns_sdlzimplementation_t *imp;
1247 /* check that things are as we expect */
1248 REQUIRE(dbp != NULL && *dbp == NULL);
1249 REQUIRE(name != NULL);
1251 imp = (dns_sdlzimplementation_t *) driverarg;
1253 /* allocate and zero memory for driver structure */
1254 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1255 if (sdlzdb == NULL)
1256 return (ISC_R_NOMEMORY);
1257 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1259 /* initialize and set origin */
1260 dns_name_init(&sdlzdb->common.origin, NULL);
1261 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1262 if (result != ISC_R_SUCCESS)
1263 goto mem_cleanup;
1265 /* initialize the reference count mutex */
1266 result = isc_mutex_init(&sdlzdb->refcnt_lock);
1267 if (result != ISC_R_SUCCESS)
1268 goto name_cleanup;
1270 /* set the rest of the database structure attributes */
1271 sdlzdb->dlzimp = imp;
1272 sdlzdb->common.methods = &sdlzdb_methods;
1273 sdlzdb->common.attributes = 0;
1274 sdlzdb->common.rdclass = rdclass;
1275 sdlzdb->common.mctx = NULL;
1276 sdlzdb->dbdata = dbdata;
1277 sdlzdb->references = 1;
1279 /* attach to the memory context */
1280 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1282 /* mark structure as valid */
1283 sdlzdb->common.magic = DNS_DB_MAGIC;
1284 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1285 *dbp = (dns_db_t *) sdlzdb;
1287 return (result);
1290 * reference count mutex could not be initialized, clean up
1291 * name memory
1293 name_cleanup:
1294 dns_name_free(&sdlzdb->common.origin, mctx);
1295 mem_cleanup:
1296 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1297 return (result);
1300 static isc_result_t
1301 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1302 dns_rdataclass_t rdclass, dns_name_t *name,
1303 isc_sockaddr_t *clientaddr, dns_db_t **dbp)
1305 isc_buffer_t b;
1306 isc_buffer_t b2;
1307 char namestr[DNS_NAME_MAXTEXT + 1];
1308 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1309 + 1];
1310 isc_netaddr_t netaddr;
1311 isc_result_t result;
1312 dns_sdlzimplementation_t *imp;
1315 * Perform checks to make sure data is as we expect it to be.
1317 REQUIRE(driverarg != NULL);
1318 REQUIRE(name != NULL);
1319 REQUIRE(clientaddr != NULL);
1320 REQUIRE(dbp != NULL && *dbp == NULL);
1322 imp = (dns_sdlzimplementation_t *) driverarg;
1324 /* Convert DNS name to ascii text */
1325 isc_buffer_init(&b, namestr, sizeof(namestr));
1326 result = dns_name_totext(name, ISC_TRUE, &b);
1327 if (result != ISC_R_SUCCESS)
1328 return (result);
1329 isc_buffer_putuint8(&b, 0);
1331 /* convert client address to ascii text */
1332 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1333 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1334 result = isc_netaddr_totext(&netaddr, &b2);
1335 if (result != ISC_R_SUCCESS)
1336 return (result);
1337 isc_buffer_putuint8(&b2, 0);
1339 /* make sure strings are always lowercase */
1340 dns_sdlz_tolower(namestr);
1341 dns_sdlz_tolower(clientstr);
1343 /* Call SDLZ driver's find zone method */
1344 if (imp->methods->allowzonexfr != NULL) {
1345 MAYBE_LOCK(imp);
1346 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1347 namestr, clientstr);
1348 MAYBE_UNLOCK(imp);
1350 * if zone is supported and transfers allowed build a 'bind'
1351 * database driver
1353 if (result == ISC_R_SUCCESS)
1354 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1355 name, rdclass, dbp);
1356 return (result);
1359 return (ISC_R_NOTIMPLEMENTED);
1362 static isc_result_t
1363 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1364 char *argv[], void *driverarg, void **dbdata)
1366 dns_sdlzimplementation_t *imp;
1367 isc_result_t result = ISC_R_NOTFOUND;
1369 /* Write debugging message to log */
1370 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1371 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1372 "Loading SDLZ driver.");
1375 * Performs checks to make sure data is as we expect it to be.
1377 REQUIRE(driverarg != NULL);
1378 REQUIRE(dlzname != NULL);
1379 REQUIRE(dbdata != NULL);
1380 UNUSED(mctx);
1382 imp = driverarg;
1384 /* If the create method exists, call it. */
1385 if (imp->methods->create != NULL) {
1386 MAYBE_LOCK(imp);
1387 result = imp->methods->create(dlzname, argc, argv,
1388 imp->driverarg, dbdata);
1389 MAYBE_UNLOCK(imp);
1392 /* Write debugging message to log */
1393 if (result == ISC_R_SUCCESS) {
1394 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1395 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1396 "SDLZ driver loaded successfully.");
1397 } else {
1398 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1399 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1400 "SDLZ driver failed to load.");
1403 return (result);
1406 static void
1407 dns_sdlzdestroy(void *driverdata, void **dbdata)
1410 dns_sdlzimplementation_t *imp;
1412 /* Write debugging message to log */
1413 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1414 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1415 "Unloading SDLZ driver.");
1417 imp = driverdata;
1419 /* If the destroy method exists, call it. */
1420 if (imp->methods->destroy != NULL) {
1421 MAYBE_LOCK(imp);
1422 imp->methods->destroy(imp->driverarg, dbdata);
1423 MAYBE_UNLOCK(imp);
1427 static isc_result_t
1428 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1429 dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
1431 isc_buffer_t b;
1432 char namestr[DNS_NAME_MAXTEXT + 1];
1433 isc_result_t result;
1434 dns_sdlzimplementation_t *imp;
1437 * Perform checks to make sure data is as we expect it to be.
1439 REQUIRE(driverarg != NULL);
1440 REQUIRE(name != NULL);
1441 REQUIRE(dbp != NULL && *dbp == NULL);
1443 imp = (dns_sdlzimplementation_t *) driverarg;
1445 /* Convert DNS name to ascii text */
1446 isc_buffer_init(&b, namestr, sizeof(namestr));
1447 result = dns_name_totext(name, ISC_TRUE, &b);
1448 if (result != ISC_R_SUCCESS)
1449 return (result);
1450 isc_buffer_putuint8(&b, 0);
1452 /* make sure strings are always lowercase */
1453 dns_sdlz_tolower(namestr);
1455 /* Call SDLZ driver's find zone method */
1456 MAYBE_LOCK(imp);
1457 result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
1458 MAYBE_UNLOCK(imp);
1461 * if zone is supported build a 'bind' database driver
1462 * structure to return
1464 if (result == ISC_R_SUCCESS)
1465 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1466 rdclass, dbp);
1468 return (result);
1471 static dns_dlzmethods_t sdlzmethods = {
1472 dns_sdlzcreate,
1473 dns_sdlzdestroy,
1474 dns_sdlzfindzone,
1475 dns_sdlzallowzonexfr
1479 * Public functions.
1482 isc_result_t
1483 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1484 const char *data)
1486 dns_rdatalist_t *rdatalist;
1487 dns_rdata_t *rdata;
1488 dns_rdatatype_t typeval;
1489 isc_consttextregion_t r;
1490 isc_buffer_t b;
1491 isc_buffer_t *rdatabuf = NULL;
1492 isc_lex_t *lex;
1493 isc_result_t result;
1494 unsigned int size;
1495 isc_mem_t *mctx;
1496 dns_name_t *origin;
1498 REQUIRE(VALID_SDLZLOOKUP(lookup));
1499 REQUIRE(type != NULL);
1500 REQUIRE(data != NULL);
1502 mctx = lookup->sdlz->common.mctx;
1504 r.base = type;
1505 r.length = strlen(type);
1506 result = dns_rdatatype_fromtext(&typeval, (void *) &r);
1507 if (result != ISC_R_SUCCESS)
1508 return (result);
1510 rdatalist = ISC_LIST_HEAD(lookup->lists);
1511 while (rdatalist != NULL) {
1512 if (rdatalist->type == typeval)
1513 break;
1514 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1517 if (rdatalist == NULL) {
1518 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1519 if (rdatalist == NULL)
1520 return (ISC_R_NOMEMORY);
1521 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1522 rdatalist->type = typeval;
1523 rdatalist->covers = 0;
1524 rdatalist->ttl = ttl;
1525 ISC_LIST_INIT(rdatalist->rdata);
1526 ISC_LINK_INIT(rdatalist, link);
1527 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1528 } else
1529 if (rdatalist->ttl != ttl)
1530 return (DNS_R_BADTTL);
1532 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1533 if (rdata == NULL)
1534 return (ISC_R_NOMEMORY);
1535 dns_rdata_init(rdata);
1537 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1538 origin = &lookup->sdlz->common.origin;
1539 else
1540 origin = dns_rootname;
1542 lex = NULL;
1543 result = isc_lex_create(mctx, 64, &lex);
1544 if (result != ISC_R_SUCCESS)
1545 goto failure;
1547 size = initial_size(data);
1548 do {
1549 isc_buffer_init(&b, data, strlen(data));
1550 isc_buffer_add(&b, strlen(data));
1552 result = isc_lex_openbuffer(lex, &b);
1553 if (result != ISC_R_SUCCESS)
1554 goto failure;
1556 rdatabuf = NULL;
1557 result = isc_buffer_allocate(mctx, &rdatabuf, size);
1558 if (result != ISC_R_SUCCESS)
1559 goto failure;
1561 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1562 rdatalist->type, lex,
1563 origin, ISC_FALSE,
1564 mctx, rdatabuf,
1565 &lookup->callbacks);
1566 if (result != ISC_R_SUCCESS)
1567 isc_buffer_free(&rdatabuf);
1568 size *= 2;
1569 } while (result == ISC_R_NOSPACE);
1571 if (result != ISC_R_SUCCESS)
1572 goto failure;
1574 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1575 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1577 if (lex != NULL)
1578 isc_lex_destroy(&lex);
1580 return (ISC_R_SUCCESS);
1582 failure:
1583 if (rdatabuf != NULL)
1584 isc_buffer_free(&rdatabuf);
1585 if (lex != NULL)
1586 isc_lex_destroy(&lex);
1587 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1589 return (result);
1592 isc_result_t
1593 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1594 const char *type, dns_ttl_t ttl, const char *data)
1596 dns_name_t *newname, *origin;
1597 dns_fixedname_t fnewname;
1598 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1599 dns_sdlznode_t *sdlznode;
1600 isc_mem_t *mctx = sdlz->common.mctx;
1601 isc_buffer_t b;
1602 isc_result_t result;
1604 dns_fixedname_init(&fnewname);
1605 newname = dns_fixedname_name(&fnewname);
1607 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1608 origin = &sdlz->common.origin;
1609 else
1610 origin = dns_rootname;
1611 isc_buffer_init(&b, name, strlen(name));
1612 isc_buffer_add(&b, strlen(name));
1614 result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
1615 if (result != ISC_R_SUCCESS)
1616 return (result);
1618 if (allnodes->common.relative_names) {
1619 /* All names are relative to the root */
1620 unsigned int nlabels = dns_name_countlabels(newname);
1621 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1624 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1625 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1626 sdlznode = NULL;
1627 result = createnode(sdlz, &sdlznode);
1628 if (result != ISC_R_SUCCESS)
1629 return (result);
1630 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1631 if (sdlznode->name == NULL) {
1632 destroynode(sdlznode);
1633 return (ISC_R_NOMEMORY);
1635 dns_name_init(sdlznode->name, NULL);
1636 result = dns_name_dup(newname, mctx, sdlznode->name);
1637 if (result != ISC_R_SUCCESS) {
1638 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
1639 destroynode(sdlznode);
1640 return (result);
1642 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1643 if (allnodes->origin == NULL &&
1644 dns_name_equal(newname, &sdlz->common.origin))
1645 allnodes->origin = sdlznode;
1647 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1651 isc_result_t
1652 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1653 isc_uint32_t serial)
1655 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1656 int n;
1658 REQUIRE(mname != NULL);
1659 REQUIRE(rname != NULL);
1661 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
1662 mname, rname, serial,
1663 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1664 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1665 if (n >= (int)sizeof(str) || n < 0)
1666 return (ISC_R_NOSPACE);
1667 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1670 isc_result_t
1671 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1672 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1673 dns_sdlzimplementation_t **sdlzimp)
1676 dns_sdlzimplementation_t *imp;
1677 isc_result_t result;
1680 * Performs checks to make sure data is as we expect it to be.
1682 REQUIRE(drivername != NULL);
1683 REQUIRE(methods != NULL);
1684 REQUIRE(methods->findzone != NULL);
1685 REQUIRE(methods->lookup != NULL);
1686 REQUIRE(mctx != NULL);
1687 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
1688 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
1689 DNS_SDLZFLAG_RELATIVERDATA |
1690 DNS_SDLZFLAG_THREADSAFE)) == 0);
1692 /* Write debugging message to log */
1693 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1694 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1695 "Registering SDLZ driver '%s'", drivername);
1698 * Allocate memory for a sdlz_implementation object. Error if
1699 * we cannot.
1701 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
1702 if (imp == NULL)
1703 return (ISC_R_NOMEMORY);
1705 /* Make sure memory region is set to all 0's */
1706 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
1708 /* Store the data passed into this method */
1709 imp->methods = methods;
1710 imp->driverarg = driverarg;
1711 imp->flags = flags;
1712 imp->mctx = NULL;
1714 /* attach the new sdlz_implementation object to a memory context */
1715 isc_mem_attach(mctx, &imp->mctx);
1718 * initialize the driver lock, error if we cannot
1719 * (used if a driver does not support multiple threads)
1721 result = isc_mutex_init(&imp->driverlock);
1722 if (result != ISC_R_SUCCESS) {
1723 UNEXPECTED_ERROR(__FILE__, __LINE__,
1724 "isc_mutex_init() failed: %s",
1725 isc_result_totext(result));
1726 goto cleanup_mctx;
1729 imp->dlz_imp = NULL;
1732 * register the DLZ driver. Pass in our "extra" sdlz information as
1733 * a driverarg. (that's why we stored the passed in driver arg in our
1734 * sdlz_implementation structure) Also, store the dlz_implementation
1735 * structure in our sdlz_implementation.
1737 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
1738 &imp->dlz_imp);
1740 /* if registration fails, cleanup and get outta here. */
1741 if (result != ISC_R_SUCCESS)
1742 goto cleanup_mutex;
1744 *sdlzimp = imp;
1746 return (ISC_R_SUCCESS);
1748 cleanup_mutex:
1749 /* destroy the driver lock, we don't need it anymore */
1750 DESTROYLOCK(&imp->driverlock);
1752 cleanup_mctx:
1754 * return the memory back to the available memory pool and
1755 * remove it from the memory context.
1757 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1758 isc_mem_detach(&mctx);
1759 return (result);
1762 void
1763 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
1764 dns_sdlzimplementation_t *imp;
1765 isc_mem_t *mctx;
1767 /* Write debugging message to log */
1768 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1769 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1770 "Unregistering SDLZ driver.");
1773 * Performs checks to make sure data is as we expect it to be.
1775 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
1777 imp = *sdlzimp;
1779 /* Unregister the DLZ driver implementation */
1780 dns_dlzunregister(&imp->dlz_imp);
1782 /* destroy the driver lock, we don't need it anymore */
1783 DESTROYLOCK(&imp->driverlock);
1785 mctx = imp->mctx;
1788 * return the memory back to the available memory pool and
1789 * remove it from the memory context.
1791 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1792 isc_mem_detach(&mctx);
1794 *sdlzimp = NULL;