check.c 17.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * Copyright (C) 2001  Internet Software Consortium.
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

18
/* $Id: check.c,v 1.20 2002/02/11 00:46:26 marka Exp $ */
19
20
21
22
23
24

#include <config.h>

#include <stdlib.h>
#include <string.h>

25
#include <isc/buffer.h>
26
27
#include <isc/log.h>
#include <isc/result.h>
28
#include <isc/symtab.h>
Brian Wellington's avatar
Brian Wellington committed
29
#include <isc/util.h>
30
31
32
#include <isc/region.h>

#include <dns/rdataclass.h>
33
#include <dns/fixedname.h>
34
35

#include <isccfg/cfg.h>
36
37

#include <bind9/check.h>
38

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
static isc_result_t
check_forward(cfg_obj_t *options, isc_log_t *logctx) {
	cfg_obj_t *forward = NULL;
	cfg_obj_t *forwarders = NULL;

	(void)cfg_map_get(options, "forward", &forward);
	(void)cfg_map_get(options, "forwarders", &forwarders);

	if (forward != NULL && forwarders == NULL) {
		cfg_obj_log(forward, logctx, ISC_LOG_ERROR,
			    "no matching 'forwarders' statement");
		return (ISC_R_FAILURE);
	}
	return (ISC_R_SUCCESS);
}

55
56
57
typedef struct {
	const char *name;
	unsigned int scale;
58
	unsigned int max;
59
60
61
} intervaltable;

static isc_result_t
62
check_options(cfg_obj_t *options, isc_log_t *logctx) {
63
64
	isc_result_t result = ISC_R_SUCCESS;
	unsigned int i;
65
	cfg_obj_t *obj = NULL;
66
67

	static intervaltable intervals[] = {
68
69
70
71
72
73
74
75
76
	{ "cleaning-interval", 60, 28 * 24 * 60 },	/* 28 days */
	{ "heartbeat-interval", 60, 28 * 24 * 60 },	/* 28 days */
	{ "interface-interval", 60, 28 * 24 * 60 },	/* 28 days */
	{ "max-transfer-idle-in", 60, 28 * 24 * 60 },	/* 28 days */
	{ "max-transfer-idle-out", 60, 28 * 24 * 60 },	/* 28 days */
	{ "max-transfer-time-in", 60, 28 * 24 * 60 },	/* 28 days */
	{ "max-transfer-time-out", 60, 28 * 24 * 60 },	/* 28 days */
	{ "sig-validity-interval", 86400, 10 * 366 },	/* 10 years */
	{ "statistics-interval", 60, 28 * 24 * 60 },	/* 28 days */
77
78
79
80
81
82
83
84
	};

	/*
	 * Check that fields specified in units of time other than seconds
	 * have reasonable values.
	 */
	for (i = 0; i < sizeof(intervals) / sizeof(intervals[0]); i++) {
		isc_uint32_t val;
85
		obj = NULL;
86
87
88
89
		(void)cfg_map_get(options, intervals[i].name, &obj);
		if (obj == NULL)
			continue;
		val = cfg_obj_asuint32(obj);
90
91
92
93
94
95
96
		if (val > intervals[i].max) {
			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
				    "%s '%u' is out of range (0..%u)",
				    intervals[i].name, val,
				    intervals[i].max);
			result = ISC_R_RANGE;
		} else if (val > (ISC_UINT32_MAX / intervals[i].scale)) {
97
98
99
100
101
102
103
104
105
			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
				    "%s '%d' is out of range",
				    intervals[i].name, val);
			result = ISC_R_RANGE;
		}
	}
	return (result);
}

106
107
108
109
110
111
112
113
114
115
116
117
#define MASTERZONE	1
#define SLAVEZONE	2
#define STUBZONE	4
#define HINTZONE	8
#define FORWARDZONE	16

typedef struct {
	const char *name;
	int allowed;
} optionstable;

