No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / named / zoneconf.c
blobfe5bf8336125d8e7611568a95dd82502e732dc9f
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2004-2009 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: zoneconf.c,v 1.161 2009/12/04 21:09:32 marka Exp */
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/fixedname.h>
36 #include <dns/log.h>
37 #include <dns/name.h>
38 #include <dns/rdatatype.h>
39 #include <dns/ssu.h>
40 #include <dns/stats.h>
41 #include <dns/view.h>
42 #include <dns/zone.h>
44 #include <named/client.h>
45 #include <named/config.h>
46 #include <named/globals.h>
47 #include <named/log.h>
48 #include <named/server.h>
49 #include <named/zoneconf.h>
51 /* ACLs associated with zone */
52 typedef enum {
53 allow_notify,
54 allow_query,
55 allow_transfer,
56 allow_update,
57 allow_update_forwarding
58 } acl_type_t;
60 #define RETERR(x) do { \
61 isc_result_t _r = (x); \
62 if (_r != ISC_R_SUCCESS) \
63 return (_r); \
64 } while (0)
66 #define CHECK(x) do { \
67 result = (x); \
68 if (result != ISC_R_SUCCESS) \
69 goto cleanup; \
70 } while (0)
72 /*%
73 * Convenience function for configuring a single zone ACL.
75 static isc_result_t
76 configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
77 const cfg_obj_t *config, acl_type_t acltype,
78 cfg_aclconfctx_t *actx, dns_zone_t *zone,
79 void (*setzacl)(dns_zone_t *, dns_acl_t *),
80 void (*clearzacl)(dns_zone_t *))
82 isc_result_t result;
83 const cfg_obj_t *maps[5] = {NULL, NULL, NULL, NULL, NULL};
84 const cfg_obj_t *aclobj = NULL;
85 int i = 0;
86 dns_acl_t **aclp = NULL, *acl = NULL;
87 const char *aclname;
88 dns_view_t *view;
90 view = dns_zone_getview(zone);
92 switch (acltype) {
93 case allow_notify:
94 if (view != NULL)
95 aclp = &view->notifyacl;
96 aclname = "allow-notify";
97 break;
98 case allow_query:
99 if (view != NULL)
100 aclp = &view->queryacl;
101 aclname = "allow-query";
102 break;
103 case allow_transfer:
104 if (view != NULL)
105 aclp = &view->transferacl;
106 aclname = "allow-transfer";
107 break;
108 case allow_update:
109 if (view != NULL)
110 aclp = &view->updateacl;
111 aclname = "allow-update";
112 break;
113 case allow_update_forwarding:
114 if (view != NULL)
115 aclp = &view->upfwdacl;
116 aclname = "allow-update-forwarding";
117 break;
118 default:
119 INSIST(0);
120 return (ISC_R_FAILURE);
123 /* First check to see if ACL is defined within the zone */
124 if (zconfig != NULL) {
125 maps[0] = cfg_tuple_get(zconfig, "options");
126 ns_config_get(maps, aclname, &aclobj);
127 if (aclobj != NULL) {
128 aclp = NULL;
129 goto parse_acl;
133 /* Failing that, see if there's a default ACL already in the view */
134 if (aclp != NULL && *aclp != NULL) {
135 (*setzacl)(zone, *aclp);
136 return (ISC_R_SUCCESS);
139 /* Check for default ACLs that haven't been parsed yet */
140 if (vconfig != NULL)
141 maps[i++] = cfg_tuple_get(vconfig, "options");
142 if (config != NULL) {
143 const cfg_obj_t *options = NULL;
144 (void)cfg_map_get(config, "options", &options);
145 if (options != NULL)
146 maps[i++] = options;
148 maps[i++] = ns_g_defaults;
149 maps[i] = NULL;
151 result = ns_config_get(maps, aclname, &aclobj);
152 if (aclobj == NULL) {
153 (*clearzacl)(zone);
154 return (ISC_R_SUCCESS);
157 parse_acl:
158 result = cfg_acl_fromconfig(aclobj, config, ns_g_lctx, actx,
159 dns_zone_getmctx(zone), 0, &acl);
160 if (result != ISC_R_SUCCESS)
161 return (result);
162 (*setzacl)(zone, acl);
164 /* Set the view default now */
165 if (aclp != NULL)
166 dns_acl_attach(acl, aclp);
168 dns_acl_detach(&acl);
169 return (ISC_R_SUCCESS);
173 * Parse the zone update-policy statement.
175 static isc_result_t
176 configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
177 const char *zname)
179 const cfg_obj_t *updatepolicy = NULL;
180 const cfg_listelt_t *element, *element2;
181 dns_ssutable_t *table = NULL;
182 isc_mem_t *mctx = dns_zone_getmctx(zone);
183 isc_boolean_t autoddns = ISC_FALSE;
184 isc_result_t result;
186 (void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
188 if (updatepolicy == NULL) {
189 dns_zone_setssutable(zone, NULL);
190 return (ISC_R_SUCCESS);
193 if (cfg_obj_isstring(updatepolicy) &&
194 strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) {
195 autoddns = ISC_TRUE;
196 updatepolicy = NULL;
199 result = dns_ssutable_create(mctx, &table);
200 if (result != ISC_R_SUCCESS)
201 return (result);
203 for (element = cfg_list_first(updatepolicy);
204 element != NULL;
205 element = cfg_list_next(element))
207 const cfg_obj_t *stmt = cfg_listelt_value(element);
208 const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
209 const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
210 const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
211 const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
212 const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
213 const char *str;
214 isc_boolean_t grant = ISC_FALSE;
215 isc_boolean_t usezone = ISC_FALSE;
216 unsigned int mtype = DNS_SSUMATCHTYPE_NAME;
217 dns_fixedname_t fname, fident;
218 isc_buffer_t b;
219 dns_rdatatype_t *types;
220 unsigned int i, n;
222 str = cfg_obj_asstring(mode);
223 if (strcasecmp(str, "grant") == 0)
224 grant = ISC_TRUE;
225 else if (strcasecmp(str, "deny") == 0)
226 grant = ISC_FALSE;
227 else
228 INSIST(0);
230 str = cfg_obj_asstring(matchtype);
231 if (strcasecmp(str, "name") == 0)
232 mtype = DNS_SSUMATCHTYPE_NAME;
233 else if (strcasecmp(str, "subdomain") == 0)
234 mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
235 else if (strcasecmp(str, "wildcard") == 0)
236 mtype = DNS_SSUMATCHTYPE_WILDCARD;
237 else if (strcasecmp(str, "self") == 0)
238 mtype = DNS_SSUMATCHTYPE_SELF;
239 else if (strcasecmp(str, "selfsub") == 0)
240 mtype = DNS_SSUMATCHTYPE_SELFSUB;
241 else if (strcasecmp(str, "selfwild") == 0)
242 mtype = DNS_SSUMATCHTYPE_SELFWILD;
243 else if (strcasecmp(str, "ms-self") == 0)
244 mtype = DNS_SSUMATCHTYPE_SELFMS;
245 else if (strcasecmp(str, "krb5-self") == 0)
246 mtype = DNS_SSUMATCHTYPE_SELFKRB5;
247 else if (strcasecmp(str, "ms-subdomain") == 0)
248 mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS;
249 else if (strcasecmp(str, "krb5-subdomain") == 0)
250 mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5;
251 else if (strcasecmp(str, "tcp-self") == 0)
252 mtype = DNS_SSUMATCHTYPE_TCPSELF;
253 else if (strcasecmp(str, "6to4-self") == 0)
254 mtype = DNS_SSUMATCHTYPE_6TO4SELF;
255 else if (strcasecmp(str, "zonesub") == 0) {
256 mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
257 usezone = ISC_TRUE;
258 } else
259 INSIST(0);
261 dns_fixedname_init(&fident);
262 str = cfg_obj_asstring(identity);
263 isc_buffer_init(&b, str, strlen(str));
264 isc_buffer_add(&b, strlen(str));
265 result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
266 dns_rootname, 0, NULL);
267 if (result != ISC_R_SUCCESS) {
268 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
269 "'%s' is not a valid name", str);
270 goto cleanup;
273 dns_fixedname_init(&fname);
274 if (usezone) {
275 result = dns_name_copy(dns_zone_getorigin(zone),
276 dns_fixedname_name(&fname),
277 NULL);
278 if (result != ISC_R_SUCCESS) {
279 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
280 "error copying origin: %s",
281 isc_result_totext(result));
282 goto cleanup;
284 } else {
285 str = cfg_obj_asstring(dname);
286 isc_buffer_init(&b, str, strlen(str));
287 isc_buffer_add(&b, strlen(str));
288 result = dns_name_fromtext(dns_fixedname_name(&fname),
289 &b, dns_rootname, 0, NULL);
290 if (result != ISC_R_SUCCESS) {
291 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
292 "'%s' is not a valid name", str);
293 goto cleanup;
297 n = ns_config_listcount(typelist);
298 if (n == 0)
299 types = NULL;
300 else {
301 types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
302 if (types == NULL) {
303 result = ISC_R_NOMEMORY;
304 goto cleanup;
308 i = 0;
309 for (element2 = cfg_list_first(typelist);
310 element2 != NULL;
311 element2 = cfg_list_next(element2))
313 const cfg_obj_t *typeobj;
314 isc_textregion_t r;
316 INSIST(i < n);
318 typeobj = cfg_listelt_value(element2);
319 str = cfg_obj_asstring(typeobj);
320 DE_CONST(str, r.base);
321 r.length = strlen(str);
323 result = dns_rdatatype_fromtext(&types[i++], &r);
324 if (result != ISC_R_SUCCESS) {
325 cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
326 "'%s' is not a valid type", str);
327 isc_mem_put(mctx, types,
328 n * sizeof(dns_rdatatype_t));
329 goto cleanup;
332 INSIST(i == n);
334 result = dns_ssutable_addrule(table, grant,
335 dns_fixedname_name(&fident),
336 mtype,
337 dns_fixedname_name(&fname),
338 n, types);
339 if (types != NULL)
340 isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
341 if (result != ISC_R_SUCCESS) {
342 goto cleanup;
347 * If "update-policy local;" and a session key exists,
348 * then use the default policy, which is equivalent to:
349 * update-policy { grant <session-keyname> zonesub any; };
351 if (autoddns) {
352 dns_rdatatype_t any = dns_rdatatype_any;
354 if (ns_g_server->session_keyname == NULL) {
355 isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
356 NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
357 "failed to enable auto DDNS policy "
358 "for zone %s: session key not found",
359 zname);
360 result = ISC_R_NOTFOUND;
361 goto cleanup;
364 result = dns_ssutable_addrule(table, ISC_TRUE,
365 ns_g_server->session_keyname,
366 DNS_SSUMATCHTYPE_SUBDOMAIN,
367 dns_zone_getorigin(zone),
368 1, &any);
370 if (result != ISC_R_SUCCESS)
371 goto cleanup;
374 result = ISC_R_SUCCESS;
375 dns_zone_setssutable(zone, table);
377 cleanup:
378 dns_ssutable_detach(&table);
379 return (result);
383 * Convert a config file zone type into a server zone type.
385 static inline dns_zonetype_t
386 zonetype_fromconfig(const cfg_obj_t *map) {
387 const cfg_obj_t *obj = NULL;
388 isc_result_t result;
390 result = cfg_map_get(map, "type", &obj);
391 INSIST(result == ISC_R_SUCCESS);
392 return (ns_config_getzonetype(obj));
396 * Helper function for strtoargv(). Pardon the gratuitous recursion.
398 static isc_result_t
399 strtoargvsub(isc_mem_t *mctx, char *s, unsigned int *argcp,
400 char ***argvp, unsigned int n)
402 isc_result_t result;
404 /* Discard leading whitespace. */
405 while (*s == ' ' || *s == '\t')
406 s++;
408 if (*s == '\0') {
409 /* We have reached the end of the string. */
410 *argcp = n;
411 *argvp = isc_mem_get(mctx, n * sizeof(char *));
412 if (*argvp == NULL)
413 return (ISC_R_NOMEMORY);
414 } else {
415 char *p = s;
416 while (*p != ' ' && *p != '\t' && *p != '\0')
417 p++;
418 if (*p != '\0')
419 *p++ = '\0';
421 result = strtoargvsub(mctx, p, argcp, argvp, n + 1);
422 if (result != ISC_R_SUCCESS)
423 return (result);
424 (*argvp)[n] = s;
426 return (ISC_R_SUCCESS);
430 * Tokenize the string "s" into whitespace-separated words,
431 * return the number of words in '*argcp' and an array
432 * of pointers to the words in '*argvp'. The caller
433 * must free the array using isc_mem_put(). The string
434 * is modified in-place.
436 static isc_result_t
437 strtoargv(isc_mem_t *mctx, char *s, unsigned int *argcp, char ***argvp) {
438 return (strtoargvsub(mctx, s, argcp, argvp, 0));
441 static void
442 checknames(dns_zonetype_t ztype, const cfg_obj_t **maps,
443 const cfg_obj_t **objp)
445 const char *zone = NULL;
446 isc_result_t result;
448 switch (ztype) {
449 case dns_zone_slave: zone = "slave"; break;
450 case dns_zone_master: zone = "master"; break;
451 default:
452 INSIST(0);
454 result = ns_checknames_get(maps, zone, objp);
455 INSIST(result == ISC_R_SUCCESS);
458 isc_result_t
459 ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
460 const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
461 dns_zone_t *zone)
463 isc_result_t result;
464 const char *zname;
465 dns_rdataclass_t zclass;
466 dns_rdataclass_t vclass;
467 const cfg_obj_t *maps[5];
468 const cfg_obj_t *zoptions = NULL;
469 const cfg_obj_t *options = NULL;
470 const cfg_obj_t *obj;
471 const char *filename = NULL;
472 dns_notifytype_t notifytype = dns_notifytype_yes;
473 isc_sockaddr_t *addrs;
474 dns_name_t **keynames;
475 isc_uint32_t count;
476 char *cpval;
477 unsigned int dbargc;
478 char **dbargv;
479 static char default_dbtype[] = "rbt";
480 isc_mem_t *mctx = dns_zone_getmctx(zone);
481 dns_dialuptype_t dialup = dns_dialuptype_no;
482 dns_zonetype_t ztype;
483 int i;
484 isc_int32_t journal_size;
485 isc_boolean_t multi;
486 isc_boolean_t alt;
487 dns_view_t *view;
488 isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE;
489 isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE;
490 isc_boolean_t ixfrdiff;
491 dns_masterformat_t masterformat;
492 isc_stats_t *zoneqrystats;
493 isc_boolean_t zonestats_on;
494 int seconds;
496 i = 0;
497 if (zconfig != NULL) {
498 zoptions = cfg_tuple_get(zconfig, "options");
499 maps[i++] = zoptions;
501 if (vconfig != NULL)
502 maps[i++] = cfg_tuple_get(vconfig, "options");
503 if (config != NULL) {
504 (void)cfg_map_get(config, "options", &options);
505 if (options != NULL)
506 maps[i++] = options;
508 maps[i++] = ns_g_defaults;
509 maps[i++] = NULL;
511 if (vconfig != NULL)
512 RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"),
513 dns_rdataclass_in, &vclass));
514 else
515 vclass = dns_rdataclass_in;
518 * Configure values common to all zone types.
521 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
523 RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
524 vclass, &zclass));
525 dns_zone_setclass(zone, zclass);
527 ztype = zonetype_fromconfig(zoptions);
528 dns_zone_settype(zone, ztype);
530 obj = NULL;
531 result = cfg_map_get(zoptions, "database", &obj);
532 if (result == ISC_R_SUCCESS)
533 cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
534 else
535 cpval = default_dbtype;
537 if (cpval == NULL)
538 return(ISC_R_NOMEMORY);
540 result = strtoargv(mctx, cpval, &dbargc, &dbargv);
541 if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
542 isc_mem_free(mctx, cpval);
543 return (result);
547 * ANSI C is strange here. There is no logical reason why (char **)
548 * cannot be promoted automatically to (const char * const *) by the
549 * compiler w/o generating a warning.
551 result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv);
552 isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
553 if (cpval != default_dbtype)
554 isc_mem_free(mctx, cpval);
555 if (result != ISC_R_SUCCESS)
556 return (result);
558 obj = NULL;
559 result = cfg_map_get(zoptions, "file", &obj);
560 if (result == ISC_R_SUCCESS)
561 filename = cfg_obj_asstring(obj);
563 masterformat = dns_masterformat_text;
564 obj = NULL;
565 result= ns_config_get(maps, "masterfile-format", &obj);
566 if (result == ISC_R_SUCCESS) {
567 const char *masterformatstr = cfg_obj_asstring(obj);
569 if (strcasecmp(masterformatstr, "text") == 0)
570 masterformat = dns_masterformat_text;
571 else if (strcasecmp(masterformatstr, "raw") == 0)
572 masterformat = dns_masterformat_raw;
573 else
574 INSIST(0);
576 RETERR(dns_zone_setfile2(zone, filename, masterformat));
578 obj = NULL;
579 result = cfg_map_get(zoptions, "journal", &obj);
580 if (result == ISC_R_SUCCESS)
581 RETERR(dns_zone_setjournal(zone, cfg_obj_asstring(obj)));
583 if (ztype == dns_zone_slave)
584 RETERR(configure_zone_acl(zconfig, vconfig, config,
585 allow_notify, ac, zone,
586 dns_zone_setnotifyacl,
587 dns_zone_clearnotifyacl));
589 * XXXAG This probably does not make sense for stubs.
591 RETERR(configure_zone_acl(zconfig, vconfig, config,
592 allow_query, ac, zone,
593 dns_zone_setqueryacl,
594 dns_zone_clearqueryacl));
596 obj = NULL;
597 result = ns_config_get(maps, "dialup", &obj);
598 INSIST(result == ISC_R_SUCCESS);
599 if (cfg_obj_isboolean(obj)) {
600 if (cfg_obj_asboolean(obj))
601 dialup = dns_dialuptype_yes;
602 else
603 dialup = dns_dialuptype_no;
604 } else {
605 const char *dialupstr = cfg_obj_asstring(obj);
606 if (strcasecmp(dialupstr, "notify") == 0)
607 dialup = dns_dialuptype_notify;
608 else if (strcasecmp(dialupstr, "notify-passive") == 0)
609 dialup = dns_dialuptype_notifypassive;
610 else if (strcasecmp(dialupstr, "refresh") == 0)
611 dialup = dns_dialuptype_refresh;
612 else if (strcasecmp(dialupstr, "passive") == 0)
613 dialup = dns_dialuptype_passive;
614 else
615 INSIST(0);
617 dns_zone_setdialup(zone, dialup);
619 obj = NULL;
620 result = ns_config_get(maps, "zone-statistics", &obj);
621 INSIST(result == ISC_R_SUCCESS);
622 zonestats_on = cfg_obj_asboolean(obj);
623 zoneqrystats = NULL;
624 if (zonestats_on) {
625 RETERR(isc_stats_create(mctx, &zoneqrystats,
626 dns_nsstatscounter_max));
628 dns_zone_setrequeststats(zone, zoneqrystats);
629 if (zoneqrystats != NULL)
630 isc_stats_detach(&zoneqrystats);
633 * Configure master functionality. This applies
634 * to primary masters (type "master") and slaves
635 * acting as masters (type "slave"), but not to stubs.
637 if (ztype != dns_zone_stub) {
638 obj = NULL;
639 result = ns_config_get(maps, "notify", &obj);
640 INSIST(result == ISC_R_SUCCESS);
641 if (cfg_obj_isboolean(obj)) {
642 if (cfg_obj_asboolean(obj))
643 notifytype = dns_notifytype_yes;
644 else
645 notifytype = dns_notifytype_no;
646 } else {
647 const char *notifystr = cfg_obj_asstring(obj);
648 if (strcasecmp(notifystr, "explicit") == 0)
649 notifytype = dns_notifytype_explicit;
650 else if (strcasecmp(notifystr, "master-only") == 0)
651 notifytype = dns_notifytype_masteronly;
652 else
653 INSIST(0);
655 dns_zone_setnotifytype(zone, notifytype);
657 obj = NULL;
658 result = ns_config_get(maps, "also-notify", &obj);
659 if (result == ISC_R_SUCCESS) {
660 isc_sockaddr_t *addrs = NULL;
661 isc_uint32_t addrcount;
662 result = ns_config_getiplist(config, obj, 0, mctx,
663 &addrs, &addrcount);
664 if (result != ISC_R_SUCCESS)
665 return (result);
666 result = dns_zone_setalsonotify(zone, addrs,
667 addrcount);
668 ns_config_putiplist(mctx, &addrs, addrcount);
669 if (result != ISC_R_SUCCESS)
670 return (result);
671 } else
672 RETERR(dns_zone_setalsonotify(zone, NULL, 0));
674 obj = NULL;
675 result = ns_config_get(maps, "notify-source", &obj);
676 INSIST(result == ISC_R_SUCCESS);
677 RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
678 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
680 obj = NULL;
681 result = ns_config_get(maps, "notify-source-v6", &obj);
682 INSIST(result == ISC_R_SUCCESS);
683 RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
684 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
686 obj = NULL;
687 result = ns_config_get(maps, "notify-to-soa", &obj);
688 INSIST(result == ISC_R_SUCCESS);
689 dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
690 cfg_obj_asboolean(obj));
692 dns_zone_setisself(zone, ns_client_isself, NULL);
694 RETERR(configure_zone_acl(zconfig, vconfig, config,
695 allow_transfer, ac, zone,
696 dns_zone_setxfracl,
697 dns_zone_clearxfracl));
699 obj = NULL;
700 result = ns_config_get(maps, "max-transfer-time-out", &obj);
701 INSIST(result == ISC_R_SUCCESS);
702 dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);
704 obj = NULL;
705 result = ns_config_get(maps, "max-transfer-idle-out", &obj);
706 INSIST(result == ISC_R_SUCCESS);
707 dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);
709 obj = NULL;
710 result = ns_config_get(maps, "max-journal-size", &obj);
711 INSIST(result == ISC_R_SUCCESS);
712 dns_zone_setjournalsize(zone, -1);
713 if (cfg_obj_isstring(obj)) {
714 const char *str = cfg_obj_asstring(obj);
715 INSIST(strcasecmp(str, "unlimited") == 0);
716 journal_size = ISC_UINT32_MAX / 2;
717 } else {
718 isc_resourcevalue_t value;
719 value = cfg_obj_asuint64(obj);
720 if (value > ISC_UINT32_MAX / 2) {
721 cfg_obj_log(obj, ns_g_lctx,
722 ISC_LOG_ERROR,
723 "'max-journal-size "
724 "%" ISC_PRINT_QUADFORMAT "d' "
725 "is too large",
726 value);
727 RETERR(ISC_R_RANGE);
729 journal_size = (isc_uint32_t)value;
731 dns_zone_setjournalsize(zone, journal_size);
733 obj = NULL;
734 result = ns_config_get(maps, "ixfr-from-differences", &obj);
735 INSIST(result == ISC_R_SUCCESS);
736 if (cfg_obj_isboolean(obj))
737 ixfrdiff = cfg_obj_asboolean(obj);
738 else if (strcasecmp(cfg_obj_asstring(obj), "master") &&
739 ztype == dns_zone_master)
740 ixfrdiff = ISC_TRUE;
741 else if (strcasecmp(cfg_obj_asstring(obj), "slave") &&
742 ztype == dns_zone_slave)
743 ixfrdiff = ISC_TRUE;
744 else
745 ixfrdiff = ISC_FALSE;
746 dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff);
748 checknames(ztype, maps, &obj);
749 INSIST(obj != NULL);
750 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
751 fail = ISC_FALSE;
752 check = ISC_TRUE;
753 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
754 fail = check = ISC_TRUE;
755 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
756 fail = check = ISC_FALSE;
757 } else
758 INSIST(0);
759 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check);
760 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail);
762 obj = NULL;
763 result = ns_config_get(maps, "notify-delay", &obj);
764 INSIST(result == ISC_R_SUCCESS);
765 dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));
767 obj = NULL;
768 result = ns_config_get(maps, "check-sibling", &obj);
769 INSIST(result == ISC_R_SUCCESS);
770 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
771 cfg_obj_asboolean(obj));
773 obj = NULL;
774 result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
775 INSIST(result == ISC_R_SUCCESS);
776 dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));
778 obj = NULL;
779 result = ns_config_get(maps, "nsec3-test-zone", &obj);
780 INSIST(result == ISC_R_SUCCESS);
781 dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
782 cfg_obj_asboolean(obj));
786 * Configure update-related options. These apply to
787 * primary masters only.
789 if (ztype == dns_zone_master) {
790 dns_acl_t *updateacl;
792 RETERR(configure_zone_acl(zconfig, vconfig, config,
793 allow_update, ac, zone,
794 dns_zone_setupdateacl,
795 dns_zone_clearupdateacl));
797 updateacl = dns_zone_getupdateacl(zone);
798 if (updateacl != NULL && dns_acl_isinsecure(updateacl))
799 isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
800 NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
801 "zone '%s' allows updates by IP "
802 "address, which is insecure",
803 zname);
805 RETERR(configure_zone_ssutable(zoptions, zone, zname));
807 obj = NULL;
808 result = ns_config_get(maps, "sig-validity-interval", &obj);
809 INSIST(result == ISC_R_SUCCESS);
811 const cfg_obj_t *validity, *resign;
813 validity = cfg_tuple_get(obj, "validity");
814 seconds = cfg_obj_asuint32(validity) * 86400;
815 dns_zone_setsigvalidityinterval(zone, seconds);
817 resign = cfg_tuple_get(obj, "re-sign");
818 if (cfg_obj_isvoid(resign)) {
819 seconds /= 4;
820 } else {
821 if (seconds > 7 * 86400)
822 seconds = cfg_obj_asuint32(resign) *
823 86400;
824 else
825 seconds = cfg_obj_asuint32(resign) *
826 3600;
828 dns_zone_setsigresigninginterval(zone, seconds);
831 obj = NULL;
832 result = ns_config_get(maps, "key-directory", &obj);
833 if (result == ISC_R_SUCCESS) {
834 filename = cfg_obj_asstring(obj);
835 RETERR(dns_zone_setkeydirectory(zone, filename));
838 obj = NULL;
839 result = ns_config_get(maps, "sig-signing-signatures", &obj);
840 INSIST(result == ISC_R_SUCCESS);
841 dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));
843 obj = NULL;
844 result = ns_config_get(maps, "sig-signing-nodes", &obj);
845 INSIST(result == ISC_R_SUCCESS);
846 dns_zone_setnodes(zone, cfg_obj_asuint32(obj));
848 obj = NULL;
849 result = ns_config_get(maps, "sig-signing-type", &obj);
850 INSIST(result == ISC_R_SUCCESS);
851 dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));
853 obj = NULL;
854 result = ns_config_get(maps, "update-check-ksk", &obj);
855 INSIST(result == ISC_R_SUCCESS);
856 dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
857 cfg_obj_asboolean(obj));
859 obj = NULL;
860 result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj);
861 INSIST(result == ISC_R_SUCCESS);
862 dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
863 cfg_obj_asboolean(obj));
864 } else if (ztype == dns_zone_slave) {
865 RETERR(configure_zone_acl(zconfig, vconfig, config,
866 allow_update_forwarding, ac, zone,
867 dns_zone_setforwardacl,
868 dns_zone_clearforwardacl));
872 * Primary master functionality.
874 if (ztype == dns_zone_master) {
875 isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE;
876 isc_boolean_t create = ISC_FALSE;
878 obj = NULL;
879 result = ns_config_get(maps, "check-wildcard", &obj);
880 if (result == ISC_R_SUCCESS)
881 check = cfg_obj_asboolean(obj);
882 else
883 check = ISC_FALSE;
884 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check);
886 obj = NULL;
887 result = ns_config_get(maps, "check-dup-records", &obj);
888 INSIST(obj != NULL);
889 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
890 fail = ISC_FALSE;
891 check = ISC_TRUE;
892 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
893 fail = check = ISC_TRUE;
894 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
895 fail = check = ISC_FALSE;
896 } else
897 INSIST(0);
898 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check);
899 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);
901 obj = NULL;
902 result = ns_config_get(maps, "check-mx", &obj);
903 INSIST(obj != NULL);
904 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
905 fail = ISC_FALSE;
906 check = ISC_TRUE;
907 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
908 fail = check = ISC_TRUE;
909 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
910 fail = check = ISC_FALSE;
911 } else
912 INSIST(0);
913 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMX, check);
914 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMXFAIL, fail);
916 obj = NULL;
917 result = ns_config_get(maps, "check-integrity", &obj);
918 INSIST(obj != NULL);
919 dns_zone_setoption(zone, DNS_ZONEOPT_CHECKINTEGRITY,
920 cfg_obj_asboolean(obj));
922 obj = NULL;
923 result = ns_config_get(maps, "check-mx-cname", &obj);
924 INSIST(obj != NULL);
925 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
926 warn = ISC_TRUE;
927 ignore = ISC_FALSE;
928 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
929 warn = ignore = ISC_FALSE;
930 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
931 warn = ignore = ISC_TRUE;
932 } else
933 INSIST(0);
934 dns_zone_setoption(zone, DNS_ZONEOPT_WARNMXCNAME, warn);
935 dns_zone_setoption(zone, DNS_ZONEOPT_IGNOREMXCNAME, ignore);
937 obj = NULL;
938 result = ns_config_get(maps, "check-srv-cname", &obj);
939 INSIST(obj != NULL);
940 if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
941 warn = ISC_TRUE;
942 ignore = ISC_FALSE;
943 } else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
944 warn = ignore = ISC_FALSE;
945 } else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
946 warn = ignore = ISC_TRUE;
947 } else
948 INSIST(0);
949 dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn);
950 dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore);
952 obj = NULL;
953 result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj);
954 INSIST(obj != NULL);
955 dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE,
956 cfg_obj_asboolean(obj));
958 obj = NULL;
959 result = cfg_map_get(zoptions, "auto-dnssec", &obj);
960 if (result == ISC_R_SUCCESS) {
961 const char *arg = cfg_obj_asstring(obj);
962 if (strcasecmp(arg, "allow") == 0)
963 allow = ISC_TRUE;
964 else if (strcasecmp(arg, "maintain") == 0)
965 allow = maint = ISC_TRUE;
966 else if (strcasecmp(arg, "create") == 0)
967 allow = maint = create = ISC_TRUE;
968 else if (strcasecmp(arg, "off") == 0)
970 else
971 INSIST(0);
972 dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
973 dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
974 dns_zone_setkeyopt(zone, DNS_ZONEKEY_CREATE, create);
979 * Configure slave functionality.
981 switch (ztype) {
982 case dns_zone_slave:
983 case dns_zone_stub:
984 count = 0;
985 obj = NULL;
986 result = cfg_map_get(zoptions, "masters", &obj);
987 if (obj != NULL) {
988 addrs = NULL;
989 keynames = NULL;
990 RETERR(ns_config_getipandkeylist(config, obj, mctx,
991 &addrs, &keynames,
992 &count));
993 result = dns_zone_setmasterswithkeys(zone, addrs,
994 keynames, count);
995 ns_config_putipandkeylist(mctx, &addrs, &keynames,
996 count);
997 } else
998 result = dns_zone_setmasters(zone, NULL, 0);
999 RETERR(result);
1001 multi = ISC_FALSE;
1002 if (count > 1) {
1003 obj = NULL;
1004 result = ns_config_get(maps, "multi-master", &obj);
1005 INSIST(result == ISC_R_SUCCESS);
1006 multi = cfg_obj_asboolean(obj);
1008 dns_zone_setoption(zone, DNS_ZONEOPT_MULTIMASTER, multi);
1010 obj = NULL;
1011 result = ns_config_get(maps, "max-transfer-time-in", &obj);
1012 INSIST(result == ISC_R_SUCCESS);
1013 dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60);
1015 obj = NULL;
1016 result = ns_config_get(maps, "max-transfer-idle-in", &obj);
1017 INSIST(result == ISC_R_SUCCESS);
1018 dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60);
1020 obj = NULL;
1021 result = ns_config_get(maps, "max-refresh-time", &obj);
1022 INSIST(result == ISC_R_SUCCESS);
1023 dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj));
1025 obj = NULL;
1026 result = ns_config_get(maps, "min-refresh-time", &obj);
1027 INSIST(result == ISC_R_SUCCESS);
1028 dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj));
1030 obj = NULL;
1031 result = ns_config_get(maps, "max-retry-time", &obj);
1032 INSIST(result == ISC_R_SUCCESS);
1033 dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj));
1035 obj = NULL;
1036 result = ns_config_get(maps, "min-retry-time", &obj);
1037 INSIST(result == ISC_R_SUCCESS);
1038 dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj));
1040 obj = NULL;
1041 result = ns_config_get(maps, "transfer-source", &obj);
1042 INSIST(result == ISC_R_SUCCESS);
1043 RETERR(dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj)));
1044 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1046 obj = NULL;
1047 result = ns_config_get(maps, "transfer-source-v6", &obj);
1048 INSIST(result == ISC_R_SUCCESS);
1049 RETERR(dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj)));
1050 ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));
1052 obj = NULL;
1053 result = ns_config_get(maps, "alt-transfer-source", &obj);
1054 INSIST(result == ISC_R_SUCCESS);
1055 RETERR(dns_zone_setaltxfrsource4(zone, cfg_obj_assockaddr(obj)));
1057 obj = NULL;
1058 result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
1059 INSIST(result == ISC_R_SUCCESS);
1060 RETERR(dns_zone_setaltxfrsource6(zone, cfg_obj_assockaddr(obj)));
1062 obj = NULL;
1063 (void)ns_config_get(maps, "use-alt-transfer-source", &obj);
1064 if (obj == NULL) {
1066 * Default off when views are in use otherwise
1067 * on for BIND 8 compatibility.
1069 view = dns_zone_getview(zone);
1070 if (view != NULL && strcmp(view->name, "_default") == 0)
1071 alt = ISC_TRUE;
1072 else
1073 alt = ISC_FALSE;
1074 } else
1075 alt = cfg_obj_asboolean(obj);
1076 dns_zone_setoption(zone, DNS_ZONEOPT_USEALTXFRSRC, alt);
1078 obj = NULL;
1079 (void)ns_config_get(maps, "try-tcp-refresh", &obj);
1080 dns_zone_setoption(zone, DNS_ZONEOPT_TRYTCPREFRESH,
1081 cfg_obj_asboolean(obj));
1082 break;
1084 default:
1085 break;
1088 return (ISC_R_SUCCESS);
1091 isc_boolean_t
1092 ns_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig) {
1093 const cfg_obj_t *zoptions = NULL;
1094 const cfg_obj_t *obj = NULL;
1095 const char *cfilename;
1096 const char *zfilename;
1098 zoptions = cfg_tuple_get(zconfig, "options");
1100 if (zonetype_fromconfig(zoptions) != dns_zone_gettype(zone))
1101 return (ISC_FALSE);
1103 obj = NULL;
1104 (void)cfg_map_get(zoptions, "file", &obj);
1105 if (obj != NULL)
1106 cfilename = cfg_obj_asstring(obj);
1107 else
1108 cfilename = NULL;
1109 zfilename = dns_zone_getfile(zone);
1110 if (!((cfilename == NULL && zfilename == NULL) ||
1111 (cfilename != NULL && zfilename != NULL &&
1112 strcmp(cfilename, zfilename) == 0)))
1113 return (ISC_FALSE);
1115 return (ISC_TRUE);