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