static isc_result_t
118
119
120
check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab,
	       dns_rdataclass_t defclass, isc_log_t *logctx)
{
121
122
123
124
125
	const char *zname;
	const char *typestr;
	unsigned int ztype;
	cfg_obj_t *zoptions;
	cfg_obj_t *obj = NULL;
126
	cfg_obj_t *addrlist = NULL;
127
	isc_symvalue_t symvalue;
Brian Wellington's avatar
Brian Wellington committed
128
	isc_result_t result = ISC_R_SUCCESS;
129
	isc_result_t tresult;
130
	unsigned int i;
131
	dns_rdataclass_t zclass;
132
133
	dns_fixedname_t fixedname;
	isc_buffer_t b;
134
135
136

	static optionstable options[] = {
	{ "allow-query", MASTERZONE | SLAVEZONE | STUBZONE },
137
	{ "allow-notify", SLAVEZONE },
138
	{ "allow-transfer", MASTERZONE | SLAVEZONE },
139
140
141
142
143
144
145
	{ "notify", MASTERZONE | SLAVEZONE },
	{ "also-notify", MASTERZONE | SLAVEZONE },
	{ "dialup", MASTERZONE | SLAVEZONE | STUBZONE },
	{ "forward", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
	{ "forwarders", MASTERZONE | SLAVEZONE | STUBZONE | FORWARDZONE},
	{ "maintain-ixfr-base", MASTERZONE | SLAVEZONE },
	{ "max-ixfr-log-size", MASTERZONE | SLAVEZONE },
146
147
	{ "notify-source", MASTERZONE | SLAVEZONE },
	{ "notify-source-v6", MASTERZONE | SLAVEZONE },
148
149
	{ "transfer-source", SLAVEZONE | STUBZONE },
	{ "transfer-source-v6", SLAVEZONE | STUBZONE },
150
151
152
153
154
155
156
157
158
159
160
	{ "max-transfer-time-in", SLAVEZONE | STUBZONE },
	{ "max-transfer-time-out", MASTERZONE | SLAVEZONE },
	{ "max-transfer-idle-in", SLAVEZONE | STUBZONE },
	{ "max-transfer-idle-out", MASTERZONE | SLAVEZONE },
	{ "max-retry-time", SLAVEZONE | STUBZONE },
	{ "min-retry-time", SLAVEZONE | STUBZONE },
	{ "max-refresh-time", SLAVEZONE | STUBZONE },
	{ "min-refresh-time", SLAVEZONE | STUBZONE },
	{ "sig-validity-interval", MASTERZONE },
	{ "zone-statistics", MASTERZONE | SLAVEZONE | STUBZONE },
	{ "allow-update", MASTERZONE },
161
	{ "allow-update-forwarding", SLAVEZONE },
162
163
164
165
166
167
168
	{ "file", MASTERZONE | SLAVEZONE | STUBZONE | HINTZONE},
	{ "ixfr-base", MASTERZONE | SLAVEZONE },
	{ "ixfr-tmp-file", MASTERZONE | SLAVEZONE },
	{ "masters", SLAVEZONE | STUBZONE },
	{ "pubkey", MASTERZONE | SLAVEZONE | STUBZONE },
	{ "update-policy", MASTERZONE },
	{ "database", MASTERZONE | SLAVEZONE | STUBZONE },
169
	{ "key-directory", MASTERZONE },
170
171
172
173
174
175
176
177
178
	};

	static optionstable dialups[] = {
	{ "notify", MASTERZONE | SLAVEZONE },
	{ "notify-passive", SLAVEZONE },
	{ "refresh", SLAVEZONE | STUBZONE },
	{ "passive", SLAVEZONE | STUBZONE },
	};

Brian Wellington's avatar
bugs    
Brian Wellington committed
179
180
181
	zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));

	zoptions = cfg_tuple_get(zconfig, "options");
182
183

	obj = NULL;
Brian Wellington's avatar
bugs    
Brian Wellington committed
184
	(void)cfg_map_get(zoptions, "type", &obj);
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
	if (obj == NULL) {
		cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
			    "zone '%s': type not present", zname);
		return (ISC_R_FAILURE);
	}

	typestr = cfg_obj_asstring(obj);
	if (strcasecmp(typestr, "master") == 0)
		ztype = MASTERZONE;
	else if (strcasecmp(typestr, "slave") == 0)
		ztype = SLAVEZONE;
	else if (strcasecmp(typestr, "stub") == 0)
		ztype = STUBZONE;
	else if (strcasecmp(typestr, "forward") == 0)
		ztype = FORWARDZONE;
	else if (strcasecmp(typestr, "hint") == 0)
		ztype = HINTZONE;
	else {
		cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
			    "zone '%s': invalid type %s",
			    zname, typestr);
		return (ISC_R_FAILURE);
	}

