1 /*
2  * Portions Copyright (C) 2005, 2007, 2009-2013, 2015  Internet Systems Consortium, Inc. ("ISC")
3  * Portions Copyright (C) 1999-2001  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 /*
19  * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
20  *
21  * Permission to use, copy, modify, and distribute this software for any
22  * purpose with or without fee is hereby granted, provided that the
23  * above copyright notice and this permission notice appear in all
24  * copies.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
27  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
29  * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
30  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
31  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
32  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
33  * USE OR PERFORMANCE OF THIS SOFTWARE.
34  *
35  * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
36  * conceived and contributed by Rob Butler.
37  *
38  * Permission to use, copy, modify, and distribute this software for any
39  * purpose with or without fee is hereby granted, provided that the
40  * above copyright notice and this permission notice appear in all
41  * copies.
42  *
43  * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
44  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
45  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
46  * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
47  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
48  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
49  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
50  * USE OR PERFORMANCE OF THIS SOFTWARE.
51  */
52 
53 /* $Id$ */
54 
55 /*! \file */
56 
57 /***
58  *** Imports
59  ***/
60 
61 #include <config.h>
62 
63 #include <dns/fixedname.h>
64 #include <dns/log.h>
65 #include <dns/master.h>
66 #include <dns/dlz.h>
67 #include <dns/ssu.h>
68 #include <dns/zone.h>
69 
70 
71 #include <isc/buffer.h>
72 #include <isc/magic.h>
73 #include <isc/mem.h>
74 #include <isc/once.h>
75 #include <isc/rwlock.h>
76 #include <isc/string.h>
77 #include <isc/util.h>
78 
79 /***
80  *** Supported DLZ DB Implementations Registry
81  ***/
82 
83 static ISC_LIST(dns_dlzimplementation_t) dlz_implementations;
84 static isc_rwlock_t dlz_implock;
85 static isc_once_t once = ISC_ONCE_INIT;
86 
87 static void
dlz_initialize(void)88 dlz_initialize(void) {
89 	RUNTIME_CHECK(isc_rwlock_init(&dlz_implock, 0, 0) == ISC_R_SUCCESS);
90 	ISC_LIST_INIT(dlz_implementations);
91 }
92 
93 /*%
94  * Searches the dlz_implementations list for a driver matching name.
95  */
96 static inline dns_dlzimplementation_t *
dlz_impfind(const char * name)97 dlz_impfind(const char *name) {
98 	dns_dlzimplementation_t *imp;
99 
100 	for (imp = ISC_LIST_HEAD(dlz_implementations);
101 	     imp != NULL;
102 	     imp = ISC_LIST_NEXT(imp, link))
103 		if (strcasecmp(name, imp->name) == 0)
104 			return (imp);
105 	return (NULL);
106 }
107 
108 /***
109  *** Basic DLZ Methods
110  ***/
111 
112 isc_result_t
dns_dlzallowzonexfr(dns_view_t * view,dns_name_t * name,isc_sockaddr_t * clientaddr,dns_db_t ** dbp)113 dns_dlzallowzonexfr(dns_view_t *view, dns_name_t *name,
114 		    isc_sockaddr_t *clientaddr, dns_db_t **dbp)
115 {
116 	isc_result_t result;
117 	dns_dlzallowzonexfr_t allowzonexfr;
118 	dns_dlzdb_t *dlzdatabase;
119 
120 	/*
121 	 * Performs checks to make sure data is as we expect it to be.
122 	 */
123 	REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
124 	REQUIRE(name != NULL);
125 	REQUIRE(dbp != NULL && *dbp == NULL);
126 
127 	/* ask driver if the zone is supported */
128 	dlzdatabase = view->dlzdatabase;
129 	allowzonexfr = dlzdatabase->implementation->methods->allowzonexfr;
130 	result = (*allowzonexfr)(dlzdatabase->implementation->driverarg,
131 				 dlzdatabase->dbdata, dlzdatabase->mctx,
132 				 view->rdclass, name, clientaddr, dbp);
133 
134 	if (result == ISC_R_NOTIMPLEMENTED)
135 		return (ISC_R_NOTFOUND);
136 	return (result);
137 }
138 
139 isc_result_t
dns_dlzcreate(isc_mem_t * mctx,const char * dlzname,const char * drivername,unsigned int argc,char * argv[],dns_dlzdb_t ** dbp)140 dns_dlzcreate(isc_mem_t *mctx, const char *dlzname, const char *drivername,
141 	      unsigned int argc, char *argv[], dns_dlzdb_t **dbp)
142 {
143 	dns_dlzimplementation_t *impinfo;
144 	isc_result_t result;
145 	dns_dlzdb_t *db = NULL;
146 
147 	/*
148 	 * initialize the dlz_implementations list, this is guaranteed
149 	 * to only really happen once.
150 	 */
151 	RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
152 
153 	/*
154 	 * Performs checks to make sure data is as we expect it to be.
155 	 */
156 	REQUIRE(dbp != NULL && *dbp == NULL);
157 	REQUIRE(dlzname != NULL);
158 	REQUIRE(drivername != NULL);
159 	REQUIRE(mctx != NULL);
160 
161 	/* write log message */
162 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
163 		      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
164 		      "Loading '%s' using driver %s", dlzname, drivername);
165 
166 	/* lock the dlz_implementations list so we can search it. */
167 	RWLOCK(&dlz_implock, isc_rwlocktype_read);
168 
169 	/* search for the driver implementation	 */
170 	impinfo = dlz_impfind(drivername);
171 	if (impinfo == NULL) {
172 		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
173 
174 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
175 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
176 			      "unsupported DLZ database driver '%s'."
177 			      "  %s not loaded.",
178 			      drivername, dlzname);
179 
180 		return (ISC_R_NOTFOUND);
181 	}
182 
183 	/* Allocate memory to hold the DLZ database driver */
184 	db = isc_mem_get(mctx, sizeof(dns_dlzdb_t));
185 	if (db == NULL) {
186 		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
187 		return (ISC_R_NOMEMORY);
188 	}
189 
190 	/* Make sure memory region is set to all 0's */
191 	memset(db, 0, sizeof(dns_dlzdb_t));
192 
193 	db->implementation = impinfo;
194 
195 	/* Create a new database using implementation 'drivername'. */
196 	result = ((impinfo->methods->create)(mctx, dlzname, argc, argv,
197 					     impinfo->driverarg,
198 					     &db->dbdata));
199 
200 	/* mark the DLZ driver as valid */
201 	if (result == ISC_R_SUCCESS) {
202 		RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
203 		db->magic = DNS_DLZ_MAGIC;
204 		isc_mem_attach(mctx, &db->mctx);
205 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
206 			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
207 			      "DLZ driver loaded successfully.");
208 		*dbp = db;
209 		return (ISC_R_SUCCESS);
210 	} else {
211 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
212 			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
213 			      "DLZ driver failed to load.");
214 	}
215 
216 	/* impinfo->methods->create failed. */
217 	RWUNLOCK(&dlz_implock, isc_rwlocktype_read);
218 	isc_mem_put(mctx, db, sizeof(dns_dlzdb_t));
219 	return (result);
220 }
221 
222 void
dns_dlzdestroy(dns_dlzdb_t ** dbp)223 dns_dlzdestroy(dns_dlzdb_t **dbp) {
224 	dns_dlzdestroy_t destroy;
225 	dns_dlzdb_t *db;
226 
227 	/* Write debugging message to log */
228 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
229 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
230 		      "Unloading DLZ driver.");
231 
232 	/*
233 	 * Perform checks to make sure data is as we expect it to be.
234 	 */
235 	REQUIRE(dbp != NULL && DNS_DLZ_VALID(*dbp));
236 
237 	db = *dbp;
238 	*dbp = NULL;
239 
240 #ifdef BIND9
241 	if (db->ssutable != NULL)
242 		dns_ssutable_detach(&db->ssutable);
243 #endif
244 
245 	/* call the drivers destroy method */
246 	destroy = db->implementation->methods->destroy;
247 	(*destroy)(db->implementation->driverarg, db->dbdata);
248 	/* return memory and detach */
249 	isc_mem_putanddetach(&db->mctx, db, sizeof(dns_dlzdb_t));
250 }
251 
252 
253 isc_result_t
dns_dlzfindzone(dns_view_t * view,dns_name_t * name,unsigned int minlabels,dns_db_t ** dbp)254 dns_dlzfindzone(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
255 		dns_db_t **dbp)
256 {
257 	dns_fixedname_t fname;
258 	dns_name_t *zonename;
259 	unsigned int namelabels;
260 	unsigned int i;
261 	isc_result_t result;
262 	dns_dlzfindzone_t findzone;
263 	dns_dlzdb_t *dlzdatabase;
264 
265 	/*
266 	 * Performs checks to make sure data is as we expect it to be.
267 	 */
268 	REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
269 	REQUIRE(name != NULL);
270 	REQUIRE(dbp != NULL && *dbp == NULL);
271 
272 	/* setup a "fixed" dns name */
273 	dns_fixedname_init(&fname);
274 	zonename = dns_fixedname_name(&fname);
275 
276 	/* count the number of labels in the name */
277 	namelabels = dns_name_countlabels(name);
278 
279 	/*
280 	 * loop through starting with the longest domain name and
281 	 * trying shorter names portions of the name until we find a
282 	 * match, have an error, or are below the 'minlabels'
283 	 * threshold.  minlabels is 0, if the standard database didn't
284 	 * have a zone name match.  Otherwise minlabels is the number
285 	 * of labels in that name.  We need to beat that for a
286 	 * "better" match for the DLZ database to be authoritative
287 	 * instead of the standard database.
288 	 */
289 	for (i = namelabels; i > minlabels && i > 1; i--) {
290 		if (i == namelabels) {
291 			result = dns_name_copy(name, zonename, NULL);
292 			if (result != ISC_R_SUCCESS)
293 				return (result);
294 		} else
295 			dns_name_split(name, i, NULL, zonename);
296 
297 		/* ask SDLZ driver if the zone is supported */
298 		dlzdatabase = view->dlzdatabase;
299 		findzone = dlzdatabase->implementation->methods->findzone;
300 		result = (*findzone)(dlzdatabase->implementation->driverarg,
301 				     dlzdatabase->dbdata, dlzdatabase->mctx,
302 				     view->rdclass, zonename, dbp);
303 		if (result != ISC_R_NOTFOUND)
304 			return (result);
305 	}
306 	return (ISC_R_NOTFOUND);
307 }
308 
309 /*%
310  * Registers a DLZ driver.  This basically just adds the dlz
311  * driver to the list of available drivers in the dlz_implementations list.
312  */
313 isc_result_t
dns_dlzregister(const char * drivername,const dns_dlzmethods_t * methods,void * driverarg,isc_mem_t * mctx,dns_dlzimplementation_t ** dlzimp)314 dns_dlzregister(const char *drivername, const dns_dlzmethods_t *methods,
315 		void *driverarg, isc_mem_t *mctx,
316 		dns_dlzimplementation_t **dlzimp)
317 {
318 
319 	dns_dlzimplementation_t *dlz_imp;
320 
321 	/* Write debugging message to log */
322 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
323 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
324 		      "Registering DLZ driver '%s'", drivername);
325 
326 	/*
327 	 * Performs checks to make sure data is as we expect it to be.
328 	 */
329 	REQUIRE(drivername != NULL);
330 	REQUIRE(methods != NULL);
331 	REQUIRE(methods->create != NULL);
332 	REQUIRE(methods->destroy != NULL);
333 	REQUIRE(methods->findzone != NULL);
334 	REQUIRE(mctx != NULL);
335 	REQUIRE(dlzimp != NULL && *dlzimp == NULL);
336 
337 	/*
338 	 * initialize the dlz_implementations list, this is guaranteed
339 	 * to only really happen once.
340 	 */
341 	RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
342 
343 	/* lock the dlz_implementations list so we can modify it. */
344 	RWLOCK(&dlz_implock, isc_rwlocktype_write);
345 
346 	/*
347 	 * check that another already registered driver isn't using
348 	 * the same name
349 	 */
350 	dlz_imp = dlz_impfind(drivername);
351 	if (dlz_imp != NULL) {
352 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
353 			      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
354 			      "DLZ Driver '%s' already registered",
355 			      drivername);
356 		RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
357 		return (ISC_R_EXISTS);
358 	}
359 
360 	/*
361 	 * Allocate memory for a dlz_implementation object.  Error if
362 	 * we cannot.
363 	 */
364 	dlz_imp = isc_mem_get(mctx, sizeof(dns_dlzimplementation_t));
365 	if (dlz_imp == NULL) {
366 		RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
367 		return (ISC_R_NOMEMORY);
368 	}
369 
370 	/* Make sure memory region is set to all 0's */
371 	memset(dlz_imp, 0, sizeof(dns_dlzimplementation_t));
372 
373 	/* Store the data passed into this method */
374 	dlz_imp->name = drivername;
375 	dlz_imp->methods = methods;
376 	dlz_imp->mctx = NULL;
377 	dlz_imp->driverarg = driverarg;
378 
379 	/* attach the new dlz_implementation object to a memory context */
380 	isc_mem_attach(mctx, &dlz_imp->mctx);
381 
382 	/*
383 	 * prepare the dlz_implementation object to be put in a list,
384 	 * and append it to the list
385 	 */
386 	ISC_LINK_INIT(dlz_imp, link);
387 	ISC_LIST_APPEND(dlz_implementations, dlz_imp, link);
388 
389 	/* Unlock the dlz_implementations list.	 */
390 	RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
391 
392 	/* Pass back the dlz_implementation that we created. */
393 	*dlzimp = dlz_imp;
394 
395 	return (ISC_R_SUCCESS);
396 }
397 
398 /*%
399  * Helper function for dns_dlzstrtoargv().
400  * Pardon the gratuitous recursion.
401  */
402 static isc_result_t
dns_dlzstrtoargvsub(isc_mem_t * mctx,char * s,unsigned int * argcp,char *** argvp,unsigned int n)403 dns_dlzstrtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
404 		    char ***argvp, unsigned int n)
405 {
406 	isc_result_t result;
407 
408  restart:
409 	/* Discard leading whitespace. */
410 	while (*s == ' ' || *s == '\t')
411 		s++;
412 
413 	if (*s == '\0') {
414 		/* We have reached the end of the string. */
415 		*argcp = n;
416 		*argvp = isc_mem_get(mctx, n * sizeof(char *));
417 		if (*argvp == NULL)
418 			return (ISC_R_NOMEMORY);
419 	} else {
420 		char *p = s;
421 		while (*p != ' ' && *p != '\t' && *p != '\0' && *p != '{') {
422 			if (*p == '\n') {
423 				*p = ' ';
424 				goto restart;
425 			}
426 			p++;
427 		}
428 
429 		/* do "grouping", items between { and } are one arg */
430 		if (*p == '{') {
431 			char *t = p;
432 			/*
433 			 * shift all characters to left by 1 to get rid of '{'
434 			 */
435 			while (*t != '\0') {
436 				t++;
437 				*(t-1) = *t;
438 			}
439 			while (*p != '\0' && *p != '}') {
440 				p++;
441 			}
442 			/* get rid of '}' character */
443 			if (*p == '}') {
444 				*p = '\0';
445 				p++;
446 			}
447 			/* normal case, no "grouping" */
448 		} else if (*p != '\0')
449 			*p++ = '\0';
450 
451 		result = dns_dlzstrtoargvsub(mctx, p, argcp, argvp, n + 1);
452 		if (result != ISC_R_SUCCESS)
453 			return (result);
454 		(*argvp)[n] = s;
455 	}
456 	return (ISC_R_SUCCESS);
457 }
458 
459 /*%
460  * Tokenize the string "s" into whitespace-separated words,
461  * return the number of words in '*argcp' and an array
462  * of pointers to the words in '*argvp'.  The caller
463  * must free the array using isc_mem_put().  The string
464  * is modified in-place.
465  */
466 isc_result_t
dns_dlzstrtoargv(isc_mem_t * mctx,char * s,unsigned int * argcp,char *** argvp)467 dns_dlzstrtoargv(isc_mem_t *mctx, char *s,
468 		 unsigned int *argcp, char ***argvp)
469 {
470 	return(dns_dlzstrtoargvsub(mctx, s, argcp, argvp, 0));
471 }
472 
473 /*%
474  * Unregisters a DLZ driver.  This basically just removes the dlz
475  * driver from the list of available drivers in the dlz_implementations list.
476  */
477 void
dns_dlzunregister(dns_dlzimplementation_t ** dlzimp)478 dns_dlzunregister(dns_dlzimplementation_t **dlzimp) {
479 	dns_dlzimplementation_t *dlz_imp;
480 	isc_mem_t *mctx;
481 
482 	/* Write debugging message to log */
483 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
484 		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
485 		      "Unregistering DLZ driver.");
486 
487 	/*
488 	 * Performs checks to make sure data is as we expect it to be.
489 	 */
490 	REQUIRE(dlzimp != NULL && *dlzimp != NULL);
491 
492 	/*
493 	 * initialize the dlz_implementations list, this is guaranteed
494 	 * to only really happen once.
495 	 */
496 	RUNTIME_CHECK(isc_once_do(&once, dlz_initialize) == ISC_R_SUCCESS);
497 
498 	dlz_imp = *dlzimp;
499 
500 	/* lock the dlz_implementations list so we can modify it. */
501 	RWLOCK(&dlz_implock, isc_rwlocktype_write);
502 
503 	/* remove the dlz_implementation object from the list */
504 	ISC_LIST_UNLINK(dlz_implementations, dlz_imp, link);
505 	mctx = dlz_imp->mctx;
506 
507 	/*
508 	 * Return the memory back to the available memory pool and
509 	 * remove it from the memory context.
510 	 */
511 	isc_mem_put(mctx, dlz_imp, sizeof(dns_dlzimplementation_t));
512 	isc_mem_detach(&mctx);
513 
514 	/* Unlock the dlz_implementations list. */
515 	RWUNLOCK(&dlz_implock, isc_rwlocktype_write);
516 }
517 
518 #ifdef BIND9
519 /*
520  * Create a writeable DLZ zone. This can be called by DLZ drivers
521  * during configure() to create a zone that can be updated. The zone
522  * type is set to dns_zone_dlz, which is equivalent to a master zone
523  *
524  * This function uses a callback setup in dns_dlzconfigure() to call
525  * into the server zone code to setup the remaining pieces of server
526  * specific functionality on the zone
527  */
528 isc_result_t
dns_dlz_writeablezone(dns_view_t * view,const char * zone_name)529 dns_dlz_writeablezone(dns_view_t *view, const char *zone_name) {
530 	dns_zone_t *zone = NULL;
531 	dns_zone_t *dupzone = NULL;
532 	isc_result_t result;
533 	isc_buffer_t buffer;
534 	dns_fixedname_t fixorigin;
535 	dns_name_t *origin;
536 	dns_dlzdb_t *dlzdatabase;
537 
538 	REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
539 
540 	dlzdatabase = view->dlzdatabase;
541 
542 	REQUIRE(dlzdatabase->configure_callback != NULL);
543 
544 	isc_buffer_constinit(&buffer, zone_name, strlen(zone_name));
545 	isc_buffer_add(&buffer, strlen(zone_name));
546 	dns_fixedname_init(&fixorigin);
547 	result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
548 				   &buffer, dns_rootname, 0, NULL);
549 	if (result != ISC_R_SUCCESS)
550 		goto cleanup;
551 	origin = dns_fixedname_name(&fixorigin);
552 
553 	/* See if the zone already exists */
554 	result = dns_view_findzone(view, origin, &dupzone);
555 	if (result == ISC_R_SUCCESS) {
556 		dns_zone_detach(&dupzone);
557 		result = ISC_R_EXISTS;
558 		goto cleanup;
559 	}
560 	INSIST(dupzone == NULL);
561 
562 	/* Create it */
563 	result = dns_zone_create(&zone, view->mctx);
564 	if (result != ISC_R_SUCCESS)
565 		goto cleanup;
566 	result = dns_zone_setorigin(zone, origin);
567 	if (result != ISC_R_SUCCESS)
568 		goto cleanup;
569 	dns_zone_setview(zone, view);
570 
571 	dns_zone_setadded(zone, ISC_TRUE);
572 
573 	if (dlzdatabase->ssutable == NULL) {
574 		result = dns_ssutable_createdlz(dlzdatabase->mctx,
575 						&dlzdatabase->ssutable,
576 						view->dlzdatabase);
577 		if (result != ISC_R_SUCCESS)
578 			goto cleanup;
579 	}
580 	dns_zone_setssutable(zone, dlzdatabase->ssutable);
581 
582 	result = dlzdatabase->configure_callback(view, zone);
583 	if (result != ISC_R_SUCCESS)
584 		goto cleanup;
585 
586 	/*
587 	 * Add the zone to its view in the new view list.
588 	 */
589 	result = dns_view_addzone(view, zone);
590 
591  cleanup:
592 	if (zone != NULL)
593 		dns_zone_detach(&zone);
594 
595 	return (result);
596 }
597 #endif
598 
599 /*%
600  * Configure a DLZ driver. This is optional, and if supplied gives
601  * the backend an opportunity to configure parameters related to DLZ.
602  */
603 isc_result_t
dns_dlzconfigure(dns_view_t * view,isc_result_t (* callback)(dns_view_t *,dns_zone_t *))604 dns_dlzconfigure(dns_view_t *view, isc_result_t (*callback)(dns_view_t *,
605 		 dns_zone_t *))
606 {
607 	dns_dlzimplementation_t *impl;
608 	dns_dlzdb_t *dlzdatabase;
609 	isc_result_t result;
610 
611 	REQUIRE(view != NULL);
612 	REQUIRE(DNS_DLZ_VALID(view->dlzdatabase));
613 	REQUIRE(view->dlzdatabase->implementation != NULL);
614 
615 	dlzdatabase = view->dlzdatabase;
616 	impl = dlzdatabase->implementation;
617 
618 	if (impl->methods->configure == NULL)
619 		return (ISC_R_SUCCESS);
620 
621 	dlzdatabase->configure_callback = callback;
622 
623 	result = impl->methods->configure(impl->driverarg,
624 					  dlzdatabase->dbdata, view);
625 	return (result);
626 }
627 
628 isc_boolean_t
dns_dlz_ssumatch(dns_dlzdb_t * dlzdatabase,dns_name_t * signer,dns_name_t * name,isc_netaddr_t * tcpaddr,dns_rdatatype_t type,const dst_key_t * key)629 dns_dlz_ssumatch(dns_dlzdb_t *dlzdatabase,
630 		  dns_name_t *signer, dns_name_t *name, isc_netaddr_t *tcpaddr,
631 		  dns_rdatatype_t type, const dst_key_t *key)
632 {
633 	dns_dlzimplementation_t *impl;
634 	isc_boolean_t r;
635 
636 	REQUIRE(dlzdatabase != NULL);
637 	REQUIRE(dlzdatabase->implementation != NULL);
638 	REQUIRE(dlzdatabase->implementation->methods != NULL);
639 	impl = dlzdatabase->implementation;
640 
641 	if (impl->methods->ssumatch == NULL) {
642 		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
643 			      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
644 			      "No ssumatch method for DLZ database");
645 		return (ISC_FALSE);
646 	}
647 
648 	r = impl->methods->ssumatch(signer, name, tcpaddr, type, key,
649 				    impl->driverarg, dlzdatabase->dbdata);
650 	return (r);
651 }
652