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