zoneconf.c revision 1.13 1 /* $NetBSD: zoneconf.c,v 1.13 2023/01/25 21:43:23 christos Exp $ */
2
3 /*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16 #include <inttypes.h>
17 #include <stdbool.h>
18
19 #include <isc/buffer.h>
20 #include <isc/file.h>
21 #include <isc/mem.h>
22 #include <isc/print.h>
23 #include <isc/stats.h>
24 #include <isc/string.h> /* Required for HP/UX (and others?) */
25 #include <isc/util.h>
26
27 #include <dns/acl.h>
28 #include <dns/db.h>
29 #include <dns/fixedname.h>
30 #include <dns/ipkeylist.h>
31 #include <dns/journal.h>
32 #include <dns/kasp.h>
33 #include <dns/log.h>
34 #include <dns/masterdump.h>
35 #include <dns/name.h>
36 #include <dns/nsec3.h>
37 #include <dns/rdata.h>
38 #include <dns/rdatalist.h>
39 #include <dns/rdataset.h>
40 #include <dns/rdatatype.h>
41 #include <dns/result.h>
42 #include <dns/sdlz.h>
43 #include <dns/ssu.h>
44 #include <dns/stats.h>
45 #include <dns/tsig.h>
46 #include <dns/view.h>
47 #include <dns/zone.h>
48
49 #include <ns/client.h>
50
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) \
68 do { \
69 isc_result_t _r = (x); \
70 if (_r != ISC_R_SUCCESS) \
71 return ((_r)); \
72 } while (0)
73
74 #define CHECK(x) \
75 do { \
76 result = (x); \
77 if (result != ISC_R_SUCCESS) \
78 goto cleanup; \
79 } while (0)
80
81 /*%
82 * Convenience function for configuring a single zone ACL.
83 */
84 static isc_result_t
85 configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
86 const cfg_obj_t *config, acl_type_t acltype,
87 cfg_aclconfctx_t *actx, dns_zone_t *zone,
88 void (*setzacl)(dns_zone_t *, dns_acl_t *),
89 void (*clearzacl)(dns_zone_t *)) {
90 isc_result_t result;
91 const cfg_obj_t *maps[5] = { NULL, NULL, NULL, NULL, NULL };
92 const cfg_obj_t *aclobj = NULL;
93 int i = 0;
94 dns_acl_t **aclp = NULL, *acl = NULL;
95 const char *aclname;
96 dns_view_t *view;
97
98 view = dns_zone_getview(zone);
99
100 switch (acltype) {
101 case allow_notify:
102 if (view != NULL) {
103 aclp = &view->notifyacl;
104 }
105 aclname = "allow-notify";
106 break;
107 case allow_query:
108 if (view != NULL) {
109 aclp = &view->queryacl;
110 }
111 aclname = "allow-query";
112 break;
113 case allow_query_on:
114 if (view != NULL) {
115 aclp = &view->queryonacl;
116 }
117 aclname = "allow-query-on";
118 break;
119 case allow_transfer:
120 if (view != NULL) {
121 aclp = &view->transferacl;
122 }
123 aclname = "allow-transfer";
124 break;
125 case allow_update:
126 if (view != NULL) {
127 aclp = &view->updateacl;
128 }
129 aclname = "allow-update";
130 break;
131 case allow_update_forwarding:
132 if (view != NULL) {
133 aclp = &view->upfwdacl;
134 }
135 aclname = "allow-update-forwarding";
136 break;
137 default:
138 UNREACHABLE();
139 }
140
141 /* First check to see if ACL is defined within the zone */
142 if (zconfig != NULL) {
143 maps[0] = cfg_tuple_get(zconfig, "options");
144 (void)named_config_get(maps, aclname, &aclobj);
145 if (aclobj != NULL) {
146 aclp = NULL;
147 goto parse_acl;
148 }
149 }
150
151 /* Failing that, see if there's a default ACL already in the view */
152 if (aclp != NULL && *aclp != NULL) {
153 (*setzacl)(zone, *aclp);
154 return (ISC_R_SUCCESS);
155 }
156
157 /* Check for default ACLs that haven't been parsed yet */
158 if (vconfig != NULL) {
159 const cfg_obj_t *options = cfg_tuple_get(vconfig, "options");
160 if (options != NULL) {
161 maps[i++] = options;
162 }
163 }
164 if (config != NULL) {
165 const cfg_obj_t *options = NULL;
166 (void)cfg_map_get(config, "options", &options);
167 if (options != NULL) {
168 maps[i++] = options;
169 }
170 }
171 maps[i++] = named_g_defaults;
172 maps[i] = NULL;
173
174 (void)named_config_get(maps, aclname, &aclobj);
175 if (aclobj == NULL) {
176 (*clearzacl)(zone);
177 return (ISC_R_SUCCESS);
178 }
179
180 parse_acl:
181 result = cfg_acl_fromconfig(aclobj, config, named_g_lctx, actx,
182 named_g_mctx, 0, &acl);
183 if (result != ISC_R_SUCCESS) {
184 return (result);
185 }
186 (*setzacl)(zone, acl);
187
188 /* Set the view default now */
189 if (aclp != NULL) {
190 dns_acl_attach(acl, aclp);
191 }
192
193 dns_acl_detach(&acl);
194 return (ISC_R_SUCCESS);
195 }
196
197 /*%
198 * Parse the zone update-policy statement.
199 */
200 static isc_result_t
201 configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
202 const char *zname) {
203 const cfg_obj_t *updatepolicy = NULL;
204 const cfg_listelt_t *element, *element2;
205 dns_ssutable_t *table = NULL;
206 isc_mem_t *mctx = dns_zone_getmctx(zone);
207 bool autoddns = false;
208 isc_result_t result;
209
210 (void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
211
212 if (updatepolicy == NULL) {
213 dns_zone_setssutable(zone, NULL);
214 return (ISC_R_SUCCESS);
215 }
216
217 if (cfg_obj_isstring(updatepolicy) &&
218 strcmp("local", cfg_obj_asstring(updatepolicy)) == 0)
219 {
220 autoddns = true;
221 updatepolicy = NULL;
222 }
223
224 result = dns_ssutable_create(mctx, &table);
225 if (result != ISC_R_SUCCESS) {
226 return (result);
227 }
228
229 for (element = cfg_list_first(updatepolicy); element != NULL;
230 element = cfg_list_next(element))
231 {
232 const cfg_obj_t *stmt = cfg_listelt_value(element);
233 const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
234 const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
235 const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
236 const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
237 const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
238 const char *str;
239 bool grant = false;
240 bool usezone = false;
241 dns_ssumatchtype_t mtype = dns_ssumatchtype_name;
242 dns_fixedname_t fname, fident;
243 isc_buffer_t b;
244 dns_rdatatype_t *types;
245 unsigned int i, n;
246
247 str = cfg_obj_asstring(mode);
248 if (strcasecmp(str, "grant") == 0) {
249 grant = true;
250 } else if (strcasecmp(str, "deny") == 0) {
251 grant = false;
252 } else {
253 UNREACHABLE();
254 }
255
256 str = cfg_obj_asstring(matchtype);
257 CHECK(dns_ssu_mtypefromstring(str, &mtype));
258 if (mtype == dns_ssumatchtype_subdomain &&
259 strcasecmp(str, "zonesub") == 0)
260 {
261 usezone = true;
262 }
263
264 dns_fixedname_init(&fident);
265 str = cfg_obj_asstring(identity);
266 isc_buffer_constinit(&b, str, strlen(str));
267 isc_buffer_add(&b, strlen(str));
268 result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
269 dns_rootname, 0, NULL);
270 if (result != ISC_R_SUCCESS) {
271 cfg_obj_log(identity, named_g_lctx, ISC_LOG_ERROR,
272 "'%s' is not a valid name", str);
273 goto cleanup;
274 }
275
276 dns_fixedname_init(&fname);
277 if (usezone) {
278 dns_name_copynf(dns_zone_getorigin(zone),
279 dns_fixedname_name(&fname));
280 } else {
281 str = cfg_obj_asstring(dname);
282 isc_buffer_constinit(&b, str, strlen(str));
283 isc_buffer_add(&b, strlen(str));
284 result = dns_name_fromtext(dns_fixedname_name(&fname),
285 &b, dns_rootname, 0, NULL);
286 if (result != ISC_R_SUCCESS) {
287 cfg_obj_log(identity, named_g_lctx,
288 ISC_LOG_ERROR,
289 "'%s' is not a valid name", str);
290 goto cleanup;
291 }
292 }
293
294 n = named_config_listcount(typelist);
295 if (n == 0) {
296 types = NULL;
297 } else {
298 types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
299 }
300
301 i = 0;
302 for (element2 = cfg_list_first(typelist); element2 != NULL;
303 element2 = cfg_list_next(element2))
304 {
305 const cfg_obj_t *typeobj;
306 isc_textregion_t r;
307
308 INSIST(i < n);
309
310 typeobj = cfg_listelt_value(element2);
311 str = cfg_obj_asstring(typeobj);
312 DE_CONST(str, r.base);
313 r.length = strlen(str);
314
315 result = dns_rdatatype_fromtext(&types[i++], &r);
316 if (result != ISC_R_SUCCESS) {
317 cfg_obj_log(identity, named_g_lctx,
318 ISC_LOG_ERROR,
319 "'%s' is not a valid type", str);
320 isc_mem_put(mctx, types,
321 n * sizeof(dns_rdatatype_t));
322 goto cleanup;
323 }
324 }
325 INSIST(i == n);
326
327 result = dns_ssutable_addrule(
328 table, grant, dns_fixedname_name(&fident), mtype,
329 dns_fixedname_name(&fname), n, types);
330 if (types != NULL) {
331 isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
332 }
333 if (result != ISC_R_SUCCESS) {
334 goto cleanup;
335 }
336 }
337
338 /*
339 * If "update-policy local;" and a session key exists,
340 * then use the default policy, which is equivalent to:
341 * update-policy { grant <session-keyname> zonesub any; };
342 */
343 if (autoddns) {
344 dns_rdatatype_t any = dns_rdatatype_any;
345
346 if (named_g_server->session_keyname == NULL) {
347 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
348 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
349 "failed to enable auto DDNS policy "
350 "for zone %s: session key not found",
351 zname);
352 result = ISC_R_NOTFOUND;
353 goto cleanup;
354 }
355
356 result = dns_ssutable_addrule(
357 table, true, named_g_server->session_keyname,
358 dns_ssumatchtype_local, dns_zone_getorigin(zone), 1,
359 &any);
360
361 if (result != ISC_R_SUCCESS) {
362 goto cleanup;
363 }
364 }
365
366 result = ISC_R_SUCCESS;
367 dns_zone_setssutable(zone, table);
368
369 cleanup:
370 dns_ssutable_detach(&table);
371 return (result);
372 }
373
374 /*
375 * This is the TTL used for internally generated RRsets for static-stub zones.
376 * The value doesn't matter because the mapping is static, but needs to be
377 * defined for the sake of implementation.
378 */
379 #define STATICSTUB_SERVER_TTL 86400
380
381 /*%
382 * Configure an apex NS with glues for a static-stub zone.
383 * For example, for the zone named "example.com", the following RRs will be
384 * added to the zone DB:
385 * example.com. NS example.com.
386 * example.com. A 192.0.2.1
387 * example.com. AAAA 2001:db8::1
388 */
389 static isc_result_t
390 configure_staticstub_serveraddrs(const cfg_obj_t *zconfig, dns_zone_t *zone,
391 dns_rdatalist_t *rdatalist_ns,
392 dns_rdatalist_t *rdatalist_a,
393 dns_rdatalist_t *rdatalist_aaaa) {
394 const cfg_listelt_t *element;
395 isc_mem_t *mctx = dns_zone_getmctx(zone);
396 isc_region_t region, sregion;
397 dns_rdata_t *rdata;
398 isc_result_t result = ISC_R_SUCCESS;
399
400 for (element = cfg_list_first(zconfig); element != NULL;
401 element = cfg_list_next(element))
402 {
403 const isc_sockaddr_t *sa;
404 isc_netaddr_t na;
405 const cfg_obj_t *address = cfg_listelt_value(element);
406 dns_rdatalist_t *rdatalist;
407
408 sa = cfg_obj_assockaddr(address);
409 if (isc_sockaddr_getport(sa) != 0) {
410 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
411 "port is not configurable for "
412 "static stub server-addresses");
413 return (ISC_R_FAILURE);
414 }
415 isc_netaddr_fromsockaddr(&na, sa);
416 if (isc_netaddr_getzone(&na) != 0) {
417 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
418 "scoped address is not allowed "
419 "for static stub "
420 "server-addresses");
421 return (ISC_R_FAILURE);
422 }
423
424 switch (na.family) {
425 case AF_INET:
426 region.length = sizeof(na.type.in);
427 rdatalist = rdatalist_a;
428 break;
429 default:
430 INSIST(na.family == AF_INET6);
431 region.length = sizeof(na.type.in6);
432 rdatalist = rdatalist_aaaa;
433 break;
434 }
435
436 rdata = isc_mem_get(mctx, sizeof(*rdata) + region.length);
437 region.base = (unsigned char *)(rdata + 1);
438 memmove(region.base, &na.type, region.length);
439 dns_rdata_init(rdata);
440 dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
441 rdatalist->type, ®ion);
442 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
443 }
444
445 /*
446 * If no address is specified (unlikely in this context, but possible),
447 * there's nothing to do anymore.
448 */
449 if (ISC_LIST_EMPTY(rdatalist_a->rdata) &&
450 ISC_LIST_EMPTY(rdatalist_aaaa->rdata))
451 {
452 return (ISC_R_SUCCESS);
453 }
454
455 /* Add to the list an apex NS with the ns name being the origin name */
456 dns_name_toregion(dns_zone_getorigin(zone), &sregion);
457 rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
458 region.length = sregion.length;
459 region.base = (unsigned char *)(rdata + 1);
460 memmove(region.base, sregion.base, region.length);
461 dns_rdata_init(rdata);
462 dns_rdata_fromregion(rdata, dns_zone_getclass(zone), dns_rdatatype_ns,
463 ®ion);
464 ISC_LIST_APPEND(rdatalist_ns->rdata, rdata, link);
465
466 return (result);
467 }
468
469 /*%
470 * Configure an apex NS with an out-of-zone NS names for a static-stub zone.
471 * For example, for the zone named "example.com", something like the following
472 * RRs will be added to the zone DB:
473 * example.com. NS ns.example.net.
474 */
475 static isc_result_t
476 configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
477 dns_rdatalist_t *rdatalist,
478 const char *zname) {
479 const cfg_listelt_t *element;
480 isc_mem_t *mctx = dns_zone_getmctx(zone);
481 dns_rdata_t *rdata;
482 isc_region_t sregion, region;
483 isc_result_t result = ISC_R_SUCCESS;
484
485 for (element = cfg_list_first(zconfig); element != NULL;
486 element = cfg_list_next(element))
487 {
488 const cfg_obj_t *obj;
489 const char *str;
490 dns_fixedname_t fixed_name;
491 dns_name_t *nsname;
492 isc_buffer_t b;
493
494 obj = cfg_listelt_value(element);
495 str = cfg_obj_asstring(obj);
496
497 nsname = dns_fixedname_initname(&fixed_name);
498
499 isc_buffer_constinit(&b, str, strlen(str));
500 isc_buffer_add(&b, strlen(str));
501 result = dns_name_fromtext(nsname, &b, dns_rootname, 0, NULL);
502 if (result != ISC_R_SUCCESS) {
503 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
504 "server-name '%s' is not a valid "
505 "name",
506 str);
507 return (result);
508 }
509 if (dns_name_issubdomain(nsname, dns_zone_getorigin(zone))) {
510 cfg_obj_log(zconfig, named_g_lctx, ISC_LOG_ERROR,
511 "server-name '%s' must not be a "
512 "subdomain of zone name '%s'",
513 str, zname);
514 return (ISC_R_FAILURE);
515 }
516
517 dns_name_toregion(nsname, &sregion);
518 rdata = isc_mem_get(mctx, sizeof(*rdata) + sregion.length);
519 region.length = sregion.length;
520 region.base = (unsigned char *)(rdata + 1);
521 memmove(region.base, sregion.base, region.length);
522 dns_rdata_init(rdata);
523 dns_rdata_fromregion(rdata, dns_zone_getclass(zone),
524 dns_rdatatype_ns, ®ion);
525 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
526 }
527
528 return (result);
529 }
530
531 /*%
532 * Configure static-stub zone.
533 */
534 static isc_result_t
535 configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
536 const char *zname, const char *dbtype) {
537 int i = 0;
538 const cfg_obj_t *obj;
539 isc_mem_t *mctx = dns_zone_getmctx(zone);
540 dns_db_t *db = NULL;
541 dns_dbversion_t *dbversion = NULL;
542 dns_dbnode_t *apexnode = NULL;
543 dns_name_t apexname;
544 isc_result_t result;
545 dns_rdataset_t rdataset;
546 dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa;
547 dns_rdatalist_t *rdatalists[] = { &rdatalist_ns, &rdatalist_a,
548 &rdatalist_aaaa, NULL };
549 dns_rdata_t *rdata;
550 isc_region_t region;
551
552 /* Create the DB beforehand */
553 RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone),
554 dns_dbtype_stub, dns_zone_getclass(zone), 0, NULL,
555 &db));
556
557 dns_rdataset_init(&rdataset);
558
559 dns_rdatalist_init(&rdatalist_ns);
560 rdatalist_ns.rdclass = dns_zone_getclass(zone);
561 rdatalist_ns.type = dns_rdatatype_ns;
562 rdatalist_ns.ttl = STATICSTUB_SERVER_TTL;
563
564 dns_rdatalist_init(&rdatalist_a);
565 rdatalist_a.rdclass = dns_zone_getclass(zone);
566 rdatalist_a.type = dns_rdatatype_a;
567 rdatalist_a.ttl = STATICSTUB_SERVER_TTL;
568
569 dns_rdatalist_init(&rdatalist_aaaa);
570 rdatalist_aaaa.rdclass = dns_zone_getclass(zone);
571 rdatalist_aaaa.type = dns_rdatatype_aaaa;
572 rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL;
573
574 /* Prepare zone RRs from the configuration */
575 obj = NULL;
576 result = cfg_map_get(zconfig, "server-addresses", &obj);
577 if (result == ISC_R_SUCCESS) {
578 INSIST(obj != NULL);
579 CHECK(configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns,
580 &rdatalist_a,
581 &rdatalist_aaaa));
582 }
583
584 obj = NULL;
585 result = cfg_map_get(zconfig, "server-names", &obj);
586 if (result == ISC_R_SUCCESS) {
587 INSIST(obj != NULL);
588 CHECK(configure_staticstub_servernames(obj, zone, &rdatalist_ns,
589 zname));
590 }
591
592 /*
593 * Sanity check: there should be at least one NS RR at the zone apex
594 * to trigger delegation.
595 */
596 if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) {
597 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
598 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
599 "No NS record is configured for a "
600 "static-stub zone '%s'",
601 zname);
602 result = ISC_R_FAILURE;
603 goto cleanup;
604 }
605
606 /*
607 * Now add NS and glue A/AAAA RRsets to the zone DB.
608 * First open a new version for the add operation and get a pointer
609 * to the apex node (all RRs are of the apex name).
610 */
611 CHECK(dns_db_newversion(db, &dbversion));
612
613 dns_name_init(&apexname, NULL);
614 dns_name_clone(dns_zone_getorigin(zone), &apexname);
615 CHECK(dns_db_findnode(db, &apexname, false, &apexnode));
616
617 /* Add NS RRset */
618 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset) ==
619 ISC_R_SUCCESS);
620 CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset, 0,
621 NULL));
622 dns_rdataset_disassociate(&rdataset);
623
624 /* Add glue A RRset, if any */
625 if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
626 RUNTIME_CHECK(
627 dns_rdatalist_tordataset(&rdatalist_a, &rdataset) ==
628 ISC_R_SUCCESS);
629 CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
630 0, NULL));
631 dns_rdataset_disassociate(&rdataset);
632 }
633
634 /* Add glue AAAA RRset, if any */
635 if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
636 RUNTIME_CHECK(
637 dns_rdatalist_tordataset(&rdatalist_aaaa, &rdataset) ==
638 ISC_R_SUCCESS);
639 CHECK(dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
640 0, NULL));
641 dns_rdataset_disassociate(&rdataset);
642 }
643
644 dns_db_closeversion(db, &dbversion, true);
645 dns_zone_setdb(zone, db);
646
647 result = ISC_R_SUCCESS;
648
649 cleanup:
650 if (dns_rdataset_isassociated(&rdataset)) {
651 dns_rdataset_disassociate(&rdataset);
652 }
653 if (apexnode != NULL) {
654 dns_db_detachnode(db, &apexnode);
655 }
656 if (dbversion != NULL) {
657 dns_db_closeversion(db, &dbversion, false);
658 }
659 if (db != NULL) {
660 dns_db_detach(&db);
661 }
662 for (i = 0; rdatalists[i] != NULL; i++) {
663 while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) {
664 ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link);
665 dns_rdata_toregion(rdata, ®ion);
666 isc_mem_put(mctx, rdata,
667 sizeof(*rdata) + region.length);
668 }
669 }
670
671 INSIST(dbversion == NULL);
672
673 return (result);
674 }
675
676 /*%
677 * Convert a config file zone type into a server zone type.
678 */
679 static dns_zonetype_t
680 zonetype_fromconfig(const cfg_obj_t *map) {
681 const cfg_obj_t *obj = NULL;
682 isc_result_t result;
683
684 result = cfg_map_get(map, "type", &obj);
685 INSIST(result == ISC_R_SUCCESS && obj != NULL);
686 return (named_config_getzonetype(obj));
687 }
688
689 /*%
690 * Helper function for strtoargv(). Pardon the gratuitous recursion.
691 */
692 static isc_result_t
693 strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp,
694 unsigned int n) {
695 isc_result_t result;
696
697 /* Discard leading whitespace. */
698 while (*s == ' ' || *s == '\t') {
699 s++;
700 }
701
702 if (*s == '\0') {
703 /* We have reached the end of the string. */
704 *argcp = n;
705 *argvp = isc_mem_get(mctx, n * sizeof(char *));
706 } else {
707 char *p = s;
708 while (*p != ' ' && *p != '\t' && *p != '\0') {
709 p++;
710 }
711 if (*p != '\0') {
712 *p++ = '\0';
713 }
714
715 result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
716 if (result != ISC_R_SUCCESS) {
717 return (result);
718 }
719 (*argvp)[n] = s;
720 }
721 return (ISC_R_SUCCESS);
722 }
723
724 /*%
725 * Tokenize the string "s" into whitespace-separated words,
726 * return the number of words in '*argcp' and an array
727 * of pointers to the words in '*argvp'. The caller
728 * must free the array using isc_mem_put(). The string
729 * is modified in-place.
730 */
731 static isc_result_t
732 strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
733 return (strtoargvsub(mctx, s, argcp, argvp, 0));
734 }
735
736 static const char *const primary_synonyms[] = { "primary", "master", NULL };
737
738 static const char *const secondary_synonyms[] = { "secondary", "slave", NULL };
739
740 static void
741 checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
742 const cfg_obj_t **objp) {
743 isc_result_t result;
744
745 switch (ztype) {
746 case dns_zone_secondary:
747 case dns_zone_mirror:
748 result = named_checknames_get(maps, secondary_synonyms, objp);
749 break;
750 case dns_zone_primary:
751 result = named_checknames_get(maps, primary_synonyms, objp);
752 break;
753 default:
754 UNREACHABLE();
755 }
756
757 INSIST(result == ISC_R_SUCCESS && objp != NULL && *objp != NULL);
758 }
759
760 /*
761 * Callback to see if a non-recursive query coming from 'srcaddr' to
762 * 'destaddr', with optional key 'mykey' for class 'rdclass' would be
763 * delivered to 'myview'.
764 *
765 * We run this unlocked as both the view list and the interface list
766 * are updated when the appropriate task has exclusivity.
767 */
768 static bool
769 isself(dns_view_t *myview, dns_tsigkey_t *mykey, const isc_sockaddr_t *srcaddr,
770 const isc_sockaddr_t *dstaddr, dns_rdataclass_t rdclass, void *arg) {
771 ns_interfacemgr_t *interfacemgr = (ns_interfacemgr_t *)arg;
772 dns_aclenv_t *env = ns_interfacemgr_getaclenv(interfacemgr);
773 dns_view_t *view;
774 dns_tsigkey_t *key = NULL;
775 isc_netaddr_t netsrc;
776 isc_netaddr_t netdst;
777
778 if (interfacemgr == NULL) {
779 return (true);
780 }
781
782 if (!ns_interfacemgr_listeningon(interfacemgr, dstaddr)) {
783 return (false);
784 }
785
786 isc_netaddr_fromsockaddr(&netsrc, srcaddr);
787 isc_netaddr_fromsockaddr(&netdst, dstaddr);
788
789 for (view = ISC_LIST_HEAD(named_g_server->viewlist); view != NULL;
790 view = ISC_LIST_NEXT(view, link))
791 {
792 const dns_name_t *tsig = NULL;
793
794 if (view->matchrecursiveonly) {
795 continue;
796 }
797
798 if (rdclass != view->rdclass) {
799 continue;
800 }
801
802 if (mykey != NULL) {
803 bool match;
804 isc_result_t result;
805
806 result = dns_view_gettsig(view, &mykey->name, &key);
807 if (result != ISC_R_SUCCESS) {
808 continue;
809 }
810 match = dst_key_compare(mykey->key, key->key);
811 dns_tsigkey_detach(&key);
812 if (!match) {
813 continue;
814 }
815 tsig = dns_tsigkey_identity(mykey);
816 }
817
818 if (dns_acl_allowed(&netsrc, tsig, view->matchclients, env) &&
819 dns_acl_allowed(&netdst, tsig, view->matchdestinations,
820 env))
821 {
822 break;
823 }
824 }
825 return (view == myview);
826 }
827
828 /*%
829 * For mirror zones, change "notify yes;" to "notify explicit;", informing the
830 * user only if "notify" was explicitly configured rather than inherited from
831 * default configuration.
832 */
833 static dns_notifytype_t
834 process_notifytype(dns_notifytype_t ntype, dns_zonetype_t ztype,
835 const char *zname, const cfg_obj_t **maps) {
836 const cfg_obj_t *obj = NULL;
837
838 /*
839 * Return the original setting if this is not a mirror zone or if the
840 * zone is configured with something else than "notify yes;".
841 */
842 if (ztype != dns_zone_mirror || ntype != dns_notifytype_yes) {
843 return (ntype);
844 }
845
846 /*
847 * Only log a message if "notify" was set in the configuration
848 * hierarchy supplied in 'maps'.
849 */
850 if (named_config_get(maps, "notify", &obj) == ISC_R_SUCCESS) {
851 cfg_obj_log(obj, named_g_lctx, ISC_LOG_INFO,
852 "'notify explicit;' will be used for mirror zone "
853 "'%s'",
854 zname);
855 }
856
857 return (dns_notifytype_explicit);
858 }
859
860 isc_result_t
861 named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
862 const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
863 dns_kasplist_t *kasplist, dns_zone_t *zone,
864 dns_zone_t *raw) {
865 isc_result_t result;
866 const char *zname;
867 dns_rdataclass_t zclass;
868 dns_rdataclass_t vclass;
869 const cfg_obj_t *maps[5];
870 const cfg_obj_t *nodefault[4];
871 const cfg_obj_t *zoptions = NULL;
872 const cfg_obj_t *options = NULL;
873 const cfg_obj_t *obj;
874 const char *filename = NULL;
875 const char *kaspname = NULL;
876 const char *dupcheck;
877 dns_notifytype_t notifytype = dns_notifytype_yes;
878 uint32_t count;
879 unsigned int dbargc;
880 char **dbargv;
881 static char default_dbtype[] = "rbt";
882 static char dlz_dbtype[] = "dlz";
883 char *cpval = default_dbtype;
884 isc_mem_t *mctx = dns_zone_getmctx(zone);
885 dns_dialuptype_t dialup = dns_dialuptype_no;
886 dns_zonetype_t ztype;
887 int i;
888 int32_t journal_size;
889 bool multi;
890 bool alt;
891 dns_view_t *view = NULL;
892 dns_kasp_t *kasp = NULL;
893 bool check = false, fail = false;
894 bool warn = false, ignore = false;
895 bool ixfrdiff;
896 bool use_kasp = false;
897 dns_masterformat_t masterformat;
898 const dns_master_style_t *masterstyle = &dns_master_style_default;
899 isc_stats_t *zoneqrystats;
900 dns_stats_t *rcvquerystats;
901 dns_stats_t *dnssecsignstats;
902 dns_zonestat_level_t statlevel = dns_zonestat_none;
903 int seconds;
904 dns_ttl_t maxttl = 0; /* unlimited */
905 dns_zone_t *mayberaw = (raw != NULL) ? raw : zone;
906 isc_dscp_t dscp;
907
908 i = 0;
909 if (zconfig != NULL) {
910 zoptions = cfg_tuple_get(zconfig, "options");
911 nodefault[i] = maps[i] = zoptions;
912 i++;
913 }
914 if (vconfig != NULL) {
915 nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options");
916 i++;
917 }
918 if (config != NULL) {
919 (void)cfg_map_get(config, "options", &options);
920 if (options != NULL) {
921 nodefault[i] = maps[i] = options;
922 i++;
923 }
924 }
925 nodefault[i] = NULL;
926 maps[i++] = named_g_defaults;
927 maps[i] = NULL;
928
929 if (vconfig != NULL) {
930 RETERR(named_config_getclass(cfg_tuple_get(vconfig, "class"),
931 dns_rdataclass_in, &vclass));
932 } else {
933 vclass = dns_rdataclass_in;
934 }
935
936 /*
937 * Configure values common to all zone types.
938 */
939
940 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
941
942 RETERR(named_config_getclass(cfg_tuple_get(zconfig, "class"), vclass,
943 &zclass));
944 dns_zone_setclass(zone, zclass);
945 if (raw != NULL) {
946 dns_zone_setclass(raw, zclass);
947 }
948
949 ztype = zonetype_fromconfig(zoptions);
950 if (raw != NULL) {
951 dns_zone_settype(raw, ztype);
952 dns_zone_settype(zone, dns_zone_primary);
953 } else {
954 dns_zone_settype(zone, ztype);
955 }
956
957 obj = NULL;
958 result = cfg_map_get(zoptions, "database", &obj);
959 if (result == ISC_R_SUCCESS) {
960 cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
961 }
962 if (cpval == NULL) {
963 return (ISC_R_NOMEMORY);
964 }
965
966 obj = NULL;
967 result = cfg_map_get(zoptions, "dlz", &obj);
968 if (result == ISC_R_SUCCESS) {
969 const char *dlzname = cfg_obj_asstring(obj);
970 size_t len;
971
972 if (cpval != default_dbtype) {
973 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
974 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
975 "zone '%s': both 'database' and 'dlz' "
976 "specified",
977 zname);
978 return (ISC_R_FAILURE);
979 }
980
981 len = strlen(dlzname) + 5;
982 cpval = isc_mem_allocate(mctx, len);
983 snprintf(cpval, len, "dlz %s", dlzname);
984 }
985
986 result = strtoargv(mctx, cpval, &dbargc, &dbargv);
987 if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
988 isc_mem_free(mctx, cpval);
989 return (result);
990 }
991
992 /*
993 * ANSI C is strange here. There is no logical reason why (char **)
994 * cannot be promoted automatically to (const char * const *) by the
995 * compiler w/o generating a warning.
996 */
997 dns_zone_setdbtype(zone, dbargc, (const char *const *)dbargv);
998 isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
999 if (cpval != default_dbtype && cpval != dlz_dbtype) {
1000 isc_mem_free(mctx, cpval);
1001 }
1002
1003 obj = NULL;
1004 result = cfg_map_get(zoptions, "file", &obj);
1005 if (result == ISC_R_SUCCESS) {
1006 filename = cfg_obj_asstring(obj);
1007 }
1008
1009 /*
1010 * Unless we're using some alternative database, a master zone
1011 * will be needing a master file.
1012 */
1013 if (ztype == dns_zone_primary && cpval == default_dbtype &&
1014 filename == NULL)
1015 {
1016 isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
1017 NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
1018 "zone '%s': 'file' not specified", zname);
1019 return (ISC_R_FAILURE);
1020 }
1021
1022 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
1023 masterformat = dns_masterformat_raw;
1024 } else {
1025 masterformat = dns_masterformat_text;
1026 }
1027 obj = NULL;
1028 result = named_config_get(maps, "masterfile-format", &obj);
1029 if (result == ISC_R_SUCCESS) {
1030 const char *masterformatstr = cfg_obj_asstring(obj);
1031
1032 if (strcasecmp(masterformatstr, "text") == 0) {
1033 masterformat = dns_masterformat_text;
1034 } else if (strcasecmp(masterformatstr, "raw") == 0) {
1035 masterformat = dns_masterformat_raw;
1036 } else if (strcasecmp(masterformatstr, "map") == 0) {
1037 masterformat = dns_masterformat_map;
1038 cfg_obj_log(obj, named_g_lctx, ISC_LOG_WARNING,
1039 "masterfile-format: format 'map' is "
1040 "deprecated");
1041 } else {
1042 UNREACHABLE();
1043 }
1044 }
1045
1046 obj = NULL;
1047 result = named_config_get(maps, "masterfile-style", &obj);
1048 if (result == ISC_R_SUCCESS) {
1049 const char *masterstylestr = cfg_obj_asstring(obj);
1050
1051 if (masterformat != dns_masterformat_text) {
1052 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
1053 "zone '%s': 'masterfile-style' "
1054 "can only be used with "
1055 "'masterfile-format text'",
1056 zname);
1057 return (ISC_R_FAILURE);
1058 }
1059
1060 if (strcasecmp(masterstylestr, "full") == 0) {
1061 masterstyle = &dns_master_style_full;
1062 } else if (strcasecmp(masterstylestr, "relative") == 0) {
1063 masterstyle = &dns_master_style_default;
1064 } else {
1065 UNREACHABLE();
1066 }
1067 }
1068
1069 obj = NULL;
1070 result = named_config_get(maps, "max-records", &obj);
1071 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1072 dns_zone_setmaxrecords(mayberaw, cfg_obj_asuint32(obj));
1073 if (zone != mayberaw) {
1074 dns_zone_setmaxrecords(zone, 0);
1075 }
1076
1077 if (raw != NULL && filename != NULL) {
1078 #define SIGNED ".signed"
1079 size_t signedlen = strlen(filename) + sizeof(SIGNED);
1080 char *signedname;
1081
1082 RETERR(dns_zone_setfile(raw, filename, masterformat,
1083 masterstyle));
1084 signedname = isc_mem_get(mctx, signedlen);
1085
1086 (void)snprintf(signedname, signedlen, "%s" SIGNED, filename);
1087 result = dns_zone_setfile(zone, signedname,
1088 dns_masterformat_raw, NULL);
1089 isc_mem_put(mctx, signedname, signedlen);
1090 if (result != ISC_R_SUCCESS) {
1091 return (result);
1092 }
1093 } else {
1094 RETERR(dns_zone_setfile(zone, filename, masterformat,
1095 masterstyle));
1096 }
1097
1098 obj = NULL;
1099 result = cfg_map_get(zoptions, "journal", &obj);
1100 if (result == ISC_R_SUCCESS) {
1101 RETERR(dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj)));
1102 }
1103
1104 /*
1105 * Notify messages are processed by the raw zone if it exists.
1106 */
1107 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
1108 RETERR(configure_zone_acl(
1109 zconfig, vconfig, config, allow_notify, ac, mayberaw,
1110 dns_zone_setnotifyacl, dns_zone_clearnotifyacl));
1111 }
1112
1113 /*
1114 * XXXAG This probably does not make sense for stubs.
1115 */
1116 RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query, ac,
1117 zone, dns_zone_setqueryacl,
1118 dns_zone_clearqueryacl));
1119
1120 RETERR(configure_zone_acl(zconfig, vconfig, config, allow_query_on, ac,
1121 zone, dns_zone_setqueryonacl,
1122 dns_zone_clearqueryonacl));
1123
1124 obj = NULL;
1125 result = named_config_get(maps, "dialup", &obj);
1126 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1127 if (cfg_obj_isboolean(obj)) {
1128 if (cfg_obj_asboolean(obj)) {
1129 dialup = dns_dialuptype_yes;
1130 } else {
1131 dialup = dns_dialuptype_no;
1132 }
1133 } else {
1134 const char *dialupstr = cfg_obj_asstring(obj);
1135 if (strcasecmp(dialupstr, "notify") == 0) {
1136 dialup = dns_dialuptype_notify;
1137 } else if (strcasecmp(dialupstr, "notify-passive") == 0) {
1138 dialup = dns_dialuptype_notifypassive;
1139 } else if (strcasecmp(dialupstr, "refresh") == 0) {
1140 dialup = dns_dialuptype_refresh;
1141 } else if (strcasecmp(dialupstr, "passive") == 0) {
1142 dialup = dns_dialuptype_passive;
1143 } else {
1144 UNREACHABLE();
1145 }
1146 }
1147 if (raw != NULL) {
1148 dns_zone_setdialup(raw, dialup);
1149 }
1150 dns_zone_setdialup(zone, dialup);
1151
1152 obj = NULL;
1153 result = named_config_get(maps, "zone-statistics", &obj);
1154 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1155 if (cfg_obj_isboolean(obj)) {
1156 if (cfg_obj_asboolean(obj)) {
1157 statlevel = dns_zonestat_full;
1158 } else {
1159 statlevel = dns_zonestat_none;
1160 }
1161 } else {
1162 const char *levelstr = cfg_obj_asstring(obj);
1163 if (strcasecmp(levelstr, "full") == 0) {
1164 statlevel = dns_zonestat_full;
1165 } else if (strcasecmp(levelstr, "terse") == 0) {
1166 statlevel = dns_zonestat_terse;
1167 } else if (strcasecmp(levelstr, "none") == 0) {
1168 statlevel = dns_zonestat_none;
1169 } else {
1170 UNREACHABLE();
1171 }
1172 }
1173 dns_zone_setstatlevel(zone, statlevel);
1174
1175 zoneqrystats = NULL;
1176 rcvquerystats = NULL;
1177 dnssecsignstats = NULL;
1178 if (statlevel == dns_zonestat_full) {
1179 RETERR(isc_stats_create(mctx, &zoneqrystats,
1180 ns_statscounter_max));
1181 RETERR(dns_rdatatypestats_create(mctx, &rcvquerystats));
1182 RETERR(dns_dnssecsignstats_create(mctx, &dnssecsignstats));
1183 }
1184 dns_zone_setrequeststats(zone, zoneqrystats);
1185 dns_zone_setrcvquerystats(zone, rcvquerystats);
1186 dns_zone_setdnssecsignstats(zone, dnssecsignstats);
1187
1188 if (zoneqrystats != NULL) {
1189 isc_stats_detach(&zoneqrystats);
1190 }
1191
1192 if (rcvquerystats != NULL) {
1193 dns_stats_detach(&rcvquerystats);
1194 }
1195
1196 if (dnssecsignstats != NULL) {
1197 dns_stats_detach(&dnssecsignstats);
1198 }
1199
1200 /*
1201 * Configure master functionality. This applies
1202 * to primary servers (type "primary") and secondaries
1203 * acting as primaries (type "secondary"), but not to stubs.
1204 */
1205 if (ztype != dns_zone_stub && ztype != dns_zone_staticstub &&
1206 ztype != dns_zone_redirect)
1207 {
1208 obj = NULL;
1209 result = named_config_get(maps, "dnssec-policy", &obj);
1210 if (result == ISC_R_SUCCESS) {
1211 kaspname = cfg_obj_asstring(obj);
1212 if (strcmp(kaspname, "none") != 0) {
1213 result = dns_kasplist_find(kasplist, kaspname,
1214 &kasp);
1215 if (result != ISC_R_SUCCESS) {
1216 cfg_obj_log(
1217 obj, named_g_lctx,
1218 ISC_LOG_ERROR,
1219 "dnssec-policy '%s' not found ",
1220 kaspname);
1221 RETERR(result);
1222 }
1223 dns_zone_setkasp(zone, kasp);
1224 use_kasp = true;
1225 }
1226 }
1227 if (!use_kasp) {
1228 dns_zone_setkasp(zone, NULL);
1229 }
1230
1231 obj = NULL;
1232 result = named_config_get(maps, "notify", &obj);
1233 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1234 if (cfg_obj_isboolean(obj)) {
1235 if (cfg_obj_asboolean(obj)) {
1236 notifytype = dns_notifytype_yes;
1237 } else {
1238 notifytype = dns_notifytype_no;
1239 }
1240 } else {
1241 const char *str = cfg_obj_asstring(obj);
1242 if (strcasecmp(str, "explicit") == 0) {
1243 notifytype = dns_notifytype_explicit;
1244 } else if (strcasecmp(str, "master-only") == 0 ||
1245 strcasecmp(str, "primary-only") == 0)
1246 {
1247 notifytype = dns_notifytype_masteronly;
1248 } else {
1249 UNREACHABLE();
1250 }
1251 }
1252 notifytype = process_notifytype(notifytype, ztype, zname,
1253 nodefault);
1254 if (raw != NULL) {
1255 dns_zone_setnotifytype(raw, dns_notifytype_no);
1256 }
1257 dns_zone_setnotifytype(zone, notifytype);
1258
1259 obj = NULL;
1260 result = named_config_get(maps, "also-notify", &obj);
1261 if (result == ISC_R_SUCCESS &&
1262 (notifytype == dns_notifytype_yes ||
1263 notifytype == dns_notifytype_explicit ||
1264 (notifytype == dns_notifytype_masteronly &&
1265 ztype == dns_zone_primary)))
1266 {
1267 dns_ipkeylist_t ipkl;
1268 dns_ipkeylist_init(&ipkl);
1269
1270 RETERR(named_config_getipandkeylist(config, "primaries",
1271 obj, mctx, &ipkl));
1272 result = dns_zone_setalsonotifydscpkeys(
1273 zone, ipkl.addrs, ipkl.dscps, ipkl.keys,
1274 ipkl.count);
1275 dns_ipkeylist_clear(mctx, &ipkl);
1276 RETERR(result);
1277 } else {
1278 RETERR(dns_zone_setalsonotify(zone, NULL, 0));
1279 }
1280
1281 obj = NULL;
1282 result = named_config_get(maps, "parental-source", &obj);
1283 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1284 RETERR(dns_zone_setparentalsrc4(zone, cfg_obj_assockaddr(obj)));
1285 dscp = cfg_obj_getdscp(obj);
1286 if (dscp == -1) {
1287 dscp = named_g_dscp;
1288 }
1289 RETERR(dns_zone_setparentalsrc4dscp(zone, dscp));
1290 named_add_reserved_dispatch(named_g_server,
1291 cfg_obj_assockaddr(obj));
1292
1293 obj = NULL;
1294 result = named_config_get(maps, "parental-source-v6", &obj);
1295 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1296 RETERR(dns_zone_setparentalsrc6(zone, cfg_obj_assockaddr(obj)));
1297 dscp = cfg_obj_getdscp(obj);
1298 if (dscp == -1) {
1299 dscp = named_g_dscp;
1300 }
1301 RETERR(dns_zone_setparentalsrc6dscp(zone, dscp));
1302 named_add_reserved_dispatch(named_g_server,
1303 cfg_obj_assockaddr(obj));
1304
1305 obj = NULL;
1306 result = named_config_get(maps, "notify-source", &obj);
1307 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1308 RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
1309 dscp = cfg_obj_getdscp(obj);
1310 if (dscp == -1) {
1311 dscp = named_g_dscp;
1312 }
1313 RETERR(dns_zone_setnotifysrc4dscp(zone, dscp));
1314 named_add_reserved_dispatch(named_g_server,
1315 cfg_obj_assockaddr(obj));
1316
1317 obj = NULL;
1318 result = named_config_get(maps, "notify-source-v6", &obj);
1319 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1320 RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
1321 dscp = cfg_obj_getdscp(obj);
1322 if (dscp == -1) {
1323 dscp = named_g_dscp;
1324 }
1325 RETERR(dns_zone_setnotifysrc6dscp(zone, dscp));
1326 named_add_reserved_dispatch(named_g_server,
1327 cfg_obj_assockaddr(obj));
1328
1329 obj = NULL;
1330 result = named_config_get(maps, "notify-to-soa", &obj);
1331 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1332 dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
1333 cfg_obj_asboolean(obj));
1334
1335 dns_zone_setisself(zone, isself, named_g_server->interfacemgr);
1336
1337 RETERR(configure_zone_acl(
1338 zconfig, vconfig, config, allow_transfer, ac, zone,
1339 dns_zone_setxfracl, dns_zone_clearxfracl));
1340
1341 obj = NULL;
1342 result = named_config_get(maps, "max-transfer-time-out", &obj);
1343 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1344 dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
1345
1346 obj = NULL;
1347 result = named_config_get(maps, "max-transfer-idle-out", &obj);
1348 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1349 dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
1350
1351 obj = NULL;
1352 result = named_config_get(maps, "max-journal-size", &obj);
1353 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1354 if (raw != NULL) {
1355 dns_zone_setjournalsize(raw, -1);
1356 }
1357 dns_zone_setjournalsize(zone, -1);
1358 if (cfg_obj_isstring(obj)) {
1359 const char *str = cfg_obj_asstring(obj);
1360 if (strcasecmp(str, "unlimited") == 0) {
1361 journal_size = DNS_JOURNAL_SIZE_MAX;
1362 } else {
1363 INSIST(strcasecmp(str, "default") == 0);
1364 journal_size = -1;
1365 }
1366 } else {
1367 isc_resourcevalue_t value;
1368 value = cfg_obj_asuint64(obj);
1369 if (value > DNS_JOURNAL_SIZE_MAX) {
1370 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
1371 "'max-journal-size "
1372 "%" PRId64 "' "
1373 "is too large",
1374 value);
1375 RETERR(ISC_R_RANGE);
1376 }
1377 journal_size = (uint32_t)value;
1378 }
1379 if (raw != NULL) {
1380 dns_zone_setjournalsize(raw, journal_size);
1381 }
1382 dns_zone_setjournalsize(zone, journal_size);
1383
1384 obj = NULL;
1385 result = named_config_get(maps, "ixfr-from-differences", &obj);
1386 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1387 if (cfg_obj_isboolean(obj)) {
1388 ixfrdiff = cfg_obj_asboolean(obj);
1389 } else if ((strcasecmp(cfg_obj_asstring(obj), "primary") == 0 ||
1390 strcasecmp(cfg_obj_asstring(obj), "master") == 0) &&
1391 ztype == dns_zone_primary)
1392 {
1393 ixfrdiff = true;
1394 } else if ((strcasecmp(cfg_obj_asstring(obj), "secondary") ==
1395 0 ||
1396 strcasecmp(cfg_obj_asstring(obj), "slave") == 0) &&
1397 ztype == dns_zone_secondary)
1398 {
1399 ixfrdiff = true;
1400 } else {
1401 ixfrdiff = false;
1402 }
1403 if (raw != NULL) {
1404 dns_zone_setoption(raw, DNS_ZONEOPT_IXFRFROMDIFFS,
1405 true);
1406 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
1407 false);
1408 } else {
1409 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS,
1410 ixfrdiff);
1411 }
1412
1413 obj = NULL;
1414 result = named_config_get(maps, "max-ixfr-ratio", &obj);
1415 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1416 if (cfg_obj_isstring(obj)) {
1417 dns_zone_setixfrratio(zone, 0);
1418 } else {
1419 dns_zone_setixfrratio(zone, cfg_obj_aspercentage(obj));
1420 }
1421
1422 obj = NULL;
1423 result = named_config_get(maps, "request-expire", &obj);
1424 INSIST(result == ISC_R_SUCCESS);
1425 dns_zone_setrequestexpire(zone, cfg_obj_asboolean(obj));
1426
1427 obj = NULL;
1428 result = named_config_get(maps, "request-ixfr", &obj);
1429 INSIST(result == ISC_R_SUCCESS);
1430 dns_zone_setrequestixfr(zone, cfg_obj_asboolean(obj));
1431
1432 obj = NULL;
1433 checknames(ztype, maps, &obj);
1434 INSIST(obj != NULL);
1435 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1436 fail = false;
1437 check = true;
1438 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1439 fail = check = true;
1440 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1441 fail = check = false;
1442 } else {
1443 UNREACHABLE();
1444 }
1445 if (raw != NULL) {
1446 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMES, check);
1447 dns_zone_setoption(raw, DNS_ZONEOPT_CHECKNAMESFAIL,
1448 fail);
1449 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, false);
1450 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
1451 false);
1452 } else {
1453 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check);
1454 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL,
1455 fail);
1456 }
1457
1458 obj = NULL;
1459 result = named_config_get(maps, "notify-delay", &obj);
1460 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1461 dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
1462
1463 obj = NULL;
1464 result = named_config_get(maps, "check-sibling", &obj);
1465 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1466 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
1467 cfg_obj_asboolean(obj));
1468
1469 obj = NULL;
1470 result = named_config_get(maps, "check-spf", &obj);
1471 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1472 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1473 check = true;
1474 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1475 check = false;
1476 } else {
1477 UNREACHABLE();
1478 }
1479 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSPF, check);
1480
1481 obj = NULL;
1482 result = named_config_get(maps, "zero-no-soa-ttl", &obj);
1483 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1484 dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));
1485
1486 obj = NULL;
1487 result = named_config_get(maps, "nsec3-test-zone", &obj);
1488 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1489 dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
1490 cfg_obj_asboolean(obj));
1491 } else if (ztype == dns_zone_redirect) {
1492 dns_zone_setnotifytype(zone, dns_notifytype_no);
1493
1494 obj = NULL;
1495 result = named_config_get(maps, "max-journal-size", &obj);
1496 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1497 dns_zone_setjournalsize(zone, -1);
1498 if (cfg_obj_isstring(obj)) {
1499 const char *str = cfg_obj_asstring(obj);
1500 if (strcasecmp(str, "unlimited") == 0) {
1501 journal_size = DNS_JOURNAL_SIZE_MAX;
1502 } else {
1503 INSIST(strcasecmp(str, "default") == 0);
1504 journal_size = -1;
1505 }
1506 } else {
1507 isc_resourcevalue_t value;
1508 value = cfg_obj_asuint64(obj);
1509 if (value > DNS_JOURNAL_SIZE_MAX) {
1510 cfg_obj_log(obj, named_g_lctx, ISC_LOG_ERROR,
1511 "'max-journal-size "
1512 "%" PRId64 "' "
1513 "is too large",
1514 value);
1515 RETERR(ISC_R_RANGE);
1516 }
1517 journal_size = (uint32_t)value;
1518 }
1519 dns_zone_setjournalsize(zone, journal_size);
1520 }
1521
1522 if (use_kasp) {
1523 maxttl = dns_kasp_zonemaxttl(dns_zone_getkasp(zone));
1524 } else {
1525 obj = NULL;
1526 result = named_config_get(maps, "max-zone-ttl", &obj);
1527 if (result == ISC_R_SUCCESS) {
1528 if (cfg_obj_isduration(obj)) {
1529 maxttl = cfg_obj_asduration(obj);
1530 }
1531 }
1532 }
1533 dns_zone_setmaxttl(zone, maxttl);
1534 if (raw != NULL) {
1535 dns_zone_setmaxttl(raw, maxttl);
1536 }
1537
1538 /*
1539 * Configure update-related options. These apply to
1540 * primary servers only.
1541 */
1542 if (ztype == dns_zone_primary) {
1543 dns_acl_t *updateacl;
1544
1545 RETERR(configure_zone_acl(
1546 zconfig, vconfig, config, allow_update, ac, mayberaw,
1547 dns_zone_setupdateacl, dns_zone_clearupdateacl));
1548
1549 updateacl = dns_zone_getupdateacl(mayberaw);
1550 if (updateacl != NULL && dns_acl_isinsecure(updateacl)) {
1551 isc_log_write(named_g_lctx, DNS_LOGCATEGORY_SECURITY,
1552 NAMED_LOGMODULE_SERVER, ISC_LOG_WARNING,
1553 "zone '%s' allows unsigned updates "
1554 "from remote hosts, which is insecure",
1555 zname);
1556 }
1557
1558 RETERR(configure_zone_ssutable(zoptions, mayberaw, zname));
1559 }
1560
1561 /*
1562 * Configure DNSSEC signing. These apply to primary zones or zones that
1563 * use inline-signing (raw != NULL).
1564 */
1565 if (ztype == dns_zone_primary || raw != NULL) {
1566 const cfg_obj_t *validity, *resign;
1567 bool allow = false, maint = false;
1568 bool sigvalinsecs;
1569
1570 if (use_kasp) {
1571 if (dns_kasp_nsec3(kasp)) {
1572 result = dns_zone_setnsec3param(
1573 zone, 1, dns_kasp_nsec3flags(kasp),
1574 dns_kasp_nsec3iter(kasp),
1575 dns_kasp_nsec3saltlen(kasp), NULL, true,
1576 false);
1577 } else {
1578 result = dns_zone_setnsec3param(
1579 zone, 0, 0, 0, 0, NULL, true, false);
1580 }
1581 INSIST(result == ISC_R_SUCCESS);
1582 }
1583
1584 if (use_kasp) {
1585 seconds = (uint32_t)dns_kasp_sigvalidity_dnskey(kasp);
1586 } else {
1587 obj = NULL;
1588 result = named_config_get(maps, "dnskey-sig-validity",
1589 &obj);
1590 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1591 seconds = cfg_obj_asuint32(obj) * 86400;
1592 }
1593 dns_zone_setkeyvalidityinterval(zone, seconds);
1594
1595 if (use_kasp) {
1596 seconds = (uint32_t)dns_kasp_sigvalidity(kasp);
1597 dns_zone_setsigvalidityinterval(zone, seconds);
1598 seconds = (uint32_t)dns_kasp_sigrefresh(kasp);
1599 dns_zone_setsigresigninginterval(zone, seconds);
1600 } else {
1601 obj = NULL;
1602 result = named_config_get(maps, "sig-validity-interval",
1603 &obj);
1604 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1605
1606 sigvalinsecs = ns_server_getoption(
1607 named_g_server->sctx, NS_SERVER_SIGVALINSECS);
1608 validity = cfg_tuple_get(obj, "validity");
1609 seconds = cfg_obj_asuint32(validity);
1610 if (!sigvalinsecs) {
1611 seconds *= 86400;
1612 }
1613 dns_zone_setsigvalidityinterval(zone, seconds);
1614
1615 resign = cfg_tuple_get(obj, "re-sign");
1616 if (cfg_obj_isvoid(resign)) {
1617 seconds /= 4;
1618 } else if (!sigvalinsecs) {
1619 uint32_t r = cfg_obj_asuint32(resign);
1620 if (seconds > 7 * 86400) {
1621 seconds = r * 86400;
1622 } else {
1623 seconds = r * 3600;
1624 }
1625 } else {
1626 seconds = cfg_obj_asuint32(resign);
1627 }
1628 dns_zone_setsigresigninginterval(zone, seconds);
1629 }
1630
1631 obj = NULL;
1632 result = named_config_get(maps, "key-directory", &obj);
1633 if (result == ISC_R_SUCCESS) {
1634 filename = cfg_obj_asstring(obj);
1635 RETERR(dns_zone_setkeydirectory(zone, filename));
1636 }
1637
1638 obj = NULL;
1639 result = named_config_get(maps, "sig-signing-signatures", &obj);
1640 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1641 dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));
1642
1643 obj = NULL;
1644 result = named_config_get(maps, "sig-signing-nodes", &obj);
1645 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1646 dns_zone_setnodes(zone, cfg_obj_asuint32(obj));
1647
1648 obj = NULL;
1649 result = named_config_get(maps, "sig-signing-type", &obj);
1650 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1651 dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));
1652
1653 obj = NULL;
1654 result = named_config_get(maps, "update-check-ksk", &obj);
1655 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1656 dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
1657 cfg_obj_asboolean(obj));
1658 /*
1659 * This setting will be ignored if dnssec-policy is used.
1660 * named-checkconf will error if both are configured.
1661 */
1662
1663 obj = NULL;
1664 result = named_config_get(maps, "dnssec-dnskey-kskonly", &obj);
1665 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1666 dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
1667 cfg_obj_asboolean(obj));
1668 /*
1669 * This setting will be ignored if dnssec-policy is used.
1670 * named-checkconf will error if both are configured.
1671 */
1672
1673 obj = NULL;
1674 result = named_config_get(maps, "dnssec-loadkeys-interval",
1675 &obj);
1676 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1677 RETERR(dns_zone_setrefreshkeyinterval(zone,
1678 cfg_obj_asuint32(obj)));
1679
1680 obj = NULL;
1681 result = cfg_map_get(zoptions, "auto-dnssec", &obj);
1682 if (kasp != NULL) {
1683 bool s2i = (strcmp(dns_kasp_getname(kasp),
1684 "insecure") != 0);
1685 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, true);
1686 dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, !s2i);
1687 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, true);
1688 } else if (result == ISC_R_SUCCESS) {
1689 const char *arg = cfg_obj_asstring(obj);
1690 if (strcasecmp(arg, "allow") == 0) {
1691 allow = true;
1692 } else if (strcasecmp(arg, "maintain") == 0) {
1693 allow = maint = true;
1694 } else if (strcasecmp(arg, "off") == 0) {
1695 /* Default */
1696 } else {
1697 UNREACHABLE();
1698 }
1699 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
1700 dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, false);
1701 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
1702 }
1703 }
1704
1705 if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
1706 RETERR(configure_zone_acl(zconfig, vconfig, config,
1707 allow_update_forwarding, ac, mayberaw,
1708 dns_zone_setforwardacl,
1709 dns_zone_clearforwardacl));
1710 }
1711
1712 /*%
1713 * Configure parental agents, applies to primary and secondary zones.
1714 */
1715 if (ztype == dns_zone_primary || ztype == dns_zone_secondary) {
1716 obj = NULL;
1717 (void)cfg_map_get(zoptions, "parental-agents", &obj);
1718 if (obj != NULL) {
1719 dns_ipkeylist_t ipkl;
1720 dns_ipkeylist_init(&ipkl);
1721 RETERR(named_config_getipandkeylist(
1722 config, "parental-agents", obj, mctx, &ipkl));
1723 result = dns_zone_setparentals(zone, ipkl.addrs,
1724 ipkl.keys, ipkl.count);
1725 dns_ipkeylist_clear(mctx, &ipkl);
1726 RETERR(result);
1727 } else {
1728 RETERR(dns_zone_setparentals(zone, NULL, NULL, 0));
1729 }
1730 }
1731
1732 /*%
1733 * Primary master functionality.
1734 */
1735 if (ztype == dns_zone_primary) {
1736 obj = NULL;
1737 result = named_config_get(maps, "check-wildcard", &obj);
1738 if (result == ISC_R_SUCCESS) {
1739 check = cfg_obj_asboolean(obj);
1740 } else {
1741 check = false;
1742 }
1743 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKWILDCARD, check);
1744
1745 /*
1746 * With map files, the default is ignore duplicate
1747 * records. With other master formats, the default is
1748 * taken from the global configuration.
1749 */
1750 obj = NULL;
1751 if (masterformat != dns_masterformat_map) {
1752 result = named_config_get(maps, "check-dup-records",
1753 &obj);
1754 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1755 dupcheck = cfg_obj_asstring(obj);
1756 } else {
1757 result = named_config_get(nodefault,
1758 "check-dup-records", &obj);
1759 if (result == ISC_R_SUCCESS) {
1760 dupcheck = cfg_obj_asstring(obj);
1761 } else {
1762 dupcheck = "ignore";
1763 }
1764 }
1765 if (strcasecmp(dupcheck, "warn") == 0) {
1766 fail = false;
1767 check = true;
1768 } else if (strcasecmp(dupcheck, "fail") == 0) {
1769 fail = check = true;
1770 } else if (strcasecmp(dupcheck, "ignore") == 0) {
1771 fail = check = false;
1772 } else {
1773 UNREACHABLE();
1774 }
1775 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRR, check);
1776 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
1777
1778 obj = NULL;
1779 result = named_config_get(maps, "check-mx", &obj);
1780 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1781 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1782 fail = false;
1783 check = true;
1784 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1785 fail = check = true;
1786 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1787 fail = check = false;
1788 } else {
1789 UNREACHABLE();
1790 }
1791 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMX, check);
1792 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKMXFAIL, fail);
1793
1794 /*
1795 * With map files, the default is *not* to check
1796 * integrity. With other master formats, the default is
1797 * taken from the global configuration.
1798 */
1799 obj = NULL;
1800 if (masterformat != dns_masterformat_map) {
1801 result = named_config_get(maps, "check-integrity",
1802 &obj);
1803 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1804 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
1805 cfg_obj_asboolean(obj));
1806 } else {
1807 check = false;
1808 result = named_config_get(nodefault, "check-integrity",
1809 &obj);
1810 if (result == ISC_R_SUCCESS) {
1811 check = cfg_obj_asboolean(obj);
1812 }
1813 dns_zone_setoption(mayberaw, DNS_ZONEOPT_CHECKINTEGRITY,
1814 check);
1815 }
1816
1817 obj = NULL;
1818 result = named_config_get(maps, "check-mx-cname", &obj);
1819 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1820 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1821 warn = true;
1822 ignore = false;
1823 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1824 warn = ignore = false;
1825 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1826 warn = ignore = true;
1827 } else {
1828 UNREACHABLE();
1829 }
1830 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNMXCNAME, warn);
1831 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
1832
1833 obj = NULL;
1834 result = named_config_get(maps, "check-srv-cname", &obj);
1835 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1836 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
1837 warn = true;
1838 ignore = false;
1839 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
1840 warn = ignore = false;
1841 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
1842 warn = ignore = true;
1843 } else {
1844 UNREACHABLE();
1845 }
1846 dns_zone_setoption(mayberaw, DNS_ZONEOPT_WARNSRVCNAME, warn);
1847 dns_zone_setoption(mayberaw, DNS_ZONEOPT_IGNORESRVCNAME,
1848 ignore);
1849
1850 obj = NULL;
1851 result = named_config_get(maps, "dnssec-secure-to-insecure",
1852 &obj);
1853 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1854 dns_zone_setoption(mayberaw, DNS_ZONEOPT_SECURETOINSECURE,
1855 cfg_obj_asboolean(obj));
1856
1857 obj = NULL;
1858 result = cfg_map_get(zoptions, "dnssec-update-mode", &obj);
1859 if (result == ISC_R_SUCCESS) {
1860 const char *arg = cfg_obj_asstring(obj);
1861 if (strcasecmp(arg, "no-resign") == 0) {
1862 dns_zone_setkeyopt(zone, DNS_ZONEKEY_NORESIGN,
1863 true);
1864 } else if (strcasecmp(arg, "maintain") == 0) {
1865 /* Default */
1866 } else {
1867 UNREACHABLE();
1868 }
1869 }
1870
1871 obj = NULL;
1872 result = named_config_get(maps, "serial-update-method", &obj);
1873 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1874 if (strcasecmp(cfg_obj_asstring(obj), "unixtime") == 0) {
1875 dns_zone_setserialupdatemethod(
1876 zone, dns_updatemethod_unixtime);
1877 } else if (strcasecmp(cfg_obj_asstring(obj), "date") == 0) {
1878 dns_zone_setserialupdatemethod(zone,
1879 dns_updatemethod_date);
1880 } else {
1881 dns_zone_setserialupdatemethod(
1882 zone, dns_updatemethod_increment);
1883 }
1884 }
1885
1886 /*
1887 * Configure slave functionality.
1888 */
1889 switch (ztype) {
1890 case dns_zone_mirror:
1891 /*
1892 * Disable outgoing zone transfers for mirror zones unless they
1893 * are explicitly enabled by zone configuration.
1894 */
1895 obj = NULL;
1896 (void)cfg_map_get(zoptions, "allow-transfer", &obj);
1897 if (obj == NULL) {
1898 dns_acl_t *none;
1899 RETERR(dns_acl_none(mctx, &none));
1900 dns_zone_setxfracl(zone, none);
1901 dns_acl_detach(&none);
1902 }
1903 FALLTHROUGH;
1904 case dns_zone_secondary:
1905 case dns_zone_stub:
1906 case dns_zone_redirect:
1907 count = 0;
1908 obj = NULL;
1909 (void)cfg_map_get(zoptions, "primaries", &obj);
1910 if (obj == NULL) {
1911 (void)cfg_map_get(zoptions, "masters", &obj);
1912 }
1913
1914 /*
1915 * Use the built-in primary server list if one was not
1916 * explicitly specified and this is a root zone mirror.
1917 */
1918 if (obj == NULL && ztype == dns_zone_mirror &&
1919 dns_name_equal(dns_zone_getorigin(zone), dns_rootname))
1920 {
1921 result = named_config_getremotesdef(
1922 named_g_config, "primaries",
1923 DEFAULT_IANA_ROOT_ZONE_PRIMARIES, &obj);
1924 RETERR(result);
1925 }
1926 if (obj != NULL) {
1927 dns_ipkeylist_t ipkl;
1928 dns_ipkeylist_init(&ipkl);
1929
1930 RETERR(named_config_getipandkeylist(config, "primaries",
1931 obj, mctx, &ipkl));
1932 result = dns_zone_setprimarieswithkeys(
1933 mayberaw, ipkl.addrs, ipkl.keys, ipkl.count);
1934 count = ipkl.count;
1935 dns_ipkeylist_clear(mctx, &ipkl);
1936 RETERR(result);
1937 } else {
1938 result = dns_zone_setprimaries(mayberaw, NULL, 0);
1939 }
1940 RETERR(result);
1941
1942 multi = false;
1943 if (count > 1) {
1944 obj = NULL;
1945 result = named_config_get(maps, "multi-master", &obj);
1946 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1947 multi = cfg_obj_asboolean(obj);
1948 }
1949 dns_zone_setoption(mayberaw, DNS_ZONEOPT_MULTIMASTER, multi);
1950
1951 obj = NULL;
1952 result = named_config_get(maps, "max-transfer-time-in", &obj);
1953 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1954 dns_zone_setmaxxfrin(mayberaw, cfg_obj_asuint32(obj) * 60);
1955
1956 obj = NULL;
1957 result = named_config_get(maps, "max-transfer-idle-in", &obj);
1958 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1959 dns_zone_setidlein(mayberaw, cfg_obj_asuint32(obj) * 60);
1960
1961 obj = NULL;
1962 result = named_config_get(maps, "max-refresh-time", &obj);
1963 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1964 dns_zone_setmaxrefreshtime(mayberaw, cfg_obj_asuint32(obj));
1965
1966 obj = NULL;
1967 result = named_config_get(maps, "min-refresh-time", &obj);
1968 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1969 dns_zone_setminrefreshtime(mayberaw, cfg_obj_asuint32(obj));
1970
1971 obj = NULL;
1972 result = named_config_get(maps, "max-retry-time", &obj);
1973 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1974 dns_zone_setmaxretrytime(mayberaw, cfg_obj_asuint32(obj));
1975
1976 obj = NULL;
1977 result = named_config_get(maps, "min-retry-time", &obj);
1978 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1979 dns_zone_setminretrytime(mayberaw, cfg_obj_asuint32(obj));
1980
1981 obj = NULL;
1982 result = named_config_get(maps, "transfer-source", &obj);
1983 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1984 RETERR(dns_zone_setxfrsource4(mayberaw,
1985 cfg_obj_assockaddr(obj)));
1986 dscp = cfg_obj_getdscp(obj);
1987 if (dscp == -1) {
1988 dscp = named_g_dscp;
1989 }
1990 RETERR(dns_zone_setxfrsource4dscp(mayberaw, dscp));
1991 named_add_reserved_dispatch(named_g_server,
1992 cfg_obj_assockaddr(obj));
1993
1994 obj = NULL;
1995 result = named_config_get(maps, "transfer-source-v6", &obj);
1996 INSIST(result == ISC_R_SUCCESS && obj != NULL);
1997 RETERR(dns_zone_setxfrsource6(mayberaw,
1998 cfg_obj_assockaddr(obj)));
1999 dscp = cfg_obj_getdscp(obj);
2000 if (dscp == -1) {
2001 dscp = named_g_dscp;
2002 }
2003 RETERR(dns_zone_setxfrsource6dscp(mayberaw, dscp));
2004 named_add_reserved_dispatch(named_g_server,
2005 cfg_obj_assockaddr(obj));
2006
2007 obj = NULL;
2008 result = named_config_get(maps, "alt-transfer-source", &obj);
2009 INSIST(result == ISC_R_SUCCESS && obj != NULL);
2010 RETERR(dns_zone_setaltxfrsource4(mayberaw,
2011 cfg_obj_assockaddr(obj)));
2012 dscp = cfg_obj_getdscp(obj);
2013 if (dscp == -1) {
2014 dscp = named_g_dscp;
2015 }
2016 RETERR(dns_zone_setaltxfrsource4dscp(mayberaw, dscp));
2017
2018 obj = NULL;
2019 result = named_config_get(maps, "alt-transfer-source-v6", &obj);
2020 INSIST(result == ISC_R_SUCCESS && obj != NULL);
2021 RETERR(dns_zone_setaltxfrsource6(mayberaw,
2022 cfg_obj_assockaddr(obj)));
2023 dscp = cfg_obj_getdscp(obj);
2024 if (dscp == -1) {
2025 dscp = named_g_dscp;
2026 }
2027 RETERR(dns_zone_setaltxfrsource6dscp(mayberaw, dscp));
2028
2029 obj = NULL;
2030 (void)named_config_get(maps, "use-alt-transfer-source", &obj);
2031 if (obj == NULL) {
2032 /*
2033 * Default off when views are in use otherwise
2034 * on for BIND 8 compatibility.
2035 */
2036 view = dns_zone_getview(zone);
2037 if (view != NULL && strcmp(view->name, "_default") == 0)
2038 {
2039 alt = true;
2040 } else {
2041 alt = false;
2042 }
2043 } else {
2044 alt = cfg_obj_asboolean(obj);
2045 }
2046 dns_zone_setoption(mayberaw, DNS_ZONEOPT_USEALTXFRSRC, alt);
2047
2048 obj = NULL;
2049 (void)named_config_get(maps, "try-tcp-refresh", &obj);
2050 dns_zone_setoption(mayberaw, DNS_ZONEOPT_TRYTCPREFRESH,
2051 cfg_obj_asboolean(obj));
2052 break;
2053
2054 case dns_zone_staticstub:
2055 RETERR(configure_staticstub(zoptions, zone, zname,
2056 default_dbtype));
2057 break;
2058
2059 default:
2060 break;
2061 }
2062
2063 return (ISC_R_SUCCESS);
2064 }
2065
2066 /*
2067 * Set up a DLZ zone as writeable
2068 */
2069 isc_result_t
2070 named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
2071 dns_rdataclass_t rdclass, dns_name_t *name) {
2072 dns_db_t *db = NULL;
2073 isc_time_t now;
2074 isc_result_t result;
2075
2076 TIME_NOW(&now);
2077
2078 dns_zone_settype(zone, dns_zone_dlz);
2079 result = dns_sdlz_setdb(dlzdatabase, rdclass, name, &db);
2080 if (result != ISC_R_SUCCESS) {
2081 return (result);
2082 }
2083 result = dns_zone_dlzpostload(zone, db);
2084 dns_db_detach(&db);
2085 return (result);
2086 }
2087
2088 bool
2089 named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
2090 const cfg_obj_t *zoptions = NULL;
2091 const cfg_obj_t *obj = NULL;
2092 const char *cfilename;
2093 const char *zfilename;
2094 dns_zone_t *raw = NULL;
2095 bool has_raw, inline_signing;
2096 dns_zonetype_t ztype;
2097
2098 zoptions = cfg_tuple_get(zconfig, "options");
2099
2100 /*
2101 * We always reconfigure a static-stub zone for simplicity, assuming
2102 * the amount of data to be loaded is small.
2103 */
2104 if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) {
2105 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2106 "not reusable: staticstub");
2107 return (false);
2108 }
2109
2110 /* If there's a raw zone, use that for filename and type comparison */
2111 dns_zone_getraw(zone, &raw);
2112 if (raw != NULL) {
2113 zfilename = dns_zone_getfile(raw);
2114 ztype = dns_zone_gettype(raw);
2115 dns_zone_detach(&raw);
2116 has_raw = true;
2117 } else {
2118 zfilename = dns_zone_getfile(zone);
2119 ztype = dns_zone_gettype(zone);
2120 has_raw = false;
2121 }
2122
2123 inline_signing = named_zone_inlinesigning(zconfig);
2124 if (!inline_signing && has_raw) {
2125 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2126 "not reusable: old zone was inline-signing");
2127 return (false);
2128 } else if (inline_signing && !has_raw) {
2129 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2130 "not reusable: old zone was not inline-signing");
2131 return (false);
2132 }
2133
2134 if (zonetype_fromconfig(zoptions) != ztype) {
2135 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2136 "not reusable: type mismatch");
2137 return (false);
2138 }
2139
2140 obj = NULL;
2141 (void)cfg_map_get(zoptions, "file", &obj);
2142 if (obj != NULL) {
2143 cfilename = cfg_obj_asstring(obj);
2144 } else {
2145 cfilename = NULL;
2146 }
2147 if (!((cfilename == NULL && zfilename == NULL) ||
2148 (cfilename != NULL && zfilename != NULL &&
2149 strcmp(cfilename, zfilename) == 0)))
2150 {
2151 dns_zone_log(zone, ISC_LOG_DEBUG(1),
2152 "not reusable: filename mismatch");
2153 return (false);
2154 }
2155
2156 return (true);
2157 }
2158
2159 bool
2160 named_zone_inlinesigning(const cfg_obj_t *zconfig) {
2161 const cfg_obj_t *zoptions = NULL;
2162 const cfg_obj_t *signing = NULL;
2163 bool inline_signing = false;
2164
2165 zoptions = cfg_tuple_get(zconfig, "options");
2166 inline_signing = (cfg_map_get(zoptions, "inline-signing", &signing) ==
2167 ISC_R_SUCCESS &&
2168 cfg_obj_asboolean(signing));
2169
2170 return (inline_signing);
2171 }
2172