209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
	obj = cfg_tuple_get(zconfig, "class");
	if (cfg_obj_isstring(obj)) {
		isc_textregion_t r;

		DE_CONST(cfg_obj_asstring(obj), r.base);
		r.length = strlen(r.base);
		result = dns_rdataclass_fromtext(&zclass, &r);
		if (result != ISC_R_SUCCESS) {
			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
				    "zone '%s': invalid class %s",
				    zname, r.base);
			return (ISC_R_FAILURE);
		}
		if (zclass != defclass) {
			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
				    "zone '%s': class '%s' does not "
				    "match view/default class",
				    zname, r.base);
			return (ISC_R_FAILURE);
		}
	}

231
232
	/*
	 * Look for an already existing zone.
233
234
	 * We need to make this cannonical as isc_symtab_define()
	 * deals with strings.
235
	 */
236
237
238
239
240
241
	dns_fixedname_init(&fixedname);
	isc_buffer_init(&b, zname, strlen(zname));
	isc_buffer_add(&b, strlen(zname));
	result = dns_name_fromtext(dns_fixedname_name(&fixedname), &b,
				   dns_rootname, ISC_TRUE, NULL);
	if (result != ISC_R_SUCCESS) {
242
		cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
243
			    "zone '%s': is not a valid name", zname);
244
		result = ISC_R_FAILURE;
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
	} else {
		char namebuf[DNS_NAME_FORMATSIZE];
		dns_name_format(dns_fixedname_name(&fixedname),
				namebuf, sizeof(namebuf));
		symvalue.as_pointer = NULL;
		tresult = isc_symtab_define(symtab, namebuf,
					    ztype == HINTZONE ? 1 : 2,
					    symvalue, isc_symexists_reject);
		if (tresult == ISC_R_EXISTS) {
			cfg_obj_log(zconfig, logctx, ISC_LOG_ERROR,
				    "zone '%s': already exists ", zname);
			result = ISC_R_FAILURE;
		} else if (tresult != ISC_R_SUCCESS)
			return (tresult);
	}
260
261
262
263

	/*
	 * Look for inappropriate options for the given zone type.
	 */
264
265
266
267
268
269
270
271
272
273
274
275
276
277
	for (i = 0; i < sizeof(options) / sizeof(options[0]); i++) {
		obj = NULL;
		if ((options[i].allowed & ztype) == 0 &&
		    cfg_map_get(zoptions, options[i].name, &obj) ==
		    ISC_R_SUCCESS)
		{
			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
				    "option '%s' is not allowed in '%s' "
				    "zone '%s'",
				    options[i].name, typestr, zname);
			result = ISC_R_FAILURE;
		}
	}

278
279
280
	/*
	 * Slave & stub zones must have a "masters" field.
	 */
281
282
283
	if (ztype == SLAVEZONE || ztype == STUBZONE) {
		obj = NULL;
		if (cfg_map_get(zoptions, "masters", &obj) != ISC_R_SUCCESS) {
284
			cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
285
286
287
288
				    "zone '%s': missing 'masters' entry",
				    zname);
			result = ISC_R_FAILURE;
		}
289
290
291
292
293
294
295
		addrlist = cfg_tuple_get(obj, "addresses");
		if (cfg_list_first(addrlist) == NULL) {
			cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
				    "zone '%s': empty 'masters' entry",
				    zname);
			result = ISC_R_FAILURE;
		}
296
297
	}

298
299
300
	/*
	 * Master zones can't have both "allow-update" and "update-policy".
	 */
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
	if (ztype == MASTERZONE) {
		isc_result_t res1, res2;
		obj = NULL;
		res1 = cfg_map_get(zoptions, "allow-update", &obj);
		obj = NULL;
		res2 = cfg_map_get(zoptions, "update-policy", &obj);
		if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
				    "zone '%s': 'allow-update' is ignored "
				    "when 'update-policy' is present",
				    zname);
			result = ISC_R_FAILURE;
		}
	}

