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