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