316
317
318
	/*
	 * Check the excessively complicated "dialup" option.
	 */
319
320
	if (ztype == MASTERZONE || ztype == SLAVEZONE || ztype == STUBZONE) {
		cfg_obj_t *dialup = NULL;
321
		(void)cfg_map_get(zoptions, "dialup", &dialup);
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
		if (dialup != NULL && cfg_obj_isstring(dialup)) {
			char *str = cfg_obj_asstring(dialup);
			for (i = 0;
			     i < sizeof(dialups) / sizeof(dialups[0]);
			     i++)
			{
				if (strcasecmp(dialups[i].name, str) != 0)
					continue;
				if ((dialups[i].allowed & ztype) == 0) {
					cfg_obj_log(obj, logctx,
						    ISC_LOG_ERROR,
						    "dialup type '%s' is not "
						    "allowed in '%s' "
						    "zone '%s'",
						    str, typestr, zname);
					result = ISC_R_FAILURE;
				}
				break;
			}
			if (i == sizeof(dialups) / sizeof(dialups[0])) {
				cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
					    "invalid dialup type '%s' in zone "
					    "'%s'", str, zname);
				result = ISC_R_FAILURE;
			}
		}
	}

350
351
352
353
354
355
	/*
	 * Check that forwarding is reasonable.
	 */
	if (check_forward(zoptions, logctx) != ISC_R_SUCCESS)
		result = ISC_R_FAILURE;

356
357
358
	/*
	 * Check various options.
	 */
359
	tresult = check_options(zoptions, logctx);
360
361
362
	if (tresult != ISC_R_SUCCESS)
		result = tresult;

363
364
365
	return (result);
}

366
isc_result_t
367
bind9_check_key(cfg_obj_t *key, isc_log_t *logctx) {
368
369
370
371
	cfg_obj_t *algobj = NULL;
	cfg_obj_t *secretobj = NULL;
	const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
	
372
373
	(void)cfg_map_get(key, "algorithm", &algobj);
	(void)cfg_map_get(key, "secret", &secretobj);
374
375
376
377
378
	if (secretobj == NULL || algobj == NULL) {
		cfg_obj_log(key, logctx, ISC_LOG_ERROR,
			    "key '%s' must have both 'secret' and "
			    "'algorithm' defined",
			    keyname);
Brian Wellington's avatar
style    
Brian Wellington committed
379
		return (ISC_R_FAILURE);
380
	}
Brian Wellington's avatar
style    
Brian Wellington committed
381
	return (ISC_R_SUCCESS);
382
}
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

static isc_result_t
check_keylist(cfg_obj_t *keys, isc_symtab_t *symtab, isc_log_t *logctx) {
	isc_result_t result = ISC_R_SUCCESS;
	isc_result_t tresult;
	cfg_listelt_t *element;

	for (element = cfg_list_first(keys);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		cfg_obj_t *key = cfg_listelt_value(element);
		const char *keyname = cfg_obj_asstring(cfg_map_getname(key));
		isc_symvalue_t symvalue;

		symvalue.as_pointer = NULL;
		tresult = isc_symtab_define(symtab, keyname, 1,
					    symvalue, isc_symexists_reject);
		if (tresult == ISC_R_EXISTS) {
			cfg_obj_log(key, logctx, ISC_LOG_ERROR,
				    "key '%s': already exists ", keyname);
			result = tresult;
		} else if (tresult != ISC_R_SUCCESS)
			return (tresult);

		tresult = bind9_check_key(key, logctx);
		if (tresult != ISC_R_SUCCESS)
			return (tresult);
	}
	return (result);
}
414
		
Brian Wellington's avatar
Brian Wellington committed
415
static isc_result_t
416
check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
417
	       isc_log_t *logctx, isc_mem_t *mctx)
