1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 /*! \file */
13
14 #include <inttypes.h>
15 #include <stdbool.h>
16 #include <string.h>
17
18 #include <isc/buffer.h>
19 #include <isc/lex.h>
20 #include <isc/log.h>
21 #include <isc/magic.h>
22 #include <isc/mem.h>
23 #include <isc/once.h>
24 #include <isc/print.h>
25 #include <isc/refcount.h>
26 #include <isc/region.h>
27 #include <isc/util.h>
28
29 #include <dns/callbacks.h>
30 #include <dns/db.h>
31 #include <dns/dbiterator.h>
32 #include <dns/fixedname.h>
33 #include <dns/log.h>
34 #include <dns/rdata.h>
35 #include <dns/rdatalist.h>
36 #include <dns/rdataset.h>
37 #include <dns/rdatasetiter.h>
38 #include <dns/rdatatype.h>
39 #include <dns/result.h>
40 #include <dns/sdb.h>
41 #include <dns/types.h>
42
43 #include "rdatalist_p.h"
44
45 struct dns_sdbimplementation {
46 const dns_sdbmethods_t *methods;
47 void *driverdata;
48 unsigned int flags;
49 isc_mem_t *mctx;
50 isc_mutex_t driverlock;
51 dns_dbimplementation_t *dbimp;
52 };
53
54 struct dns_sdb {
55 /* Unlocked */
56 dns_db_t common;
57 char *zone;
58 dns_sdbimplementation_t *implementation;
59 void *dbdata;
60
61 /* Atomic */
62 isc_refcount_t references;
63 };
64
65 struct dns_sdblookup {
66 /* Unlocked */
67 unsigned int magic;
68 dns_sdb_t *sdb;
69 ISC_LIST(dns_rdatalist_t) lists;
70 ISC_LIST(isc_buffer_t) buffers;
71 dns_name_t *name;
72 ISC_LINK(dns_sdblookup_t) link;
73 dns_rdatacallbacks_t callbacks;
74
75 /* Atomic */
76 isc_refcount_t references;
77 };
78
79 typedef struct dns_sdblookup dns_sdbnode_t;
80
81 struct dns_sdballnodes {
82 dns_dbiterator_t common;
83 ISC_LIST(dns_sdbnode_t) nodelist;
84 dns_sdbnode_t *current;
85 dns_sdbnode_t *origin;
86 };
87
88 typedef dns_sdballnodes_t sdb_dbiterator_t;
89
90 typedef struct sdb_rdatasetiter {
91 dns_rdatasetiter_t common;
92 dns_rdatalist_t *current;
93 } sdb_rdatasetiter_t;
94
95 #define SDB_MAGIC ISC_MAGIC('S', 'D', 'B', '-')
96
97 /*%
98 * Note that "impmagic" is not the first four bytes of the struct, so
99 * ISC_MAGIC_VALID cannot be used.
100 */
101 #define VALID_SDB(sdb) ((sdb) != NULL && (sdb)->common.impmagic == SDB_MAGIC)
102
103 #define SDBLOOKUP_MAGIC ISC_MAGIC('S', 'D', 'B', 'L')
104 #define VALID_SDBLOOKUP(sdbl) ISC_MAGIC_VALID(sdbl, SDBLOOKUP_MAGIC)
105 #define VALID_SDBNODE(sdbn) VALID_SDBLOOKUP(sdbn)
106
107 /* These values are taken from RFC1537 */
108 #define SDB_DEFAULT_REFRESH 28800U /* 8 hours */
109 #define SDB_DEFAULT_RETRY 7200U /* 2 hours */
110 #define SDB_DEFAULT_EXPIRE 604800U /* 7 days */
111 #define SDB_DEFAULT_MINIMUM 86400U /* 1 day */
112
113 /* This is a reasonable value */
114 #define SDB_DEFAULT_TTL (60 * 60 * 24)
115
116 #ifdef __COVERITY__
117 #define MAYBE_LOCK(sdb) LOCK(&sdb->implementation->driverlock)
118 #define MAYBE_UNLOCK(sdb) UNLOCK(&sdb->implementation->driverlock)
119 #else /* ifdef __COVERITY__ */
120 #define MAYBE_LOCK(sdb) \
121 do { \
122 unsigned int flags = sdb->implementation->flags; \
123 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
124 LOCK(&sdb->implementation->driverlock); \
125 } while (0)
126
127 #define MAYBE_UNLOCK(sdb) \
128 do { \
129 unsigned int flags = sdb->implementation->flags; \
130 if ((flags & DNS_SDBFLAG_THREADSAFE) == 0) \
131 UNLOCK(&sdb->implementation->driverlock); \
132 } while (0)
133 #endif /* ifdef __COVERITY__ */
134
135 static int dummy;
136
137 static isc_result_t
138 dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
139 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
140 void *driverarg, dns_db_t **dbp);
141
142 static isc_result_t
143 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
144 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
145 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset);
146
147 static isc_result_t
148 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep);
149
150 static void
151 destroynode(dns_sdbnode_t *node);
152
153 static void
154 detachnode(dns_db_t *db, dns_dbnode_t **targetp);
155
156 static void
157 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
158 dns_rdataset_t *rdataset);
159
160 static void
161 dbiterator_destroy(dns_dbiterator_t **iteratorp);
162 static isc_result_t
163 dbiterator_first(dns_dbiterator_t *iterator);
164 static isc_result_t
165 dbiterator_last(dns_dbiterator_t *iterator);
166 static isc_result_t
167 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name);
168 static isc_result_t
169 dbiterator_prev(dns_dbiterator_t *iterator);
170 static isc_result_t
171 dbiterator_next(dns_dbiterator_t *iterator);
172 static isc_result_t
173 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
174 dns_name_t *name);
175 static isc_result_t
176 dbiterator_pause(dns_dbiterator_t *iterator);
177 static isc_result_t
178 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name);
179
180 static dns_dbiteratormethods_t dbiterator_methods = {
181 dbiterator_destroy, dbiterator_first, dbiterator_last,
182 dbiterator_seek, dbiterator_prev, dbiterator_next,
183 dbiterator_current, dbiterator_pause, dbiterator_origin
184 };
185
186 static void
187 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp);
188 static isc_result_t
189 rdatasetiter_first(dns_rdatasetiter_t *iterator);
190 static isc_result_t
191 rdatasetiter_next(dns_rdatasetiter_t *iterator);
192 static void
193 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset);
194
195 static dns_rdatasetitermethods_t rdatasetiter_methods = {
196 rdatasetiter_destroy, rdatasetiter_first, rdatasetiter_next,
197 rdatasetiter_current
198 };
199
200 /*
201 * Functions used by implementors of simple databases
202 */
203 isc_result_t
dns_sdb_register(const char * drivername,const dns_sdbmethods_t * methods,void * driverdata,unsigned int flags,isc_mem_t * mctx,dns_sdbimplementation_t ** sdbimp)204 dns_sdb_register(const char *drivername, const dns_sdbmethods_t *methods,
205 void *driverdata, unsigned int flags, isc_mem_t *mctx,
206 dns_sdbimplementation_t **sdbimp) {
207 dns_sdbimplementation_t *imp;
208 isc_result_t result;
209
210 REQUIRE(drivername != NULL);
211 REQUIRE(methods != NULL);
212 REQUIRE(methods->lookup != NULL || methods->lookup2 != NULL);
213 REQUIRE(mctx != NULL);
214 REQUIRE(sdbimp != NULL && *sdbimp == NULL);
215 REQUIRE((flags &
216 ~(DNS_SDBFLAG_RELATIVEOWNER | DNS_SDBFLAG_RELATIVERDATA |
217 DNS_SDBFLAG_THREADSAFE | DNS_SDBFLAG_DNS64)) == 0);
218
219 imp = isc_mem_get(mctx, sizeof(dns_sdbimplementation_t));
220 imp->methods = methods;
221 imp->driverdata = driverdata;
222 imp->flags = flags;
223 imp->mctx = NULL;
224 isc_mem_attach(mctx, &imp->mctx);
225 isc_mutex_init(&imp->driverlock);
226
227 imp->dbimp = NULL;
228 result = dns_db_register(drivername, dns_sdb_create, imp, mctx,
229 &imp->dbimp);
230 if (result != ISC_R_SUCCESS) {
231 goto cleanup_mutex;
232 }
233 *sdbimp = imp;
234
235 return (ISC_R_SUCCESS);
236
237 cleanup_mutex:
238 isc_mutex_destroy(&imp->driverlock);
239 isc_mem_put(mctx, imp, sizeof(dns_sdbimplementation_t));
240 return (result);
241 }
242
243 void
dns_sdb_unregister(dns_sdbimplementation_t ** sdbimp)244 dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
245 dns_sdbimplementation_t *imp;
246
247 REQUIRE(sdbimp != NULL && *sdbimp != NULL);
248
249 imp = *sdbimp;
250 *sdbimp = NULL;
251 dns_db_unregister(&imp->dbimp);
252 isc_mutex_destroy(&imp->driverlock);
253
254 isc_mem_putanddetach(&imp->mctx, imp, sizeof(dns_sdbimplementation_t));
255 }
256
257 static inline unsigned int
initial_size(unsigned int len)258 initial_size(unsigned int len) {
259 unsigned int size;
260
261 for (size = 1024; size < (64 * 1024); size *= 2) {
262 if (len < size) {
263 return (size);
264 }
265 }
266 return (65535);
267 }
268
269 isc_result_t
dns_sdb_putrdata(dns_sdblookup_t * lookup,dns_rdatatype_t typeval,dns_ttl_t ttl,const unsigned char * rdatap,unsigned int rdlen)270 dns_sdb_putrdata(dns_sdblookup_t *lookup, dns_rdatatype_t typeval,
271 dns_ttl_t ttl, const unsigned char *rdatap,
272 unsigned int rdlen) {
273 dns_rdatalist_t *rdatalist;
274 dns_rdata_t *rdata;
275 isc_buffer_t *rdatabuf = NULL;
276 isc_mem_t *mctx;
277 isc_region_t region;
278
279 mctx = lookup->sdb->common.mctx;
280
281 rdatalist = ISC_LIST_HEAD(lookup->lists);
282 while (rdatalist != NULL) {
283 if (rdatalist->type == typeval) {
284 break;
285 }
286 rdatalist = ISC_LIST_NEXT(rdatalist, link);
287 }
288
289 if (rdatalist == NULL) {
290 rdatalist = isc_mem_get(mctx, sizeof(dns_rdatalist_t));
291 dns_rdatalist_init(rdatalist);
292 rdatalist->rdclass = lookup->sdb->common.rdclass;
293 rdatalist->type = typeval;
294 rdatalist->ttl = ttl;
295 ISC_LIST_APPEND(lookup->lists, rdatalist, link);
296 } else if (rdatalist->ttl != ttl) {
297 return (DNS_R_BADTTL);
298 }
299
300 rdata = isc_mem_get(mctx, sizeof(dns_rdata_t));
301
302 isc_buffer_allocate(mctx, &rdatabuf, rdlen);
303 DE_CONST(rdatap, region.base);
304 region.length = rdlen;
305 isc_buffer_copyregion(rdatabuf, ®ion);
306 isc_buffer_usedregion(rdatabuf, ®ion);
307 dns_rdata_init(rdata);
308 dns_rdata_fromregion(rdata, rdatalist->rdclass, rdatalist->type,
309 ®ion);
310 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
311 ISC_LIST_APPEND(lookup->buffers, rdatabuf, link);
312
313 return (ISC_R_SUCCESS);
314 }
315
316 isc_result_t
dns_sdb_putrr(dns_sdblookup_t * lookup,const char * type,dns_ttl_t ttl,const char * data)317 dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
318 const char *data) {
319 unsigned int datalen;
320 dns_rdatatype_t typeval;
321 isc_textregion_t r;
322 isc_lex_t *lex = NULL;
323 isc_result_t result;
324 unsigned char *p = NULL;
325 unsigned int size = 0; /* Init to suppress compiler warning */
326 isc_mem_t *mctx;
327 dns_sdbimplementation_t *imp;
328 const dns_name_t *origin;
329 isc_buffer_t b;
330 isc_buffer_t rb;
331
332 REQUIRE(VALID_SDBLOOKUP(lookup));
333 REQUIRE(type != NULL);
334 REQUIRE(data != NULL);
335
336 mctx = lookup->sdb->common.mctx;
337
338 DE_CONST(type, r.base);
339 r.length = strlen(type);
340 result = dns_rdatatype_fromtext(&typeval, &r);
341 if (result != ISC_R_SUCCESS) {
342 return (result);
343 }
344
345 imp = lookup->sdb->implementation;
346 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) {
347 origin = &lookup->sdb->common.origin;
348 } else {
349 origin = dns_rootname;
350 }
351
352 result = isc_lex_create(mctx, 64, &lex);
353 if (result != ISC_R_SUCCESS) {
354 goto failure;
355 }
356
357 datalen = strlen(data);
358 size = initial_size(datalen);
359 do {
360 isc_buffer_constinit(&b, data, datalen);
361 isc_buffer_add(&b, datalen);
362 result = isc_lex_openbuffer(lex, &b);
363 if (result != ISC_R_SUCCESS) {
364 goto failure;
365 }
366
367 if (size >= 65535) {
368 size = 65535;
369 }
370 p = isc_mem_get(mctx, size);
371 isc_buffer_init(&rb, p, size);
372 result = dns_rdata_fromtext(NULL, lookup->sdb->common.rdclass,
373 typeval, lex, origin, 0, mctx, &rb,
374 &lookup->callbacks);
375 if (result != ISC_R_NOSPACE) {
376 break;
377 }
378
379 /*
380 * Is the RR too big?
381 */
382 if (size >= 65535) {
383 break;
384 }
385 isc_mem_put(mctx, p, size);
386 p = NULL;
387 size *= 2;
388 } while (result == ISC_R_NOSPACE);
389
390 if (result != ISC_R_SUCCESS) {
391 goto failure;
392 }
393
394 result = dns_sdb_putrdata(lookup, typeval, ttl, isc_buffer_base(&rb),
395 isc_buffer_usedlength(&rb));
396 failure:
397 if (p != NULL) {
398 isc_mem_put(mctx, p, size);
399 }
400 if (lex != NULL) {
401 isc_lex_destroy(&lex);
402 }
403
404 return (result);
405 }
406
407 static isc_result_t
getnode(dns_sdballnodes_t * allnodes,const char * name,dns_sdbnode_t ** nodep)408 getnode(dns_sdballnodes_t *allnodes, const char *name, dns_sdbnode_t **nodep) {
409 dns_name_t *newname;
410 const dns_name_t *origin;
411 dns_fixedname_t fnewname;
412 dns_sdb_t *sdb = (dns_sdb_t *)allnodes->common.db;
413 dns_sdbimplementation_t *imp = sdb->implementation;
414 dns_sdbnode_t *sdbnode;
415 isc_mem_t *mctx = sdb->common.mctx;
416 isc_buffer_t b;
417 isc_result_t result;
418
419 newname = dns_fixedname_initname(&fnewname);
420
421 if ((imp->flags & DNS_SDBFLAG_RELATIVERDATA) != 0) {
422 origin = &sdb->common.origin;
423 } else {
424 origin = dns_rootname;
425 }
426 isc_buffer_constinit(&b, name, strlen(name));
427 isc_buffer_add(&b, strlen(name));
428
429 result = dns_name_fromtext(newname, &b, origin, 0, NULL);
430 if (result != ISC_R_SUCCESS) {
431 return (result);
432 }
433
434 if (allnodes->common.relative_names) {
435 /* All names are relative to the root */
436 unsigned int nlabels = dns_name_countlabels(newname);
437 dns_name_getlabelsequence(newname, 0, nlabels - 1, newname);
438 }
439
440 sdbnode = ISC_LIST_HEAD(allnodes->nodelist);
441 if (sdbnode == NULL || !dns_name_equal(sdbnode->name, newname)) {
442 sdbnode = NULL;
443 result = createnode(sdb, &sdbnode);
444 if (result != ISC_R_SUCCESS) {
445 return (result);
446 }
447 sdbnode->name = isc_mem_get(mctx, sizeof(dns_name_t));
448 dns_name_init(sdbnode->name, NULL);
449 dns_name_dup(newname, mctx, sdbnode->name);
450 ISC_LIST_PREPEND(allnodes->nodelist, sdbnode, link);
451 if (allnodes->origin == NULL &&
452 dns_name_equal(newname, &sdb->common.origin)) {
453 allnodes->origin = sdbnode;
454 }
455 }
456 *nodep = sdbnode;
457 return (ISC_R_SUCCESS);
458 }
459
460 isc_result_t
dns_sdb_putnamedrr(dns_sdballnodes_t * allnodes,const char * name,const char * type,dns_ttl_t ttl,const char * data)461 dns_sdb_putnamedrr(dns_sdballnodes_t *allnodes, const char *name,
462 const char *type, dns_ttl_t ttl, const char *data) {
463 isc_result_t result;
464 dns_sdbnode_t *sdbnode = NULL;
465 result = getnode(allnodes, name, &sdbnode);
466 if (result != ISC_R_SUCCESS) {
467 return (result);
468 }
469 return (dns_sdb_putrr(sdbnode, type, ttl, data));
470 }
471
472 isc_result_t
dns_sdb_putnamedrdata(dns_sdballnodes_t * allnodes,const char * name,dns_rdatatype_t type,dns_ttl_t ttl,const void * rdata,unsigned int rdlen)473 dns_sdb_putnamedrdata(dns_sdballnodes_t *allnodes, const char *name,
474 dns_rdatatype_t type, dns_ttl_t ttl, const void *rdata,
475 unsigned int rdlen) {
476 isc_result_t result;
477 dns_sdbnode_t *sdbnode = NULL;
478 result = getnode(allnodes, name, &sdbnode);
479 if (result != ISC_R_SUCCESS) {
480 return (result);
481 }
482 return (dns_sdb_putrdata(sdbnode, type, ttl, rdata, rdlen));
483 }
484
485 isc_result_t
dns_sdb_putsoa(dns_sdblookup_t * lookup,const char * mname,const char * rname,uint32_t serial)486 dns_sdb_putsoa(dns_sdblookup_t *lookup, const char *mname, const char *rname,
487 uint32_t serial) {
488 char str[2 * DNS_NAME_MAXTEXT + 5 * (sizeof("2147483647")) + 7];
489 int n;
490
491 REQUIRE(mname != NULL);
492 REQUIRE(rname != NULL);
493
494 n = snprintf(str, sizeof(str), "%s %s %u %u %u %u %u", mname, rname,
495 serial, SDB_DEFAULT_REFRESH, SDB_DEFAULT_RETRY,
496 SDB_DEFAULT_EXPIRE, SDB_DEFAULT_MINIMUM);
497 if (n >= (int)sizeof(str) || n < 0) {
498 return (ISC_R_NOSPACE);
499 }
500 return (dns_sdb_putrr(lookup, "SOA", SDB_DEFAULT_TTL, str));
501 }
502
503 /*
504 * DB routines
505 */
506
507 static void
attach(dns_db_t * source,dns_db_t ** targetp)508 attach(dns_db_t *source, dns_db_t **targetp) {
509 dns_sdb_t *sdb = (dns_sdb_t *)source;
510
511 REQUIRE(VALID_SDB(sdb));
512
513 isc_refcount_increment(&sdb->references);
514
515 *targetp = source;
516 }
517
518 static void
destroy(dns_sdb_t * sdb)519 destroy(dns_sdb_t *sdb) {
520 dns_sdbimplementation_t *imp = sdb->implementation;
521
522 isc_refcount_destroy(&sdb->references);
523
524 if (imp->methods->destroy != NULL) {
525 MAYBE_LOCK(sdb);
526 imp->methods->destroy(sdb->zone, imp->driverdata, &sdb->dbdata);
527 MAYBE_UNLOCK(sdb);
528 }
529
530 isc_mem_free(sdb->common.mctx, sdb->zone);
531
532 sdb->common.magic = 0;
533 sdb->common.impmagic = 0;
534
535 dns_name_free(&sdb->common.origin, sdb->common.mctx);
536
537 isc_mem_putanddetach(&sdb->common.mctx, sdb, sizeof(dns_sdb_t));
538 }
539
540 static void
detach(dns_db_t ** dbp)541 detach(dns_db_t **dbp) {
542 dns_sdb_t *sdb = (dns_sdb_t *)(*dbp);
543
544 REQUIRE(VALID_SDB(sdb));
545
546 *dbp = NULL;
547
548 if (isc_refcount_decrement(&sdb->references) == 1) {
549 destroy(sdb);
550 }
551 }
552
553 static isc_result_t
beginload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)554 beginload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
555 UNUSED(db);
556 UNUSED(callbacks);
557 return (ISC_R_NOTIMPLEMENTED);
558 }
559
560 static isc_result_t
endload(dns_db_t * db,dns_rdatacallbacks_t * callbacks)561 endload(dns_db_t *db, dns_rdatacallbacks_t *callbacks) {
562 UNUSED(db);
563 UNUSED(callbacks);
564 return (ISC_R_NOTIMPLEMENTED);
565 }
566
567 static isc_result_t
dump(dns_db_t * db,dns_dbversion_t * version,const char * filename,dns_masterformat_t masterformat)568 dump(dns_db_t *db, dns_dbversion_t *version, const char *filename,
569 dns_masterformat_t masterformat) {
570 UNUSED(db);
571 UNUSED(version);
572 UNUSED(filename);
573 UNUSED(masterformat);
574 return (ISC_R_NOTIMPLEMENTED);
575 }
576
577 static void
currentversion(dns_db_t * db,dns_dbversion_t ** versionp)578 currentversion(dns_db_t *db, dns_dbversion_t **versionp) {
579 REQUIRE(versionp != NULL && *versionp == NULL);
580
581 UNUSED(db);
582
583 *versionp = (void *)&dummy;
584 return;
585 }
586
587 static isc_result_t
newversion(dns_db_t * db,dns_dbversion_t ** versionp)588 newversion(dns_db_t *db, dns_dbversion_t **versionp) {
589 UNUSED(db);
590 UNUSED(versionp);
591
592 return (ISC_R_NOTIMPLEMENTED);
593 }
594
595 static void
attachversion(dns_db_t * db,dns_dbversion_t * source,dns_dbversion_t ** targetp)596 attachversion(dns_db_t *db, dns_dbversion_t *source,
597 dns_dbversion_t **targetp) {
598 REQUIRE(source != NULL && source == (void *)&dummy);
599 REQUIRE(targetp != NULL && *targetp == NULL);
600
601 UNUSED(db);
602 *targetp = source;
603 return;
604 }
605
606 static void
closeversion(dns_db_t * db,dns_dbversion_t ** versionp,bool commit)607 closeversion(dns_db_t *db, dns_dbversion_t **versionp, bool commit) {
608 REQUIRE(versionp != NULL && *versionp == (void *)&dummy);
609 REQUIRE(!commit);
610
611 UNUSED(db);
612 UNUSED(commit);
613
614 *versionp = NULL;
615 }
616
617 static isc_result_t
createnode(dns_sdb_t * sdb,dns_sdbnode_t ** nodep)618 createnode(dns_sdb_t *sdb, dns_sdbnode_t **nodep) {
619 dns_sdbnode_t *node;
620
621 node = isc_mem_get(sdb->common.mctx, sizeof(dns_sdbnode_t));
622
623 node->sdb = NULL;
624 attach((dns_db_t *)sdb, (dns_db_t **)&node->sdb);
625 ISC_LIST_INIT(node->lists);
626 ISC_LIST_INIT(node->buffers);
627 ISC_LINK_INIT(node, link);
628 node->name = NULL;
629 dns_rdatacallbacks_init(&node->callbacks);
630
631 isc_refcount_init(&node->references, 1);
632
633 node->magic = SDBLOOKUP_MAGIC;
634
635 *nodep = node;
636 return (ISC_R_SUCCESS);
637 }
638
639 static void
destroynode(dns_sdbnode_t * node)640 destroynode(dns_sdbnode_t *node) {
641 dns_rdatalist_t *list;
642 dns_rdata_t *rdata;
643 isc_buffer_t *b;
644 dns_sdb_t *sdb;
645 isc_mem_t *mctx;
646
647 sdb = node->sdb;
648 mctx = sdb->common.mctx;
649
650 while (!ISC_LIST_EMPTY(node->lists)) {
651 list = ISC_LIST_HEAD(node->lists);
652 while (!ISC_LIST_EMPTY(list->rdata)) {
653 rdata = ISC_LIST_HEAD(list->rdata);
654 ISC_LIST_UNLINK(list->rdata, rdata, link);
655 isc_mem_put(mctx, rdata, sizeof(dns_rdata_t));
656 }
657 ISC_LIST_UNLINK(node->lists, list, link);
658 isc_mem_put(mctx, list, sizeof(dns_rdatalist_t));
659 }
660
661 while (!ISC_LIST_EMPTY(node->buffers)) {
662 b = ISC_LIST_HEAD(node->buffers);
663 ISC_LIST_UNLINK(node->buffers, b, link);
664 isc_buffer_free(&b);
665 }
666
667 if (node->name != NULL) {
668 dns_name_free(node->name, mctx);
669 isc_mem_put(mctx, node->name, sizeof(dns_name_t));
670 }
671
672 node->magic = 0;
673 isc_mem_put(mctx, node, sizeof(dns_sdbnode_t));
674 detach((dns_db_t **)(void *)&sdb);
675 }
676
677 static isc_result_t
getoriginnode(dns_db_t * db,dns_dbnode_t ** nodep)678 getoriginnode(dns_db_t *db, dns_dbnode_t **nodep) {
679 dns_sdb_t *sdb = (dns_sdb_t *)db;
680 dns_sdbnode_t *node = NULL;
681 isc_result_t result;
682 isc_buffer_t b;
683 char namestr[DNS_NAME_MAXTEXT + 1];
684 dns_sdbimplementation_t *imp;
685 dns_name_t relname;
686 dns_name_t *name;
687
688 REQUIRE(VALID_SDB(sdb));
689 REQUIRE(nodep != NULL && *nodep == NULL);
690
691 imp = sdb->implementation;
692 name = &sdb->common.origin;
693
694 if (imp->methods->lookup2 != NULL) {
695 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
696 dns_name_init(&relname, NULL);
697 name = &relname;
698 }
699 } else {
700 isc_buffer_init(&b, namestr, sizeof(namestr));
701 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
702 dns_name_init(&relname, NULL);
703 result = dns_name_totext(&relname, true, &b);
704 if (result != ISC_R_SUCCESS) {
705 return (result);
706 }
707 } else {
708 result = dns_name_totext(name, true, &b);
709 if (result != ISC_R_SUCCESS) {
710 return (result);
711 }
712 }
713 isc_buffer_putuint8(&b, 0);
714 }
715
716 result = createnode(sdb, &node);
717 if (result != ISC_R_SUCCESS) {
718 return (result);
719 }
720
721 MAYBE_LOCK(sdb);
722 if (imp->methods->lookup2 != NULL) {
723 result = imp->methods->lookup2(&sdb->common.origin, name,
724 sdb->dbdata, node, NULL, NULL);
725 } else {
726 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
727 node, NULL, NULL);
728 }
729 MAYBE_UNLOCK(sdb);
730 if (result != ISC_R_SUCCESS &&
731 !(result == ISC_R_NOTFOUND && imp->methods->authority != NULL))
732 {
733 destroynode(node);
734 return (result);
735 }
736
737 if (imp->methods->authority != NULL) {
738 MAYBE_LOCK(sdb);
739 result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
740 MAYBE_UNLOCK(sdb);
741 if (result != ISC_R_SUCCESS) {
742 destroynode(node);
743 return (result);
744 }
745 }
746
747 *nodep = node;
748 return (ISC_R_SUCCESS);
749 }
750
751 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)752 findnodeext(dns_db_t *db, const dns_name_t *name, bool create,
753 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
754 dns_dbnode_t **nodep) {
755 dns_sdb_t *sdb = (dns_sdb_t *)db;
756 dns_sdbnode_t *node = NULL;
757 isc_result_t result;
758 isc_buffer_t b;
759 char namestr[DNS_NAME_MAXTEXT + 1];
760 bool isorigin;
761 dns_sdbimplementation_t *imp;
762 dns_name_t relname;
763 unsigned int labels;
764
765 REQUIRE(VALID_SDB(sdb));
766 REQUIRE(nodep != NULL && *nodep == NULL);
767
768 UNUSED(name);
769 UNUSED(create);
770
771 imp = sdb->implementation;
772
773 isorigin = dns_name_equal(name, &sdb->common.origin);
774
775 if (imp->methods->lookup2 != NULL) {
776 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
777 labels = dns_name_countlabels(name) -
778 dns_name_countlabels(&db->origin);
779 dns_name_init(&relname, NULL);
780 dns_name_getlabelsequence(name, 0, labels, &relname);
781 name = &relname;
782 }
783 } else {
784 isc_buffer_init(&b, namestr, sizeof(namestr));
785 if ((imp->flags & DNS_SDBFLAG_RELATIVEOWNER) != 0) {
786 labels = dns_name_countlabels(name) -
787 dns_name_countlabels(&db->origin);
788 dns_name_init(&relname, NULL);
789 dns_name_getlabelsequence(name, 0, labels, &relname);
790 result = dns_name_totext(&relname, true, &b);
791 if (result != ISC_R_SUCCESS) {
792 return (result);
793 }
794 } else {
795 result = dns_name_totext(name, true, &b);
796 if (result != ISC_R_SUCCESS) {
797 return (result);
798 }
799 }
800 isc_buffer_putuint8(&b, 0);
801 }
802
803 result = createnode(sdb, &node);
804 if (result != ISC_R_SUCCESS) {
805 return (result);
806 }
807
808 MAYBE_LOCK(sdb);
809 if (imp->methods->lookup2 != NULL) {
810 result = imp->methods->lookup2(&sdb->common.origin, name,
811 sdb->dbdata, node, methods,
812 clientinfo);
813 } else {
814 result = imp->methods->lookup(sdb->zone, namestr, sdb->dbdata,
815 node, methods, clientinfo);
816 }
817 MAYBE_UNLOCK(sdb);
818 if (result != ISC_R_SUCCESS && !(result == ISC_R_NOTFOUND && isorigin &&
819 imp->methods->authority != NULL))
820 {
821 destroynode(node);
822 return (result);
823 }
824
825 if (isorigin && imp->methods->authority != NULL) {
826 MAYBE_LOCK(sdb);
827 result = imp->methods->authority(sdb->zone, sdb->dbdata, node);
828 MAYBE_UNLOCK(sdb);
829 if (result != ISC_R_SUCCESS) {
830 destroynode(node);
831 return (result);
832 }
833 }
834
835 *nodep = node;
836 return (ISC_R_SUCCESS);
837 }
838
839 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)840 findext(dns_db_t *db, const dns_name_t *name, dns_dbversion_t *version,
841 dns_rdatatype_t type, unsigned int options, isc_stdtime_t now,
842 dns_dbnode_t **nodep, dns_name_t *foundname,
843 dns_clientinfomethods_t *methods, dns_clientinfo_t *clientinfo,
844 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
845 dns_sdb_t *sdb = (dns_sdb_t *)db;
846 dns_dbnode_t *node = NULL;
847 dns_fixedname_t fname;
848 dns_rdataset_t xrdataset;
849 dns_name_t *xname;
850 unsigned int nlabels, olabels;
851 isc_result_t result;
852 unsigned int i;
853 unsigned int flags;
854
855 REQUIRE(VALID_SDB(sdb));
856 REQUIRE(nodep == NULL || *nodep == NULL);
857 REQUIRE(version == NULL || version == (void *)&dummy);
858
859 UNUSED(options);
860
861 if (!dns_name_issubdomain(name, &db->origin)) {
862 return (DNS_R_NXDOMAIN);
863 }
864
865 olabels = dns_name_countlabels(&db->origin);
866 nlabels = dns_name_countlabels(name);
867
868 xname = dns_fixedname_initname(&fname);
869
870 if (rdataset == NULL) {
871 dns_rdataset_init(&xrdataset);
872 rdataset = &xrdataset;
873 }
874
875 result = DNS_R_NXDOMAIN;
876 flags = sdb->implementation->flags;
877 i = (flags & DNS_SDBFLAG_DNS64) != 0 ? nlabels : olabels;
878 for (; i <= nlabels; i++) {
879 /*
880 * Look up the next label.
881 */
882 dns_name_getlabelsequence(name, nlabels - i, i, xname);
883 result = findnodeext(db, xname, false, methods, clientinfo,
884 &node);
885 if (result == ISC_R_NOTFOUND) {
886 /*
887 * No data at zone apex?
888 */
889 if (i == olabels) {
890 return (DNS_R_BADDB);
891 }
892 result = DNS_R_NXDOMAIN;
893 continue;
894 }
895 if (result != ISC_R_SUCCESS) {
896 return (result);
897 }
898
899 /*
900 * DNS64 zone's don't have DNAME or NS records.
901 */
902 if ((flags & DNS_SDBFLAG_DNS64) != 0) {
903 goto skip;
904 }
905
906 /*
907 * DNS64 zone's don't have DNAME or NS records.
908 */
909 if ((flags & DNS_SDBFLAG_DNS64) != 0) {
910 goto skip;
911 }
912
913 /*
914 * Look for a DNAME at the current label, unless this is
915 * the qname.
916 */
917 if (i < nlabels) {
918 result = findrdataset(db, node, version,
919 dns_rdatatype_dname, 0, now,
920 rdataset, sigrdataset);
921 if (result == ISC_R_SUCCESS) {
922 result = DNS_R_DNAME;
923 break;
924 }
925 }
926
927 /*
928 * Look for an NS at the current label, unless this is the
929 * origin or glue is ok.
930 */
931 if (i != olabels && (options & DNS_DBFIND_GLUEOK) == 0) {
932 result = findrdataset(db, node, version,
933 dns_rdatatype_ns, 0, now,
934 rdataset, sigrdataset);
935 if (result == ISC_R_SUCCESS) {
936 if (i == nlabels && type == dns_rdatatype_any) {
937 result = DNS_R_ZONECUT;
938 dns_rdataset_disassociate(rdataset);
939 if (sigrdataset != NULL &&
940 dns_rdataset_isassociated(
941 sigrdataset)) {
942 dns_rdataset_disassociate(
943 sigrdataset);
944 }
945 } else {
946 result = DNS_R_DELEGATION;
947 }
948 break;
949 }
950 }
951
952 /*
953 * If the current name is not the qname, add another label
954 * and try again.
955 */
956 if (i < nlabels) {
957 destroynode(node);
958 node = NULL;
959 continue;
960 }
961
962 skip:
963 /*
964 * If we're looking for ANY, we're done.
965 */
966 if (type == dns_rdatatype_any) {
967 result = ISC_R_SUCCESS;
968 break;
969 }
970
971 /*
972 * Look for the qtype.
973 */
974 result = findrdataset(db, node, version, type, 0, now, rdataset,
975 sigrdataset);
976 if (result == ISC_R_SUCCESS) {
977 break;
978 }
979
980 /*
981 * Look for a CNAME
982 */
983 if (type != dns_rdatatype_cname) {
984 result = findrdataset(db, node, version,
985 dns_rdatatype_cname, 0, now,
986 rdataset, sigrdataset);
987 if (result == ISC_R_SUCCESS) {
988 result = DNS_R_CNAME;
989 break;
990 }
991 }
992
993 result = DNS_R_NXRRSET;
994 break;
995 }
996
997 if (rdataset == &xrdataset && dns_rdataset_isassociated(rdataset)) {
998 dns_rdataset_disassociate(rdataset);
999 }
1000
1001 if (foundname != NULL) {
1002 dns_name_copynf(xname, foundname);
1003 }
1004
1005 if (nodep != NULL) {
1006 *nodep = node;
1007 } else if (node != NULL) {
1008 detachnode(db, &node);
1009 }
1010
1011 return (result);
1012 }
1013
1014 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)1015 findzonecut(dns_db_t *db, const dns_name_t *name, unsigned int options,
1016 isc_stdtime_t now, dns_dbnode_t **nodep, dns_name_t *foundname,
1017 dns_name_t *dcname, dns_rdataset_t *rdataset,
1018 dns_rdataset_t *sigrdataset) {
1019 UNUSED(db);
1020 UNUSED(name);
1021 UNUSED(options);
1022 UNUSED(now);
1023 UNUSED(nodep);
1024 UNUSED(foundname);
1025 UNUSED(dcname);
1026 UNUSED(rdataset);
1027 UNUSED(sigrdataset);
1028
1029 return (ISC_R_NOTIMPLEMENTED);
1030 }
1031
1032 static void
attachnode(dns_db_t * db,dns_dbnode_t * source,dns_dbnode_t ** targetp)1033 attachnode(dns_db_t *db, dns_dbnode_t *source, dns_dbnode_t **targetp) {
1034 dns_sdb_t *sdb = (dns_sdb_t *)db;
1035 dns_sdbnode_t *node = (dns_sdbnode_t *)source;
1036
1037 REQUIRE(VALID_SDB(sdb));
1038
1039 UNUSED(sdb);
1040
1041 isc_refcount_increment(&node->references);
1042
1043 *targetp = source;
1044 }
1045
1046 static void
detachnode(dns_db_t * db,dns_dbnode_t ** targetp)1047 detachnode(dns_db_t *db, dns_dbnode_t **targetp) {
1048 dns_sdb_t *sdb = (dns_sdb_t *)db;
1049 dns_sdbnode_t *node;
1050
1051 REQUIRE(VALID_SDB(sdb));
1052 REQUIRE(targetp != NULL && *targetp != NULL);
1053
1054 UNUSED(sdb);
1055
1056 node = (dns_sdbnode_t *)(*targetp);
1057
1058 *targetp = NULL;
1059
1060 if (isc_refcount_decrement(&node->references) == 1) {
1061 destroynode(node);
1062 }
1063 }
1064
1065 static isc_result_t
expirenode(dns_db_t * db,dns_dbnode_t * node,isc_stdtime_t now)1066 expirenode(dns_db_t *db, dns_dbnode_t *node, isc_stdtime_t now) {
1067 UNUSED(db);
1068 UNUSED(node);
1069 UNUSED(now);
1070 INSIST(0);
1071 ISC_UNREACHABLE();
1072 }
1073
1074 static void
printnode(dns_db_t * db,dns_dbnode_t * node,FILE * out)1075 printnode(dns_db_t *db, dns_dbnode_t *node, FILE *out) {
1076 UNUSED(db);
1077 UNUSED(node);
1078 UNUSED(out);
1079 return;
1080 }
1081
1082 static isc_result_t
createiterator(dns_db_t * db,unsigned int options,dns_dbiterator_t ** iteratorp)1083 createiterator(dns_db_t *db, unsigned int options,
1084 dns_dbiterator_t **iteratorp) {
1085 dns_sdb_t *sdb = (dns_sdb_t *)db;
1086 REQUIRE(VALID_SDB(sdb));
1087
1088 sdb_dbiterator_t *sdbiter;
1089 isc_result_t result;
1090 dns_sdbimplementation_t *imp = sdb->implementation;
1091
1092 if (imp->methods->allnodes == NULL) {
1093 return (ISC_R_NOTIMPLEMENTED);
1094 }
1095
1096 if ((options & DNS_DB_NSEC3ONLY) != 0 ||
1097 (options & DNS_DB_NONSEC3) != 0) {
1098 return (ISC_R_NOTIMPLEMENTED);
1099 }
1100
1101 sdbiter = isc_mem_get(sdb->common.mctx, sizeof(sdb_dbiterator_t));
1102
1103 sdbiter->common.methods = &dbiterator_methods;
1104 sdbiter->common.db = NULL;
1105 dns_db_attach(db, &sdbiter->common.db);
1106 sdbiter->common.relative_names = ((options & DNS_DB_RELATIVENAMES) !=
1107 0);
1108 sdbiter->common.magic = DNS_DBITERATOR_MAGIC;
1109 ISC_LIST_INIT(sdbiter->nodelist);
1110 sdbiter->current = NULL;
1111 sdbiter->origin = NULL;
1112
1113 MAYBE_LOCK(sdb);
1114 result = imp->methods->allnodes(sdb->zone, sdb->dbdata, sdbiter);
1115 MAYBE_UNLOCK(sdb);
1116 if (result != ISC_R_SUCCESS) {
1117 dbiterator_destroy((dns_dbiterator_t **)(void *)&sdbiter);
1118 return (result);
1119 }
1120
1121 if (sdbiter->origin != NULL) {
1122 ISC_LIST_UNLINK(sdbiter->nodelist, sdbiter->origin, link);
1123 ISC_LIST_PREPEND(sdbiter->nodelist, sdbiter->origin, link);
1124 }
1125
1126 *iteratorp = (dns_dbiterator_t *)sdbiter;
1127
1128 return (ISC_R_SUCCESS);
1129 }
1130
1131 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)1132 findrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1133 dns_rdatatype_t type, dns_rdatatype_t covers, isc_stdtime_t now,
1134 dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
1135 REQUIRE(VALID_SDBNODE(node));
1136
1137 dns_rdatalist_t *list;
1138 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1139
1140 UNUSED(db);
1141 UNUSED(version);
1142 UNUSED(covers);
1143 UNUSED(now);
1144 UNUSED(sigrdataset);
1145
1146 if (type == dns_rdatatype_rrsig) {
1147 return (ISC_R_NOTIMPLEMENTED);
1148 }
1149
1150 list = ISC_LIST_HEAD(sdbnode->lists);
1151 while (list != NULL) {
1152 if (list->type == type) {
1153 break;
1154 }
1155 list = ISC_LIST_NEXT(list, link);
1156 }
1157 if (list == NULL) {
1158 return (ISC_R_NOTFOUND);
1159 }
1160
1161 list_tordataset(list, db, node, rdataset);
1162
1163 return (ISC_R_SUCCESS);
1164 }
1165
1166 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)1167 allrdatasets(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1168 isc_stdtime_t now, dns_rdatasetiter_t **iteratorp) {
1169 sdb_rdatasetiter_t *iterator;
1170
1171 REQUIRE(version == NULL || version == &dummy);
1172
1173 UNUSED(version);
1174 UNUSED(now);
1175
1176 iterator = isc_mem_get(db->mctx, sizeof(sdb_rdatasetiter_t));
1177
1178 iterator->common.magic = DNS_RDATASETITER_MAGIC;
1179 iterator->common.methods = &rdatasetiter_methods;
1180 iterator->common.db = db;
1181 iterator->common.node = NULL;
1182 attachnode(db, node, &iterator->common.node);
1183 iterator->common.version = version;
1184 iterator->common.now = now;
1185
1186 *iteratorp = (dns_rdatasetiter_t *)iterator;
1187
1188 return (ISC_R_SUCCESS);
1189 }
1190
1191 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)1192 addrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1193 isc_stdtime_t now, dns_rdataset_t *rdataset, unsigned int options,
1194 dns_rdataset_t *addedrdataset) {
1195 UNUSED(db);
1196 UNUSED(node);
1197 UNUSED(version);
1198 UNUSED(now);
1199 UNUSED(rdataset);
1200 UNUSED(options);
1201 UNUSED(addedrdataset);
1202
1203 return (ISC_R_NOTIMPLEMENTED);
1204 }
1205
1206 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)1207 subtractrdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1208 dns_rdataset_t *rdataset, unsigned int options,
1209 dns_rdataset_t *newrdataset) {
1210 UNUSED(db);
1211 UNUSED(node);
1212 UNUSED(version);
1213 UNUSED(rdataset);
1214 UNUSED(options);
1215 UNUSED(newrdataset);
1216
1217 return (ISC_R_NOTIMPLEMENTED);
1218 }
1219
1220 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)1221 deleterdataset(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version,
1222 dns_rdatatype_t type, dns_rdatatype_t covers) {
1223 UNUSED(db);
1224 UNUSED(node);
1225 UNUSED(version);
1226 UNUSED(type);
1227 UNUSED(covers);
1228
1229 return (ISC_R_NOTIMPLEMENTED);
1230 }
1231
1232 static bool
issecure(dns_db_t * db)1233 issecure(dns_db_t *db) {
1234 UNUSED(db);
1235
1236 return (false);
1237 }
1238
1239 static unsigned int
nodecount(dns_db_t * db)1240 nodecount(dns_db_t *db) {
1241 UNUSED(db);
1242
1243 return (0);
1244 }
1245
1246 static bool
ispersistent(dns_db_t * db)1247 ispersistent(dns_db_t *db) {
1248 UNUSED(db);
1249 return (true);
1250 }
1251
1252 static void
overmem(dns_db_t * db,bool over)1253 overmem(dns_db_t *db, bool over) {
1254 UNUSED(db);
1255 UNUSED(over);
1256 }
1257
1258 static void
settask(dns_db_t * db,isc_task_t * task)1259 settask(dns_db_t *db, isc_task_t *task) {
1260 UNUSED(db);
1261 UNUSED(task);
1262 }
1263
1264 static dns_dbmethods_t sdb_methods = {
1265 attach,
1266 detach,
1267 beginload,
1268 endload,
1269 NULL, /* serialize */
1270 dump,
1271 currentversion,
1272 newversion,
1273 attachversion,
1274 closeversion,
1275 NULL, /* findnode */
1276 NULL, /* find */
1277 findzonecut,
1278 attachnode,
1279 detachnode,
1280 expirenode,
1281 printnode,
1282 createiterator,
1283 findrdataset,
1284 allrdatasets,
1285 addrdataset,
1286 subtractrdataset,
1287 deleterdataset,
1288 issecure,
1289 nodecount,
1290 ispersistent,
1291 overmem,
1292 settask,
1293 getoriginnode, /* getoriginnode */
1294 NULL, /* transfernode */
1295 NULL, /* getnsec3parameters */
1296 NULL, /* findnsec3node */
1297 NULL, /* setsigningtime */
1298 NULL, /* getsigningtime */
1299 NULL, /* resigned */
1300 NULL, /* isdnssec */
1301 NULL, /* getrrsetstats */
1302 NULL, /* rpz_attach */
1303 NULL, /* rpz_ready */
1304 findnodeext,
1305 findext,
1306 NULL, /* setcachestats */
1307 NULL, /* hashsize */
1308 NULL, /* nodefullname */
1309 NULL, /* getsize */
1310 NULL, /* setservestalettl */
1311 NULL, /* getservestalettl */
1312 NULL /* setgluecachestats */
1313 };
1314
1315 static isc_result_t
dns_sdb_create(isc_mem_t * mctx,const dns_name_t * origin,dns_dbtype_t type,dns_rdataclass_t rdclass,unsigned int argc,char * argv[],void * driverarg,dns_db_t ** dbp)1316 dns_sdb_create(isc_mem_t *mctx, const dns_name_t *origin, dns_dbtype_t type,
1317 dns_rdataclass_t rdclass, unsigned int argc, char *argv[],
1318 void *driverarg, dns_db_t **dbp) {
1319 dns_sdb_t *sdb;
1320 isc_result_t result;
1321 char zonestr[DNS_NAME_MAXTEXT + 1];
1322 isc_buffer_t b;
1323 dns_sdbimplementation_t *imp;
1324
1325 REQUIRE(driverarg != NULL);
1326
1327 imp = driverarg;
1328
1329 if (type != dns_dbtype_zone) {
1330 return (ISC_R_NOTIMPLEMENTED);
1331 }
1332
1333 sdb = isc_mem_get(mctx, sizeof(dns_sdb_t));
1334 memset(sdb, 0, sizeof(dns_sdb_t));
1335
1336 dns_name_init(&sdb->common.origin, NULL);
1337 sdb->common.attributes = 0;
1338 sdb->common.methods = &sdb_methods;
1339 sdb->common.rdclass = rdclass;
1340 sdb->common.mctx = NULL;
1341 sdb->implementation = imp;
1342
1343 isc_mem_attach(mctx, &sdb->common.mctx);
1344
1345 result = dns_name_dupwithoffsets(origin, mctx, &sdb->common.origin);
1346 if (result != ISC_R_SUCCESS) {
1347 goto cleanup_lock;
1348 }
1349
1350 isc_buffer_init(&b, zonestr, sizeof(zonestr));
1351 result = dns_name_totext(origin, true, &b);
1352 if (result != ISC_R_SUCCESS) {
1353 goto cleanup_origin;
1354 }
1355 isc_buffer_putuint8(&b, 0);
1356
1357 sdb->zone = isc_mem_strdup(mctx, zonestr);
1358
1359 sdb->dbdata = NULL;
1360 if (imp->methods->create != NULL) {
1361 MAYBE_LOCK(sdb);
1362 result = imp->methods->create(sdb->zone, argc, argv,
1363 imp->driverdata, &sdb->dbdata);
1364 MAYBE_UNLOCK(sdb);
1365 if (result != ISC_R_SUCCESS) {
1366 goto cleanup_zonestr;
1367 }
1368 }
1369
1370 isc_refcount_init(&sdb->references, 1);
1371
1372 sdb->common.magic = DNS_DB_MAGIC;
1373 sdb->common.impmagic = SDB_MAGIC;
1374
1375 *dbp = (dns_db_t *)sdb;
1376
1377 return (ISC_R_SUCCESS);
1378
1379 cleanup_zonestr:
1380 isc_mem_free(mctx, sdb->zone);
1381 cleanup_origin:
1382 dns_name_free(&sdb->common.origin, mctx);
1383 cleanup_lock:
1384 isc_mem_putanddetach(&mctx, sdb, sizeof(dns_sdb_t));
1385
1386 return (result);
1387 }
1388
1389 /*
1390 * Rdataset Methods
1391 */
1392
1393 static void
disassociate(dns_rdataset_t * rdataset)1394 disassociate(dns_rdataset_t *rdataset) {
1395 dns_dbnode_t *node = rdataset->private5;
1396 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1397 dns_db_t *db = (dns_db_t *)sdbnode->sdb;
1398
1399 detachnode(db, &node);
1400 isc__rdatalist_disassociate(rdataset);
1401 }
1402
1403 static void
rdataset_clone(dns_rdataset_t * source,dns_rdataset_t * target)1404 rdataset_clone(dns_rdataset_t *source, dns_rdataset_t *target) {
1405 dns_dbnode_t *node = source->private5;
1406 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)node;
1407 dns_db_t *db = (dns_db_t *)sdbnode->sdb;
1408 dns_dbnode_t *tempdb = NULL;
1409
1410 isc__rdatalist_clone(source, target);
1411 attachnode(db, node, &tempdb);
1412 source->private5 = tempdb;
1413 }
1414
1415 static dns_rdatasetmethods_t sdb_rdataset_methods = {
1416 disassociate,
1417 isc__rdatalist_first,
1418 isc__rdatalist_next,
1419 isc__rdatalist_current,
1420 rdataset_clone,
1421 isc__rdatalist_count,
1422 isc__rdatalist_addnoqname,
1423 isc__rdatalist_getnoqname,
1424 NULL, /* addclosest */
1425 NULL, /* getclosest */
1426 NULL, /* settrust */
1427 NULL, /* expire */
1428 NULL, /* clearprefetch */
1429 NULL, /* setownercase */
1430 NULL, /* getownercase */
1431 NULL /* addglue */
1432 };
1433
1434 static void
list_tordataset(dns_rdatalist_t * rdatalist,dns_db_t * db,dns_dbnode_t * node,dns_rdataset_t * rdataset)1435 list_tordataset(dns_rdatalist_t *rdatalist, dns_db_t *db, dns_dbnode_t *node,
1436 dns_rdataset_t *rdataset) {
1437 /*
1438 * The sdb rdataset is an rdatalist with some additions.
1439 * - private1 & private2 are used by the rdatalist.
1440 * - private3 & private 4 are unused.
1441 * - private5 is the node.
1442 */
1443
1444 /* This should never fail. */
1445 RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) ==
1446 ISC_R_SUCCESS);
1447
1448 rdataset->methods = &sdb_rdataset_methods;
1449 dns_db_attachnode(db, node, &rdataset->private5);
1450 }
1451
1452 /*
1453 * Database Iterator Methods
1454 */
1455 static void
dbiterator_destroy(dns_dbiterator_t ** iteratorp)1456 dbiterator_destroy(dns_dbiterator_t **iteratorp) {
1457 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)(*iteratorp);
1458 dns_sdb_t *sdb = (dns_sdb_t *)sdbiter->common.db;
1459
1460 while (!ISC_LIST_EMPTY(sdbiter->nodelist)) {
1461 dns_sdbnode_t *node;
1462 node = ISC_LIST_HEAD(sdbiter->nodelist);
1463 ISC_LIST_UNLINK(sdbiter->nodelist, node, link);
1464 destroynode(node);
1465 }
1466
1467 dns_db_detach(&sdbiter->common.db);
1468 isc_mem_put(sdb->common.mctx, sdbiter, sizeof(sdb_dbiterator_t));
1469
1470 *iteratorp = NULL;
1471 }
1472
1473 static isc_result_t
dbiterator_first(dns_dbiterator_t * iterator)1474 dbiterator_first(dns_dbiterator_t *iterator) {
1475 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1476
1477 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1478 if (sdbiter->current == NULL) {
1479 return (ISC_R_NOMORE);
1480 } else {
1481 return (ISC_R_SUCCESS);
1482 }
1483 }
1484
1485 static isc_result_t
dbiterator_last(dns_dbiterator_t * iterator)1486 dbiterator_last(dns_dbiterator_t *iterator) {
1487 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1488
1489 sdbiter->current = ISC_LIST_TAIL(sdbiter->nodelist);
1490 if (sdbiter->current == NULL) {
1491 return (ISC_R_NOMORE);
1492 } else {
1493 return (ISC_R_SUCCESS);
1494 }
1495 }
1496
1497 static isc_result_t
dbiterator_seek(dns_dbiterator_t * iterator,const dns_name_t * name)1498 dbiterator_seek(dns_dbiterator_t *iterator, const dns_name_t *name) {
1499 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1500
1501 sdbiter->current = ISC_LIST_HEAD(sdbiter->nodelist);
1502 while (sdbiter->current != NULL) {
1503 if (dns_name_equal(sdbiter->current->name, name)) {
1504 return (ISC_R_SUCCESS);
1505 }
1506 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1507 }
1508 return (ISC_R_NOTFOUND);
1509 }
1510
1511 static isc_result_t
dbiterator_prev(dns_dbiterator_t * iterator)1512 dbiterator_prev(dns_dbiterator_t *iterator) {
1513 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1514
1515 sdbiter->current = ISC_LIST_PREV(sdbiter->current, link);
1516 if (sdbiter->current == NULL) {
1517 return (ISC_R_NOMORE);
1518 } else {
1519 return (ISC_R_SUCCESS);
1520 }
1521 }
1522
1523 static isc_result_t
dbiterator_next(dns_dbiterator_t * iterator)1524 dbiterator_next(dns_dbiterator_t *iterator) {
1525 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1526
1527 sdbiter->current = ISC_LIST_NEXT(sdbiter->current, link);
1528 if (sdbiter->current == NULL) {
1529 return (ISC_R_NOMORE);
1530 } else {
1531 return (ISC_R_SUCCESS);
1532 }
1533 }
1534
1535 static isc_result_t
dbiterator_current(dns_dbiterator_t * iterator,dns_dbnode_t ** nodep,dns_name_t * name)1536 dbiterator_current(dns_dbiterator_t *iterator, dns_dbnode_t **nodep,
1537 dns_name_t *name) {
1538 sdb_dbiterator_t *sdbiter = (sdb_dbiterator_t *)iterator;
1539
1540 attachnode(iterator->db, sdbiter->current, nodep);
1541 if (name != NULL) {
1542 dns_name_copynf(sdbiter->current->name, name);
1543 return (ISC_R_SUCCESS);
1544 }
1545 return (ISC_R_SUCCESS);
1546 }
1547
1548 static isc_result_t
dbiterator_pause(dns_dbiterator_t * iterator)1549 dbiterator_pause(dns_dbiterator_t *iterator) {
1550 UNUSED(iterator);
1551 return (ISC_R_SUCCESS);
1552 }
1553
1554 static isc_result_t
dbiterator_origin(dns_dbiterator_t * iterator,dns_name_t * name)1555 dbiterator_origin(dns_dbiterator_t *iterator, dns_name_t *name) {
1556 UNUSED(iterator);
1557 dns_name_copynf(dns_rootname, name);
1558 return (ISC_R_SUCCESS);
1559 }
1560
1561 /*
1562 * Rdataset Iterator Methods
1563 */
1564
1565 static void
rdatasetiter_destroy(dns_rdatasetiter_t ** iteratorp)1566 rdatasetiter_destroy(dns_rdatasetiter_t **iteratorp) {
1567 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)(*iteratorp);
1568 detachnode(sdbiterator->common.db, &sdbiterator->common.node);
1569 isc_mem_put(sdbiterator->common.db->mctx, sdbiterator,
1570 sizeof(sdb_rdatasetiter_t));
1571 *iteratorp = NULL;
1572 }
1573
1574 static isc_result_t
rdatasetiter_first(dns_rdatasetiter_t * iterator)1575 rdatasetiter_first(dns_rdatasetiter_t *iterator) {
1576 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1577 dns_sdbnode_t *sdbnode = (dns_sdbnode_t *)iterator->node;
1578
1579 if (ISC_LIST_EMPTY(sdbnode->lists)) {
1580 return (ISC_R_NOMORE);
1581 }
1582 sdbiterator->current = ISC_LIST_HEAD(sdbnode->lists);
1583 return (ISC_R_SUCCESS);
1584 }
1585
1586 static isc_result_t
rdatasetiter_next(dns_rdatasetiter_t * iterator)1587 rdatasetiter_next(dns_rdatasetiter_t *iterator) {
1588 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1589
1590 sdbiterator->current = ISC_LIST_NEXT(sdbiterator->current, link);
1591 if (sdbiterator->current == NULL) {
1592 return (ISC_R_NOMORE);
1593 } else {
1594 return (ISC_R_SUCCESS);
1595 }
1596 }
1597
1598 static void
rdatasetiter_current(dns_rdatasetiter_t * iterator,dns_rdataset_t * rdataset)1599 rdatasetiter_current(dns_rdatasetiter_t *iterator, dns_rdataset_t *rdataset) {
1600 sdb_rdatasetiter_t *sdbiterator = (sdb_rdatasetiter_t *)iterator;
1601
1602 list_tordataset(sdbiterator->current, iterator->db, iterator->node,
1603 rdataset);
1604 }
1605