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