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