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