sdlz.c revision 1.10 1 /* $NetBSD: sdlz.c,v 1.10 2022/09/23 12:15:30 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/rwlock.h>
66 #include <isc/string.h>
67 #include <isc/util.h>
68
69 #include <dns/callbacks.h>
70 #include <dns/db.h>
71 #include <dns/dbiterator.h>
72 #include <dns/dlz.h>
73 #include <dns/fixedname.h>
74 #include <dns/log.h>
75 #include <dns/master.h>
76 #include <dns/rdata.h>
77 #include <dns/rdatalist.h>
78 #include <dns/rdataset.h>
79 #include <dns/rdatasetiter.h>
80 #include <dns/rdatatype.h>
81 #include <dns/result.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 void *sdlzv, *tdlzv;
459
460 node = isc_mem_get(sdlz->common.mctx, sizeof(dns_sdlznode_t));
461
462 node->sdlz = NULL;
463 sdlzv = sdlz;
464 tdlzv = &node->sdlz;
465 attach(sdlzv, tdlzv);
466 ISC_LIST_INIT(node->lists);
467 ISC_LIST_INIT(node->buffers);
468 ISC_LINK_INIT(node, link);
469 node->name = NULL;
470 dns_rdatacallbacks_init(&node->callbacks);
471
472 isc_refcount_init(&node->references, 1);
473 node->magic = SDLZLOOKUP_MAGIC;
474
475 *nodep = node;
476 return (ISC_R_SUCCESS);
477 }
478
479 static void
480 destroynode(dns_sdlznode_t *node) {
481 dns_rdatalist_t *list;
482 dns_rdata_t *rdata;
483 isc_buffer_t *b;
484 dns_sdlz_db_t *sdlz;
485 dns_db_t *db;
486 isc_mem_t *mctx;
487
488 isc_refcount_destroy(&node->references);
489
490 sdlz = node->sdlz;
491 mctx = sdlz->common.mctx;
492
493 while (!ISC_LIST_EMPTY(node->lists)) {
494 list = ISC_LIST_HEAD(node->lists);
495 while (!ISC_LIST_EMPTY(list->rdata)) {
496 rdata = ISC_LIST_HEAD(list->rdata);
497 ISC_LIST_UNLINK(list->rdata, rdata, link);
498 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
499 }
500 ISC_LIST_UNLINK(node->lists, list, link);
501 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
502 }
503
504 while (!ISC_LIST_EMPTY(node->buffers)) {
505 b = ISC_LIST_HEAD(node->buffers);
506 ISC_LIST_UNLINK(node->buffers, b, link);
507 isc_buffer_free(&b);
508 }
509
510 if (node->name != NULL) {
511 dns_name_free(node->name, mctx);
512 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
513 }
514
515 node->magic = 0;
516 isc_mem_put(mctx, node, sizeof(dns_sdlznode_t));
517 db = &sdlz->common;
518 detach(&db);
519 }
520
521 static isc_result_t
522 getnodedata(dns_db_t *db, const dns_name_t *name, bool create,
523 unsigned int options, dns_clientinfomethods_t *methods,
524 dns_clientinfo_t *clientinfo, dns_dbnode_t **nodep) {
525 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
526 dns_sdlznode_t *node = NULL;
527 isc_result_t result;
528 isc_buffer_t b;
529 char namestr[DNS_NAME_MAXTEXT + 1];
530 isc_buffer_t b2;
531 char zonestr[DNS_NAME_MAXTEXT + 1];
532 bool isorigin;
533 dns_sdlzauthorityfunc_t authority;
534
535 REQUIRE(VALID_SDLZDB(sdlz));
536 REQUIRE(nodep != NULL && *nodep == NULL);
537
538 if (sdlz->dlzimp->methods->newversion == NULL) {
539 REQUIRE(!create);
540 }
541
542 isc_buffer_init(&b, namestr, sizeof(namestr));
543 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVEOWNER) != 0) {
544 dns_name_t relname;
545 unsigned int labels;
546
547 labels = dns_name_countlabels(name) -
548 dns_name_countlabels(&sdlz->common.origin);
549 dns_name_init(&relname, NULL);
550 dns_name_getlabelsequence(name, 0, labels, &relname);
551 result = dns_name_totext(&relname, true, &b);
552 if (result != ISC_R_SUCCESS) {
553 return (result);
554 }
555 } else {
556 result = dns_name_totext(name, true, &b);
557 if (result != ISC_R_SUCCESS) {
558 return (result);
559 }
560 }
561 isc_buffer_putuint8(&b, 0);
562
563 isc_buffer_init(&b2, zonestr, sizeof(zonestr));
564 result = dns_name_totext(&sdlz->common.origin, true, &b2);
565 if (result != ISC_R_SUCCESS) {
566 return (result);
567 }
568 isc_buffer_putuint8(&b2, 0);
569
570 result = createnode(sdlz, &node);
571 if (result != ISC_R_SUCCESS) {
572 return (result);
573 }
574
575 isorigin = dns_name_equal(name, &sdlz->common.origin);
576
577 /* make sure strings are always lowercase */
578 dns_sdlz_tolower(zonestr);
579 dns_sdlz_tolower(namestr);
580
581 MAYBE_LOCK(sdlz->dlzimp);
582
583 /* try to lookup the host (namestr) */
584 result = sdlz->dlzimp->methods->lookup(
585 zonestr, namestr, sdlz->dlzimp->driverarg, sdlz->dbdata, node,
586 methods, clientinfo);
587
588 /*
589 * If the name was not found and DNS_DBFIND_NOWILD is not
590 * set, then we try to find a wildcard entry.
591 *
592 * If DNS_DBFIND_NOZONECUT is set and there are multiple
593 * levels between the host and the zone origin, we also look
594 * for wildcards at each level.
595 */
596 if (result == ISC_R_NOTFOUND && !create &&
597 (options & DNS_DBFIND_NOWILD) == 0) {
598 unsigned int i, dlabels, nlabels;
599
600 nlabels = dns_name_countlabels(name);
601 dlabels = nlabels - dns_name_countlabels(&sdlz->common.origin);
602 for (i = 0; i < dlabels; i++) {
603 char wildstr[DNS_NAME_MAXTEXT + 1];
604 dns_fixedname_t fixed;
605 const dns_name_t *wild;
606
607 dns_fixedname_init(&fixed);
608 if (i == dlabels - 1) {
609 wild = dns_wildcardname;
610 } else {
611 dns_name_t *fname;
612 fname = dns_fixedname_name(&fixed);
613 dns_name_getlabelsequence(
614 name, i + 1, dlabels - i - 1, fname);
615 result = dns_name_concatenate(
616 dns_wildcardname, fname, fname, NULL);
617 if (result != ISC_R_SUCCESS) {
618 MAYBE_UNLOCK(sdlz->dlzimp);
619 return (result);
620 }
621 wild = fname;
622 }
623
624 isc_buffer_init(&b, wildstr, sizeof(wildstr));
625 result = dns_name_totext(wild, true, &b);
626 if (result != ISC_R_SUCCESS) {
627 MAYBE_UNLOCK(sdlz->dlzimp);
628 return (result);
629 }
630 isc_buffer_putuint8(&b, 0);
631
632 result = sdlz->dlzimp->methods->lookup(
633 zonestr, wildstr, sdlz->dlzimp->driverarg,
634 sdlz->dbdata, node, methods, clientinfo);
635 if (result == ISC_R_SUCCESS) {
636 break;
637 }
638 }
639 }
640
641 MAYBE_UNLOCK(sdlz->dlzimp);
642
643 if (result == ISC_R_NOTFOUND && (isorigin || create)) {
644 result = ISC_R_SUCCESS;
645 }
646
647 if (result != ISC_R_SUCCESS) {
648 isc_refcount_decrementz(&node->references);
649 destroynode(node);
650 return (result);
651 }
652
653 if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
654 MAYBE_LOCK(sdlz->dlzimp);
655 authority = sdlz->dlzimp->methods->authority;
656 result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
657 sdlz->dbdata, node);
658 MAYBE_UNLOCK(sdlz->dlzimp);
659 if (result != ISC_R_SUCCESS && result != ISC_R_NOTIMPLEMENTED) {
660 isc_refcount_decrementz(&node->references);
661 destroynode(node);
662 return (result);
663 }
664 }
665
666 if (node->name == NULL) {
667 node->name = isc_mem_get(sdlz->common.mctx, sizeof(dns_name_t));
668 dns_name_init(node->name, NULL);
669 dns_name_dup(name, sdlz->common.mctx, node->name);
670 }
671
672 *nodep = node;
673 return (ISC_R_SUCCESS);
674 }
675
676 static isc_result_t
677 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
678 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
679 dns_dbnode_t **nodep) {
680 return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
681 }
682
683 static isc_result_t
684 findnode(dns_db_t *db, const dns_name_t *name, bool create,
685 dns_dbnode_t **nodep) {
686 return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
687 }
688
689 static isc_result_t
690 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
691 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
692 dns_name_t *dcname, dns_rdataset_t *rdataset,
693 dns_rdataset_t *sigrdataset) {
694 UNUSED(db);
695 UNUSED(name);
696 UNUSED(options);
697 UNUSED(now);
698 UNUSED(nodep);
699 UNUSED(foundname);
700 UNUSED(dcname);
701 UNUSED(rdataset);
702 UNUSED(sigrdataset);
703
704 return (ISC_R_NOTIMPLEMENTED);
705 }
706
707 static void
708 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
709 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
710 dns_sdlznode_t *node = (dns_sdlznode_t *)source;
711
712 REQUIRE(VALID_SDLZDB(sdlz));
713
714 UNUSED(sdlz);
715
716 isc_refcount_increment(&node->references);
717
718 *targetp = source;
719 }
720
721 static void
722 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
723 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
724 dns_sdlznode_t *node;
725
726 REQUIRE(VALID_SDLZDB(sdlz));
727 REQUIRE(targetp != NULL && *targetp != NULL);
728
729 UNUSED(sdlz);
730
731 node = (dns_sdlznode_t *)(*targetp);
732 *targetp = NULL;
733
734 if (isc_refcount_decrement(&node->references) == 1) {
735 destroynode(node);
736 }
737 }
738
739 static isc_result_t
740 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
741 UNUSED(db);
742 UNUSED(node);
743 UNUSED(now);
744 UNREACHABLE();
745 }
746
747 static void
748 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
749 UNUSED(db);
750 UNUSED(node);
751 UNUSED(out);
752 return;
753 }
754
755 static isc_result_t
756 createiterator(dns_db_t *db, unsigned int options,
757 dns_dbiterator_t **iteratorp) {
758 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
759 sdlz_dbiterator_t *sdlziter;
760 isc_result_t result;
761 isc_buffer_t b;
762 char zonestr[DNS_NAME_MAXTEXT + 1];
763
764 REQUIRE(VALID_SDLZDB(sdlz));
765
766 if (sdlz->dlzimp->methods->allnodes == NULL) {
767 return (ISC_R_NOTIMPLEMENTED);
768 }
769
770 if ((options & DNS_DB_NSEC3ONLY) != 0 ||
771 (options & DNS_DB_NONSEC3) != 0) {
772 return (ISC_R_NOTIMPLEMENTED);
773 }
774
775 isc_buffer_init(&b, zonestr, sizeof(zonestr));
776 result = dns_name_totext(&sdlz->common.origin, true, &b);
777 if (result != ISC_R_SUCCESS) {
778 return (result);
779 }
780 isc_buffer_putuint8(&b, 0);
781
782 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
783
784 sdlziter->common.methods = &dbiterator_methods;
785 sdlziter->common.db = NULL;
786 dns_db_attach(db, &sdlziter->common.db);
787 sdlziter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
788 0);
789 sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
790 ISC_LIST_INIT(sdlziter->nodelist);
791 sdlziter->current = NULL;
792 sdlziter->origin = NULL;
793
794 /* make sure strings are always lowercase */
795 dns_sdlz_tolower(zonestr);
796
797 MAYBE_LOCK(sdlz->dlzimp);
798 result = sdlz->dlzimp->methods->allnodes(
799 zonestr, sdlz->dlzimp->driverarg, sdlz->dbdata, sdlziter);
800 MAYBE_UNLOCK(sdlz->dlzimp);
801 if (result != ISC_R_SUCCESS) {
802 dns_dbiterator_t *iter = &sdlziter->common;
803 dbiterator_destroy(&iter);
804 return (result);
805 }
806
807 if (sdlziter->origin != NULL) {
808 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
809 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
810 }
811
812 *iteratorp = (dns_dbiterator_t *)sdlziter;
813
814 return (ISC_R_SUCCESS);
815 }
816
817 static isc_result_t
818 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
819 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
820 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
821 REQUIRE(VALID_SDLZNODE(node));
822 dns_rdatalist_t *list;
823 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
824
825 UNUSED(db);
826 UNUSED(version);
827 UNUSED(covers);
828 UNUSED(now);
829 UNUSED(sigrdataset);
830
831 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig) {
832 return (ISC_R_NOTIMPLEMENTED);
833 }
834
835 list = ISC_LIST_HEAD(sdlznode->lists);
836 while (list != NULL) {
837 if (list->type == type) {
838 break;
839 }
840 list = ISC_LIST_NEXT(list, link);
841 }
842 if (list == NULL) {
843 return (ISC_R_NOTFOUND);
844 }
845
846 list_tordataset(list, db, node, rdataset);
847
848 return (ISC_R_SUCCESS);
849 }
850
851 static isc_result_t
852 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
853 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
854 dns_dbnode_t **nodep, dns_name_t *foundname,
855 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
856 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
857 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
858 dns_dbnode_t *node = NULL;
859 dns_fixedname_t fname;
860 dns_rdataset_t xrdataset;
861 dns_name_t *xname;
862 unsigned int nlabels, olabels;
863 isc_result_t result;
864 unsigned int i;
865
866 REQUIRE(VALID_SDLZDB(sdlz));
867 REQUIRE(nodep == NULL || *nodep == NULL);
868 REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
869 version == sdlz->future_version);
870
871 UNUSED(sdlz);
872
873 if (!dns_name_issubdomain(name, &db->origin)) {
874 return (DNS_R_NXDOMAIN);
875 }
876
877 olabels = dns_name_countlabels(&db->origin);
878 nlabels = dns_name_countlabels(name);
879
880 xname = dns_fixedname_initname(&fname);
881
882 if (rdataset == NULL) {
883 dns_rdataset_init(&xrdataset);
884 rdataset = &xrdataset;
885 }
886
887 result = DNS_R_NXDOMAIN;
888
889 /*
890 * If we're not walking down searching for zone
891 * cuts, we can cut straight to the chase
892 */
893 if ((options & DNS_DBFIND_NOZONECUT) != 0) {
894 i = nlabels;
895 goto search;
896 }
897
898 for (i = olabels; i <= nlabels; i++) {
899 search:
900 /*
901 * Look up the next label.
902 */
903 dns_name_getlabelsequence(name, nlabels - i, i, xname);
904 result = getnodedata(db, xname, false, options, methods,
905 clientinfo, &node);
906 if (result == ISC_R_NOTFOUND) {
907 result = DNS_R_NXDOMAIN;
908 continue;
909 } else if (result != ISC_R_SUCCESS) {
910 break;
911 }
912
913 /*
914 * Look for a DNAME at the current label, unless this is
915 * the qname.
916 */
917 if (i < nlabels) {
918 result = findrdataset(db, node, version,
919 dns_rdatatype_dname, 0, now,
920 rdataset, sigrdataset);
921 if (result == ISC_R_SUCCESS) {
922 result = DNS_R_DNAME;
923 break;
924 }
925 }
926
927 /*
928 * Look for an NS at the current label, unless this is the
929 * origin, glue is ok, or there are known to be no zone cuts.
930 */
931 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
932 (options & DNS_DBFIND_NOZONECUT) == 0)
933 {
934 result = findrdataset(db, node, version,
935 dns_rdatatype_ns, 0, now,
936 rdataset, sigrdataset);
937
938 if (result == ISC_R_SUCCESS && i == nlabels &&
939 type == dns_rdatatype_any) {
940 result = DNS_R_ZONECUT;
941 dns_rdataset_disassociate(rdataset);
942 if (sigrdataset != NULL &&
943 dns_rdataset_isassociated(sigrdataset)) {
944 dns_rdataset_disassociate(sigrdataset);
945 }
946 break;
947 } else if (result == ISC_R_SUCCESS) {
948 result = DNS_R_DELEGATION;
949 break;
950 }
951 }
952
953 /*
954 * If the current name is not the qname, add another label
955 * and try again.
956 */
957 if (i < nlabels) {
958 detachnode(db, &node);
959 node = NULL;
960 continue;
961 }
962
963 /*
964 * If we're looking for ANY, we're done.
965 */
966 if (type == dns_rdatatype_any) {
967 result = ISC_R_SUCCESS;
968 break;
969 }
970
971 /*
972 * Look for the qtype.
973 */
974 result = findrdataset(db, node, version, type, 0, now, rdataset,
975 sigrdataset);
976 if (result == ISC_R_SUCCESS) {
977 break;
978 }
979
980 /*
981 * Look for a CNAME
982 */
983 if (type != dns_rdatatype_cname) {
984 result = findrdataset(db, node, version,
985 dns_rdatatype_cname, 0, now,
986 rdataset, sigrdataset);
987 if (result == ISC_R_SUCCESS) {
988 result = DNS_R_CNAME;
989 break;
990 }
991 }
992
993 result = DNS_R_NXRRSET;
994 break;
995 }
996
997 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
998 dns_rdataset_disassociate(rdataset);
999 }
1000
1001 if (foundname != NULL) {
1002 dns_name_copynf(xname, foundname);
1003 }
1004
1005 if (nodep != NULL) {
1006 *nodep = node;
1007 } else if (node != NULL) {
1008 detachnode(db, &node);
1009 }
1010
1011 return (result);
1012 }
1013
1014 static isc_result_t
1015 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
1016 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
1017 dns_dbnode_t **nodep, dns_name_t *foundname, dns_rdataset_t *rdataset,
1018 dns_rdataset_t *sigrdataset) {
1019 return (findext(db, name, version, type, options, now, nodep, foundname,
1020 NULL, NULL, rdataset, sigrdataset));
1021 }
1022
1023 static isc_result_t
1024 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1025 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) {
1026 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1027 sdlz_rdatasetiter_t *iterator;
1028
1029 REQUIRE(VALID_SDLZDB(sdlz));
1030
1031 REQUIRE(version == NULL || version == (void *)&sdlz->dummy_version ||
1032 version == sdlz->future_version);
1033
1034 UNUSED(version);
1035 UNUSED(now);
1036
1037 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
1038
1039 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1040 iterator->common.methods = &rdatasetiter_methods;
1041 iterator->common.db = db;
1042 iterator->common.node = NULL;
1043 attachnode(db, node, &iterator->common.node);
1044 iterator->common.version = version;
1045 iterator->common.now = now;
1046
1047 *iteratorp = (dns_rdatasetiter_t *)iterator;
1048
1049 return (ISC_R_SUCCESS);
1050 }
1051
1052 static isc_result_t
1053 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1054 dns_rdataset_t *rdataset, unsigned int options,
1055 dns_sdlzmodrdataset_t mod_function) {
1056 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1057 dns_master_style_t *style = NULL;
1058 isc_result_t result;
1059 isc_buffer_t *buffer = NULL;
1060 isc_mem_t *mctx;
1061 dns_sdlznode_t *sdlznode;
1062 char *rdatastr = NULL;
1063 char name[DNS_NAME_MAXTEXT + 1];
1064
1065 REQUIRE(VALID_SDLZDB(sdlz));
1066
1067 if (mod_function == NULL) {
1068 return (ISC_R_NOTIMPLEMENTED);
1069 }
1070
1071 sdlznode = (dns_sdlznode_t *)node;
1072
1073 UNUSED(options);
1074
1075 dns_name_format(sdlznode->name, name, sizeof(name));
1076
1077 mctx = sdlz->common.mctx;
1078
1079 isc_buffer_allocate(mctx, &buffer, 1024);
1080
1081 result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1, 0xffffffff,
1082 mctx);
1083 if (result != ISC_R_SUCCESS) {
1084 goto cleanup;
1085 }
1086
1087 result = dns_master_rdatasettotext(sdlznode->name, rdataset, style,
1088 NULL, buffer);
1089 if (result != ISC_R_SUCCESS) {
1090 goto cleanup;
1091 }
1092
1093 if (isc_buffer_usedlength(buffer) < 1) {
1094 result = ISC_R_BADADDRESSFORM;
1095 goto cleanup;
1096 }
1097
1098 rdatastr = isc_buffer_base(buffer);
1099 if (rdatastr == NULL) {
1100 result = ISC_R_NOMEMORY;
1101 goto cleanup;
1102 }
1103 rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
1104
1105 MAYBE_LOCK(sdlz->dlzimp);
1106 result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
1107 sdlz->dbdata, version);
1108 MAYBE_UNLOCK(sdlz->dlzimp);
1109
1110 cleanup:
1111 isc_buffer_free(&buffer);
1112 if (style != NULL) {
1113 dns_master_styledestroy(&style, mctx);
1114 }
1115
1116 return (result);
1117 }
1118
1119 static isc_result_t
1120 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1121 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1122 dns_rdataset_t *addedrdataset) {
1123 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1124 isc_result_t result;
1125
1126 UNUSED(now);
1127 UNUSED(addedrdataset);
1128 REQUIRE(VALID_SDLZDB(sdlz));
1129
1130 if (sdlz->dlzimp->methods->addrdataset == NULL) {
1131 return (ISC_R_NOTIMPLEMENTED);
1132 }
1133
1134 result = modrdataset(db, node, version, rdataset, options,
1135 sdlz->dlzimp->methods->addrdataset);
1136 return (result);
1137 }
1138
1139 static isc_result_t
1140 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1141 dns_rdataset_t *rdataset, unsigned int options,
1142 dns_rdataset_t *newrdataset) {
1143 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1144 isc_result_t result;
1145
1146 UNUSED(newrdataset);
1147 REQUIRE(VALID_SDLZDB(sdlz));
1148
1149 if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
1150 return (ISC_R_NOTIMPLEMENTED);
1151 }
1152
1153 result = modrdataset(db, node, version, rdataset, options,
1154 sdlz->dlzimp->methods->subtractrdataset);
1155 return (result);
1156 }
1157
1158 static isc_result_t
1159 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1160 dns_rdatatype_t type, dns_rdatatype_t covers) {
1161 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1162 char name[DNS_NAME_MAXTEXT + 1];
1163 char b_type[DNS_RDATATYPE_FORMATSIZE];
1164 dns_sdlznode_t *sdlznode;
1165 isc_result_t result;
1166
1167 UNUSED(covers);
1168
1169 REQUIRE(VALID_SDLZDB(sdlz));
1170
1171 if (sdlz->dlzimp->methods->delrdataset == NULL) {
1172 return (ISC_R_NOTIMPLEMENTED);
1173 }
1174
1175 sdlznode = (dns_sdlznode_t *)node;
1176 dns_name_format(sdlznode->name, name, sizeof(name));
1177 dns_rdatatype_format(type, b_type, sizeof(b_type));
1178
1179 MAYBE_LOCK(sdlz->dlzimp);
1180 result = sdlz->dlzimp->methods->delrdataset(
1181 name, b_type, sdlz->dlzimp->driverarg, sdlz->dbdata, version);
1182 MAYBE_UNLOCK(sdlz->dlzimp);
1183
1184 return (result);
1185 }
1186
1187 static bool
1188 issecure(dns_db_t *db) {
1189 UNUSED(db);
1190
1191 return (false);
1192 }
1193
1194 static unsigned int
1195 nodecount(dns_db_t *db) {
1196 UNUSED(db);
1197
1198 return (0);
1199 }
1200
1201 static bool
1202 ispersistent(dns_db_t *db) {
1203 UNUSED(db);
1204 return (true);
1205 }
1206
1207 static void
1208 overmem(dns_db_t *db, bool over) {
1209 UNUSED(db);
1210 UNUSED(over);
1211 }
1212
1213 static void
1214 settask(dns_db_t *db, isc_task_t *task) {
1215 UNUSED(db);
1216 UNUSED(task);
1217 }
1218
1219 /*
1220 * getoriginnode() is used by the update code to find the
1221 * dns_rdatatype_dnskey record for a zone
1222 */
1223 static isc_result_t
1224 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
1225 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1226 isc_result_t result;
1227
1228 REQUIRE(VALID_SDLZDB(sdlz));
1229 if (sdlz->dlzimp->methods->newversion == NULL) {
1230 return (ISC_R_NOTIMPLEMENTED);
1231 }
1232
1233 result = getnodedata(db, &sdlz->common.origin, false, 0, NULL, NULL,
1234 nodep);
1235 if (result != ISC_R_SUCCESS) {
1236 sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
1237 isc_result_totext(result));
1238 }
1239 return (result);
1240 }
1241
1242 static dns_dbmethods_t sdlzdb_methods = {
1243 attach,
1244 detach,
1245 beginload,
1246 endload,
1247 NULL, /* serialize */
1248 dump,
1249 currentversion,
1250 newversion,
1251 attachversion,
1252 closeversion,
1253 findnode,
1254 find,
1255 findzonecut,
1256 attachnode,
1257 detachnode,
1258 expirenode,
1259 printnode,
1260 createiterator,
1261 findrdataset,
1262 allrdatasets,
1263 addrdataset,
1264 subtractrdataset,
1265 deleterdataset,
1266 issecure,
1267 nodecount,
1268 ispersistent,
1269 overmem,
1270 settask,
1271 getoriginnode,
1272 NULL, /* transfernode */
1273 NULL, /* getnsec3parameters */
1274 NULL, /* findnsec3node */
1275 NULL, /* setsigningtime */
1276 NULL, /* getsigningtime */
1277 NULL, /* resigned */
1278 NULL, /* isdnssec */
1279 NULL, /* getrrsetstats */
1280 NULL, /* rpz_attach */
1281 NULL, /* rpz_ready */
1282 findnodeext,
1283 findext,
1284 NULL, /* setcachestats */
1285 NULL, /* hashsize */
1286 NULL, /* nodefullname */
1287 NULL, /* getsize */
1288 NULL, /* setservestalettl */
1289 NULL, /* getservestalettl */
1290 NULL, /* setservestalerefresh */
1291 NULL, /* getservestalerefresh */
1292 NULL, /* setgluecachestats */
1293 NULL /* adjusthashsize */
1294 };
1295
1296 /*
1297 * Database Iterator Methods. These methods were "borrowed" from the SDB
1298 * driver interface. See the SDB driver interface documentation for more info.
1299 */
1300
1301 static void
1302 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1303 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1304 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1305
1306 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1307 dns_sdlznode_t *node;
1308 node = ISC_LIST_HEAD(sdlziter->nodelist);
1309 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1310 isc_refcount_decrementz(&node->references);
1311 destroynode(node);
1312 }
1313
1314 dns_db_detach(&sdlziter->common.db);
1315 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1316
1317 *iteratorp = NULL;
1318 }
1319
1320 static isc_result_t
1321 dbiterator_first(dns_dbiterator_t *iterator) {
1322 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1323
1324 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1325 if (sdlziter->current == NULL) {
1326 return (ISC_R_NOMORE);
1327 } else {
1328 return (ISC_R_SUCCESS);
1329 }
1330 }
1331
1332 static isc_result_t
1333 dbiterator_last(dns_dbiterator_t *iterator) {
1334 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1335
1336 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1337 if (sdlziter->current == NULL) {
1338 return (ISC_R_NOMORE);
1339 } else {
1340 return (ISC_R_SUCCESS);
1341 }
1342 }
1343
1344 static isc_result_t
1345 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1346 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1347
1348 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1349 while (sdlziter->current != NULL) {
1350 if (dns_name_equal(sdlziter->current->name, name)) {
1351 return (ISC_R_SUCCESS);
1352 }
1353 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1354 }
1355 return (ISC_R_NOTFOUND);
1356 }
1357
1358 static isc_result_t
1359 dbiterator_prev(dns_dbiterator_t *iterator) {
1360 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1361
1362 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1363 if (sdlziter->current == NULL) {
1364 return (ISC_R_NOMORE);
1365 } else {
1366 return (ISC_R_SUCCESS);
1367 }
1368 }
1369
1370 static isc_result_t
1371 dbiterator_next(dns_dbiterator_t *iterator) {
1372 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1373
1374 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1375 if (sdlziter->current == NULL) {
1376 return (ISC_R_NOMORE);
1377 } else {
1378 return (ISC_R_SUCCESS);
1379 }
1380 }
1381
1382 static isc_result_t
1383 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1384 dns_name_t *name) {
1385 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1386
1387 attachnode(iterator->db, sdlziter->current, nodep);
1388 if (name != NULL) {
1389 dns_name_copynf(sdlziter->current->name, name);
1390 return (ISC_R_SUCCESS);
1391 }
1392 return (ISC_R_SUCCESS);
1393 }
1394
1395 static isc_result_t
1396 dbiterator_pause(dns_dbiterator_t *iterator) {
1397 UNUSED(iterator);
1398 return (ISC_R_SUCCESS);
1399 }
1400
1401 static isc_result_t
1402 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1403 UNUSED(iterator);
1404 dns_name_copynf(dns_rootname, name);
1405 return (ISC_R_SUCCESS);
1406 }
1407
1408 /*
1409 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1410 * interface. See the SDB driver interface documentation for more info.
1411 */
1412
1413 static void
1414 disassociate(dns_rdataset_t *rdataset) {
1415 dns_dbnode_t *node = rdataset->private5;
1416 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1417 dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1418
1419 detachnode(db, &node);
1420 isc__rdatalist_disassociate(rdataset);
1421 }
1422
1423 static void
1424 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1425 dns_dbnode_t *node = source->private5;
1426 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
1427 dns_db_t *db = (dns_db_t *)sdlznode->sdlz;
1428 dns_dbnode_t *tempdb = NULL;
1429
1430 isc__rdatalist_clone(source, target);
1431 attachnode(db, node, &tempdb);
1432 source->private5 = tempdb;
1433 }
1434
1435 static dns_rdatasetmethods_t rdataset_methods = {
1436 disassociate,
1437 isc__rdatalist_first,
1438 isc__rdatalist_next,
1439 isc__rdatalist_current,
1440 rdataset_clone,
1441 isc__rdatalist_count,
1442 isc__rdatalist_addnoqname,
1443 isc__rdatalist_getnoqname,
1444 NULL, /* addclosest */
1445 NULL, /* getclosest */
1446 NULL, /* settrust */
1447 NULL, /* expire */
1448 NULL, /* clearprefetch */
1449 NULL, /* setownercase */
1450 NULL, /* getownercase */
1451 NULL /* addglue */
1452 };
1453
1454 static void
1455 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
1456 dns_rdataset_t *rdataset) {
1457 /*
1458 * The sdlz rdataset is an rdatalist with some additions.
1459 * - private1 & private2 are used by the rdatalist.
1460 * - private3 & private 4 are unused.
1461 * - private5 is the node.
1462 */
1463
1464 /* This should never fail. */
1465 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1466 ISC_R_SUCCESS);
1467
1468 rdataset->methods = &rdataset_methods;
1469 dns_db_attachnode(db, node, &rdataset->private5);
1470 }
1471
1472 /*
1473 * SDLZ core methods. This is the core of the new DLZ functionality.
1474 */
1475
1476 /*%
1477 * Build a 'bind' database driver structure to be returned by
1478 * either the find zone or the allow zone transfer method.
1479 * This method is only available in this source file, it is
1480 * not made available anywhere else.
1481 */
1482
1483 static isc_result_t
1484 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1485 const dns_name_t *name, dns_rdataclass_t rdclass,
1486 dns_db_t **dbp) {
1487 isc_result_t result;
1488 dns_sdlz_db_t *sdlzdb;
1489 dns_sdlzimplementation_t *imp;
1490
1491 /* check that things are as we expect */
1492 REQUIRE(dbp != NULL && *dbp == NULL);
1493 REQUIRE(name != NULL);
1494
1495 imp = (dns_sdlzimplementation_t *)driverarg;
1496
1497 /* allocate and zero memory for driver structure */
1498 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1499 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1500
1501 /* initialize and set origin */
1502 dns_name_init(&sdlzdb->common.origin, NULL);
1503 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1504 if (result != ISC_R_SUCCESS) {
1505 goto mem_cleanup;
1506 }
1507
1508 /* set the rest of the database structure attributes */
1509 sdlzdb->dlzimp = imp;
1510 sdlzdb->common.methods = &sdlzdb_methods;
1511 sdlzdb->common.attributes = 0;
1512 sdlzdb->common.rdclass = rdclass;
1513 sdlzdb->common.mctx = NULL;
1514 sdlzdb->dbdata = dbdata;
1515 isc_refcount_init(&sdlzdb->references, 1);
1516
1517 /* attach to the memory context */
1518 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1519
1520 /* mark structure as valid */
1521 sdlzdb->common.magic = DNS_DB_MAGIC;
1522 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1523 *dbp = (dns_db_t *)sdlzdb;
1524
1525 return (result);
1526 mem_cleanup:
1527 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1528 return (result);
1529 }
1530
1531 static isc_result_t
1532 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1533 dns_rdataclass_t rdclass, const dns_name_t *name,
1534 const isc_sockaddr_t *clientaddr, dns_db_t **dbp) {
1535 isc_buffer_t b;
1536 isc_buffer_t b2;
1537 char namestr[DNS_NAME_MAXTEXT + 1];
1538 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255."
1539 "255") +
1540 1];
1541 isc_netaddr_t netaddr;
1542 isc_result_t result;
1543 dns_sdlzimplementation_t *imp;
1544
1545 /*
1546 * Perform checks to make sure data is as we expect it to be.
1547 */
1548 REQUIRE(driverarg != NULL);
1549 REQUIRE(name != NULL);
1550 REQUIRE(clientaddr != NULL);
1551 REQUIRE(dbp != NULL && *dbp == NULL);
1552
1553 imp = (dns_sdlzimplementation_t *)driverarg;
1554
1555 /* Convert DNS name to ascii text */
1556 isc_buffer_init(&b, namestr, sizeof(namestr));
1557 result = dns_name_totext(name, true, &b);
1558 if (result != ISC_R_SUCCESS) {
1559 return (result);
1560 }
1561 isc_buffer_putuint8(&b, 0);
1562
1563 /* convert client address to ascii text */
1564 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1565 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1566 result = isc_netaddr_totext(&netaddr, &b2);
1567 if (result != ISC_R_SUCCESS) {
1568 return (result);
1569 }
1570 isc_buffer_putuint8(&b2, 0);
1571
1572 /* make sure strings are always lowercase */
1573 dns_sdlz_tolower(namestr);
1574 dns_sdlz_tolower(clientstr);
1575
1576 /* Call SDLZ driver's find zone method */
1577 if (imp->methods->allowzonexfr != NULL) {
1578 isc_result_t rresult = ISC_R_SUCCESS;
1579
1580 MAYBE_LOCK(imp);
1581 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1582 namestr, clientstr);
1583 MAYBE_UNLOCK(imp);
1584 /*
1585 * if zone is supported and transfers are (or might be)
1586 * allowed, build a 'bind' database driver
1587 */
1588 if (result == ISC_R_SUCCESS || result == ISC_R_DEFAULT) {
1589 rresult = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1590 name, rdclass, dbp);
1591 }
1592 if (rresult != ISC_R_SUCCESS) {
1593 result = rresult;
1594 }
1595 return (result);
1596 }
1597
1598 return (ISC_R_NOTIMPLEMENTED);
1599 }
1600
1601 static isc_result_t
1602 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1603 char *argv[], void *driverarg, void **dbdata) {
1604 dns_sdlzimplementation_t *imp;
1605 isc_result_t result = ISC_R_NOTFOUND;
1606
1607 /* Write debugging message to log */
1608 sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1609
1610 /*
1611 * Performs checks to make sure data is as we expect it to be.
1612 */
1613 REQUIRE(driverarg != NULL);
1614 REQUIRE(dlzname != NULL);
1615 REQUIRE(dbdata != NULL);
1616 UNUSED(mctx);
1617
1618 imp = driverarg;
1619
1620 /* If the create method exists, call it. */
1621 if (imp->methods->create != NULL) {
1622 MAYBE_LOCK(imp);
1623 result = imp->methods->create(dlzname, argc, argv,
1624 imp->driverarg, dbdata);
1625 MAYBE_UNLOCK(imp);
1626 }
1627
1628 /* Write debugging message to log */
1629 if (result == ISC_R_SUCCESS) {
1630 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1631 } else {
1632 sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1633 }
1634
1635 return (result);
1636 }
1637
1638 static void
1639 dns_sdlzdestroy(void *driverdata, void **dbdata) {
1640 dns_sdlzimplementation_t *imp;
1641
1642 /* Write debugging message to log */
1643 sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1644
1645 imp = driverdata;
1646
1647 /* If the destroy method exists, call it. */
1648 if (imp->methods->destroy != NULL) {
1649 MAYBE_LOCK(imp);
1650 imp->methods->destroy(imp->driverarg, dbdata);
1651 MAYBE_UNLOCK(imp);
1652 }
1653 }
1654
1655 static isc_result_t
1656 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1657 dns_rdataclass_t rdclass, const dns_name_t *name,
1658 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
1659 dns_db_t **dbp) {
1660 isc_buffer_t b;
1661 char namestr[DNS_NAME_MAXTEXT + 1];
1662 isc_result_t result;
1663 dns_sdlzimplementation_t *imp;
1664
1665 /*
1666 * Perform checks to make sure data is as we expect it to be.
1667 */
1668 REQUIRE(driverarg != NULL);
1669 REQUIRE(name != NULL);
1670 REQUIRE(dbp != NULL && *dbp == NULL);
1671
1672 imp = (dns_sdlzimplementation_t *)driverarg;
1673
1674 /* Convert DNS name to ascii text */
1675 isc_buffer_init(&b, namestr, sizeof(namestr));
1676 result = dns_name_totext(name, true, &b);
1677 if (result != ISC_R_SUCCESS) {
1678 return (result);
1679 }
1680 isc_buffer_putuint8(&b, 0);
1681
1682 /* make sure strings are always lowercase */
1683 dns_sdlz_tolower(namestr);
1684
1685 /* Call SDLZ driver's find zone method */
1686 MAYBE_LOCK(imp);
1687 result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1688 methods, clientinfo);
1689 MAYBE_UNLOCK(imp);
1690
1691 /*
1692 * if zone is supported build a 'bind' database driver
1693 * structure to return
1694 */
1695 if (result == ISC_R_SUCCESS) {
1696 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1697 rdclass, dbp);
1698 }
1699
1700 return (result);
1701 }
1702
1703 static isc_result_t
1704 dns_sdlzconfigure(void *driverarg, void *dbdata, dns_view_t *view,
1705 dns_dlzdb_t *dlzdb) {
1706 isc_result_t result;
1707 dns_sdlzimplementation_t *imp;
1708
1709 REQUIRE(driverarg != NULL);
1710
1711 imp = (dns_sdlzimplementation_t *)driverarg;
1712
1713 /* Call SDLZ driver's configure method */
1714 if (imp->methods->configure != NULL) {
1715 MAYBE_LOCK(imp);
1716 result = imp->methods->configure(view, dlzdb, imp->driverarg,
1717 dbdata);
1718 MAYBE_UNLOCK(imp);
1719 } else {
1720 result = ISC_R_SUCCESS;
1721 }
1722
1723 return (result);
1724 }
1725
1726 static bool
1727 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
1728 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
1729 const dst_key_t *key, void *driverarg, void *dbdata) {
1730 dns_sdlzimplementation_t *imp;
1731 char b_signer[DNS_NAME_FORMATSIZE];
1732 char b_name[DNS_NAME_FORMATSIZE];
1733 char b_addr[ISC_NETADDR_FORMATSIZE];
1734 char b_type[DNS_RDATATYPE_FORMATSIZE];
1735 char b_key[DST_KEY_FORMATSIZE];
1736 isc_buffer_t *tkey_token = NULL;
1737 isc_region_t token_region = { NULL, 0 };
1738 uint32_t token_len = 0;
1739 bool ret;
1740
1741 REQUIRE(driverarg != NULL);
1742
1743 imp = (dns_sdlzimplementation_t *)driverarg;
1744 if (imp->methods->ssumatch == NULL) {
1745 return (false);
1746 }
1747
1748 /*
1749 * Format the request elements. sdlz operates on strings, not
1750 * structures
1751 */
1752 if (signer != NULL) {
1753 dns_name_format(signer, b_signer, sizeof(b_signer));
1754 } else {
1755 b_signer[0] = 0;
1756 }
1757
1758 dns_name_format(name, b_name, sizeof(b_name));
1759
1760 if (tcpaddr != NULL) {
1761 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
1762 } else {
1763 b_addr[0] = 0;
1764 }
1765
1766 dns_rdatatype_format(type, b_type, sizeof(b_type));
1767
1768 if (key != NULL) {
1769 dst_key_format(key, b_key, sizeof(b_key));
1770 tkey_token = dst_key_tkeytoken(key);
1771 } else {
1772 b_key[0] = 0;
1773 }
1774
1775 if (tkey_token != NULL) {
1776 isc_buffer_region(tkey_token, &token_region);
1777 token_len = token_region.length;
1778 }
1779
1780 MAYBE_LOCK(imp);
1781 ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1782 token_len,
1783 token_len != 0 ? token_region.base : NULL,
1784 imp->driverarg, dbdata);
1785 MAYBE_UNLOCK(imp);
1786 return (ret);
1787 }
1788
1789 static dns_dlzmethods_t sdlzmethods = { dns_sdlzcreate, dns_sdlzdestroy,
1790 dns_sdlzfindzone, dns_sdlzallowzonexfr,
1791 dns_sdlzconfigure, dns_sdlzssumatch };
1792
1793 /*
1794 * Public functions.
1795 */
1796
1797 isc_result_t
1798 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1799 const char *data) {
1800 dns_rdatalist_t *rdatalist;
1801 dns_rdata_t *rdata;
1802 dns_rdatatype_t typeval;
1803 isc_consttextregion_t r;
1804 isc_buffer_t b;
1805 isc_buffer_t *rdatabuf = NULL;
1806 isc_lex_t *lex;
1807 isc_result_t result;
1808 unsigned int size;
1809 isc_mem_t *mctx;
1810 const dns_name_t *origin;
1811
1812 REQUIRE(VALID_SDLZLOOKUP(lookup));
1813 REQUIRE(type != NULL);
1814 REQUIRE(data != NULL);
1815
1816 mctx = lookup->sdlz->common.mctx;
1817
1818 r.base = type;
1819 r.length = strlen(type);
1820 result = dns_rdatatype_fromtext(&typeval, (void *)&r);
1821 if (result != ISC_R_SUCCESS) {
1822 return (result);
1823 }
1824
1825 rdatalist = ISC_LIST_HEAD(lookup->lists);
1826 while (rdatalist != NULL) {
1827 if (rdatalist->type == typeval) {
1828 break;
1829 }
1830 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1831 }
1832
1833 if (rdatalist == NULL) {
1834 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1835 dns_rdatalist_init(rdatalist);
1836 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1837 rdatalist->type = typeval;
1838 rdatalist->ttl = ttl;
1839 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1840 } else if (rdatalist->ttl > ttl) {
1841 /*
1842 * BIND9 doesn't enforce all RRs in an RRset
1843 * having the same TTL, as per RFC 2136,
1844 * section 7.12. If a DLZ backend has
1845 * different TTLs, then the best
1846 * we can do is return the lowest.
1847 */
1848 rdatalist->ttl = ttl;
1849 }
1850
1851 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1852 dns_rdata_init(rdata);
1853
1854 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1855 origin = &lookup->sdlz->common.origin;
1856 } else {
1857 origin = dns_rootname;
1858 }
1859
1860 lex = NULL;
1861 result = isc_lex_create(mctx, 64, &lex);
1862 if (result != ISC_R_SUCCESS) {
1863 goto failure;
1864 }
1865
1866 size = initial_size(data);
1867 do {
1868 isc_buffer_constinit(&b, data, strlen(data));
1869 isc_buffer_add(&b, strlen(data));
1870
1871 result = isc_lex_openbuffer(lex, &b);
1872 if (result != ISC_R_SUCCESS) {
1873 goto failure;
1874 }
1875
1876 rdatabuf = NULL;
1877 isc_buffer_allocate(mctx, &rdatabuf, size);
1878
1879 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1880 rdatalist->type, lex, origin, false,
1881 mctx, rdatabuf, &lookup->callbacks);
1882 if (result != ISC_R_SUCCESS) {
1883 isc_buffer_free(&rdatabuf);
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 result = DNS_R_SERVFAIL;
1896 goto failure;
1897 }
1898
1899 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1900 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1901
1902 if (lex != NULL) {
1903 isc_lex_destroy(&lex);
1904 }
1905
1906 return (ISC_R_SUCCESS);
1907
1908 failure:
1909 if (rdatabuf != NULL) {
1910 isc_buffer_free(&rdatabuf);
1911 }
1912 if (lex != NULL) {
1913 isc_lex_destroy(&lex);
1914 }
1915 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1916
1917 return (result);
1918 }
1919
1920 isc_result_t
1921 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1922 const char *type, dns_ttl_t ttl, const char *data) {
1923 dns_name_t *newname;
1924 const dns_name_t *origin;
1925 dns_fixedname_t fnewname;
1926 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1927 dns_sdlznode_t *sdlznode;
1928 isc_mem_t *mctx = sdlz->common.mctx;
1929 isc_buffer_t b;
1930 isc_result_t result;
1931
1932 newname = dns_fixedname_initname(&fnewname);
1933
1934 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0) {
1935 origin = &sdlz->common.origin;
1936 } else {
1937 origin = dns_rootname;
1938 }
1939 isc_buffer_constinit(&b, name, strlen(name));
1940 isc_buffer_add(&b, strlen(name));
1941
1942 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1943 if (result != ISC_R_SUCCESS) {
1944 return (result);
1945 }
1946
1947 if (allnodes->common.relative_names) {
1948 /* All names are relative to the root */
1949 unsigned int nlabels = dns_name_countlabels(newname);
1950 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1951 }
1952
1953 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1954 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1955 sdlznode = NULL;
1956 result = createnode(sdlz, &sdlznode);
1957 if (result != ISC_R_SUCCESS) {
1958 return (result);
1959 }
1960 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1961 dns_name_init(sdlznode->name, NULL);
1962 dns_name_dup(newname, mctx, sdlznode->name);
1963 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
1964 if (allnodes->origin == NULL &&
1965 dns_name_equal(newname, &sdlz->common.origin)) {
1966 allnodes->origin = sdlznode;
1967 }
1968 }
1969 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
1970 }
1971
1972 isc_result_t
1973 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
1974 uint32_t serial) {
1975 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
1976 int n;
1977
1978 REQUIRE(mname != NULL);
1979 REQUIRE(rname != NULL);
1980
1981 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u", mname, rname,
1982 serial, SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
1983 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
1984 if (n >= (int)sizeof(str) || n < 0) {
1985 return (ISC_R_NOSPACE);
1986 }
1987 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
1988 }
1989
1990 isc_result_t
1991 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
1992 void *driverarg, unsigned int flags, isc_mem_t *mctx,
1993 dns_sdlzimplementation_t **sdlzimp) {
1994 dns_sdlzimplementation_t *imp;
1995 isc_result_t result;
1996
1997 /*
1998 * Performs checks to make sure data is as we expect it to be.
1999 */
2000 REQUIRE(drivername != NULL);
2001 REQUIRE(methods != NULL);
2002 REQUIRE(methods->findzone != NULL);
2003 REQUIRE(methods->lookup != NULL);
2004 REQUIRE(mctx != NULL);
2005 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
2006 REQUIRE((flags &
2007 ~(DNS_SDLZFLAG_RELATIVEOWNER | DNS_SDLZFLAG_RELATIVERDATA |
2008 DNS_SDLZFLAG_THREADSAFE)) == 0);
2009
2010 /* Write debugging message to log */
2011 sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
2012
2013 /*
2014 * Allocate memory for a sdlz_implementation object. Error if
2015 * we cannot.
2016 */
2017 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2018
2019 /* Make sure memory region is set to all 0's */
2020 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2021
2022 /* Store the data passed into this method */
2023 imp->methods = methods;
2024 imp->driverarg = driverarg;
2025 imp->flags = flags;
2026 imp->mctx = NULL;
2027
2028 /* attach the new sdlz_implementation object to a memory context */
2029 isc_mem_attach(mctx, &imp->mctx);
2030
2031 /*
2032 * initialize the driver lock, error if we cannot
2033 * (used if a driver does not support multiple threads)
2034 */
2035 isc_mutex_init(&imp->driverlock);
2036
2037 imp->dlz_imp = NULL;
2038
2039 /*
2040 * register the DLZ driver. Pass in our "extra" sdlz information as
2041 * a driverarg. (that's why we stored the passed in driver arg in our
2042 * sdlz_implementation structure) Also, store the dlz_implementation
2043 * structure in our sdlz_implementation.
2044 */
2045 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2046 &imp->dlz_imp);
2047
2048 /* if registration fails, cleanup and get outta here. */
2049 if (result != ISC_R_SUCCESS) {
2050 goto cleanup_mutex;
2051 }
2052
2053 *sdlzimp = imp;
2054
2055 return (ISC_R_SUCCESS);
2056
2057 cleanup_mutex:
2058 /* destroy the driver lock, we don't need it anymore */
2059 isc_mutex_destroy(&imp->driverlock);
2060
2061 /*
2062 * return the memory back to the available memory pool and
2063 * remove it from the memory context.
2064 */
2065 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2066 return (result);
2067 }
2068
2069 void
2070 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2071 dns_sdlzimplementation_t *imp;
2072
2073 /* Write debugging message to log */
2074 sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2075
2076 /*
2077 * Performs checks to make sure data is as we expect it to be.
2078 */
2079 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2080
2081 imp = *sdlzimp;
2082 *sdlzimp = NULL;
2083
2084 /* Unregister the DLZ driver implementation */
2085 dns_dlzunregister(&imp->dlz_imp);
2086
2087 /* destroy the driver lock, we don't need it anymore */
2088 isc_mutex_destroy(&imp->driverlock);
2089
2090 /*
2091 * return the memory back to the available memory pool and
2092 * remove it from the memory context.
2093 */
2094 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdlzimplementation_t));
2095 }
2096
2097 isc_result_t
2098 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
2099 const dns_name_t *name, dns_db_t **dbp) {
2100 isc_result_t result;
2101
2102 result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2103 dlzdatabase->implementation->driverarg,
2104 dlzdatabase->dbdata, name, rdclass, dbp);
2105 return (result);
2106 }
2107