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