xref: /openbsd/usr.sbin/nsd/options.c (revision fc61954a)
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->size_limit_xfr = 0;
817 	p->notify = 0;
818 	p->provide_xfr = 0;
819 	p->outgoing_interface = 0;
820 	p->notify_retry = 5;
821 	p->notify_retry_is_default = 1;
822 	p->allow_axfr_fallback = 1;
823 	p->allow_axfr_fallback_is_default = 1;
824 	p->implicit = 0;
825 	p->xfrd_flags = 0;
826 	p->max_refresh_time = 2419200;	/* 4 weeks */
827 	p->max_refresh_time_is_default = 1;
828 	p->min_refresh_time = 0;
829 	p->min_refresh_time_is_default = 1;
830 	p->max_retry_time = 1209600;	/* 2 weeks */
831 	p->max_retry_time_is_default = 1;
832 	p->min_retry_time = 0;
833 	p->min_retry_time_is_default = 1;
834 #ifdef RATELIMIT
835 	p->rrl_whitelist = 0;
836 #endif
837 	p->multi_master_check = 0;
838 	return p;
839 }
840 
841 static void
842 acl_delete(region_type* region, acl_options_t* acl)
843 {
844 	if(acl->ip_address_spec)
845 		region_recycle(region, (void*)acl->ip_address_spec,
846 			strlen(acl->ip_address_spec)+1);
847 	if(acl->key_name)
848 		region_recycle(region, (void*)acl->key_name,
849 			strlen(acl->key_name)+1);
850 	/* key_options is a convenience pointer, not owned by the acl */
851 	region_recycle(region, acl, sizeof(*acl));
852 }
853 
854 static void
855 acl_list_delete(region_type* region, acl_options_t* list)
856 {
857 	acl_options_t* n;
858 	while(list) {
859 		n = list->next;
860 		acl_delete(region, list);
861 		list = n;
862 	}
863 }
864 
865 void
866 pattern_options_remove(nsd_options_t* opt, const char* name)
867 {
868 	pattern_options_t* p = (pattern_options_t*)rbtree_delete(
869 		opt->patterns, name);
870 	/* delete p and its contents */
871 	if (!p)
872 		return;
873 	if(p->pname)
874 		region_recycle(opt->region, (void*)p->pname,
875 			strlen(p->pname)+1);
876 	if(p->zonefile)
877 		region_recycle(opt->region, (void*)p->zonefile,
878 			strlen(p->zonefile)+1);
879 	if(p->zonestats)
880 		region_recycle(opt->region, (void*)p->zonestats,
881 			strlen(p->zonestats)+1);
882 	acl_list_delete(opt->region, p->allow_notify);
883 	acl_list_delete(opt->region, p->request_xfr);
884 	acl_list_delete(opt->region, p->notify);
885 	acl_list_delete(opt->region, p->provide_xfr);
886 	acl_list_delete(opt->region, p->outgoing_interface);
887 
888 	region_recycle(opt->region, p, sizeof(pattern_options_t));
889 }
890 
891 static acl_options_t*
892 copy_acl(region_type* region, acl_options_t* a)
893 {
894 	acl_options_t* b;
895 	if(!a) return NULL;
896 	b = (acl_options_t*)region_alloc(region, sizeof(*b));
897 	/* copy the whole lot */
898 	*b = *a;
899 	/* fix the pointers */
900 	if(a->ip_address_spec)
901 		b->ip_address_spec = region_strdup(region, a->ip_address_spec);
902 	if(a->key_name)
903 		b->key_name = region_strdup(region, a->key_name);
904 	b->next = NULL;
905 	b->key_options = NULL;
906 	return b;
907 }
908 
909 static acl_options_t*
910 copy_acl_list(nsd_options_t* opt, acl_options_t* a)
911 {
912 	acl_options_t* b, *blast = NULL, *blist = NULL;
913 	while(a) {
914 		b = copy_acl(opt->region, a);
915 		/* fixup key_options */
916 		if(b->key_name)
917 			b->key_options = key_options_find(opt, b->key_name);
918 		else	b->key_options = NULL;
919 
920 		/* link as last into list */
921 		b->next = NULL;
922 		if(!blist) blist = b;
923 		else blast->next = b;
924 		blast = b;
925 
926 		a = a->next;
927 	}
928 	return blist;
929 }
930 
931 static void
932 copy_changed_acl(nsd_options_t* opt, acl_options_t** orig,
933 	acl_options_t* anew)
934 {
935 	if(!acl_list_equal(*orig, anew)) {
936 		acl_list_delete(opt->region, *orig);
937 		*orig = copy_acl_list(opt, anew);
938 	}
939 }
940 
941 static void
942 copy_pat_fixed(region_type* region, pattern_options_t* orig,
943 	pattern_options_t* p)
944 {
945 	orig->allow_axfr_fallback = p->allow_axfr_fallback;
946 	orig->allow_axfr_fallback_is_default =
947 		p->allow_axfr_fallback_is_default;
948 	orig->notify_retry = p->notify_retry;
949 	orig->notify_retry_is_default = p->notify_retry_is_default;
950 	orig->implicit = p->implicit;
951 	if(p->zonefile)
952 		orig->zonefile = region_strdup(region, p->zonefile);
953 	else orig->zonefile = NULL;
954 	if(p->zonestats)
955 		orig->zonestats = region_strdup(region, p->zonestats);
956 	else orig->zonestats = NULL;
957 	orig->max_refresh_time = p->max_refresh_time;
958 	orig->max_refresh_time_is_default = p->max_refresh_time_is_default;
959 	orig->min_refresh_time = p->min_refresh_time;
960 	orig->min_refresh_time_is_default = p->min_refresh_time_is_default;
961 	orig->max_retry_time = p->max_retry_time;
962 	orig->max_retry_time_is_default = p->max_retry_time_is_default;
963 	orig->min_retry_time = p->min_retry_time;
964 	orig->min_retry_time_is_default = p->min_retry_time_is_default;
965 #ifdef RATELIMIT
966 	orig->rrl_whitelist = p->rrl_whitelist;
967 #endif
968 	orig->multi_master_check = p->multi_master_check;
969 }
970 
971 void
972 pattern_options_add_modify(nsd_options_t* opt, pattern_options_t* p)
973 {
974 	pattern_options_t* orig = pattern_options_find(opt, p->pname);
975 	if(!orig) {
976 		/* needs to be copied to opt region */
977 		orig = pattern_options_create(opt->region);
978 		orig->pname = region_strdup(opt->region, p->pname);
979 		copy_pat_fixed(opt->region, orig, p);
980 		orig->allow_notify = copy_acl_list(opt, p->allow_notify);
981 		orig->request_xfr = copy_acl_list(opt, p->request_xfr);
982 		orig->notify = copy_acl_list(opt, p->notify);
983 		orig->provide_xfr = copy_acl_list(opt, p->provide_xfr);
984 		orig->outgoing_interface = copy_acl_list(opt,
985 			p->outgoing_interface);
986 		nsd_options_insert_pattern(opt, orig);
987 	} else {
988 		/* modify in place so pointers stay valid (and copy
989 		   into region). Do not touch unchanged acls. */
990 		if(orig->zonefile)
991 			region_recycle(opt->region, (char*)orig->zonefile,
992 				strlen(orig->zonefile)+1);
993 		if(orig->zonestats)
994 			region_recycle(opt->region, (char*)orig->zonestats,
995 				strlen(orig->zonestats)+1);
996 		copy_pat_fixed(opt->region, orig, p);
997 		copy_changed_acl(opt, &orig->allow_notify, p->allow_notify);
998 		copy_changed_acl(opt, &orig->request_xfr, p->request_xfr);
999 		copy_changed_acl(opt, &orig->notify, p->notify);
1000 		copy_changed_acl(opt, &orig->provide_xfr, p->provide_xfr);
1001 		copy_changed_acl(opt, &orig->outgoing_interface,
1002 			p->outgoing_interface);
1003 	}
1004 }
1005 
1006 pattern_options_t*
1007 pattern_options_find(nsd_options_t* opt, const char* name)
1008 {
1009 	return (pattern_options_t*)rbtree_search(opt->patterns, name);
1010 }
1011 
1012 int
1013 pattern_options_equal(pattern_options_t* p, pattern_options_t* q)
1014 {
1015 	if(strcmp(p->pname, q->pname) != 0) return 0;
1016 	if(!p->zonefile && q->zonefile) return 0;
1017 	else if(p->zonefile && !q->zonefile) return 0;
1018 	else if(p->zonefile && q->zonefile) {
1019 		if(strcmp(p->zonefile, q->zonefile) != 0) return 0;
1020 	}
1021 	if(!p->zonestats && q->zonestats) return 0;
1022 	else if(p->zonestats && !q->zonestats) return 0;
1023 	else if(p->zonestats && q->zonestats) {
1024 		if(strcmp(p->zonestats, q->zonestats) != 0) return 0;
1025 	}
1026 	if(!booleq(p->allow_axfr_fallback, q->allow_axfr_fallback)) return 0;
1027 	if(!booleq(p->allow_axfr_fallback_is_default,
1028 		q->allow_axfr_fallback_is_default)) return 0;
1029 	if(p->notify_retry != q->notify_retry) return 0;
1030 	if(!booleq(p->notify_retry_is_default,
1031 		q->notify_retry_is_default)) return 0;
1032 	if(!booleq(p->implicit, q->implicit)) return 0;
1033 	if(!acl_list_equal(p->allow_notify, q->allow_notify)) return 0;
1034 	if(!acl_list_equal(p->request_xfr, q->request_xfr)) return 0;
1035 	if(!acl_list_equal(p->notify, q->notify)) return 0;
1036 	if(!acl_list_equal(p->provide_xfr, q->provide_xfr)) return 0;
1037 	if(!acl_list_equal(p->outgoing_interface, q->outgoing_interface))
1038 		return 0;
1039 	if(p->max_refresh_time != q->max_refresh_time) return 0;
1040 	if(!booleq(p->max_refresh_time_is_default,
1041 		q->max_refresh_time_is_default)) return 0;
1042 	if(p->min_refresh_time != q->min_refresh_time) return 0;
1043 	if(!booleq(p->min_refresh_time_is_default,
1044 		q->min_refresh_time_is_default)) return 0;
1045 	if(p->max_retry_time != q->max_retry_time) return 0;
1046 	if(!booleq(p->max_retry_time_is_default,
1047 		q->max_retry_time_is_default)) return 0;
1048 	if(p->min_retry_time != q->min_retry_time) return 0;
1049 	if(!booleq(p->min_retry_time_is_default,
1050 		q->min_retry_time_is_default)) return 0;
1051 #ifdef RATELIMIT
1052 	if(p->rrl_whitelist != q->rrl_whitelist) return 0;
1053 #endif
1054 	if(!booleq(p->multi_master_check,q->multi_master_check)) return 0;
1055 	if(p->size_limit_xfr != q->size_limit_xfr) return 0;
1056 	return 1;
1057 }
1058 
1059 static void
1060 marshal_u8(struct buffer* b, uint8_t v)
1061 {
1062 	buffer_reserve(b, 1);
1063 	buffer_write_u8(b, v);
1064 }
1065 
1066 static uint8_t
1067 unmarshal_u8(struct buffer* b)
1068 {
1069 	return buffer_read_u8(b);
1070 }
1071 
1072 static void
1073 marshal_u64(struct buffer* b, uint64_t v)
1074 {
1075 	buffer_reserve(b, 8);
1076 	buffer_write_u64(b, v);
1077 }
1078 
1079 static uint64_t
1080 unmarshal_u64(struct buffer* b)
1081 {
1082 	return buffer_read_u64(b);
1083 }
1084 
1085 #ifdef RATELIMIT
1086 static void
1087 marshal_u16(struct buffer* b, uint16_t v)
1088 {
1089 	buffer_reserve(b, 2);
1090 	buffer_write_u16(b, v);
1091 }
1092 #endif
1093 
1094 #ifdef RATELIMIT
1095 static uint16_t
1096 unmarshal_u16(struct buffer* b)
1097 {
1098 	return buffer_read_u16(b);
1099 }
1100 #endif
1101 
1102 static void
1103 marshal_u32(struct buffer* b, uint32_t v)
1104 {
1105 	buffer_reserve(b, 4);
1106 	buffer_write_u32(b, v);
1107 }
1108 
1109 static uint32_t
1110 unmarshal_u32(struct buffer* b)
1111 {
1112 	return buffer_read_u32(b);
1113 }
1114 
1115 static void
1116 marshal_str(struct buffer* b, const char* s)
1117 {
1118 	if(!s) marshal_u8(b, 0);
1119 	else {
1120 		size_t len = strlen(s);
1121 		marshal_u8(b, 1);
1122 		buffer_reserve(b, len+1);
1123 		buffer_write(b, s, len+1);
1124 	}
1125 }
1126 
1127 static char*
1128 unmarshal_str(region_type* r, struct buffer* b)
1129 {
1130 	uint8_t nonnull = unmarshal_u8(b);
1131 	if(nonnull) {
1132 		char* result = region_strdup(r, (char*)buffer_current(b));
1133 		size_t len = strlen((char*)buffer_current(b));
1134 		buffer_skip(b, len+1);
1135 		return result;
1136 	} else return NULL;
1137 }
1138 
1139 static void
1140 marshal_acl(struct buffer* b, acl_options_t* acl)
1141 {
1142 	buffer_reserve(b, sizeof(*acl));
1143 	buffer_write(b, acl, sizeof(*acl));
1144 	marshal_str(b, acl->ip_address_spec);
1145 	marshal_str(b, acl->key_name);
1146 }
1147 
1148 static acl_options_t*
1149 unmarshal_acl(region_type* r, struct buffer* b)
1150 {
1151 	acl_options_t* acl = (acl_options_t*)region_alloc(r, sizeof(*acl));
1152 	buffer_read(b, acl, sizeof(*acl));
1153 	acl->next = NULL;
1154 	acl->key_options = NULL;
1155 	acl->ip_address_spec = unmarshal_str(r, b);
1156 	acl->key_name = unmarshal_str(r, b);
1157 	return acl;
1158 }
1159 
1160 static void
1161 marshal_acl_list(struct buffer* b, acl_options_t* list)
1162 {
1163 	while(list) {
1164 		marshal_u8(b, 1); /* is there a next one marker */
1165 		marshal_acl(b, list);
1166 		list = list->next;
1167 	}
1168 	marshal_u8(b, 0); /* end of list marker */
1169 }
1170 
1171 static acl_options_t*
1172 unmarshal_acl_list(region_type* r, struct buffer* b)
1173 {
1174 	acl_options_t* a, *last=NULL, *list=NULL;
1175 	while(unmarshal_u8(b)) {
1176 		a = unmarshal_acl(r, b);
1177 		/* link in */
1178 		a->next = NULL;
1179 		if(!list) list = a;
1180 		else last->next = a;
1181 		last = a;
1182 	}
1183 	return list;
1184 }
1185 
1186 void
1187 pattern_options_marshal(struct buffer* b, pattern_options_t* p)
1188 {
1189 	marshal_str(b, p->pname);
1190 	marshal_str(b, p->zonefile);
1191 	marshal_str(b, p->zonestats);
1192 #ifdef RATELIMIT
1193 	marshal_u16(b, p->rrl_whitelist);
1194 #endif
1195 	marshal_u8(b, p->allow_axfr_fallback);
1196 	marshal_u8(b, p->allow_axfr_fallback_is_default);
1197 	marshal_u8(b, p->notify_retry);
1198 	marshal_u8(b, p->notify_retry_is_default);
1199 	marshal_u8(b, p->implicit);
1200 	marshal_u64(b, p->size_limit_xfr);
1201 	marshal_acl_list(b, p->allow_notify);
1202 	marshal_acl_list(b, p->request_xfr);
1203 	marshal_acl_list(b, p->notify);
1204 	marshal_acl_list(b, p->provide_xfr);
1205 	marshal_acl_list(b, p->outgoing_interface);
1206 	marshal_u32(b, p->max_refresh_time);
1207 	marshal_u8(b, p->max_refresh_time_is_default);
1208 	marshal_u32(b, p->min_refresh_time);
1209 	marshal_u8(b, p->min_refresh_time_is_default);
1210 	marshal_u32(b, p->max_retry_time);
1211 	marshal_u8(b, p->max_retry_time_is_default);
1212 	marshal_u32(b, p->min_retry_time);
1213 	marshal_u8(b, p->min_retry_time_is_default);
1214 	marshal_u8(b, p->multi_master_check);
1215 }
1216 
1217 pattern_options_t*
1218 pattern_options_unmarshal(region_type* r, struct buffer* b)
1219 {
1220 	pattern_options_t* p = pattern_options_create(r);
1221 	p->pname = unmarshal_str(r, b);
1222 	p->zonefile = unmarshal_str(r, b);
1223 	p->zonestats = unmarshal_str(r, b);
1224 #ifdef RATELIMIT
1225 	p->rrl_whitelist = unmarshal_u16(b);
1226 #endif
1227 	p->allow_axfr_fallback = unmarshal_u8(b);
1228 	p->allow_axfr_fallback_is_default = unmarshal_u8(b);
1229 	p->notify_retry = unmarshal_u8(b);
1230 	p->notify_retry_is_default = unmarshal_u8(b);
1231 	p->implicit = unmarshal_u8(b);
1232 	p->size_limit_xfr = unmarshal_u64(b);
1233 	p->allow_notify = unmarshal_acl_list(r, b);
1234 	p->request_xfr = unmarshal_acl_list(r, b);
1235 	p->notify = unmarshal_acl_list(r, b);
1236 	p->provide_xfr = unmarshal_acl_list(r, b);
1237 	p->outgoing_interface = unmarshal_acl_list(r, b);
1238 	p->max_refresh_time = unmarshal_u32(b);
1239 	p->max_refresh_time_is_default = unmarshal_u8(b);
1240 	p->min_refresh_time = unmarshal_u32(b);
1241 	p->min_refresh_time_is_default = unmarshal_u8(b);
1242 	p->max_retry_time = unmarshal_u32(b);
1243 	p->max_retry_time_is_default = unmarshal_u8(b);
1244 	p->min_retry_time = unmarshal_u32(b);
1245 	p->min_retry_time_is_default = unmarshal_u8(b);
1246 	p->multi_master_check = unmarshal_u8(b);
1247 	return p;
1248 }
1249 
1250 key_options_t*
1251 key_options_create(region_type* region)
1252 {
1253 	key_options_t* key;
1254 	key = (key_options_t*)region_alloc_zero(region, sizeof(key_options_t));
1255 	return key;
1256 }
1257 
1258 void
1259 key_options_insert(nsd_options_t* opt, key_options_t* key)
1260 {
1261 	if(!key->name) return;
1262 	key->node.key = key->name;
1263 	(void)rbtree_insert(opt->keys, &key->node);
1264 }
1265 
1266 key_options_t*
1267 key_options_find(nsd_options_t* opt, const char* name)
1268 {
1269 	return (key_options_t*)rbtree_search(opt->keys, name);
1270 }
1271 
1272 /** remove tsig_key contents */
1273 void
1274 key_options_desetup(region_type* region, key_options_t* key)
1275 {
1276 	/* keep tsig_key pointer so that existing references keep valid */
1277 	if(!key->tsig_key)
1278 		return;
1279 	/* name stays the same */
1280 	if(key->tsig_key->data) {
1281 		/* wipe secret! */
1282 		memset(key->tsig_key->data, 0xdd, key->tsig_key->size);
1283 		region_recycle(region, key->tsig_key->data,
1284 			key->tsig_key->size);
1285 		key->tsig_key->data = NULL;
1286 		key->tsig_key->size = 0;
1287 	}
1288 }
1289 
1290 /** add tsig_key contents */
1291 void
1292 key_options_setup(region_type* region, key_options_t* key)
1293 {
1294 	uint8_t data[16384]; /* 16KB */
1295 	int size;
1296 	if(!key->tsig_key) {
1297 		/* create it */
1298 		key->tsig_key = (tsig_key_type *) region_alloc(region,
1299 			sizeof(tsig_key_type));
1300 		/* create name */
1301 		key->tsig_key->name = dname_parse(region, key->name);
1302 		if(!key->tsig_key->name) {
1303 			log_msg(LOG_ERR, "Failed to parse tsig key name %s",
1304 				key->name);
1305 			/* key and base64 were checked during syntax parse */
1306 			exit(1);
1307 		}
1308 		key->tsig_key->size = 0;
1309 		key->tsig_key->data = NULL;
1310 	}
1311 	size = __b64_pton(key->secret, data, sizeof(data));
1312 	if(size == -1) {
1313 		log_msg(LOG_ERR, "Failed to parse tsig key data %s",
1314 			key->name);
1315 		/* key and base64 were checked during syntax parse */
1316 		exit(1);
1317 	}
1318 	key->tsig_key->size = size;
1319 	key->tsig_key->data = (uint8_t *)region_alloc_init(region, data, size);
1320 }
1321 
1322 void
1323 key_options_remove(nsd_options_t* opt, const char* name)
1324 {
1325 	key_options_t* k = key_options_find(opt, name);
1326 	if(!k) return;
1327 	(void)rbtree_delete(opt->keys, name);
1328 	if(k->name)
1329 		region_recycle(opt->region, k->name, strlen(k->name)+1);
1330 	if(k->algorithm)
1331 		region_recycle(opt->region, k->algorithm, strlen(k->algorithm)+1);
1332 	if(k->secret) {
1333 		memset(k->secret, 0xdd, strlen(k->secret)); /* wipe secret! */
1334 		region_recycle(opt->region, k->secret, strlen(k->secret)+1);
1335 	}
1336 	if(k->tsig_key) {
1337 		tsig_del_key(k->tsig_key);
1338 		if(k->tsig_key->name)
1339 			region_recycle(opt->region, (void*)k->tsig_key->name,
1340 				dname_total_size(k->tsig_key->name));
1341 		key_options_desetup(opt->region, k);
1342 		region_recycle(opt->region, k->tsig_key, sizeof(tsig_key_type));
1343 	}
1344 	region_recycle(opt->region, k, sizeof(key_options_t));
1345 }
1346 
1347 int
1348 key_options_equal(key_options_t* p, key_options_t* q)
1349 {
1350 	return strcmp(p->name, q->name)==0 && strcmp(p->algorithm,
1351 		q->algorithm)==0 && strcmp(p->secret, q->secret)==0;
1352 }
1353 
1354 void
1355 key_options_add_modify(nsd_options_t* opt, key_options_t* key)
1356 {
1357 	key_options_t* orig = key_options_find(opt, key->name);
1358 	if(!orig) {
1359 		/* needs to be copied to opt region */
1360 		orig = key_options_create(opt->region);
1361 		orig->name = region_strdup(opt->region, key->name);
1362 		orig->algorithm = region_strdup(opt->region, key->algorithm);
1363 		orig->secret = region_strdup(opt->region, key->secret);
1364 		key_options_setup(opt->region, orig);
1365 		tsig_add_key(orig->tsig_key);
1366 		key_options_insert(opt, orig);
1367 	} else {
1368 		/* modify entries in existing key, and copy to opt region */
1369 		key_options_desetup(opt->region, orig);
1370 		region_recycle(opt->region, orig->algorithm,
1371 			strlen(orig->algorithm)+1);
1372 		orig->algorithm = region_strdup(opt->region, key->algorithm);
1373 		region_recycle(opt->region, orig->secret,
1374 			strlen(orig->secret)+1);
1375 		orig->secret = region_strdup(opt->region, key->secret);
1376 		key_options_setup(opt->region, orig);
1377 	}
1378 }
1379 
1380 int
1381 acl_check_incoming(acl_options_t* acl, struct query* q,
1382 	acl_options_t** reason)
1383 {
1384 	/* check each acl element.
1385 	   if 1 blocked element matches - return -1.
1386 	   if any element matches - return number.
1387 	   else return -1. */
1388 	int found_match = -1;
1389 	int number = 0;
1390 	acl_options_t* match = 0;
1391 
1392 	if(reason)
1393 		*reason = NULL;
1394 
1395 	while(acl)
1396 	{
1397 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "testing acl %s %s",
1398 			acl->ip_address_spec, acl->nokey?"NOKEY":
1399 			(acl->blocked?"BLOCKED":acl->key_name)));
1400 		if(acl_addr_matches(acl, q) && acl_key_matches(acl, q)) {
1401 			if(!match)
1402 			{
1403 				match = acl; /* remember first match */
1404 				found_match=number;
1405 			}
1406 			if(acl->blocked) {
1407 				if(reason)
1408 					*reason = acl;
1409 				return -1;
1410 			}
1411 		}
1412 		number++;
1413 		acl = acl->next;
1414 	}
1415 
1416 	if(reason)
1417 		*reason = match;
1418 	return found_match;
1419 }
1420 
1421 #ifdef INET6
1422 int
1423 acl_addr_matches_ipv6host(acl_options_t* acl, struct sockaddr_storage* addr_storage, unsigned int port)
1424 {
1425 	struct sockaddr_in6* addr = (struct sockaddr_in6*)addr_storage;
1426 	if(acl->port != 0 && acl->port != port)
1427 		return 0;
1428 	switch(acl->rangetype) {
1429 	case acl_range_mask:
1430 	case acl_range_subnet:
1431 		if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
1432 			(uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr)))
1433 			return 0;
1434 		break;
1435 	case acl_range_minmax:
1436 		if(!acl_addr_match_range((uint32_t*)&acl->addr.addr6, (uint32_t*)&addr->sin6_addr,
1437 			(uint32_t*)&acl->range_mask.addr6, sizeof(struct in6_addr)))
1438 			return 0;
1439 		break;
1440 	case acl_range_single:
1441 	default:
1442 		if(memcmp(&addr->sin6_addr, &acl->addr.addr6,
1443 			sizeof(struct in6_addr)) != 0)
1444 			return 0;
1445 		break;
1446 	}
1447 	return 1;
1448 }
1449 #endif
1450 
1451 int
1452 acl_addr_matches_ipv4host(acl_options_t* acl, struct sockaddr_in* addr, unsigned int port)
1453 {
1454 	if(acl->port != 0 && acl->port != port)
1455 		return 0;
1456 	switch(acl->rangetype) {
1457 	case acl_range_mask:
1458 	case acl_range_subnet:
1459 		if(!acl_addr_match_mask((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
1460 			(uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr)))
1461 			return 0;
1462 		break;
1463 	case acl_range_minmax:
1464 		if(!acl_addr_match_range((uint32_t*)&acl->addr.addr, (uint32_t*)&addr->sin_addr,
1465 			(uint32_t*)&acl->range_mask.addr, sizeof(struct in_addr)))
1466 			return 0;
1467 		break;
1468 	case acl_range_single:
1469 	default:
1470 		if(memcmp(&addr->sin_addr, &acl->addr.addr,
1471 			sizeof(struct in_addr)) != 0)
1472 			return 0;
1473 		break;
1474 	}
1475 	return 1;
1476 }
1477 
1478 int
1479 acl_addr_matches_host(acl_options_t* acl, acl_options_t* host)
1480 {
1481 	if(acl->is_ipv6)
1482 	{
1483 #ifdef INET6
1484 		struct sockaddr_storage* addr = (struct sockaddr_storage*)&host->addr;
1485 		if(!host->is_ipv6) return 0;
1486 		return acl_addr_matches_ipv6host(acl, addr, host->port);
1487 #else
1488 		return 0; /* no inet6, no match */
1489 #endif
1490 	}
1491 	else
1492 	{
1493 		struct sockaddr_in* addr = (struct sockaddr_in*)&host->addr;
1494 		if(host->is_ipv6) return 0;
1495 		return acl_addr_matches_ipv4host(acl, addr, host->port);
1496 	}
1497 	/* ENOTREACH */
1498 	return 0;
1499 }
1500 
1501 int
1502 acl_addr_matches(acl_options_t* acl, struct query* q)
1503 {
1504 	if(acl->is_ipv6)
1505 	{
1506 #ifdef INET6
1507 		struct sockaddr_storage* addr = (struct sockaddr_storage*)&q->addr;
1508 		if(addr->ss_family != AF_INET6)
1509 			return 0;
1510 		return acl_addr_matches_ipv6host(acl, addr, ntohs(((struct sockaddr_in6*)addr)->sin6_port));
1511 #else
1512 		return 0; /* no inet6, no match */
1513 #endif
1514 	}
1515 	else
1516 	{
1517 		struct sockaddr_in* addr = (struct sockaddr_in*)&q->addr;
1518 		if(addr->sin_family != AF_INET)
1519 			return 0;
1520 		return acl_addr_matches_ipv4host(acl, addr, ntohs(addr->sin_port));
1521 	}
1522 	/* ENOTREACH */
1523 	return 0;
1524 }
1525 
1526 int
1527 acl_addr_match_mask(uint32_t* a, uint32_t* b, uint32_t* mask, size_t sz)
1528 {
1529 	size_t i;
1530 #ifndef NDEBUG
1531 	assert(sz % 4 == 0);
1532 #endif
1533 	sz /= 4;
1534 	for(i=0; i<sz; ++i)
1535 	{
1536 		if(((*a++)&*mask) != ((*b++)&*mask))
1537 			return 0;
1538 		++mask;
1539 	}
1540 	return 1;
1541 }
1542 
1543 int
1544 acl_addr_match_range(uint32_t* minval, uint32_t* x, uint32_t* maxval, size_t sz)
1545 {
1546 	size_t i;
1547 	uint8_t checkmin = 1, checkmax = 1;
1548 #ifndef NDEBUG
1549 	assert(sz % 4 == 0);
1550 #endif
1551 	/* check treats x as one huge number */
1552 	sz /= 4;
1553 	for(i=0; i<sz; ++i)
1554 	{
1555 		/* if outside bounds, we are done */
1556 		if(checkmin)
1557 			if(minval[i] > x[i])
1558 				return 0;
1559 		if(checkmax)
1560 			if(maxval[i] < x[i])
1561 				return 0;
1562 		/* if x is equal to a bound, that bound needs further checks */
1563 		if(checkmin && minval[i]!=x[i])
1564 			checkmin = 0;
1565 		if(checkmax && maxval[i]!=x[i])
1566 			checkmax = 0;
1567 		if(!checkmin && !checkmax)
1568 			return 1; /* will always match */
1569 	}
1570 	return 1;
1571 }
1572 
1573 int
1574 acl_key_matches(acl_options_t* acl, struct query* q)
1575 {
1576 	if(acl->blocked)
1577 		return 1;
1578 	if(acl->nokey) {
1579 		if(q->tsig.status == TSIG_NOT_PRESENT)
1580 			return 1;
1581 		return 0;
1582 	}
1583 	/* check name of tsig key */
1584 	if(q->tsig.status != TSIG_OK) {
1585 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail query has no TSIG"));
1586 		return 0; /* query has no TSIG */
1587 	}
1588 	if(q->tsig.error_code != TSIG_ERROR_NOERROR) {
1589 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail, tsig has error"));
1590 		return 0; /* some tsig error */
1591 	}
1592 	if(!acl->key_options->tsig_key) {
1593 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail no config"));
1594 		return 0; /* key not properly configured */
1595 	}
1596 	if(dname_compare(q->tsig.key_name,
1597 		acl->key_options->tsig_key->name) != 0) {
1598 		DEBUG(DEBUG_XFRD,2, (LOG_INFO, "keymatch fail wrong key name"));
1599 		return 0; /* wrong key name */
1600 	}
1601 	if(tsig_strlowercmp(q->tsig.algorithm->short_name,
1602 		acl->key_options->algorithm) != 0 && (
1603 		strncmp("hmac-", q->tsig.algorithm->short_name, 5) != 0 ||
1604 		tsig_strlowercmp(q->tsig.algorithm->short_name+5,
1605 		acl->key_options->algorithm) != 0) ) {
1606 		DEBUG(DEBUG_XFRD,2, (LOG_ERR, "query tsig wrong algorithm"));
1607 		return 0; /* no such algo */
1608 	}
1609 	return 1;
1610 }
1611 
1612 int
1613 acl_same_host(acl_options_t* a, acl_options_t* b)
1614 {
1615 	if(a->is_ipv6 && !b->is_ipv6)
1616 		return 0;
1617 	if(!a->is_ipv6 && b->is_ipv6)
1618 		return 0;
1619 	if(a->port != b->port)
1620 		return 0;
1621 	if(a->rangetype != b->rangetype)
1622 		return 0;
1623 	if(!a->is_ipv6) {
1624 		if(memcmp(&a->addr.addr, &b->addr.addr,
1625 		   sizeof(struct in_addr)) != 0)
1626 			return 0;
1627 		if(a->rangetype != acl_range_single &&
1628 		   memcmp(&a->range_mask.addr, &b->range_mask.addr,
1629 		   sizeof(struct in_addr)) != 0)
1630 			return 0;
1631 	} else {
1632 #ifdef INET6
1633 		if(memcmp(&a->addr.addr6, &b->addr.addr6,
1634 		   sizeof(struct in6_addr)) != 0)
1635 			return 0;
1636 		if(a->rangetype != acl_range_single &&
1637 		   memcmp(&a->range_mask.addr6, &b->range_mask.addr6,
1638 		   sizeof(struct in6_addr)) != 0)
1639 			return 0;
1640 #else
1641 		return 0;
1642 #endif
1643 	}
1644 	return 1;
1645 }
1646 
1647 #if defined(HAVE_SSL)
1648 void
1649 key_options_tsig_add(nsd_options_t* opt)
1650 {
1651 	key_options_t* optkey;
1652 	RBTREE_FOR(optkey, key_options_t*, opt->keys) {
1653 		key_options_setup(opt->region, optkey);
1654 		tsig_add_key(optkey->tsig_key);
1655 	}
1656 }
1657 #endif
1658 
1659 int
1660 zone_is_slave(zone_options_t* opt)
1661 {
1662 	return opt && opt->pattern && opt->pattern->request_xfr != 0;
1663 }
1664 
1665 /* get a character in string (or replacement char if not long enough) */
1666 static const char*
1667 get_char(const char* str, size_t i)
1668 {
1669 	static char res[2];
1670 	if(i >= strlen(str))
1671 		return ".";
1672 	res[0] = str[i];
1673 	res[1] = 0;
1674 	return res;
1675 }
1676 /* get end label of the zone name (or .) */
1677 static const char*
1678 get_end_label(zone_options_t* zone, int i)
1679 {
1680 	const dname_type* d = (const dname_type*)zone->node.key;
1681 	if(i >= d->label_count) {
1682 		return ".";
1683 	}
1684 	return wirelabel2str(dname_label(d, i));
1685 }
1686 /* replace occurrences of one with two */
1687 void
1688 replace_str(char* str, size_t len, const char* one, const char* two)
1689 {
1690 	char* pos;
1691 	char* at = str;
1692 	while( (pos=strstr(at, one)) ) {
1693 		if(strlen(str)+strlen(two)-strlen(one) >= len)
1694 			return; /* no more space to replace */
1695 		/* stuff before pos is fine */
1696 		/* move the stuff after pos to make space for two, add
1697 		 * one to length of remainder to also copy the 0 byte end */
1698 		memmove(pos+strlen(two), pos+strlen(one),
1699 			strlen(pos+strlen(one))+1);
1700 		/* copy in two */
1701 		memmove(pos, two, strlen(two));
1702 		/* at is end of the newly inserted two (avoids recursion if
1703 		 * two contains one) */
1704 		at = pos+strlen(two);
1705 	}
1706 }
1707 
1708 const char*
1709 config_cook_string(zone_options_t* zone, const char* input)
1710 {
1711 	static char f[1024];
1712 	/* if not a template, return as-is */
1713 	if(!strchr(input, '%')) {
1714 		return input;
1715 	}
1716 	strlcpy(f, input, sizeof(f));
1717 	if(strstr(f, "%1"))
1718 		replace_str(f, sizeof(f), "%1", get_char(zone->name, 0));
1719 	if(strstr(f, "%2"))
1720 		replace_str(f, sizeof(f), "%2", get_char(zone->name, 1));
1721 	if(strstr(f, "%3"))
1722 		replace_str(f, sizeof(f), "%3", get_char(zone->name, 2));
1723 	if(strstr(f, "%z"))
1724 		replace_str(f, sizeof(f), "%z", get_end_label(zone, 1));
1725 	if(strstr(f, "%y"))
1726 		replace_str(f, sizeof(f), "%y", get_end_label(zone, 2));
1727 	if(strstr(f, "%x"))
1728 		replace_str(f, sizeof(f), "%x", get_end_label(zone, 3));
1729 	if(strstr(f, "%s"))
1730 		replace_str(f, sizeof(f), "%s", zone->name);
1731 	return f;
1732 }
1733 
1734 const char*
1735 config_make_zonefile(zone_options_t* zone, struct nsd* nsd)
1736 {
1737 	static char f[1024];
1738 	/* if not a template, return as-is */
1739 	if(!strchr(zone->pattern->zonefile, '%')) {
1740 		if (nsd->chrootdir && nsd->chrootdir[0] &&
1741 			zone->pattern->zonefile &&
1742 			zone->pattern->zonefile[0] == '/' &&
1743 			strncmp(zone->pattern->zonefile, nsd->chrootdir,
1744 			strlen(nsd->chrootdir)) == 0)
1745 			/* -1 because chrootdir ends in trailing slash */
1746 			return zone->pattern->zonefile + strlen(nsd->chrootdir) - 1;
1747 		return zone->pattern->zonefile;
1748 	}
1749 	strlcpy(f, zone->pattern->zonefile, sizeof(f));
1750 	if(strstr(f, "%1"))
1751 		replace_str(f, sizeof(f), "%1", get_char(zone->name, 0));
1752 	if(strstr(f, "%2"))
1753 		replace_str(f, sizeof(f), "%2", get_char(zone->name, 1));
1754 	if(strstr(f, "%3"))
1755 		replace_str(f, sizeof(f), "%3", get_char(zone->name, 2));
1756 	if(strstr(f, "%z"))
1757 		replace_str(f, sizeof(f), "%z", get_end_label(zone, 1));
1758 	if(strstr(f, "%y"))
1759 		replace_str(f, sizeof(f), "%y", get_end_label(zone, 2));
1760 	if(strstr(f, "%x"))
1761 		replace_str(f, sizeof(f), "%x", get_end_label(zone, 3));
1762 	if(strstr(f, "%s"))
1763 		replace_str(f, sizeof(f), "%s", zone->name);
1764 	if (nsd->chrootdir && nsd->chrootdir[0] && f[0] == '/' &&
1765 		strncmp(f, nsd->chrootdir, strlen(nsd->chrootdir)) == 0)
1766 		/* -1 because chrootdir ends in trailing slash */
1767 		return f + strlen(nsd->chrootdir) - 1;
1768 	return f;
1769 }
1770 
1771 zone_options_t*
1772 zone_options_find(nsd_options_t* opt, const struct dname* apex)
1773 {
1774 	return (zone_options_t*) rbtree_search(opt->zone_options, apex);
1775 }
1776 
1777 acl_options_t*
1778 acl_find_num(acl_options_t* acl, int num)
1779 {
1780 	int count = num;
1781 	if(num < 0)
1782 		return 0;
1783 	while(acl && count > 0) {
1784 		acl = acl->next;
1785 		count--;
1786 	}
1787 	if(count == 0)
1788 		return acl;
1789 	return 0;
1790 }
1791 
1792 /* true if ipv6 address, false if ipv4 */
1793 int
1794 parse_acl_is_ipv6(const char* p)
1795 {
1796 	/* see if addr is ipv6 or ipv4 -- by : and . */
1797 	while(*p) {
1798 		if(*p == '.') return 0;
1799 		if(*p == ':') return 1;
1800 		++p;
1801 	}
1802 	return 0;
1803 }
1804 
1805 /* returns range type. mask is the 2nd part of the range */
1806 int
1807 parse_acl_range_type(char* ip, char** mask)
1808 {
1809 	char *p;
1810 	if((p=strchr(ip, '&'))!=0) {
1811 		*p = 0;
1812 		*mask = p+1;
1813 		return acl_range_mask;
1814 	}
1815 	if((p=strchr(ip, '/'))!=0) {
1816 		*p = 0;
1817 		*mask = p+1;
1818 		return acl_range_subnet;
1819 	}
1820 	if((p=strchr(ip, '-'))!=0) {
1821 		*p = 0;
1822 		*mask = p+1;
1823 		return acl_range_minmax;
1824 	}
1825 	*mask = 0;
1826 	return acl_range_single;
1827 }
1828 
1829 /* parses subnet mask, fills 0 mask as well */
1830 void
1831 parse_acl_range_subnet(char* p, void* addr, int maxbits)
1832 {
1833 	int subnet_bits = atoi(p);
1834 	uint8_t* addr_bytes = (uint8_t*)addr;
1835 	if(subnet_bits == 0 && strcmp(p, "0")!=0) {
1836 		c_error_msg("bad subnet range '%s'", p);
1837 		return;
1838 	}
1839 	if(subnet_bits < 0 || subnet_bits > maxbits) {
1840 		c_error_msg("subnet of %d bits out of range [0..%d]", subnet_bits, maxbits);
1841 		return;
1842 	}
1843 	/* fill addr with n bits of 1s (struct has been zeroed) */
1844 	while(subnet_bits >= 8) {
1845 		*addr_bytes++ = 0xff;
1846 		subnet_bits -= 8;
1847 	}
1848 	if(subnet_bits > 0) {
1849 		uint8_t shifts[] = {0x0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
1850 		*addr_bytes = shifts[subnet_bits];
1851 	}
1852 }
1853 
1854 acl_options_t*
1855 parse_acl_info(region_type* region, char* ip, const char* key)
1856 {
1857 	char* p;
1858 	acl_options_t* acl = (acl_options_t*)region_alloc(region, sizeof(acl_options_t));
1859 	acl->next = 0;
1860 	/* ip */
1861 	acl->ip_address_spec = region_strdup(region, ip);
1862 	acl->use_axfr_only = 0;
1863 	acl->allow_udp = 0;
1864 	acl->ixfr_disabled = 0;
1865 	acl->bad_xfr_count = 0;
1866 	acl->key_options = 0;
1867 	acl->is_ipv6 = 0;
1868 	acl->port = 0;
1869 	memset(&acl->addr, 0, sizeof(union acl_addr_storage));
1870 	memset(&acl->range_mask, 0, sizeof(union acl_addr_storage));
1871 	if((p=strrchr(ip, '@'))!=0) {
1872 		if(atoi(p+1) == 0) c_error("expected port number after '@'");
1873 		else acl->port = atoi(p+1);
1874 		*p=0;
1875 	}
1876 	acl->rangetype = parse_acl_range_type(ip, &p);
1877 	if(parse_acl_is_ipv6(ip)) {
1878 		acl->is_ipv6 = 1;
1879 #ifdef INET6
1880 		if(inet_pton(AF_INET6, ip, &acl->addr.addr6) != 1)
1881 			c_error_msg("Bad ip6 address '%s'", ip);
1882 		if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax)
1883 			if(inet_pton(AF_INET6, p, &acl->range_mask.addr6) != 1)
1884 				c_error_msg("Bad ip6 address mask '%s'", p);
1885 		if(acl->rangetype==acl_range_subnet)
1886 			parse_acl_range_subnet(p, &acl->range_mask.addr6, 128);
1887 #else
1888 		c_error_msg("encountered IPv6 address '%s'.", ip);
1889 #endif /* INET6 */
1890 	} else {
1891 		acl->is_ipv6 = 0;
1892 		if(inet_pton(AF_INET, ip, &acl->addr.addr) != 1)
1893 			c_error_msg("Bad ip4 address '%s'", ip);
1894 		if(acl->rangetype==acl_range_mask || acl->rangetype==acl_range_minmax)
1895 			if(inet_pton(AF_INET, p, &acl->range_mask.addr) != 1)
1896 				c_error_msg("Bad ip4 address mask '%s'", p);
1897 		if(acl->rangetype==acl_range_subnet)
1898 			parse_acl_range_subnet(p, &acl->range_mask.addr, 32);
1899 	}
1900 
1901 	/* key */
1902 	if(strcmp(key, "NOKEY")==0) {
1903 		acl->nokey = 1;
1904 		acl->blocked = 0;
1905 		acl->key_name = 0;
1906 	} else if(strcmp(key, "BLOCKED")==0) {
1907 		acl->nokey = 0;
1908 		acl->blocked = 1;
1909 		acl->key_name = 0;
1910 	} else {
1911 		acl->nokey = 0;
1912 		acl->blocked = 0;
1913 		acl->key_name = region_strdup(region, key);
1914 	}
1915 	return acl;
1916 }
1917 
1918 /* copy acl list at end of parser start, update current */
1919 static
1920 void append_acl(acl_options_t** start, acl_options_t** cur,
1921 	acl_options_t* list)
1922 {
1923 	while(list) {
1924 		acl_options_t* acl = copy_acl(cfg_parser->opt->region, list);
1925 		acl->next = NULL;
1926 		if(*cur)
1927 			(*cur)->next = acl;
1928 		else	*start = acl;
1929 		*cur = acl;
1930 		list = list->next;
1931 	}
1932 }
1933 
1934 void
1935 config_apply_pattern(const char* name)
1936 {
1937 	/* find the pattern */
1938 	pattern_options_t* pat = pattern_options_find(cfg_parser->opt, name);
1939 	pattern_options_t* a = cfg_parser->current_pattern;
1940 	if(!pat) {
1941 		c_error_msg("could not find pattern %s", name);
1942 		return;
1943 	}
1944 
1945 	/* apply settings */
1946 	if(pat->zonefile)
1947 		a->zonefile = region_strdup(cfg_parser->opt->region,
1948 			pat->zonefile);
1949 	if(pat->zonestats)
1950 		a->zonestats = region_strdup(cfg_parser->opt->region,
1951 			pat->zonestats);
1952 	if(!pat->allow_axfr_fallback_is_default) {
1953 		a->allow_axfr_fallback = pat->allow_axfr_fallback;
1954 		a->allow_axfr_fallback_is_default = 0;
1955 	}
1956 	if(!pat->notify_retry_is_default) {
1957 		a->notify_retry = pat->notify_retry;
1958 		a->notify_retry_is_default = 0;
1959 	}
1960 	if(!pat->max_refresh_time_is_default) {
1961 		a->max_refresh_time = pat->max_refresh_time;
1962 		a->max_refresh_time_is_default = 0;
1963 	}
1964 	if(!pat->min_refresh_time_is_default) {
1965 		a->min_refresh_time = pat->min_refresh_time;
1966 		a->min_refresh_time_is_default = 0;
1967 	}
1968 	if(!pat->max_retry_time_is_default) {
1969 		a->max_retry_time = pat->max_retry_time;
1970 		a->max_retry_time_is_default = 0;
1971 	}
1972 	if(!pat->min_retry_time_is_default) {
1973 		a->min_retry_time = pat->min_retry_time;
1974 		a->min_retry_time_is_default = 0;
1975 	}
1976 	a->size_limit_xfr = pat->size_limit_xfr;
1977 #ifdef RATELIMIT
1978 	a->rrl_whitelist |= pat->rrl_whitelist;
1979 #endif
1980 	/* append acl items */
1981 	append_acl(&a->allow_notify, &cfg_parser->current_allow_notify,
1982 		pat->allow_notify);
1983 	append_acl(&a->request_xfr, &cfg_parser->current_request_xfr,
1984 		pat->request_xfr);
1985 	append_acl(&a->notify, &cfg_parser->current_notify, pat->notify);
1986 	append_acl(&a->provide_xfr, &cfg_parser->current_provide_xfr,
1987 		pat->provide_xfr);
1988 	append_acl(&a->outgoing_interface, &cfg_parser->
1989 		current_outgoing_interface, pat->outgoing_interface);
1990 	if(pat->multi_master_check)
1991 		a->multi_master_check = pat->multi_master_check;
1992 }
1993 
1994 void
1995 nsd_options_destroy(nsd_options_t* opt)
1996 {
1997 	region_destroy(opt->region);
1998 }
1999 
2000 unsigned getzonestatid(nsd_options_t* opt, zone_options_t* zopt)
2001 {
2002 #ifdef USE_ZONE_STATS
2003 	const char* statname;
2004 	struct zonestatname* n;
2005 	rbnode_t* res;
2006 	/* try to find the instantiated zonestat name */
2007 	if(!zopt->pattern->zonestats || zopt->pattern->zonestats[0]==0)
2008 		return 0; /* no zone stats */
2009 	statname = config_cook_string(zopt, zopt->pattern->zonestats);
2010 	res = rbtree_search(opt->zonestatnames, statname);
2011 	if(res)
2012 		return ((struct zonestatname*)res)->id;
2013 	/* create it */
2014 	n = (struct zonestatname*)xalloc(sizeof(*n));
2015 	memset(n, 0, sizeof(*n));
2016 	n->node.key = strdup(statname);
2017 	if(!n->node.key) {
2018 		log_msg(LOG_ERR, "malloc failed: %s", strerror(errno));
2019 		exit(1);
2020 	}
2021 	n->id = (unsigned)(opt->zonestatnames->count);
2022 	rbtree_insert(opt->zonestatnames, (rbnode_t*)n);
2023 	return n->id;
2024 #else /* USE_ZONE_STATS */
2025 	(void)opt; (void)zopt;
2026 	return 0;
2027 #endif /* USE_ZONE_STATS */
2028 }
2029