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