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