xref: /openbsd/usr.sbin/nsd/zonec.c (revision cca36db2)
1 /*
2  * zonec.c -- zone compiler.
3  *
4  * Copyright (c) 2001-2011, NLnet Labs. All rights reserved.
5  *
6  * See LICENSE for the license.
7  *
8  */
9 
10 #include <config.h>
11 
12 #include <assert.h>
13 #include <fcntl.h>
14 #include <ctype.h>
15 #include <errno.h>
16 #include <limits.h>
17 #include <stdio.h>
18 #include <string.h>
19 #ifdef HAVE_STRINGS_H
20 #include <strings.h>
21 #endif
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <time.h>
25 
26 #include <netinet/in.h>
27 
28 #ifdef HAVE_NETDB_H
29 #include <netdb.h>
30 #endif
31 
32 #include "zonec.h"
33 
34 #include "dname.h"
35 #include "dns.h"
36 #include "namedb.h"
37 #include "rdata.h"
38 #include "region-allocator.h"
39 #include "util.h"
40 #include "zparser.h"
41 #include "options.h"
42 #include "nsec3.h"
43 
44 const dname_type *error_dname;
45 domain_type *error_domain;
46 
47 /* The database file... */
48 static const char *dbfile = 0;
49 
50 /* Some global flags... */
51 static int vflag = 0;
52 /* if -v then print progress each 'progress' RRs */
53 static int progress = 10000;
54 
55 /* Total errors counter */
56 static long int totalerrors = 0;
57 static long int totalrrs = 0;
58 
59 extern uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE];
60 extern uint16_t nsec_highest_rcode;
61 
62 
63 /*
64  * Allocate SIZE+sizeof(uint16_t) bytes and store SIZE in the first
65  * element.  Return a pointer to the allocation.
66  */
67 static uint16_t *
68 alloc_rdata(region_type *region, size_t size)
69 {
70 	uint16_t *result = region_alloc(region, sizeof(uint16_t) + size);
71 	*result = size;
72 	return result;
73 }
74 
75 uint16_t *
76 alloc_rdata_init(region_type *region, const void *data, size_t size)
77 {
78 	uint16_t *result = region_alloc(region, sizeof(uint16_t) + size);
79 	*result = size;
80 	memcpy(result + 1, data, size);
81 	return result;
82 }
83 
84 /*
85  * These are parser function for generic zone file stuff.
86  */
87 uint16_t *
88 zparser_conv_hex(region_type *region, const char *hex, size_t len)
89 {
90 	/* convert a hex value to wireformat */
91 	uint16_t *r = NULL;
92 	uint8_t *t;
93 	int i;
94 
95 	if (len % 2 != 0) {
96 		zc_error_prev_line("number of hex digits must be a multiple of 2");
97 	} else if (len > MAX_RDLENGTH * 2) {
98 		zc_error_prev_line("hex data exceeds maximum rdata length (%d)",
99 				   MAX_RDLENGTH);
100 	} else {
101 		/* the length part */
102 		r = alloc_rdata(region, len/2);
103 		t = (uint8_t *)(r + 1);
104 
105 		/* Now process octet by octet... */
106 		while (*hex) {
107 			*t = 0;
108 			for (i = 16; i >= 1; i -= 15) {
109 				if (isxdigit((int)*hex)) {
110 					*t += hexdigit_to_int(*hex) * i;
111 				} else {
112 					zc_error_prev_line(
113 						"illegal hex character '%c'",
114 						(int) *hex);
115 					return NULL;
116 				}
117 				++hex;
118 			}
119 			++t;
120 		}
121 	}
122 	return r;
123 }
124 
125 /* convert hex, precede by a 1-byte length */
126 uint16_t *
127 zparser_conv_hex_length(region_type *region, const char *hex, size_t len)
128 {
129 	uint16_t *r = NULL;
130 	uint8_t *t;
131 	int i;
132 	if (len % 2 != 0) {
133 		zc_error_prev_line("number of hex digits must be a multiple of 2");
134 	} else if (len > 255 * 2) {
135 		zc_error_prev_line("hex data exceeds 255 bytes");
136 	} else {
137 		uint8_t *l;
138 
139 		/* the length part */
140 		r = alloc_rdata(region, len/2+1);
141 		t = (uint8_t *)(r + 1);
142 
143 		l = t++;
144 		*l = '\0';
145 
146 		/* Now process octet by octet... */
147 		while (*hex) {
148 			*t = 0;
149 			for (i = 16; i >= 1; i -= 15) {
150 				if (isxdigit((int)*hex)) {
151 					*t += hexdigit_to_int(*hex) * i;
152 				} else {
153 					zc_error_prev_line(
154 						"illegal hex character '%c'",
155 						(int) *hex);
156 					return NULL;
157 				}
158 				++hex;
159 			}
160 			++t;
161 			++*l;
162 		}
163 	}
164 	return r;
165 }
166 
167 uint16_t *
168 zparser_conv_time(region_type *region, const char *time)
169 {
170 	/* convert a time YYHM to wireformat */
171 	uint16_t *r = NULL;
172 	struct tm tm;
173 
174 	/* Try to scan the time... */
175 	if (!strptime(time, "%Y%m%d%H%M%S", &tm)) {
176 		zc_error_prev_line("date and time is expected");
177 	} else {
178 		uint32_t l = htonl(mktime_from_utc(&tm));
179 		r = alloc_rdata_init(region, &l, sizeof(l));
180 	}
181 	return r;
182 }
183 
184 uint16_t *
185 zparser_conv_services(region_type *region, const char *protostr,
186 		      char *servicestr)
187 {
188 	/*
189 	 * Convert a protocol and a list of service port numbers
190 	 * (separated by spaces) in the rdata to wireformat
191 	 */
192 	uint16_t *r = NULL;
193 	uint8_t *p;
194 	uint8_t bitmap[65536/8];
195 	char sep[] = " ";
196 	char *word;
197 	int max_port = -8;
198 	/* convert a protocol in the rdata to wireformat */
199 	struct protoent *proto;
200 
201 	memset(bitmap, 0, sizeof(bitmap));
202 
203 	proto = getprotobyname(protostr);
204 	if (!proto) {
205 		proto = getprotobynumber(atoi(protostr));
206 	}
207 	if (!proto) {
208 		zc_error_prev_line("unknown protocol '%s'", protostr);
209 		return NULL;
210 	}
211 
212 	for (word = strtok(servicestr, sep); word; word = strtok(NULL, sep)) {
213 		struct servent *service;
214 		int port;
215 
216 		service = getservbyname(word, proto->p_name);
217 		if (service) {
218 			/* Note: ntohs not ntohl!  Strange but true.  */
219 			port = ntohs((uint16_t) service->s_port);
220 		} else {
221 			char *end;
222 			port = strtol(word, &end, 10);
223 			if (*end != '\0') {
224 				zc_error_prev_line("unknown service '%s' for protocol '%s'",
225 						   word, protostr);
226 				continue;
227 			}
228 		}
229 
230 		if (port < 0 || port > 65535) {
231 			zc_error_prev_line("bad port number %d", port);
232 		} else {
233 			set_bit(bitmap, port);
234 			if (port > max_port)
235 				max_port = port;
236 		}
237 	}
238 
239 	r = alloc_rdata(region, sizeof(uint8_t) + max_port / 8 + 1);
240 	p = (uint8_t *) (r + 1);
241 	*p = proto->p_proto;
242 	memcpy(p + 1, bitmap, *r);
243 
244 	return r;
245 }
246 
247 uint16_t *
248 zparser_conv_serial(region_type *region, const char *serialstr)
249 {
250 	uint16_t *r = NULL;
251 	uint32_t serial;
252 	const char *t;
253 
254 	serial = strtoserial(serialstr, &t);
255 	if (*t != '\0') {
256 		zc_error_prev_line("serial is expected");
257 	} else {
258 		serial = htonl(serial);
259 		r = alloc_rdata_init(region, &serial, sizeof(serial));
260 	}
261 	return r;
262 }
263 
264 uint16_t *
265 zparser_conv_period(region_type *region, const char *periodstr)
266 {
267 	/* convert a time period (think TTL's) to wireformat) */
268 	uint16_t *r = NULL;
269 	uint32_t period;
270 	const char *end;
271 
272 	/* Allocate required space... */
273 	period = strtottl(periodstr, &end);
274 	if (*end != '\0') {
275 		zc_error_prev_line("time period is expected");
276 	} else {
277 		period = htonl(period);
278 		r = alloc_rdata_init(region, &period, sizeof(period));
279 	}
280 	return r;
281 }
282 
283 uint16_t *
284 zparser_conv_short(region_type *region, const char *text)
285 {
286 	uint16_t *r = NULL;
287 	uint16_t value;
288 	char *end;
289 
290 	value = htons((uint16_t) strtol(text, &end, 10));
291 	if (*end != '\0') {
292 		zc_error_prev_line("integer value is expected");
293 	} else {
294 		r = alloc_rdata_init(region, &value, sizeof(value));
295 	}
296 	return r;
297 }
298 
299 uint16_t *
300 zparser_conv_byte(region_type *region, const char *text)
301 {
302 	uint16_t *r = NULL;
303 	uint8_t value;
304 	char *end;
305 
306 	value = (uint8_t) strtol(text, &end, 10);
307 	if (*end != '\0') {
308 		zc_error_prev_line("integer value is expected");
309 	} else {
310 		r = alloc_rdata_init(region, &value, sizeof(value));
311 	}
312 	return r;
313 }
314 
315 uint16_t *
316 zparser_conv_algorithm(region_type *region, const char *text)
317 {
318 	const lookup_table_type *alg;
319 	uint8_t id;
320 
321 	alg = lookup_by_name(dns_algorithms, text);
322 	if (alg) {
323 		id = (uint8_t) alg->id;
324 	} else {
325 		char *end;
326 		id = (uint8_t) strtol(text, &end, 10);
327 		if (*end != '\0') {
328 			zc_error_prev_line("algorithm is expected");
329 			return NULL;
330 		}
331 	}
332 
333 	return alloc_rdata_init(region, &id, sizeof(id));
334 }
335 
336 uint16_t *
337 zparser_conv_certificate_type(region_type *region, const char *text)
338 {
339 	/* convert a algoritm string to integer */
340 	const lookup_table_type *type;
341 	uint16_t id;
342 
343 	type = lookup_by_name(dns_certificate_types, text);
344 	if (type) {
345 		id = htons((uint16_t) type->id);
346 	} else {
347 		char *end;
348 		id = htons((uint16_t) strtol(text, &end, 10));
349 		if (*end != '\0') {
350 			zc_error_prev_line("certificate type is expected");
351 			return NULL;
352 		}
353 	}
354 
355 	return alloc_rdata_init(region, &id, sizeof(id));
356 }
357 
358 uint16_t *
359 zparser_conv_a(region_type *region, const char *text)
360 {
361 	in_addr_t address;
362 	uint16_t *r = NULL;
363 
364 	if (inet_pton(AF_INET, text, &address) != 1) {
365 		zc_error_prev_line("invalid IPv4 address '%s'", text);
366 	} else {
367 		r = alloc_rdata_init(region, &address, sizeof(address));
368 	}
369 	return r;
370 }
371 
372 uint16_t *
373 zparser_conv_aaaa(region_type *region, const char *text)
374 {
375 	uint8_t address[IP6ADDRLEN];
376 	uint16_t *r = NULL;
377 
378 	if (inet_pton(AF_INET6, text, address) != 1) {
379 		zc_error_prev_line("invalid IPv6 address '%s'", text);
380 	} else {
381 		r = alloc_rdata_init(region, address, sizeof(address));
382 	}
383 	return r;
384 }
385 
386 uint16_t *
387 zparser_conv_text(region_type *region, const char *text, size_t len)
388 {
389 	uint16_t *r = NULL;
390 
391 	if (len > 255) {
392 		zc_error_prev_line("text string is longer than 255 characters,"
393 				   " try splitting it into multiple parts");
394 	} else {
395 		uint8_t *p;
396 		r = alloc_rdata(region, len + 1);
397 		p = (uint8_t *) (r + 1);
398 		*p = len;
399 		memcpy(p + 1, text, len);
400 	}
401 	return r;
402 }
403 
404 uint16_t *
405 zparser_conv_dns_name(region_type *region, const uint8_t* name, size_t len)
406 {
407 	uint16_t* r = NULL;
408 	uint8_t* p = NULL;
409 	r = alloc_rdata(region, len);
410 	p = (uint8_t *) (r + 1);
411 	memcpy(p, name, len);
412 
413 	return r;
414 }
415 
416 uint16_t *
417 zparser_conv_b32(region_type *region, const char *b32)
418 {
419 	uint8_t buffer[B64BUFSIZE];
420 	uint16_t *r = NULL;
421 	int i;
422 
423 	if(strcmp(b32, "-") == 0) {
424 		return alloc_rdata_init(region, "", 1);
425 	}
426 	i = b32_pton(b32, buffer+1, B64BUFSIZE-1);
427 	if (i == -1 || i > 255) {
428 		zc_error_prev_line("invalid base32 data");
429 	} else {
430 		buffer[0] = i; /* store length byte */
431 		r = alloc_rdata_init(region, buffer, i+1);
432 	}
433 	return r;
434 }
435 
436 uint16_t *
437 zparser_conv_b64(region_type *region, const char *b64)
438 {
439 	uint8_t buffer[B64BUFSIZE];
440 	uint16_t *r = NULL;
441 	int i;
442 
443 	i = b64_pton(b64, buffer, B64BUFSIZE);
444 	if (i == -1) {
445 		zc_error_prev_line("invalid base64 data");
446 	} else {
447 		r = alloc_rdata_init(region, buffer, i);
448 	}
449 	return r;
450 }
451 
452 uint16_t *
453 zparser_conv_rrtype(region_type *region, const char *text)
454 {
455 	uint16_t *r = NULL;
456 	uint16_t type = rrtype_from_string(text);
457 
458 	if (type == 0) {
459 		zc_error_prev_line("unrecognized RR type '%s'", text);
460 	} else {
461 		type = htons(type);
462 		r = alloc_rdata_init(region, &type, sizeof(type));
463 	}
464 	return r;
465 }
466 
467 uint16_t *
468 zparser_conv_nxt(region_type *region, uint8_t nxtbits[])
469 {
470 	/* nxtbits[] consists of 16 bytes with some zero's in it
471 	 * copy every byte with zero to r and write the length in
472 	 * the first byte
473 	 */
474 	uint16_t i;
475 	uint16_t last = 0;
476 
477 	for (i = 0; i < 16; i++) {
478 		if (nxtbits[i] != 0)
479 			last = i + 1;
480 	}
481 
482 	return alloc_rdata_init(region, nxtbits, last);
483 }
484 
485 
486 /* we potentially have 256 windows, each one is numbered. empty ones
487  * should be discarded
488  */
489 uint16_t *
490 zparser_conv_nsec(region_type *region,
491 		  uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE])
492 {
493 	/* nsecbits contains up to 64K of bits which represent the
494 	 * types available for a name. Walk the bits according to
495 	 * nsec++ draft from jakob
496 	 */
497 	uint16_t *r;
498 	uint8_t *ptr;
499 	size_t i,j;
500 	uint16_t window_count = 0;
501 	uint16_t total_size = 0;
502 	uint16_t window_max = 0;
503 
504 	/* The used windows.  */
505 	int used[NSEC_WINDOW_COUNT];
506 	/* The last byte used in each the window.  */
507 	int size[NSEC_WINDOW_COUNT];
508 
509 	window_max = 1 + (nsec_highest_rcode / 256);
510 
511 	/* used[i] is the i-th window included in the nsec
512 	 * size[used[0]] is the size of window 0
513 	 */
514 
515 	/* walk through the 256 windows */
516 	for (i = 0; i < window_max; ++i) {
517 		int empty_window = 1;
518 		/* check each of the 32 bytes */
519 		for (j = 0; j < NSEC_WINDOW_BITS_SIZE; ++j) {
520 			if (nsecbits[i][j] != 0) {
521 				size[i] = j + 1;
522 				empty_window = 0;
523 			}
524 		}
525 		if (!empty_window) {
526 			used[window_count] = i;
527 			window_count++;
528 		}
529 	}
530 
531 	for (i = 0; i < window_count; ++i) {
532 		total_size += sizeof(uint16_t) + size[used[i]];
533 	}
534 
535 	r = alloc_rdata(region, total_size);
536 	ptr = (uint8_t *) (r + 1);
537 
538 	/* now walk used and copy it */
539 	for (i = 0; i < window_count; ++i) {
540 		ptr[0] = used[i];
541 		ptr[1] = size[used[i]];
542 		memcpy(ptr + 2, &nsecbits[used[i]], size[used[i]]);
543 		ptr += size[used[i]] + 2;
544 	}
545 
546 	return r;
547 }
548 
549 /* Parse an int terminated in the specified range. */
550 static int
551 parse_int(const char *str,
552 	  char **end,
553 	  int *result,
554 	  const char *name,
555 	  int min,
556 	  int max)
557 {
558 	*result = (int) strtol(str, end, 10);
559 	if (*result < min || *result > max) {
560 		zc_error_prev_line("%s must be within the range [%d .. %d]",
561 				   name,
562 				   min,
563 				   max);
564 		return 0;
565 	} else {
566 		return 1;
567 	}
568 }
569 
570 /* RFC1876 conversion routines */
571 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
572 				1000000,10000000,100000000,1000000000};
573 
574 /*
575  * Converts ascii size/precision X * 10**Y(cm) to 0xXY.
576  * Sets the given pointer to the last used character.
577  *
578  */
579 static uint8_t
580 precsize_aton (char *cp, char **endptr)
581 {
582 	unsigned int mval = 0, cmval = 0;
583 	uint8_t retval = 0;
584 	int exponent;
585 	int mantissa;
586 
587 	while (isdigit((int)*cp))
588 		mval = mval * 10 + hexdigit_to_int(*cp++);
589 
590 	if (*cp == '.') {	/* centimeters */
591 		cp++;
592 		if (isdigit((int)*cp)) {
593 			cmval = hexdigit_to_int(*cp++) * 10;
594 			if (isdigit((int)*cp)) {
595 				cmval += hexdigit_to_int(*cp++);
596 			}
597 		}
598 	}
599 
600 	if(mval >= poweroften[7]) {
601 		/* integer overflow possible for *100 */
602 		mantissa = mval / poweroften[7];
603 		exponent = 9; /* max */
604 	}
605 	else {
606 		cmval = (mval * 100) + cmval;
607 
608 		for (exponent = 0; exponent < 9; exponent++)
609 			if (cmval < poweroften[exponent+1])
610 				break;
611 
612 		mantissa = cmval / poweroften[exponent];
613 	}
614 	if (mantissa > 9)
615 		mantissa = 9;
616 
617 	retval = (mantissa << 4) | exponent;
618 
619 	if (*cp == 'm') cp++;
620 
621 	*endptr = cp;
622 
623 	return (retval);
624 }
625 
626 /*
627  * Parses a specific part of rdata.
628  *
629  * Returns:
630  *
631  *	number of elements parsed
632  *	zero on error
633  *
634  */
635 uint16_t *
636 zparser_conv_loc(region_type *region, char *str)
637 {
638 	uint16_t *r;
639 	uint32_t *p;
640 	int i;
641 	int deg, min, secs;	/* Secs is stored times 1000.  */
642 	uint32_t lat = 0, lon = 0, alt = 0;
643 	/* encoded defaults: version=0 sz=1m hp=10000m vp=10m */
644 	uint8_t vszhpvp[4] = {0, 0x12, 0x16, 0x13};
645 	char *start;
646 	double d;
647 
648 	for(;;) {
649 		deg = min = secs = 0;
650 
651 		/* Degrees */
652 		if (*str == '\0') {
653 			zc_error_prev_line("unexpected end of LOC data");
654 			return NULL;
655 		}
656 
657 		if (!parse_int(str, &str, &deg, "degrees", 0, 180))
658 			return NULL;
659 		if (!isspace((int)*str)) {
660 			zc_error_prev_line("space expected after degrees");
661 			return NULL;
662 		}
663 		++str;
664 
665 		/* Minutes? */
666 		if (isdigit((int)*str)) {
667 			if (!parse_int(str, &str, &min, "minutes", 0, 60))
668 				return NULL;
669 			if (!isspace((int)*str)) {
670 				zc_error_prev_line("space expected after minutes");
671 				return NULL;
672 			}
673 			++str;
674 		}
675 
676 		/* Seconds? */
677 		if (isdigit((int)*str)) {
678 			start = str;
679 			if (!parse_int(str, &str, &i, "seconds", 0, 60)) {
680 				return NULL;
681 			}
682 
683 			if (*str == '.' && !parse_int(str + 1, &str, &i, "seconds fraction", 0, 999)) {
684 				return NULL;
685 			}
686 
687 			if (!isspace((int)*str)) {
688 				zc_error_prev_line("space expected after seconds");
689 				return NULL;
690 			}
691 
692 			if (sscanf(start, "%lf", &d) != 1) {
693 				zc_error_prev_line("error parsing seconds");
694 			}
695 
696 			if (d < 0.0 || d > 60.0) {
697 				zc_error_prev_line("seconds not in range 0.0 .. 60.0");
698 			}
699 
700 			secs = (int) (d * 1000.0 + 0.5);
701 			++str;
702 		}
703 
704 		switch(*str) {
705 		case 'N':
706 		case 'n':
707 			lat = ((uint32_t)1<<31) + (deg * 3600000 + min * 60000 + secs);
708 			break;
709 		case 'E':
710 		case 'e':
711 			lon = ((uint32_t)1<<31) + (deg * 3600000 + min * 60000 + secs);
712 			break;
713 		case 'S':
714 		case 's':
715 			lat = ((uint32_t)1<<31) - (deg * 3600000 + min * 60000 + secs);
716 			break;
717 		case 'W':
718 		case 'w':
719 			lon = ((uint32_t)1<<31) - (deg * 3600000 + min * 60000 + secs);
720 			break;
721 		default:
722 			zc_error_prev_line("invalid latitude/longtitude: '%c'", *str);
723 			return NULL;
724 		}
725 		++str;
726 
727 		if (lat != 0 && lon != 0)
728 			break;
729 
730 		if (!isspace((int)*str)) {
731 			zc_error_prev_line("space expected after latitude/longitude");
732 			return NULL;
733 		}
734 		++str;
735 	}
736 
737 	/* Altitude */
738 	if (*str == '\0') {
739 		zc_error_prev_line("unexpected end of LOC data");
740 		return NULL;
741 	}
742 
743 	if (!isspace((int)*str)) {
744 		zc_error_prev_line("space expected before altitude");
745 		return NULL;
746 	}
747 	++str;
748 
749 	start = str;
750 
751 	/* Sign */
752 	if (*str == '+' || *str == '-') {
753 		++str;
754 	}
755 
756 	/* Meters of altitude... */
757 	(void) strtol(str, &str, 10);
758 	switch(*str) {
759 	case ' ':
760 	case '\0':
761 	case 'm':
762 		break;
763 	case '.':
764 		if (!parse_int(str + 1, &str, &i, "altitude fraction", 0, 99)) {
765 			return NULL;
766 		}
767 		if (!isspace((int)*str) && *str != '\0' && *str != 'm') {
768 			zc_error_prev_line("altitude fraction must be a number");
769 			return NULL;
770 		}
771 		break;
772 	default:
773 		zc_error_prev_line("altitude must be expressed in meters");
774 		return NULL;
775 	}
776 	if (!isspace((int)*str) && *str != '\0')
777 		++str;
778 
779 	if (sscanf(start, "%lf", &d) != 1) {
780 		zc_error_prev_line("error parsing altitude");
781 	}
782 
783 	alt = (uint32_t) (10000000.0 + d * 100 + 0.5);
784 
785 	if (!isspace((int)*str) && *str != '\0') {
786 		zc_error_prev_line("unexpected character after altitude");
787 		return NULL;
788 	}
789 
790 	/* Now parse size, horizontal precision and vertical precision if any */
791 	for(i = 1; isspace((int)*str) && i <= 3; i++) {
792 		vszhpvp[i] = precsize_aton(str + 1, &str);
793 
794 		if (!isspace((int)*str) && *str != '\0') {
795 			zc_error_prev_line("invalid size or precision");
796 			return NULL;
797 		}
798 	}
799 
800 	/* Allocate required space... */
801 	r = alloc_rdata(region, 16);
802 	p = (uint32_t *) (r + 1);
803 
804 	memmove(p, vszhpvp, 4);
805 	write_uint32(p + 1, lat);
806 	write_uint32(p + 2, lon);
807 	write_uint32(p + 3, alt);
808 
809 	return r;
810 }
811 
812 /*
813  * Convert an APL RR RDATA element.
814  */
815 uint16_t *
816 zparser_conv_apl_rdata(region_type *region, char *str)
817 {
818 	int negated = 0;
819 	uint16_t address_family;
820 	uint8_t prefix;
821 	uint8_t maximum_prefix;
822 	uint8_t length;
823 	uint8_t address[IP6ADDRLEN];
824 	char *colon = strchr(str, ':');
825 	char *slash = strchr(str, '/');
826 	int af;
827 	int rc;
828 	uint16_t rdlength;
829 	uint16_t *r;
830 	uint8_t *t;
831 	char *end;
832 	long p;
833 
834 	if (!colon) {
835 		zc_error("address family separator is missing");
836 		return NULL;
837 	}
838 	if (!slash) {
839 		zc_error("prefix separator is missing");
840 		return NULL;
841 	}
842 
843 	*colon = '\0';
844 	*slash = '\0';
845 
846 	if (*str == '!') {
847 		negated = 1;
848 		++str;
849 	}
850 
851 	if (strcmp(str, "1") == 0) {
852 		address_family = htons(1);
853 		af = AF_INET;
854 		length = sizeof(in_addr_t);
855 		maximum_prefix = length * 8;
856 	} else if (strcmp(str, "2") == 0) {
857 		address_family = htons(2);
858 		af = AF_INET6;
859 		length = IP6ADDRLEN;
860 		maximum_prefix = length * 8;
861 	} else {
862 		zc_error("invalid address family '%s'", str);
863 		return NULL;
864 	}
865 
866 	rc = inet_pton(af, colon + 1, address);
867 	if (rc == 0) {
868 		zc_error("invalid address '%s'", colon + 1);
869 		return NULL;
870 	} else if (rc == -1) {
871 		zc_error("inet_pton failed: %s", strerror(errno));
872 		return NULL;
873 	}
874 
875 	/* Strip trailing zero octets.	*/
876 	while (length > 0 && address[length - 1] == 0)
877 		--length;
878 
879 
880 	p = strtol(slash + 1, &end, 10);
881 	if (p < 0 || p > maximum_prefix) {
882 		zc_error("prefix not in the range 0 .. %d", maximum_prefix);
883 		return NULL;
884 	} else if (*end != '\0') {
885 		zc_error("invalid prefix '%s'", slash + 1);
886 		return NULL;
887 	}
888 	prefix = (uint8_t) p;
889 
890 	rdlength = (sizeof(address_family) + sizeof(prefix) + sizeof(length)
891 		    + length);
892 	r = alloc_rdata(region, rdlength);
893 	t = (uint8_t *) (r + 1);
894 
895 	memcpy(t, &address_family, sizeof(address_family));
896 	t += sizeof(address_family);
897 	memcpy(t, &prefix, sizeof(prefix));
898 	t += sizeof(prefix);
899 	memcpy(t, &length, sizeof(length));
900 	if (negated) {
901 		*t |= APL_NEGATION_MASK;
902 	}
903 	t += sizeof(length);
904 	memcpy(t, address, length);
905 
906 	return r;
907 }
908 
909 /*
910  * Below some function that also convert but not to wireformat
911  * but to "normal" (int,long,char) types
912  */
913 
914 uint32_t
915 zparser_ttl2int(const char *ttlstr, int* error)
916 {
917 	/* convert a ttl value to a integer
918 	 * return the ttl in a int
919 	 * -1 on error
920 	 */
921 
922 	uint32_t ttl;
923 	const char *t;
924 
925 	ttl = strtottl(ttlstr, &t);
926 	if (*t != 0) {
927 		zc_error_prev_line("invalid TTL value: %s",ttlstr);
928 		*error = 1;
929 	}
930 
931 	return ttl;
932 }
933 
934 
935 void
936 zadd_rdata_wireformat(uint16_t *data)
937 {
938 	if (parser->current_rr.rdata_count >= MAXRDATALEN) {
939 		zc_error_prev_line("too many rdata elements");
940 	} else {
941 		parser->current_rr.rdatas[parser->current_rr.rdata_count].data
942 			= data;
943 		++parser->current_rr.rdata_count;
944 	}
945 }
946 
947 /**
948  * Used for TXT RR's to grow with undefined number of strings.
949  */
950 void
951 zadd_rdata_txt_wireformat(uint16_t *data, int first)
952 {
953 	rdata_atom_type *rd;
954 
955 	/* First STR in str_seq, allocate 65K in first unused rdata
956 	 * else find last used rdata */
957 	if (first) {
958 		rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count];
959 		if ((rd->data = (uint16_t *) region_alloc(parser->rr_region,
960 			sizeof(uint16_t) + 65535 * sizeof(uint8_t))) == NULL) {
961 			zc_error_prev_line("Could not allocate memory for TXT RR");
962 			return;
963 		}
964 		parser->current_rr.rdata_count++;
965 		rd->data[0] = 0;
966 	}
967 	else
968 		rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1];
969 
970 	if ((size_t)rd->data[0] + (size_t)data[0] > 65535) {
971 		zc_error_prev_line("too large rdata element");
972 		return;
973 	}
974 
975 	memcpy((uint8_t *)rd->data + 2 + rd->data[0], data + 1, data[0]);
976 	rd->data[0] += data[0];
977 }
978 
979 /**
980  * Clean up after last call of zadd_rdata_txt_wireformat
981  */
982 void
983 zadd_rdata_txt_clean_wireformat()
984 {
985 	uint16_t *tmp_data;
986 	rdata_atom_type *rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1];
987 	if ((tmp_data = (uint16_t *) region_alloc(parser->region,
988 		rd->data[0] + 2)) != NULL) {
989 		memcpy(tmp_data, rd->data, rd->data[0] + 2);
990 		rd->data = tmp_data;
991 	}
992 	else {
993 		/* We could not get memory in non-volatile region */
994 		zc_error_prev_line("could not allocate memory for rdata");
995 		return;
996 	}
997 }
998 
999 void
1000 zadd_rdata_domain(domain_type *domain)
1001 {
1002 	if (parser->current_rr.rdata_count >= MAXRDATALEN) {
1003 		zc_error_prev_line("too many rdata elements");
1004 	} else {
1005 		parser->current_rr.rdatas[parser->current_rr.rdata_count].domain
1006 			= domain;
1007 		++parser->current_rr.rdata_count;
1008 	}
1009 }
1010 
1011 void
1012 parse_unknown_rdata(uint16_t type, uint16_t *wireformat)
1013 {
1014 	buffer_type packet;
1015 	uint16_t size;
1016 	ssize_t rdata_count;
1017 	ssize_t i;
1018 	rdata_atom_type *rdatas;
1019 
1020 	if (wireformat) {
1021 		size = *wireformat;
1022 	} else {
1023 		return;
1024 	}
1025 
1026 	buffer_create_from(&packet, wireformat + 1, *wireformat);
1027 	rdata_count = rdata_wireformat_to_rdata_atoms(parser->region,
1028 						      parser->db->domains,
1029 						      type,
1030 						      size,
1031 						      &packet,
1032 						      &rdatas);
1033 	if (rdata_count == -1) {
1034 		zc_error_prev_line("bad unknown RDATA");
1035 		return;
1036 	}
1037 
1038 	for (i = 0; i < rdata_count; ++i) {
1039 		if (rdata_atom_is_domain(type, i)) {
1040 			zadd_rdata_domain(rdatas[i].domain);
1041 		} else {
1042 			zadd_rdata_wireformat(rdatas[i].data);
1043 		}
1044 	}
1045 }
1046 
1047 
1048 /*
1049  * Compares two rdata arrays.
1050  *
1051  * Returns:
1052  *
1053  *	zero if they are equal
1054  *	non-zero if not
1055  *
1056  */
1057 static int
1058 zrdatacmp(uint16_t type, rr_type *a, rr_type *b)
1059 {
1060 	int i = 0;
1061 
1062 	assert(a);
1063 	assert(b);
1064 
1065 	/* One is shorter than another */
1066 	if (a->rdata_count != b->rdata_count)
1067 		return 1;
1068 
1069 	/* Compare element by element */
1070 	for (i = 0; i < a->rdata_count; ++i) {
1071 		if (rdata_atom_is_domain(type, i)) {
1072 			if (rdata_atom_domain(a->rdatas[i])
1073 			    != rdata_atom_domain(b->rdatas[i]))
1074 			{
1075 				return 1;
1076 			}
1077 		} else {
1078 			if (rdata_atom_size(a->rdatas[i])
1079 			    != rdata_atom_size(b->rdatas[i]))
1080 			{
1081 				return 1;
1082 			}
1083 			if (memcmp(rdata_atom_data(a->rdatas[i]),
1084 				   rdata_atom_data(b->rdatas[i]),
1085 				   rdata_atom_size(a->rdatas[i])) != 0)
1086 			{
1087 				return 1;
1088 			}
1089 		}
1090 	}
1091 
1092 	/* Otherwise they are equal */
1093 	return 0;
1094 }
1095 
1096 /*
1097  *
1098  * Opens a zone file.
1099  *
1100  * Returns:
1101  *
1102  *	- pointer to the parser structure
1103  *	- NULL on error and errno set
1104  *
1105  */
1106 static int
1107 zone_open(const char *filename, uint32_t ttl, uint16_t klass,
1108 	  const dname_type *origin)
1109 {
1110 	/* Open the zone file... */
1111 	if (strcmp(filename, "-") == 0) {
1112 		yyin = stdin;
1113 		filename = "<stdin>";
1114 	} else if (!(yyin = fopen(filename, "r"))) {
1115 		return 0;
1116 	}
1117 
1118 	/* Open the network database */
1119 	setprotoent(1);
1120 	setservent(1);
1121 
1122 	zparser_init(filename, ttl, klass, origin);
1123 
1124 	return 1;
1125 }
1126 
1127 
1128 void
1129 set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE],
1130 	    uint16_t index)
1131 {
1132 	/*
1133 	 * The bits are counted from left to right, so bit #0 is the
1134 	 * left most bit.
1135 	 */
1136 	uint8_t window = index / 256;
1137 	uint8_t bit = index % 256;
1138 
1139 	bits[window][bit / 8] |= (1 << (7 - bit % 8));
1140 }
1141 
1142 
1143 static void
1144 cleanup_rrset(void *r)
1145 {
1146 	rrset_type *rrset = (rrset_type *) r;
1147 	if (rrset) {
1148 		free(rrset->rrs);
1149 	}
1150 }
1151 
1152 int
1153 process_rr(void)
1154 {
1155 	zone_type *zone = parser->current_zone;
1156 	rr_type *rr = &parser->current_rr;
1157 	rrset_type *rrset;
1158 	size_t max_rdlength;
1159 	int i;
1160 	rrtype_descriptor_type *descriptor
1161 		= rrtype_descriptor_by_type(rr->type);
1162 
1163 	/* We only support IN class */
1164 	if (rr->klass != CLASS_IN) {
1165 		if(zone->opts && zone->opts->request_xfr)
1166 			zc_warning_prev_line("only class IN is supported");
1167 		else
1168 			zc_error_prev_line("only class IN is supported");
1169 		return 0;
1170 	}
1171 
1172 	/* Make sure the maximum RDLENGTH does not exceed 65535 bytes.	*/
1173 	max_rdlength = rdata_maximum_wireformat_size(
1174 		descriptor, rr->rdata_count, rr->rdatas);
1175 
1176 	if (max_rdlength > MAX_RDLENGTH) {
1177 		zc_error_prev_line("maximum rdata length exceeds %d octets", MAX_RDLENGTH);
1178 		return 0;
1179 	}
1180 
1181 	/* Do we have the zone already? */
1182 	if (!zone)
1183 	{
1184 		zone = (zone_type *) region_alloc(parser->region,
1185 							  sizeof(zone_type));
1186 		zone->apex = parser->default_apex;
1187 		zone->soa_rrset = NULL;
1188 		zone->soa_nx_rrset = NULL;
1189 		zone->ns_rrset = NULL;
1190 		zone->opts = NULL;
1191 		zone->is_secure = 0;
1192 		zone->updated = 1;
1193 
1194 		zone->next = parser->db->zones;
1195 		parser->db->zones = zone;
1196 		parser->current_zone = zone;
1197 	}
1198 
1199 	if (rr->type == TYPE_SOA) {
1200 		/*
1201 		 * This is a SOA record, start a new zone or continue
1202 		 * an existing one.
1203 		 */
1204 		if (rr->owner->is_apex) {
1205 			if(zone->opts && zone->opts->request_xfr)
1206 				zc_warning_prev_line("this SOA record was already encountered");
1207 			else
1208 				zc_error_prev_line("this SOA record was already encountered");
1209 		} else if (rr->owner == parser->default_apex) {
1210 			zone->apex = rr->owner;
1211 			rr->owner->is_apex = 1;
1212 		}
1213 
1214 		/* parser part */
1215 		parser->current_zone = zone;
1216 	}
1217 
1218 	if (!dname_is_subdomain(domain_dname(rr->owner),
1219 				domain_dname(zone->apex)))
1220 	{
1221 		if(zone->opts && zone->opts->request_xfr)
1222 			zc_warning_prev_line("out of zone data");
1223 		else
1224 			zc_error_prev_line("out of zone data");
1225 		return 0;
1226 	}
1227 
1228 	/* Do we have this type of rrset already? */
1229 	rrset = domain_find_rrset(rr->owner, zone, rr->type);
1230 	if (!rrset) {
1231 		rrset = (rrset_type *) region_alloc(parser->region,
1232 						    sizeof(rrset_type));
1233 		rrset->zone = zone;
1234 		rrset->rr_count = 1;
1235 		rrset->rrs = (rr_type *) xalloc(sizeof(rr_type));
1236 		rrset->rrs[0] = *rr;
1237 
1238 		region_add_cleanup(parser->region, cleanup_rrset, rrset);
1239 
1240 		/* Add it */
1241 		domain_add_rrset(rr->owner, rrset);
1242 	} else {
1243 		if (rr->type != TYPE_RRSIG && rrset->rrs[0].ttl != rr->ttl) {
1244 			zc_warning_prev_line(
1245 				"TTL does not match the TTL of the RRset");
1246 		}
1247 
1248 		/* Search for possible duplicates... */
1249 		for (i = 0; i < rrset->rr_count; i++) {
1250 			if (!zrdatacmp(rr->type, rr, &rrset->rrs[i])) {
1251 				break;
1252 			}
1253 		}
1254 
1255 		/* Discard the duplicates... */
1256 		if (i < rrset->rr_count) {
1257 			return 0;
1258 		}
1259 
1260 		/* Add it... */
1261 		rrset->rrs = (rr_type *) xrealloc(
1262 			rrset->rrs,
1263 			(rrset->rr_count + 1) * sizeof(rr_type));
1264 		rrset->rrs[rrset->rr_count] = *rr;
1265 		++rrset->rr_count;
1266 	}
1267 
1268 	if(rr->type == TYPE_DNAME && rrset->rr_count > 1) {
1269 		if(zone->opts && zone->opts->request_xfr)
1270 			zc_warning_prev_line("multiple DNAMEs at the same name");
1271 		else
1272 			zc_error_prev_line("multiple DNAMEs at the same name");
1273 	}
1274 	if(rr->type == TYPE_CNAME && rrset->rr_count > 1) {
1275 		if(zone->opts && zone->opts->request_xfr)
1276 			zc_warning_prev_line("multiple CNAMEs at the same name");
1277 		else
1278 			zc_error_prev_line("multiple CNAMEs at the same name");
1279 	}
1280 	if((rr->type == TYPE_DNAME && domain_find_rrset(rr->owner, zone, TYPE_CNAME))
1281 	 ||(rr->type == TYPE_CNAME && domain_find_rrset(rr->owner, zone, TYPE_DNAME))) {
1282 		if(zone->opts && zone->opts->request_xfr)
1283 			zc_warning_prev_line("DNAME and CNAME at the same name");
1284 		else
1285 			zc_error_prev_line("DNAME and CNAME at the same name");
1286 	}
1287 	if(domain_find_rrset(rr->owner, zone, TYPE_CNAME) &&
1288 		domain_find_non_cname_rrset(rr->owner, zone)) {
1289 		if(zone->opts && zone->opts->request_xfr)
1290 			zc_warning_prev_line("CNAME and other data at the same name");
1291 		else
1292 			zc_error_prev_line("CNAME and other data at the same name");
1293 	}
1294 
1295 	if (rr->type == TYPE_RRSIG && rr_rrsig_type_covered(rr) == TYPE_DNSKEY) {
1296 		rrset->zone->is_secure = 1;
1297 	}
1298 
1299 	/* Check we have SOA */
1300 	if (zone->soa_rrset == NULL) {
1301 		if (rr->type == TYPE_SOA) {
1302 			if (rr->owner != zone->apex) {
1303 				zc_error_prev_line(
1304 					"SOA record with invalid domain name");
1305 			} else {
1306 				zone->soa_rrset = rrset;
1307 			}
1308 		}
1309 	}
1310 	else if (rr->type == TYPE_SOA) {
1311 		if(zone->opts && zone->opts->request_xfr)
1312 			zc_warning_prev_line("duplicate SOA record discarded");
1313 		else
1314 			zc_error_prev_line("duplicate SOA record discarded");
1315 		--rrset->rr_count;
1316 	}
1317 
1318 	/* Is this a zone NS? */
1319 	if (rr->type == TYPE_NS && rr->owner == zone->apex) {
1320 		zone->ns_rrset = rrset;
1321 	}
1322 	if (vflag > 1 && totalrrs > 0 && (totalrrs % progress == 0)) {
1323 		fprintf(stdout, "%ld\n", totalrrs);
1324 	}
1325 	++totalrrs;
1326 	return 1;
1327 }
1328 
1329 /*
1330  * Find rrset type for any zone
1331  */
1332 static rrset_type*
1333 domain_find_rrset_any(domain_type *domain, uint16_t type)
1334 {
1335 	rrset_type *result = domain->rrsets;
1336 	while (result) {
1337 		if (rrset_rrtype(result) == type) {
1338 			return result;
1339 		}
1340 		result = result->next;
1341 	}
1342 	return NULL;
1343 }
1344 
1345 /*
1346  * Check for DNAME type. Nothing is allowed below it
1347  */
1348 static void
1349 check_dname(namedb_type* db)
1350 {
1351 	domain_type* domain;
1352 	RBTREE_FOR(domain, domain_type*, db->domains->names_to_domains)
1353 	{
1354 		if(domain->is_existing) {
1355 			/* there may not be DNAMEs above it */
1356 			domain_type* parent = domain->parent;
1357 #ifdef NSEC3
1358 			if(domain_has_only_NSEC3(domain, NULL))
1359 				continue;
1360 #endif
1361 			while(parent) {
1362 				if(domain_find_rrset_any(parent, TYPE_DNAME)) {
1363 					zc_error("While checking node %s,",
1364 						dname_to_string(domain_dname(domain), NULL));
1365 					zc_error("DNAME at %s has data below it. "
1366 						"This is not allowed (rfc 2672).",
1367 						dname_to_string(domain_dname(parent), NULL));
1368 					exit(1);
1369 				}
1370 				parent = parent->parent;
1371 			}
1372 		}
1373 	}
1374 }
1375 
1376 /*
1377  * Reads the specified zone into the memory
1378  * nsd_options can be NULL if no config file is passed.
1379  *
1380  */
1381 static void
1382 zone_read(const char *name, const char *zonefile, nsd_options_t* nsd_options)
1383 {
1384 	const dname_type *dname;
1385 
1386 	dname = dname_parse(parser->region, name);
1387 	if (!dname) {
1388 		zc_error("incorrect zone name '%s'", name);
1389 		return;
1390 	}
1391 
1392 #ifndef ROOT_SERVER
1393 	/* Is it a root zone? Are we a root server then? Idiot proof. */
1394 	if (dname->label_count == 1) {
1395 		zc_error("not configured as a root server");
1396 		return;
1397 	}
1398 #endif
1399 
1400 	/* Open the zone file */
1401 	if (!zone_open(zonefile, 3600, CLASS_IN, dname)) {
1402 		if(nsd_options) {
1403 			/* check for secondary zone, they can start with no zone info */
1404 			zone_options_t* zopt = zone_options_find(nsd_options, dname);
1405 			if(zopt && zone_is_slave(zopt)) {
1406 				zc_warning("slave zone %s with no zonefile '%s'(%s) will "
1407 					"force zone transfer.",
1408 					name, zonefile, strerror(errno));
1409 				return;
1410 			}
1411 		}
1412 		/* cannot happen with stdin - so no fix needed for zonefile */
1413 		zc_error("cannot open '%s': %s", zonefile, strerror(errno));
1414 		return;
1415 	}
1416 
1417 	/* Parse and process all RRs.  */
1418 	yyparse();
1419 
1420 	/* check if zone file contained a correct SOA record */
1421 	if (parser->current_zone && parser->current_zone->soa_rrset
1422 		&& parser->current_zone->soa_rrset->rr_count!=0)
1423 	{
1424 		if(dname_compare(domain_dname(
1425 			parser->current_zone->soa_rrset->rrs[0].owner),
1426 			dname) != 0) {
1427 			zc_error("zone configured as '%s', but SOA has owner '%s'.",
1428 				name, dname_to_string(
1429 				domain_dname(parser->current_zone->
1430 				soa_rrset->rrs[0].owner), NULL));
1431 		}
1432 	}
1433 
1434 	fclose(yyin);
1435 
1436 	fflush(stdout);
1437 	totalerrors += parser->errors;
1438 	parser->filename = NULL;
1439 }
1440 
1441 static void
1442 usage (void)
1443 {
1444 #ifndef NDEBUG
1445 	fprintf(stderr, "usage: nsd-zonec [-v|-h|-C|-F|-L] [-c configfile] [-o origin] [-d directory] [-f database] [-z zonefile]\n\n");
1446 #else
1447 	fprintf(stderr, "usage: nsd-zonec [-v|-h|-C] [-c configfile] [-o origin] [-d directory] [-f database] [-z zonefile]\n\n");
1448 #endif
1449 	fprintf(stderr, "\tNSD zone compiler, creates database from zone files.\n");
1450 	fprintf(stderr, "\tVersion %s. Report bugs to <%s>.\n\n",
1451 		PACKAGE_VERSION, PACKAGE_BUGREPORT);
1452 	fprintf(stderr, "\t-v\tBe more verbose.\n");
1453 	fprintf(stderr, "\t-h\tPrint this help information.\n");
1454 	fprintf(stderr, "\t-c\tSpecify config file to read instead of default nsd.conf.\n");
1455 	fprintf(stderr, "\t-C\tNo config file is read.\n");
1456 	fprintf(stderr, "\t-d\tSet working directory to open files from.\n");
1457 	fprintf(stderr, "\t-o\tSpecify a zone's origin (only used with -z).\n");
1458 	fprintf(stderr, "\t-f\tSpecify database file to use.\n");
1459 	fprintf(stderr, "\t-z\tSpecify a zonefile to read (read from stdin with \'-\').\n");
1460 #ifndef NDEBUG
1461 	fprintf(stderr, "\t-F\tSet debug facilities.\n");
1462 	fprintf(stderr, "\t-L\tSet debug level.\n");
1463 #endif
1464 }
1465 
1466 extern char *optarg;
1467 extern int optind;
1468 
1469 int
1470 main (int argc, char **argv)
1471 {
1472 	struct namedb *db;
1473 	char *origin = NULL;
1474 	int c;
1475 	region_type *global_region;
1476 	region_type *rr_region;
1477 	const char* configfile= CONFIGFILE;
1478 	const char* zonesdir = NULL;
1479 	const char* singlefile = NULL;
1480 	nsd_options_t* nsd_options = NULL;
1481 
1482 	log_init("nsd-zonec");
1483 
1484 	global_region = region_create(xalloc, free);
1485 	rr_region = region_create(xalloc, free);
1486 	totalerrors = 0;
1487 
1488 	/* Parse the command line... */
1489 	while ((c = getopt(argc, argv, "d:f:vhCF:L:o:c:z:")) != -1) {
1490 		switch (c) {
1491 		case 'c':
1492 			configfile = optarg;
1493 			break;
1494 		case 'v':
1495 			++vflag;
1496 			break;
1497 		case 'f':
1498 			dbfile = optarg;
1499 			break;
1500 		case 'd':
1501 			zonesdir = optarg;
1502 			break;
1503 		case 'C':
1504 			configfile = 0;
1505 			break;
1506 #ifndef NDEBUG
1507 		case 'F':
1508 			sscanf(optarg, "%x", &nsd_debug_facilities);
1509 			break;
1510 		case 'L':
1511 			sscanf(optarg, "%d", &nsd_debug_level);
1512 			break;
1513 #endif /* NDEBUG */
1514 		case 'o':
1515 			origin = optarg;
1516 			break;
1517 		case 'z':
1518 			singlefile = optarg;
1519 			break;
1520 		case 'h':
1521 			usage();
1522 			exit(0);
1523 		case '?':
1524 		default:
1525 			usage();
1526 			exit(1);
1527 		}
1528 	}
1529 
1530 	argc -= optind;
1531 	argv += optind;
1532 
1533 	if (argc != 0) {
1534 		usage();
1535 		exit(1);
1536 	}
1537 
1538 	/* Read options */
1539 	if(configfile != 0) {
1540 		nsd_options = nsd_options_create(global_region);
1541 		if(!parse_options_file(nsd_options, configfile))
1542 		{
1543 			fprintf(stderr, "nsd-zonec: could not read config: %s\n", configfile);
1544 			exit(1);
1545 		}
1546 	}
1547 	if(nsd_options && zonesdir == 0) zonesdir = nsd_options->zonesdir;
1548 	if(zonesdir && zonesdir[0]) {
1549 		if (chdir(zonesdir)) {
1550 			fprintf(stderr, "nsd-zonec: cannot chdir to %s: %s\n", zonesdir, strerror(errno));
1551 			exit(1);
1552 		}
1553 	}
1554 	if(dbfile == 0) {
1555 		if(nsd_options && nsd_options->database) dbfile = nsd_options->database;
1556 		else dbfile = DBFILE;
1557 	}
1558 
1559 	/* Create the database */
1560 	if ((db = namedb_new(dbfile)) == NULL) {
1561 		fprintf(stderr, "nsd-zonec: error creating the database (%s): %s\n",
1562 			dbfile, strerror(errno));
1563 		exit(1);
1564 	}
1565 
1566 	parser = zparser_create(global_region, rr_region, db);
1567 	if (!parser) {
1568 		fprintf(stderr, "nsd-zonec: error creating the parser\n");
1569 		exit(1);
1570 	}
1571 
1572 	/* Unique pointers used to mark errors.	 */
1573 	error_dname = (dname_type *) region_alloc(global_region, 0);
1574 	error_domain = (domain_type *) region_alloc(global_region, 0);
1575 
1576 	if (singlefile || origin) {
1577 		/*
1578 		 * Read a single zone file with the specified origin
1579 		 */
1580 		if(!singlefile) {
1581 			fprintf(stderr, "nsd-zonec: must have -z zonefile when reading single zone.\n");
1582 			exit(1);
1583 		}
1584 		if(!origin) {
1585 			fprintf(stderr, "nsd-zonec: must have -o origin when reading single zone.\n");
1586 			exit(1);
1587 		}
1588 		if (vflag > 0)
1589 			fprintf(stdout, "nsd-zonec: reading zone \"%s\".\n", origin);
1590 		zone_read(origin, singlefile, nsd_options);
1591 		if (vflag > 0)
1592 			fprintf(stdout, "nsd-zonec: processed %ld RRs in \"%s\".\n", totalrrs, origin);
1593 	} else {
1594 		zone_options_t* zone;
1595 		if(!nsd_options) {
1596 			fprintf(stderr, "nsd-zonec: no zones specified.\n");
1597 			exit(1);
1598 		}
1599 		/* read all zones */
1600 		RBTREE_FOR(zone, zone_options_t*, nsd_options->zone_options)
1601 		{
1602 			if (vflag > 0)
1603 				fprintf(stdout, "nsd-zonec: reading zone \"%s\".\n",
1604 					zone->name);
1605 			zone_read(zone->name, zone->zonefile, nsd_options);
1606 			if (vflag > 0)
1607 				fprintf(stdout,
1608 					"nsd-zonec: processed %ld RRs in \"%s\".\n",
1609 					totalrrs, zone->name);
1610 			totalrrs = 0;
1611 		}
1612 	}
1613 	check_dname(db);
1614 
1615 #ifndef NDEBUG
1616 	if (vflag > 0) {
1617 		fprintf(stdout, "global_region: ");
1618 		region_dump_stats(global_region, stdout);
1619 		fprintf(stdout, "\n");
1620 		fprintf(stdout, "db->region: ");
1621 		region_dump_stats(db->region, stdout);
1622 		fprintf(stdout, "\n");
1623 	}
1624 #endif /* NDEBUG */
1625 
1626 	/* Close the database */
1627 	if (namedb_save(db) != 0) {
1628 		fprintf(stderr, "nsd-zonec: error writing the database (%s): %s\n", db->filename, strerror(errno));
1629 		namedb_discard(db);
1630 		exit(1);
1631 	}
1632 
1633 	/* Print the total number of errors */
1634 	if (vflag > 0 || totalerrors > 0) {
1635 		if (totalerrors > 0) {
1636 			fprintf(stderr, "\nnsd-zonec: done with %ld errors.\n",
1637 			totalerrors);
1638 		} else {
1639 			fprintf(stdout, "\nnsd-zonec: done with no errors.\n");
1640 		}
1641 	}
1642 
1643 	/* Disable this to save some time.  */
1644 #if 0
1645 	region_destroy(global_region);
1646 #endif
1647 
1648 	return totalerrors ? 1 : 0;
1649 }
1650