418
{
Brian Wellington's avatar
Brian Wellington committed
419
420
421
	cfg_obj_t *zones = NULL;
	cfg_obj_t *keys = NULL;
	cfg_listelt_t *element;
422
	isc_symtab_t *symtab = NULL;
Brian Wellington's avatar
Brian Wellington committed
423
	isc_result_t result = ISC_R_SUCCESS;
424
	isc_result_t tresult = ISC_R_SUCCESS;
Brian Wellington's avatar
Brian Wellington committed
425

426
427
428
429
	/*
	 * Check that all zone statements are syntactically correct and
	 * there are no duplicate zones.
	 */
430
431
	tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
	if (tresult != ISC_R_SUCCESS)
432
433
		return (ISC_R_NOMEMORY);

434
435
436
437
	if (vconfig != NULL)
		(void)cfg_map_get(vconfig, "zone", &zones);
	else
		(void)cfg_map_get(config, "zone", &zones);
438

Brian Wellington's avatar
Brian Wellington committed
439
440
441
442
	for (element = cfg_list_first(zones);
	     element != NULL;
	     element = cfg_list_next(element))
	{
443
		isc_result_t tresult;
Brian Wellington's avatar
Brian Wellington committed
444
445
		cfg_obj_t *zone = cfg_listelt_value(element);

446
447
		tresult = check_zoneconf(zone, symtab, vclass, logctx);
		if (tresult != ISC_R_SUCCESS)
Brian Wellington's avatar
Brian Wellington committed
448
449
450
			result = ISC_R_FAILURE;
	}

451
452
453
454
455
456
	isc_symtab_destroy(&symtab);

	/*
	 * Check that all key statements are syntactically correct and
	 * there are no duplicate keys.
	 */
457
458
	tresult = isc_symtab_create(mctx, 100, NULL, NULL, ISC_TRUE, &symtab);
	if (tresult != ISC_R_SUCCESS)
459
460
		return (ISC_R_NOMEMORY);

461
	(void)cfg_map_get(config, "key", &keys);
462
463
464
465
466
467
468
469
470
471
472
473
474
	tresult = check_keylist(keys, symtab, logctx);
	if (tresult == ISC_R_EXISTS)
		result = ISC_R_FAILURE;
	else if (tresult != ISC_R_SUCCESS) {
		isc_symtab_destroy(&symtab);
		return (tresult);
	}
	
	if (vconfig != NULL) {
		keys = NULL;
		(void)cfg_map_get(vconfig, "key", &keys);
		tresult = check_keylist(keys, symtab, logctx);
		if (tresult == ISC_R_EXISTS)
475
			result = ISC_R_FAILURE;
476
		else if (tresult != ISC_R_SUCCESS) {
477
478
			isc_symtab_destroy(&symtab);
			return (tresult);
Brian Wellington's avatar
Brian Wellington committed
479
480
481
		}
	}

482
483
	isc_symtab_destroy(&symtab);

484
485
486
	/*
	 * Check that forwarding is reasonable.
	 */
487
	if (vconfig == NULL) {
488
		cfg_obj_t *options = NULL;
489
		(void)cfg_map_get(config, "options", &options);
490
491
492
493
494
495
496
497
		if (options != NULL)
			if (check_forward(options, logctx) != ISC_R_SUCCESS)
				result = ISC_R_FAILURE;
	} else {
		if (check_forward(vconfig, logctx) != ISC_R_SUCCESS)
			result = ISC_R_FAILURE;
	}

498
	if (vconfig != NULL)
499
		tresult = check_options(vconfig, logctx);
500
	else
501
		tresult = check_options(config, logctx);
502
503
504
	if (tresult != ISC_R_SUCCESS)
		result = tresult;

Brian Wellington's avatar
Brian Wellington committed
505
506
507
508
	return (result);
}


