sdlz.c revision 1.9 1 /* $NetBSD: sdlz.c,v 1.9 2021/04/05 11:27:02 rillig 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 https://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 (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 (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_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 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, /* setservestalerefresh */
1290 NULL, /* getservestalerefresh */
1291 NULL, /* setgluecachestats */
1292 NULL /* adjusthashsize */
1293 };
1294
1295 /*
1296 * Database Iterator Methods. These methods were "borrowed" from the SDB
1297 * driver interface. See the SDB driver interface documentation for more info.
1298 */
1299
1300 static void
1301 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1302 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1303 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1304
1305 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1306 dns_sdlznode_t *node;
1307 node = ISC_LIST_HEAD(sdlziter->nodelist);
1308 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1309 isc_refcount_decrementz(&node->references);
1310 destroynode(node);
1311 }
1312
1313 dns_db_detach(&sdlziter->common.db);
1314 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1315
1316 *iteratorp = NULL;
1317 }
1318
1319 static isc_result_t
1320 dbiterator_first(dns_dbiterator_t *iterator) {
1321 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1322
1323 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1324 if (sdlziter->current == NULL) {
1325 return (ISC_R_NOMORE);
1326 } else {
1327 return (ISC_R_SUCCESS);
1328 }
1329 }
1330
1331 static isc_result_t
1332 dbiterator_last(dns_dbiterator_t *iterator) {
1333 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1334
1335 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1336 if (sdlziter->current == NULL) {
1337 return (ISC_R_NOMORE);
1338 } else {
1339 return (ISC_R_SUCCESS);
1340 }
1341 }
1342
1343 static isc_result_t
1344 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1345 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1346
1347 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1348 while (sdlziter->current != NULL) {
1349 if (dns_name_equal(sdlziter->current->name, name)) {
1350 return (ISC_R_SUCCESS);
1351 }
1352 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1353 }
1354 return (ISC_R_NOTFOUND);
1355 }
1356
1357 static isc_result_t
1358 dbiterator_prev(dns_dbiterator_t *iterator) {
1359 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1360
1361 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1362 if (sdlziter->current == NULL) {
1363 return (ISC_R_NOMORE);
1364 } else {
1365 return (ISC_R_SUCCESS);
1366 }
1367 }
1368
1369 static isc_result_t
1370 dbiterator_next(dns_dbiterator_t *iterator) {
1371 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1372
1373 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1374 if (sdlziter->current == NULL) {
1375 return (ISC_R_NOMORE);
1376 } else {
1377 return (ISC_R_SUCCESS);
1378 }
1379 }
1380
1381 static isc_result_t
1382 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1383 dns_name_t *name) {
1384 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1385
1386 attachnode(iterator->db, sdlziter->current, nodep);
1387 if (name != NULL) {
1388 dns_name_copynf(sdlziter->current->name, name);
1389 return (ISC_R_SUCCESS);
1390 }
1391 return (ISC_R_SUCCESS);
1392 }
1393
1394 static isc_result_t
1395 dbiterator_pause(dns_dbiterator_t *iterator) {
1396 UNUSED(iterator);
1397 return (ISC_R_SUCCESS);
1398 }
1399
1400 static isc_result_t
1401 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1402 UNUSED(iterator);
1403 dns_name_copynf(dns_rootname, name);
1404 return (ISC_R_SUCCESS);
1405 }
1406
1407 /*
1408 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1409 * interface. See the SDB driver interface documentation for more info.
1410 */
1411
1412 static void
1413 disassociate(dns_rdataset_t *rdataset) {
1414 dns_dbnode_t *node = rdataset->private5;
1415 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1416 dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1417
1418 detachnode(db, &node);
1419 isc__rdatalist_disassociate(rdataset);
1420 }
1421
1422 static void
1423 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1424 dns_dbnode_t *node = source->private5;
1425 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1426 dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1427 dns_dbnode_t *tempdb = NULL;
1428
1429 isc__rdatalist_clone(source, target);
1430 attachnode(db, node, &tempdb);
1431 source->private5 = tempdb;
1432 }
1433
1434 static dns_rdatasetmethods_t rdataset_methods = {
1435 disassociate,
1436 isc__rdatalist_first,
1437 isc__rdatalist_next,
1438 isc__rdatalist_current,
1439 rdataset_clone,
1440 isc__rdatalist_count,
1441 isc__rdatalist_addnoqname,
1442 isc__rdatalist_getnoqname,
1443 NULL, /* addclosest */
1444 NULL, /* getclosest */
1445 NULL, /* settrust */
1446 NULL, /* expire */
1447 NULL, /* clearprefetch */
1448 NULL, /* setownercase */
1449 NULL, /* getownercase */
1450 NULL /* addglue */
1451 };
1452
1453 static void
1454 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
1455 dns_rdataset_t *rdataset) {
1456 /*
1457 * The sdlz rdataset is an rdatalist with some additions.
1458 * - private1 & private2 are used by the rdatalist.
1459 * - private3 & private 4 are unused.
1460 * - private5 is the node.
1461 */
1462
1463 /* This should never fail. */
1464 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1465 ISC_R_SUCCESS);
1466
1467 rdataset->methods = &rdataset_methods;
1468 dns_db_attachnode(db, node, &rdataset->private5);
1469 }
1470
1471 /*
1472 * SDLZ core methods. This is the core of the new DLZ functionality.
1473 */
1474
1475 /*%
1476 * Build a 'bind' database driver structure to be returned by
1477 * either the find zone or the allow zone transfer method.
1478 * This method is only available in this source file, it is
1479 * not made available anywhere else.
1480 */
1481
1482 static isc_result_t
1483 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1484 const dns_name_t *name, dns_rdataclass_t rdclass,
1485 dns_db_t **dbp) {
1486 isc_result_t result;
1487 dns_sdlz_db_t *sdlzdb;
1488 dns_sdlzimplementation_t *imp;
1489
1490 /* check that things are as we expect */
1491 REQUIRE(dbp != NULL && *dbp == NULL);
1492 REQUIRE(name != NULL);
1493
1494 imp = (dns_sdlzimplementation_t *)driverarg;
1495
1496 /* allocate and zero memory for driver structure */
1497 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1498 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1499
1500 /* initialize and set origin */
1501 dns_name_init(&sdlzdb->common.origin, NULL);
1502 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1503 if (result != ISC_R_SUCCESS) {
1504 goto mem_cleanup;
1505 }
1506
1507 /* set the rest of the database structure attributes */
1508 sdlzdb->dlzimp = imp;
1509 sdlzdb->common.methods = &sdlzdb_methods;
1510 sdlzdb->common.attributes = 0;
1511 sdlzdb->common.rdclass = rdclass;
1512 sdlzdb->common.mctx = NULL;
1513 sdlzdb->dbdata = dbdata;
1514 isc_refcount_init(&sdlzdb->references, 1);
1515
1516 /* attach to the memory context */
1517 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1518
1519 /* mark structure as valid */
1520 sdlzdb->common.magic = DNS_DB_MAGIC;
1521 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1522 *dbp = (dns_db_t *)sdlzdb;
1523
1524 return (result);
1525 mem_cleanup:
1526 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1527 return (result);
1528 }
1529
1530 static isc_result_t
1531 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1532 dns_rdataclass_t rdclass, const dns_name_t *name,
1533 const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
1534 isc_buffer_t b;
1535 isc_buffer_t b2;
1536 char namestr[DNS_NAME_MAXTEXT + 1];
1537 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
1538 "255") +
1539 1];
1540 isc_netaddr_t netaddr;
1541 isc_result_t result;
1542 dns_sdlzimplementation_t *imp;
1543
1544 /*
1545 * Perform checks to make sure data is as we expect it to be.
1546 */
1547 REQUIRE(driverarg != NULL);
1548 REQUIRE(name != NULL);
1549 REQUIRE(clientaddr != NULL);
1550 REQUIRE(dbp != NULL && *dbp == NULL);
1551
1552 imp = (dns_sdlzimplementation_t *)driverarg;
1553
1554 /* Convert DNS name to ascii text */
1555 isc_buffer_init(&b, namestr, sizeof(namestr));
1556 result = dns_name_totext(name, true, &b);
1557 if (result != ISC_R_SUCCESS) {
1558 return (result);
1559 }
1560 isc_buffer_putuint8(&b, 0);
1561
1562 /* convert client address to ascii text */
1563 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1564 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1565 result = isc_netaddr_totext(&netaddr, &b2);
1566 if (result != ISC_R_SUCCESS) {
1567 return (result);
1568 }
1569 isc_buffer_putuint8(&b2, 0);
1570
1571 /* make sure strings are always lowercase */
1572 dns_sdlz_tolower(namestr);
1573 dns_sdlz_tolower(clientstr);
1574
1575 /* Call SDLZ driver's find zone method */
1576 if (imp->methods->allowzonexfr != NULL) {
1577 isc_result_t rresult = ISC_R_SUCCESS;
1578
1579 MAYBE_LOCK(imp);
1580 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1581 namestr, clientstr);
1582 MAYBE_UNLOCK(imp);
1583 /*
1584 * if zone is supported and transfers are (or might be)
1585 * allowed, build a 'bind' database driver
1586 */
1587 if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
1588 rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1589 name, rdclass, dbp);
1590 }
1591 if (rresult != ISC_R_SUCCESS) {
1592 result = rresult;
1593 }
1594 return (result);
1595 }
1596
1597 return (ISC_R_NOTIMPLEMENTED);
1598 }
1599
1600 static isc_result_t
1601 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1602 char *argv[], void *driverarg, void **dbdata) {
1603 dns_sdlzimplementation_t *imp;
1604 isc_result_t result = ISC_R_NOTFOUND;
1605
1606 /* Write debugging message to log */
1607 sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1608
1609 /*
1610 * Performs checks to make sure data is as we expect it to be.
1611 */
1612 REQUIRE(driverarg != NULL);
1613 REQUIRE(dlzname != NULL);
1614 REQUIRE(dbdata != NULL);
1615 UNUSED(mctx);
1616
1617 imp = driverarg;
1618
1619 /* If the create method exists, call it. */
1620 if (imp->methods->create != NULL) {
1621 MAYBE_LOCK(imp);
1622 result = imp->methods->create(dlzname, argc, argv,
1623 imp->driverarg, dbdata);
1624 MAYBE_UNLOCK(imp);
1625 }
1626
1627 /* Write debugging message to log */
1628 if (result == ISC_R_SUCCESS) {
1629 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1630 } else {
1631 sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1632 }
1633
1634 return (result);
1635 }
1636
1637 static void
1638 dns_sdlzdestroy(void *driverdata, void **dbdata) {
1639 dns_sdlzimplementation_t *imp;
1640
1641 /* Write debugging message to log */
1642 sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1643
1644 imp = driverdata;
1645
1646 /* If the destroy method exists, call it. */
1647 if (imp->methods->destroy != NULL) {
1648 MAYBE_LOCK(imp);
1649 imp->methods->destroy(imp->driverarg, dbdata);
1650 MAYBE_UNLOCK(imp);
1651 }
1652 }
1653
1654 static isc_result_t
1655 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1656 dns_rdataclass_t rdclass, const dns_name_t *name,
1657 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
1658 dns_db_t **dbp) {
1659 isc_buffer_t b;
1660 char namestr[DNS_NAME_MAXTEXT + 1];
1661 isc_result_t result;
1662 dns_sdlzimplementation_t *imp;
1663
1664 /*
1665 * Perform checks to make sure data is as we expect it to be.
1666 */
1667 REQUIRE(driverarg != NULL);
1668 REQUIRE(name != NULL);
1669 REQUIRE(dbp != NULL && *dbp == NULL);
1670
1671 imp = (dns_sdlzimplementation_t *)driverarg;
1672
1673 /* Convert DNS name to ascii text */
1674 isc_buffer_init(&b, namestr, sizeof(namestr));
1675 result = dns_name_totext(name, true, &b);
1676 if (result != ISC_R_SUCCESS) {
1677 return (result);
1678 }
1679 isc_buffer_putuint8(&b, 0);
1680
1681 /* make sure strings are always lowercase */
1682 dns_sdlz_tolower(namestr);
1683
1684 /* Call SDLZ driver's find zone method */
1685 MAYBE_LOCK(imp);
1686 result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1687 methods, clientinfo);
1688 MAYBE_UNLOCK(imp);
1689
1690 /*
1691 * if zone is supported build a 'bind' database driver
1692 * structure to return
1693 */
1694 if (result == ISC_R_SUCCESS) {
1695 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1696 rdclass, dbp);
1697 }
1698
1699 return (result);
1700 }
1701
1702 static isc_result_t
1703 dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
1704 dns_dlzdb_t *dlzdb) {
1705 isc_result_t result;
1706 dns_sdlzimplementation_t *imp;
1707
1708 REQUIRE(driverarg != NULL);
1709
1710 imp = (dns_sdlzimplementation_t *)driverarg;
1711
1712 /* Call SDLZ driver's configure method */
1713 if (imp->methods->configure != NULL) {
1714 MAYBE_LOCK(imp);
1715 result = imp->methods->configure(view, dlzdb, imp->driverarg,
1716 dbdata);
1717 MAYBE_UNLOCK(imp);
1718 } else {
1719 result = ISC_R_SUCCESS;
1720 }
1721
1722 return (result);
1723 }
1724
1725 static bool
1726 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
1727 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
1728 const dst_key_t *key, void *driverarg, void *dbdata) {
1729 dns_sdlzimplementation_t *imp;
1730 char b_signer[DNS_NAME_FORMATSIZE];
1731 char b_name[DNS_NAME_FORMATSIZE];
1732 char b_addr[ISC_NETADDR_FORMATSIZE];
1733 char b_type[DNS_RDATATYPE_FORMATSIZE];
1734 char b_key[DST_KEY_FORMATSIZE];
1735 isc_buffer_t *tkey_token = NULL;
1736 isc_region_t token_region = { NULL, 0 };
1737 uint32_t token_len = 0;
1738 bool ret;
1739
1740 REQUIRE(driverarg != NULL);
1741
1742 imp = (dns_sdlzimplementation_t *)driverarg;
1743 if (imp->methods->ssumatch == NULL) {
1744 return (false);
1745 }
1746
1747 /*
1748 * Format the request elements. sdlz operates on strings, not
1749 * structures
1750 */
1751 if (signer != NULL) {
1752 dns_name_format(signer, b_signer, sizeof(b_signer));
1753 } else {
1754 b_signer[0] = 0;
1755 }
1756
1757 dns_name_format(name, b_name, sizeof(b_name));
1758
1759 if (tcpaddr != NULL) {
1760 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
1761 } else {
1762 b_addr[0] = 0;
1763 }
1764
1765 dns_rdatatype_format(type, b_type, sizeof(b_type));
1766
1767 if (key != NULL) {
1768 dst_key_format(key, b_key, sizeof(b_key));
1769 tkey_token = dst_key_tkeytoken(key);
1770 } else {
1771 b_key[0] = 0;
1772 }
1773
1774 if (tkey_token != NULL) {
1775 isc_buffer_region(tkey_token, &token_region);
1776 token_len = token_region.length;
1777 }
1778
1779 MAYBE_LOCK(imp);
1780 ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1781 token_len,
1782 token_len != 0 ? token_region.base : NULL,
1783 imp->driverarg, dbdata);
1784 MAYBE_UNLOCK(imp);
1785 return (ret);
1786 }
1787
1788 static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy,
1789 dns_sdlzfindzone, dns_sdlzallowzonexfr,
1790 dns_sdlzconfigure, dns_sdlzssumatch };
1791
1792 /*
1793 * Public functions.
1794 */
1795
1796 isc_result_t
1797 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1798 const char *data) {
1799 dns_rdatalist_t *rdatalist;
1800 dns_rdata_t *rdata;
1801 dns_rdatatype_t typeval;
1802 isc_consttextregion_t r;
1803 isc_buffer_t b;
1804 isc_buffer_t *rdatabuf = NULL;
1805 isc_lex_t *lex;
1806 isc_result_t result;
1807 unsigned int size;
1808 isc_mem_t *mctx;
1809 const dns_name_t *origin;
1810
1811 REQUIRE(VALID_SDLZLOOKUP(lookup));
1812 REQUIRE(type != NULL);
1813 REQUIRE(data != NULL);
1814
1815 mctx = lookup->sdlz->common.mctx;
1816
1817 r.base = type;
1818 r.length = strlen(type);
1819 result = dns_rdatatype_fromtext(&typeval, (void *)&r);
1820 if (result != ISC_R_SUCCESS) {
1821 return (result);
1822 }
1823
1824 rdatalist = ISC_LIST_HEAD(lookup->lists);
1825 while (rdatalist != NULL) {
1826 if (rdatalist->type == typeval) {
1827 break;
1828 }
1829 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1830 }
1831
1832 if (rdatalist == NULL) {
1833 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1834 dns_rdatalist_init(rdatalist);
1835 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1836 rdatalist->type = typeval;
1837 rdatalist->ttl = ttl;
1838 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1839 } else if (rdatalist->ttl > ttl) {
1840 /*
1841 * BIND9 doesn't enforce all RRs in an RRset
1842 * having the same TTL, as per RFC 2136,
1843 * section 7.12. If a DLZ backend has
1844 * different TTLs, then the best
1845 * we can do is return the lowest.
1846 */
1847 rdatalist->ttl = ttl;
1848 }
1849
1850 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1851 dns_rdata_init(rdata);
1852
1853 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1854 origin = &lookup->sdlz->common.origin;
1855 } else {
1856 origin = dns_rootname;
1857 }
1858
1859 lex = NULL;
1860 result = isc_lex_create(mctx, 64, &lex);
1861 if (result != ISC_R_SUCCESS) {
1862 goto failure;
1863 }
1864
1865 size = initial_size(data);
1866 do {
1867 isc_buffer_constinit(&b, data, strlen(data));
1868 isc_buffer_add(&b, strlen(data));
1869
1870 result = isc_lex_openbuffer(lex, &b);
1871 if (result != ISC_R_SUCCESS) {
1872 goto failure;
1873 }
1874
1875 rdatabuf = NULL;
1876 isc_buffer_allocate(mctx, &rdatabuf, size);
1877
1878 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1879 rdatalist->type, lex, origin, false,
1880 mctx, rdatabuf, &lookup->callbacks);
1881 if (result != ISC_R_SUCCESS) {
1882 isc_buffer_free(&rdatabuf);
1883 result = DNS_R_SERVFAIL;
1884 }
1885 if (size >= 65535) {
1886 break;
1887 }
1888 size *= 2;
1889 if (size >= 65535) {
1890 size = 65535;
1891 }
1892 } while (result == ISC_R_NOSPACE);
1893
1894 if (result != ISC_R_SUCCESS) {
1895 goto failure;
1896 }
1897
1898 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1899 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1900
1901 if (lex != NULL) {
1902 isc_lex_destroy(&lex);
1903 }
1904
1905 return (ISC_R_SUCCESS);
1906
1907 failure:
1908 if (rdatabuf != NULL) {
1909 isc_buffer_free(&rdatabuf);
1910 }
1911 if (lex != NULL) {
1912 isc_lex_destroy(&lex);
1913 }
1914 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1915
1916 return (result);
1917 }
1918
1919 isc_result_t
1920 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1921 const char *type, dns_ttl_t ttl, const char *data) {
1922 dns_name_t *newname;
1923 const dns_name_t *origin;
1924 dns_fixedname_t fnewname;
1925 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1926 dns_sdlznode_t *sdlznode;
1927 isc_mem_t *mctx = sdlz->common.mctx;
1928 isc_buffer_t b;
1929 isc_result_t result;
1930
1931 newname = dns_fixedname_initname(&fnewname);
1932
1933 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1934 origin = &sdlz->common.origin;
1935 } else {
1936 origin = dns_rootname;
1937 }
1938 isc_buffer_constinit(&b, name, strlen(name));
1939 isc_buffer_add(&b, strlen(name));
1940
1941 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1942 if (result != ISC_R_SUCCESS) {
1943 return (result);
1944 }
1945
1946 if (allnodes->common.relative_names) {
1947 /* All names are relative to the root */
1948 unsigned int nlabels = dns_name_countlabels(newname);
1949 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1950 }
1951
1952 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1953 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1954 sdlznode = NULL;
1955 result = createnode(sdlz, &sdlznode);
1956 if (result != ISC_R_SUCCESS) {
1957 return (result);
1958 }
1959 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1960 dns_name_init(sdlznode->name, NULL);
1961 dns_name_dup(newname, mctx, sdlznode->name);
1962 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1963 if (allnodes->origin == NULL &&
1964 dns_name_equal(newname, &sdlz->common.origin)) {
1965 allnodes->origin = sdlznode;
1966 }
1967 }
1968 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1969 }
1970
1971 isc_result_t
1972 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1973 uint32_t serial) {
1974 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1975 int n;
1976
1977 REQUIRE(mname != NULL);
1978 REQUIRE(rname != NULL);
1979
1980 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
1981 serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1982 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1983 if (n >= (int)sizeof(str) || n < 0) {
1984 return (ISC_R_NOSPACE);
1985 }
1986 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1987 }
1988
1989 isc_result_t
1990 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1991 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1992 dns_sdlzimplementation_t **sdlzimp) {
1993 dns_sdlzimplementation_t *imp;
1994 isc_result_t result;
1995
1996 /*
1997 * Performs checks to make sure data is as we expect it to be.
1998 */
1999 REQUIRE(drivername != NULL);
2000 REQUIRE(methods != NULL);
2001 REQUIRE(methods->findzone != NULL);
2002 REQUIRE(methods->lookup != NULL);
2003 REQUIRE(mctx != NULL);
2004 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
2005 REQUIRE((flags &
2006 ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
2007 DNS_SDLZFLAG_THREADSAFE)) == 0);
2008
2009 /* Write debugging message to log */
2010 sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
2011
2012 /*
2013 * Allocate memory for a sdlz_implementation object. Error if
2014 * we cannot.
2015 */
2016 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2017
2018 /* Make sure memory region is set to all 0's */
2019 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2020
2021 /* Store the data passed into this method */
2022 imp->methods = methods;
2023 imp->driverarg = driverarg;
2024 imp->flags = flags;
2025 imp->mctx = NULL;
2026
2027 /* attach the new sdlz_implementation object to a memory context */
2028 isc_mem_attach(mctx, &imp->mctx);
2029
2030 /*
2031 * initialize the driver lock, error if we cannot
2032 * (used if a driver does not support multiple threads)
2033 */
2034 isc_mutex_init(&imp->driverlock);
2035
2036 imp->dlz_imp = NULL;
2037
2038 /*
2039 * register the DLZ driver. Pass in our "extra" sdlz information as
2040 * a driverarg. (that's why we stored the passed in driver arg in our
2041 * sdlz_implementation structure) Also, store the dlz_implementation
2042 * structure in our sdlz_implementation.
2043 */
2044 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2045 &imp->dlz_imp);
2046
2047 /* if registration fails, cleanup and get outta here. */
2048 if (result != ISC_R_SUCCESS) {
2049 goto cleanup_mutex;
2050 }
2051
2052 *sdlzimp = imp;
2053
2054 return (ISC_R_SUCCESS);
2055
2056 cleanup_mutex:
2057 /* destroy the driver lock, we don't need it anymore */
2058 isc_mutex_destroy(&imp->driverlock);
2059
2060 /*
2061 * return the memory back to the available memory pool and
2062 * remove it from the memory context.
2063 */
2064 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2065 return (result);
2066 }
2067
2068 void
2069 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2070 dns_sdlzimplementation_t *imp;
2071
2072 /* Write debugging message to log */
2073 sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2074
2075 /*
2076 * Performs checks to make sure data is as we expect it to be.
2077 */
2078 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2079
2080 imp = *sdlzimp;
2081 *sdlzimp = NULL;
2082
2083 /* Unregister the DLZ driver implementation */
2084 dns_dlzunregister(&imp->dlz_imp);
2085
2086 /* destroy the driver lock, we don't need it anymore */
2087 isc_mutex_destroy(&imp->driverlock);
2088
2089 /*
2090 * return the memory back to the available memory pool and
2091 * remove it from the memory context.
2092 */
2093 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2094 }
2095
2096 isc_result_t
2097 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
2098 const dns_name_t *name, dns_db_t **dbp) {
2099 isc_result_t result;
2100
2101 result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2102 dlzdatabase->implementation->driverarg,
2103 dlzdatabase->dbdata, name, rdclass, dbp);
2104 return (result);
2105 }
2106