etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / named / zoneconf.c
blob41b4e3585d2bc030ab48fa83887644f3d5e31614
1 /* $NetBSD: zoneconf.c,v 1.8 2015/07/08 17:28:55 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2003 Internet Software Consortium.
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.
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.
20 /* Id */
22 /*% */
24 #include <config.h>
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>
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>
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>
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;
67 #define RETERR(x) do { \
68 isc_result_t _r = (x); \
69 if (_r != ISC_R_SUCCESS) \
70 return (_r); \
71 } while (/*CONSTCOND*/0)
73 #define CHECK(x) do { \
74 result = (x); \
75 if (result != ISC_R_SUCCESS) \
76 goto cleanup; \
77 } while (/*CONSTCOND*/0)
79 /*%
80 * Convenience function for configuring a single zone ACL.
82 static isc_result_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 *))
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;
97 view = dns_zone_getview(zone);
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);
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;
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);
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;
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;
163 maps[i++] = ns_g_defaults;
164 maps[i] = NULL;
166 (void)ns_config_get(maps, aclname, &aclobj);
167 if (aclobj == NULL) {
168 (*clearzacl)(zone);
169 return (ISC_R_SUCCESS);
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);
179 /* Set the view default now */
180 if (aclp != NULL)
181 dns_acl_attach(acl, aclp);
183 dns_acl_detach(&acl);
184 return (ISC_R_SUCCESS);
188 * Parse the zone update-policy statement.
190 static isc_result_t
191 configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
192 const char *zname)
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;
201 (void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
203 if (updatepolicy == NULL) {
204 dns_zone_setssutable(zone, NULL);
205 return (ISC_R_SUCCESS);
208 if (cfg_obj_isstring(updatepolicy) &&
209 strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) {
210 autoddns = ISC_TRUE;
211 updatepolicy = NULL;
214 result = dns_ssutable_create(mctx, &table);
215 if (result != ISC_R_SUCCESS)
216 return (result);
218 for (element = cfg_list_first(updatepolicy);
219 element != NULL;
220 element = cfg_list_next(element))
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;
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);
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);
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;
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;
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;
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;
325 i = 0;
326 for (element2 = cfg_list_first(typelist);
327 element2 != NULL;
328 element2 = cfg_list_next(element2))
330 const cfg_obj_t *typeobj;
331 isc_textregion_t r;
333 INSIST(i < n);
335 typeobj = cfg_listelt_value(element2);
336 str = cfg_obj_asstring(typeobj);
337 DE_CONST(str, r.base);
338 r.length = strlen(str);
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;
349 INSIST(i == n);
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;
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; };
368 if (autoddns) {
369 dns_rdatatype_t any = dns_rdatatype_any;
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;
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);
387 if (result != ISC_R_SUCCESS)
388 goto cleanup;
391 result = ISC_R_SUCCESS;
392 dns_zone_setssutable(zone, table);
394 cleanup:
395 dns_ssutable_detach(&table);
396 return (result);
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.
404 #define STATICSTUB_SERVER_TTL 86400
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
414 static isc_result_t
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)
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;
426 for (element = cfg_list_first(zconfig);
427 element != NULL;
428 element = cfg_list_next(element))
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;
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);
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);
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;
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);
475 * If no address is specified (unlikely in this context, but possible),
476 * there's nothing to do anymore.
478 if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
479 ISC_LIST_EMPTY(rdatalist_aaaa->rdata)) {
480 return (ISC_R_SUCCESS);
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) {
488 * Already allocated data will be freed in the caller, so
489 * we can simply return here.
491 return (ISC_R_NOMEMORY);
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);
501 return (result);
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.
510 static isc_result_t
511 configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
512 dns_rdatalist_t *rdatalist, const char *zname)
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;
520 for (element = cfg_list_first(zconfig);
521 element != NULL;
522 element = cfg_list_next(element))
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;
530 obj = cfg_listelt_value(element);
531 str = cfg_obj_asstring(obj);
533 dns_fixedname_init(&fixed_name);
534 nsname = dns_fixedname_name(&fixed_name);
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);
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);
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);
566 return (result);
570 * Configure static-stub zone.
572 static isc_result_t
573 configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
574 const char *zname, const char *dbtype)
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
589 dns_rdata_t *rdata;
590 isc_region_t region;
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);
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;
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;
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;
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;
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;
638 * Sanity check: there should be at least one NS RR at the zone apex
639 * to trigger delegation.
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;
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).
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;
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;
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;
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;
697 result = ISC_R_SUCCESS;
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);
715 INSIST(dbversion == NULL);
717 return (result);
721 * Convert a config file zone type into a server zone type.
723 static inline dns_zonetype_t
724 zonetype_fromconfig(const cfg_obj_t *map) {
725 const cfg_obj_t *obj = NULL;
726 isc_result_t result;
728 result = cfg_map_get(map, "type", &obj);
729 INSIST(result == ISC_R_SUCCESS && obj != NULL);
730 return (ns_config_getzonetype(obj));
734 * Helper function for strtoargv(). Pardon the gratuitous recursion.
736 static isc_result_t
737 strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
738 char ***argvp, unsigned int n)
740 isc_result_t result;
742 /* Discard leading whitespace. */
743 while (*s == ' ' || *s == '\t')
744 s++;
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';
759 result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
760 if (result != ISC_R_SUCCESS)
761 return (result);
762 (*argvp)[n] = s;
764 return (ISC_R_SUCCESS);
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.
774 static isc_result_t
775 strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
776 return (strtoargvsub(mctx, s, argcp, argvp, 0));
779 static void
780 checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
781 const cfg_obj_t **objp)
783 const char *zone = NULL;
784 isc_result_t result;
786 switch (ztype) {
787 case dns_zone_slave: zone = "slave"; break;
788 case dns_zone_master: zone = "master"; break;
789 default:
790 INSIST(0);
792 result = ns_checknames_get(maps, zone, objp);
793 INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL);
796 isc_result_t
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)
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;
841 i = 0;
842 if (zconfig != NULL) {
843 zoptions = cfg_tuple_get(zconfig, "options");
844 nodefault[i] = maps[i] = zoptions;
845 i++;
847 if (vconfig != NULL) {
848 nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options");
849 i++;
851 if (config != NULL) {
852 (void)cfg_map_get(config, "options", &options);
853 if (options != NULL) {
854 nodefault[i] = maps[i] = options;
855 i++;
858 nodefault[i] = NULL;
859 maps[i++] = ns_g_defaults;
860 maps[i] = NULL;
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;
869 * Configure values common to all zone types.
872 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
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);
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);
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);
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;
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);
908 len = strlen(dlzname) + 5;
909 cpval = isc_mem_allocate(mctx, len);
910 snprintf(cpval, len, "dlz %s", dlzname);
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);
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.
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);
931 obj = NULL;
932 result = cfg_map_get(zoptions, "file", &obj);
933 if (result == ISC_R_SUCCESS)
934 filename = cfg_obj_asstring(obj);
937 * Unless we're using some alternative database, a master zone
938 * will be needing a master file.
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);
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);
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);
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);
983 if (raw != NULL && filename != NULL) {
984 #define SIGNED ".signed"
985 size_t signedlen = strlen(filename) + sizeof(SIGNED);
986 char *signedname;
988 RETERR(dns_zone_setfile2(raw, filename, masterformat));
989 signedname = isc_mem_get(mctx, signedlen);
990 if (signedname == NULL)
991 return (ISC_R_NOMEMORY);
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));
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)));
1008 * Notify messages are processed by the raw zone if it exists.
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));
1017 * XXXAG This probably does not make sense for stubs.
1019 RETERR(configure_zone_acl(zconfig, vconfig, config,
1020 allow_query, ac, zone,
1021 dns_zone_setqueryacl,
1022 dns_zone_clearqueryacl));
1024 RETERR(configure_zone_acl(zconfig, vconfig, config,
1025 allow_query_on, ac, zone,
1026 dns_zone_setqueryonacl,
1027 dns_zone_clearqueryonacl));
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);
1050 if (raw != NULL)
1051 dns_zone_setdialup(raw, dialup);
1052 dns_zone_setdialup(zone, dialup);
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);
1073 dns_zone_setstatlevel(zone, statlevel);
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));
1083 dns_zone_setrequeststats(zone, zoneqrystats);
1084 dns_zone_setrcvquerystats(zone, rcvquerystats);
1086 if (zoneqrystats != NULL)
1087 isc_stats_detach(&zoneqrystats);
1089 if(rcvquerystats != NULL)
1090 dns_stats_detach(&rcvquerystats);
1093 * Configure master functionality. This applies
1094 * to primary masters (type "master") and slaves
1095 * acting as masters (type "slave"), but not to stubs.
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);
1116 if (raw != NULL)
1117 dns_zone_setnotifytype(raw, dns_notifytype_no);
1118 dns_zone_setnotifytype(zone, notifytype);
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)))
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));
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));
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));
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));
1175 dns_zone_setisself(zone, ns_client_isself, NULL);
1177 RETERR(configure_zone_acl(zconfig, vconfig, config,
1178 allow_transfer, ac, zone,
1179 dns_zone_setxfracl,
1180 dns_zone_clearxfracl));
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);
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);
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);
1214 journal_size = (isc_uint32_t)value;
1216 if (raw != NULL)
1217 dns_zone_setjournalsize(raw, journal_size);
1218 dns_zone_setjournalsize(zone, journal_size);
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);
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));
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);
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));
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));
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);
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));
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);
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);
1329 journal_size = (isc_uint32_t)value;
1331 dns_zone_setjournalsize(zone, journal_size);
1335 * Configure update-related options. These apply to
1336 * primary masters only.
1338 if (ztype == dns_zone_master) {
1339 dns_acl_t *updateacl;
1341 RETERR(configure_zone_acl(zconfig, vconfig, config,
1342 allow_update, ac, mayberaw,
1343 dns_zone_setupdateacl,
1344 dns_zone_clearupdateacl));
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);
1354 RETERR(configure_zone_ssutable(zoptions, mayberaw, zname));
1357 if (ztype == dns_zone_master || raw != NULL) {
1358 isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE;
1360 obj = NULL;
1361 result = ns_config_get(maps, "sig-validity-interval", &obj);
1362 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1364 const cfg_obj_t *validity, *resign;
1366 validity = cfg_tuple_get(obj, "validity");
1367 seconds = cfg_obj_asuint32(validity) * 86400;
1368 dns_zone_setsigvalidityinterval(zone, seconds);
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;
1381 dns_zone_setsigresigninginterval(zone, seconds);
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));
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));
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));
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));
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));
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));
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)));
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)
1434 else
1435 INSIST(0);
1436 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
1437 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
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));
1449 * Primary master functionality.
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);
1461 * With map files, the default is ignore duplicate
1462 * records. With other master formats, the default is
1463 * taken from the global configuration.
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";
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);
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);
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.
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);
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);
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);
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));
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)
1573 else
1574 INSIST(0);
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);
1589 * Configure slave functionality.
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);
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);
1623 dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi);
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);
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);
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));
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));
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));
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));
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));
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));
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));
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));
1697 obj = NULL;
1698 (void)ns_config_get(maps, "use-alt-transfer-source", &obj);
1699 if (obj == NULL) {
1701 * Default off when views are in use otherwise
1702 * on for BIND 8 compatibility.
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);
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;
1719 case dns_zone_staticstub:
1720 RETERR(configure_staticstub(zoptions, zone, zname,
1721 default_dbtype));
1722 break;
1724 default:
1725 break;
1728 return (ISC_R_SUCCESS);
1733 * Set up a DLZ zone as writeable
1735 isc_result_t
1736 ns_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
1737 dns_rdataclass_t rdclass, dns_name_t *name)
1739 dns_db_t *db = NULL;
1740 isc_time_t now;
1741 isc_result_t result;
1743 TIME_NOW(&now);
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);
1754 isc_boolean_t
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;
1764 zoptions = cfg_tuple_get(zconfig, "options");
1767 * We always reconfigure a static-stub zone for simplicity, assuming
1768 * the amount of data to be loaded is small.
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);
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;
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);
1801 if (zonetype_fromconfig(zoptions) != ztype) {
1802 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1803 "not reusable: type mismatch");
1804 return (ISC_FALSE);
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)))
1817 dns_zone_log(zone, ISC_LOG_DEBUG(1),
1818 "not reusable: filename mismatch");
1819 return (ISC_FALSE);
1822 return (ISC_TRUE);