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