509
isc_result_t
510
bind9_check_namedconf(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
511
	cfg_obj_t *options = NULL;
512
	cfg_obj_t *views = NULL;
513
	cfg_obj_t *acls = NULL;
514
515
	cfg_obj_t *obj;
	cfg_listelt_t *velement;
Brian Wellington's avatar
Brian Wellington committed
516
	isc_result_t result = ISC_R_SUCCESS;
517
	isc_result_t tresult;
518

519
	static const char *builtin[] = { "localhost", "localnets",
520
					 "any", "none"};
521

522
523
	(void)cfg_map_get(config, "options", &options);

524
	if (options != NULL &&
525
	    check_options(options, logctx) != ISC_R_SUCCESS)
526
		result = ISC_R_FAILURE;
527

528
529
530
	(void)cfg_map_get(config, "view", &views);

	if (views == NULL) {
531
		if (check_viewconf(config, NULL, dns_rdataclass_in,
532
				   logctx, mctx) != ISC_R_SUCCESS)
Brian Wellington's avatar
Brian Wellington committed
533
			result = ISC_R_FAILURE;
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
	} else {
		cfg_obj_t *zones = NULL;

		(void)cfg_map_get(config, "zone", &zones);
		if (zones != NULL) {
			cfg_obj_log(zones, logctx, ISC_LOG_ERROR,
				    "when using 'view' statements, "
				    "all zones must be in views");
			result = ISC_R_FAILURE;
		}
	}

	for (velement = cfg_list_first(views);
	     velement != NULL;
	     velement = cfg_list_next(velement))
	{
		cfg_obj_t *view = cfg_listelt_value(velement);
Brian Wellington's avatar
Brian Wellington committed
551
		cfg_obj_t *vname = cfg_tuple_get(view, "name");
552
		cfg_obj_t *voptions = cfg_tuple_get(view, "options");
553
554
555
		cfg_obj_t *vclassobj = cfg_tuple_get(view, "class");
		dns_rdataclass_t vclass = dns_rdataclass_in;
		isc_result_t tresult = ISC_R_SUCCESS;
556

557
558
559
560
561
562
563
		if (cfg_obj_isstring(vclassobj)) {
			isc_textregion_t r;

			DE_CONST(cfg_obj_asstring(vclassobj), r.base);
			r.length = strlen(r.base);
			tresult = dns_rdataclass_fromtext(&vclass, &r);
			if (tresult != ISC_R_SUCCESS)
564
				cfg_obj_log(vclassobj, logctx, ISC_LOG_ERROR,
565
566
567
568
					    "view '%s': invalid class %s",
					    cfg_obj_asstring(vname), r.base);
		}
		if (tresult == ISC_R_SUCCESS)
569
			tresult = check_viewconf(config, voptions,
570
571
						 vclass, logctx, mctx);
		if (tresult != ISC_R_SUCCESS)
Brian Wellington's avatar
Brian Wellington committed
572
			result = ISC_R_FAILURE;
573
574
	}

575
576
	if (views != NULL && options != NULL) {
		obj = NULL;
577
578
		tresult = cfg_map_get(options, "cache-file", &obj);
		if (tresult == ISC_R_SUCCESS) {
579
580
581
582
583
584
			cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
				    "'cache-file' cannot be a global "
				    "option if views are present");
			result = ISC_R_FAILURE;
		}
	}
585

586
587
588
        tresult = cfg_map_get(config, "acl", &acls);
        if (tresult == ISC_R_SUCCESS) {
		cfg_listelt_t *elt;
589
		cfg_listelt_t *elt2;
590
591
592
593
594
595
		const char *aclname;

		for (elt = cfg_list_first(acls);
		     elt != NULL;
		     elt = cfg_list_next(elt)) {
			cfg_obj_t *acl = cfg_listelt_value(elt);
596
			unsigned int i;
597
598

			aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
599
600
601
			for (i = 0;
			     i < sizeof(builtin) / sizeof(builtin[0]);
			     i++)
602
603
604
605
606
607
608
609
				if (strcasecmp(aclname, builtin[i]) == 0) {
					cfg_obj_log(acl, logctx, ISC_LOG_ERROR,
						    "attempt to redefine "
						    "builtin acl '%s'",
				    		    aclname);
					result = ISC_R_FAILURE;
					break;
				}
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625

			for (elt2 = cfg_list_next(elt);
			     elt2 != NULL;
			     elt2 = cfg_list_next(elt2)) {
				cfg_obj_t *acl2 = cfg_listelt_value(elt2);
				const char *name;
				name = cfg_obj_asstring(cfg_tuple_get(acl2,
								      "name"));
				if (strcasecmp(aclname, name) == 0) {
					cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
						    "attempt to redefine "
						    "acl '%s'", name);
					result = ISC_R_FAILURE;
					break;
				}
			}
626
627
628
		}
	}

629
630
	return (result);
}