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