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