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