xref: /openbsd-src/usr.sbin/nsd/options.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /*
2  * options.c -- options functions.
3  *
4  * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 #include "config.h"
10 #include <string.h>
11 #include <stdio.h>
12 #include <errno.h>
13 #include "options.h"
14 #include "query.h"
15 #include "tsig.h"
16 #include "difffile.h"
17 #include "rrl.h"
18 
19 #include "configyyrename.h"
20 #include "configparser.h"
21 config_parser_state_t* cfg_parser = 0;
22 extern FILE* c_in, *c_out;
23 int c_parse(void);
24 int c_lex(void);
25 int c_wrap(void);
26 void c_error(const char *message);
27 extern char* c_text;
28 
29 static int
30 rbtree_strcmp(const void* p1, const void* p2)
31 {
32 	if(p1 == NULL && p2 == NULL) return 0;
33 	if(p1 == NULL) return -1;
34 	if(p2 == NULL) return 1;
35 	return strcmp((const char*)p1, (const char*)p2);
36 }
37 
38 nsd_options_t*
39 nsd_options_create(region_type* region)
40 {
41 	nsd_options_t* opt;
42 	opt = (nsd_options_t*)region_alloc(region, sizeof(nsd_options_t));
43 	opt->region = region;
44 	opt->zone_options = rbtree_create(region,
45 		(int (*)(const void *, const void *)) dname_compare);
46 	opt->configfile = NULL;
47 	opt->zonestatnames = rbtree_create(opt->region, rbtree_strcmp);
48 	opt->patterns = rbtree_create(region, rbtree_strcmp);
49 	opt->keys = rbtree_create(region, rbtree_strcmp);
50 	opt->ip_addresses = NULL;
51 	opt->ip_transparent = 0;
52 	opt->ip_freebind = 0;
53 	opt->debug_mode = 0;
54 	opt->verbosity = 0;
55 	opt->hide_version = 0;
56 	opt->do_ip4 = 1;
57 	opt->do_ip6 = 1;
58 	opt->database = DBFILE;
59 	opt->identity = 0;
60 	opt->version = 0;
61 	opt->nsid = 0;
62 	opt->logfile = 0;
63 	opt->log_time_ascii = 1;
64 	opt->round_robin = 0; /* also packet.h::round_robin */
65 	opt->server_count = 1;
66 	opt->tcp_count = 100;
67 	opt->tcp_query_count = 0;
68 	opt->tcp_timeout = TCP_TIMEOUT;
69 	opt->tcp_mss = 0;
70 	opt->outgoing_tcp_mss = 0;
71 	opt->ipv4_edns_size = EDNS_MAX_MESSAGE_LEN;
72 	opt->ipv6_edns_size = EDNS_MAX_MESSAGE_LEN;
73 	opt->pidfile = PIDFILE;
74 	opt->port = UDP_PORT;
75 /* deprecated?	opt->port = TCP_PORT; */
76 	opt->reuseport = 0;
77 	opt->statistics = 0;
78 	opt->chroot = 0;
79 	opt->username = USER;
80 	opt->zonesdir = ZONESDIR;
81 	opt->xfrdfile = XFRDFILE;
82 	opt->xfrdir = XFRDIR;
83 	opt->zonelistfile = ZONELISTFILE;
84 #ifdef RATELIMIT
85 	opt->rrl_size = RRL_BUCKETS;
86 	opt->rrl_slip = RRL_SLIP;
87 	opt->rrl_ipv4_prefix_length = RRL_IPV4_PREFIX_LENGTH;
88 	opt->rrl_ipv6_prefix_length = RRL_IPV6_PREFIX_LENGTH;
89 #  ifdef RATELIMIT_DEFAULT_OFF
90 	opt->rrl_ratelimit = 0;
91 	opt->rrl_whitelist_ratelimit = 0;
92 #  else
93 	opt->rrl_ratelimit = RRL_LIMIT/2;
94 	opt->rrl_whitelist_ratelimit = RRL_WLIST_LIMIT/2;
95 #  endif
96 #endif
97 	opt->zonefiles_check = 1;
98 	if(opt->database == NULL || opt->database[0] == 0)
99 		opt->zonefiles_write = ZONEFILES_WRITE_INTERVAL;
100 	else	opt->zonefiles_write = 0;
101 	opt->xfrd_reload_timeout = 1;
102 	opt->control_enable = 0;
103 	opt->control_interface = NULL;
104 	opt->control_port = NSD_CONTROL_PORT;
105 	opt->server_key_file = CONFIGDIR"/nsd_server.key";
106 	opt->server_cert_file = CONFIGDIR"/nsd_server.pem";
107 	opt->control_key_file = CONFIGDIR"/nsd_control.key";
108 	opt->control_cert_file = CONFIGDIR"/nsd_control.pem";
109 	return opt;
110 }
111 
112 int
113 nsd_options_insert_zone(nsd_options_t* opt, zone_options_t* zone)
114 {
115 	/* create dname for lookup */
116 	const dname_type* dname = dname_parse(opt->region, zone->name);
117 	if(!dname)
118 		return 0;
119 	zone->node.key = dname;
120 	if(!rbtree_insert(opt->zone_options, (rbnode_t*)zone))
121 		return 0;
122 	return 1;
123 }
124 
125 int
126 nsd_options_insert_pattern(nsd_options_t* opt, pattern_options_t* pat)
127 {
128 	if(!pat->pname)
129 		return 0;
130 	pat->node.key = pat->pname;
131 	if(!rbtree_insert(opt->patterns, (rbnode_t*)pat))
132 		return 0;
133 	return 1;
134 }
135 
136 int
137 parse_options_file(nsd_options_t* opt, const char* file,
138 	void (*err)(void*,const char*), void* err_arg)
139 {
140 	FILE *in = 0;
141 	pattern_options_t* pat;
142 	acl_options_t* acl;
143 
144 	if(!cfg_parser) {
145 		cfg_parser = (config_parser_state_t*)region_alloc(
146 			opt->region, sizeof(config_parser_state_t));
147 		cfg_parser->chroot = 0;
148 	}
149 	cfg_parser->err = err;
150 	cfg_parser->err_arg = err_arg;
151 	cfg_parser->filename = (char*)file;
152 	cfg_parser->line = 1;
153 	cfg_parser->errors = 0;
154 	cfg_parser->server_settings_seen = 0;
155 	cfg_parser->opt = opt;
156 	cfg_parser->current_pattern = 0;
157 	cfg_parser->current_zone = 0;
158 	cfg_parser->current_key = 0;
159 	cfg_parser->current_ip_address_option = opt->ip_addresses;
160 	while(cfg_parser->current_ip_address_option && cfg_parser->current_ip_address_option->next)
161 		cfg_parser->current_ip_address_option = cfg_parser->current_ip_address_option->next;
162 	cfg_parser->current_allow_notify = 0;
163 	cfg_parser->current_request_xfr = 0;
164 	cfg_parser->current_notify = 0;
165 	cfg_parser->current_provide_xfr = 0;
166 
167 	in = fopen(cfg_parser->filename, "r");
168 	if(!in) {
169 		if(err) {
170 			char m[MAXSYSLOGMSGLEN];
171 			snprintf(m, sizeof(m), "Could not open %s: %s\n",
172 				file, strerror(errno));
173 			err(err_arg, m);
174 		} else {
175 			fprintf(stderr, "Could not open %s: %s\n",
176 				file, strerror(errno));
177 		}
178 		return 0;
179 	}
180 	c_in = in;
181 	c_parse();
182 	fclose(in);
183 
184 	opt->configfile = region_strdup(opt->region, file);
185 	if(cfg_parser->current_pattern) {
186 		if(!cfg_parser->current_pattern->pname)
187 			c_error("last pattern has no name");
188 		else {
189 			if(!nsd_options_insert_pattern(cfg_parser->opt,
190 				cfg_parser->current_pattern))
191 				c_error("duplicate pattern");
192 		}
193 	}
194 	if(cfg_parser->current_zone) {
195 		if(!cfg_parser->current_zone->name)
196 			c_error("last zone has no name");
197 		else {
198 			if(!nsd_options_insert_zone(opt,
199 				cfg_parser->current_zone))
200 				c_error("duplicate zone");
201 		}
202 		if(!cfg_parser->current_zone->pattern)
203 			c_error("last zone has no pattern");
204 	}
205 	if(cfg_parser->current_key)
206 	{
207 		if(!cfg_parser->current_key->name)
208 			c_error("last key has no name");
209 		if(!cfg_parser->current_key->algorithm)
210 			c_error("last key has no algorithm");
211 		if(!cfg_parser->current_key->secret)
212 			c_error("last key has no secret blob");
213 		key_options_insert(opt, cfg_parser->current_key);
214 	}
215 	RBTREE_FOR(pat, pattern_options_t*, opt->patterns)
216 	{
217 		/* lookup keys for acls */
218 		for(acl=pat->allow_notify; acl; acl=acl->next)
219 		{
220 			if(acl->nokey || acl->blocked)
221 				continue;
222 			acl->key_options = key_options_find(opt, acl->key_name);
223 			if(!acl->key_options)
224 				c_error_msg("key %s in pattern %s could not be found",
225 					acl->key_name, pat->pname);
226 		}
227 		for(acl=pat->notify; acl; acl=acl->next)
228 		{
229 			if(acl->nokey || acl->blocked)
230 				continue;
231 			acl->key_options = key_options_find(opt, acl->key_name);
232 			if(!acl->key_options)
233 				c_error_msg("key %s in pattern %s could not be found",
234 					acl->key_name, pat->pname);
235 		}
236 		for(acl=pat->request_xfr; acl; acl=acl->next)
237 		{
238 			if(acl->nokey || acl->blocked)
239 				continue;
240 			acl->key_options = key_options_find(opt, acl->key_name);
241 			if(!acl->key_options)
242 				c_error_msg("key %s in pattern %s could not be found",
243 					acl->key_name, pat->pname);
244 		}
245 		for(acl=pat->provide_xfr; acl; acl=acl->next)
246 		{
247 			if(acl->nokey || acl->blocked)
248 				continue;
249 			acl->key_options = key_options_find(opt, acl->key_name);
250 			if(!acl->key_options)
251 				c_error_msg("key %s in pattern %s could not be found",
252 					acl->key_name, pat->pname);
253 		}
254 	}
255 
256 	if(cfg_parser->errors > 0)
257 	{
258 		if(err) {
259 			char m[MAXSYSLOGMSGLEN];
260 			snprintf(m, sizeof(m), "read %s failed: %d errors in "
261 				"configuration file\n", file,
262 				cfg_parser->errors);
263 			err(err_arg, m);
264 		} else {
265 			fprintf(stderr, "read %s failed: %d errors in "
266 				"configuration file\n", file,
267 				cfg_parser->errors);
268 		}
269 		return 0;
270 	}
271 	return 1;
272 }
273 
274 void options_zonestatnames_create(nsd_options_t* opt)
275 {
276 	zone_options_t* zopt;
277 	/* allocate "" as zonestat 0, for zones without a zonestat */
278 	if(!rbtree_search(opt->zonestatnames, "")) {
279 		struct zonestatname* n;
280 		n = (struct zonestatname*)xalloc(sizeof(*n));
281 		memset(n, 0, sizeof(*n));
282 		n->node.key = strdup("");
283 		if(!n->node.key) {
284 			log_msg(LOG_ERR, "malloc failed: %s", strerror(errno));
285 			exit(1);
286 		}
287 		n->id = (unsigned)(opt->zonestatnames->count);
288 		rbtree_insert(opt->zonestatnames, (rbnode_t*)n);
289 	}
290 	RBTREE_FOR(zopt, zone_options_t*, opt->zone_options) {
291 		/* insert into tree, so that when read in later id exists */
292 		(void)getzonestatid(opt, zopt);
293 	}
294 }
295 
296 #define ZONELIST_HEADER "# NSD zone list\n# name pattern\n"
297 static int
298 comp_zonebucket(const void* a, const void* b)
299 {
300 	/* the line size is much smaller than max-int, and positive,
301 	 * so the subtraction works */
302 	return *(const int*)b - *(const int*)a;
303 }
304 
305 /* insert free entry into zonelist free buckets */
306 static void
307 zone_list_free_insert(nsd_options_t* opt, int linesize, off_t off)
308 {
309 	struct zonelist_free* e;
310 	struct zonelist_bucket* b = (struct zonelist_bucket*)rbtree_search(
311 		opt->zonefree, &linesize);
312 	if(!b) {
313 		b = region_alloc_zero(opt->region, sizeof(*b));
314 		b->linesize = linesize;
315 		b->node = *RBTREE_NULL;
316 		b->node.key = &b->linesize;
317 		rbtree_insert(opt->zonefree, &b->node);
318 	}
319 	e = (struct zonelist_free*)region_alloc_zero(opt->region, sizeof(*e));
320 	e->next = b->list;
321 	b->list = e;
322 	e->off = off;
323 	opt->zonefree_number++;
324 }
325 
326 zone_options_t*
327 zone_list_zone_insert(nsd_options_t* opt, const char* nm, const char* patnm,
328 	int linesize, off_t off)
329 {
330 	pattern_options_t* pat = pattern_options_find(opt, patnm);
331 	zone_options_t* zone;
332 	if(!pat) {
333 		log_msg(LOG_ERR, "pattern does not exist for zone %s "
334 			"pattern %s", nm, patnm);
335 		return NULL;
336 	}
337 	zone = zone_options_create(opt->region);
338 	zone->part_of_config = 0;
339 	zone->name = region_strdup(opt->region, nm);
340 	zone->linesize = linesize;
341 	zone->off = off;
342 	zone->pattern = pat;
343 	if(!nsd_options_insert_zone(opt, zone)) {
344 		log_msg(LOG_ERR, "bad domain name or duplicate zone '%s' "
345 			"pattern %s", nm, patnm);
346 		region_recycle(opt->region, (void*)zone->name, strlen(nm)+1);
347 		region_recycle(opt->region, zone, sizeof(*zone));
348 		return NULL;
349 	}
350 	return zone;
351 }
352 
353 int
354 parse_zone_list_file(nsd_options_t* opt)
355 {
356 	/* zonelist looks like this:
357 	# name pattern
358 	add example.com master
359 	del example.net slave
360 	add foo.bar.nl slave
361 	add rutabaga.uk config
362 	*/
363 	char buf[1024];
364 
365 	/* create empty data structures */
366 	opt->zonefree = rbtree_create(opt->region, comp_zonebucket);
367 	opt->zonelist = NULL;
368 	opt->zonefree_number = 0;
369 	opt->zonelist_off = 0;
370 
371 	/* try to open the zonelist file, an empty or nonexist file is OK */
372 	opt->zonelist = fopen(opt->zonelistfile, "r+");
373 	if(!opt->zonelist) {
374 		if(errno == ENOENT)
375 			return 1; /* file does not exist, it is created later */
376 		log_msg(LOG_ERR, "could not open zone list %s: %s", opt->zonelistfile,
377 			strerror(errno));
378 		return 0;
379 	}
380 	/* read header */
381 	buf[strlen(ZONELIST_HEADER)] = 0;
382 	if(fread(buf, 1, strlen(ZONELIST_HEADER), opt->zonelist) !=
383 		strlen(ZONELIST_HEADER) || strncmp(buf, ZONELIST_HEADER,
384 		strlen(ZONELIST_HEADER)) != 0) {
385 		log_msg(LOG_ERR, "zone list %s contains bad header\n", opt->zonelistfile);
386 		fclose(opt->zonelist);
387 		opt->zonelist = NULL;
388 		return 0;
389 	}
390 
391 	/* read entries in file */
392 	while(fgets(buf, sizeof(buf), opt->zonelist)) {
393 		/* skip comments and empty lines */
394 		if(buf[0] == 0 || buf[0] == '\n' || buf[0] == '#')
395 			continue;
396 		if(strncmp(buf, "add ", 4) == 0) {
397 			int linesize = strlen(buf);
398 			/* parse the 'add' line */
399 			/* pick last space on the line, so that the domain
400 			 * name can have a space in it (but not the pattern)*/
401 			char* space = strrchr(buf+4, ' ');
402 			char* nm, *patnm;
403 			if(!space) {
404 				/* parse error */
405 				log_msg(LOG_ERR, "parse error in %s: '%s'",
406 					opt->zonelistfile, buf);
407 				continue;
408 			}
409 			nm = buf+4;
410 			*space = 0;
411 			patnm = space+1;
412 			if(linesize && buf[linesize-1] == '\n')
413 				buf[linesize-1] = 0;
414 
415 			/* store offset and line size for zone entry */
416 			/* and create zone entry in zonetree */
417 			(void)zone_list_zone_insert(opt, nm, patnm, linesize,
418 				ftello(opt->zonelist)-linesize);
419 		} else if(strncmp(buf, "del ", 4) == 0) {
420 			/* store offset and line size for deleted entry */
421 			int linesize = strlen(buf);
422 			zone_list_free_insert(opt, linesize,
423 				ftello(opt->zonelist)-linesize);
424 		} else {
425 			log_msg(LOG_WARNING, "bad data in %s, '%s'", opt->zonelistfile,
426 				buf);
427 		}
428 	}
429 	/* store EOF offset */
430 	opt->zonelist_off = ftello(opt->zonelist);
431 	return 1;
432 }
433 
434 void
435 zone_options_delete(nsd_options_t* opt, zone_options_t* zone)
436 {
437 	rbtree_delete(opt->zone_options, zone->node.key);
438 	region_recycle(opt->region, (void*)zone->node.key, dname_total_size(
439 		(dname_type*)zone->node.key));
440 	region_recycle(opt->region, zone, sizeof(*zone));
441 }
442 
443 /* add a new zone to the zonelist */
444 zone_options_t*
445 zone_list_add(nsd_options_t* opt, const char* zname, const char* pname)
446 {
447 	int r;
448 	struct zonelist_free* e;
449 	struct zonelist_bucket* b;
450 	int linesize = 6 + strlen(zname) + strlen(pname);
451 	/* create zone entry */
452 	zone_options_t* zone = zone_list_zone_insert(opt, zname, pname,
453 		linesize, 0);
454 	if(!zone)
455 		return NULL;
456 
457 	/* use free entry or append to file or create new file */
458 	if(!opt->zonelist || opt->zonelist_off == 0) {
459 		/* create new file */
460 		if(opt->zonelist) fclose(opt->zonelist);
461 		opt->zonelist = fopen(opt->zonelistfile, "w+");
462 		if(!opt->zonelist) {
463 			log_msg(LOG_ERR, "could not create zone list %s: %s",
464 				opt->zonelistfile, strerror(errno));
465 			log_msg(LOG_ERR, "zone %s could not be added", zname);
466 			zone_options_delete(opt, zone);
467 			return NULL;
468 		}
469 		r = fprintf(opt->zonelist, ZONELIST_HEADER);
470 		if(r != strlen(ZONELIST_HEADER)) {
471 			if(r == -1)
472 				log_msg(LOG_ERR, "could not write to %s: %s",
473 					opt->zonelistfile, strerror(errno));
474 			else log_msg(LOG_ERR, "partial write to %s: disk full",
475 				opt->zonelistfile);
476 			log_msg(LOG_ERR, "zone %s could not be added", zname);
477 			zone_options_delete(opt, zone);
478 			return NULL;
479 		}
480 		zone->off = ftello(opt->zonelist);
481 		if(zone->off == -1)
482 			log_msg(LOG_ERR, "ftello(%s): %s", opt->zonelistfile, strerror(errno));
483 		r = fprintf(opt->zonelist, "add %s %s\n", zname, pname);
484 		if(r != zone->linesize) {
485 			if(r == -1)
486 				log_msg(LOG_ERR, "could not write to %s: %s",
487 					opt->zonelistfile, strerror(errno));
488 			else log_msg(LOG_ERR, "partial write to %s: disk full",
489 				opt->zonelistfile);
490 			log_msg(LOG_ERR, "zone %s could not be added", zname);
491 			zone_options_delete(opt, zone);
492 			return NULL;
493 		}
494 		opt->zonelist_off = ftello(opt->zonelist);
495 		if(opt->zonelist_off == -1)
496 			log_msg(LOG_ERR, "ftello(%s): %s", opt->zonelistfile, strerror(errno));
497 		if(fflush(opt->zonelist) != 0) {
498 			log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
499 		}
500 		return zone;
501 	}
502 	b = (struct zonelist_bucket*)rbtree_search(opt->zonefree,
503 		&zone->linesize);
504 	if(!b || b->list == NULL) {
505 		/* no empty place, append to file */
506 		zone->off = opt->zonelist_off;
507 		if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) {
508 			log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno));
509 			log_msg(LOG_ERR, "zone %s could not be added", zname);
510 			zone_options_delete(opt, zone);
511 			return NULL;
512 		}
513 		r = fprintf(opt->zonelist, "add %s %s\n", zname, pname);
514 		if(r != zone->linesize) {
515 			if(r == -1)
516 				log_msg(LOG_ERR, "could not write to %s: %s",
517 					opt->zonelistfile, strerror(errno));
518 			else log_msg(LOG_ERR, "partial write to %s: disk full",
519 				opt->zonelistfile);
520 			log_msg(LOG_ERR, "zone %s could not be added", zname);
521 			zone_options_delete(opt, zone);
522 			return NULL;
523 		}
524 		opt->zonelist_off += linesize;
525 		if(fflush(opt->zonelist) != 0) {
526 			log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
527 		}
528 		return zone;
529 	}
530 	/* reuse empty spot */
531 	e = b->list;
532 	zone->off = e->off;
533 	if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) {
534 		log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno));
535 		log_msg(LOG_ERR, "zone %s could not be added", zname);
536 		zone_options_delete(opt, zone);
537 		return NULL;
538 	}
539 	r = fprintf(opt->zonelist, "add %s %s\n", zname, pname);
540 	if(r != zone->linesize) {
541 		if(r == -1)
542 			log_msg(LOG_ERR, "could not write to %s: %s",
543 				opt->zonelistfile, strerror(errno));
544 		else log_msg(LOG_ERR, "partial write to %s: disk full",
545 			opt->zonelistfile);
546 		log_msg(LOG_ERR, "zone %s could not be added", zname);
547 		zone_options_delete(opt, zone);
548 		return NULL;
549 	}
550 	if(fflush(opt->zonelist) != 0) {
551 		log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
552 	}
553 
554 	/* snip off and recycle element */
555 	b->list = e->next;
556 	region_recycle(opt->region, e, sizeof(*e));
557 	if(b->list == NULL) {
558 		rbtree_delete(opt->zonefree, &b->linesize);
559 		region_recycle(opt->region, b, sizeof(*b));
560 	}
561 	opt->zonefree_number--;
562 	return zone;
563 }
564 
565 /* remove a zone on the zonelist */
566 void
567 zone_list_del(nsd_options_t* opt, zone_options_t* zone)
568 {
569 	/* put its space onto the free entry */
570 	if(fseeko(opt->zonelist, zone->off, SEEK_SET) == -1) {
571 		log_msg(LOG_ERR, "fseeko(%s): %s", opt->zonelistfile, strerror(errno));
572 		return;
573 	}
574 	fprintf(opt->zonelist, "del");
575 	zone_list_free_insert(opt, zone->linesize, zone->off);
576 
577 	/* remove zone_options_t */
578 	zone_options_delete(opt, zone);
579 
580 	/* see if we need to compact: it is going to halve the zonelist */
581 	if(opt->zonefree_number > opt->zone_options->count) {
582 		zone_list_compact(opt);
583 	} else {
584 		if(fflush(opt->zonelist) != 0) {
585 			log_msg(LOG_ERR, "fflush %s: %s", opt->zonelistfile, strerror(errno));
586 		}
587 	}
588 }
589 /* postorder delete of zonelist free space tree */
590 static void
591 delbucket(region_type* region, struct zonelist_bucket* b)
592 {
593 	struct zonelist_free* e, *f;
594 	if(!b || (rbnode_t*)b==RBTREE_NULL)
595 		return;
596 	delbucket(region, (struct zonelist_bucket*)b->node.left);
597 	delbucket(region, (struct zonelist_bucket*)b->node.right);
598 	e = b->list;
599 	while(e) {
600 		f = e->next;
601 		region_recycle(region, e, sizeof(*e));
602 		e = f;
603 	}
604 	region_recycle(region, b, sizeof(*b));
605 }
606 
607 /* compact zonelist file */
608 void
609 zone_list_compact(nsd_options_t* opt)
610 {
611 	char outname[1024];
612 	FILE* out;
613 	zone_options_t* zone;
614 	off_t off;
615 	int r;
616 	snprintf(outname, sizeof(outname), "%s~", opt->zonelistfile);
617 	/* useful, when : count-of-free > count-of-used */
618 	/* write zonelist to zonelist~ */
619 	out = fopen(outname, "w+");
620 	if(!out) {
621 		log_msg(LOG_ERR, "could not open %s: %s", outname, strerror(errno));
622 		return;
623 	}
624 	r = fprintf(out, ZONELIST_HEADER);
625 	if(r == -1) {
626 		log_msg(LOG_ERR, "write %s failed: %s", outname,
627 			strerror(errno));
628 		fclose(out);
629 		return;
630 	} else if(r != strlen(ZONELIST_HEADER)) {
631 		log_msg(LOG_ERR, "write %s was partial: disk full",
632 			outname);
633 		fclose(out);
634 		return;
635 	}
636 	off = ftello(out);
637 	if(off == -1) {
638 		log_msg(LOG_ERR, "ftello(%s): %s", outname, strerror(errno));
639 		fclose(out);
640 		return;
641 	}
642 	RBTREE_FOR(zone, zone_options_t*, opt->zone_options) {
643 		if(zone->part_of_config)
644 			continue;
645 		r = fprintf(out, "add %s %s\n", zone->name,
646 			zone->pattern->pname);
647 		if(r < 0) {
648 			log_msg(LOG_ERR, "write %s failed: %s", outname,
649 				strerror(errno));
650 			fclose(out);
651 			return;
652 		} else if(r != zone->linesize) {
653 			log_msg(LOG_ERR, "write %s was partial: disk full",
654 				outname);
655 			fclose(out);
656 			return;
657 		}
658 	}
659 	if(fflush(out) != 0) {
660 		log_msg(LOG_ERR, "fflush %s: %s", outname, strerror(errno));
661 	}
662 
663 	/* rename zonelist~ onto zonelist */
664 	if(rename(outname, opt->zonelistfile) == -1) {
665 		log_msg(LOG_ERR, "rename(%s to %s) failed: %s",
666 			outname, opt->zonelistfile, strerror(errno));
667 		fclose(out);
668 		return;
669 	}
670 	fclose(opt->zonelist);
671 	/* set offsets */
672 	RBTREE_FOR(zone, zone_options_t*, opt->zone_options) {
673 		if(zone->part_of_config)
674 			continue;
675 		zone->off = off;
676 		off += zone->linesize;
677 	}
678 	/* empty the free tree */
679 	delbucket(opt->region, (struct zonelist_bucket*)opt->zonefree->root);
680 	opt->zonefree->root = RBTREE_NULL;
681 	opt->zonefree->count = 0;
682 	opt->zonefree_number = 0;
683 	/* finish */
684 	opt->zonelist = out;
685 	opt->zonelist_off = off;
686 }
687 
688 /* close zonelist file */
689 void
690 zone_list_close(nsd_options_t* opt)
691 {
692 	fclose(opt->zonelist);
693 	opt->zonelist = NULL;
694 }
695 
696 void
697 c_error_va_list_pos(int showpos, const char* fmt, va_list args)
698 {
699 	char* at = NULL;
700 	cfg_parser->errors++;
701 	if(showpos && c_text && c_text[0]!=0) {
702 		at = c_text;
703 	}
704 	if(cfg_parser->err) {
705 		char m[MAXSYSLOGMSGLEN];
706 		snprintf(m, sizeof(m), "%s:%d: ", cfg_parser->filename,
707 			cfg_parser->line);
708 		(*cfg_parser->err)(cfg_parser->err_arg, m);
709 		if(at) {
710 			snprintf(m, sizeof(m), "at '%s': ", at);
711 			(*cfg_parser->err)(cfg_parser->err_arg, m);
712 		}
713 		(*cfg_parser->err)(cfg_parser->err_arg, "error: ");
714 		vsnprintf(m, sizeof(m), fmt, args);
715 		(*cfg_parser->err)(cfg_parser->err_arg, m);
716 		(*cfg_parser->err)(cfg_parser->err_arg, "\n");
717 		return;
718 	}
719         fprintf(stderr, "%s:%d: ", cfg_parser->filename, cfg_parser->line);
720 	if(at) fprintf(stderr, "at '%s': ", at);
721 	fprintf(stderr, "error: ");
722 	vfprintf(stderr, fmt, args);
723 	fprintf(stderr, "\n");
724 }
725 
726 void
727 c_error_msg_pos(int showpos, const char* fmt, ...)
728 {
729         va_list args;
730         va_start(args, fmt);
731         c_error_va_list_pos(showpos, fmt, args);
732         va_end(args);
733 }
734 
735 void
736 c_error_msg(const char* fmt, ...)
737 {
738         va_list args;
739         va_start(args, fmt);
740         c_error_va_list_pos(0, fmt, args);
741         va_end(args);
742 }
743 
744 void
745 c_error(const char* str)
746 {
747 	if((strcmp(str, "syntax error")==0 || strcmp(str, "parse error")==0))
748 		c_error_msg_pos(1, "%s", str);
749 	else	c_error_msg("%s", str);
750 }
751 
752 int
753 c_wrap()
754 {
755         return 1;
756 }
757 
758 zone_options_t*
759 zone_options_create(region_type* region)
760 {
761 	zone_options_t* zone;
762 	zone = (zone_options_t*)region_alloc(region, sizeof(zone_options_t));
763 	zone->node = *RBTREE_NULL;
764 	zone->name = 0;
765 	zone->pattern = 0;
766 	zone->part_of_config = 0;
767 	return zone;
768 }
769 
770 /* true is booleans are the same truth value */
771 #define booleq(x,y) ( ((x) && (y)) || (!(x) && !(y)) )
772 
773 int
774 acl_equal(acl_options_t* p, acl_options_t* q)
775 {
776 	if(!booleq(p->use_axfr_only, q->use_axfr_only)) return 0;
777 	if(!booleq(p->allow_udp, q->allow_udp)) return 0;
778 	if(strcmp(p->ip_address_spec, q->ip_address_spec)!=0) return 0;
779 	/* the ip6, port, addr, mask, type: are derived from the ip_address_spec */
780 	if(!booleq(p->nokey, q->nokey)) return 0;
781 	if(!booleq(p->blocked, q->blocked)) return 0;
782 	if(p->key_name && q->key_name) {
783 		if(strcmp(p->key_name, q->key_name)!=0) return 0;
784 	} else if(p->key_name && !q->key_name) return 0;
785 	else if(!p->key_name && q->key_name) return 0;
786 	/* key_options is derived from key_name */
787 	return 1;
788 }
789 
790 int
791 acl_list_equal(acl_options_t* p, acl_options_t* q)
792 {
793 	/* must be same and in same order */
794 	while(p && q) {
795 		if(!acl_equal(p, q))
796 			return 0;
797 		p = p->next;
798 		q = q->next;
799 	}
800 	if(!p && !q) return 1;
801 	/* different lengths */
802 	return 0;
803 }
804 
805 pattern_options_t*
806 pattern_options_create(region_type* region)
807 {
808 	pattern_options_t* p;
809 	p = (pattern_options_t*)region_alloc(region, sizeof(pattern_options_t));
810 	p->node = *RBTREE_NULL;
811 	p->pname = 0;
812 	p->zonefile = 0;
813 	p->zonestats = 0;
814 	p->allow_notify = 0;
815 	p->request_xfr = 0;
816 	p->notify = 0;
817 	p->provide_xfr = 0;
818 	p->outgoing_interface = 0;
819 	p->notify_retry = 5;
820 	p->notify_retry_is_default = 1;
821 	p->allow_axfr_fallback = 1;
822 	p->allow_axfr_fallback_is_default = 1;
823 	p->implicit = 0;
824 	p->xfrd_flags = 0;
825 #ifdef RATELIMIT
826 	p->rrl_whitelist = 0;
827 #endif
828 	return p;
829 }
830 
831 static void
832 acl_delete(region_type* region, acl_options_t* acl)
833 {
834 	if(acl->ip_address_spec)
835 		region_recycle(region, (void*)acl->ip_address_spec,
836 			strlen(acl->ip_address_spec)+1);
837 	if(acl->key_name)
838 		region_recycle(region, (void*)acl->key_name,
839 			strlen(acl->key_name)+1);
840 	/* key_options is a convenience pointer, not owned by the acl */
841 	region_recycle(region, acl, sizeof(*acl));
842 }
843 
844 static void
845 acl_list_delete(region_type* region, acl_options_t* list)
846 {
847 	acl_options_t* n;
848 	while(list) {
849 		n = list->next;
850 		acl_delete(region, list);
851 		list = n;
852 	}
853 }
854 
855 void
856 pattern_options_remove(nsd_options_t* opt, const char* name)
857 {
858 	pattern_options_t* p = (pattern_options_t*)rbtree_delete(
859 		opt->patterns, name);
860 	/* delete p and its contents */
861 	if (!p)
862 		return;
863 	if(p->pname)
864 		region_recycle(opt->region, (void*)p->pname,
865 			strlen(p->pname)+1);
866 	if(p->zonefile)
867 		region_recycle(opt->region, (void*)p->zonefile,
868 			strlen(p->zonefile)+1);
869 	if(p->zonestats)
870 		region_recycle(opt->region, (void*)p->zonestats,
871 			strlen(p->zonestats)+1);
872 	acl_list_delete(opt->region, p->allow_notify);
873 	acl_list_delete(opt->region, p->request_xfr);
874 	acl_list_delete(opt->region, p->notify);
875 	acl_list_delete(opt->region, p->provide_xfr);
876 	acl_list_delete(opt->region, p->outgoing_interface);
877 
878 	region_recycle(opt->region, p, sizeof(pattern_options_t));
879 }
880 
881 static acl_options_t*
882 copy_acl(region_type* region, acl_options_t* a)
883 {
884 	acl_options_t* b;
885 	if(!a) return NULL;
886 	b = (acl_options_t*)region_alloc(region, sizeof(*b));
887 	/* copy the whole lot */
888 	*b = *a;
889 	/* fix the pointers */
890 	if(a->ip_address_spec)
891 		b->ip_address_spec = region_strdup(region, a->ip_address_spec);
892 	if(a->key_name)
893 		b->key_name = region_strdup(region, a->key_name);
894 	b->next = NULL;
895 	b->key_options = NULL;
896 	return b;
897 }
898 
899 static acl_options_t*
900 copy_acl_list(nsd_options_t* opt, acl_options_t* a)
901 {
902 	acl_options_t* b, *blast = NULL, *blist = NULL;
903 	while(a) {
904 		b = copy_acl(opt->region, a);
905 		/* fixup key_options */
906 		if(b->key_name)
907 			b->key_options = key_options_find(opt, b->key_name);
908 		else	b->key_options = NULL;
909 
910 		/* link as last into list */
911 		b->next = NULL;
912 		if(!blist) blist = b;
913 		else blast->next = b;
914 		blast = b;
915 
916 		a = a->next;
917 	}
918 	return blist;
919 }
920 
921 static void
922 copy_changed_acl(nsd_options_t* opt, acl_options_t** orig,
923 	acl_options_t* anew)
924 {
925 	if(!acl_list_equal(*orig, anew)) {
926 		acl_list_delete(opt->region, *orig);
927 		*orig = copy_acl_list(opt, anew);
928 	}
929 }
930 
931 static void
932 copy_pat_fixed(region_type* region, pattern_options_t* orig,
933 	pattern_options_t* p)
934 {
935 	orig->allow_axfr_fallback = p->allow_axfr_fallback;
936 	orig->allow_axfr_fallback_is_default =
937 		p->allow_axfr_fallback_is_default;
938 	orig->notify_retry = p->notify_retry;
939 	orig->notify_retry_is_default = p->notify_retry_is_default;
940 	orig->implicit = p->implicit;
941 	if(p->zonefile)
942 		orig->zonefile = region_strdup(region, p->zonefile);
943 	else orig->zonefile = NULL;
944 	if(p->zonestats)
945 		orig->zonestats = region_strdup(region, p->zonestats);
946 	else orig->zonestats = NULL;
947 #ifdef RATELIMIT
948 	orig->rrl_whitelist = p->rrl_whitelist;
949 #endif
950 }
951 
952 void
953 pattern_options_add_modify(nsd_options_t* opt, pattern_options_t* p)
954 {
955 	pattern_options_t* orig = pattern_options_find(opt, p->pname);
956 	if(!orig) {
957 		/* needs to be copied to opt region */
958 		orig = pattern_options_create(opt->region);
959 		orig->pname = region_strdup(opt->region, p->pname);
960 		copy_pat_fixed(opt->region, orig, p);
961 		orig->allow_notify = copy_acl_list(opt, p->allow_notify);
962 		orig->request_xfr = copy_acl_list(opt, p->request_xfr);
963 		orig->notify = copy_acl_list(opt, p->notify);
964 		orig->provide_xfr = copy_acl_list(opt, p->provide_xfr);
965 		orig->outgoing_interface = copy_acl_list(opt,
966 			p->outgoing_interface);
967 		nsd_options_insert_pattern(opt, orig);
968 	} else {
969 		/* modify in place so pointers stay valid (and copy
970 		   into region). Do not touch unchanged acls. */
971 		if(orig->zonefile)
972 			region_recycle(opt->region, (char*)orig->zonefile,
973 				strlen(orig->zonefile)+1);
974 		if(orig->zonestats)
975 			region_recycle(opt->region, (char*)orig->zonestats,
976 				strlen(orig->zonestats)+1);
977 		copy_pat_fixed(opt->region, orig, p);
978 		copy_changed_acl(opt, &orig->allow_notify, p->allow_notify);
979 		copy_changed_acl(opt, &orig->request_xfr, p->request_xfr);
980 		copy_changed_acl(opt, &orig->notify, p->notify);
981 		copy_changed_acl(opt, &orig->provide_xfr, p->provide_xfr);
982 		copy_changed_acl(opt, &orig->outgoing_interface,
983 			p->outgoing_interface);
984 	}
985 }
986 
987 pattern_options_t*
988 pattern_options_find(nsd_options_t* opt, const char* name)
989 {
990 	return (pattern_options_t*)rbtree_search(opt->patterns, name);
991 }
992 
993 int
994 pattern_options_equal(pattern_options_t* p, pattern_options_t* q)
995 {
996 	if(strcmp(p->pname, q->pname) != 0) return 0;
997 	if(!p->zonefile && q->zonefile) return 0;
998 	else if(p->zonefile && !q->zonefile) return 0;
999 	else if(p->zonefile && q->zonefile) {
1000 		if(strcmp(p->zonefile, q->zonefile) != 0) return 0;
1001 	}
1002 	if(!p->zonestats && q->zonestats) return 0;
1003 	else if(p->zonestats && !q->zonestats) return 0;
1004 	else if(p->zonestats && q->zonestats) {
1005 		if(strcmp(p->zonestats, q->zonestats) != 0) return 0;
1006 	}
1007 	if(!booleq(p->allow_axfr_fallback, q->allow_axfr_fallback)) return 0;
1008 	if(!booleq(p->allow_axfr_fallback_is_default,
1009 		q->allow_axfr_fallback_is_default)) return 0;
1010 	if(p->notify_retry != q->notify_retry) return 0;
1011 	if(!booleq(p->notify_retry_is_default,
1012 		q->notify_retry_is_default)) return 0;
1013 	if(!booleq(p->implicit, q->implicit)) return 0;
1014 	if(!acl_list_equal(p->allow_notify, q->allow_notify)) return 0;
1015 	if(!acl_list_equal(p->request_xfr, q->request_xfr)) return 0;
1016 	if(!acl_list_equal(p->notify, q->notify)) return 0;
1017 	if(!acl_list_equal(p->provide_xfr, q->provide_xfr)) return 0;
1018 	if(!acl_list_equal(p->outgoing_interface, q->outgoing_interface))
1019 		return 0;
1020 #ifdef RATELIMIT
1021 	if(p->rrl_whitelist != q->rrl_whitelist) return 0;
1022 #endif
1023 	return 1;
1024 }
1025 
1026 static void
1027 marshal_u8(struct buffer* b, uint8_t v)
1028 {
1029 	buffer_reserve(b, 1);
1030 	buffer_write_u8(b, v);
1031 }
1032 
1033 static uint8_t
1034 unmarshal_u8(struct buffer* b)
1035 {
1036 	return buffer_read_u8(b);
1037 }
1038 
1039 #ifdef RATELIMIT
1040 static void
1041 marshal_u16(struct buffer* b, uint16_t v)
1042 {
1043 	buffer_reserve(b, 2);
1044 	buffer_write_u16(b, v);
1045 }
1046 #endif
1047 
1048 #ifdef RATELIMIT
1049 static uint16_t
1050 unmarshal_u16(struct buffer* b)
1051 {
1052 	return buffer_read_u16(b);
1053 }
1054 #endif
1055 
1056 static void
1057 marshal_str(struct buffer* b, const char* s)
1058 {
1059 	if(!s) marshal_u8(b, 0);
1060 	else {
1061 		size_t len = strlen(s);
1062 		marshal_u8(b, 1);
1063 		buffer_reserve(b, len+1);
1064 		buffer_write(b, s, len+1);
1065 	}
1066 }
1067 
1068 static char*
1069 unmarshal_str(region_type* r, struct buffer* b)
1070 {
1071 	uint8_t nonnull = unmarshal_u8(b);
1072 	if(nonnull) {
1073 		char* result = region_strdup(r, (char*)buffer_current(b));
1074 		size_t len = strlen((char*)buffer_current(b));
1075 		buffer_skip(b, len+1);
1076 		return result;
1077 	} else return NULL;
1078 }
1079 
1080 static void
1081 marshal_acl(struct buffer* b, acl_options_t* acl)
1082 {
1083 	buffer_reserve(b, sizeof(*acl));
1084 	buffer_write(b, acl, sizeof(*acl));
1085 	marshal_str(b, acl->ip_address_spec);
1086 	marshal_str(b, acl->key_name);
1087 }
1088 
1089 static acl_options_t*
1090 unmarshal_acl(region_type* r, struct buffer* b)
1091 {
1092 	acl_options_t* acl = (acl_options_t*)region_alloc(r, sizeof(*acl));
1093 	buffer_read(b, acl, sizeof(*acl));
1094 	acl->next = NULL;
1095 	acl->key_options = NULL;
1096 	acl->ip_address_spec = unmarshal_str(r, b);
1097 	acl->key_name = unmarshal_str(r, b);
1098 	return acl;
1099 }
1100 
1101 static void
1102 marshal_acl_list(struct buffer* b, acl_options_t* list)
1103 {
1104 	while(list) {
1105 		marshal_u8(b, 1); /* is there a next one marker */
1106 		marshal_acl(b, list);
1107 		list = list->next;
1108 	}
1109 	marshal_u8(b, 0); /* end of list marker */
1110 }
1111 
1112 static acl_options_t*
1113 unmarshal_acl_list(region_type* r, struct buffer* b)
1114 {
1115 	acl_options_t* a, *last=NULL, *list=NULL;
1116 	while(unmarshal_u8(b)) {
1117 		a = unmarshal_acl(r, b);
1118 		/* link in */
1119 		a->next = NULL;
1120 		if(!list) list = a;
1121 		else last->next = a;
1122 		last = a;
1123 	}
1124 	return list;
1125 }
1126 
1127 void
1128 pattern_options_marshal(struct buffer* b, pattern_options_t* p)
1129 {
1130 	marshal_str(b, p->pname);
1131 	marshal_str(b, p->zonefile);
1132 	marshal_str(b, p->zonestats);
1133 #ifdef RATELIMIT
1134 	marshal_u16(b, p->rrl_whitelist);
1135 #endif
1136 	marshal_u8(b, p->allow_axfr_fallback);
1137 	marshal_u8(b, p->allow_axfr_fallback_is_default);
1138 	marshal_u8(b, p->notify_retry);
1139 	marshal_u8(b, p->notify_retry_is_default);
1140 	marshal_u8(b, p->implicit);
1141 	marshal_acl_list(b, p->allow_notify);
1142 	marshal_acl_list(b, p->request_xfr);
1143 	marshal_acl_list(b, p->notify);
1144 	marshal_acl_list(b, p->provide_xfr);
1145 	marshal_acl_list(b, p->outgoing_interface);
1146 }
1147 
1148 pattern_options_t*
1149 pattern_options_unmarshal(region_type* r, struct buffer* b)
1150 {
1151 	pattern_options_t* p = pattern_options_create(r);
1152 	p->pname = unmarshal_str(r, b);
1153 	p->zonefile = unmarshal_str(r, b);
1154 	p->zonestats = unmarshal_str(r, b);
1155 #ifdef RATELIMIT
1156 	p->rrl_whitelist = unmarshal_u16(b);
1157 #endif
1158 	p->allow_axfr_fallback = unmarshal_u8(b);
1159 	p->allow_axfr_fallback_is_default = unmarshal_u8(b);
1160 	p->notify_retry = unmarshal_u8(b);
1161 	p->notify_retry_is_default = unmarshal_u8(b);
1162 	p->implicit = unmarshal_u8(b);
1163 	p->allow_notify = unmarshal_acl_list(r, b);
1164 	p->request_xfr = unmarshal_acl_list(r, b);
1165 	p->notify = unmarshal_acl_list(r, b);
1166 	p->provide_xfr = unmarshal_acl_list(r, b);
1167 	p->outgoing_interface = unmarshal_acl_list(r, b);
1168 	return p;
1169 }
1170 
1171 key_options_t*
1172 key_options_create(region_type* region)
1173 {
1174 	key_options_t* key;
1175 	key = (key_options_t*)region_alloc_zero(region, sizeof(key_options_t));
1176 	return key;
1177 }
1178 
1179 void
1180 key_options_insert(nsd_options_t* opt, key_options_t* key)
1181 {
1182 	if(!key->name) return;
1183 	key->node.key = key->name;
1184 	(void)rbtree_insert(opt->keys, &key->node);
1185 }
1186 
1187 key_options_t*
1188 key_options_find(nsd_options_t* opt, const char* name)
1189 {
1190 	return (key_options_t*)rbtree_search(opt->keys, name);
1191 }
1192 
1193 /** remove tsig_key contents */
1194 void
1195 key_options_desetup(region_type* region, key_options_t* key)
1196 {
1197 	/* keep tsig_key pointer so that existing references keep valid */
1198 	if(!key->tsig_key)
1199 		return;
1200 	/* name stays the same */
1201 	if(key->tsig_key->data) {
1202 		/* wipe secret! */
1203 		memset(key->tsig_key->data, 0xdd, key->tsig_key->size);
1204 		region_recycle(region, key->tsig_key->data,
1205 			key->tsig_key->size);
1206 		key->tsig_key->data = NULL;
1207 		key->tsig_key->size = 0;
1208 	}
1209 }
1210 
1211 /** add tsig_key contents */
1212 void
1213 key_options_setup(region_type* region, key_options_t* key)
1214 {
1215 	uint8_t data[16384]; /* 16KB */
1216 	int size;
1217 	if(!key->tsig_key) {
1218 		/* create it */
1219 		key->tsig_key = (tsig_key_type *) region_alloc(region,
1220 			sizeof(tsig_key_type));
1221 		/* create name */
1222 		key->tsig_key->name = dname_parse(region, key->name);
1223 		if(!key->tsig_key->name) {
1224 			log_msg(LOG_ERR, "Failed to parse tsig key name %s",
1225 				key->name);
1226 			/* key and base64 were checked during syntax parse */
1227 			exit(1);
1228 		}
1229 		key->tsig_key->size = 0;
1230 		key->tsig_key->data = NULL;
1231 	}
1232 	size = __b64_pton(key->secret, data, sizeof(data));
1233 	if(size == -1) {
1234 		log_msg(LOG_ERR, "Failed to parse tsig key data %s",
1235 			key->name);
1236 		/* key and base64 were checked during syntax parse */
1237 		exit(1);
1238 	}
1239 	key->tsig_key->size = size;
1240 	key->tsig_key->data = (uint8_t *)region_alloc_init(region, data, size);
1241 }
1242 
1243 void
1244 key_options_remove(nsd_options_t* opt, const char* name)
1245 {
1246 	key_options_t* k = key_options_find(opt, name);
1247 	if(!k) return;
1248 	(void)rbtree_delete(opt->keys, name);
1249 	if(k->name)
1250 		region_recycle(opt->region, k->name, strlen(k->name)+1);
1251 	if(k->algorithm)
1252 		region_recycle(opt->region, k->algorithm, strlen(k->algorithm)+1);
1253 	if(k->secret) {
1254 		memset(k->secret, 0xdd, strlen(k->secret)); /* wipe secret! */
1255 		region_recycle(opt->region, k->secret, strlen(k->secret)+1);
1256 	}
1257 	if(k->tsig_key) {
1258 		tsig_del_key(k->tsig_key);
1259 		if(k->tsig_key->name)
1260 			region_recycle(opt->region, (void*)k->tsig_key->name,
1261 				dname_total_size(k->tsig_key->name));
1262 		key_options_desetup(opt->region, k);
1263 		region_recycle(opt->region, k->tsig_key, sizeof(tsig_key_type));
1264 	}
1265 	region_recycle(opt->region, k, sizeof(key_options_t));
1266 }
1267 
1268 int
1269 key_options_equal(key_options_t* p, key_options_t* q)
1270 {
1271 	return strcmp(p->name, q->name)==0 && strcmp(p->algorithm,
1272 		q->algorithm)==0 && strcmp(p->secret, q->secret)==0;
1273 }
1274 
1275 void
1276 key_options_add_modify(nsd_options_t* opt, key_options_t* key)
1277 {
1278 	key_options_t* orig = key_options_find(opt, key->name);
1279 	if(!orig) {
1280 		/* needs to be copied to opt region */
1281 		orig = key_options_create(opt->region);
1282 		orig->name = region_strdup(opt->region, key->name);
1283 		orig->algorithm = region_strdup(opt->region, key->algorithm);
1284 		orig->secret = region_strdup(opt->region, key->secret);
1285 		key_options_setup(opt->region, orig);
1286 		tsig_add_key(orig->tsig_key);
1287 		key_options_insert(opt, orig);
1288 	} else {
1289 		/* modify entries in existing key, and copy to opt region */
1290 		key_options_desetup(opt->region, orig);
1291 		region_recycle(opt->region, orig->algorithm,
1292 			strlen(orig->algorithm)+1);
1293 		orig->algorithm = region_strdup(opt->region, key->algorithm);
1294 		region_recycle(opt->region, orig->secret,
1295 			strlen(orig->secret)+1);
1296 		orig->secret = region_strdup(opt->region, key->secret);
1297 		key_options_setup(opt->region, orig);
1298 	}
1299 }
1300 
1301 int
1302 acl_check_incoming(acl_options_t* acl, struct query* q,
1303 	acl_options_t** reason)
1304 {
1305 	/* check each acl element.
1306 	   if 1 blocked element matches - return -1.
1307 	   if any element matches - return number.
1308 	   else return -1. */
1309 	int found_match = -1;
1310 	int number = 0;
1311 	acl_options_t* match = 0;
1312 
1313 	if(reason)
1314 		*reason = NULL;
1315 
1316 	while(acl)
1317 	{
1318 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "testing acl %s %s",
1319 			acl->ip_address_spec, acl->nokey?"NOKEY":
1320 			(acl->blocked?"BLOCKED":acl->key_name)));
1321 		if(acl_addr_matches(acl, q) && acl_key_matches(acl, q)) {
1322 			if(!match)
1323 			{
1324 				match = acl; /* remember first match */
1325 				found_match=number;
1326 			}
1327 			if(acl->blocked) {
1328 				if(reason)
1329 					*reason = acl;
1330 				return -1;
1331 			}
1332 		}
1333 		number++;
1334 		acl = acl->next;
1335 	}
1336 
1337 	if(reason)
1338 		*reason = match;
1339 	return found_match;
1340 }
1341 
1342 #ifdef INET6
1343 int
1344 acl_addr_matches_ipv6host(acl_options_t* acl, struct sockaddr_storage* addr_storage, unsigned int port)
1345 {
1346 	struct sockaddr_in6* addr = (struct sockaddr_in6*)addr_storage;
1347 	if(acl->port != 0 && acl->port != port)
1348 		return 0;
1349 	switch(acl->rangetype) {
1350 	case acl_range_mask:
1351 	case acl_range_subnet:
1352 		if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
1353 			(uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr)))
1354 			return 0;
1355 		break;
1356 	case acl_range_minmax:
1357 		if(!acl_addr_match_range((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
1358 			(uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr)))
1359 			return 0;
1360 		break;
1361 	case acl_range_single:
1362 	default:
1363 		if(memcmp(&addr->sin6_addr, &acl->addr.addr6,
1364 			sizeof(struct in6_addr)) != 0)
1365 			return 0;
1366 		break;
1367 	}
1368 	return 1;
1369 }
1370 #endif
1371 
1372 int
1373 acl_addr_matches_ipv4host(acl_options_t* acl, struct sockaddr_in* addr, unsigned int port)
1374 {
1375 	if(acl->port != 0 && acl->port != port)
1376 		return 0;
1377 	switch(acl->rangetype) {
1378 	case acl_range_mask:
1379 	case acl_range_subnet:
1380 		if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
1381 			(uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr)))
1382 			return 0;
1383 		break;
1384 	case acl_range_minmax:
1385 		if(!acl_addr_match_range((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
1386 			(uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr)))
1387 			return 0;
1388 		break;
1389 	case acl_range_single:
1390 	default:
1391 		if(memcmp(&addr->sin_addr, &acl->addr.addr,
1392 			sizeof(struct in_addr)) != 0)
1393 			return 0;
1394 		break;
1395 	}
1396 	return 1;
1397 }
1398 
1399 int
1400 acl_addr_matches_host(acl_options_t* acl, acl_options_t* host)
1401 {
1402 	if(acl->is_ipv6)
1403 	{
1404 #ifdef INET6
1405 		struct sockaddr_storage* addr = (struct sockaddr_storage*)&host->addr;
1406 		if(!host->is_ipv6) return 0;
1407 		return acl_addr_matches_ipv6host(acl, addr, host->port);
1408 #else
1409 		return 0; /* no inet6, no match */
1410 #endif
1411 	}
1412 	else
1413 	{
1414 		struct sockaddr_in* addr = (struct sockaddr_in*)&host->addr;
1415 		if(host->is_ipv6) return 0;
1416 		return acl_addr_matches_ipv4host(acl, addr, host->port);
1417 	}
1418 	/* ENOTREACH */
1419 	return 0;
1420 }
1421 
1422 int
1423 acl_addr_matches(acl_options_t* acl, struct query* q)
1424 {
1425 	if(acl->is_ipv6)
1426 	{
1427 #ifdef INET6
1428 		struct sockaddr_storage* addr = (struct sockaddr_storage*)&q->addr;
1429 		if(addr->ss_family != AF_INET6)
1430 			return 0;
1431 		return acl_addr_matches_ipv6host(acl, addr, ntohs(((struct sockaddr_in6*)addr)->sin6_port));
1432 #else
1433 		return 0; /* no inet6, no match */
1434 #endif
1435 	}
1436 	else
1437 	{
1438 		struct sockaddr_in* addr = (struct sockaddr_in*)&q->addr;
1439 		if(addr->sin_family != AF_INET)
1440 			return 0;
1441 		return acl_addr_matches_ipv4host(acl, addr, ntohs(addr->sin_port));
1442 	}
1443 	/* ENOTREACH */
1444 	return 0;
1445 }
1446 
1447 int
1448 acl_addr_match_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz)
1449 {
1450 	size_t i;
1451 #ifndef NDEBUG
1452 	assert(sz % 4 == 0);
1453 #endif
1454 	sz /= 4;
1455 	for(i=0; i<sz; ++i)
1456 	{
1457 		if(((*a++)&*mask) != ((*b++)&*mask))
1458 			return 0;
1459 		++mask;
1460 	}
1461 	return 1;
1462 }
1463 
1464 int
1465 acl_addr_match_range(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
1466 {
1467 	size_t i;
1468 	uint8_t checkmin = 1, checkmax = 1;
1469 #ifndef NDEBUG
1470 	assert(sz % 4 == 0);
1471 #endif
1472 	/* check treats x as one huge number */
1473 	sz /= 4;
1474 	for(i=0; i<sz; ++i)
1475 	{
1476 		/* if outside bounds, we are done */
1477 		if(checkmin)
1478 			if(minval[i] > x[i])
1479 				return 0;
1480 		if(checkmax)
1481 			if(maxval[i] < x[i])
1482 				return 0;
1483 		/* if x is equal to a bound, that bound needs further checks */
1484 		if(checkmin && minval[i]!=x[i])
1485 			checkmin = 0;
1486 		if(checkmax && maxval[i]!=x[i])
1487 			checkmax = 0;
1488 		if(!checkmin && !checkmax)
1489 			return 1; /* will always match */
1490 	}
1491 	return 1;
1492 }
1493 
1494 int
1495 acl_key_matches(acl_options_t* acl, struct query* q)
1496 {
1497 	if(acl->blocked)
1498 		return 1;
1499 	if(acl->nokey) {
1500 		if(q->tsig.status == TSIG_NOT_PRESENT)
1501 			return 1;
1502 		return 0;
1503 	}
1504 	/* check name of tsig key */
1505 	if(q->tsig.status != TSIG_OK) {
1506 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail query has no TSIG"));
1507 		return 0; /* query has no TSIG */
1508 	}
1509 	if(q->tsig.error_code != TSIG_ERROR_NOERROR) {
1510 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail, tsig has error"));
1511 		return 0; /* some tsig error */
1512 	}
1513 	if(!acl->key_options->tsig_key) {
1514 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail no config"));
1515 		return 0; /* key not properly configured */
1516 	}
1517 	if(dname_compare(q->tsig.key_name,
1518 		acl->key_options->tsig_key->name) != 0) {
1519 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail wrong key name"));
1520 		return 0; /* wrong key name */
1521 	}
1522 	if(tsig_strlowercmp(q->tsig.algorithm->short_name,
1523 		acl->key_options->algorithm) != 0) {
1524 		DEBUG(DEBUG_XFRD,2, (LOG_ERR, "query tsig wrong algorithm"));
1525 		return 0; /* no such algo */
1526 	}
1527 	return 1;
1528 }
1529 
1530 int
1531 acl_same_host(acl_options_t* a, acl_options_t* b)
1532 {
1533 	if(a->is_ipv6 && !b->is_ipv6)
1534 		return 0;
1535 	if(!a->is_ipv6 && b->is_ipv6)
1536 		return 0;
1537 	if(a->port != b->port)
1538 		return 0;
1539 	if(a->rangetype != b->rangetype)
1540 		return 0;
1541 	if(!a->is_ipv6) {
1542 		if(memcmp(&a->addr.addr, &b->addr.addr,
1543 		   sizeof(struct in_addr)) != 0)
1544 			return 0;
1545 		if(a->rangetype != acl_range_single &&
1546 		   memcmp(&a->range_mask.addr, &b->range_mask.addr,
1547 		   sizeof(struct in_addr)) != 0)
1548 			return 0;
1549 	} else {
1550 #ifdef INET6
1551 		if(memcmp(&a->addr.addr6, &b->addr.addr6,
1552 		   sizeof(struct in6_addr)) != 0)
1553 			return 0;
1554 		if(a->rangetype != acl_range_single &&
1555 		   memcmp(&a->range_mask.addr6, &b->range_mask.addr6,
1556 		   sizeof(struct in6_addr)) != 0)
1557 			return 0;
1558 #else
1559 		return 0;
1560 #endif
1561 	}
1562 	return 1;
1563 }
1564 
1565 #if defined(HAVE_SSL)
1566 void
1567 key_options_tsig_add(nsd_options_t* opt)
1568 {
1569 	key_options_t* optkey;
1570 	RBTREE_FOR(optkey, key_options_t*, opt->keys) {
1571 		key_options_setup(opt->region, optkey);
1572 		tsig_add_key(optkey->tsig_key);
1573 	}
1574 }
1575 #endif
1576 
1577 int
1578 zone_is_slave(zone_options_t* opt)
1579 {
1580 	return opt && opt->pattern && opt->pattern->request_xfr != 0;
1581 }
1582 
1583 /* get a character in string (or replacement char if not long enough) */
1584 static const char*
1585 get_char(const char* str, size_t i)
1586 {
1587 	static char res[2];
1588 	if(i >= strlen(str))
1589 		return ".";
1590 	res[0] = str[i];
1591 	res[1] = 0;
1592 	return res;
1593 }
1594 /* get end label of the zone name (or .) */
1595 static const char*
1596 get_end_label(zone_options_t* zone, int i)
1597 {
1598 	const dname_type* d = (const dname_type*)zone->node.key;
1599 	if(i >= d->label_count) {
1600 		return ".";
1601 	}
1602 	return wirelabel2str(dname_label(d, i));
1603 }
1604 /* replace occurrences of one with two */
1605 void
1606 replace_str(char* str, size_t len, const char* one, const char* two)
1607 {
1608 	char* pos;
1609 	char* at = str;
1610 	while( (pos=strstr(at, one)) ) {
1611 		if(strlen(str)+strlen(two)-strlen(one) >= len)
1612 			return; /* no more space to replace */
1613 		/* stuff before pos is fine */
1614 		/* move the stuff after pos to make space for two, add
1615 		 * one to length of remainder to also copy the 0 byte end */
1616 		memmove(pos+strlen(two), pos+strlen(one),
1617 			strlen(pos+strlen(one))+1);
1618 		/* copy in two */
1619 		memmove(pos, two, strlen(two));
1620 		/* at is end of the newly inserted two (avoids recursion if
1621 		 * two contains one) */
1622 		at = pos+strlen(two);
1623 	}
1624 }
1625 
1626 const char*
1627 config_cook_string(zone_options_t* zone, const char* input)
1628 {
1629 	static char f[1024];
1630 	/* if not a template, return as-is */
1631 	if(!strchr(input, '%')) {
1632 		return input;
1633 	}
1634 	strlcpy(f, input, sizeof(f));
1635 	if(strstr(f, "%1"))
1636 		replace_str(f, sizeof(f), "%1", get_char(zone->name, 0));
1637 	if(strstr(f, "%2"))
1638 		replace_str(f, sizeof(f), "%2", get_char(zone->name, 1));
1639 	if(strstr(f, "%3"))
1640 		replace_str(f, sizeof(f), "%3", get_char(zone->name, 2));
1641 	if(strstr(f, "%z"))
1642 		replace_str(f, sizeof(f), "%z", get_end_label(zone, 1));
1643 	if(strstr(f, "%y"))
1644 		replace_str(f, sizeof(f), "%y", get_end_label(zone, 2));
1645 	if(strstr(f, "%x"))
1646 		replace_str(f, sizeof(f), "%x", get_end_label(zone, 3));
1647 	if(strstr(f, "%s"))
1648 		replace_str(f, sizeof(f), "%s", zone->name);
1649 	return f;
1650 }
1651 
1652 const char*
1653 config_make_zonefile(zone_options_t* zone, struct nsd* nsd)
1654 {
1655 	static char f[1024];
1656 	/* if not a template, return as-is */
1657 	if(!strchr(zone->pattern->zonefile, '%')) {
1658 		if (nsd->chrootdir && nsd->chrootdir[0] &&
1659 			zone->pattern->zonefile &&
1660 			zone->pattern->zonefile[0] == '/' &&
1661 			strncmp(zone->pattern->zonefile, nsd->chrootdir,
1662 			strlen(nsd->chrootdir)) == 0)
1663 			/* -1 because chrootdir ends in trailing slash */
1664 			return zone->pattern->zonefile + strlen(nsd->chrootdir) - 1;
1665 		return zone->pattern->zonefile;
1666 	}
1667 	strlcpy(f, zone->pattern->zonefile, sizeof(f));
1668 	if(strstr(f, "%1"))
1669 		replace_str(f, sizeof(f), "%1", get_char(zone->name, 0));
1670 	if(strstr(f, "%2"))
1671 		replace_str(f, sizeof(f), "%2", get_char(zone->name, 1));
1672 	if(strstr(f, "%3"))
1673 		replace_str(f, sizeof(f), "%3", get_char(zone->name, 2));
1674 	if(strstr(f, "%z"))
1675 		replace_str(f, sizeof(f), "%z", get_end_label(zone, 1));
1676 	if(strstr(f, "%y"))
1677 		replace_str(f, sizeof(f), "%y", get_end_label(zone, 2));
1678 	if(strstr(f, "%x"))
1679 		replace_str(f, sizeof(f), "%x", get_end_label(zone, 3));
1680 	if(strstr(f, "%s"))
1681 		replace_str(f, sizeof(f), "%s", zone->name);
1682 	if (nsd->chrootdir && nsd->chrootdir[0] && f[0] == '/' &&
1683 		strncmp(f, nsd->chrootdir, strlen(nsd->chrootdir)) == 0)
1684 		/* -1 because chrootdir ends in trailing slash */
1685 		return f + strlen(nsd->chrootdir) - 1;
1686 	return f;
1687 }
1688 
1689 zone_options_t*
1690 zone_options_find(nsd_options_t* opt, const struct dname* apex)
1691 {
1692 	return (zone_options_t*) rbtree_search(opt->zone_options, apex);
1693 }
1694 
1695 acl_options_t*
1696 acl_find_num(acl_options_t* acl, int num)
1697 {
1698 	int count = num;
1699 	if(num < 0)
1700 		return 0;
1701 	while(acl && count > 0) {
1702 		acl = acl->next;
1703 		count--;
1704 	}
1705 	if(count == 0)
1706 		return acl;
1707 	return 0;
1708 }
1709 
1710 /* true if ipv6 address, false if ipv4 */
1711 int
1712 parse_acl_is_ipv6(const char* p)
1713 {
1714 	/* see if addr is ipv6 or ipv4 -- by : and . */
1715 	while(*p) {
1716 		if(*p == '.') return 0;
1717 		if(*p == ':') return 1;
1718 		++p;
1719 	}
1720 	return 0;
1721 }
1722 
1723 /* returns range type. mask is the 2nd part of the range */
1724 int
1725 parse_acl_range_type(char* ip, char** mask)
1726 {
1727 	char *p;
1728 	if((p=strchr(ip, '&'))!=0) {
1729 		*p = 0;
1730 		*mask = p+1;
1731 		return acl_range_mask;
1732 	}
1733 	if((p=strchr(ip, '/'))!=0) {
1734 		*p = 0;
1735 		*mask = p+1;
1736 		return acl_range_subnet;
1737 	}
1738 	if((p=strchr(ip, '-'))!=0) {
1739 		*p = 0;
1740 		*mask = p+1;
1741 		return acl_range_minmax;
1742 	}
1743 	*mask = 0;
1744 	return acl_range_single;
1745 }
1746 
1747 /* parses subnet mask, fills 0 mask as well */
1748 void
1749 parse_acl_range_subnet(char* p, void* addr, int maxbits)
1750 {
1751 	int subnet_bits = atoi(p);
1752 	uint8_t* addr_bytes = (uint8_t*)addr;
1753 	if(subnet_bits == 0 && strcmp(p, "0")!=0) {
1754 		c_error_msg("bad subnet range '%s'", p);
1755 		return;
1756 	}
1757 	if(subnet_bits < 0 || subnet_bits > maxbits) {
1758 		c_error_msg("subnet of %d bits out of range [0..%d]", subnet_bits, maxbits);
1759 		return;
1760 	}
1761 	/* fill addr with n bits of 1s (struct has been zeroed) */
1762 	while(subnet_bits >= 8) {
1763 		*addr_bytes++ = 0xff;
1764 		subnet_bits -= 8;
1765 	}
1766 	if(subnet_bits > 0) {
1767 		uint8_t shifts[] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
1768 		*addr_bytes = shifts[subnet_bits];
1769 	}
1770 }
1771 
1772 acl_options_t*
1773 parse_acl_info(region_type* region, char* ip, const char* key)
1774 {
1775 	char* p;
1776 	acl_options_t* acl = (acl_options_t*)region_alloc(region, sizeof(acl_options_t));
1777 	acl->next = 0;
1778 	/* ip */
1779 	acl->ip_address_spec = region_strdup(region, ip);
1780 	acl->use_axfr_only = 0;
1781 	acl->allow_udp = 0;
1782 	acl->ixfr_disabled = 0;
1783 	acl->bad_xfr_count = 0;
1784 	acl->key_options = 0;
1785 	acl->is_ipv6 = 0;
1786 	acl->port = 0;
1787 	memset(&acl->addr, 0, sizeof(union acl_addr_storage));
1788 	memset(&acl->range_mask, 0, sizeof(union acl_addr_storage));
1789 	if((p=strrchr(ip, '@'))!=0) {
1790 		if(atoi(p+1) == 0) c_error("expected port number after '@'");
1791 		else acl->port = atoi(p+1);
1792 		*p=0;
1793 	}
1794 	acl->rangetype = parse_acl_range_type(ip, &p);
1795 	if(parse_acl_is_ipv6(ip)) {
1796 		acl->is_ipv6 = 1;
1797 #ifdef INET6
1798 		if(inet_pton(AF_INET6, ip, &acl->addr.addr6) != 1)
1799 			c_error_msg("Bad ip6 address '%s'", ip);
1800 		if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax)
1801 			if(inet_pton(AF_INET6, p, &acl->range_mask.addr6) != 1)
1802 				c_error_msg("Bad ip6 address mask '%s'", p);
1803 		if(acl->rangetype==acl_range_subnet)
1804 			parse_acl_range_subnet(p, &acl->range_mask.addr6, 128);
1805 #else
1806 		c_error_msg("encountered IPv6 address '%s'.", ip);
1807 #endif /* INET6 */
1808 	} else {
1809 		acl->is_ipv6 = 0;
1810 		if(inet_pton(AF_INET, ip, &acl->addr.addr) != 1)
1811 			c_error_msg("Bad ip4 address '%s'", ip);
1812 		if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax)
1813 			if(inet_pton(AF_INET, p, &acl->range_mask.addr) != 1)
1814 				c_error_msg("Bad ip4 address mask '%s'", p);
1815 		if(acl->rangetype==acl_range_subnet)
1816 			parse_acl_range_subnet(p, &acl->range_mask.addr, 32);
1817 	}
1818 
1819 	/* key */
1820 	if(strcmp(key, "NOKEY")==0) {
1821 		acl->nokey = 1;
1822 		acl->blocked = 0;
1823 		acl->key_name = 0;
1824 	} else if(strcmp(key, "BLOCKED")==0) {
1825 		acl->nokey = 0;
1826 		acl->blocked = 1;
1827 		acl->key_name = 0;
1828 	} else {
1829 		acl->nokey = 0;
1830 		acl->blocked = 0;
1831 		acl->key_name = region_strdup(region, key);
1832 	}
1833 	return acl;
1834 }
1835 
1836 /* copy acl list at end of parser start, update current */
1837 static
1838 void append_acl(acl_options_t** start, acl_options_t** cur,
1839 	acl_options_t* list)
1840 {
1841 	while(list) {
1842 		acl_options_t* acl = copy_acl(cfg_parser->opt->region, list);
1843 		acl->next = NULL;
1844 		if(*cur)
1845 			(*cur)->next = acl;
1846 		else	*start = acl;
1847 		*cur = acl;
1848 		list = list->next;
1849 	}
1850 }
1851 
1852 void
1853 config_apply_pattern(const char* name)
1854 {
1855 	/* find the pattern */
1856 	pattern_options_t* pat = pattern_options_find(cfg_parser->opt, name);
1857 	pattern_options_t* a = cfg_parser->current_pattern;
1858 	if(!pat) {
1859 		c_error_msg("could not find pattern %s", name);
1860 		return;
1861 	}
1862 
1863 	/* apply settings */
1864 	if(pat->zonefile)
1865 		a->zonefile = region_strdup(cfg_parser->opt->region,
1866 			pat->zonefile);
1867 	if(pat->zonestats)
1868 		a->zonestats = region_strdup(cfg_parser->opt->region,
1869 			pat->zonestats);
1870 	if(!pat->allow_axfr_fallback_is_default) {
1871 		a->allow_axfr_fallback = pat->allow_axfr_fallback;
1872 		a->allow_axfr_fallback_is_default = 0;
1873 	}
1874 	if(!pat->notify_retry_is_default) {
1875 		a->notify_retry = pat->notify_retry;
1876 		a->notify_retry_is_default = 0;
1877 	}
1878 #ifdef RATELIMIT
1879 	a->rrl_whitelist |= pat->rrl_whitelist;
1880 #endif
1881 	/* append acl items */
1882 	append_acl(&a->allow_notify, &cfg_parser->current_allow_notify,
1883 		pat->allow_notify);
1884 	append_acl(&a->request_xfr, &cfg_parser->current_request_xfr,
1885 		pat->request_xfr);
1886 	append_acl(&a->notify, &cfg_parser->current_notify, pat->notify);
1887 	append_acl(&a->provide_xfr, &cfg_parser->current_provide_xfr,
1888 		pat->provide_xfr);
1889 	append_acl(&a->outgoing_interface, &cfg_parser->
1890 		current_outgoing_interface, pat->outgoing_interface);
1891 }
1892 
1893 void
1894 nsd_options_destroy(nsd_options_t* opt)
1895 {
1896 	region_destroy(opt->region);
1897 }
1898 
1899 unsigned getzonestatid(nsd_options_t* opt, zone_options_t* zopt)
1900 {
1901 #ifdef USE_ZONE_STATS
1902 	const char* statname;
1903 	struct zonestatname* n;
1904 	rbnode_t* res;
1905 	/* try to find the instantiated zonestat name */
1906 	if(!zopt->pattern->zonestats || zopt->pattern->zonestats[0]==0)
1907 		return 0; /* no zone stats */
1908 	statname = config_cook_string(zopt, zopt->pattern->zonestats);
1909 	res = rbtree_search(opt->zonestatnames, statname);
1910 	if(res)
1911 		return ((struct zonestatname*)res)->id;
1912 	/* create it */
1913 	n = (struct zonestatname*)xalloc(sizeof(*n));
1914 	memset(n, 0, sizeof(*n));
1915 	n->node.key = strdup(statname);
1916 	if(!n->node.key) {
1917 		log_msg(LOG_ERR, "malloc failed: %s", strerror(errno));
1918 		exit(1);
1919 	}
1920 	n->id = (unsigned)(opt->zonestatnames->count);
1921 	rbtree_insert(opt->zonestatnames, (rbnode_t*)n);
1922 	return n->id;
1923 #else /* USE_ZONE_STATS */
1924 	(void)opt; (void)zopt;
1925 	return 0;
1926 #endif /* USE_ZONE_STATS */
1927 }
1928