xref: /minix/external/bsd/bind/dist/bin/named/zoneconf.c (revision 00b67f09)
1 /*	$NetBSD: zoneconf.c,v 1.8 2015/07/08 17:28:55 christos Exp $	*/
2 
3 /*
4  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
5  * Copyright (C) 1999-2003  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /* Id */
21 
22 /*% */
23 
24 #include <config.h>
25 
26 #include <isc/buffer.h>
27 #include <isc/file.h>
28 #include <isc/mem.h>
29 #include <isc/print.h>
30 #include <isc/stats.h>
31 #include <isc/string.h>		/* Required for HP/UX (and others?) */
32 #include <isc/util.h>
33 
34 #include <dns/acl.h>
35 #include <dns/db.h>
36 #include <dns/fixedname.h>
37 #include <dns/log.h>
38 #include <dns/name.h>
39 #include <dns/rdata.h>
40 #include <dns/rdatatype.h>
41 #include <dns/rdataset.h>
42 #include <dns/rdatalist.h>
43 #include <dns/result.h>
44 #include <dns/sdlz.h>
45 #include <dns/ssu.h>
46 #include <dns/stats.h>
47 #include <dns/view.h>
48 #include <dns/zone.h>
49 
50 #include <named/client.h>
51 #include <named/config.h>
52 #include <named/globals.h>
53 #include <named/log.h>
54 #include <named/server.h>
55 #include <named/zoneconf.h>
56 
57 /* ACLs associated with zone */
58 typedef enum {
59 	allow_notify,
60 	allow_query,
61 	allow_query_on,
62 	allow_transfer,
63 	allow_update,
64 	allow_update_forwarding
65 } acl_type_t;
66 
67 #define RETERR(x) do { \
68 	isc_result_t _r = (x); \
69 	if (_r != ISC_R_SUCCESS) \
70 		return (_r); \
71 	} while (/*CONSTCOND*/0)
72 
73 #define CHECK(x) do { \
74 	result = (x); \
75 	if (result != ISC_R_SUCCESS) \
76 		goto cleanup; \
77 	} while (/*CONSTCOND*/0)
78 
79 /*%
80  * Convenience function for configuring a single zone ACL.
81  */
82 static isc_result_t
configure_zone_acl(const cfg_obj_t * zconfig,const cfg_obj_t * vconfig,const cfg_obj_t * config,acl_type_t acltype,cfg_aclconfctx_t * actx,dns_zone_t * zone,void (* setzacl)(dns_zone_t *,dns_acl_t *),void (* clearzacl)(dns_zone_t *))83 configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
84 		   const cfg_obj_t *config, acl_type_t acltype,
85 		   cfg_aclconfctx_t *actx, dns_zone_t *zone,
86 		   void (*setzacl)(dns_zone_t *, dns_acl_t *),
87 		   void (*clearzacl)(dns_zone_t *))
88 {
89 	isc_result_t result;
90 	const cfg_obj_t *maps[5] = {NULL, NULL, NULL, NULL, NULL};
91 	const cfg_obj_t *aclobj = NULL;
92 	int i = 0;
93 	dns_acl_t **aclp = NULL, *acl = NULL;
94 	const char *aclname;
95 	dns_view_t *view;
96 
97 	view = dns_zone_getview(zone);
98 
99 	switch (acltype) {
100 	    case allow_notify:
101 		if (view != NULL)
102 			aclp = &view->notifyacl;
103 		aclname = "allow-notify";
104 		break;
105 	    case allow_query:
106 		if (view != NULL)
107 			aclp = &view->queryacl;
108 		aclname = "allow-query";
109 		break;
110 	    case allow_query_on:
111 		if (view != NULL)
112 			aclp = &view->queryonacl;
113 		aclname = "allow-query-on";
114 		break;
115 	    case allow_transfer:
116 		if (view != NULL)
117 			aclp = &view->transferacl;
118 		aclname = "allow-transfer";
119 		break;
120 	    case allow_update:
121 		if (view != NULL)
122 			aclp = &view->updateacl;
123 		aclname = "allow-update";
124 		break;
125 	    case allow_update_forwarding:
126 		if (view != NULL)
127 			aclp = &view->upfwdacl;
128 		aclname = "allow-update-forwarding";
129 		break;
130 	    default:
131 		INSIST(0);
132 		return (ISC_R_FAILURE);
133 	}
134 
135 	/* First check to see if ACL is defined within the zone */
136 	if (zconfig != NULL) {
137 		maps[0] = cfg_tuple_get(zconfig, "options");
138 		(void)ns_config_get(maps, aclname, &aclobj);
139 		if (aclobj != NULL) {
140 			aclp = NULL;
141 			goto parse_acl;
142 		}
143 	}
144 
145 	/* Failing that, see if there's a default ACL already in the view */
146 	if (aclp != NULL && *aclp != NULL) {
147 		(*setzacl)(zone, *aclp);
148 		return (ISC_R_SUCCESS);
149 	}
150 
151 	/* Check for default ACLs that haven't been parsed yet */
152 	if (vconfig != NULL) {
153 		const cfg_obj_t *options = cfg_tuple_get(vconfig, "options");
154 		if (options != NULL)
155 			maps[i++] = options;
156 	}
157 	if (config != NULL) {
158 		const cfg_obj_t *options = NULL;
159 		(void)cfg_map_get(config, "options", &options);
160 		if (options != NULL)
161 			maps[i++] = options;
162 	}
163 	maps[i++] = ns_g_defaults;
164 	maps[i] = NULL;
165 
166 	(void)ns_config_get(maps, aclname, &aclobj);
167 	if (aclobj == NULL) {
168 		(*clearzacl)(zone);
169 		return (ISC_R_SUCCESS);
170 	}
171 
172 parse_acl:
173 	result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx,
174 				    dns_zone_getmctx(zone), 0, &acl);
175 	if (result != ISC_R_SUCCESS)
176 		return (result);
177 	(*setzacl)(zone, acl);
178 
179 	/* Set the view default now */
180 	if (aclp != NULL)
181 		dns_acl_attach(acl, aclp);
182 
183 	dns_acl_detach(&acl);
184 	return (ISC_R_SUCCESS);
185 }
186 
187 /*%
188  * Parse the zone update-policy statement.
189  */
190 static isc_result_t
configure_zone_ssutable(const cfg_obj_t * zconfig,dns_zone_t * zone,const char * zname)191 configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
192 			const char *zname)
193 {
194 	const cfg_obj_t *updatepolicy = NULL;
195 	const cfg_listelt_t *element, *element2;
196 	dns_ssutable_t *table = NULL;
197 	isc_mem_t *mctx = dns_zone_getmctx(zone);
198 	isc_boolean_t autoddns = ISC_FALSE;
199 	isc_result_t result;
200 
201 	(void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
202 
203 	if (updatepolicy == NULL) {
204 		dns_zone_setssutable(zone, NULL);
205 		return (ISC_R_SUCCESS);
206 	}
207 
208 	if (cfg_obj_isstring(updatepolicy) &&
209 	    strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) {
210 		autoddns = ISC_TRUE;
211 		updatepolicy = NULL;
212 	}
213 
214 	result = dns_ssutable_create(mctx, &table);
215 	if (result != ISC_R_SUCCESS)
216 		return (result);
217 
218 	for (element = cfg_list_first(updatepolicy);
219 	     element != NULL;
220 	     element = cfg_list_next(element))
221 	{
222 		const cfg_obj_t *stmt = cfg_listelt_value(element);
223 		const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
224 		const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
225 		const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
226 		const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
227 		const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
228 		const char *str;
229 		isc_boolean_t grant = ISC_FALSE;
230 		isc_boolean_t usezone = ISC_FALSE;
231 		unsigned int mtype = DNS_SSUMATCHTYPE_NAME;
232 		dns_fixedname_t fname, fident;
233 		isc_buffer_t b;
234 		dns_rdatatype_t *types;
235 		unsigned int i, n;
236 
237 		str = cfg_obj_asstring(mode);
238 		if (strcasecmp(str, "grant") == 0)
239 			grant = ISC_TRUE;
240 		else if (strcasecmp(str, "deny") == 0)
241 			grant = ISC_FALSE;
242 		else
243 			INSIST(0);
244 
245 		str = cfg_obj_asstring(matchtype);
246 		if (strcasecmp(str, "name") == 0)
247 			mtype = DNS_SSUMATCHTYPE_NAME;
248 		else if (strcasecmp(str, "subdomain") == 0)
249 			mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
250 		else if (strcasecmp(str, "wildcard") == 0)
251 			mtype = DNS_SSUMATCHTYPE_WILDCARD;
252 		else if (strcasecmp(str, "self") == 0)
253 			mtype = DNS_SSUMATCHTYPE_SELF;
254 		else if (strcasecmp(str, "selfsub") == 0)
255 			mtype = DNS_SSUMATCHTYPE_SELFSUB;
256 		else if (strcasecmp(str, "selfwild") == 0)
257 			mtype = DNS_SSUMATCHTYPE_SELFWILD;
258 		else if (strcasecmp(str, "ms-self") == 0)
259 			mtype = DNS_SSUMATCHTYPE_SELFMS;
260 		else if (strcasecmp(str, "krb5-self") == 0)
261 			mtype = DNS_SSUMATCHTYPE_SELFKRB5;
262 		else if (strcasecmp(str, "ms-subdomain") == 0)
263 			mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS;
264 		else if (strcasecmp(str, "krb5-subdomain") == 0)
265 			mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5;
266 		else if (strcasecmp(str, "tcp-self") == 0)
267 			mtype = DNS_SSUMATCHTYPE_TCPSELF;
268 		else if (strcasecmp(str, "6to4-self") == 0)
269 			mtype = DNS_SSUMATCHTYPE_6TO4SELF;
270 		else if (strcasecmp(str, "zonesub") == 0) {
271 			mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
272 			usezone = ISC_TRUE;
273 		} else if (strcasecmp(str, "external") == 0)
274 			mtype = DNS_SSUMATCHTYPE_EXTERNAL;
275 		else
276 			INSIST(0);
277 
278 		dns_fixedname_init(&fident);
279 		str = cfg_obj_asstring(identity);
280 		isc_buffer_constinit(&b, str, strlen(str));
281 		isc_buffer_add(&b, strlen(str));
282 		result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
283 					   dns_rootname, 0, NULL);
284 		if (result != ISC_R_SUCCESS) {
285 			cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
286 				    "'%s' is not a valid name", str);
287 			goto cleanup;
288 		}
289 
290 		dns_fixedname_init(&fname);
291 		if (usezone) {
292 			result = dns_name_copy(dns_zone_getorigin(zone),
293 					       dns_fixedname_name(&fname),
294 					       NULL);
295 			if (result != ISC_R_SUCCESS) {
296 				cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
297 					    "error copying origin: %s",
298 					    isc_result_totext(result));
299 				goto cleanup;
300 			}
301 		} else {
302 			str = cfg_obj_asstring(dname);
303 			isc_buffer_constinit(&b, str, strlen(str));
304 			isc_buffer_add(&b, strlen(str));
305 			result = dns_name_fromtext(dns_fixedname_name(&fname),
306 						   &b, dns_rootname, 0, NULL);
307 			if (result != ISC_R_SUCCESS) {
308 				cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
309 					    "'%s' is not a valid name", str);
310 				goto cleanup;
311 			}
312 		}
313 
314 		n = ns_config_listcount(typelist);
315 		if (n == 0)
316 			types = NULL;
317 		else {
318 			types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
319 			if (types == NULL) {
320 				result = ISC_R_NOMEMORY;
321 				goto cleanup;
322 			}
323 		}
324 
325 		i = 0;
326 		for (element2 = cfg_list_first(typelist);
327 		     element2 != NULL;
328 		     element2 = cfg_list_next(element2))
329 		{
330 			const cfg_obj_t *typeobj;
331 			isc_textregion_t r;
332 
333 			INSIST(i < n);
334 
335 			typeobj = cfg_listelt_value(element2);
336 			str = cfg_obj_asstring(typeobj);
337 			DE_CONST(str, r.base);
338 			r.length = strlen(str);
339 
340 			result = dns_rdatatype_fromtext(&types[i++], &r);
341 			if (result != ISC_R_SUCCESS) {
342 				cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
343 					    "'%s' is not a valid type", str);
344 				isc_mem_put(mctx, types,
345 					    n * sizeof(dns_rdatatype_t));
346 				goto cleanup;
347 			}
348 		}
349 		INSIST(i == n);
350 
351 		result = dns_ssutable_addrule(table, grant,
352 					      dns_fixedname_name(&fident),
353 					      mtype,
354 					      dns_fixedname_name(&fname),
355 					      n, types);
356 		if (types != NULL)
357 			isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
358 		if (result != ISC_R_SUCCESS) {
359 			goto cleanup;
360 		}
361 	}
362 
363 	/*
364 	 * If "update-policy local;" and a session key exists,
365 	 * then use the default policy, which is equivalent to:
366 	 * update-policy { grant <session-keyname> zonesub any; };
367 	 */
368 	if (autoddns) {
369 		dns_rdatatype_t any = dns_rdatatype_any;
370 
371 		if (ns_g_server->session_keyname == NULL) {
372 			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
373 				      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
374 				      "failed to enable auto DDNS policy "
375 				      "for zone %s: session key not found",
376 				      zname);
377 			result = ISC_R_NOTFOUND;
378 			goto cleanup;
379 		}
380 
381 		result = dns_ssutable_addrule(table, ISC_TRUE,
382 					      ns_g_server->session_keyname,
383 					      DNS_SSUMATCHTYPE_SUBDOMAIN,
384 					      dns_zone_getorigin(zone),
385 					      1, &any);
386 
387 		if (result != ISC_R_SUCCESS)
388 			goto cleanup;
389 	}
390 
391 	result = ISC_R_SUCCESS;
392 	dns_zone_setssutable(zone, table);
393 
394  cleanup:
395 	dns_ssutable_detach(&table);
396 	return (result);
397 }
398 
399 /*
400  * This is the TTL used for internally generated RRsets for static-stub zones.
401  * The value doesn't matter because the mapping is static, but needs to be
402  * defined for the sake of implementation.
403  */
404 #define STATICSTUB_SERVER_TTL 86400
405 
406 /*%
407  * Configure an apex NS with glues for a static-stub zone.
408  * For example, for the zone named "example.com", the following RRs will be
409  * added to the zone DB:
410  * example.com. NS example.com.
411  * example.com. A 192.0.2.1
412  * example.com. AAAA 2001:db8::1
413  */
414 static isc_result_t
configure_staticstub_serveraddrs(const cfg_obj_t * zconfig,dns_zone_t * zone,dns_rdatalist_t * rdatalist_ns,dns_rdatalist_t * rdatalist_a,dns_rdatalist_t * rdatalist_aaaa)415 configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone,
416 				 dns_rdatalist_t *rdatalist_ns,
417 				 dns_rdatalist_t *rdatalist_a,
418 				 dns_rdatalist_t *rdatalist_aaaa)
419 {
420 	const cfg_listelt_t *element;
421 	isc_mem_t *mctx = dns_zone_getmctx(zone);
422 	isc_region_t region, sregion;
423 	dns_rdata_t *rdata;
424 	isc_result_t result = ISC_R_SUCCESS;
425 
426 	for (element = cfg_list_first(zconfig);
427 	     element != NULL;
428 	     element = cfg_list_next(element))
429 	{
430 		const isc_sockaddr_t* sa;
431 		isc_netaddr_t na;
432 		const cfg_obj_t *address = cfg_listelt_value(element);
433 		dns_rdatalist_t *rdatalist;
434 
435 		sa = cfg_obj_assockaddr(address);
436 		if (isc_sockaddr_getport(sa) != 0) {
437 			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
438 				    "port is not configurable for "
439 				    "static stub server-addresses");
440 			return (ISC_R_FAILURE);
441 		}
442 		isc_netaddr_fromsockaddr(&na, sa);
443 		if (isc_netaddr_getzone(&na) != 0) {
444 			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
445 					    "scoped address is not allowed "
446 					    "for static stub "
447 					    "server-addresses");
448 			return (ISC_R_FAILURE);
449 		}
450 
451 		switch (na.family) {
452 		case AF_INET:
453 			region.length = sizeof(na.type.in);
454 			rdatalist = rdatalist_a;
455 			break;
456 		default:
457 			INSIST(na.family == AF_INET6);
458 			region.length = sizeof(na.type.in6);
459 			rdatalist = rdatalist_aaaa;
460 			break;
461 		}
462 
463 		rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length);
464 		if (rdata == NULL)
465 			return (ISC_R_NOMEMORY);
466 		region.base = (unsigned char *)(rdata + 1);
467 		memmove(region.base, &na.type, region.length);
468 		dns_rdata_init(rdata);
469 		dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
470 				     rdatalist->type, &region);
471 		ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
472 	}
473 
474 	/*
475 	 * If no address is specified (unlikely in this context, but possible),
476 	 * there's nothing to do anymore.
477 	 */
478 	if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
479 	    ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) {
480 		return (ISC_R_SUCCESS);
481 	}
482 
483 	/* Add to the list an apex NS with the ns name being the origin name */
484 	dns_name_toregion(dns_zone_getorigin(zone), &sregion);
485 	rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
486 	if (rdata == NULL) {
487 		/*
488 		 * Already allocated data will be freed in the caller, so
489 		 * we can simply return here.
490 		 */
491 		return (ISC_R_NOMEMORY);
492 	}
493 	region.length = sregion.length;
494 	region.base = (unsigned char *)(rdata + 1);
495 	memmove(region.base, sregion.base, region.length);
496 	dns_rdata_init(rdata);
497 	dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
498 			     dns_rdatatype_ns, &region);
499 	ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link);
500 
501 	return (result);
502 }
503 
504 /*%
505  * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
506  * For example, for the zone named "example.com", something like the following
507  * RRs will be added to the zone DB:
508  * example.com. NS ns.example.net.
509  */
510 static isc_result_t
configure_staticstub_servernames(const cfg_obj_t * zconfig,dns_zone_t * zone,dns_rdatalist_t * rdatalist,const char * zname)511 configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
512 				 dns_rdatalist_t *rdatalist, const char *zname)
513 {
514 	const cfg_listelt_t *element;
515 	isc_mem_t *mctx = dns_zone_getmctx(zone);
516 	dns_rdata_t *rdata;
517 	isc_region_t sregion, region;
518 	isc_result_t result = ISC_R_SUCCESS;
519 
520 	for (element = cfg_list_first(zconfig);
521 	     element != NULL;
522 	     element = cfg_list_next(element))
523 	{
524 		const cfg_obj_t *obj;
525 		const char *str;
526 		dns_fixedname_t fixed_name;
527 		dns_name_t *nsname;
528 		isc_buffer_t b;
529 
530 		obj = cfg_listelt_value(element);
531 		str = cfg_obj_asstring(obj);
532 
533 		dns_fixedname_init(&fixed_name);
534 		nsname = dns_fixedname_name(&fixed_name);
535 
536 		isc_buffer_constinit(&b, str, strlen(str));
537 		isc_buffer_add(&b, strlen(str));
538 		result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
539 		if (result != ISC_R_SUCCESS) {
540 			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
541 					    "server-name '%s' is not a valid "
542 					    "name", str);
543 			return (result);
544 		}
545 		if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
546 			cfg_obj_log(zconfig, ns_g_lctx, ISC_LOG_ERROR,
547 				    "server-name '%s' must not be a "
548 				    "subdomain of zone name '%s'",
549 				    str, zname);
550 			return (ISC_R_FAILURE);
551 		}
552 
553 		dns_name_toregion(nsname, &sregion);
554 		rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
555 		if (rdata == NULL)
556 			return (ISC_R_NOMEMORY);
557 		region.length = sregion.length;
558 		region.base = (unsigned char *)(rdata + 1);
559 		memmove(region.base, sregion.base, region.length);
560 		dns_rdata_init(rdata);
561 		dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
562 				     dns_rdatatype_ns, &region);
563 		ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
564 	}
565 
566 	return (result);
567 }
568 
569 /*%
570  * Configure static-stub zone.
571  */
572 static isc_result_t
configure_staticstub(const cfg_obj_t * zconfig,dns_zone_t * zone,const char * zname,const char * dbtype)573 configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
574 		     const char *zname, const char *dbtype)
575 {
576 	int i = 0;
577 	const cfg_obj_t *obj;
578 	isc_mem_t *mctx = dns_zone_getmctx(zone);
579 	dns_db_t *db = NULL;
580 	dns_dbversion_t *dbversion = NULL;
581 	dns_dbnode_t *apexnode = NULL;
582 	dns_name_t apexname;
583 	isc_result_t result;
584 	dns_rdataset_t rdataset;
585 	dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa;
586 	dns_rdatalist_t* rdatalists[] = {
587 		&rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL
588 	};
589 	dns_rdata_t *rdata;
590 	isc_region_t region;
591 
592 	/* Create the DB beforehand */
593 	RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone),
594 			     dns_dbtype_stub, dns_zone_getclass(zone),
595 			     0, NULL, &db));
596 	dns_zone_setdb(zone, db);
597 
598 	dns_rdatalist_init(&rdatalist_ns);
599 	rdatalist_ns.rdclass = dns_zone_getclass(zone);
600 	rdatalist_ns.type = dns_rdatatype_ns;
601 	rdatalist_ns.ttl = STATICSTUB_SERVER_TTL;
602 
603 	dns_rdatalist_init(&rdatalist_a);
604 	rdatalist_a.rdclass = dns_zone_getclass(zone);
605 	rdatalist_a.type = dns_rdatatype_a;
606 	rdatalist_a.ttl = STATICSTUB_SERVER_TTL;
607 
608 	dns_rdatalist_init(&rdatalist_aaaa);
609 	rdatalist_aaaa.rdclass = dns_zone_getclass(zone);
610 	rdatalist_aaaa.type = dns_rdatatype_aaaa;
611 	rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL;
612 
613 	/* Prepare zone RRs from the configuration */
614 	obj = NULL;
615 	result = cfg_map_get(zconfig, "server-addresses", &obj);
616 	if (result == ISC_R_SUCCESS) {
617 		INSIST(obj != NULL);
618 		result = configure_staticstub_serveraddrs(obj, zone,
619 							  &rdatalist_ns,
620 							  &rdatalist_a,
621 							  &rdatalist_aaaa);
622 		if (result != ISC_R_SUCCESS)
623 			goto cleanup;
624 	}
625 
626 	obj = NULL;
627 	result = cfg_map_get(zconfig, "server-names", &obj);
628 	if (result == ISC_R_SUCCESS) {
629 		INSIST(obj != NULL);
630 		result = configure_staticstub_servernames(obj, zone,
631 							  &rdatalist_ns,
632 							  zname);
633 		if (result != ISC_R_SUCCESS)
634 			goto cleanup;
635 	}
636 
637 	/*
638 	 * Sanity check: there should be at least one NS RR at the zone apex
639 	 * to trigger delegation.
640 	 */
641 	if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) {
642 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
643 			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
644 			      "No NS record is configured for a "
645 			      "static-stub zone '%s'", zname);
646 		result = ISC_R_FAILURE;
647 		goto cleanup;
648 	}
649 
650 	/*
651 	 * Now add NS and glue A/AAAA RRsets to the zone DB.
652 	 * First open a new version for the add operation and get a pointer
653 	 * to the apex node (all RRs are of the apex name).
654 	 */
655 	result = dns_db_newversion(db, &dbversion);
656 	if (result != ISC_R_SUCCESS)
657 		goto cleanup;
658 	dns_name_init(&apexname, NULL);
659 	dns_name_clone(dns_zone_getorigin(zone), &apexname);
660 	result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode);
661 	if (result != ISC_R_SUCCESS)
662 		goto cleanup;
663 
664 	/* Add NS RRset */
665 	dns_rdataset_init(&rdataset);
666 	RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset)
667 		      == ISC_R_SUCCESS);
668 	result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
669 				    0, NULL);
670 	dns_rdataset_disassociate(&rdataset);
671 	if (result != ISC_R_SUCCESS)
672 		goto cleanup;
673 
674 	/* Add glue A RRset, if any */
675 	if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
676 		RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset)
677 			      == ISC_R_SUCCESS);
678 		result = dns_db_addrdataset(db, apexnode, dbversion, 0,
679 					    &rdataset, 0, NULL);
680 		dns_rdataset_disassociate(&rdataset);
681 		if (result != ISC_R_SUCCESS)
682 			goto cleanup;
683 	}
684 
685 	/* Add glue AAAA RRset, if any */
686 	if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
687 		RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa,
688 						       &rdataset)
689 			      == ISC_R_SUCCESS);
690 		result = dns_db_addrdataset(db, apexnode, dbversion, 0,
691 					    &rdataset, 0, NULL);
692 		dns_rdataset_disassociate(&rdataset);
693 		if (result != ISC_R_SUCCESS)
694 			goto cleanup;
695 	}
696 
697 	result = ISC_R_SUCCESS;
698 
699   cleanup:
700 	if (apexnode != NULL)
701 		dns_db_detachnode(db, &apexnode);
702 	if (dbversion != NULL)
703 		dns_db_closeversion(db, &dbversion, ISC_TRUE);
704 	if (db != NULL)
705 		dns_db_detach(&db);
706 	for (i = 0; rdatalists[i] != NULL; i++) {
707 		while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) {
708 			ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link);
709 			dns_rdata_toregion(rdata, &region);
710 			isc_mem_put(mctx, rdata,
711 				    sizeof(*rdata) + region.length);
712 		}
713 	}
714 
715 	INSIST(dbversion == NULL);
716 
717 	return (result);
718 }
719 
720 /*%
721  * Convert a config file zone type into a server zone type.
722  */
723 static inline dns_zonetype_t
zonetype_fromconfig(const cfg_obj_t * map)724 zonetype_fromconfig(const cfg_obj_t *map) {
725 	const cfg_obj_t *obj = NULL;
726 	isc_result_t result;
727 
728 	result = cfg_map_get(map, "type", &obj);
729 	INSIST(result == ISC_R_SUCCESS && obj != NULL);
730 	return (ns_config_getzonetype(obj));
731 }
732 
733 /*%
734  * Helper function for strtoargv().  Pardon the gratuitous recursion.
735  */
736 static isc_result_t
strtoargvsub(isc_mem_t * mctx,char * s,unsigned int * argcp,char *** argvp,unsigned int n)737 strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
738 	     char ***argvp, unsigned int n)
739 {
740 	isc_result_t result;
741 
742 	/* Discard leading whitespace. */
743 	while (*s == ' ' || *s == '\t')
744 		s++;
745 
746 	if (*s == '\0') {
747 		/* We have reached the end of the string. */
748 		*argcp = n;
749 		*argvp = isc_mem_get(mctx, n * sizeof(char *));
750 		if (*argvp == NULL)
751 			return (ISC_R_NOMEMORY);
752 	} else {
753 		char *p = s;
754 		while (*p != ' ' && *p != '\t' && *p != '\0')
755 			p++;
756 		if (*p != '\0')
757 			*p++ = '\0';
758 
759 		result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
760 		if (result != ISC_R_SUCCESS)
761 			return (result);
762 		(*argvp)[n] = s;
763 	}
764 	return (ISC_R_SUCCESS);
765 }
766 
767 /*%
768  * Tokenize the string "s" into whitespace-separated words,
769  * return the number of words in '*argcp' and an array
770  * of pointers to the words in '*argvp'.  The caller
771  * must free the array using isc_mem_put().  The string
772  * is modified in-place.
773  */
774 static isc_result_t
strtoargv(isc_mem_t * mctx,char * s,unsigned int * argcp,char *** argvp)775 strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
776 	return (strtoargvsub(mctx, s, argcp, argvp, 0));
777 }
778 
779 static void
checknames(dns_zonetype_t ztype,const cfg_obj_t ** maps,const cfg_obj_t ** objp)780 checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
781 	   const cfg_obj_t **objp)
782 {
783 	const char *zone = NULL;
784 	isc_result_t result;
785 
786 	switch (ztype) {
787 	case dns_zone_slave: zone = "slave"; break;
788 	case dns_zone_master: zone = "master"; break;
789 	default:
790 		INSIST(0);
791 	}
792 	result = ns_checknames_get(maps, zone, objp);
793 	INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL);
794 }
795 
796 isc_result_t
ns_zone_configure(const cfg_obj_t * config,const cfg_obj_t * vconfig,const cfg_obj_t * zconfig,cfg_aclconfctx_t * ac,dns_zone_t * zone,dns_zone_t * raw)797 ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
798 		  const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
799 		  dns_zone_t *zone, dns_zone_t *raw)
800 {
801 	isc_result_t result;
802 	const char *zname;
803 	dns_rdataclass_t zclass;
804 	dns_rdataclass_t vclass;
805 	const cfg_obj_t *maps[5];
806 	const cfg_obj_t *nodefault[4];
807 	const cfg_obj_t *zoptions = NULL;
808 	const cfg_obj_t *options = NULL;
809 	const cfg_obj_t *obj;
810 	const char *filename = NULL;
811 	const char *dupcheck;
812 	dns_notifytype_t notifytype = dns_notifytype_yes;
813 	isc_sockaddr_t *addrs;
814 	isc_dscp_t *dscps;
815 	dns_name_t **keynames;
816 	isc_uint32_t count;
817 	unsigned int dbargc;
818 	char **dbargv;
819 	static char default_dbtype[] = "rbt";
820 	static char dlz_dbtype[] = "dlz";
821 	char *cpval = default_dbtype;
822 	isc_mem_t *mctx = dns_zone_getmctx(zone);
823 	dns_dialuptype_t dialup = dns_dialuptype_no;
824 	dns_zonetype_t ztype;
825 	int i;
826 	isc_int32_t journal_size;
827 	isc_boolean_t multi;
828 	isc_boolean_t alt;
829 	dns_view_t *view;
830 	isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE;
831 	isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE;
832 	isc_boolean_t ixfrdiff;
833 	dns_masterformat_t masterformat;
834 	isc_stats_t *zoneqrystats;
835 	dns_stats_t *rcvquerystats;
836 	dns_zonestat_level_t statlevel;
837 	int seconds;
838 	dns_zone_t *mayberaw = (raw != NULL) ? raw : zone;
839 	isc_dscp_t dscp;
840 
841 	i = 0;
842 	if (zconfig != NULL) {
843 		zoptions = cfg_tuple_get(zconfig, "options");
844 		nodefault[i] = maps[i] = zoptions;
845 		i++;
846 	}
847 	if (vconfig != NULL) {
848 		nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options");
849 		i++;
850 	}
851 	if (config != NULL) {
852 		(void)cfg_map_get(config, "options", &options);
853 		if (options != NULL) {
854 			nodefault[i] = maps[i] = options;
855 			i++;
856 		}
857 	}
858 	nodefault[i] = NULL;
859 	maps[i++] = ns_g_defaults;
860 	maps[i] = NULL;
861 
862 	if (vconfig != NULL)
863 		RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"),
864 					  dns_rdataclass_in, &vclass));
865 	else
866 		vclass = dns_rdataclass_in;
867 
868 	/*
869 	 * Configure values common to all zone types.
870 	 */
871 
872 	zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
873 
874 	RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
875 				  vclass, &zclass));
876 	dns_zone_setclass(zone, zclass);
877 	if (raw != NULL)
878 		dns_zone_setclass(raw, zclass);
879 
880 	ztype = zonetype_fromconfig(zoptions);
881 	if (raw != NULL) {
882 		dns_zone_settype(raw, ztype);
883 		dns_zone_settype(zone, dns_zone_master);
884 	} else
885 		dns_zone_settype(zone, ztype);
886 
887 	obj = NULL;
888 	result = cfg_map_get(zoptions, "database", &obj);
889 	if (result == ISC_R_SUCCESS)
890 		cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
891 	if (cpval == NULL)
892 		return(ISC_R_NOMEMORY);
893 
894 	obj = NULL;
895 	result = cfg_map_get(zoptions, "dlz", &obj);
896 	if (result == ISC_R_SUCCESS) {
897 		const char *dlzname = cfg_obj_asstring(obj);
898 		size_t len;
899 
900 		if (cpval != default_dbtype) {
901 		       isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
902 				     NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
903 				     "zone '%s': both 'database' and 'dlz' "
904 				     "specified", zname);
905 		       return (ISC_R_FAILURE);
906 		}
907 
908 		len = strlen(dlzname) + 5;
909 		cpval = isc_mem_allocate(mctx, len);
910 		snprintf(cpval, len, "dlz %s", dlzname);
911 	}
912 
913 	result = strtoargv(mctx, cpval, &dbargc, &dbargv);
914 	if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
915 		isc_mem_free(mctx, cpval);
916 		return (result);
917 	}
918 
919 	/*
920 	 * ANSI C is strange here.  There is no logical reason why (char **)
921 	 * cannot be promoted automatically to (const char * const *) by the
922 	 * compiler w/o generating a warning.
923 	 */
924 	result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv);
925 	isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
926 	if (cpval != default_dbtype && cpval != dlz_dbtype)
927 		isc_mem_free(mctx, cpval);
928 	if (result != ISC_R_SUCCESS)
929 		return (result);
930 
931 	obj = NULL;
932 	result = cfg_map_get(zoptions, "file", &obj);
933 	if (result == ISC_R_SUCCESS)
934 		filename = cfg_obj_asstring(obj);
935 
936 	/*
937 	 * Unless we're using some alternative database, a master zone
938 	 * will be needing a master file.
939 	 */
940 	if (ztype == dns_zone_master && cpval == default_dbtype &&
941 	    filename == NULL) {
942 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
943 			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
944 			      "zone '%s': 'file' not specified",
945 			      zname);
946 		return (ISC_R_FAILURE);
947 	}
948 
949 	if (ztype == dns_zone_slave)
950 		masterformat = dns_masterformat_raw;
951 	else
952 		masterformat = dns_masterformat_text;
953 	obj = NULL;
954 	result= ns_config_get(maps, "masterfile-format", &obj);
955 	if (result == ISC_R_SUCCESS) {
956 		const char *masterformatstr = cfg_obj_asstring(obj);
957 
958 		if (strcasecmp(masterformatstr, "text") == 0)
959 			masterformat = dns_masterformat_text;
960 		else if (strcasecmp(masterformatstr, "raw") == 0)
961 			masterformat = dns_masterformat_raw;
962 		else if (strcasecmp(masterformatstr, "map") == 0)
963 			masterformat = dns_masterformat_map;
964 		else
965 			INSIST(0);
966 	}
967 
968 	obj = NULL;
969 	result = ns_config_get(maps, "max-zone-ttl", &obj);
970 	if (result == ISC_R_SUCCESS && masterformat == dns_masterformat_map) {
971 		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
972 			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
973 			      "zone '%s': 'max-zone-ttl' is not compatible "
974 			      "with 'masterfile-format map'", zname);
975 		return (ISC_R_FAILURE);
976 	} else if (result == ISC_R_SUCCESS) {
977 		dns_ttl_t maxttl = cfg_obj_asuint32(obj);
978 		dns_zone_setmaxttl(zone, maxttl);
979 		if (raw != NULL)
980 			dns_zone_setmaxttl(raw, maxttl);
981 	}
982 
983 	if (raw != NULL && filename != NULL) {
984 #define SIGNED ".signed"
985 		size_t signedlen = strlen(filename) + sizeof(SIGNED);
986 		char *signedname;
987 
988 		RETERR(dns_zone_setfile2(raw, filename, masterformat));
989 		signedname = isc_mem_get(mctx, signedlen);
990 		if (signedname == NULL)
991 			return (ISC_R_NOMEMORY);
992 
993 		(void)snprintf(signedname, signedlen, "%s" SIGNED, filename);
994 		result = dns_zone_setfile2(zone, signedname,
995 					   dns_masterformat_raw);
996 		isc_mem_put(mctx, signedname, signedlen);
997 		if (result != ISC_R_SUCCESS)
998 			return (result);
999 	} else
1000 		RETERR(dns_zone_setfile2(zone, filename, masterformat));
1001 
1002 	obj = NULL;
1003 	result = cfg_map_get(zoptions, "journal", &obj);
1004 	if (result == ISC_R_SUCCESS)
1005 		RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj)));
1006 
1007 	/*
1008 	 * Notify messages are processed by the raw zone if it exists.
1009 	 */
1010 	if (ztype == dns_zone_slave)
1011 		RETERR(configure_zone_acl(zconfig, vconfig, config,
1012 					  allow_notify, ac, mayberaw,
1013 					  dns_zone_setnotifyacl,
1014 					  dns_zone_clearnotifyacl));
1015 
1016 	/*
1017 	 * XXXAG This probably does not make sense for stubs.
1018 	 */
1019 	RETERR(configure_zone_acl(zconfig, vconfig, config,
1020 				  allow_query, ac, zone,
1021 				  dns_zone_setqueryacl,
1022 				  dns_zone_clearqueryacl));
1023 
1024 	RETERR(configure_zone_acl(zconfig, vconfig, config,
1025 				  allow_query_on, ac, zone,
1026 				  dns_zone_setqueryonacl,
1027 				  dns_zone_clearqueryonacl));
1028 
1029 	obj = NULL;
1030 	result = ns_config_get(maps, "dialup", &obj);
1031 	INSIST(result == ISC_R_SUCCESS && obj != NULL);
1032 	if (cfg_obj_isboolean(obj)) {
1033 		if (cfg_obj_asboolean(obj))
1034 			dialup = dns_dialuptype_yes;
1035 		else
1036 			dialup = dns_dialuptype_no;
1037 	} else {
1038 		const char *dialupstr = cfg_obj_asstring(obj);
1039 		if (strcasecmp(dialupstr, "notify") == 0)
1040 			dialup = dns_dialuptype_notify;
1041 		else if (strcasecmp(dialupstr, "notify-passive") == 0)
1042 			dialup = dns_dialuptype_notifypassive;
1043 		else if (strcasecmp(dialupstr, "refresh") == 0)
1044 			dialup = dns_dialuptype_refresh;
1045 		else if (strcasecmp(dialupstr, "passive") == 0)
1046 			dialup = dns_dialuptype_passive;
1047 		else
1048 			INSIST(0);
1049 	}
1050 	if (raw != NULL)
1051 		dns_zone_setdialup(raw, dialup);
1052 	dns_zone_setdialup(zone, dialup);
1053 
1054 	obj = NULL;
1055 	result = ns_config_get(maps, "zone-statistics", &obj);
1056 	INSIST(result == ISC_R_SUCCESS && obj != NULL);
1057 	if (cfg_obj_isboolean(obj)) {
1058 		if (cfg_obj_asboolean(obj))
1059 			statlevel = dns_zonestat_full;
1060 		else
1061 			statlevel = dns_zonestat_none;
1062 	} else {
1063 		const char *levelstr = cfg_obj_asstring(obj);
1064 		if (strcasecmp(levelstr, "full") == 0)
1065 			statlevel = dns_zonestat_full;
1066 		else if (strcasecmp(levelstr, "terse") == 0)
1067 			statlevel = dns_zonestat_terse;
1068 		else if (strcasecmp(levelstr, "none") == 0)
1069 			statlevel = dns_zonestat_none;
1070 		else
1071 			INSIST(0);
1072 	}
1073 	dns_zone_setstatlevel(zone, statlevel);
1074 
1075 	zoneqrystats  = NULL;
1076 	rcvquerystats = NULL;
1077 	if (statlevel == dns_zonestat_full) {
1078 		RETERR(isc_stats_create(mctx, &zoneqrystats,
1079 					dns_nsstatscounter_max));
1080 		RETERR(dns_rdatatypestats_create(mctx,
1081 					&rcvquerystats));
1082 	}
1083 	dns_zone_setrequeststats(zone,  zoneqrystats);
1084 	dns_zone_setrcvquerystats(zone, rcvquerystats);
1085 
1086 	if (zoneqrystats != NULL)
1087 		isc_stats_detach(&zoneqrystats);
1088 
1089 	if(rcvquerystats != NULL)
1090 		dns_stats_detach(&rcvquerystats);
1091 
1092 	/*
1093 	 * Configure master functionality.  This applies
1094 	 * to primary masters (type "master") and slaves
1095 	 * acting as masters (type "slave"), but not to stubs.
1096 	 */
1097 	if (ztype != dns_zone_stub && ztype != dns_zone_staticstub &&
1098 	    ztype != dns_zone_redirect) {
1099 		obj = NULL;
1100 		result = ns_config_get(maps, "notify", &obj);
1101 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1102 		if (cfg_obj_isboolean(obj)) {
1103 			if (cfg_obj_asboolean(obj))
1104 				notifytype = dns_notifytype_yes;
1105 			else
1106 				notifytype = dns_notifytype_no;
1107 		} else {
1108 			const char *notifystr = cfg_obj_asstring(obj);
1109 			if (strcasecmp(notifystr, "explicit") == 0)
1110 				notifytype = dns_notifytype_explicit;
1111 			else if (strcasecmp(notifystr, "master-only") == 0)
1112 				notifytype = dns_notifytype_masteronly;
1113 			else
1114 				INSIST(0);
1115 		}
1116 		if (raw != NULL)
1117 			dns_zone_setnotifytype(raw, dns_notifytype_no);
1118 		dns_zone_setnotifytype(zone, notifytype);
1119 
1120 		obj = NULL;
1121 		result = ns_config_get(maps, "also-notify", &obj);
1122 		if (result == ISC_R_SUCCESS &&
1123 		    (notifytype == dns_notifytype_yes ||
1124 		     notifytype == dns_notifytype_explicit ||
1125 		     (notifytype == dns_notifytype_masteronly &&
1126 		      ztype == dns_zone_master)))
1127 		{
1128 			isc_uint32_t addrcount;
1129 			addrs = NULL;
1130 			keynames = NULL;
1131 			dscps = NULL;
1132 			RETERR(ns_config_getipandkeylist(config, obj, mctx,
1133 							 &addrs, &dscps,
1134 							 &keynames,
1135 							 &addrcount));
1136 			result = dns_zone_setalsonotifydscpkeys(zone, addrs,
1137 								dscps, keynames,
1138 								addrcount);
1139 			if (addrcount != 0)
1140 				ns_config_putipandkeylist(mctx, &addrs, &dscps,
1141 							  &keynames, addrcount);
1142 			else
1143 				INSIST(addrs == NULL && dscps == NULL &&
1144 				       keynames == NULL);
1145 			RETERR(result);
1146 		} else
1147 			RETERR(dns_zone_setalsonotify(zone, NULL, 0));
1148 
1149 		obj = NULL;
1150 		result = ns_config_get(maps, "notify-source", &obj);
1151 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1152 		RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
1153 		dscp = cfg_obj_getdscp(obj);
1154 		if (dscp == -1)
1155 			dscp = ns_g_dscp;
1156 		RETERR(dns_zone_setnotifysrc4dscp(zone, dscp));
1157 		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1158 
1159 		obj = NULL;
1160 		result = ns_config_get(maps, "notify-source-v6", &obj);
1161 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1162 		RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
1163 		dscp = cfg_obj_getdscp(obj);
1164 		if (dscp == -1)
1165 			dscp = ns_g_dscp;
1166 		RETERR(dns_zone_setnotifysrc6dscp(zone, dscp));
1167 		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1168 
1169 		obj = NULL;
1170 		result = ns_config_get(maps, "notify-to-soa", &obj);
1171 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1172 		dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
1173 				   cfg_obj_asboolean(obj));
1174 
1175 		dns_zone_setisself(zone, ns_client_isself, NULL);
1176 
1177 		RETERR(configure_zone_acl(zconfig, vconfig, config,
1178 					  allow_transfer, ac, zone,
1179 					  dns_zone_setxfracl,
1180 					  dns_zone_clearxfracl));
1181 
1182 		obj = NULL;
1183 		result = ns_config_get(maps, "max-transfer-time-out", &obj);
1184 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1185 		dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
1186 
1187 		obj = NULL;
1188 		result = ns_config_get(maps, "max-transfer-idle-out", &obj);
1189 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1190 		dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
1191 
1192 		obj = NULL;
1193 		result = ns_config_get(maps, "max-journal-size", &obj);
1194 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1195 		if (raw != NULL)
1196 			dns_zone_setjournalsize(raw, -1);
1197 		dns_zone_setjournalsize(zone, -1);
1198 		if (cfg_obj_isstring(obj)) {
1199 			const char *str = cfg_obj_asstring(obj);
1200 			INSIST(strcasecmp(str, "unlimited") == 0);
1201 			journal_size = ISC_UINT32_MAX / 2;
1202 		} else {
1203 			isc_resourcevalue_t value;
1204 			value = cfg_obj_asuint64(obj);
1205 			if (value > ISC_UINT32_MAX / 2) {
1206 				cfg_obj_log(obj, ns_g_lctx,
1207 					    ISC_LOG_ERROR,
1208 					    "'max-journal-size "
1209 					    "%" ISC_PRINT_QUADFORMAT "d' "
1210 					    "is too large",
1211 					    value);
1212 				RETERR(ISC_R_RANGE);
1213 			}
1214 			journal_size = (isc_uint32_t)value;
1215 		}
1216 		if (raw != NULL)
1217 			dns_zone_setjournalsize(raw, journal_size);
1218 		dns_zone_setjournalsize(zone, journal_size);
1219 
1220 		obj = NULL;
1221 		result = ns_config_get(maps, "ixfr-from-differences", &obj);
1222 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1223 		if (cfg_obj_isboolean(obj))
1224 			ixfrdiff = cfg_obj_asboolean(obj);
1225 		else if (!strcasecmp(cfg_obj_asstring(obj), "master") &&
1226 			 ztype == dns_zone_master)
1227 			ixfrdiff = ISC_TRUE;
1228 		else if (!strcasecmp(cfg_obj_asstring(obj), "slave") &&
1229 			ztype == dns_zone_slave)
1230 			ixfrdiff = ISC_TRUE;
1231 		else
1232 			ixfrdiff = ISC_FALSE;
1233 		if (raw != NULL) {
1234 			dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS,
1235 					   ISC_TRUE);
1236 			dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
1237 					   ISC_TRUE);
1238 		} else
1239 			dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
1240 					   ixfrdiff);
1241 
1242 		obj = NULL;
1243 		result = ns_config_get(maps, "request-ixfr", &obj);
1244 		INSIST(result == ISC_R_SUCCESS);
1245 		dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj));
1246 
1247 		checknames(ztype, maps, &obj);
1248 		INSIST(obj != NULL);
1249 		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1250 			fail = ISC_FALSE;
1251 			check = ISC_TRUE;
1252 		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1253 			fail = check = ISC_TRUE;
1254 		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1255 			fail = check = ISC_FALSE;
1256 		} else
1257 			INSIST(0);
1258 		if (raw != NULL) {
1259 			dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES,
1260 					   check);
1261 			dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL,
1262 					   fail);
1263 			dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES,
1264 					   ISC_FALSE);
1265 			dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
1266 					   ISC_FALSE);
1267 		} else {
1268 			dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES,
1269 					   check);
1270 			dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
1271 					   fail);
1272 		}
1273 
1274 		obj = NULL;
1275 		result = ns_config_get(maps, "notify-delay", &obj);
1276 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1277 		dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
1278 
1279 		obj = NULL;
1280 		result = ns_config_get(maps, "check-sibling", &obj);
1281 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1282 		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
1283 				   cfg_obj_asboolean(obj));
1284 
1285 		obj = NULL;
1286 		result = ns_config_get(maps, "check-spf", &obj);
1287 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1288 		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1289 			check = ISC_TRUE;
1290 		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1291 			check = ISC_FALSE;
1292 		} else
1293 			INSIST(0);
1294 		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check);
1295 
1296 		obj = NULL;
1297 		result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
1298 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1299 		dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));
1300 
1301 		obj = NULL;
1302 		result = ns_config_get(maps, "nsec3-test-zone", &obj);
1303 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1304 		dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
1305 				   cfg_obj_asboolean(obj));
1306 	} else if (ztype == dns_zone_redirect) {
1307 		dns_zone_setnotifytype(zone, dns_notifytype_no);
1308 
1309 		obj = NULL;
1310 		result = ns_config_get(maps, "max-journal-size", &obj);
1311 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1312 		dns_zone_setjournalsize(zone, -1);
1313 		if (cfg_obj_isstring(obj)) {
1314 			const char *str = cfg_obj_asstring(obj);
1315 			INSIST(strcasecmp(str, "unlimited") == 0);
1316 			journal_size = ISC_UINT32_MAX / 2;
1317 		} else {
1318 			isc_resourcevalue_t value;
1319 			value = cfg_obj_asuint64(obj);
1320 			if (value > ISC_UINT32_MAX / 2) {
1321 				cfg_obj_log(obj, ns_g_lctx,
1322 					    ISC_LOG_ERROR,
1323 					    "'max-journal-size "
1324 					    "%" ISC_PRINT_QUADFORMAT "d' "
1325 					    "is too large",
1326 					    value);
1327 				RETERR(ISC_R_RANGE);
1328 			}
1329 			journal_size = (isc_uint32_t)value;
1330 		}
1331 		dns_zone_setjournalsize(zone, journal_size);
1332 	}
1333 
1334 	/*
1335 	 * Configure update-related options.  These apply to
1336 	 * primary masters only.
1337 	 */
1338 	if (ztype == dns_zone_master) {
1339 		dns_acl_t *updateacl;
1340 
1341 		RETERR(configure_zone_acl(zconfig, vconfig, config,
1342 					  allow_update, ac, mayberaw,
1343 					  dns_zone_setupdateacl,
1344 					  dns_zone_clearupdateacl));
1345 
1346 		updateacl = dns_zone_getupdateacl(mayberaw);
1347 		if (updateacl != NULL  && dns_acl_isinsecure(updateacl))
1348 			isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
1349 				      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
1350 				      "zone '%s' allows updates by IP "
1351 				      "address, which is insecure",
1352 				      zname);
1353 
1354 		RETERR(configure_zone_ssutable(zoptions, mayberaw, zname));
1355 	}
1356 
1357 	if (ztype == dns_zone_master || raw != NULL) {
1358 		isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE;
1359 
1360 		obj = NULL;
1361 		result = ns_config_get(maps, "sig-validity-interval", &obj);
1362 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1363 		{
1364 			const cfg_obj_t *validity, *resign;
1365 
1366 			validity = cfg_tuple_get(obj, "validity");
1367 			seconds = cfg_obj_asuint32(validity) * 86400;
1368 			dns_zone_setsigvalidityinterval(zone, seconds);
1369 
1370 			resign = cfg_tuple_get(obj, "re-sign");
1371 			if (cfg_obj_isvoid(resign)) {
1372 				seconds /= 4;
1373 			} else {
1374 				if (seconds > 7 * 86400)
1375 					seconds = cfg_obj_asuint32(resign) *
1376 							86400;
1377 				else
1378 					seconds = cfg_obj_asuint32(resign) *
1379 							3600;
1380 			}
1381 			dns_zone_setsigresigninginterval(zone, seconds);
1382 		}
1383 
1384 		obj = NULL;
1385 		result = ns_config_get(maps, "key-directory", &obj);
1386 		if (result == ISC_R_SUCCESS) {
1387 			filename = cfg_obj_asstring(obj);
1388 			RETERR(dns_zone_setkeydirectory(zone, filename));
1389 		}
1390 
1391 		obj = NULL;
1392 		result = ns_config_get(maps, "sig-signing-signatures", &obj);
1393 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1394 		dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));
1395 
1396 		obj = NULL;
1397 		result = ns_config_get(maps, "sig-signing-nodes", &obj);
1398 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1399 		dns_zone_setnodes(zone, cfg_obj_asuint32(obj));
1400 
1401 		obj = NULL;
1402 		result = ns_config_get(maps, "sig-signing-type", &obj);
1403 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1404 		dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));
1405 
1406 		obj = NULL;
1407 		result = ns_config_get(maps, "update-check-ksk", &obj);
1408 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1409 		dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
1410 				   cfg_obj_asboolean(obj));
1411 
1412 		obj = NULL;
1413 		result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj);
1414 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1415 		dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
1416 				   cfg_obj_asboolean(obj));
1417 
1418 		obj = NULL;
1419 		result = ns_config_get(maps, "dnssec-loadkeys-interval", &obj);
1420 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1421 		RETERR(dns_zone_setrefreshkeyinterval(zone,
1422 						      cfg_obj_asuint32(obj)));
1423 
1424 		obj = NULL;
1425 		result = cfg_map_get(zoptions, "auto-dnssec", &obj);
1426 		if (result == ISC_R_SUCCESS) {
1427 			const char *arg = cfg_obj_asstring(obj);
1428 			if (strcasecmp(arg, "allow") == 0)
1429 				allow = ISC_TRUE;
1430 			else if (strcasecmp(arg, "maintain") == 0)
1431 				allow = maint = ISC_TRUE;
1432 			else if (strcasecmp(arg, "off") == 0)
1433 				;
1434 			else
1435 				INSIST(0);
1436 			dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
1437 			dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
1438 		}
1439 	}
1440 
1441 	if (ztype == dns_zone_slave) {
1442 		RETERR(configure_zone_acl(zconfig, vconfig, config,
1443 					  allow_update_forwarding, ac,
1444 					  mayberaw, dns_zone_setforwardacl,
1445 					  dns_zone_clearforwardacl));
1446 	}
1447 
1448 	/*%
1449 	 * Primary master functionality.
1450 	 */
1451 	if (ztype == dns_zone_master) {
1452 		obj = NULL;
1453 		result = ns_config_get(maps, "check-wildcard", &obj);
1454 		if (result == ISC_R_SUCCESS)
1455 			check = cfg_obj_asboolean(obj);
1456 		else
1457 			check = ISC_FALSE;
1458 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check);
1459 
1460 		/*
1461 		 * With map files, the default is ignore duplicate
1462 		 * records.  With other master formats, the default is
1463 		 * taken from the global configuration.
1464 		 */
1465 		obj = NULL;
1466 		if (masterformat != dns_masterformat_map) {
1467 			result = ns_config_get(maps, "check-dup-records", &obj);
1468 			INSIST(result == ISC_R_SUCCESS && obj != NULL);
1469 			dupcheck = cfg_obj_asstring(obj);
1470 		} else {
1471 			result = ns_config_get(nodefault, "check-dup-records",
1472 					       &obj);
1473 			if (result == ISC_R_SUCCESS)
1474 				dupcheck = cfg_obj_asstring(obj);
1475 			else
1476 				dupcheck = "ignore";
1477 
1478 		}
1479 		if (strcasecmp(dupcheck, "warn") == 0) {
1480 			fail = ISC_FALSE;
1481 			check = ISC_TRUE;
1482 		} else if (strcasecmp(dupcheck, "fail") == 0) {
1483 			fail = check = ISC_TRUE;
1484 		} else if (strcasecmp(dupcheck, "ignore") == 0) {
1485 			fail = check = ISC_FALSE;
1486 		} else
1487 			INSIST(0);
1488 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check);
1489 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
1490 
1491 		obj = NULL;
1492 		result = ns_config_get(maps, "check-mx", &obj);
1493 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1494 		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1495 			fail = ISC_FALSE;
1496 			check = ISC_TRUE;
1497 		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1498 			fail = check = ISC_TRUE;
1499 		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1500 			fail = check = ISC_FALSE;
1501 		} else
1502 			INSIST(0);
1503 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check);
1504 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail);
1505 
1506 		/*
1507 		 * With map files, the default is *not* to check
1508 		 * integrity.  With other master formats, the default is
1509 		 * taken from the global configuration.
1510 		 */
1511 		obj = NULL;
1512 		if (masterformat != dns_masterformat_map) {
1513 			result = ns_config_get(maps, "check-integrity", &obj);
1514 			INSIST(result == ISC_R_SUCCESS && obj != NULL);
1515 			dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
1516 					   cfg_obj_asboolean(obj));
1517 		} else {
1518 			check = ISC_FALSE;
1519 			result = ns_config_get(nodefault, "check-integrity",
1520 					       &obj);
1521 			if (result == ISC_R_SUCCESS)
1522 				check = cfg_obj_asboolean(obj);
1523 			dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
1524 					   check);
1525 		}
1526 
1527 		obj = NULL;
1528 		result = ns_config_get(maps, "check-mx-cname", &obj);
1529 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1530 		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1531 			warn = ISC_TRUE;
1532 			ignore = ISC_FALSE;
1533 		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1534 			warn = ignore = ISC_FALSE;
1535 		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1536 			warn = ignore = ISC_TRUE;
1537 		} else
1538 			INSIST(0);
1539 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn);
1540 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
1541 
1542 		obj = NULL;
1543 		result = ns_config_get(maps, "check-srv-cname", &obj);
1544 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1545 		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1546 			warn = ISC_TRUE;
1547 			ignore = ISC_FALSE;
1548 		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1549 			warn = ignore = ISC_FALSE;
1550 		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1551 			warn = ignore = ISC_TRUE;
1552 		} else
1553 			INSIST(0);
1554 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn);
1555 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME,
1556 				   ignore);
1557 
1558 		obj = NULL;
1559 		result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj);
1560 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1561 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE,
1562 				   cfg_obj_asboolean(obj));
1563 
1564 		obj = NULL;
1565 		result = cfg_map_get(zoptions, "dnssec-update-mode", &obj);
1566 		if (result == ISC_R_SUCCESS) {
1567 			const char *arg = cfg_obj_asstring(obj);
1568 			if (strcasecmp(arg, "no-resign") == 0)
1569 				dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN,
1570 						   ISC_TRUE);
1571 			else if (strcasecmp(arg, "maintain") == 0)
1572 				;
1573 			else
1574 				INSIST(0);
1575 		}
1576 
1577 		obj = NULL;
1578 		result = ns_config_get(maps, "serial-update-method", &obj);
1579 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1580 		if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0)
1581 			dns_zone_setserialupdatemethod(zone,
1582 						    dns_updatemethod_unixtime);
1583 		else
1584 			dns_zone_setserialupdatemethod(zone,
1585 						  dns_updatemethod_increment);
1586 	}
1587 
1588 	/*
1589 	 * Configure slave functionality.
1590 	 */
1591 	switch (ztype) {
1592 	case dns_zone_slave:
1593 	case dns_zone_stub:
1594 	case dns_zone_redirect:
1595 		count = 0;
1596 		obj = NULL;
1597 		(void)cfg_map_get(zoptions, "masters", &obj);
1598 		if (obj != NULL) {
1599 			addrs = NULL;
1600 			dscps = NULL;
1601 			keynames = NULL;
1602 			RETERR(ns_config_getipandkeylist(config, obj, mctx,
1603 							 &addrs, &dscps,
1604 							 &keynames, &count));
1605 			result = dns_zone_setmasterswithkeys(mayberaw, addrs,
1606 							     keynames, count);
1607 			if (count != 0)
1608 				ns_config_putipandkeylist(mctx, &addrs, &dscps,
1609 							  &keynames, count);
1610 			else
1611 				INSIST(addrs == NULL && keynames == NULL);
1612 		} else
1613 			result = dns_zone_setmasters(mayberaw, NULL, 0);
1614 		RETERR(result);
1615 
1616 		multi = ISC_FALSE;
1617 		if (count > 1) {
1618 			obj = NULL;
1619 			result = ns_config_get(maps, "multi-master", &obj);
1620 			INSIST(result == ISC_R_SUCCESS && obj != NULL);
1621 			multi = cfg_obj_asboolean(obj);
1622 		}
1623 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi);
1624 
1625 		obj = NULL;
1626 		result = ns_config_get(maps, "max-transfer-time-in", &obj);
1627 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1628 		dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60);
1629 
1630 		obj = NULL;
1631 		result = ns_config_get(maps, "max-transfer-idle-in", &obj);
1632 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1633 		dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60);
1634 
1635 		obj = NULL;
1636 		result = ns_config_get(maps, "max-refresh-time", &obj);
1637 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1638 		dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj));
1639 
1640 		obj = NULL;
1641 		result = ns_config_get(maps, "min-refresh-time", &obj);
1642 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1643 		dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj));
1644 
1645 		obj = NULL;
1646 		result = ns_config_get(maps, "max-retry-time", &obj);
1647 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1648 		dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj));
1649 
1650 		obj = NULL;
1651 		result = ns_config_get(maps, "min-retry-time", &obj);
1652 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1653 		dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj));
1654 
1655 		obj = NULL;
1656 		result = ns_config_get(maps, "transfer-source", &obj);
1657 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1658 		RETERR(dns_zone_setxfrsource4(mayberaw,
1659 					      cfg_obj_assockaddr(obj)));
1660 		dscp = cfg_obj_getdscp(obj);
1661 		if (dscp == -1)
1662 			dscp = ns_g_dscp;
1663 		RETERR(dns_zone_setxfrsource4dscp(mayberaw, dscp));
1664 		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1665 
1666 		obj = NULL;
1667 		result = ns_config_get(maps, "transfer-source-v6", &obj);
1668 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1669 		RETERR(dns_zone_setxfrsource6(mayberaw,
1670 					      cfg_obj_assockaddr(obj)));
1671 		dscp = cfg_obj_getdscp(obj);
1672 		if (dscp == -1)
1673 			dscp = ns_g_dscp;
1674 		RETERR(dns_zone_setxfrsource6dscp(mayberaw, dscp));
1675 		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1676 
1677 		obj = NULL;
1678 		result = ns_config_get(maps, "alt-transfer-source", &obj);
1679 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1680 		RETERR(dns_zone_setaltxfrsource4(mayberaw,
1681 						 cfg_obj_assockaddr(obj)));
1682 		dscp = cfg_obj_getdscp(obj);
1683 		if (dscp == -1)
1684 			dscp = ns_g_dscp;
1685 		RETERR(dns_zone_setaltxfrsource4dscp(mayberaw, dscp));
1686 
1687 		obj = NULL;
1688 		result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
1689 		INSIST(result == ISC_R_SUCCESS && obj != NULL);
1690 		RETERR(dns_zone_setaltxfrsource6(mayberaw,
1691 						 cfg_obj_assockaddr(obj)));
1692 		dscp = cfg_obj_getdscp(obj);
1693 		if (dscp == -1)
1694 			dscp = ns_g_dscp;
1695 		RETERR(dns_zone_setaltxfrsource6dscp(mayberaw, dscp));
1696 
1697 		obj = NULL;
1698 		(void)ns_config_get(maps, "use-alt-transfer-source", &obj);
1699 		if (obj == NULL) {
1700 			/*
1701 			 * Default off when views are in use otherwise
1702 			 * on for BIND 8 compatibility.
1703 			 */
1704 			view = dns_zone_getview(zone);
1705 			if (view != NULL && strcmp(view->name, "_default") == 0)
1706 				alt = ISC_TRUE;
1707 			else
1708 				alt = ISC_FALSE;
1709 		} else
1710 			alt = cfg_obj_asboolean(obj);
1711 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt);
1712 
1713 		obj = NULL;
1714 		(void)ns_config_get(maps, "try-tcp-refresh", &obj);
1715 		dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH,
1716 				   cfg_obj_asboolean(obj));
1717 		break;
1718 
1719 	case dns_zone_staticstub:
1720 		RETERR(configure_staticstub(zoptions, zone, zname,
1721 					    default_dbtype));
1722 		break;
1723 
1724 	default:
1725 		break;
1726 	}
1727 
1728 	return (ISC_R_SUCCESS);
1729 }
1730 
1731 
1732 /*
1733  * Set up a DLZ zone as writeable
1734  */
1735 isc_result_t
ns_zone_configure_writeable_dlz(dns_dlzdb_t * dlzdatabase,dns_zone_t * zone,dns_rdataclass_t rdclass,dns_name_t * name)1736 ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
1737 				dns_rdataclass_t rdclass, dns_name_t *name)
1738 {
1739 	dns_db_t *db = NULL;
1740 	isc_time_t now;
1741 	isc_result_t result;
1742 
1743 	TIME_NOW(&now);
1744 
1745 	dns_zone_settype(zone, dns_zone_dlz);
1746 	result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db);
1747 	if (result != ISC_R_SUCCESS)
1748 		return (result);
1749 	result = dns_zone_dlzpostload(zone, db);
1750 	dns_db_detach(&db);
1751 	return (result);
1752 }
1753 
1754 isc_boolean_t
ns_zone_reusable(dns_zone_t * zone,const cfg_obj_t * zconfig)1755 ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
1756 	const cfg_obj_t *zoptions = NULL;
1757 	const cfg_obj_t *obj = NULL;
1758 	const char *cfilename;
1759 	const char *zfilename;
1760 	dns_zone_t *raw = NULL;
1761 	isc_boolean_t has_raw;
1762 	dns_zonetype_t ztype;
1763 
1764 	zoptions = cfg_tuple_get(zconfig, "options");
1765 
1766 	/*
1767 	 * We always reconfigure a static-stub zone for simplicity, assuming
1768 	 * the amount of data to be loaded is small.
1769 	 */
1770 	if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) {
1771 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
1772 			     "not reusable: staticstub");
1773 		return (ISC_FALSE);
1774 	}
1775 
1776 	/* If there's a raw zone, use that for filename and type comparison */
1777 	dns_zone_getraw(zone, &raw);
1778 	if (raw != NULL) {
1779 		zfilename = dns_zone_getfile(raw);
1780 		ztype = dns_zone_gettype(raw);
1781 		dns_zone_detach(&raw);
1782 		has_raw = ISC_TRUE;
1783 	} else {
1784 		zfilename = dns_zone_getfile(zone);
1785 		ztype = dns_zone_gettype(zone);
1786 		has_raw = ISC_FALSE;
1787 	}
1788 
1789 	obj = NULL;
1790 	(void)cfg_map_get(zoptions, "inline-signing", &obj);
1791 	if ((obj == NULL || !cfg_obj_asboolean(obj)) && has_raw) {
1792 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
1793 			     "not reusable: old zone was inline-signing");
1794 		return (ISC_FALSE);
1795 	} else if ((obj != NULL && cfg_obj_asboolean(obj)) && !has_raw) {
1796 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
1797 			     "not reusable: old zone was not inline-signing");
1798 		return (ISC_FALSE);
1799 	}
1800 
1801 	if (zonetype_fromconfig(zoptions) != ztype) {
1802 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
1803 			     "not reusable: type mismatch");
1804 		return (ISC_FALSE);
1805 	}
1806 
1807 	obj = NULL;
1808 	(void)cfg_map_get(zoptions, "file", &obj);
1809 	if (obj != NULL)
1810 		cfilename = cfg_obj_asstring(obj);
1811 	else
1812 		cfilename = NULL;
1813 	if (!((cfilename == NULL && zfilename == NULL) ||
1814 	      (cfilename != NULL && zfilename != NULL &&
1815 	       strcmp(cfilename, zfilename) == 0)))
1816 	{
1817 		dns_zone_log(zone, ISC_LOG_DEBUG(1),
1818 			     "not reusable: filename mismatch");
1819 		return (ISC_FALSE);
1820 	}
1821 
1822 	return (ISC_TRUE);
1823 }
1824