kernel - Update swapcache manual page
[dragonfly.git] / contrib / bind / lib / dns / sdlz.c
blob11993939bccb24c3d33645688e5e83d851a8e184
1 /*
2 * Portions Copyright (C) 2005-2009 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 2009/06/26 06:23:47 marka 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
1206 static void
1207 list_tordataset(dns_rdatalist_t *rdatalist,
1208 dns_db_t *db, dns_dbnode_t *node,
1209 dns_rdataset_t *rdataset)
1212 * The sdlz rdataset is an rdatalist with some additions.
1213 * - private1 & private2 are used by the rdatalist.
1214 * - private3 & private 4 are unused.
1215 * - private5 is the node.
1218 /* This should never fail. */
1219 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1220 ISC_R_SUCCESS);
1222 rdataset->methods = &rdataset_methods;
1223 dns_db_attachnode(db, node, &rdataset->private5);
1227 * SDLZ core methods. This is the core of the new DLZ functionality.
1231 * Build a 'bind' database driver structure to be returned by
1232 * either the find zone or the allow zone transfer method.
1233 * This method is only available in this source file, it is
1234 * not made available anywhere else.
1237 static isc_result_t
1238 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1239 dns_name_t *name, dns_rdataclass_t rdclass, dns_db_t **dbp)
1241 isc_result_t result;
1242 dns_sdlz_db_t *sdlzdb;
1243 dns_sdlzimplementation_t *imp;
1245 /* check that things are as we expect */
1246 REQUIRE(dbp != NULL && *dbp == NULL);
1247 REQUIRE(name != NULL);
1249 imp = (dns_sdlzimplementation_t *) driverarg;
1251 /* allocate and zero memory for driver structure */
1252 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1253 if (sdlzdb == NULL)
1254 return (ISC_R_NOMEMORY);
1255 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1257 /* initialize and set origin */
1258 dns_name_init(&sdlzdb->common.origin, NULL);
1259 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1260 if (result != ISC_R_SUCCESS)
1261 goto mem_cleanup;
1263 /* initialize the reference count mutex */
1264 result = isc_mutex_init(&sdlzdb->refcnt_lock);
1265 if (result != ISC_R_SUCCESS)
1266 goto name_cleanup;
1268 /* set the rest of the database structure attributes */
1269 sdlzdb->dlzimp = imp;
1270 sdlzdb->common.methods = &sdlzdb_methods;
1271 sdlzdb->common.attributes = 0;
1272 sdlzdb->common.rdclass = rdclass;
1273 sdlzdb->common.mctx = NULL;
1274 sdlzdb->dbdata = dbdata;
1275 sdlzdb->references = 1;
1277 /* attach to the memory context */
1278 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1280 /* mark structure as valid */
1281 sdlzdb->common.magic = DNS_DB_MAGIC;
1282 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1283 *dbp = (dns_db_t *) sdlzdb;
1285 return (result);
1288 * reference count mutex could not be initialized, clean up
1289 * name memory
1291 name_cleanup:
1292 dns_name_free(&sdlzdb->common.origin, mctx);
1293 mem_cleanup:
1294 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1295 return (result);
1298 static isc_result_t
1299 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1300 dns_rdataclass_t rdclass, dns_name_t *name,
1301 isc_sockaddr_t *clientaddr, dns_db_t **dbp)
1303 isc_buffer_t b;
1304 isc_buffer_t b2;
1305 char namestr[DNS_NAME_MAXTEXT + 1];
1306 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1307 + 1];
1308 isc_netaddr_t netaddr;
1309 isc_result_t result;
1310 dns_sdlzimplementation_t *imp;
1313 * Perform checks to make sure data is as we expect it to be.
1315 REQUIRE(driverarg != NULL);
1316 REQUIRE(name != NULL);
1317 REQUIRE(clientaddr != NULL);
1318 REQUIRE(dbp != NULL && *dbp == NULL);
1320 imp = (dns_sdlzimplementation_t *) driverarg;
1322 /* Convert DNS name to ascii text */
1323 isc_buffer_init(&b, namestr, sizeof(namestr));
1324 result = dns_name_totext(name, ISC_TRUE, &b);
1325 if (result != ISC_R_SUCCESS)
1326 return (result);
1327 isc_buffer_putuint8(&b, 0);
1329 /* convert client address to ascii text */
1330 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1331 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1332 result = isc_netaddr_totext(&netaddr, &b2);
1333 if (result != ISC_R_SUCCESS)
1334 return (result);
1335 isc_buffer_putuint8(&b2, 0);
1337 /* make sure strings are always lowercase */
1338 dns_sdlz_tolower(namestr);
1339 dns_sdlz_tolower(clientstr);
1341 /* Call SDLZ driver's find zone method */
1342 if (imp->methods->allowzonexfr != NULL) {
1343 MAYBE_LOCK(imp);
1344 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1345 namestr, clientstr);
1346 MAYBE_UNLOCK(imp);
1348 * if zone is supported and transfers allowed build a 'bind'
1349 * database driver
1351 if (result == ISC_R_SUCCESS)
1352 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1353 name, rdclass, dbp);
1354 return (result);
1357 return (ISC_R_NOTIMPLEMENTED);
1360 static isc_result_t
1361 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1362 char *argv[], void *driverarg, void **dbdata)
1364 dns_sdlzimplementation_t *imp;
1365 isc_result_t result = ISC_R_NOTFOUND;
1367 /* Write debugging message to log */
1368 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1369 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1370 "Loading SDLZ driver.");
1373 * Performs checks to make sure data is as we expect it to be.
1375 REQUIRE(driverarg != NULL);
1376 REQUIRE(dlzname != NULL);
1377 REQUIRE(dbdata != NULL);
1378 UNUSED(mctx);
1380 imp = driverarg;
1382 /* If the create method exists, call it. */
1383 if (imp->methods->create != NULL) {
1384 MAYBE_LOCK(imp);
1385 result = imp->methods->create(dlzname, argc, argv,
1386 imp->driverarg, dbdata);
1387 MAYBE_UNLOCK(imp);
1390 /* Write debugging message to log */
1391 if (result == ISC_R_SUCCESS) {
1392 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1393 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1394 "SDLZ driver loaded successfully.");
1395 } else {
1396 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1397 DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
1398 "SDLZ driver failed to load.");
1401 return (result);
1404 static void
1405 dns_sdlzdestroy(void *driverdata, void **dbdata)
1408 dns_sdlzimplementation_t *imp;
1410 /* Write debugging message to log */
1411 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1412 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1413 "Unloading SDLZ driver.");
1415 imp = driverdata;
1417 /* If the destroy method exists, call it. */
1418 if (imp->methods->destroy != NULL) {
1419 MAYBE_LOCK(imp);
1420 imp->methods->destroy(imp->driverarg, dbdata);
1421 MAYBE_UNLOCK(imp);
1425 static isc_result_t
1426 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1427 dns_rdataclass_t rdclass, dns_name_t *name, dns_db_t **dbp)
1429 isc_buffer_t b;
1430 char namestr[DNS_NAME_MAXTEXT + 1];
1431 isc_result_t result;
1432 dns_sdlzimplementation_t *imp;
1435 * Perform checks to make sure data is as we expect it to be.
1437 REQUIRE(driverarg != NULL);
1438 REQUIRE(name != NULL);
1439 REQUIRE(dbp != NULL && *dbp == NULL);
1441 imp = (dns_sdlzimplementation_t *) driverarg;
1443 /* Convert DNS name to ascii text */
1444 isc_buffer_init(&b, namestr, sizeof(namestr));
1445 result = dns_name_totext(name, ISC_TRUE, &b);
1446 if (result != ISC_R_SUCCESS)
1447 return (result);
1448 isc_buffer_putuint8(&b, 0);
1450 /* make sure strings are always lowercase */
1451 dns_sdlz_tolower(namestr);
1453 /* Call SDLZ driver's find zone method */
1454 MAYBE_LOCK(imp);
1455 result = imp->methods->findzone(imp->driverarg, dbdata, namestr);
1456 MAYBE_UNLOCK(imp);
1459 * if zone is supported build a 'bind' database driver
1460 * structure to return
1462 if (result == ISC_R_SUCCESS)
1463 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1464 rdclass, dbp);
1466 return (result);
1469 static dns_dlzmethods_t sdlzmethods = {
1470 dns_sdlzcreate,
1471 dns_sdlzdestroy,
1472 dns_sdlzfindzone,
1473 dns_sdlzallowzonexfr
1477 * Public functions.
1480 isc_result_t
1481 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1482 const char *data)
1484 dns_rdatalist_t *rdatalist;
1485 dns_rdata_t *rdata;
1486 dns_rdatatype_t typeval;
1487 isc_consttextregion_t r;
1488 isc_buffer_t b;
1489 isc_buffer_t *rdatabuf = NULL;
1490 isc_lex_t *lex;
1491 isc_result_t result;
1492 unsigned int size;
1493 isc_mem_t *mctx;
1494 dns_name_t *origin;
1496 REQUIRE(VALID_SDLZLOOKUP(lookup));
1497 REQUIRE(type != NULL);
1498 REQUIRE(data != NULL);
1500 mctx = lookup->sdlz->common.mctx;
1502 r.base = type;
1503 r.length = strlen(type);
1504 result = dns_rdatatype_fromtext(&typeval, (void *) &r);
1505 if (result != ISC_R_SUCCESS)
1506 return (result);
1508 rdatalist = ISC_LIST_HEAD(lookup->lists);
1509 while (rdatalist != NULL) {
1510 if (rdatalist->type == typeval)
1511 break;
1512 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1515 if (rdatalist == NULL) {
1516 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1517 if (rdatalist == NULL)
1518 return (ISC_R_NOMEMORY);
1519 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1520 rdatalist->type = typeval;
1521 rdatalist->covers = 0;
1522 rdatalist->ttl = ttl;
1523 ISC_LIST_INIT(rdatalist->rdata);
1524 ISC_LINK_INIT(rdatalist, link);
1525 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1526 } else
1527 if (rdatalist->ttl != ttl)
1528 return (DNS_R_BADTTL);
1530 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1531 if (rdata == NULL)
1532 return (ISC_R_NOMEMORY);
1533 dns_rdata_init(rdata);
1535 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1536 origin = &lookup->sdlz->common.origin;
1537 else
1538 origin = dns_rootname;
1540 lex = NULL;
1541 result = isc_lex_create(mctx, 64, &lex);
1542 if (result != ISC_R_SUCCESS)
1543 goto failure;
1545 size = initial_size(data);
1546 do {
1547 isc_buffer_init(&b, data, strlen(data));
1548 isc_buffer_add(&b, strlen(data));
1550 result = isc_lex_openbuffer(lex, &b);
1551 if (result != ISC_R_SUCCESS)
1552 goto failure;
1554 rdatabuf = NULL;
1555 result = isc_buffer_allocate(mctx, &rdatabuf, size);
1556 if (result != ISC_R_SUCCESS)
1557 goto failure;
1559 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1560 rdatalist->type, lex,
1561 origin, ISC_FALSE,
1562 mctx, rdatabuf,
1563 &lookup->callbacks);
1564 if (result != ISC_R_SUCCESS)
1565 isc_buffer_free(&rdatabuf);
1566 size *= 2;
1567 } while (result == ISC_R_NOSPACE);
1569 if (result != ISC_R_SUCCESS)
1570 goto failure;
1572 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1573 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1575 if (lex != NULL)
1576 isc_lex_destroy(&lex);
1578 return (ISC_R_SUCCESS);
1580 failure:
1581 if (rdatabuf != NULL)
1582 isc_buffer_free(&rdatabuf);
1583 if (lex != NULL)
1584 isc_lex_destroy(&lex);
1585 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1587 return (result);
1590 isc_result_t
1591 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1592 const char *type, dns_ttl_t ttl, const char *data)
1594 dns_name_t *newname, *origin;
1595 dns_fixedname_t fnewname;
1596 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1597 dns_sdlznode_t *sdlznode;
1598 isc_mem_t *mctx = sdlz->common.mctx;
1599 isc_buffer_t b;
1600 isc_result_t result;
1602 dns_fixedname_init(&fnewname);
1603 newname = dns_fixedname_name(&fnewname);
1605 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1606 origin = &sdlz->common.origin;
1607 else
1608 origin = dns_rootname;
1609 isc_buffer_init(&b, name, strlen(name));
1610 isc_buffer_add(&b, strlen(name));
1612 result = dns_name_fromtext(newname, &b, origin, ISC_FALSE, NULL);
1613 if (result != ISC_R_SUCCESS)
1614 return (result);
1616 if (allnodes->common.relative_names) {
1617 /* All names are relative to the root */
1618 unsigned int nlabels = dns_name_countlabels(newname);
1619 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1622 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1623 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1624 sdlznode = NULL;
1625 result = createnode(sdlz, &sdlznode);
1626 if (result != ISC_R_SUCCESS)
1627 return (result);
1628 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1629 if (sdlznode->name == NULL) {
1630 destroynode(sdlznode);
1631 return (ISC_R_NOMEMORY);
1633 dns_name_init(sdlznode->name, NULL);
1634 result = dns_name_dup(newname, mctx, sdlznode->name);
1635 if (result != ISC_R_SUCCESS) {
1636 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
1637 destroynode(sdlznode);
1638 return (result);
1640 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1641 if (allnodes->origin == NULL &&
1642 dns_name_equal(newname, &sdlz->common.origin))
1643 allnodes->origin = sdlznode;
1645 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1649 isc_result_t
1650 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1651 isc_uint32_t serial)
1653 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1654 int n;
1656 REQUIRE(mname != NULL);
1657 REQUIRE(rname != NULL);
1659 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
1660 mname, rname, serial,
1661 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1662 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1663 if (n >= (int)sizeof(str) || n < 0)
1664 return (ISC_R_NOSPACE);
1665 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1668 isc_result_t
1669 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1670 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1671 dns_sdlzimplementation_t **sdlzimp)
1674 dns_sdlzimplementation_t *imp;
1675 isc_result_t result;
1678 * Performs checks to make sure data is as we expect it to be.
1680 REQUIRE(drivername != NULL);
1681 REQUIRE(methods != NULL);
1682 REQUIRE(methods->findzone != NULL);
1683 REQUIRE(methods->lookup != NULL);
1684 REQUIRE(mctx != NULL);
1685 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
1686 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
1687 DNS_SDLZFLAG_RELATIVERDATA |
1688 DNS_SDLZFLAG_THREADSAFE)) == 0);
1690 /* Write debugging message to log */
1691 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1692 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1693 "Registering SDLZ driver '%s'", drivername);
1696 * Allocate memory for a sdlz_implementation object. Error if
1697 * we cannot.
1699 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
1700 if (imp == NULL)
1701 return (ISC_R_NOMEMORY);
1703 /* Make sure memory region is set to all 0's */
1704 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
1706 /* Store the data passed into this method */
1707 imp->methods = methods;
1708 imp->driverarg = driverarg;
1709 imp->flags = flags;
1710 imp->mctx = NULL;
1712 /* attach the new sdlz_implementation object to a memory context */
1713 isc_mem_attach(mctx, &imp->mctx);
1716 * initialize the driver lock, error if we cannot
1717 * (used if a driver does not support multiple threads)
1719 result = isc_mutex_init(&imp->driverlock);
1720 if (result != ISC_R_SUCCESS) {
1721 UNEXPECTED_ERROR(__FILE__, __LINE__,
1722 "isc_mutex_init() failed: %s",
1723 isc_result_totext(result));
1724 goto cleanup_mctx;
1727 imp->dlz_imp = NULL;
1730 * register the DLZ driver. Pass in our "extra" sdlz information as
1731 * a driverarg. (that's why we stored the passed in driver arg in our
1732 * sdlz_implementation structure) Also, store the dlz_implementation
1733 * structure in our sdlz_implementation.
1735 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
1736 &imp->dlz_imp);
1738 /* if registration fails, cleanup and get outta here. */
1739 if (result != ISC_R_SUCCESS)
1740 goto cleanup_mutex;
1742 *sdlzimp = imp;
1744 return (ISC_R_SUCCESS);
1746 cleanup_mutex:
1747 /* destroy the driver lock, we don't need it anymore */
1748 DESTROYLOCK(&imp->driverlock);
1750 cleanup_mctx:
1752 * return the memory back to the available memory pool and
1753 * remove it from the memory context.
1755 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1756 isc_mem_detach(&mctx);
1757 return (result);
1760 void
1761 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
1762 dns_sdlzimplementation_t *imp;
1763 isc_mem_t *mctx;
1765 /* Write debugging message to log */
1766 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
1767 DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
1768 "Unregistering SDLZ driver.");
1771 * Performs checks to make sure data is as we expect it to be.
1773 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
1775 imp = *sdlzimp;
1777 /* Unregister the DLZ driver implementation */
1778 dns_dlzunregister(&imp->dlz_imp);
1780 /* destroy the driver lock, we don't need it anymore */
1781 DESTROYLOCK(&imp->driverlock);
1783 mctx = imp->mctx;
1786 * return the memory back to the available memory pool and
1787 * remove it from the memory context.
1789 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
1790 isc_mem_detach(&mctx);
1792 *sdlzimp = NULL;