sdlz.c revision 1.5 1 /* $NetBSD: sdlz.c,v 1.5 2019/11/27 05:48:41 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(sdlznode));
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 dns_name_copynf(xname, foundname);
1042 }
1043
1044 if (nodep != NULL)
1045 *nodep = node;
1046 else if (node != NULL)
1047 detachnode(db, &node);
1048
1049 return (result);
1050 }
1051
1052 static isc_result_t
1053 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
1054 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
1055 dns_dbnode_t **nodep, dns_name_t *foundname,
1056 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1057 {
1058 return (findext(db, name, version, type, options, now, nodep,
1059 foundname, NULL, NULL, rdataset, sigrdataset));
1060 }
1061
1062 static isc_result_t
1063 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1064 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1065 {
1066 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
1067 sdlz_rdatasetiter_t *iterator;
1068
1069 REQUIRE(VALID_SDLZDB(sdlz));
1070
1071 REQUIRE(version == NULL ||
1072 version == (void*)&sdlz->dummy_version ||
1073 version == sdlz->future_version);
1074
1075 UNUSED(version);
1076 UNUSED(now);
1077
1078 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
1079 if (iterator == NULL)
1080 return (ISC_R_NOMEMORY);
1081
1082 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1083 iterator->common.methods = &rdatasetiter_methods;
1084 iterator->common.db = db;
1085 iterator->common.node = NULL;
1086 attachnode(db, node, &iterator->common.node);
1087 iterator->common.version = version;
1088 iterator->common.now = now;
1089
1090 *iteratorp = (dns_rdatasetiter_t *)iterator;
1091
1092 return (ISC_R_SUCCESS);
1093 }
1094
1095 static isc_result_t
1096 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1097 dns_rdataset_t *rdataset, unsigned int options,
1098 dns_sdlzmodrdataset_t mod_function)
1099 {
1100 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1101 dns_master_style_t *style = NULL;
1102 isc_result_t result;
1103 isc_buffer_t *buffer = NULL;
1104 isc_mem_t *mctx;
1105 dns_sdlznode_t *sdlznode;
1106 char *rdatastr = NULL;
1107 char name[DNS_NAME_MAXTEXT + 1];
1108
1109 REQUIRE(VALID_SDLZDB(sdlz));
1110
1111 if (mod_function == NULL)
1112 return (ISC_R_NOTIMPLEMENTED);
1113
1114 sdlznode = (dns_sdlznode_t *)node;
1115
1116 UNUSED(options);
1117
1118 dns_name_format(sdlznode->name, name, sizeof(name));
1119
1120 mctx = sdlz->common.mctx;
1121
1122 result = isc_buffer_allocate(mctx, &buffer, 1024);
1123 if (result != ISC_R_SUCCESS)
1124 return (result);
1125
1126 result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1,
1127 0xffffffff, mctx);
1128 if (result != ISC_R_SUCCESS)
1129 goto cleanup;
1130
1131 result = dns_master_rdatasettotext(sdlznode->name, rdataset,
1132 style, buffer);
1133 if (result != ISC_R_SUCCESS)
1134 goto cleanup;
1135
1136 if (isc_buffer_usedlength(buffer) < 1) {
1137 result = ISC_R_BADADDRESSFORM;
1138 goto cleanup;
1139 }
1140
1141 rdatastr = isc_buffer_base(buffer);
1142 if (rdatastr == NULL) {
1143 result = ISC_R_NOMEMORY;
1144 goto cleanup;
1145 }
1146 rdatastr[isc_buffer_usedlength(buffer) - 1] = 0;
1147
1148 MAYBE_LOCK(sdlz->dlzimp);
1149 result = mod_function(name, rdatastr, sdlz->dlzimp->driverarg,
1150 sdlz->dbdata, version);
1151 MAYBE_UNLOCK(sdlz->dlzimp);
1152
1153 cleanup:
1154 isc_buffer_free(&buffer);
1155 if (style != NULL)
1156 dns_master_styledestroy(&style, mctx);
1157
1158 return (result);
1159 }
1160
1161 static isc_result_t
1162 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1163 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1164 dns_rdataset_t *addedrdataset)
1165 {
1166 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1167 isc_result_t result;
1168
1169 UNUSED(now);
1170 UNUSED(addedrdataset);
1171 REQUIRE(VALID_SDLZDB(sdlz));
1172
1173 if (sdlz->dlzimp->methods->addrdataset == NULL)
1174 return (ISC_R_NOTIMPLEMENTED);
1175
1176 result = modrdataset(db, node, version, rdataset, options,
1177 sdlz->dlzimp->methods->addrdataset);
1178 return (result);
1179 }
1180
1181
1182 static isc_result_t
1183 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1184 dns_rdataset_t *rdataset, unsigned int options,
1185 dns_rdataset_t *newrdataset)
1186 {
1187 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1188 isc_result_t result;
1189
1190 UNUSED(newrdataset);
1191 REQUIRE(VALID_SDLZDB(sdlz));
1192
1193 if (sdlz->dlzimp->methods->subtractrdataset == NULL) {
1194 return (ISC_R_NOTIMPLEMENTED);
1195 }
1196
1197 result = modrdataset(db, node, version, rdataset, options,
1198 sdlz->dlzimp->methods->subtractrdataset);
1199 return (result);
1200 }
1201
1202 static isc_result_t
1203 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1204 dns_rdatatype_t type, dns_rdatatype_t covers)
1205 {
1206 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1207 char name[DNS_NAME_MAXTEXT + 1];
1208 char b_type[DNS_RDATATYPE_FORMATSIZE];
1209 dns_sdlznode_t *sdlznode;
1210 isc_result_t result;
1211
1212 UNUSED(covers);
1213
1214 REQUIRE(VALID_SDLZDB(sdlz));
1215
1216 if (sdlz->dlzimp->methods->delrdataset == NULL)
1217 return (ISC_R_NOTIMPLEMENTED);
1218
1219 sdlznode = (dns_sdlznode_t *)node;
1220 dns_name_format(sdlznode->name, name, sizeof(name));
1221 dns_rdatatype_format(type, b_type, sizeof(b_type));
1222
1223 MAYBE_LOCK(sdlz->dlzimp);
1224 result = sdlz->dlzimp->methods->delrdataset(name, b_type,
1225 sdlz->dlzimp->driverarg,
1226 sdlz->dbdata, version);
1227 MAYBE_UNLOCK(sdlz->dlzimp);
1228
1229 return (result);
1230 }
1231
1232 static bool
1233 issecure(dns_db_t *db) {
1234 UNUSED(db);
1235
1236 return (false);
1237 }
1238
1239 static unsigned int
1240 nodecount(dns_db_t *db) {
1241 UNUSED(db);
1242
1243 return (0);
1244 }
1245
1246 static bool
1247 ispersistent(dns_db_t *db) {
1248 UNUSED(db);
1249 return (true);
1250 }
1251
1252 static void
1253 overmem(dns_db_t *db, bool over) {
1254 UNUSED(db);
1255 UNUSED(over);
1256 }
1257
1258 static void
1259 settask(dns_db_t *db, isc_task_t *task) {
1260 UNUSED(db);
1261 UNUSED(task);
1262 }
1263
1264 /*
1265 * getoriginnode() is used by the update code to find the
1266 * dns_rdatatype_dnskey record for a zone
1267 */
1268 static isc_result_t
1269 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
1270 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1271 isc_result_t result;
1272
1273 REQUIRE(VALID_SDLZDB(sdlz));
1274 if (sdlz->dlzimp->methods->newversion == NULL)
1275 return (ISC_R_NOTIMPLEMENTED);
1276
1277 result = getnodedata(db, &sdlz->common.origin, false,
1278 0, NULL, NULL, nodep);
1279 if (result != ISC_R_SUCCESS)
1280 sdlz_log(ISC_LOG_ERROR, "sdlz getoriginnode failed: %s",
1281 isc_result_totext(result));
1282 return (result);
1283 }
1284
1285 static dns_dbmethods_t sdlzdb_methods = {
1286 attach,
1287 detach,
1288 beginload,
1289 endload,
1290 NULL, /* serialize */
1291 dump,
1292 currentversion,
1293 newversion,
1294 attachversion,
1295 closeversion,
1296 findnode,
1297 find,
1298 findzonecut,
1299 attachnode,
1300 detachnode,
1301 expirenode,
1302 printnode,
1303 createiterator,
1304 findrdataset,
1305 allrdatasets,
1306 addrdataset,
1307 subtractrdataset,
1308 deleterdataset,
1309 issecure,
1310 nodecount,
1311 ispersistent,
1312 overmem,
1313 settask,
1314 getoriginnode,
1315 NULL, /* transfernode */
1316 NULL, /* getnsec3parameters */
1317 NULL, /* findnsec3node */
1318 NULL, /* setsigningtime */
1319 NULL, /* getsigningtime */
1320 NULL, /* resigned */
1321 NULL, /* isdnssec */
1322 NULL, /* getrrsetstats */
1323 NULL, /* rpz_attach */
1324 NULL, /* rpz_ready */
1325 findnodeext,
1326 findext,
1327 NULL, /* setcachestats */
1328 NULL, /* hashsize */
1329 NULL, /* nodefullname */
1330 NULL, /* getsize */
1331 NULL, /* setservestalettl */
1332 NULL, /* getservestalettl */
1333 NULL /* setgluecachestats */
1334 };
1335
1336 /*
1337 * Database Iterator Methods. These methods were "borrowed" from the SDB
1338 * driver interface. See the SDB driver interface documentation for more info.
1339 */
1340
1341 static void
1342 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1343 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)(*iteratorp);
1344 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)sdlziter->common.db;
1345
1346 while (!ISC_LIST_EMPTY(sdlziter->nodelist)) {
1347 dns_sdlznode_t *node;
1348 node = ISC_LIST_HEAD(sdlziter->nodelist);
1349 ISC_LIST_UNLINK(sdlziter->nodelist, node, link);
1350 destroynode(node);
1351 }
1352
1353 dns_db_detach(&sdlziter->common.db);
1354 isc_mem_put(sdlz->common.mctx, sdlziter, sizeof(sdlz_dbiterator_t));
1355
1356 *iteratorp = NULL;
1357 }
1358
1359 static isc_result_t
1360 dbiterator_first(dns_dbiterator_t *iterator) {
1361 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1362
1363 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1364 if (sdlziter->current == NULL)
1365 return (ISC_R_NOMORE);
1366 else
1367 return (ISC_R_SUCCESS);
1368 }
1369
1370 static isc_result_t
1371 dbiterator_last(dns_dbiterator_t *iterator) {
1372 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1373
1374 sdlziter->current = ISC_LIST_TAIL(sdlziter->nodelist);
1375 if (sdlziter->current == NULL)
1376 return (ISC_R_NOMORE);
1377 else
1378 return (ISC_R_SUCCESS);
1379 }
1380
1381 static isc_result_t
1382 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1383 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1384
1385 sdlziter->current = ISC_LIST_HEAD(sdlziter->nodelist);
1386 while (sdlziter->current != NULL) {
1387 if (dns_name_equal(sdlziter->current->name, name))
1388 return (ISC_R_SUCCESS);
1389 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1390 }
1391 return (ISC_R_NOTFOUND);
1392 }
1393
1394 static isc_result_t
1395 dbiterator_prev(dns_dbiterator_t *iterator) {
1396 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1397
1398 sdlziter->current = ISC_LIST_PREV(sdlziter->current, link);
1399 if (sdlziter->current == NULL)
1400 return (ISC_R_NOMORE);
1401 else
1402 return (ISC_R_SUCCESS);
1403 }
1404
1405 static isc_result_t
1406 dbiterator_next(dns_dbiterator_t *iterator) {
1407 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1408
1409 sdlziter->current = ISC_LIST_NEXT(sdlziter->current, link);
1410 if (sdlziter->current == NULL)
1411 return (ISC_R_NOMORE);
1412 else
1413 return (ISC_R_SUCCESS);
1414 }
1415
1416 static isc_result_t
1417 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1418 dns_name_t *name)
1419 {
1420 sdlz_dbiterator_t *sdlziter = (sdlz_dbiterator_t *)iterator;
1421
1422 attachnode(iterator->db, sdlziter->current, nodep);
1423 if (name != NULL) {
1424 dns_name_copynf(sdlziter->current->name, name);
1425 return (ISC_R_SUCCESS);
1426 }
1427 return (ISC_R_SUCCESS);
1428 }
1429
1430 static isc_result_t
1431 dbiterator_pause(dns_dbiterator_t *iterator) {
1432 UNUSED(iterator);
1433 return (ISC_R_SUCCESS);
1434 }
1435
1436 static isc_result_t
1437 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1438 UNUSED(iterator);
1439 dns_name_copynf(dns_rootname, name);
1440 return (ISC_R_SUCCESS);
1441 }
1442
1443 /*
1444 * Rdataset Methods. These methods were "borrowed" from the SDB driver
1445 * interface. See the SDB driver interface documentation for more info.
1446 */
1447
1448 static void
1449 disassociate(dns_rdataset_t *rdataset) {
1450 dns_dbnode_t *node = rdataset->private5;
1451 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1452 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1453
1454 detachnode(db, &node);
1455 isc__rdatalist_disassociate(rdataset);
1456 }
1457
1458 static void
1459 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1460 dns_dbnode_t *node = source->private5;
1461 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *) node;
1462 dns_db_t *db = (dns_db_t *) sdlznode->sdlz;
1463 dns_dbnode_t *tempdb = NULL;
1464
1465 isc__rdatalist_clone(source, target);
1466 attachnode(db, node, &tempdb);
1467 source->private5 = tempdb;
1468 }
1469
1470 static dns_rdatasetmethods_t rdataset_methods = {
1471 disassociate,
1472 isc__rdatalist_first,
1473 isc__rdatalist_next,
1474 isc__rdatalist_current,
1475 rdataset_clone,
1476 isc__rdatalist_count,
1477 isc__rdatalist_addnoqname,
1478 isc__rdatalist_getnoqname,
1479 NULL, /* addclosest */
1480 NULL, /* getclosest */
1481 NULL, /* settrust */
1482 NULL, /* expire */
1483 NULL, /* clearprefetch */
1484 NULL, /* setownercase */
1485 NULL, /* getownercase */
1486 NULL /* addglue */
1487 };
1488
1489 static void
1490 list_tordataset(dns_rdatalist_t *rdatalist,
1491 dns_db_t *db, dns_dbnode_t *node,
1492 dns_rdataset_t *rdataset)
1493 {
1494 /*
1495 * The sdlz rdataset is an rdatalist with some additions.
1496 * - private1 & private2 are used by the rdatalist.
1497 * - private3 & private 4 are unused.
1498 * - private5 is the node.
1499 */
1500
1501 /* This should never fail. */
1502 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1503 ISC_R_SUCCESS);
1504
1505 rdataset->methods = &rdataset_methods;
1506 dns_db_attachnode(db, node, &rdataset->private5);
1507 }
1508
1509 /*
1510 * SDLZ core methods. This is the core of the new DLZ functionality.
1511 */
1512
1513 /*%
1514 * Build a 'bind' database driver structure to be returned by
1515 * either the find zone or the allow zone transfer method.
1516 * This method is only available in this source file, it is
1517 * not made available anywhere else.
1518 */
1519
1520 static isc_result_t
1521 dns_sdlzcreateDBP(isc_mem_t *mctx, void *driverarg, void *dbdata,
1522 const dns_name_t *name, dns_rdataclass_t rdclass,
1523 dns_db_t **dbp)
1524 {
1525 isc_result_t result;
1526 dns_sdlz_db_t *sdlzdb;
1527 dns_sdlzimplementation_t *imp;
1528
1529 /* check that things are as we expect */
1530 REQUIRE(dbp != NULL && *dbp == NULL);
1531 REQUIRE(name != NULL);
1532
1533 imp = (dns_sdlzimplementation_t *) driverarg;
1534
1535 /* allocate and zero memory for driver structure */
1536 sdlzdb = isc_mem_get(mctx, sizeof(dns_sdlz_db_t));
1537 if (sdlzdb == NULL)
1538 return (ISC_R_NOMEMORY);
1539 memset(sdlzdb, 0, sizeof(dns_sdlz_db_t));
1540
1541 /* initialize and set origin */
1542 dns_name_init(&sdlzdb->common.origin, NULL);
1543 result = dns_name_dupwithoffsets(name, mctx, &sdlzdb->common.origin);
1544 if (result != ISC_R_SUCCESS)
1545 goto mem_cleanup;
1546
1547 /* initialize the reference count mutex */
1548 isc_mutex_init(&sdlzdb->refcnt_lock);
1549
1550 /* set the rest of the database structure attributes */
1551 sdlzdb->dlzimp = imp;
1552 sdlzdb->common.methods = &sdlzdb_methods;
1553 sdlzdb->common.attributes = 0;
1554 sdlzdb->common.rdclass = rdclass;
1555 sdlzdb->common.mctx = NULL;
1556 sdlzdb->dbdata = dbdata;
1557 sdlzdb->references = 1;
1558
1559 /* attach to the memory context */
1560 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1561
1562 /* mark structure as valid */
1563 sdlzdb->common.magic = DNS_DB_MAGIC;
1564 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1565 *dbp = (dns_db_t *) sdlzdb;
1566
1567 return (result);
1568 mem_cleanup:
1569 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1570 return (result);
1571 }
1572
1573 static isc_result_t
1574 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1575 dns_rdataclass_t rdclass, const dns_name_t *name,
1576 const isc_sockaddr_t *clientaddr, dns_db_t **dbp)
1577 {
1578 isc_buffer_t b;
1579 isc_buffer_t b2;
1580 char namestr[DNS_NAME_MAXTEXT + 1];
1581 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1582 + 1];
1583 isc_netaddr_t netaddr;
1584 isc_result_t result;
1585 dns_sdlzimplementation_t *imp;
1586
1587 /*
1588 * Perform checks to make sure data is as we expect it to be.
1589 */
1590 REQUIRE(driverarg != NULL);
1591 REQUIRE(name != NULL);
1592 REQUIRE(clientaddr != NULL);
1593 REQUIRE(dbp != NULL && *dbp == NULL);
1594
1595 imp = (dns_sdlzimplementation_t *) driverarg;
1596
1597 /* Convert DNS name to ascii text */
1598 isc_buffer_init(&b, namestr, sizeof(namestr));
1599 result = dns_name_totext(name, true, &b);
1600 if (result != ISC_R_SUCCESS)
1601 return (result);
1602 isc_buffer_putuint8(&b, 0);
1603
1604 /* convert client address to ascii text */
1605 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1606 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1607 result = isc_netaddr_totext(&netaddr, &b2);
1608 if (result != ISC_R_SUCCESS)
1609 return (result);
1610 isc_buffer_putuint8(&b2, 0);
1611
1612 /* make sure strings are always lowercase */
1613 dns_sdlz_tolower(namestr);
1614 dns_sdlz_tolower(clientstr);
1615
1616 /* Call SDLZ driver's find zone method */
1617 if (imp->methods->allowzonexfr != NULL) {
1618 MAYBE_LOCK(imp);
1619 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1620 namestr, clientstr);
1621 MAYBE_UNLOCK(imp);
1622 /*
1623 * if zone is supported and transfers allowed build a 'bind'
1624 * database driver
1625 */
1626 if (result == ISC_R_SUCCESS)
1627 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1628 name, rdclass, dbp);
1629 return (result);
1630 }
1631
1632 return (ISC_R_NOTIMPLEMENTED);
1633 }
1634
1635 static isc_result_t
1636 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1637 char *argv[], void *driverarg, void **dbdata)
1638 {
1639 dns_sdlzimplementation_t *imp;
1640 isc_result_t result = ISC_R_NOTFOUND;
1641
1642 /* Write debugging message to log */
1643 sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1644
1645 /*
1646 * Performs checks to make sure data is as we expect it to be.
1647 */
1648 REQUIRE(driverarg != NULL);
1649 REQUIRE(dlzname != NULL);
1650 REQUIRE(dbdata != NULL);
1651 UNUSED(mctx);
1652
1653 imp = driverarg;
1654
1655 /* If the create method exists, call it. */
1656 if (imp->methods->create != NULL) {
1657 MAYBE_LOCK(imp);
1658 result = imp->methods->create(dlzname, argc, argv,
1659 imp->driverarg, dbdata);
1660 MAYBE_UNLOCK(imp);
1661 }
1662
1663 /* Write debugging message to log */
1664 if (result == ISC_R_SUCCESS) {
1665 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1666 } else {
1667 sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1668 }
1669
1670 return (result);
1671 }
1672
1673 static void
1674 dns_sdlzdestroy(void *driverdata, void **dbdata) {
1675 dns_sdlzimplementation_t *imp;
1676
1677 /* Write debugging message to log */
1678 sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1679
1680 imp = driverdata;
1681
1682 /* If the destroy method exists, call it. */
1683 if (imp->methods->destroy != NULL) {
1684 MAYBE_LOCK(imp);
1685 imp->methods->destroy(imp->driverarg, dbdata);
1686 MAYBE_UNLOCK(imp);
1687 }
1688 }
1689
1690 static isc_result_t
1691 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1692 dns_rdataclass_t rdclass, const dns_name_t *name,
1693 dns_clientinfomethods_t *methods,
1694 dns_clientinfo_t *clientinfo,
1695 dns_db_t **dbp)
1696 {
1697 isc_buffer_t b;
1698 char namestr[DNS_NAME_MAXTEXT + 1];
1699 isc_result_t result;
1700 dns_sdlzimplementation_t *imp;
1701
1702 /*
1703 * Perform checks to make sure data is as we expect it to be.
1704 */
1705 REQUIRE(driverarg != NULL);
1706 REQUIRE(name != NULL);
1707 REQUIRE(dbp != NULL && *dbp == NULL);
1708
1709 imp = (dns_sdlzimplementation_t *) driverarg;
1710
1711 /* Convert DNS name to ascii text */
1712 isc_buffer_init(&b, namestr, sizeof(namestr));
1713 result = dns_name_totext(name, true, &b);
1714 if (result != ISC_R_SUCCESS)
1715 return (result);
1716 isc_buffer_putuint8(&b, 0);
1717
1718 /* make sure strings are always lowercase */
1719 dns_sdlz_tolower(namestr);
1720
1721 /* Call SDLZ driver's find zone method */
1722 MAYBE_LOCK(imp);
1723 result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1724 methods, clientinfo);
1725 MAYBE_UNLOCK(imp);
1726
1727 /*
1728 * if zone is supported build a 'bind' database driver
1729 * structure to return
1730 */
1731 if (result == ISC_R_SUCCESS)
1732 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1733 rdclass, dbp);
1734
1735 return (result);
1736 }
1737
1738
1739 static isc_result_t
1740 dns_sdlzconfigure(void *driverarg, void *dbdata,
1741 dns_view_t *view, dns_dlzdb_t *dlzdb)
1742 {
1743 isc_result_t result;
1744 dns_sdlzimplementation_t *imp;
1745
1746 REQUIRE(driverarg != NULL);
1747
1748 imp = (dns_sdlzimplementation_t *) driverarg;
1749
1750 /* Call SDLZ driver's configure method */
1751 if (imp->methods->configure != NULL) {
1752 MAYBE_LOCK(imp);
1753 result = imp->methods->configure(view, dlzdb,
1754 imp->driverarg, dbdata);
1755 MAYBE_UNLOCK(imp);
1756 } else {
1757 result = ISC_R_SUCCESS;
1758 }
1759
1760 return (result);
1761 }
1762
1763 static bool
1764 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
1765 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
1766 const dst_key_t *key, void *driverarg, void *dbdata)
1767 {
1768 dns_sdlzimplementation_t *imp;
1769 char b_signer[DNS_NAME_FORMATSIZE];
1770 char b_name[DNS_NAME_FORMATSIZE];
1771 char b_addr[ISC_NETADDR_FORMATSIZE];
1772 char b_type[DNS_RDATATYPE_FORMATSIZE];
1773 char b_key[DST_KEY_FORMATSIZE];
1774 isc_buffer_t *tkey_token = NULL;
1775 isc_region_t token_region = { NULL, 0 };
1776 uint32_t token_len = 0;
1777 bool ret;
1778
1779 REQUIRE(driverarg != NULL);
1780
1781 imp = (dns_sdlzimplementation_t *) driverarg;
1782 if (imp->methods->ssumatch == NULL)
1783 return (false);
1784
1785 /*
1786 * Format the request elements. sdlz operates on strings, not
1787 * structures
1788 */
1789 if (signer != NULL)
1790 dns_name_format(signer, b_signer, sizeof(b_signer));
1791 else
1792 b_signer[0] = 0;
1793
1794 dns_name_format(name, b_name, sizeof(b_name));
1795
1796 if (tcpaddr != NULL)
1797 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
1798 else
1799 b_addr[0] = 0;
1800
1801 dns_rdatatype_format(type, b_type, sizeof(b_type));
1802
1803 if (key != NULL) {
1804 dst_key_format(key, b_key, sizeof(b_key));
1805 tkey_token = dst_key_tkeytoken(key);
1806 } else
1807 b_key[0] = 0;
1808
1809 if (tkey_token != NULL) {
1810 isc_buffer_region(tkey_token, &token_region);
1811 token_len = token_region.length;
1812 }
1813
1814 MAYBE_LOCK(imp);
1815 ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1816 token_len,
1817 token_len != 0 ? token_region.base : NULL,
1818 imp->driverarg, dbdata);
1819 MAYBE_UNLOCK(imp);
1820 return (ret);
1821 }
1822
1823 static dns_dlzmethods_t sdlzmethods = {
1824 dns_sdlzcreate,
1825 dns_sdlzdestroy,
1826 dns_sdlzfindzone,
1827 dns_sdlzallowzonexfr,
1828 dns_sdlzconfigure,
1829 dns_sdlzssumatch
1830 };
1831
1832 /*
1833 * Public functions.
1834 */
1835
1836 isc_result_t
1837 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1838 const char *data)
1839 {
1840 dns_rdatalist_t *rdatalist;
1841 dns_rdata_t *rdata;
1842 dns_rdatatype_t typeval;
1843 isc_consttextregion_t r;
1844 isc_buffer_t b;
1845 isc_buffer_t *rdatabuf = NULL;
1846 isc_lex_t *lex;
1847 isc_result_t result;
1848 unsigned int size;
1849 isc_mem_t *mctx;
1850 const dns_name_t *origin;
1851
1852 REQUIRE(VALID_SDLZLOOKUP(lookup));
1853 REQUIRE(type != NULL);
1854 REQUIRE(data != NULL);
1855
1856 mctx = lookup->sdlz->common.mctx;
1857
1858 r.base = type;
1859 r.length = strlen(type);
1860 result = dns_rdatatype_fromtext(&typeval, (void *) &r);
1861 if (result != ISC_R_SUCCESS)
1862 return (result);
1863
1864 rdatalist = ISC_LIST_HEAD(lookup->lists);
1865 while (rdatalist != NULL) {
1866 if (rdatalist->type == typeval)
1867 break;
1868 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1869 }
1870
1871 if (rdatalist == NULL) {
1872 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1873 if (rdatalist == NULL)
1874 return (ISC_R_NOMEMORY);
1875 dns_rdatalist_init(rdatalist);
1876 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1877 rdatalist->type = typeval;
1878 rdatalist->ttl = ttl;
1879 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1880 } else
1881 if (rdatalist->ttl > ttl) {
1882 /*
1883 * BIND9 doesn't enforce all RRs in an RRset
1884 * having the same TTL, as per RFC 2136,
1885 * section 7.12. If a DLZ backend has
1886 * different TTLs, then the best
1887 * we can do is return the lowest.
1888 */
1889 rdatalist->ttl = ttl;
1890 }
1891
1892 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1893 if (rdata == NULL)
1894 return (ISC_R_NOMEMORY);
1895 dns_rdata_init(rdata);
1896
1897 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1898 origin = &lookup->sdlz->common.origin;
1899 else
1900 origin = dns_rootname;
1901
1902 lex = NULL;
1903 result = isc_lex_create(mctx, 64, &lex);
1904 if (result != ISC_R_SUCCESS)
1905 goto failure;
1906
1907 size = initial_size(data);
1908 do {
1909 isc_buffer_constinit(&b, data, strlen(data));
1910 isc_buffer_add(&b, strlen(data));
1911
1912 result = isc_lex_openbuffer(lex, &b);
1913 if (result != ISC_R_SUCCESS)
1914 goto failure;
1915
1916 rdatabuf = NULL;
1917 result = isc_buffer_allocate(mctx, &rdatabuf, size);
1918 if (result != ISC_R_SUCCESS)
1919 goto failure;
1920
1921 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1922 rdatalist->type, lex,
1923 origin, false,
1924 mctx, rdatabuf,
1925 &lookup->callbacks);
1926 if (result != ISC_R_SUCCESS) {
1927 isc_buffer_free(&rdatabuf);
1928 result = DNS_R_SERVFAIL;
1929 }
1930 if (size >= 65535)
1931 break;
1932 size *= 2;
1933 if (size >= 65535)
1934 size = 65535;
1935 } while (result == ISC_R_NOSPACE);
1936
1937 if (result != ISC_R_SUCCESS)
1938 goto failure;
1939
1940 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1941 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1942
1943 if (lex != NULL)
1944 isc_lex_destroy(&lex);
1945
1946 return (ISC_R_SUCCESS);
1947
1948 failure:
1949 if (rdatabuf != NULL)
1950 isc_buffer_free(&rdatabuf);
1951 if (lex != NULL)
1952 isc_lex_destroy(&lex);
1953 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1954
1955 return (result);
1956 }
1957
1958 isc_result_t
1959 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1960 const char *type, dns_ttl_t ttl, const char *data)
1961 {
1962 dns_name_t *newname;
1963 const dns_name_t *origin;
1964 dns_fixedname_t fnewname;
1965 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1966 dns_sdlznode_t *sdlznode;
1967 isc_mem_t *mctx = sdlz->common.mctx;
1968 isc_buffer_t b;
1969 isc_result_t result;
1970
1971 newname = dns_fixedname_initname(&fnewname);
1972
1973 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1974 origin = &sdlz->common.origin;
1975 else
1976 origin = dns_rootname;
1977 isc_buffer_constinit(&b, name, strlen(name));
1978 isc_buffer_add(&b, strlen(name));
1979
1980 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1981 if (result != ISC_R_SUCCESS)
1982 return (result);
1983
1984 if (allnodes->common.relative_names) {
1985 /* All names are relative to the root */
1986 unsigned int nlabels = dns_name_countlabels(newname);
1987 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1988 }
1989
1990 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1991 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1992 sdlznode = NULL;
1993 result = createnode(sdlz, &sdlznode);
1994 if (result != ISC_R_SUCCESS)
1995 return (result);
1996 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
1997 if (sdlznode->name == NULL) {
1998 destroynode(sdlznode);
1999 return (ISC_R_NOMEMORY);
2000 }
2001 dns_name_init(sdlznode->name, NULL);
2002 result = dns_name_dup(newname, mctx, sdlznode->name);
2003 if (result != ISC_R_SUCCESS) {
2004 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
2005 destroynode(sdlznode);
2006 return (result);
2007 }
2008 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
2009 if (allnodes->origin == NULL &&
2010 dns_name_equal(newname, &sdlz->common.origin))
2011 allnodes->origin = sdlznode;
2012 }
2013 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
2014
2015 }
2016
2017 isc_result_t
2018 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
2019 uint32_t serial)
2020 {
2021 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
2022 int n;
2023
2024 REQUIRE(mname != NULL);
2025 REQUIRE(rname != NULL);
2026
2027 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
2028 mname, rname, serial,
2029 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
2030 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
2031 if (n >= (int)sizeof(str) || n < 0)
2032 return (ISC_R_NOSPACE);
2033 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
2034 }
2035
2036 isc_result_t
2037 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
2038 void *driverarg, unsigned int flags, isc_mem_t *mctx,
2039 dns_sdlzimplementation_t **sdlzimp)
2040 {
2041
2042 dns_sdlzimplementation_t *imp;
2043 isc_result_t result;
2044
2045 /*
2046 * Performs checks to make sure data is as we expect it to be.
2047 */
2048 REQUIRE(drivername != NULL);
2049 REQUIRE(methods != NULL);
2050 REQUIRE(methods->findzone != NULL);
2051 REQUIRE(methods->lookup != NULL);
2052 REQUIRE(mctx != NULL);
2053 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
2054 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
2055 DNS_SDLZFLAG_RELATIVERDATA |
2056 DNS_SDLZFLAG_THREADSAFE)) == 0);
2057
2058 /* Write debugging message to log */
2059 sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
2060
2061 /*
2062 * Allocate memory for a sdlz_implementation object. Error if
2063 * we cannot.
2064 */
2065 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2066 if (imp == NULL)
2067 return (ISC_R_NOMEMORY);
2068
2069 /* Make sure memory region is set to all 0's */
2070 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2071
2072 /* Store the data passed into this method */
2073 imp->methods = methods;
2074 imp->driverarg = driverarg;
2075 imp->flags = flags;
2076 imp->mctx = NULL;
2077
2078 /* attach the new sdlz_implementation object to a memory context */
2079 isc_mem_attach(mctx, &imp->mctx);
2080
2081 /*
2082 * initialize the driver lock, error if we cannot
2083 * (used if a driver does not support multiple threads)
2084 */
2085 isc_mutex_init(&imp->driverlock);
2086
2087 imp->dlz_imp = NULL;
2088
2089 /*
2090 * register the DLZ driver. Pass in our "extra" sdlz information as
2091 * a driverarg. (that's why we stored the passed in driver arg in our
2092 * sdlz_implementation structure) Also, store the dlz_implementation
2093 * structure in our sdlz_implementation.
2094 */
2095 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2096 &imp->dlz_imp);
2097
2098 /* if registration fails, cleanup and get outta here. */
2099 if (result != ISC_R_SUCCESS)
2100 goto cleanup_mutex;
2101
2102 *sdlzimp = imp;
2103
2104 return (ISC_R_SUCCESS);
2105
2106 cleanup_mutex:
2107 /* destroy the driver lock, we don't need it anymore */
2108 isc_mutex_destroy(&imp->driverlock);
2109
2110 /*
2111 * return the memory back to the available memory pool and
2112 * remove it from the memory context.
2113 */
2114 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
2115 isc_mem_detach(&mctx);
2116 return (result);
2117 }
2118
2119 void
2120 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2121 dns_sdlzimplementation_t *imp;
2122 isc_mem_t *mctx;
2123
2124 /* Write debugging message to log */
2125 sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2126
2127 /*
2128 * Performs checks to make sure data is as we expect it to be.
2129 */
2130 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2131
2132 imp = *sdlzimp;
2133
2134 /* Unregister the DLZ driver implementation */
2135 dns_dlzunregister(&imp->dlz_imp);
2136
2137 /* destroy the driver lock, we don't need it anymore */
2138 isc_mutex_destroy(&imp->driverlock);
2139
2140 mctx = imp->mctx;
2141
2142 /*
2143 * return the memory back to the available memory pool and
2144 * remove it from the memory context.
2145 */
2146 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
2147 isc_mem_detach(&mctx);
2148
2149 *sdlzimp = NULL;
2150 }
2151
2152
2153 isc_result_t
2154 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
2155 const dns_name_t *name, dns_db_t **dbp)
2156 {
2157 isc_result_t result;
2158
2159 result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2160 dlzdatabase->implementation->driverarg,
2161 dlzdatabase->dbdata, name, rdclass, dbp);
2162 return (result);
2163 }
2164