sdlz.c revision 1.1.1.3 1 /* $NetBSD: sdlz.c,v 1.1.1.3 2019/04/27 23:47:29 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 - 1) {
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 MAYBE_UNLOCK(sdlz->dlzimp);
631 return (result);
632 }
633 wild = fname;
634 }
635
636 isc_buffer_init(&b, wildstr, sizeof(wildstr));
637 result = dns_name_totext(wild, true, &b);
638 if (result != ISC_R_SUCCESS) {
639 MAYBE_UNLOCK(sdlz->dlzimp);
640 return (result);
641 }
642 isc_buffer_putuint8(&b, 0);
643
644 result = sdlz->dlzimp->methods->lookup(zonestr, wildstr,
645 sdlz->dlzimp->driverarg,
646 sdlz->dbdata, node,
647 methods, clientinfo);
648 if (result == ISC_R_SUCCESS)
649 break;
650 }
651 }
652
653 MAYBE_UNLOCK(sdlz->dlzimp);
654
655 if (result == ISC_R_NOTFOUND && (isorigin || create))
656 result = ISC_R_SUCCESS;
657
658 if (result != ISC_R_SUCCESS) {
659 destroynode(node);
660 return (result);
661 }
662
663 if (isorigin && sdlz->dlzimp->methods->authority != NULL) {
664 MAYBE_LOCK(sdlz->dlzimp);
665 authority = sdlz->dlzimp->methods->authority;
666 result = (*authority)(zonestr, sdlz->dlzimp->driverarg,
667 sdlz->dbdata, node);
668 MAYBE_UNLOCK(sdlz->dlzimp);
669 if (result != ISC_R_SUCCESS &&
670 result != ISC_R_NOTIMPLEMENTED)
671 {
672 destroynode(node);
673 return (result);
674 }
675 }
676
677 if (node->name == NULL) {
678 node->name = isc_mem_get(sdlz->common.mctx,
679 sizeof(dns_name_t));
680 if (node->name == NULL) {
681 destroynode(node);
682 return (ISC_R_NOMEMORY);
683 }
684 dns_name_init(node->name, NULL);
685 result = dns_name_dup(name, sdlz->common.mctx, node->name);
686 if (result != ISC_R_SUCCESS) {
687 isc_mem_put(sdlz->common.mctx, node->name,
688 sizeof(dns_name_t));
689 destroynode(node);
690 return (result);
691 }
692 }
693
694 *nodep = node;
695 return (ISC_R_SUCCESS);
696 }
697
698 static isc_result_t
699 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
700 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
701 dns_dbnode_t **nodep)
702 {
703 return (getnodedata(db, name, create, 0, methods, clientinfo, nodep));
704 }
705
706 static isc_result_t
707 findnode(dns_db_t *db, const dns_name_t *name, bool create,
708 dns_dbnode_t **nodep)
709 {
710 return (getnodedata(db, name, create, 0, NULL, NULL, nodep));
711 }
712
713 static isc_result_t
714 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
715 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
716 dns_name_t *dcname, dns_rdataset_t *rdataset,
717 dns_rdataset_t *sigrdataset)
718 {
719 UNUSED(db);
720 UNUSED(name);
721 UNUSED(options);
722 UNUSED(now);
723 UNUSED(nodep);
724 UNUSED(foundname);
725 UNUSED(dcname);
726 UNUSED(rdataset);
727 UNUSED(sigrdataset);
728
729 return (ISC_R_NOTIMPLEMENTED);
730 }
731
732 static void
733 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
734 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
735 dns_sdlznode_t *node = (dns_sdlznode_t *)source;
736
737 REQUIRE(VALID_SDLZDB(sdlz));
738
739 UNUSED(sdlz);
740
741 LOCK(&node->lock);
742 INSIST(node->references > 0);
743 node->references++;
744 INSIST(node->references != 0); /* Catch overflow. */
745 UNLOCK(&node->lock);
746
747 *targetp = source;
748 }
749
750 static void
751 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
752 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
753 dns_sdlznode_t *node;
754 bool need_destroy = false;
755
756 REQUIRE(VALID_SDLZDB(sdlz));
757 REQUIRE(targetp != NULL && *targetp != NULL);
758
759 UNUSED(sdlz);
760
761 node = (dns_sdlznode_t *)(*targetp);
762
763 LOCK(&node->lock);
764 INSIST(node->references > 0);
765 node->references--;
766 if (node->references == 0)
767 need_destroy = true;
768 UNLOCK(&node->lock);
769
770 if (need_destroy)
771 destroynode(node);
772
773 *targetp = NULL;
774 }
775
776 static isc_result_t
777 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
778 UNUSED(db);
779 UNUSED(node);
780 UNUSED(now);
781 INSIST(0);
782 ISC_UNREACHABLE();
783 }
784
785 static void
786 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
787 UNUSED(db);
788 UNUSED(node);
789 UNUSED(out);
790 return;
791 }
792
793 static isc_result_t
794 createiterator(dns_db_t *db, unsigned int options, dns_dbiterator_t **iteratorp)
795 {
796 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
797 sdlz_dbiterator_t *sdlziter;
798 isc_result_t result;
799 isc_buffer_t b;
800 char zonestr[DNS_NAME_MAXTEXT + 1];
801
802 REQUIRE(VALID_SDLZDB(sdlz));
803
804 if (sdlz->dlzimp->methods->allnodes == NULL)
805 return (ISC_R_NOTIMPLEMENTED);
806
807 if ((options & DNS_DB_NSEC3ONLY) != 0 ||
808 (options & DNS_DB_NONSEC3) != 0)
809 return (ISC_R_NOTIMPLEMENTED);
810
811 isc_buffer_init(&b, zonestr, sizeof(zonestr));
812 result = dns_name_totext(&sdlz->common.origin, true, &b);
813 if (result != ISC_R_SUCCESS)
814 return (result);
815 isc_buffer_putuint8(&b, 0);
816
817 sdlziter = isc_mem_get(sdlz->common.mctx, sizeof(sdlz_dbiterator_t));
818 if (sdlziter == NULL)
819 return (ISC_R_NOMEMORY);
820
821 sdlziter->common.methods = &dbiterator_methods;
822 sdlziter->common.db = NULL;
823 dns_db_attach(db, &sdlziter->common.db);
824 sdlziter->common.relative_names =
825 ((options & DNS_DB_RELATIVENAMES) != 0);
826 sdlziter->common.magic = DNS_DBITERATOR_MAGIC;
827 ISC_LIST_INIT(sdlziter->nodelist);
828 sdlziter->current = NULL;
829 sdlziter->origin = NULL;
830
831 /* make sure strings are always lowercase */
832 dns_sdlz_tolower(zonestr);
833
834 MAYBE_LOCK(sdlz->dlzimp);
835 result = sdlz->dlzimp->methods->allnodes(zonestr,
836 sdlz->dlzimp->driverarg,
837 sdlz->dbdata, sdlziter);
838 MAYBE_UNLOCK(sdlz->dlzimp);
839 if (result != ISC_R_SUCCESS) {
840 dns_dbiterator_t *iter = &sdlziter->common;
841 dbiterator_destroy(&iter);
842 return (result);
843 }
844
845 if (sdlziter->origin != NULL) {
846 ISC_LIST_UNLINK(sdlziter->nodelist, sdlziter->origin, link);
847 ISC_LIST_PREPEND(sdlziter->nodelist, sdlziter->origin, link);
848 }
849
850 *iteratorp = (dns_dbiterator_t *)sdlziter;
851
852 return (ISC_R_SUCCESS);
853 }
854
855 static isc_result_t
856 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
857 dns_rdatatype_t type, dns_rdatatype_t covers,
858 isc_stdtime_t now, dns_rdataset_t *rdataset,
859 dns_rdataset_t *sigrdataset)
860 {
861 dns_rdatalist_t *list;
862 dns_sdlznode_t *sdlznode = (dns_sdlznode_t *)node;
863
864 REQUIRE(VALID_SDLZNODE(node));
865
866 UNUSED(db);
867 UNUSED(version);
868 UNUSED(covers);
869 UNUSED(now);
870 UNUSED(sigrdataset);
871
872 if (type == dns_rdatatype_sig || type == dns_rdatatype_rrsig)
873 return (ISC_R_NOTIMPLEMENTED);
874
875 list = ISC_LIST_HEAD(sdlznode->lists);
876 while (list != NULL) {
877 if (list->type == type)
878 break;
879 list = ISC_LIST_NEXT(list, link);
880 }
881 if (list == NULL)
882 return (ISC_R_NOTFOUND);
883
884 list_tordataset(list, db, node, rdataset);
885
886 return (ISC_R_SUCCESS);
887 }
888
889 static isc_result_t
890 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
891 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
892 dns_dbnode_t **nodep, dns_name_t *foundname,
893 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
894 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
895 {
896 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
897 dns_dbnode_t *node = NULL;
898 dns_fixedname_t fname;
899 dns_rdataset_t xrdataset;
900 dns_name_t *xname;
901 unsigned int nlabels, olabels;
902 isc_result_t result;
903 unsigned int i;
904
905 REQUIRE(VALID_SDLZDB(sdlz));
906 REQUIRE(nodep == NULL || *nodep == NULL);
907 REQUIRE(version == NULL ||
908 version == (void*)&sdlz->dummy_version ||
909 version == sdlz->future_version);
910
911 UNUSED(sdlz);
912
913 if (!dns_name_issubdomain(name, &db->origin))
914 return (DNS_R_NXDOMAIN);
915
916 olabels = dns_name_countlabels(&db->origin);
917 nlabels = dns_name_countlabels(name);
918
919 xname = dns_fixedname_initname(&fname);
920
921 if (rdataset == NULL) {
922 dns_rdataset_init(&xrdataset);
923 rdataset = &xrdataset;
924 }
925
926 result = DNS_R_NXDOMAIN;
927
928 /*
929 * If we're not walking down searching for zone
930 * cuts, we can cut straight to the chase
931 */
932 if ((options & DNS_DBFIND_NOZONECUT) != 0) {
933 i = nlabels;
934 goto search;
935 }
936
937 for (i = olabels; i <= nlabels; i++) {
938 search:
939 /*
940 * Look up the next label.
941 */
942 dns_name_getlabelsequence(name, nlabels - i, i, xname);
943 result = getnodedata(db, xname, false, options,
944 methods, clientinfo, &node);
945 if (result == ISC_R_NOTFOUND) {
946 result = DNS_R_NXDOMAIN;
947 continue;
948 } else if (result != ISC_R_SUCCESS)
949 break;
950
951 /*
952 * Look for a DNAME at the current label, unless this is
953 * the qname.
954 */
955 if (i < nlabels) {
956 result = findrdataset(db, node, version,
957 dns_rdatatype_dname, 0, now,
958 rdataset, sigrdataset);
959 if (result == ISC_R_SUCCESS) {
960 result = DNS_R_DNAME;
961 break;
962 }
963 }
964
965 /*
966 * Look for an NS at the current label, unless this is the
967 * origin, glue is ok, or there are known to be no zone cuts.
968 */
969 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0 &&
970 (options & DNS_DBFIND_NOZONECUT) == 0)
971 {
972 result = findrdataset(db, node, version,
973 dns_rdatatype_ns, 0, now,
974 rdataset, sigrdataset);
975
976 if (result == ISC_R_SUCCESS &&
977 i == nlabels && type == dns_rdatatype_any)
978 {
979 result = DNS_R_ZONECUT;
980 dns_rdataset_disassociate(rdataset);
981 if (sigrdataset != NULL &&
982 dns_rdataset_isassociated(sigrdataset))
983 dns_rdataset_disassociate(sigrdataset);
984 break;
985 } else if (result == ISC_R_SUCCESS) {
986 result = DNS_R_DELEGATION;
987 break;
988 }
989 }
990
991 /*
992 * If the current name is not the qname, add another label
993 * and try again.
994 */
995 if (i < nlabels) {
996 destroynode(node);
997 node = NULL;
998 continue;
999 }
1000
1001 /*
1002 * If we're looking for ANY, we're done.
1003 */
1004 if (type == dns_rdatatype_any) {
1005 result = ISC_R_SUCCESS;
1006 break;
1007 }
1008
1009 /*
1010 * Look for the qtype.
1011 */
1012 result = findrdataset(db, node, version, type, 0, now,
1013 rdataset, sigrdataset);
1014 if (result == ISC_R_SUCCESS)
1015 break;
1016
1017 /*
1018 * Look for a CNAME
1019 */
1020 if (type != dns_rdatatype_cname) {
1021 result = findrdataset(db, node, version,
1022 dns_rdatatype_cname, 0, now,
1023 rdataset, sigrdataset);
1024 if (result == ISC_R_SUCCESS) {
1025 result = DNS_R_CNAME;
1026 break;
1027 }
1028 }
1029
1030 result = DNS_R_NXRRSET;
1031 break;
1032 }
1033
1034 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset))
1035 dns_rdataset_disassociate(rdataset);
1036
1037 if (foundname != NULL) {
1038 isc_result_t xresult;
1039
1040 xresult = dns_name_copy(xname, foundname, NULL);
1041 if (xresult != ISC_R_SUCCESS) {
1042 if (node != NULL)
1043 destroynode(node);
1044 if (dns_rdataset_isassociated(rdataset))
1045 dns_rdataset_disassociate(rdataset);
1046 return (DNS_R_BADDB);
1047 }
1048 }
1049
1050 if (nodep != NULL)
1051 *nodep = node;
1052 else if (node != NULL)
1053 detachnode(db, &node);
1054
1055 return (result);
1056 }
1057
1058 static isc_result_t
1059 find(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
1060 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
1061 dns_dbnode_t **nodep, dns_name_t *foundname,
1062 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
1063 {
1064 return (findext(db, name, version, type, options, now, nodep,
1065 foundname, NULL, NULL, rdataset, sigrdataset));
1066 }
1067
1068 static isc_result_t
1069 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1070 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp)
1071 {
1072 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *) db;
1073 sdlz_rdatasetiter_t *iterator;
1074
1075 REQUIRE(VALID_SDLZDB(sdlz));
1076
1077 REQUIRE(version == NULL ||
1078 version == (void*)&sdlz->dummy_version ||
1079 version == sdlz->future_version);
1080
1081 UNUSED(version);
1082 UNUSED(now);
1083
1084 iterator = isc_mem_get(db->mctx, sizeof(sdlz_rdatasetiter_t));
1085 if (iterator == NULL)
1086 return (ISC_R_NOMEMORY);
1087
1088 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1089 iterator->common.methods = &rdatasetiter_methods;
1090 iterator->common.db = db;
1091 iterator->common.node = NULL;
1092 attachnode(db, node, &iterator->common.node);
1093 iterator->common.version = version;
1094 iterator->common.now = now;
1095
1096 *iteratorp = (dns_rdatasetiter_t *)iterator;
1097
1098 return (ISC_R_SUCCESS);
1099 }
1100
1101 static isc_result_t
1102 modrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1103 dns_rdataset_t *rdataset, unsigned int options,
1104 dns_sdlzmodrdataset_t mod_function)
1105 {
1106 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)db;
1107 dns_master_style_t *style = NULL;
1108 isc_result_t result;
1109 isc_buffer_t *buffer = NULL;
1110 isc_mem_t *mctx;
1111 dns_sdlznode_t *sdlznode;
1112 char *rdatastr = NULL;
1113 char name[DNS_NAME_MAXTEXT + 1];
1114
1115 REQUIRE(VALID_SDLZDB(sdlz));
1116
1117 if (mod_function == NULL)
1118 return (ISC_R_NOTIMPLEMENTED);
1119
1120 sdlznode = (dns_sdlznode_t *)node;
1121
1122 UNUSED(options);
1123
1124 dns_name_format(sdlznode->name, name, sizeof(name));
1125
1126 mctx = sdlz->common.mctx;
1127
1128 result = isc_buffer_allocate(mctx, &buffer, 1024);
1129 if (result != ISC_R_SUCCESS)
1130 return (result);
1131
1132 result = dns_master_stylecreate(&style, 0, 0, 0, 0, 0, 0, 1,
1133 0xffffffff, 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 bool
1239 issecure(dns_db_t *db) {
1240 UNUSED(db);
1241
1242 return (false);
1243 }
1244
1245 static unsigned int
1246 nodecount(dns_db_t *db) {
1247 UNUSED(db);
1248
1249 return (0);
1250 }
1251
1252 static bool
1253 ispersistent(dns_db_t *db) {
1254 UNUSED(db);
1255 return (true);
1256 }
1257
1258 static void
1259 overmem(dns_db_t *db, bool 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, 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 isc_mutex_init(&sdlzdb->refcnt_lock);
1552
1553 /* set the rest of the database structure attributes */
1554 sdlzdb->dlzimp = imp;
1555 sdlzdb->common.methods = &sdlzdb_methods;
1556 sdlzdb->common.attributes = 0;
1557 sdlzdb->common.rdclass = rdclass;
1558 sdlzdb->common.mctx = NULL;
1559 sdlzdb->dbdata = dbdata;
1560 sdlzdb->references = 1;
1561
1562 /* attach to the memory context */
1563 isc_mem_attach(mctx, &sdlzdb->common.mctx);
1564
1565 /* mark structure as valid */
1566 sdlzdb->common.magic = DNS_DB_MAGIC;
1567 sdlzdb->common.impmagic = SDLZDB_MAGIC;
1568 *dbp = (dns_db_t *) sdlzdb;
1569
1570 return (result);
1571 mem_cleanup:
1572 isc_mem_put(mctx, sdlzdb, sizeof(dns_sdlz_db_t));
1573 return (result);
1574 }
1575
1576 static isc_result_t
1577 dns_sdlzallowzonexfr(void *driverarg, void *dbdata, isc_mem_t *mctx,
1578 dns_rdataclass_t rdclass, const dns_name_t *name,
1579 const isc_sockaddr_t *clientaddr, dns_db_t **dbp)
1580 {
1581 isc_buffer_t b;
1582 isc_buffer_t b2;
1583 char namestr[DNS_NAME_MAXTEXT + 1];
1584 char clientstr[(sizeof "xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")
1585 + 1];
1586 isc_netaddr_t netaddr;
1587 isc_result_t result;
1588 dns_sdlzimplementation_t *imp;
1589
1590 /*
1591 * Perform checks to make sure data is as we expect it to be.
1592 */
1593 REQUIRE(driverarg != NULL);
1594 REQUIRE(name != NULL);
1595 REQUIRE(clientaddr != NULL);
1596 REQUIRE(dbp != NULL && *dbp == NULL);
1597
1598 imp = (dns_sdlzimplementation_t *) driverarg;
1599
1600 /* Convert DNS name to ascii text */
1601 isc_buffer_init(&b, namestr, sizeof(namestr));
1602 result = dns_name_totext(name, true, &b);
1603 if (result != ISC_R_SUCCESS)
1604 return (result);
1605 isc_buffer_putuint8(&b, 0);
1606
1607 /* convert client address to ascii text */
1608 isc_buffer_init(&b2, clientstr, sizeof(clientstr));
1609 isc_netaddr_fromsockaddr(&netaddr, clientaddr);
1610 result = isc_netaddr_totext(&netaddr, &b2);
1611 if (result != ISC_R_SUCCESS)
1612 return (result);
1613 isc_buffer_putuint8(&b2, 0);
1614
1615 /* make sure strings are always lowercase */
1616 dns_sdlz_tolower(namestr);
1617 dns_sdlz_tolower(clientstr);
1618
1619 /* Call SDLZ driver's find zone method */
1620 if (imp->methods->allowzonexfr != NULL) {
1621 MAYBE_LOCK(imp);
1622 result = imp->methods->allowzonexfr(imp->driverarg, dbdata,
1623 namestr, clientstr);
1624 MAYBE_UNLOCK(imp);
1625 /*
1626 * if zone is supported and transfers allowed build a 'bind'
1627 * database driver
1628 */
1629 if (result == ISC_R_SUCCESS)
1630 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata,
1631 name, rdclass, dbp);
1632 return (result);
1633 }
1634
1635 return (ISC_R_NOTIMPLEMENTED);
1636 }
1637
1638 static isc_result_t
1639 dns_sdlzcreate(isc_mem_t *mctx, const char *dlzname, unsigned int argc,
1640 char *argv[], void *driverarg, void **dbdata)
1641 {
1642 dns_sdlzimplementation_t *imp;
1643 isc_result_t result = ISC_R_NOTFOUND;
1644
1645 /* Write debugging message to log */
1646 sdlz_log(ISC_LOG_DEBUG(2), "Loading SDLZ driver.");
1647
1648 /*
1649 * Performs checks to make sure data is as we expect it to be.
1650 */
1651 REQUIRE(driverarg != NULL);
1652 REQUIRE(dlzname != NULL);
1653 REQUIRE(dbdata != NULL);
1654 UNUSED(mctx);
1655
1656 imp = driverarg;
1657
1658 /* If the create method exists, call it. */
1659 if (imp->methods->create != NULL) {
1660 MAYBE_LOCK(imp);
1661 result = imp->methods->create(dlzname, argc, argv,
1662 imp->driverarg, dbdata);
1663 MAYBE_UNLOCK(imp);
1664 }
1665
1666 /* Write debugging message to log */
1667 if (result == ISC_R_SUCCESS) {
1668 sdlz_log(ISC_LOG_DEBUG(2), "SDLZ driver loaded successfully.");
1669 } else {
1670 sdlz_log(ISC_LOG_ERROR, "SDLZ driver failed to load.");
1671 }
1672
1673 return (result);
1674 }
1675
1676 static void
1677 dns_sdlzdestroy(void *driverdata, void **dbdata) {
1678 dns_sdlzimplementation_t *imp;
1679
1680 /* Write debugging message to log */
1681 sdlz_log(ISC_LOG_DEBUG(2), "Unloading SDLZ driver.");
1682
1683 imp = driverdata;
1684
1685 /* If the destroy method exists, call it. */
1686 if (imp->methods->destroy != NULL) {
1687 MAYBE_LOCK(imp);
1688 imp->methods->destroy(imp->driverarg, dbdata);
1689 MAYBE_UNLOCK(imp);
1690 }
1691 }
1692
1693 static isc_result_t
1694 dns_sdlzfindzone(void *driverarg, void *dbdata, isc_mem_t *mctx,
1695 dns_rdataclass_t rdclass, const dns_name_t *name,
1696 dns_clientinfomethods_t *methods,
1697 dns_clientinfo_t *clientinfo,
1698 dns_db_t **dbp)
1699 {
1700 isc_buffer_t b;
1701 char namestr[DNS_NAME_MAXTEXT + 1];
1702 isc_result_t result;
1703 dns_sdlzimplementation_t *imp;
1704
1705 /*
1706 * Perform checks to make sure data is as we expect it to be.
1707 */
1708 REQUIRE(driverarg != NULL);
1709 REQUIRE(name != NULL);
1710 REQUIRE(dbp != NULL && *dbp == NULL);
1711
1712 imp = (dns_sdlzimplementation_t *) driverarg;
1713
1714 /* Convert DNS name to ascii text */
1715 isc_buffer_init(&b, namestr, sizeof(namestr));
1716 result = dns_name_totext(name, true, &b);
1717 if (result != ISC_R_SUCCESS)
1718 return (result);
1719 isc_buffer_putuint8(&b, 0);
1720
1721 /* make sure strings are always lowercase */
1722 dns_sdlz_tolower(namestr);
1723
1724 /* Call SDLZ driver's find zone method */
1725 MAYBE_LOCK(imp);
1726 result = imp->methods->findzone(imp->driverarg, dbdata, namestr,
1727 methods, clientinfo);
1728 MAYBE_UNLOCK(imp);
1729
1730 /*
1731 * if zone is supported build a 'bind' database driver
1732 * structure to return
1733 */
1734 if (result == ISC_R_SUCCESS)
1735 result = dns_sdlzcreateDBP(mctx, driverarg, dbdata, name,
1736 rdclass, dbp);
1737
1738 return (result);
1739 }
1740
1741
1742 static isc_result_t
1743 dns_sdlzconfigure(void *driverarg, void *dbdata,
1744 dns_view_t *view, dns_dlzdb_t *dlzdb)
1745 {
1746 isc_result_t result;
1747 dns_sdlzimplementation_t *imp;
1748
1749 REQUIRE(driverarg != NULL);
1750
1751 imp = (dns_sdlzimplementation_t *) driverarg;
1752
1753 /* Call SDLZ driver's configure method */
1754 if (imp->methods->configure != NULL) {
1755 MAYBE_LOCK(imp);
1756 result = imp->methods->configure(view, dlzdb,
1757 imp->driverarg, dbdata);
1758 MAYBE_UNLOCK(imp);
1759 } else {
1760 result = ISC_R_SUCCESS;
1761 }
1762
1763 return (result);
1764 }
1765
1766 static bool
1767 dns_sdlzssumatch(const dns_name_t *signer, const dns_name_t *name,
1768 const isc_netaddr_t *tcpaddr, dns_rdatatype_t type,
1769 const dst_key_t *key, void *driverarg, void *dbdata)
1770 {
1771 dns_sdlzimplementation_t *imp;
1772 char b_signer[DNS_NAME_FORMATSIZE];
1773 char b_name[DNS_NAME_FORMATSIZE];
1774 char b_addr[ISC_NETADDR_FORMATSIZE];
1775 char b_type[DNS_RDATATYPE_FORMATSIZE];
1776 char b_key[DST_KEY_FORMATSIZE];
1777 isc_buffer_t *tkey_token = NULL;
1778 isc_region_t token_region = { NULL, 0 };
1779 uint32_t token_len = 0;
1780 bool ret;
1781
1782 REQUIRE(driverarg != NULL);
1783
1784 imp = (dns_sdlzimplementation_t *) driverarg;
1785 if (imp->methods->ssumatch == NULL)
1786 return (false);
1787
1788 /*
1789 * Format the request elements. sdlz operates on strings, not
1790 * structures
1791 */
1792 if (signer != NULL)
1793 dns_name_format(signer, b_signer, sizeof(b_signer));
1794 else
1795 b_signer[0] = 0;
1796
1797 dns_name_format(name, b_name, sizeof(b_name));
1798
1799 if (tcpaddr != NULL)
1800 isc_netaddr_format(tcpaddr, b_addr, sizeof(b_addr));
1801 else
1802 b_addr[0] = 0;
1803
1804 dns_rdatatype_format(type, b_type, sizeof(b_type));
1805
1806 if (key != NULL) {
1807 dst_key_format(key, b_key, sizeof(b_key));
1808 tkey_token = dst_key_tkeytoken(key);
1809 } else
1810 b_key[0] = 0;
1811
1812 if (tkey_token != NULL) {
1813 isc_buffer_region(tkey_token, &token_region);
1814 token_len = token_region.length;
1815 }
1816
1817 MAYBE_LOCK(imp);
1818 ret = imp->methods->ssumatch(b_signer, b_name, b_addr, b_type, b_key,
1819 token_len,
1820 token_len != 0 ? token_region.base : NULL,
1821 imp->driverarg, dbdata);
1822 MAYBE_UNLOCK(imp);
1823 return (ret);
1824 }
1825
1826 static dns_dlzmethods_t sdlzmethods = {
1827 dns_sdlzcreate,
1828 dns_sdlzdestroy,
1829 dns_sdlzfindzone,
1830 dns_sdlzallowzonexfr,
1831 dns_sdlzconfigure,
1832 dns_sdlzssumatch
1833 };
1834
1835 /*
1836 * Public functions.
1837 */
1838
1839 isc_result_t
1840 dns_sdlz_putrr(dns_sdlzlookup_t *lookup, const char *type, dns_ttl_t ttl,
1841 const char *data)
1842 {
1843 dns_rdatalist_t *rdatalist;
1844 dns_rdata_t *rdata;
1845 dns_rdatatype_t typeval;
1846 isc_consttextregion_t r;
1847 isc_buffer_t b;
1848 isc_buffer_t *rdatabuf = NULL;
1849 isc_lex_t *lex;
1850 isc_result_t result;
1851 unsigned int size;
1852 isc_mem_t *mctx;
1853 const dns_name_t *origin;
1854
1855 REQUIRE(VALID_SDLZLOOKUP(lookup));
1856 REQUIRE(type != NULL);
1857 REQUIRE(data != NULL);
1858
1859 mctx = lookup->sdlz->common.mctx;
1860
1861 r.base = type;
1862 r.length = strlen(type);
1863 result = dns_rdatatype_fromtext(&typeval, (void *) &r);
1864 if (result != ISC_R_SUCCESS)
1865 return (result);
1866
1867 rdatalist = ISC_LIST_HEAD(lookup->lists);
1868 while (rdatalist != NULL) {
1869 if (rdatalist->type == typeval)
1870 break;
1871 rdatalist = ISC_LIST_NEXT(rdatalist, link);
1872 }
1873
1874 if (rdatalist == NULL) {
1875 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
1876 if (rdatalist == NULL)
1877 return (ISC_R_NOMEMORY);
1878 dns_rdatalist_init(rdatalist);
1879 rdatalist->rdclass = lookup->sdlz->common.rdclass;
1880 rdatalist->type = typeval;
1881 rdatalist->ttl = ttl;
1882 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
1883 } else
1884 if (rdatalist->ttl > ttl) {
1885 /*
1886 * BIND9 doesn't enforce all RRs in an RRset
1887 * having the same TTL, as per RFC 2136,
1888 * section 7.12. If a DLZ backend has
1889 * different TTLs, then the best
1890 * we can do is return the lowest.
1891 */
1892 rdatalist->ttl = ttl;
1893 }
1894
1895 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
1896 if (rdata == NULL)
1897 return (ISC_R_NOMEMORY);
1898 dns_rdata_init(rdata);
1899
1900 if ((lookup->sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1901 origin = &lookup->sdlz->common.origin;
1902 else
1903 origin = dns_rootname;
1904
1905 lex = NULL;
1906 result = isc_lex_create(mctx, 64, &lex);
1907 if (result != ISC_R_SUCCESS)
1908 goto failure;
1909
1910 size = initial_size(data);
1911 do {
1912 isc_buffer_constinit(&b, data, strlen(data));
1913 isc_buffer_add(&b, strlen(data));
1914
1915 result = isc_lex_openbuffer(lex, &b);
1916 if (result != ISC_R_SUCCESS)
1917 goto failure;
1918
1919 rdatabuf = NULL;
1920 result = isc_buffer_allocate(mctx, &rdatabuf, size);
1921 if (result != ISC_R_SUCCESS)
1922 goto failure;
1923
1924 result = dns_rdata_fromtext(rdata, rdatalist->rdclass,
1925 rdatalist->type, lex,
1926 origin, false,
1927 mctx, rdatabuf,
1928 &lookup->callbacks);
1929 if (result != ISC_R_SUCCESS) {
1930 isc_buffer_free(&rdatabuf);
1931 result = DNS_R_SERVFAIL;
1932 }
1933 if (size >= 65535)
1934 break;
1935 size *= 2;
1936 if (size >= 65535)
1937 size = 65535;
1938 } while (result == ISC_R_NOSPACE);
1939
1940 if (result != ISC_R_SUCCESS)
1941 goto failure;
1942
1943 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
1944 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
1945
1946 if (lex != NULL)
1947 isc_lex_destroy(&lex);
1948
1949 return (ISC_R_SUCCESS);
1950
1951 failure:
1952 if (rdatabuf != NULL)
1953 isc_buffer_free(&rdatabuf);
1954 if (lex != NULL)
1955 isc_lex_destroy(&lex);
1956 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
1957
1958 return (result);
1959 }
1960
1961 isc_result_t
1962 dns_sdlz_putnamedrr(dns_sdlzallnodes_t *allnodes, const char *name,
1963 const char *type, dns_ttl_t ttl, const char *data)
1964 {
1965 dns_name_t *newname;
1966 const dns_name_t *origin;
1967 dns_fixedname_t fnewname;
1968 dns_sdlz_db_t *sdlz = (dns_sdlz_db_t *)allnodes->common.db;
1969 dns_sdlznode_t *sdlznode;
1970 isc_mem_t *mctx = sdlz->common.mctx;
1971 isc_buffer_t b;
1972 isc_result_t result;
1973
1974 newname = dns_fixedname_initname(&fnewname);
1975
1976 if ((sdlz->dlzimp->flags & DNS_SDLZFLAG_RELATIVERDATA) != 0)
1977 origin = &sdlz->common.origin;
1978 else
1979 origin = dns_rootname;
1980 isc_buffer_constinit(&b, name, strlen(name));
1981 isc_buffer_add(&b, strlen(name));
1982
1983 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
1984 if (result != ISC_R_SUCCESS)
1985 return (result);
1986
1987 if (allnodes->common.relative_names) {
1988 /* All names are relative to the root */
1989 unsigned int nlabels = dns_name_countlabels(newname);
1990 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
1991 }
1992
1993 sdlznode = ISC_LIST_HEAD(allnodes->nodelist);
1994 if (sdlznode == NULL || !dns_name_equal(sdlznode->name, newname)) {
1995 sdlznode = NULL;
1996 result = createnode(sdlz, &sdlznode);
1997 if (result != ISC_R_SUCCESS)
1998 return (result);
1999 sdlznode->name = isc_mem_get(mctx, sizeof(dns_name_t));
2000 if (sdlznode->name == NULL) {
2001 destroynode(sdlznode);
2002 return (ISC_R_NOMEMORY);
2003 }
2004 dns_name_init(sdlznode->name, NULL);
2005 result = dns_name_dup(newname, mctx, sdlznode->name);
2006 if (result != ISC_R_SUCCESS) {
2007 isc_mem_put(mctx, sdlznode->name, sizeof(dns_name_t));
2008 destroynode(sdlznode);
2009 return (result);
2010 }
2011 ISC_LIST_PREPEND(allnodes->nodelist, sdlznode, link);
2012 if (allnodes->origin == NULL &&
2013 dns_name_equal(newname, &sdlz->common.origin))
2014 allnodes->origin = sdlznode;
2015 }
2016 return (dns_sdlz_putrr(sdlznode, type, ttl, data));
2017
2018 }
2019
2020 isc_result_t
2021 dns_sdlz_putsoa(dns_sdlzlookup_t *lookup, const char *mname, const char *rname,
2022 uint32_t serial)
2023 {
2024 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
2025 int n;
2026
2027 REQUIRE(mname != NULL);
2028 REQUIRE(rname != NULL);
2029
2030 n = snprintf(str, sizeof str, "%s %s %u %u %u %u %u",
2031 mname, rname, serial,
2032 SDLZ_DEFAULT_REFRESH, SDLZ_DEFAULT_RETRY,
2033 SDLZ_DEFAULT_EXPIRE, SDLZ_DEFAULT_MINIMUM);
2034 if (n >= (int)sizeof(str) || n < 0)
2035 return (ISC_R_NOSPACE);
2036 return (dns_sdlz_putrr(lookup, "SOA", SDLZ_DEFAULT_TTL, str));
2037 }
2038
2039 isc_result_t
2040 dns_sdlzregister(const char *drivername, const dns_sdlzmethods_t *methods,
2041 void *driverarg, unsigned int flags, isc_mem_t *mctx,
2042 dns_sdlzimplementation_t **sdlzimp)
2043 {
2044
2045 dns_sdlzimplementation_t *imp;
2046 isc_result_t result;
2047
2048 /*
2049 * Performs checks to make sure data is as we expect it to be.
2050 */
2051 REQUIRE(drivername != NULL);
2052 REQUIRE(methods != NULL);
2053 REQUIRE(methods->findzone != NULL);
2054 REQUIRE(methods->lookup != NULL);
2055 REQUIRE(mctx != NULL);
2056 REQUIRE(sdlzimp != NULL && *sdlzimp == NULL);
2057 REQUIRE((flags & ~(DNS_SDLZFLAG_RELATIVEOWNER |
2058 DNS_SDLZFLAG_RELATIVERDATA |
2059 DNS_SDLZFLAG_THREADSAFE)) == 0);
2060
2061 /* Write debugging message to log */
2062 sdlz_log(ISC_LOG_DEBUG(2), "Registering SDLZ driver '%s'", drivername);
2063
2064 /*
2065 * Allocate memory for a sdlz_implementation object. Error if
2066 * we cannot.
2067 */
2068 imp = isc_mem_get(mctx, sizeof(dns_sdlzimplementation_t));
2069 if (imp == NULL)
2070 return (ISC_R_NOMEMORY);
2071
2072 /* Make sure memory region is set to all 0's */
2073 memset(imp, 0, sizeof(dns_sdlzimplementation_t));
2074
2075 /* Store the data passed into this method */
2076 imp->methods = methods;
2077 imp->driverarg = driverarg;
2078 imp->flags = flags;
2079 imp->mctx = NULL;
2080
2081 /* attach the new sdlz_implementation object to a memory context */
2082 isc_mem_attach(mctx, &imp->mctx);
2083
2084 /*
2085 * initialize the driver lock, error if we cannot
2086 * (used if a driver does not support multiple threads)
2087 */
2088 isc_mutex_init(&imp->driverlock);
2089
2090 imp->dlz_imp = NULL;
2091
2092 /*
2093 * register the DLZ driver. Pass in our "extra" sdlz information as
2094 * a driverarg. (that's why we stored the passed in driver arg in our
2095 * sdlz_implementation structure) Also, store the dlz_implementation
2096 * structure in our sdlz_implementation.
2097 */
2098 result = dns_dlzregister(drivername, &sdlzmethods, imp, mctx,
2099 &imp->dlz_imp);
2100
2101 /* if registration fails, cleanup and get outta here. */
2102 if (result != ISC_R_SUCCESS)
2103 goto cleanup_mutex;
2104
2105 *sdlzimp = imp;
2106
2107 return (ISC_R_SUCCESS);
2108
2109 cleanup_mutex:
2110 /* destroy the driver lock, we don't need it anymore */
2111 isc_mutex_destroy(&imp->driverlock);
2112
2113 /*
2114 * return the memory back to the available memory pool and
2115 * remove it from the memory context.
2116 */
2117 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
2118 isc_mem_detach(&mctx);
2119 return (result);
2120 }
2121
2122 void
2123 dns_sdlzunregister(dns_sdlzimplementation_t **sdlzimp) {
2124 dns_sdlzimplementation_t *imp;
2125 isc_mem_t *mctx;
2126
2127 /* Write debugging message to log */
2128 sdlz_log(ISC_LOG_DEBUG(2), "Unregistering SDLZ driver.");
2129
2130 /*
2131 * Performs checks to make sure data is as we expect it to be.
2132 */
2133 REQUIRE(sdlzimp != NULL && *sdlzimp != NULL);
2134
2135 imp = *sdlzimp;
2136
2137 /* Unregister the DLZ driver implementation */
2138 dns_dlzunregister(&imp->dlz_imp);
2139
2140 /* destroy the driver lock, we don't need it anymore */
2141 isc_mutex_destroy(&imp->driverlock);
2142
2143 mctx = imp->mctx;
2144
2145 /*
2146 * return the memory back to the available memory pool and
2147 * remove it from the memory context.
2148 */
2149 isc_mem_put(mctx, imp, sizeof(dns_sdlzimplementation_t));
2150 isc_mem_detach(&mctx);
2151
2152 *sdlzimp = NULL;
2153 }
2154
2155
2156 isc_result_t
2157 dns_sdlz_setdb(dns_dlzdb_t *dlzdatabase, dns_rdataclass_t rdclass,
2158 const dns_name_t *name, dns_db_t **dbp)
2159 {
2160 isc_result_t result;
2161
2162 result = dns_sdlzcreateDBP(dlzdatabase->mctx,
2163 dlzdatabase->implementation->driverarg,
2164 dlzdatabase->dbdata, name, rdclass, dbp);
2165 return (result);
2166 }
2167