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