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