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