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