Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isccfg / check.c
blob415691021479299fd8a3fdea5cb42e6db2beea4f
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2001-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: check.c,v 1.14.2.25 2004/07/29 00:08:17 marka Exp $ */
20 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
25 #include <isc/buffer.h>
26 #include <isc/log.h>
27 #include <isc/mem.h>
28 #include <isc/netaddr.h>
29 #include <isc/result.h>
30 #include <isc/sockaddr.h>
31 #include <isc/symtab.h>
32 #include <isc/util.h>
34 #include <dns/fixedname.h>
35 #include <dns/rdataclass.h>
37 #include <isccfg/cfg.h>
38 #include <isccfg/check.h>
40 static void
41 freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
42 UNUSED(type);
43 UNUSED(value);
44 isc_mem_free(userarg, key);
47 static isc_result_t
48 check_forward(cfg_obj_t *options, isc_log_t *logctx) {
49 cfg_obj_t *forward = NULL;
50 cfg_obj_t *forwarders = NULL;
52 (void)cfg_map_get(options, "forward", &forward);
53 (void)cfg_map_get(options, "forwarders", &forwarders);
55 if (forward != NULL && forwarders == NULL) {
56 cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
57 "no matching 'forwarders' statement");
58 return (ISC_R_FAILURE);
60 return (ISC_R_SUCCESS);
63 typedef struct {
64 const char *name;
65 unsigned int scale;
66 } intervaltable;
68 static isc_result_t
69 check_options(cfg_obj_t *options, isc_log_t *logctx) {
70 isc_result_t result = ISC_R_SUCCESS;
71 unsigned int i;
72 cfg_obj_t *obj;
74 static intervaltable intervals[] = {
75 { "cleaning-interval", 60 },
76 { "heartbeat-interval", 60 },
77 { "interface-interval", 60 },
78 { "max-transfer-idle-in", 60 },
79 { "max-transfer-idle-out", 60 },
80 { "max-transfer-time-in", 60 },
81 { "max-transfer-time-out", 60 },
82 { "sig-validity-interval", 86400},
83 { "statistics-interval", 60 },
87 * Check that fields specified in units of time other than seconds
88 * have reasonable values.
90 for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
91 isc_uint32_t val;
92 cfg_obj_t *obj = NULL;
93 (void)cfg_map_get(options, intervals[i].name, &obj);
94 if (obj == NULL)
95 continue;
96 val = cfg_obj_asuint32(obj);
97 if (val > (ISC_UINT32_MAX / intervals[i].scale)) {
98 cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
99 "%s '%d' is out of range",
100 intervals[i].name, val);
101 result = ISC_R_RANGE;
105 obj = NULL;
106 (void)cfg_map_get(options, "root-delegation-only", &obj);
107 if (obj != NULL) {
108 if (!cfg_obj_isvoid(obj)) {
109 cfg_listelt_t *element;
110 cfg_obj_t *exclude;
111 char *str;
112 dns_fixedname_t fixed;
113 dns_name_t *name;
114 isc_buffer_t b;
115 isc_result_t tresult;
117 dns_fixedname_init(&fixed);
118 name = dns_fixedname_name(&fixed);
119 for (element = cfg_list_first(obj);
120 element != NULL;
121 element = cfg_list_next(element)) {
122 exclude = cfg_listelt_value(element);
123 str = cfg_obj_asstring(exclude);
124 isc_buffer_init(&b, str, strlen(str));
125 isc_buffer_add(&b, strlen(str));
126 tresult = dns_name_fromtext(name, &b,
127 dns_rootname,
128 ISC_FALSE, NULL);
129 if (tresult != ISC_R_SUCCESS) {
130 cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
131 "bad domain name '%s'",
132 str);
133 result = tresult;
138 return (result);
141 #define MASTERZONE 1
142 #define SLAVEZONE 2
143 #define STUBZONE 4
144 #define HINTZONE 8
145 #define FORWARDZONE 16
146 #define DELEGATIONZONE 32
148 typedef struct {
149 const char *name;
150 int allowed;
151 } optionstable;
153 static isc_result_t
154 check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab, isc_log_t *logctx,
155 isc_mem_t *mctx)
157 const char *zname;
158 const char *typestr;
159 unsigned int ztype;
160 cfg_obj_t *zoptions;
161 cfg_obj_t *obj = NULL;
162 cfg_obj_t *addrlist = NULL;
163 isc_symvalue_t symvalue;
164 isc_result_t result = ISC_R_SUCCESS;
165 isc_result_t tresult;
166 unsigned int i;
167 dns_fixedname_t fixedname;
168 isc_buffer_t b;
170 static optionstable options[] = {
171 { "allow-query", MASTERZONE | SLAVEZONE | STUBZONE },
172 { "allow-notify", SLAVEZONE },
173 { "allow-transfer", MASTERZONE | SLAVEZONE },
174 { "notify", MASTERZONE | SLAVEZONE },
175 { "also-notify", MASTERZONE | SLAVEZONE },
176 { "dialup", MASTERZONE | SLAVEZONE | STUBZONE },
177 { "delegation-only", HINTZONE | STUBZONE },
178 { "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
179 { "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
180 { "maintain-ixfr-base", MASTERZONE | SLAVEZONE },
181 { "max-ixfr-log-size", MASTERZONE | SLAVEZONE },
182 { "notify-source", MASTERZONE | SLAVEZONE },
183 { "notify-source-v6", MASTERZONE | SLAVEZONE },
184 { "transfer-source", SLAVEZONE | STUBZONE },
185 { "transfer-source-v6", SLAVEZONE | STUBZONE },
186 { "max-transfer-time-in", SLAVEZONE | STUBZONE },
187 { "max-transfer-time-out", MASTERZONE | SLAVEZONE },
188 { "max-transfer-idle-in", SLAVEZONE | STUBZONE },
189 { "max-transfer-idle-out", MASTERZONE | SLAVEZONE },
190 { "max-retry-time", SLAVEZONE | STUBZONE },
191 { "min-retry-time", SLAVEZONE | STUBZONE },
192 { "max-refresh-time", SLAVEZONE | STUBZONE },
193 { "min-refresh-time", SLAVEZONE | STUBZONE },
194 { "sig-validity-interval", MASTERZONE },
195 { "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE },
196 { "allow-update", MASTERZONE },
197 { "allow-update-forwarding", SLAVEZONE },
198 { "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE},
199 { "ixfr-base", MASTERZONE | SLAVEZONE },
200 { "ixfr-tmp-file", MASTERZONE | SLAVEZONE },
201 { "masters", SLAVEZONE | STUBZONE },
202 { "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
203 { "update-policy", MASTERZONE },
204 { "database", MASTERZONE | SLAVEZONE | STUBZONE },
207 static optionstable dialups[] = {
208 { "notify", MASTERZONE | SLAVEZONE },
209 { "notify-passive", SLAVEZONE },
210 { "refresh", SLAVEZONE | STUBZONE },
211 { "passive", SLAVEZONE | STUBZONE },
214 zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
216 zoptions = cfg_tuple_get(zconfig, "options");
218 obj = NULL;
219 (void)cfg_map_get(zoptions, "type", &obj);
220 if (obj == NULL) {
221 cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
222 "zone '%s': type not present", zname);
223 return (ISC_R_FAILURE);
226 typestr = cfg_obj_asstring(obj);
227 if (strcasecmp(typestr, "master") == 0)
228 ztype = MASTERZONE;
229 else if (strcasecmp(typestr, "slave") == 0)
230 ztype = SLAVEZONE;
231 else if (strcasecmp(typestr, "stub") == 0)
232 ztype = STUBZONE;
233 else if (strcasecmp(typestr, "forward") == 0)
234 ztype = FORWARDZONE;
235 else if (strcasecmp(typestr, "hint") == 0)
236 ztype = HINTZONE;
237 else if (strcasecmp(typestr, "delegation-only") == 0)
238 ztype = DELEGATIONZONE;
239 else {
240 cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
241 "zone '%s': invalid type %s",
242 zname, typestr);
243 return (ISC_R_FAILURE);
247 * Look for an already existing zone.
248 * We need to make this cannonical as isc_symtab_define()
249 * deals with strings.
251 dns_fixedname_init(&fixedname);
252 isc_buffer_init(&b, zname, strlen(zname));
253 isc_buffer_add(&b, strlen(zname));
254 result = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
255 dns_rootname, ISC_TRUE, NULL);
256 if (result != ISC_R_SUCCESS) {
257 cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
258 "zone '%s': is not a valid name", zname);
259 result = ISC_R_FAILURE;
260 } else {
261 char namebuf[DNS_NAME_FORMATSIZE];
262 char *key;
264 dns_name_format(dns_fixedname_name(&fixedname),
265 namebuf, sizeof(namebuf));
266 key = isc_mem_strdup(mctx, namebuf);
267 if (key == NULL)
268 return (ISC_R_NOMEMORY);
269 symvalue.as_pointer = NULL;
270 tresult = isc_symtab_define(symtab, key,
271 ztype == HINTZONE ? 1 : 2,
272 symvalue, isc_symexists_reject);
273 if (tresult == ISC_R_EXISTS) {
274 isc_mem_free(mctx, key);
275 cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
276 "zone '%s': already exists ", zname);
277 result = ISC_R_FAILURE;
278 } else if (tresult != ISC_R_SUCCESS) {
279 isc_mem_free(mctx, key);
281 return (tresult);
286 * Look for inappropriate options for the given zone type.
288 for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
289 obj = NULL;
290 if ((options[i].allowed & ztype) == 0 &&
291 cfg_map_get(zoptions, options[i].name, &obj) ==
292 ISC_R_SUCCESS)
294 if (strcmp(options[i].name, "allow-update") != 0 ||
295 ztype != SLAVEZONE) {
296 cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
297 "option '%s' is not allowed "
298 "in '%s' zone '%s'",
299 options[i].name, typestr, zname);
300 result = ISC_R_FAILURE;
301 } else
302 cfg_obj_log(obj, logctx, ISC_LOG_WARNING,
303 "option '%s' is not allowed "
304 "in '%s' zone '%s'",
305 options[i].name, typestr, zname);
310 * Slave & stub zones must have a "masters" field.
312 if (ztype == SLAVEZONE || ztype == STUBZONE) {
313 obj = NULL;
314 if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) {
315 cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
316 "zone '%s': missing 'masters' entry",
317 zname);
318 result = ISC_R_FAILURE;
319 } else {
320 addrlist = cfg_tuple_get(obj, "addresses");
321 if (cfg_list_first(addrlist) == NULL) {
322 cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
323 "zone '%s': empty 'masters' entry",
324 zname);
325 result = ISC_R_FAILURE;
331 * Master zones can't have both "allow-update" and "update-policy".
333 if (ztype == MASTERZONE) {
334 isc_result_t res1, res2;
335 obj = NULL;
336 res1 = cfg_map_get(zoptions, "allow-update", &obj);
337 obj = NULL;
338 res2 = cfg_map_get(zoptions, "update-policy", &obj);
339 if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
340 cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
341 "zone '%s': 'allow-update' is ignored "
342 "when 'update-policy' is present",
343 zname);
344 result = ISC_R_FAILURE;
349 * Check the excessively complicated "dialup" option.
351 if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) {
352 cfg_obj_t *dialup = NULL;
353 cfg_map_get(zoptions, "dialup", &dialup);
354 if (dialup != NULL && cfg_obj_isstring(dialup)) {
355 char *str = cfg_obj_asstring(dialup);
356 for (i = 0;
357 i < sizeof(dialups) / sizeof(dialups[0]);
358 i++)
360 if (strcasecmp(dialups[i].name, str) != 0)
361 continue;
362 if ((dialups[i].allowed & ztype) == 0) {
363 cfg_obj_log(obj, logctx,
364 ISC_LOG_ERROR,
365 "dialup type '%s' is not "
366 "allowed in '%s' "
367 "zone '%s'",
368 str, typestr, zname);
369 result = ISC_R_FAILURE;
371 break;
373 if (i == sizeof(dialups) / sizeof(dialups[0])) {
374 cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
375 "invalid dialup type '%s' in zone "
376 "'%s'", str, zname);
377 result = ISC_R_FAILURE;
383 * Check that forwarding is reasonable.
385 if (check_forward(zoptions, logctx) != ISC_R_SUCCESS)
386 result = ISC_R_FAILURE;
389 * Check various options.
391 tresult = check_options(zoptions, logctx);
392 if (tresult != ISC_R_SUCCESS)
393 result = tresult;
395 return (result);
398 isc_result_t
399 cfg_check_key(cfg_obj_t *key, isc_log_t *logctx) {
400 cfg_obj_t *algobj = NULL;
401 cfg_obj_t *secretobj = NULL;
402 const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
404 cfg_map_get(key, "algorithm", &algobj);
405 cfg_map_get(key, "secret", &secretobj);
406 if (secretobj == NULL || algobj == NULL) {
407 cfg_obj_log(key, logctx, ISC_LOG_ERROR,
408 "key '%s' must have both 'secret' and "
409 "'algorithm' defined",
410 keyname);
411 return ISC_R_FAILURE;
413 return ISC_R_SUCCESS;
416 static isc_result_t
417 check_keylist(cfg_obj_t *keys, isc_symtab_t *symtab, isc_log_t *logctx) {
418 isc_result_t result = ISC_R_SUCCESS;
419 isc_result_t tresult;
420 cfg_listelt_t *element;
422 for (element = cfg_list_first(keys);
423 element != NULL;
424 element = cfg_list_next(element))
426 cfg_obj_t *key = cfg_listelt_value(element);
427 const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
428 isc_symvalue_t symvalue;
430 symvalue.as_pointer = NULL;
431 tresult = isc_symtab_define(symtab, keyname, 1,
432 symvalue, isc_symexists_reject);
433 if (tresult == ISC_R_EXISTS) {
434 cfg_obj_log(key, logctx, ISC_LOG_ERROR,
435 "key '%s': already exists ", keyname);
436 result = tresult;
437 } else if (tresult != ISC_R_SUCCESS)
438 return (tresult);
440 tresult = cfg_check_key(key, logctx);
441 if (tresult != ISC_R_SUCCESS)
442 return (tresult);
444 return (result);
447 static isc_result_t
448 check_servers(cfg_obj_t *servers, isc_log_t *logctx) {
449 isc_result_t result = ISC_R_SUCCESS;
450 cfg_listelt_t *e1, *e2;
451 cfg_obj_t *v1, *v2;
452 isc_sockaddr_t *s1, *s2;
453 isc_netaddr_t na;
455 for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) {
456 v1 = cfg_listelt_value(e1);
457 s1 = cfg_obj_assockaddr(cfg_map_getname(v1));
458 e2 = e1;
459 while ((e2 = cfg_list_next(e2)) != NULL) {
460 v2 = cfg_listelt_value(e2);
461 s2 = cfg_obj_assockaddr(cfg_map_getname(v2));
462 if (isc_sockaddr_eqaddr(s1, s2)) {
463 isc_buffer_t target;
464 char buf[128];
466 isc_netaddr_fromsockaddr(&na, s2);
467 isc_buffer_init(&target, buf, sizeof(buf) - 1);
468 INSIST(isc_netaddr_totext(&na, &target)
469 == ISC_R_SUCCESS);
470 buf[isc_buffer_usedlength(&target)] = '\0';
472 cfg_obj_log(v2, logctx, ISC_LOG_ERROR,
473 "server '%s': already exists",
474 buf);
475 result = ISC_R_FAILURE;
479 return (result);
482 static isc_result_t
483 check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, isc_log_t *logctx, isc_mem_t *mctx)
485 cfg_obj_t *servers = NULL;
486 cfg_obj_t *zones = NULL;
487 cfg_obj_t *keys = NULL;
488 cfg_listelt_t *element;
489 isc_symtab_t *symtab = NULL;
490 isc_result_t result = ISC_R_SUCCESS;
491 isc_result_t tresult = ISC_R_SUCCESS;
494 * Check that all zone statements are syntactically correct and
495 * there are no duplicate zones.
497 tresult = isc_symtab_create(mctx, 100, freekey, mctx,
498 ISC_FALSE, &symtab);
499 if (tresult != ISC_R_SUCCESS)
500 return (ISC_R_NOMEMORY);
502 if (vconfig != NULL)
503 (void)cfg_map_get(vconfig, "zone", &zones);
504 else
505 (void)cfg_map_get(config, "zone", &zones);
507 for (element = cfg_list_first(zones);
508 element != NULL;
509 element = cfg_list_next(element))
511 cfg_obj_t *zone = cfg_listelt_value(element);
513 if (check_zoneconf(zone, symtab, logctx, mctx) != ISC_R_SUCCESS)
514 result = ISC_R_FAILURE;
517 isc_symtab_destroy(&symtab);
520 * Check that all key statements are syntactically correct and
521 * there are no duplicate keys.
523 tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
524 if (tresult != ISC_R_SUCCESS)
525 return (ISC_R_NOMEMORY);
527 cfg_map_get(config, "key", &keys);
528 tresult = check_keylist(keys, symtab, logctx);
529 if (tresult == ISC_R_EXISTS)
530 result = ISC_R_FAILURE;
531 else if (tresult != ISC_R_SUCCESS) {
532 isc_symtab_destroy(&symtab);
533 return (tresult);
536 if (vconfig != NULL) {
537 keys = NULL;
538 (void)cfg_map_get(vconfig, "key", &keys);
539 tresult = check_keylist(keys, symtab, logctx);
540 if (tresult == ISC_R_EXISTS)
541 result = ISC_R_FAILURE;
542 else if (tresult != ISC_R_SUCCESS) {
543 isc_symtab_destroy(&symtab);
544 return (tresult);
548 isc_symtab_destroy(&symtab);
551 * Check that forwarding is reasonable.
553 if (vconfig == NULL) {
554 cfg_obj_t *options = NULL;
555 cfg_map_get(config, "options", &options);
556 if (options != NULL)
557 if (check_forward(options, logctx) != ISC_R_SUCCESS)
558 result = ISC_R_FAILURE;
559 } else {
560 if (check_forward(vconfig, logctx) != ISC_R_SUCCESS)
561 result = ISC_R_FAILURE;
565 if (vconfig != NULL) {
566 (void)cfg_map_get(vconfig, "server", &servers);
567 if (servers != NULL &&
568 check_servers(servers, logctx) != ISC_R_SUCCESS)
569 result = ISC_R_FAILURE;
572 if (vconfig != NULL)
573 tresult = check_options(vconfig, logctx);
574 else
575 tresult = check_options(config, logctx);
576 if (tresult != ISC_R_SUCCESS)
577 result = tresult;
579 return (result);
583 isc_result_t
584 cfg_check_namedconf(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
585 cfg_obj_t *options = NULL;
586 cfg_obj_t *servers = NULL;
587 cfg_obj_t *views = NULL;
588 cfg_obj_t *acls = NULL;
589 cfg_obj_t *obj;
590 cfg_listelt_t *velement;
591 isc_result_t result = ISC_R_SUCCESS;
592 isc_result_t tresult;
593 isc_symtab_t *symtab = NULL;
595 static const char *builtin[] = { "localhost", "localnets",
596 "any", "none" };
598 (void)cfg_map_get(config, "options", &options);
600 if (options != NULL &&
601 check_options(options, logctx) != ISC_R_SUCCESS)
602 result = ISC_R_FAILURE;
604 (void)cfg_map_get(config, "server", &servers);
605 if (servers != NULL &&
606 check_servers(servers, logctx) != ISC_R_SUCCESS)
607 result = ISC_R_FAILURE;
609 (void)cfg_map_get(config, "view", &views);
611 if (views == NULL) {
612 if (check_viewconf(config, NULL, logctx, mctx)
613 != ISC_R_SUCCESS)
614 result = ISC_R_FAILURE;
615 } else {
616 cfg_obj_t *zones = NULL;
618 (void)cfg_map_get(config, "zone", &zones);
619 if (zones != NULL) {
620 cfg_obj_log(zones, logctx, ISC_LOG_ERROR,
621 "when using 'view' statements, "
622 "all zones must be in views");
623 result = ISC_R_FAILURE;
627 tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
628 if (tresult != ISC_R_SUCCESS)
629 result = tresult;
630 for (velement = cfg_list_first(views);
631 velement != NULL;
632 velement = cfg_list_next(velement))
634 cfg_obj_t *view = cfg_listelt_value(velement);
635 cfg_obj_t *vname = cfg_tuple_get(view, "name");
636 cfg_obj_t *voptions = cfg_tuple_get(view, "options");
637 cfg_obj_t *vclassobj = cfg_tuple_get(view, "class");
638 dns_rdataclass_t vclass = dns_rdataclass_in;
639 isc_result_t tresult = ISC_R_SUCCESS;
640 const char *key = cfg_obj_asstring(vname);
641 isc_symvalue_t symvalue;
643 if (cfg_obj_isstring(vclassobj)) {
644 isc_textregion_t r;
646 DE_CONST(cfg_obj_asstring(vclassobj), r.base);
647 r.length = strlen(r.base);
648 tresult = dns_rdataclass_fromtext(&vclass, &r);
649 if (tresult != ISC_R_SUCCESS)
650 cfg_obj_log(vclassobj, logctx, ISC_LOG_ERROR,
651 "view '%s': invalid class %s",
652 cfg_obj_asstring(vname), r.base);
654 if (tresult == ISC_R_SUCCESS && symtab != NULL) {
655 symvalue.as_pointer = view;
656 tresult = isc_symtab_define(symtab, key, vclass,
657 symvalue,
658 isc_symexists_reject);
659 if (tresult == ISC_R_EXISTS) {
660 cfg_obj_log(view, logctx, ISC_LOG_ERROR,
661 "view '%s': already exists", key);
662 result = tresult;
663 } else if (result != ISC_R_SUCCESS) {
664 result = tresult;
665 } else if ((strcasecmp(key, "_bind") == 0 &&
666 vclass == dns_rdataclass_ch) ||
667 (strcasecmp(key, "_default") == 0 &&
668 vclass == dns_rdataclass_in)) {
669 cfg_obj_log(view, logctx, ISC_LOG_ERROR,
670 "attempt to redefine builtin view "
671 "'%s'", key);
672 result = ISC_R_EXISTS;
675 if (check_viewconf(config, voptions, logctx, mctx)
676 != ISC_R_SUCCESS)
677 result = ISC_R_FAILURE;
679 if (symtab != NULL)
680 isc_symtab_destroy(&symtab);
682 if (views != NULL && options != NULL) {
683 obj = NULL;
684 tresult = cfg_map_get(options, "cache-file", &obj);
685 if (tresult == ISC_R_SUCCESS) {
686 cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
687 "'cache-file' cannot be a global "
688 "option if views are present");
689 result = ISC_R_FAILURE;
693 tresult = cfg_map_get(config, "acl", &acls);
694 if (tresult == ISC_R_SUCCESS) {
695 cfg_listelt_t *elt;
696 cfg_listelt_t *elt2;
697 const char *aclname;
699 for (elt = cfg_list_first(acls);
700 elt != NULL;
701 elt = cfg_list_next(elt)) {
702 cfg_obj_t *acl = cfg_listelt_value(elt);
703 unsigned int i;
705 aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
706 for (i = 0;
707 i < sizeof(builtin) / sizeof(builtin[0]);
708 i++)
709 if (strcasecmp(aclname, builtin[i]) == 0) {
710 cfg_obj_log(acl, logctx, ISC_LOG_ERROR,
711 "attempt to redefine "
712 "builtin acl '%s'",
713 aclname);
714 result = ISC_R_FAILURE;
715 break;
718 for (elt2 = cfg_list_next(elt);
719 elt2 != NULL;
720 elt2 = cfg_list_next(elt2)) {
721 cfg_obj_t *acl2 = cfg_listelt_value(elt2);
722 const char *name;
723 name = cfg_obj_asstring(cfg_tuple_get(acl2,
724 "name"));
725 if (strcasecmp(aclname, name) == 0) {
726 cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
727 "attempt to redefine "
728 "acl '%s'", name);
729 result = ISC_R_FAILURE;
730 break;
736 return (result);