sdlz.c revision 1.10.2.2 1 /* $NetBSD: sdlz.c,v 1.10.2.2 2024/02/25 15:46:53 martin Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0 AND ISC
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 /*
17 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting (at) nlnet.nl.
18 *
19 * Permission to use, copy, modify, and distribute this software for any
20 * purpose with or without fee is hereby granted, provided that the
21 * above copyright notice and this permission notice appear in all
22 * copies.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
25 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
27 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
29 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
30 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
31 * USE OR PERFORMANCE OF THIS SOFTWARE.
32 *
33 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
34 * conceived and contributed by Rob Butler.
35 *
36 * Permission to use, copy, modify, and distribute this software for any
37 * purpose with or without fee is hereby granted, provided that the
38 * above copyright notice and this permission notice appear in all
39 * copies.
40 *
41 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
42 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
44 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
46 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
47 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
48 * USE OR PERFORMANCE OF THIS SOFTWARE.
49 */
50
51 /*! \file */
52
53 #include <inttypes.h>
54 #include <stdbool.h>
55 #include <string.h>
56
57 #include <isc/buffer.h>
58 #include <isc/lex.h>
59 #include <isc/log.h>
60 #include <isc/magic.h>
61 #include <isc/mem.h>
62 #include <isc/once.h>
63 #include <isc/print.h>
64 #include <isc/region.h>
65 #include <isc/result.h>
66 #include <isc/rwlock.h>
67 #include <isc/string.h>
68 #include <isc/util.h>
69
70 #include <dns/callbacks.h>
71 #include <dns/db.h>
72 #include <dns/dbiterator.h>
73 #include <dns/dlz.h>
74 #include <dns/fixedname.h>
75 #include <dns/log.h>
76 #include <dns/master.h>
77 #include <dns/rdata.h>
78 #include <dns/rdatalist.h>
79 #include <dns/rdataset.h>
80 #include <dns/rdatasetiter.h>
81 #include <dns/rdatatype.h>
82 #include <dns/sdlz.h>
83 #include <dns/types.h>
84
85 #include "rdatalist_p.h"
86
87 /*
88 * Private Types
89 */
90
91 struct dns_sdlzimplementation {
92 const dns_sdlzmethods_t *methods;
93 isc_mem_t *mctx;
94 void *driverarg;
95 unsigned int flags;
96 isc_mutex_t driverlock;
97 dns_dlzimplementation_t *dlz_imp;
98 };
99
100 struct dns_sdlz_db {
101 /* Unlocked */
102 dns_db_t common;
103 void *dbdata;
104 dns_sdlzimplementation_t *dlzimp;
105
106 /* Atomic */
107 isc_refcount_t references;
108
109 /* Locked */
110 dns_dbversion_t *future_version;
111 int dummy_version;
112 };
113
114 struct dns_sdlzlookup {
115 /* Unlocked */
116 unsigned int magic;
117 dns_sdlz_db_t *sdlz;
118 ISC_LIST(dns_rdatalist_t) lists;
119 ISC_LIST(isc_buffer_t) buffers;
120 dns_name_t *name;
121 ISC_LINK(dns_sdlzlookup_t) link;
122 dns_rdatacallbacks_t callbacks;
123
124 /* Atomic */
125 isc_refcount_t references;
126 };
127
128 typedef struct dns_sdlzlookup dns_sdlznode_t;
129
130 struct dns_sdlzallnodes {
131 dns_dbiterator_t common;
132 ISC_LIST(dns_sdlznode_t) nodelist;
133 dns_sdlznode_t *current;
134 dns_sdlznode_t *origin;
135 };
136
137 typedef dns_sdlzallnodes_t sdlz_dbiterator_t;
138
139 typedef struct sdlz_rdatasetiter {
140 dns_rdatasetiter_t common;
141 dns_rdatalist_t *current;
142 } sdlz_rdatasetiter_t;
143
144 #define SDLZDB_MAGIC ISC_MAGIC('D', 'L', 'Z', 'S')
145
146 /*
147 * Note that "impmagic" is not the first four bytes of the struct, so
148 * ISC_MAGIC_VALID cannot be used.
149 */
150
151 #define VALID_SDLZDB(sdlzdb) \
152 ((sdlzdb) != NULL && (sdlzdb)->common.impmagic == SDLZDB_MAGIC)
153
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)
157
158 /* These values are taken from RFC 1537 */
159 #define SDLZ_DEFAULT_REFRESH 28800U /* 8 hours */
160 #define SDLZ_DEFAULT_RETRY 7200U /* 2 hours */
161 #define SDLZ_DEFAULT_EXPIRE 604800U /* 7 days */
162 #define SDLZ_DEFAULT_MINIMUM 86400U /* 1 day */
163
164 /* This is a reasonable value */
165 #define SDLZ_DEFAULT_TTL (60 * 60 * 24)
166
167 #ifdef __COVERITY__
168 #define MAYBE_LOCK(imp) LOCK(&imp->driverlock)
169 #define MAYBE_UNLOCK(imp) UNLOCK(&imp->driverlock)
170 #else /* ifdef __COVERITY__ */
171 #define MAYBE_LOCK(imp) \
172 do { \
173 unsigned int flags = imp->flags; \
174 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
175 LOCK(&imp->driverlock); \
176 } while (0)
177
178 #define MAYBE_UNLOCK(imp) \
179 do { \
180 unsigned int flags = imp->flags; \
181 if ((flags & DNS_SDLZFLAG_THREADSAFE) == 0) \
182 UNLOCK(&imp->driverlock); \
183 } while (0)
184 #endif /* ifdef __COVERITY__ */
185
186 /*
187 * Forward references.
188 */
189 static isc_result_t
190 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
191 unsigned int options, dns_clientinfomethods_t *methods,
192 dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep);
193
194 static void
195 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
196 dns_rdataset_t *rdataset);
197
198 static void
199 detachnode(dns_db_t *db, dns_dbnode_t **targetp);
200
201 static void
202 dbiterator_destroy(dns_dbiterator_t **iteratorp);
203 static isc_result_t
204 dbiterator_first(dns_dbiterator_t *iterator);
205 static isc_result_t
206 dbiterator_last(dns_dbiterator_t *iterator);
207 static isc_result_t
208 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name);
209 static isc_result_t
210 dbiterator_prev(dns_dbiterator_t *iterator);
211 static isc_result_t
212 dbiterator_next(dns_dbiterator_t *iterator);
213 static isc_result_t
214 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
215 dns_name_t *name);
216 static isc_result_t
217 dbiterator_pause(dns_dbiterator_t *iterator);
218 static isc_result_t
219 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
220
221 static dns_dbiteratormethods_t dbiterator_methods = {
222 dbiterator_destroy, dbiterator_first, dbiterator_last,
223 dbiterator_seek, dbiterator_prev, dbiterator_next,
224 dbiterator_current, dbiterator_pause, dbiterator_origin
225 };
226
227 /*
228 * Utility functions
229 */
230
231 /*
232 * Log a message at the given level
233 */
234 static void
235 sdlz_log(int level, const char *fmt, ...) {
236 va_list ap;
237 va_start(ap, fmt);
238 isc_log_vwrite(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ,
239 ISC_LOG_DEBUG(level), fmt, ap);
240 va_end(ap);
241 }
242
243 /*% Converts the input string to lowercase, in place. */
244 static void
245 dns_sdlz_tolower(char *str) {
246 unsigned int len = strlen(str);
247 unsigned int i;
248
249 for (i = 0; i < len; i++) {
250 if (str[i] >= 'A' && str[i] <= 'Z') {
251 str[i] += 32;
252 }
253 }
254 }
255
256 static unsigned int
257 initial_size(const char *data) {
258 unsigned int len = (strlen(data) / 64) + 1;
259 return (len * 64 + 64);
260 }
261
262 /*
263 * Rdataset Iterator Methods. These methods were "borrowed" from the SDB
264 * driver interface. See the SDB driver interface documentation for more info.
265 */
266
267 static void
268 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
269 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)(*iteratorp);
270
271 detachnode(sdlziterator->common.db, &sdlziterator->common.node);
272 isc_mem_put(sdlziterator->common.db->mctx, sdlziterator,
273 sizeof(sdlz_rdatasetiter_t));
274 *iteratorp = NULL;
275 }
276
277 static isc_result_t
278 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
279 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
280 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)iterator->node;
281
282 if (ISC_LIST_EMPTY(sdlznode->lists)) {
283 return (ISC_R_NOMORE);
284 }
285 sdlziterator->current = ISC_LIST_HEAD(sdlznode->lists);
286 return (ISC_R_SUCCESS);
287 }
288
289 static isc_result_t
290 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
291 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
292
293 sdlziterator->current = ISC_LIST_NEXT(sdlziterator->current, link);
294 if (sdlziterator->current == NULL) {
295 return (ISC_R_NOMORE);
296 } else {
297 return (ISC_R_SUCCESS);
298 }
299 }
300
301 static void
302 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
303 sdlz_rdatasetiter_t *sdlziterator = (sdlz_rdatasetiter_t *)iterator;
304
305 list_tordataset(sdlziterator->current, iterator->db, iterator->node,
306 rdataset);
307 }
308
309 static dns_rdatasetitermethods_t rdatasetiter_methods = {
310 rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
311 rdatasetiter_current
312 };
313
314 /*
315 * DB routines. These methods were "borrowed" from the SDB driver interface.
316 * See the SDB driver interface documentation for more info.
317 */
318
319 static void
320 attach(dns_db_t *source, dns_db_t **targetp) {
321 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)source;
322
323 REQUIRE(VALID_SDLZDB(sdlz));
324
325 isc_refcount_increment(&sdlz->references);
326
327 *targetp = source;
328 }
329
330 static void
331 destroy(dns_sdlz_db_t *sdlz) {
332 sdlz->common.magic = 0;
333 sdlz->common.impmagic = 0;
334
335 dns_name_free(&sdlz->common.origin, sdlz->common.mctx);
336
337 isc_refcount_destroy(&sdlz->references);
338 isc_mem_putanddetach(&sdlz->common.mctx, sdlz, sizeof(dns_sdlz_db_t));
339 }
340
341 static void
342 detach(dns_db_t **dbp) {
343 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)(*dbp);
344
345 REQUIRE(VALID_SDLZDB(sdlz));
346
347 *dbp = NULL;
348
349 if (isc_refcount_decrement(&sdlz->references) == 1) {
350 destroy(sdlz);
351 }
352 }
353
354 static isc_result_t
355 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
356 UNUSED(db);
357 UNUSED(callbacks);
358 return (ISC_R_NOTIMPLEMENTED);
359 }
360
361 static isc_result_t
362 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
363 UNUSED(db);
364 UNUSED(callbacks);
365 return (ISC_R_NOTIMPLEMENTED);
366 }
367
368 static isc_result_t
369 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
370 dns_masterformat_t masterformat) {
371 UNUSED(db);
372 UNUSED(version);
373 UNUSED(filename);
374 UNUSED(masterformat);
375 return (ISC_R_NOTIMPLEMENTED);
376 }
377
378 static void
379 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
380 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
381 REQUIRE(VALID_SDLZDB(sdlz));
382 REQUIRE(versionp != NULL && *versionp == NULL);
383
384 *versionp = (void *)&sdlz->dummy_version;
385 return;
386 }
387
388 static isc_result_t
389 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
390 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
391 char origin[DNS_NAME_MAXTEXT + 1];
392 isc_result_t result;
393
394 REQUIRE(VALID_SDLZDB(sdlz));
395
396 if (sdlz->dlzimp->methods->newversion == NULL) {
397 return (ISC_R_NOTIMPLEMENTED);
398 }
399
400 dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
401
402 result = sdlz->dlzimp->methods->newversion(
403 origin, sdlz->dlzimp->driverarg, sdlz->dbdata, versionp);
404 if (result != ISC_R_SUCCESS) {
405 sdlz_log(ISC_LOG_ERROR,
406 "sdlz newversion on origin %s failed : %s", origin,
407 isc_result_totext(result));
408 return (result);
409 }
410
411 sdlz->future_version = *versionp;
412 return (ISC_R_SUCCESS);
413 }
414
415 static void
416 attachversion(dns_db_t *db, dns_dbversion_t *source,
417 dns_dbversion_t **targetp) {
418 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
419
420 REQUIRE(VALID_SDLZDB(sdlz));
421 REQUIRE(source != NULL && source == (void *)&sdlz->dummy_version);
422
423 *targetp = source;
424 }
425
426 static void
427 closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
428 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
429 char origin[DNS_NAME_MAXTEXT + 1];
430
431 REQUIRE(VALID_SDLZDB(sdlz));
432 REQUIRE(versionp != NULL);
433
434 if (*versionp == (void *)&sdlz->dummy_version) {
435 *versionp = NULL;
436 return;
437 }
438
439 REQUIRE(*versionp == sdlz->future_version);
440 REQUIRE(sdlz->dlzimp->methods->closeversion != NULL);
441
442 dns_name_format(&sdlz->common.origin, origin, sizeof(origin));
443
444 sdlz->dlzimp->methods->closeversion(origin, commit,
445 sdlz->dlzimp->driverarg,
446 sdlz->dbdata, versionp);
447 if (*versionp != NULL) {
448 sdlz_log(ISC_LOG_ERROR, "sdlz closeversion on origin %s failed",
449 origin);
450 }
451
452 sdlz->future_version = NULL;
453 }
454
455 static isc_result_t
456 createnode(dns_sdlz_db_t *sdlz, dns_sdlznode_t **nodep) {
457 dns_sdlznode_t *node;
458
459 node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
460
461 node->sdlz = NULL;
462 attach((dns_db_t *)sdlz, (dns_db_t **)&node->sdlz);
463 ISC_LIST_INIT(node->lists);
464 ISC_LIST_INIT(node->buffers);
465 ISC_LINK_INIT(node, link);
466 node->name = NULL;
467 dns_rdatacallbacks_init(&node->callbacks);
468
469 isc_refcount_init(&node->references, 1);
470 node->magic = SDLZLOOKUP_MAGIC;
471
472 *nodep = node;
473 return (ISC_R_SUCCESS);
474 }
475
476 static void
477 destroynode(dns_sdlznode_t *node) {
478 dns_rdatalist_t *list;
479 dns_rdata_t *rdata;
480 isc_buffer_t *b;
481 dns_sdlz_db_t *sdlz;
482 dns_db_t *db;
483 isc_mem_t *mctx;
484
485 isc_refcount_destroy(&node->references);
486
487 sdlz = node->sdlz;
488 mctx = sdlz->common.mctx;
489
490 while (!ISC_LIST_EMPTY(node->lists)) {
491 list = ISC_LIST_HEAD(node->lists);
492 while (!ISC_LIST_EMPTY(list->rdata)) {
493 rdata = ISC_LIST_HEAD(list->rdata);
494 ISC_LIST_UNLINK(list->rdata, rdata, link);
495 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
496 }
497 ISC_LIST_UNLINK(node->lists, list, link);
498 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
499 }
500
501 while (!ISC_LIST_EMPTY(node->buffers)) {
502 b = ISC_LIST_HEAD(node->buffers);
503 ISC_LIST_UNLINK(node->buffers, b, link);
504 isc_buffer_free(&b);
505 }
506
507 if (node->name != NULL) {
508 dns_name_free(node->name, mctx);
509 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
510 }
511
512 node->magic = 0;
513 isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
514 db = &sdlz->common;
515 detach(&db);
516 }
517
518 static isc_result_t
519 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
520 unsigned int options, dns_clientinfomethods_t *methods,
521 dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) {
522 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
523 dns_sdlznode_t *node = NULL;
524 isc_result_t result;
525 isc_buffer_t b;
526 char namestr[DNS_NAME_MAXTEXT + 1];
527 isc_buffer_t b2;
528 char zonestr[DNS_NAME_MAXTEXT + 1];
529 bool isorigin;
530 dns_sdlzauthorityfunc_t authority;
531
532 REQUIRE(VALID_SDLZDB(sdlz));
533 REQUIRE(nodep != NULL && *nodep == NULL);
534
535 if (sdlz->dlzimp->methods->newversion == NULL) {
536 REQUIRE(!create);
537 }
538
539 isc_buffer_init(&b, namestr, sizeof(namestr));
540 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
541 dns_name_t relname;
542 unsigned int labels;
543
544 labels = dns_name_countlabels(name) -
545 dns_name_countlabels(&sdlz->common.origin);
546 dns_name_init(&relname, NULL);
547 dns_name_getlabelsequence(name, 0, labels, &relname);
548 result = dns_name_totext(&relname, true, &b);
549 if (result != ISC_R_SUCCESS) {
550 return (result);
551 }
552 } else {
553 result = dns_name_totext(name, true, &b);
554 if (result != ISC_R_SUCCESS) {
555 return (result);
556 }
557 }
558 isc_buffer_putuint8(&b, 0);
559
560 isc_buffer_init(&b2, zonestr, sizeof(zonestr));
561 result = dns_name_totext(&sdlz->common.origin, true, &b2);
562 if (result != ISC_R_SUCCESS) {
563 return (result);
564 }
565 isc_buffer_putuint8(&b2, 0);
566
567 result = createnode(sdlz, &node);
568 if (result != ISC_R_SUCCESS) {
569 return (result);
570 }
571
572 isorigin = dns_name_equal(name, &sdlz->common.origin);
573
574 /* make sure strings are always lowercase */
575 dns_sdlz_tolower(zonestr);
576 dns_sdlz_tolower(namestr);
577
578 MAYBE_LOCK(sdlz->dlzimp);
579
580 /* try to lookup the host (namestr) */
581 result = sdlz->dlzimp->methods->lookup(
582 zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node,
583 methods, clientinfo);
584
585 /*
586 * If the name was not found and DNS_DBFIND_NOWILD is not
587 * set, then we try to find a wildcard entry.
588 *
589 * If DNS_DBFIND_NOZONECUT is set and there are multiple
590 * levels between the host and the zone origin, we also look
591 * for wildcards at each level.
592 */
593 if (result == ISC_R_NOTFOUND && !create &&
594 (options & DNS_DBFIND_NOWILD) == 0)
595 {
596 unsigned int i, dlabels, nlabels;
597
598 nlabels = dns_name_countlabels(name);
599 dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
600 for (i = 0; i < dlabels; i++) {
601 char wildstr[DNS_NAME_MAXTEXT + 1];
602 dns_fixedname_t fixed;
603 const dns_name_t *wild;
604
605 dns_fixedname_init(&fixed);
606 if (i == dlabels - 1) {
607 wild = dns_wildcardname;
608 } else {
609 dns_name_t *fname;
610 fname = dns_fixedname_name(&fixed);
611 dns_name_getlabelsequence(
612 name, i + 1, dlabels - i - 1, fname);
613 result = dns_name_concatenate(
614 dns_wildcardname, fname, fname, NULL);
615 if (result != ISC_R_SUCCESS) {
616 MAYBE_UNLOCK(sdlz->dlzimp);
617 return (result);
618 }
619 wild = fname;
620 }
621
622 isc_buffer_init(&b, wildstr, sizeof(wildstr));
623 result = dns_name_totext(wild, true, &b);
624 if (result != ISC_R_SUCCESS) {
625 MAYBE_UNLOCK(sdlz->dlzimp);
626 return (result);
627 }
628 isc_buffer_putuint8(&b, 0);
629
630 result = sdlz->dlzimp->methods->lookup(
631 zonestr, wildstr, sdlz->dlzimp->driverarg,
632 sdlz->dbdata, node, methods, clientinfo);
633 if (result == ISC_R_SUCCESS) {
634 break;
635 }
636 }
637 }
638
639 MAYBE_UNLOCK(sdlz->dlzimp);
640
641 if (result == ISC_R_NOTFOUND && (isorigin || create)) {
642 result = ISC_R_SUCCESS;
643 }
644
645 if (result != ISC_R_SUCCESS) {
646 isc_refcount_decrementz(&node->references);
647 destroynode(node);
648 return (result);
649 }
650
651 if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
652 MAYBE_LOCK(sdlz->dlzimp);
653 authority = sdlz->dlzimp->methods->authority;
654 result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
655 sdlz->dbdata, node);
656 MAYBE_UNLOCK(sdlz->dlzimp);
657 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
658 isc_refcount_decrementz(&node->references);
659 destroynode(node);
660 return (result);
661 }
662 }
663
664 if (node->name == NULL) {
665 node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t));
666 dns_name_init(node->name, NULL);
667 dns_name_dup(name, sdlz->common.mctx, node->name);
668 }
669
670 *nodep = node;
671 return (ISC_R_SUCCESS);
672 }
673
674 static isc_result_t
675 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
676 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
677 dns_dbnode_t **nodep) {
678 return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
679 }
680
681 static isc_result_t
682 findnode(dns_db_t *db, const dns_name_t *name, bool create,
683 dns_dbnode_t **nodep) {
684 return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
685 }
686
687 static isc_result_t
688 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
689 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
690 dns_name_t *dcname, dns_rdataset_t *rdataset,
691 dns_rdataset_t *sigrdataset) {
692 UNUSED(db);
693 UNUSED(name);
694 UNUSED(options);
695 UNUSED(now);
696 UNUSED(nodep);
697 UNUSED(foundname);
698 UNUSED(dcname);
699 UNUSED(rdataset);
700 UNUSED(sigrdataset);
701
702 return (ISC_R_NOTIMPLEMENTED);
703 }
704
705 static void
706 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
707 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
708 dns_sdlznode_t *node = (dns_sdlznode_t *)source;
709
710 REQUIRE(VALID_SDLZDB(sdlz));
711
712 UNUSED(sdlz);
713
714 isc_refcount_increment(&node->references);
715
716 *targetp = source;
717 }
718
719 static void
720 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
721 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
722 dns_sdlznode_t *node;
723
724 REQUIRE(VALID_SDLZDB(sdlz));
725 REQUIRE(targetp != NULL && *targetp != NULL);
726
727 UNUSED(sdlz);
728
729 node = (dns_sdlznode_t *)(*targetp);
730 *targetp = NULL;
731
732 if (isc_refcount_decrement(&node->references) == 1) {
733 destroynode(node);
734 }
735 }
736
737 static isc_result_t
738 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
739 UNUSED(db);
740 UNUSED(node);
741 UNUSED(now);
742 UNREACHABLE();
743 }
744
745 static void
746 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
747 UNUSED(db);
748 UNUSED(node);
749 UNUSED(out);
750 return;
751 }
752
753 static isc_result_t
754 createiterator(dns_db_t *db, unsigned int options,
755 dns_dbiterator_t **iteratorp) {
756 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
757 sdlz_dbiterator_t *sdlziter;
758 isc_result_t result;
759 isc_buffer_t b;
760 char zonestr[DNS_NAME_MAXTEXT + 1];
761
762 REQUIRE(VALID_SDLZDB(sdlz));
763
764 if (sdlz->dlzimp->methods->allnodes == NULL) {
765 return (ISC_R_NOTIMPLEMENTED);
766 }
767
768 if ((options & DNS_DB_NSEC3ONLY) != 0 ||
769 (options & DNS_DB_NONSEC3) != 0)
770 {
771 return (ISC_R_NOTIMPLEMENTED);
772 }
773
774 isc_buffer_init(&b, zonestr, sizeof(zonestr));
775 result = dns_name_totext(&sdlz->common.origin, true, &b);
776 if (result != ISC_R_SUCCESS) {
777 return (result);
778 }
779 isc_buffer_putuint8(&b, 0);
780
781 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
782
783 sdlziter->common.methods = &dbiterator_methods;
784 sdlziter->common.db = NULL;
785 dns_db_attach(db, &sdlziter->common.db);
786 sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
787 0);
788 sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
789 ISC_LIST_INIT(sdlziter->nodelist);
790 sdlziter->current = NULL;
791 sdlziter->origin = NULL;
792
793 /* make sure strings are always lowercase */
794 dns_sdlz_tolower(zonestr);
795
796 MAYBE_LOCK(sdlz->dlzimp);
797 result = sdlz->dlzimp->methods->allnodes(
798 zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter);
799 MAYBE_UNLOCK(sdlz->dlzimp);
800 if (result != ISC_R_SUCCESS) {
801 dns_dbiterator_t *iter = &sdlziter->common;
802 dbiterator_destroy(&iter);
803 return (result);
804 }
805
806 if (sdlziter->origin != NULL) {
807 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
808 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
809 }
810
811 *iteratorp = (dns_dbiterator_t *)sdlziter;
812
813 return (ISC_R_SUCCESS);
814 }
815
816 static isc_result_t
817 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
818 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
819 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
820 REQUIRE(VALID_SDLZNODE(node));
821 dns_rdatalist_t *list;
822 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
823
824 UNUSED(db);
825 UNUSED(version);
826 UNUSED(covers);
827 UNUSED(now);
828 UNUSED(sigrdataset);
829
830 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) {
831 return (ISC_R_NOTIMPLEMENTED);
832 }
833
834 list = ISC_LIST_HEAD(sdlznode->lists);
835 while (list != NULL) {
836 if (list->type == type) {
837 break;
838 }
839 list = ISC_LIST_NEXT(list, link);
840 }
841 if (list == NULL) {
842 return (ISC_R_NOTFOUND);
843 }
844
845 list_tordataset(list, db, node, rdataset);
846
847 return (ISC_R_SUCCESS);
848 }
849
850 static isc_result_t
851 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
852 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
853 dns_dbnode_t **nodep, dns_name_t *foundname,
854 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
855 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
856 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
857 dns_dbnode_t *node = NULL;
858 dns_fixedname_t fname;
859 dns_rdataset_t xrdataset;
860 dns_name_t *xname;
861 unsigned int nlabels, olabels;
862 isc_result_t result;
863 unsigned int i;
864
865 REQUIRE(VALID_SDLZDB(sdlz));
866 REQUIRE(nodep == NULL || *nodep == NULL);
867 REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
868 version == sdlz->future_version);
869
870 UNUSED(sdlz);
871
872 if (!dns_name_issubdomain(name, &db->origin)) {
873 return (DNS_R_NXDOMAIN);
874 }
875
876 olabels = dns_name_countlabels(&db->origin);
877 nlabels = dns_name_countlabels(name);
878
879 xname = dns_fixedname_initname(&fname);
880
881 if (rdataset == NULL) {
882 dns_rdataset_init(&xrdataset);
883 rdataset = &xrdataset;
884 }
885
886 result = DNS_R_NXDOMAIN;
887
888 /*
889 * If we're not walking down searching for zone
890 * cuts, we can cut straight to the chase
891 */
892 if ((options & DNS_DBFIND_NOZONECUT) != 0) {
893 i = nlabels;
894 goto search;
895 }
896
897 for (i = olabels; i <= nlabels; i++) {
898 search:
899 /*
900 * Look up the next label.
901 */
902 dns_name_getlabelsequence(name, nlabels - i, i, xname);
903 result = getnodedata(db, xname, false, options, methods,
904 clientinfo, &node);
905 if (result == ISC_R_NOTFOUND) {
906 result = DNS_R_NXDOMAIN;
907 continue;
908 } else if (result != ISC_R_SUCCESS) {
909 break;
910 }
911
912 /*
913 * Look for a DNAME at the current label, unless this is
914 * the qname.
915 */
916 if (i < nlabels) {
917 result = findrdataset(db, node, version,
918 dns_rdatatype_dname, 0, now,
919 rdataset, sigrdataset);
920 if (result == ISC_R_SUCCESS) {
921 result = DNS_R_DNAME;
922 break;
923 }
924 }
925
926 /*
927 * Look for an NS at the current label, unless this is the
928 * origin, glue is ok, or there are known to be no zone cuts.
929 */
930 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
931 (options & DNS_DBFIND_NOZONECUT) == 0)
932 {
933 result = findrdataset(db, node, version,
934 dns_rdatatype_ns, 0, now,
935 rdataset, sigrdataset);
936
937 if (result == ISC_R_SUCCESS && i == nlabels &&
938 type == dns_rdatatype_any)
939 {
940 result = DNS_R_ZONECUT;
941 dns_rdataset_disassociate(rdataset);
942 if (sigrdataset != NULL &&
943 dns_rdataset_isassociated(sigrdataset))
944 {
945 dns_rdataset_disassociate(sigrdataset);
946 }
947 break;
948 } else if (result == ISC_R_SUCCESS) {
949 result = DNS_R_DELEGATION;
950 break;
951 }
952 }
953
954 /*
955 * If the current name is not the qname, add another label
956 * and try again.
957 */
958 if (i < nlabels) {
959 detachnode(db, &node);
960 node = NULL;
961 continue;
962 }
963
964 /*
965 * If we're looking for ANY, we're done.
966 */
967 if (type == dns_rdatatype_any) {
968 result = ISC_R_SUCCESS;
969 break;
970 }
971
972 /*
973 * Look for the qtype.
974 */
975 result = findrdataset(db, node, version, type, 0, now, rdataset,
976 sigrdataset);
977 if (result == ISC_R_SUCCESS) {
978 break;
979 }
980
981 /*
982 * Look for a CNAME
983 */
984 if (type != dns_rdatatype_cname) {
985 result = findrdataset(db, node, version,
986 dns_rdatatype_cname, 0, now,
987 rdataset, sigrdataset);
988 if (result == ISC_R_SUCCESS) {
989 result = DNS_R_CNAME;
990 break;
991 }
992 }
993
994 result = DNS_R_NXRRSET;
995 break;
996 }
997
998 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
999 dns_rdataset_disassociate(rdataset);
1000 }
1001
1002 if (foundname != NULL) {
1003 dns_name_copy(xname, foundname);
1004 }
1005
1006 if (nodep != NULL) {
1007 *nodep = node;
1008 } else if (node != NULL) {
1009 detachnode(db, &node);
1010 }
1011
1012 return (result);
1013 }
1014
1015 static isc_result_t
1016 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
1017 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
1018 dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
1019 dns_rdataset_t *sigrdataset) {
1020 return (findext(db, name, version, type, options, now, nodep, foundname,
1021 NULL, NULL, rdataset, sigrdataset));
1022 }
1023
1024 static isc_result_t
1025 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1026 unsigned int options, isc_stdtime_t now,
1027 dns_rdatasetiter_t **iteratorp) {
1028 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1029 sdlz_rdatasetiter_t *iterator;
1030
1031 REQUIRE(VALID_SDLZDB(sdlz));
1032
1033 REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
1034 version == sdlz->future_version);
1035
1036 UNUSED(version);
1037 UNUSED(now);
1038
1039 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
1040
1041 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1042 iterator->common.methods = &rdatasetiter_methods;
1043 iterator->common.db = db;
1044 iterator->common.node = NULL;
1045 attachnode(db, node, &iterator->common.node);
1046 iterator->common.version = version;
1047 iterator->common.options = options;
1048 iterator->common.now = now;
1049
1050 *iteratorp = (dns_rdatasetiter_t *)iterator;
1051
1052 return (ISC_R_SUCCESS);
1053 }
1054
1055 static isc_result_t
1056 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1057 dns_rdataset_t *rdataset, unsigned int options,
1058 dns_sdlzmodrdataset_t mod_function) {
1059 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1060 dns_master_style_t *style = NULL;
1061 isc_result_t result;
1062 isc_buffer_t *buffer = NULL;
1063 isc_mem_t *mctx;
1064 dns_sdlznode_t *sdlznode;
1065 char *rdatastr = NULL;
1066 char name[DNS_NAME_MAXTEXT + 1];
1067
1068 REQUIRE(VALID_SDLZDB(sdlz));
1069
1070 if (mod_function == NULL) {
1071 return (ISC_R_NOTIMPLEMENTED);
1072 }
1073
1074 sdlznode = (dns_sdlznode_t *)node;
1075
1076 UNUSED(options);
1077
1078 dns_name_format(sdlznode->name, name, sizeof(name));
1079
1080 mctx = sdlz->common.mctx;
1081
1082 isc_buffer_allocate(mctx, &buffer, 1024);
1083
1084 result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff,
1085 mctx);
1086 if (result != ISC_R_SUCCESS) {
1087 goto cleanup;
1088 }
1089
1090 result = dns_master_rdatasettotext(sdlznode->name, rdataset, style,
1091 NULL, buffer);
1092 if (result != ISC_R_SUCCESS) {
1093 goto cleanup;
1094 }
1095
1096 if (isc_buffer_usedlength(buffer) < 1) {
1097 result = ISC_R_BADADDRESSFORM;
1098 goto cleanup;
1099 }
1100
1101 rdatastr = isc_buffer_base(buffer);
1102 if (rdatastr == NULL) {
1103 result = ISC_R_NOMEMORY;
1104 goto cleanup;
1105 }
1106 rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
1107
1108 MAYBE_LOCK(sdlz->dlzimp);
1109 result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
1110 sdlz->dbdata, version);
1111 MAYBE_UNLOCK(sdlz->dlzimp);
1112
1113 cleanup:
1114 isc_buffer_free(&buffer);
1115 if (style != NULL) {
1116 dns_master_styledestroy(&style, mctx);
1117 }
1118
1119 return (result);
1120 }
1121
1122 static isc_result_t
1123 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1124 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1125 dns_rdataset_t *addedrdataset) {
1126 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1127 isc_result_t result;
1128
1129 UNUSED(now);
1130 UNUSED(addedrdataset);
1131 REQUIRE(VALID_SDLZDB(sdlz));
1132
1133 if (sdlz->dlzimp->methods->addrdataset == NULL) {
1134 return (ISC_R_NOTIMPLEMENTED);
1135 }
1136
1137 result = modrdataset(db, node, version, rdataset, options,
1138 sdlz->dlzimp->methods->addrdataset);
1139 return (result);
1140 }
1141
1142 static isc_result_t
1143 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1144 dns_rdataset_t *rdataset, unsigned int options,
1145 dns_rdataset_t *newrdataset) {
1146 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1147 isc_result_t result;
1148
1149 UNUSED(newrdataset);
1150 REQUIRE(VALID_SDLZDB(sdlz));
1151
1152 if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
1153 return (ISC_R_NOTIMPLEMENTED);
1154 }
1155
1156 result = modrdataset(db, node, version, rdataset, options,
1157 sdlz->dlzimp->methods->subtractrdataset);
1158 return (result);
1159 }
1160
1161 static isc_result_t
1162 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1163 dns_rdatatype_t type, dns_rdatatype_t covers) {
1164 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1165 char name[DNS_NAME_MAXTEXT + 1];
1166 char b_type[DNS_RDATATYPE_FORMATSIZE];
1167 dns_sdlznode_t *sdlznode;
1168 isc_result_t result;
1169
1170 UNUSED(covers);
1171
1172 REQUIRE(VALID_SDLZDB(sdlz));
1173
1174 if (sdlz->dlzimp->methods->delrdataset == NULL) {
1175 return (ISC_R_NOTIMPLEMENTED);
1176 }
1177
1178 sdlznode = (dns_sdlznode_t *)node;
1179 dns_name_format(sdlznode->name, name, sizeof(name));
1180 dns_rdatatype_format(type, b_type, sizeof(b_type));
1181
1182 MAYBE_LOCK(sdlz->dlzimp);
1183 result = sdlz->dlzimp->methods->delrdataset(
1184 name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version);
1185 MAYBE_UNLOCK(sdlz->dlzimp);
1186
1187 return (result);
1188 }
1189
1190 static bool
1191 issecure(dns_db_t *db) {
1192 UNUSED(db);
1193
1194 return (false);
1195 }
1196
1197 static unsigned int
1198 nodecount(dns_db_t *db, dns_dbtree_t tree) {
1199 UNUSED(db);
1200 UNUSED(tree);
1201
1202 return (0);
1203 }
1204
1205 static bool
1206 ispersistent(dns_db_t *db) {
1207 UNUSED(db);
1208 return (true);
1209 }
1210
1211 static void
1212 overmem(dns_db_t *db, bool over) {
1213 UNUSED(db);
1214 UNUSED(over);
1215 }
1216
1217 static void
1218 settask(dns_db_t *db, isc_task_t *task) {
1219 UNUSED(db);
1220 UNUSED(task);
1221 }
1222
1223 /*
1224 * getoriginnode() is used by the update code to find the
1225 * dns_rdatatype_dnskey record for a zone
1226 */
1227 static isc_result_t
1228 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
1229 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1230 isc_result_t result;
1231
1232 REQUIRE(VALID_SDLZDB(sdlz));
1233 if (sdlz->dlzimp->methods->newversion == NULL) {
1234 return (ISC_R_NOTIMPLEMENTED);
1235 }
1236
1237 result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL,
1238 nodep);
1239 if (result != ISC_R_SUCCESS) {
1240 sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
1241 isc_result_totext(result));
1242 }
1243 return (result);
1244 }
1245
1246 static dns_dbmethods_t sdlzdb_methods = {
1247 attach, detach, beginload,
1248 endload, dump, currentversion,
1249 newversion, attachversion, closeversion,
1250 findnode, find, findzonecut,
1251 attachnode, detachnode, expirenode,
1252 printnode, createiterator, findrdataset,
1253 allrdatasets, addrdataset, subtractrdataset,
1254 deleterdataset, issecure, nodecount,
1255 ispersistent, overmem, settask,
1256 getoriginnode, NULL, /* transfernode */
1257 NULL, /* getnsec3parameters */
1258 NULL, /* findnsec3node */
1259 NULL, /* setsigningtime */
1260 NULL, /* getsigningtime */
1261 NULL, /* resigned */
1262 NULL, /* isdnssec */
1263 NULL, /* getrrsetstats */
1264 NULL, /* rpz_attach */
1265 NULL, /* rpz_ready */
1266 findnodeext, findext, NULL, /* setcachestats */
1267 NULL, /* hashsize */
1268 NULL, /* nodefullname */
1269 NULL, /* getsize */
1270 NULL, /* setservestalettl */
1271 NULL, /* getservestalettl */
1272 NULL, /* setservestalerefresh */
1273 NULL, /* getservestalerefresh */
1274 NULL, /* setgluecachestats */
1275 };
1276
1277 /*
1278 * Database Iterator Methods. These methods were "borrowed" from the SDB
1279 * driver interface. See the SDB driver interface documentation for more info.
1280 */
1281
1282 static void
1283 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1284 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1285 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1286
1287 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1288 dns_sdlznode_t *node;
1289 node = ISC_LIST_HEAD(sdlziter->nodelist);
1290 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1291 isc_refcount_decrementz(&node->references);
1292 destroynode(node);
1293 }
1294
1295 dns_db_detach(&sdlziter->common.db);
1296 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1297
1298 *iteratorp = NULL;
1299 }
1300
1301 static isc_result_t
1302 dbiterator_first(dns_dbiterator_t *iterator) {
1303 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1304
1305 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1306 if (sdlziter->current == NULL) {
1307 return (ISC_R_NOMORE);
1308 } else {
1309 return (ISC_R_SUCCESS);
1310 }
1311 }
1312
1313 static isc_result_t
1314 dbiterator_last(dns_dbiterator_t *iterator) {
1315 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1316
1317 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1318 if (sdlziter->current == NULL) {
1319 return (ISC_R_NOMORE);
1320 } else {
1321 return (ISC_R_SUCCESS);
1322 }
1323 }
1324
1325 static isc_result_t
1326 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1327 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1328
1329 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1330 while (sdlziter->current != NULL) {
1331 if (dns_name_equal(sdlziter->current->name, name)) {
1332 return (ISC_R_SUCCESS);
1333 }
1334 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1335 }
1336 return (ISC_R_NOTFOUND);
1337 }
1338
1339 static isc_result_t
1340 dbiterator_prev(dns_dbiterator_t *iterator) {
1341 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1342
1343 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1344 if (sdlziter->current == NULL) {
1345 return (ISC_R_NOMORE);
1346 } else {
1347 return (ISC_R_SUCCESS);
1348 }
1349 }
1350
1351 static isc_result_t
1352 dbiterator_next(dns_dbiterator_t *iterator) {
1353 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1354
1355 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1356 if (sdlziter->current == NULL) {
1357 return (ISC_R_NOMORE);
1358 } else {
1359 return (ISC_R_SUCCESS);
1360 }
1361 }
1362
1363 static isc_result_t
1364 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1365 dns_name_t *name) {
1366 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1367
1368 attachnode(iterator->db, sdlziter->current, nodep);
1369 if (name != NULL) {
1370 dns_name_copy(sdlziter->current->name, name);
1371 return (ISC_R_SUCCESS);
1372 }
1373 return (ISC_R_SUCCESS);
1374 }
1375
1376 static isc_result_t
1377 dbiterator_pause(dns_dbiterator_t *iterator) {
1378 UNUSED(iterator);
1379 return (ISC_R_SUCCESS);
1380 }
1381
1382 static isc_result_t
1383 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1384 UNUSED(iterator);
1385 dns_name_copy(dns_rootname, name);
1386 return (ISC_R_SUCCESS);
1387 }
1388
1389 /*
1390 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1391 * interface. See the SDB driver interface documentation for more info.
1392 */
1393
1394 static void
1395 disassociate(dns_rdataset_t *rdataset) {
1396 dns_dbnode_t *node = rdataset->private5;
1397 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1398 dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1399
1400 detachnode(db, &node);
1401 isc__rdatalist_disassociate(rdataset);
1402 }
1403
1404 static void
1405 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1406 dns_dbnode_t *node = source->private5;
1407 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1408 dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1409 dns_dbnode_t *tempdb = NULL;
1410
1411 isc__rdatalist_clone(source, target);
1412 attachnode(db, node, &tempdb);
1413 source->private5 = tempdb;
1414 }
1415
1416 static dns_rdatasetmethods_t rdataset_methods = {
1417 disassociate,
1418 isc__rdatalist_first,
1419 isc__rdatalist_next,
1420 isc__rdatalist_current,
1421 rdataset_clone,
1422 isc__rdatalist_count,
1423 isc__rdatalist_addnoqname,
1424 isc__rdatalist_getnoqname,
1425 NULL, /* addclosest */
1426 NULL, /* getclosest */
1427 NULL, /* settrust */
1428 NULL, /* expire */
1429 NULL, /* clearprefetch */
1430 NULL, /* setownercase */
1431 NULL, /* getownercase */
1432 NULL /* addglue */
1433 };
1434
1435 static void
1436 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
1437 dns_rdataset_t *rdataset) {
1438 /*
1439 * The sdlz rdataset is an rdatalist with some additions.
1440 * - private1 & private2 are used by the rdatalist.
1441 * - private3 & private 4 are unused.
1442 * - private5 is the node.
1443 */
1444
1445 /* This should never fail. */
1446 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1447 ISC_R_SUCCESS);
1448
1449 rdataset->methods = &rdataset_methods;
1450 dns_db_attachnode(db, node, &rdataset->private5);
1451 }
1452
1453 /*
1454 * SDLZ core methods. This is the core of the new DLZ functionality.
1455 */
1456
1457 /*%
1458 * Build a 'bind' database driver structure to be returned by
1459 * either the find zone or the allow zone transfer method.
1460 * This method is only available in this source file, it is
1461 * not made available anywhere else.
1462 */
1463
1464 static isc_result_t
1465 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1466 const dns_name_t *name, dns_rdataclass_t rdclass,
1467 dns_db_t **dbp) {
1468 isc_result_t result;
1469 dns_sdlz_db_t *sdlzdb;
1470 dns_sdlzimplementation_t *imp;
1471
1472 /* check that things are as we expect */
1473 REQUIRE(dbp != NULL && *dbp == NULL);
1474 REQUIRE(name != NULL);
1475
1476 imp = (dns_sdlzimplementation_t *)driverarg;
1477
1478 /* allocate and zero memory for driver structure */
1479 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1480 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1481
1482 /* initialize and set origin */
1483 dns_name_init(&sdlzdb->common.origin, NULL);
1484 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1485 if (result != ISC_R_SUCCESS) {
1486 goto mem_cleanup;
1487 }
1488
1489 /* set the rest of the database structure attributes */
1490 sdlzdb->dlzimp = imp;
1491 sdlzdb->common.methods = &sdlzdb_methods;
1492 sdlzdb->common.attributes = 0;
1493 sdlzdb->common.rdclass = rdclass;
1494 sdlzdb->common.mctx = NULL;
1495 sdlzdb->dbdata = dbdata;
1496 isc_refcount_init(&sdlzdb->references, 1);
1497
1498 /* attach to the memory context */
1499 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1500
1501 /* mark structure as valid */
1502 sdlzdb->common.magic = DNS_DB_MAGIC;
1503 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1504 *dbp = (dns_db_t *)sdlzdb;
1505
1506 return (result);
1507 mem_cleanup:
1508 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1509 return (result);
1510 }
1511
1512 static isc_result_t
1513 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1514 dns_rdataclass_t rdclass, const dns_name_t *name,
1515 const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
1516 isc_buffer_t b;
1517 isc_buffer_t b2;
1518 char namestr[DNS_NAME_MAXTEXT + 1];
1519 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
1520 "255") +
1521 1];
1522 isc_netaddr_t netaddr;
1523 isc_result_t result;
1524 dns_sdlzimplementation_t *imp;
1525
1526 /*
1527 * Perform checks to make sure data is as we expect it to be.
1528 */
1529 REQUIRE(driverarg != NULL);
1530 REQUIRE(name != NULL);
1531 REQUIRE(clientaddr != NULL);
1532 REQUIRE(dbp != NULL && *dbp == NULL);
1533
1534 imp = (dns_sdlzimplementation_t *)driverarg;
1535
1536 /* Convert DNS name to ascii text */
1537 isc_buffer_init(&b, namestr, sizeof(namestr));
1538 result = dns_name_totext(name, true, &b);
1539 if (result != ISC_R_SUCCESS) {
1540 return (result);
1541 }
1542 isc_buffer_putuint8(&b, 0);
1543
1544 /* convert client address to ascii text */
1545 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1546 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1547 result = isc_netaddr_totext(&netaddr, &b2);
1548 if (result != ISC_R_SUCCESS) {
1549 return (result);
1550 }
1551 isc_buffer_putuint8(&b2, 0);
1552
1553 /* make sure strings are always lowercase */
1554 dns_sdlz_tolower(namestr);
1555 dns_sdlz_tolower(clientstr);
1556
1557 /* Call SDLZ driver's find zone method */
1558 if (imp->methods->allowzonexfr != NULL) {
1559 isc_result_t rresult = ISC_R_SUCCESS;
1560
1561 MAYBE_LOCK(imp);
1562 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1563 namestr, clientstr);
1564 MAYBE_UNLOCK(imp);
1565 /*
1566 * if zone is supported and transfers are (or might be)
1567 * allowed, build a 'bind' database driver
1568 */
1569 if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
1570 rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1571 name, rdclass, dbp);
1572 }
1573 if (rresult != ISC_R_SUCCESS) {
1574 result = rresult;
1575 }
1576 return (result);
1577 }
1578
1579 return (ISC_R_NOTIMPLEMENTED);
1580 }
1581
1582 static isc_result_t
1583 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1584 char *argv[], void *driverarg, void **dbdata) {
1585 dns_sdlzimplementation_t *imp;
1586 isc_result_t result = ISC_R_NOTFOUND;
1587
1588 /* Write debugging message to log */
1589 sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1590
1591 /*
1592 * Performs checks to make sure data is as we expect it to be.
1593 */
1594 REQUIRE(driverarg != NULL);
1595 REQUIRE(dlzname != NULL);
1596 REQUIRE(dbdata != NULL);
1597 UNUSED(mctx);
1598
1599 imp = driverarg;
1600
1601 /* If the create method exists, call it. */
1602 if (imp->methods->create != NULL) {
1603 MAYBE_LOCK(imp);
1604 result = imp->methods->create(dlzname, argc, argv,
1605 imp->driverarg, dbdata);
1606 MAYBE_UNLOCK(imp);
1607 }
1608
1609 /* Write debugging message to log */
1610 if (result == ISC_R_SUCCESS) {
1611 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1612 } else {
1613 sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1614 }
1615
1616 return (result);
1617 }
1618
1619 static void
1620 dns_sdlzdestroy(void *driverdata, void **dbdata) {
1621 dns_sdlzimplementation_t *imp;
1622
1623 /* Write debugging message to log */
1624 sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1625
1626 imp = driverdata;
1627
1628 /* If the destroy method exists, call it. */
1629 if (imp->methods->destroy != NULL) {
1630 MAYBE_LOCK(imp);
1631 imp->methods->destroy(imp->driverarg, dbdata);
1632 MAYBE_UNLOCK(imp);
1633 }
1634 }
1635
1636 static isc_result_t
1637 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1638 dns_rdataclass_t rdclass, const dns_name_t *name,
1639 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
1640 dns_db_t **dbp) {
1641 isc_buffer_t b;
1642 char namestr[DNS_NAME_MAXTEXT + 1];
1643 isc_result_t result;
1644 dns_sdlzimplementation_t *imp;
1645
1646 /*
1647 * Perform checks to make sure data is as we expect it to be.
1648 */
1649 REQUIRE(driverarg != NULL);
1650 REQUIRE(name != NULL);
1651 REQUIRE(dbp != NULL && *dbp == NULL);
1652
1653 imp = (dns_sdlzimplementation_t *)driverarg;
1654
1655 /* Convert DNS name to ascii text */
1656 isc_buffer_init(&b, namestr, sizeof(namestr));
1657 result = dns_name_totext(name, true, &b);
1658 if (result != ISC_R_SUCCESS) {
1659 return (result);
1660 }
1661 isc_buffer_putuint8(&b, 0);
1662
1663 /* make sure strings are always lowercase */
1664 dns_sdlz_tolower(namestr);
1665
1666 /* Call SDLZ driver's find zone method */
1667 MAYBE_LOCK(imp);
1668 result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1669 methods, clientinfo);
1670 MAYBE_UNLOCK(imp);
1671
1672 /*
1673 * if zone is supported build a 'bind' database driver
1674 * structure to return
1675 */
1676 if (result == ISC_R_SUCCESS) {
1677 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1678 rdclass, dbp);
1679 }
1680
1681 return (result);
1682 }
1683
1684 static isc_result_t
1685 dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
1686 dns_dlzdb_t *dlzdb) {
1687 isc_result_t result;
1688 dns_sdlzimplementation_t *imp;
1689
1690 REQUIRE(driverarg != NULL);
1691
1692 imp = (dns_sdlzimplementation_t *)driverarg;
1693
1694 /* Call SDLZ driver's configure method */
1695 if (imp->methods->configure != NULL) {
1696 MAYBE_LOCK(imp);
1697 result = imp->methods->configure(view, dlzdb, imp->driverarg,
1698 dbdata);
1699 MAYBE_UNLOCK(imp);
1700 } else {
1701 result = ISC_R_SUCCESS;
1702 }
1703
1704 return (result);
1705 }
1706
1707 static bool
1708 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
1709 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
1710 const dst_key_t *key, void *driverarg, void *dbdata) {
1711 dns_sdlzimplementation_t *imp;
1712 char b_signer[DNS_NAME_FORMATSIZE];
1713 char b_name[DNS_NAME_FORMATSIZE];
1714 char b_addr[ISC_NETADDR_FORMATSIZE];
1715 char b_type[DNS_RDATATYPE_FORMATSIZE];
1716 char b_key[DST_KEY_FORMATSIZE];
1717 isc_buffer_t *tkey_token = NULL;
1718 isc_region_t token_region = { NULL, 0 };
1719 uint32_t token_len = 0;
1720 bool ret;
1721
1722 REQUIRE(driverarg != NULL);
1723
1724 imp = (dns_sdlzimplementation_t *)driverarg;
1725 if (imp->methods->ssumatch == NULL) {
1726 return (false);
1727 }
1728
1729 /*
1730 * Format the request elements. sdlz operates on strings, not
1731 * structures
1732 */
1733 if (signer != NULL) {
1734 dns_name_format(signer, b_signer, sizeof(b_signer));
1735 } else {
1736 b_signer[0] = 0;
1737 }
1738
1739 dns_name_format(name, b_name, sizeof(b_name));
1740
1741 if (tcpaddr != NULL) {
1742 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
1743 } else {
1744 b_addr[0] = 0;
1745 }
1746
1747 dns_rdatatype_format(type, b_type, sizeof(b_type));
1748
1749 if (key != NULL) {
1750 dst_key_format(key, b_key, sizeof(b_key));
1751 tkey_token = dst_key_tkeytoken(key);
1752 } else {
1753 b_key[0] = 0;
1754 }
1755
1756 if (tkey_token != NULL) {
1757 isc_buffer_region(tkey_token, &token_region);
1758 token_len = token_region.length;
1759 }
1760
1761 MAYBE_LOCK(imp);
1762 ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1763 token_len,
1764 token_len != 0 ? token_region.base : NULL,
1765 imp->driverarg, dbdata);
1766 MAYBE_UNLOCK(imp);
1767 return (ret);
1768 }
1769
1770 static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy,
1771 dns_sdlzfindzone, dns_sdlzallowzonexfr,
1772 dns_sdlzconfigure, dns_sdlzssumatch };
1773
1774 /*
1775 * Public functions.
1776 */
1777
1778 isc_result_t
1779 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1780 const char *data) {
1781 dns_rdatalist_t *rdatalist;
1782 dns_rdata_t *rdata;
1783 dns_rdatatype_t typeval;
1784 isc_consttextregion_t r;
1785 isc_buffer_t b;
1786 isc_buffer_t *rdatabuf = NULL;
1787 isc_lex_t *lex;
1788 isc_result_t result;
1789 unsigned int size;
1790 isc_mem_t *mctx;
1791 const dns_name_t *origin;
1792
1793 REQUIRE(VALID_SDLZLOOKUP(lookup));
1794 REQUIRE(type != NULL);
1795 REQUIRE(data != NULL);
1796
1797 mctx = lookup->sdlz->common.mctx;
1798
1799 r.base = type;
1800 r.length = strlen(type);
1801 result = dns_rdatatype_fromtext(&typeval, (void *)&r);
1802 if (result != ISC_R_SUCCESS) {
1803 return (result);
1804 }
1805
1806 rdatalist = ISC_LIST_HEAD(lookup->lists);
1807 while (rdatalist != NULL) {
1808 if (rdatalist->type == typeval) {
1809 break;
1810 }
1811 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1812 }
1813
1814 if (rdatalist == NULL) {
1815 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1816 dns_rdatalist_init(rdatalist);
1817 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1818 rdatalist->type = typeval;
1819 rdatalist->ttl = ttl;
1820 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1821 } else if (rdatalist->ttl > ttl) {
1822 /*
1823 * BIND9 doesn't enforce all RRs in an RRset
1824 * having the same TTL, as per RFC 2136,
1825 * section 7.12. If a DLZ backend has
1826 * different TTLs, then the best
1827 * we can do is return the lowest.
1828 */
1829 rdatalist->ttl = ttl;
1830 }
1831
1832 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1833 dns_rdata_init(rdata);
1834
1835 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1836 origin = &lookup->sdlz->common.origin;
1837 } else {
1838 origin = dns_rootname;
1839 }
1840
1841 lex = NULL;
1842 result = isc_lex_create(mctx, 64, &lex);
1843 if (result != ISC_R_SUCCESS) {
1844 goto failure;
1845 }
1846
1847 size = initial_size(data);
1848 do {
1849 isc_buffer_constinit(&b, data, strlen(data));
1850 isc_buffer_add(&b, strlen(data));
1851
1852 result = isc_lex_openbuffer(lex, &b);
1853 if (result != ISC_R_SUCCESS) {
1854 goto failure;
1855 }
1856
1857 rdatabuf = NULL;
1858 isc_buffer_allocate(mctx, &rdatabuf, size);
1859
1860 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1861 rdatalist->type, lex, origin, false,
1862 mctx, rdatabuf, &lookup->callbacks);
1863 if (result != ISC_R_SUCCESS) {
1864 isc_buffer_free(&rdatabuf);
1865 }
1866 if (size >= 65535) {
1867 break;
1868 }
1869 size *= 2;
1870 if (size >= 65535) {
1871 size = 65535;
1872 }
1873 } while (result == ISC_R_NOSPACE);
1874
1875 if (result != ISC_R_SUCCESS) {
1876 result = DNS_R_SERVFAIL;
1877 goto failure;
1878 }
1879
1880 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1881 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1882
1883 if (lex != NULL) {
1884 isc_lex_destroy(&lex);
1885 }
1886
1887 return (ISC_R_SUCCESS);
1888
1889 failure:
1890 if (rdatabuf != NULL) {
1891 isc_buffer_free(&rdatabuf);
1892 }
1893 if (lex != NULL) {
1894 isc_lex_destroy(&lex);
1895 }
1896 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1897
1898 return (result);
1899 }
1900
1901 isc_result_t
1902 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1903 const char *type, dns_ttl_t ttl, const char *data) {
1904 dns_name_t *newname;
1905 const dns_name_t *origin;
1906 dns_fixedname_t fnewname;
1907 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1908 dns_sdlznode_t *sdlznode;
1909 isc_mem_t *mctx = sdlz->common.mctx;
1910 isc_buffer_t b;
1911 isc_result_t result;
1912
1913 newname = dns_fixedname_initname(&fnewname);
1914
1915 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1916 origin = &sdlz->common.origin;
1917 } else {
1918 origin = dns_rootname;
1919 }
1920 isc_buffer_constinit(&b, name, strlen(name));
1921 isc_buffer_add(&b, strlen(name));
1922
1923 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1924 if (result != ISC_R_SUCCESS) {
1925 return (result);
1926 }
1927
1928 if (allnodes->common.relative_names) {
1929 /* All names are relative to the root */
1930 unsigned int nlabels = dns_name_countlabels(newname);
1931 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1932 }
1933
1934 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1935 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1936 sdlznode = NULL;
1937 result = createnode(sdlz, &sdlznode);
1938 if (result != ISC_R_SUCCESS) {
1939 return (result);
1940 }
1941 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1942 dns_name_init(sdlznode->name, NULL);
1943 dns_name_dup(newname, mctx, sdlznode->name);
1944 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1945 if (allnodes->origin == NULL &&
1946 dns_name_equal(newname, &sdlz->common.origin))
1947 {
1948 allnodes->origin = sdlznode;
1949 }
1950 }
1951 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1952 }
1953
1954 isc_result_t
1955 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1956 uint32_t serial) {
1957 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1958 int n;
1959
1960 REQUIRE(mname != NULL);
1961 REQUIRE(rname != NULL);
1962
1963 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
1964 serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1965 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1966 if (n >= (int)sizeof(str) || n < 0) {
1967 return (ISC_R_NOSPACE);
1968 }
1969 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1970 }
1971
1972 isc_result_t
1973 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1974 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1975 dns_sdlzimplementation_t **sdlzimp) {
1976 dns_sdlzimplementation_t *imp;
1977 isc_result_t result;
1978
1979 /*
1980 * Performs checks to make sure data is as we expect it to be.
1981 */
1982 REQUIRE(drivername != NULL);
1983 REQUIRE(methods != NULL);
1984 REQUIRE(methods->findzone != NULL);
1985 REQUIRE(methods->lookup != NULL);
1986 REQUIRE(mctx != NULL);
1987 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
1988 REQUIRE((flags &
1989 ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
1990 DNS_SDLZFLAG_THREADSAFE)) == 0);
1991
1992 /* Write debugging message to log */
1993 sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
1994
1995 /*
1996 * Allocate memory for a sdlz_implementation object. Error if
1997 * we cannot.
1998 */
1999 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2000
2001 /* Make sure memory region is set to all 0's */
2002 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2003
2004 /* Store the data passed into this method */
2005 imp->methods = methods;
2006 imp->driverarg = driverarg;
2007 imp->flags = flags;
2008 imp->mctx = NULL;
2009
2010 /* attach the new sdlz_implementation object to a memory context */
2011 isc_mem_attach(mctx, &imp->mctx);
2012
2013 /*
2014 * initialize the driver lock, error if we cannot
2015 * (used if a driver does not support multiple threads)
2016 */
2017 isc_mutex_init(&imp->driverlock);
2018
2019 imp->dlz_imp = NULL;
2020
2021 /*
2022 * register the DLZ driver. Pass in our "extra" sdlz information as
2023 * a driverarg. (that's why we stored the passed in driver arg in our
2024 * sdlz_implementation structure) Also, store the dlz_implementation
2025 * structure in our sdlz_implementation.
2026 */
2027 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2028 &imp->dlz_imp);
2029
2030 /* if registration fails, cleanup and get outta here. */
2031 if (result != ISC_R_SUCCESS) {
2032 goto cleanup_mutex;
2033 }
2034
2035 *sdlzimp = imp;
2036
2037 return (ISC_R_SUCCESS);
2038
2039 cleanup_mutex:
2040 /* destroy the driver lock, we don't need it anymore */
2041 isc_mutex_destroy(&imp->driverlock);
2042
2043 /*
2044 * return the memory back to the available memory pool and
2045 * remove it from the memory context.
2046 */
2047 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2048 return (result);
2049 }
2050
2051 void
2052 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2053 dns_sdlzimplementation_t *imp;
2054
2055 /* Write debugging message to log */
2056 sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2057
2058 /*
2059 * Performs checks to make sure data is as we expect it to be.
2060 */
2061 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2062
2063 imp = *sdlzimp;
2064 *sdlzimp = NULL;
2065
2066 /* Unregister the DLZ driver implementation */
2067 dns_dlzunregister(&imp->dlz_imp);
2068
2069 /* destroy the driver lock, we don't need it anymore */
2070 isc_mutex_destroy(&imp->driverlock);
2071
2072 /*
2073 * return the memory back to the available memory pool and
2074 * remove it from the memory context.
2075 */
2076 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2077 }
2078
2079 isc_result_t
2080 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
2081 const dns_name_t *name, dns_db_t **dbp) {
2082 isc_result_t result;
2083
2084 result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2085 dlzdatabase->implementation->driverarg,
2086 dlzdatabase->dbdata, name, rdclass, dbp);
2087 return (result);
2088 }
2089