xref: /openbsd-src/usr.sbin/nsd/util.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*
2  * util.c -- set of various support routines.
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 <ctype.h>
14 #include <errno.h>
15 #include <stdarg.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #ifdef HAVE_SYSLOG_H
20 #include <syslog.h>
21 #endif /* HAVE_SYSLOG_H */
22 #include <unistd.h>
23 
24 #include "util.h"
25 #include "region-allocator.h"
26 #include "dname.h"
27 #include "namedb.h"
28 #include "rdata.h"
29 
30 #ifdef USE_MMAP_ALLOC
31 #include <sys/mman.h>
32 
33 #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
34 #define	MAP_ANONYMOUS	MAP_ANON
35 #elif defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
36 #define	MAP_ANON	MAP_ANONYMOUS
37 #endif
38 
39 #endif /* USE_MMAP_ALLOC */
40 
41 #ifndef NDEBUG
42 unsigned nsd_debug_facilities = 0xffff;
43 int nsd_debug_level = 0;
44 #endif
45 
46 int verbosity = 0;
47 
48 static const char *global_ident = NULL;
49 static log_function_type *current_log_function = log_file;
50 static FILE *current_log_file = NULL;
51 
52 void
53 log_init(const char *ident)
54 {
55 	global_ident = ident;
56 	current_log_file = stderr;
57 }
58 
59 void
60 log_open(int option, int facility, const char *filename)
61 {
62 #ifdef HAVE_SYSLOG_H
63 	openlog(global_ident, option, facility);
64 #endif /* HAVE_SYSLOG_H */
65 	if (filename) {
66 		FILE *file = fopen(filename, "a");
67 		if (!file) {
68 			log_msg(LOG_ERR, "Cannot open %s for appending (%s), "
69 					 "logging to stderr",
70 				filename, strerror(errno));
71 		} else {
72 			current_log_file = file;
73 		}
74 	}
75 }
76 
77 void
78 log_reopen(const char *filename, uint8_t verbose)
79 {
80 	if (filename) {
81 		FILE *file = fopen(filename, "a");
82 		if (!file) {
83 			if (verbose)
84 				VERBOSITY(2, (LOG_WARNING,
85                                 	"Cannot reopen %s for appending (%s), "
86 					"keeping old logfile",
87 					filename, strerror(errno)));
88 		} else {
89 			if (current_log_file && current_log_file != stderr)
90 				fclose(current_log_file);
91 			current_log_file = file;
92 		}
93 	}
94 }
95 
96 void
97 log_finalize(void)
98 {
99 #ifdef HAVE_SYSLOG_H
100 	closelog();
101 #endif /* HAVE_SYSLOG_H */
102 	if (current_log_file && current_log_file != stderr) {
103 		fclose(current_log_file);
104 	}
105 	current_log_file = NULL;
106 }
107 
108 static lookup_table_type log_priority_table[] = {
109 	{ LOG_ERR, "error" },
110 	{ LOG_WARNING, "warning" },
111 	{ LOG_NOTICE, "notice" },
112 	{ LOG_INFO, "info" },
113 	{ 0, NULL }
114 };
115 
116 void
117 log_file(int priority, const char *message)
118 {
119 	size_t length;
120 	lookup_table_type *priority_info;
121 	const char *priority_text = "unknown";
122 
123 	assert(global_ident);
124 	assert(current_log_file);
125 
126 	priority_info = lookup_by_id(log_priority_table, priority);
127 	if (priority_info) {
128 		priority_text = priority_info->name;
129 	}
130 
131 	/* Bug #104, add time_t timestamp */
132 	fprintf(current_log_file, "[%d] %s[%d]: %s: %s",
133 		(int)time(NULL), global_ident, (int) getpid(), priority_text, message);
134 	length = strlen(message);
135 	if (length == 0 || message[length - 1] != '\n') {
136 		fprintf(current_log_file, "\n");
137 	}
138 	fflush(current_log_file);
139 }
140 
141 void
142 log_syslog(int priority, const char *message)
143 {
144 #ifdef HAVE_SYSLOG_H
145 	syslog(priority, "%s", message);
146 #endif /* !HAVE_SYSLOG_H */
147 	log_file(priority, message);
148 }
149 
150 void
151 log_set_log_function(log_function_type *log_function)
152 {
153 	current_log_function = log_function;
154 }
155 
156 void
157 log_msg(int priority, const char *format, ...)
158 {
159 	va_list args;
160 	va_start(args, format);
161 	log_vmsg(priority, format, args);
162 	va_end(args);
163 }
164 
165 void
166 log_vmsg(int priority, const char *format, va_list args)
167 {
168 	char message[MAXSYSLOGMSGLEN];
169 	vsnprintf(message, sizeof(message), format, args);
170 	current_log_function(priority, message);
171 }
172 
173 void
174 set_bit(uint8_t bits[], size_t index)
175 {
176 	/*
177 	 * The bits are counted from left to right, so bit #0 is the
178 	 * left most bit.
179 	 */
180 	bits[index / 8] |= (1 << (7 - index % 8));
181 }
182 
183 void
184 clear_bit(uint8_t bits[], size_t index)
185 {
186 	/*
187 	 * The bits are counted from left to right, so bit #0 is the
188 	 * left most bit.
189 	 */
190 	bits[index / 8] &= ~(1 << (7 - index % 8));
191 }
192 
193 int
194 get_bit(uint8_t bits[], size_t index)
195 {
196 	/*
197 	 * The bits are counted from left to right, so bit #0 is the
198 	 * left most bit.
199 	 */
200 	return bits[index / 8] & (1 << (7 - index % 8));
201 }
202 
203 lookup_table_type *
204 lookup_by_name(lookup_table_type *table, const char *name)
205 {
206 	while (table->name != NULL) {
207 		if (strcasecmp(name, table->name) == 0)
208 			return table;
209 		table++;
210 	}
211 	return NULL;
212 }
213 
214 lookup_table_type *
215 lookup_by_id(lookup_table_type *table, int id)
216 {
217 	while (table->name != NULL) {
218 		if (table->id == id)
219 			return table;
220 		table++;
221 	}
222 	return NULL;
223 }
224 
225 void *
226 xalloc(size_t size)
227 {
228 	void *result = malloc(size);
229 
230 	if (!result) {
231 		log_msg(LOG_ERR, "malloc failed: %s", strerror(errno));
232 		exit(1);
233 	}
234 	return result;
235 }
236 
237 void *
238 xalloc_zero(size_t size)
239 {
240 	void *result = xalloc(size);
241 	memset(result, 0, size);
242 	return result;
243 }
244 
245 void *
246 xrealloc(void *ptr, size_t size)
247 {
248 	ptr = realloc(ptr, size);
249 	if (!ptr) {
250 		log_msg(LOG_ERR, "realloc failed: %s", strerror(errno));
251 		exit(1);
252 	}
253 	return ptr;
254 }
255 
256 #ifdef USE_MMAP_ALLOC
257 
258 void *
259 mmap_alloc(size_t size)
260 {
261 	void *base;
262 
263 	size += MMAP_ALLOC_HEADER_SIZE;
264 #ifdef HAVE_MMAP
265 	base = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
266 	if (base == MAP_FAILED) {
267 		log_msg(LOG_ERR, "mmap failed: %s", strerror(errno));
268 		exit(1);
269 	}
270 #else /* !HAVE_MMAP */
271 	log_msg(LOG_ERR, "mmap failed: don't have mmap");
272 	exit(1);
273 #endif /* HAVE_MMAP */
274 
275 	*((size_t*) base) = size;
276 	return (void*)((uintptr_t)base + MMAP_ALLOC_HEADER_SIZE);
277 }
278 
279 
280 void
281 mmap_free(void *ptr)
282 {
283 	void *base;
284 	size_t size;
285 
286 	if (!ptr) return;
287 
288 	base = (void*)((uintptr_t)ptr - MMAP_ALLOC_HEADER_SIZE);
289 	size = *((size_t*) base);
290 
291 #ifdef HAVE_MUNMAP
292 	if (munmap(base, size) == -1) {
293 		log_msg(LOG_ERR, "munmap failed: %s", strerror(errno));
294 		exit(1);
295 	}
296 #else /* !HAVE_MUNMAP */
297 	log_msg(LOG_ERR, "munmap failed: don't have munmap");
298 	exit(1);
299 #endif /* HAVE_MUNMAP */
300 }
301 
302 #endif /* USE_MMAP_ALLOC */
303 
304 int
305 write_data(FILE *file, const void *data, size_t size)
306 {
307 	size_t result;
308 
309 	if (size == 0)
310 		return 1;
311 
312 	result = fwrite(data, 1, size, file);
313 
314 	if (result == 0) {
315 		log_msg(LOG_ERR, "write failed: %s", strerror(errno));
316 		return 0;
317 	} else if (result < size) {
318 		log_msg(LOG_ERR, "short write (disk full?)");
319 		return 0;
320 	} else {
321 		return 1;
322 	}
323 }
324 
325 int
326 write_socket(int s, const void *buf, size_t size)
327 {
328 	const char* data = (const char*)buf;
329 	size_t total_count = 0;
330 
331 	while (total_count < size) {
332 		ssize_t count
333 			= write(s, data + total_count, size - total_count);
334 		if (count == -1) {
335 			if (errno != EAGAIN && errno != EINTR) {
336 				return 0;
337 			} else {
338 				continue;
339 			}
340 		}
341 		total_count += count;
342 	}
343 	return 1;
344 }
345 
346 int
347 timespec_compare(const struct timespec *left,
348 		 const struct timespec *right)
349 {
350 	/* Compare seconds.  */
351 	if (left->tv_sec < right->tv_sec) {
352 		return -1;
353 	} else if (left->tv_sec > right->tv_sec) {
354 		return 1;
355 	} else {
356 		/* Seconds are equal, compare nanoseconds.  */
357 		if (left->tv_nsec < right->tv_nsec) {
358 			return -1;
359 		} else if (left->tv_nsec > right->tv_nsec) {
360 			return 1;
361 		} else {
362 			return 0;
363 		}
364 	}
365 }
366 
367 
368 /* One second is 1e9 nanoseconds.  */
369 #define NANOSECONDS_PER_SECOND   1000000000L
370 
371 void
372 timespec_add(struct timespec *left,
373 	     const struct timespec *right)
374 {
375 	left->tv_sec += right->tv_sec;
376 	left->tv_nsec += right->tv_nsec;
377 	if (left->tv_nsec >= NANOSECONDS_PER_SECOND) {
378 		/* Carry.  */
379 		++left->tv_sec;
380 		left->tv_nsec -= NANOSECONDS_PER_SECOND;
381 	}
382 }
383 
384 void
385 timespec_subtract(struct timespec *left,
386 		  const struct timespec *right)
387 {
388 	left->tv_sec -= right->tv_sec;
389 	left->tv_nsec -= right->tv_nsec;
390 	if (left->tv_nsec < 0L) {
391 		/* Borrow.  */
392 		--left->tv_sec;
393 		left->tv_nsec += NANOSECONDS_PER_SECOND;
394 	}
395 }
396 
397 uint32_t
398 strtoserial(const char* nptr, const char** endptr)
399 {
400 	uint32_t i = 0;
401 	uint32_t serial = 0;
402 
403 	for(*endptr = nptr; **endptr; (*endptr)++) {
404 		switch (**endptr) {
405 		case ' ':
406 		case '\t':
407 			break;
408 		case '0':
409 		case '1':
410 		case '2':
411 		case '3':
412 		case '4':
413 		case '5':
414 		case '6':
415 		case '7':
416 		case '8':
417 		case '9':
418 			i *= 10;
419 			i += (**endptr - '0');
420 			break;
421 		default:
422 			break;
423 		}
424 	}
425 	serial += i;
426 	return serial;
427 }
428 
429 uint32_t
430 strtottl(const char *nptr, const char **endptr)
431 {
432 	uint32_t i = 0;
433 	uint32_t seconds = 0;
434 
435 	for(*endptr = nptr; **endptr; (*endptr)++) {
436 		switch (**endptr) {
437 		case ' ':
438 		case '\t':
439 			break;
440 		case 's':
441 		case 'S':
442 			seconds += i;
443 			i = 0;
444 			break;
445 		case 'm':
446 		case 'M':
447 			seconds += i * 60;
448 			i = 0;
449 			break;
450 		case 'h':
451 		case 'H':
452 			seconds += i * 60 * 60;
453 			i = 0;
454 			break;
455 		case 'd':
456 		case 'D':
457 			seconds += i * 60 * 60 * 24;
458 			i = 0;
459 			break;
460 		case 'w':
461 		case 'W':
462 			seconds += i * 60 * 60 * 24 * 7;
463 			i = 0;
464 			break;
465 		case '0':
466 		case '1':
467 		case '2':
468 		case '3':
469 		case '4':
470 		case '5':
471 		case '6':
472 		case '7':
473 		case '8':
474 		case '9':
475 			i *= 10;
476 			i += (**endptr - '0');
477 			break;
478 		default:
479 			seconds += i;
480 			return seconds;
481 		}
482 	}
483 	seconds += i;
484 	return seconds;
485 }
486 
487 
488 ssize_t
489 hex_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize)
490 {
491 	static char hexdigits[] = {
492 		'0', '1', '2', '3', '4', '5', '6', '7',
493 		'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
494 	};
495 	size_t i;
496 
497 	if (targsize < srclength * 2 + 1) {
498 		return -1;
499 	}
500 
501 	for (i = 0; i < srclength; ++i) {
502 		*target++ = hexdigits[src[i] >> 4U];
503 		*target++ = hexdigits[src[i] & 0xfU];
504 	}
505 	*target = '\0';
506 	return 2 * srclength;
507 }
508 
509 ssize_t
510 hex_pton(const char* src, uint8_t* target, size_t targsize)
511 {
512 	uint8_t *t = target;
513 	if(strlen(src) % 2 != 0 || strlen(src)/2 > targsize) {
514 		return -1;
515 	}
516 	while(*src) {
517 		if(!isxdigit((int)src[0]) || !isxdigit((int)src[1]))
518 			return -1;
519 		*t++ = hexdigit_to_int(src[0]) * 16 +
520 			hexdigit_to_int(src[1]) ;
521 		src += 2;
522 	}
523 	return t-target;
524 }
525 
526 int
527 b32_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize)
528 {
529 	static char b32[]="0123456789abcdefghijklmnopqrstuv";
530 	char buf[9];
531 	ssize_t len=0;
532 
533 	while(srclength > 0)
534 	{
535 		int t;
536 		memset(buf,'\0',sizeof buf);
537 
538 		/* xxxxx000 00000000 00000000 00000000 00000000 */
539 		buf[0]=b32[src[0] >> 3];
540 
541 		/* 00000xxx xx000000 00000000 00000000 00000000 */
542 		t=(src[0]&7) << 2;
543 		if(srclength > 1)
544 			t+=src[1] >> 6;
545 		buf[1]=b32[t];
546 		if(srclength == 1)
547 			break;
548 
549 		/* 00000000 00xxxxx0 00000000 00000000 00000000 */
550 		buf[2]=b32[(src[1] >> 1)&0x1f];
551 
552 		/* 00000000 0000000x xxxx0000 00000000 00000000 */
553 		t=(src[1]&1) << 4;
554 		if(srclength > 2)
555 			t+=src[2] >> 4;
556 		buf[3]=b32[t];
557 		if(srclength == 2)
558 			break;
559 
560 		/* 00000000 00000000 0000xxxx x0000000 00000000 */
561 		t=(src[2]&0xf) << 1;
562 		if(srclength > 3)
563 			t+=src[3] >> 7;
564 		buf[4]=b32[t];
565 		if(srclength == 3)
566 			break;
567 
568 		/* 00000000 00000000 00000000 0xxxxx00 00000000 */
569 		buf[5]=b32[(src[3] >> 2)&0x1f];
570 
571 		/* 00000000 00000000 00000000 000000xx xxx00000 */
572 		t=(src[3]&3) << 3;
573 		if(srclength > 4)
574 			t+=src[4] >> 5;
575 		buf[6]=b32[t];
576 		if(srclength == 4)
577 			break;
578 
579 		/* 00000000 00000000 00000000 00000000 000xxxxx */
580 		buf[7]=b32[src[4]&0x1f];
581 
582 		if(targsize < 8)
583 			return -1;
584 
585 		src += 5;
586 		srclength -= 5;
587 
588 		memcpy(target,buf,8);
589 		target += 8;
590 		targsize -= 8;
591 		len += 8;
592 	}
593 	if(srclength)
594 	{
595 		if(targsize < strlen(buf)+1)
596 			return -1;
597 		strlcpy(target, buf, targsize);
598 		len += strlen(buf);
599 	}
600 	else if(targsize < 1)
601 		return -1;
602 	else
603 		*target='\0';
604 	return len;
605 }
606 
607 int
608 b32_pton(const char *src, uint8_t *target, size_t tsize)
609 {
610 	char ch;
611 	size_t p=0;
612 
613 	memset(target,'\0',tsize);
614 	while((ch = *src++)) {
615 		uint8_t d;
616 		size_t b;
617 		size_t n;
618 
619 		if(p+5 >= tsize*8)
620 		       return -1;
621 
622 		if(isspace(ch))
623 			continue;
624 
625 		if(ch >= '0' && ch <= '9')
626 			d=ch-'0';
627 		else if(ch >= 'A' && ch <= 'V')
628 			d=ch-'A'+10;
629 		else if(ch >= 'a' && ch <= 'v')
630 			d=ch-'a'+10;
631 		else
632 			return -1;
633 
634 		b=7-p%8;
635 		n=p/8;
636 
637 		if(b >= 4)
638 			target[n]|=d << (b-4);
639 		else {
640 			target[n]|=d >> (4-b);
641 			target[n+1]|=d << (b+4);
642 		}
643 		p+=5;
644 	}
645 	return (p+7)/8;
646 }
647 
648 void
649 strip_string(char *str)
650 {
651 	char *start = str;
652 	char *end = str + strlen(str) - 1;
653 
654 	while (isspace(*start))
655 		++start;
656 	if (start > end) {
657 		/* Completely blank. */
658 		str[0] = '\0';
659 	} else {
660 		while (isspace(*end))
661 			--end;
662 		*++end = '\0';
663 
664 		if (str != start)
665 			memmove(str, start, end - start + 1);
666 	}
667 }
668 
669 int
670 hexdigit_to_int(char ch)
671 {
672 	switch (ch) {
673 	case '0': return 0;
674 	case '1': return 1;
675 	case '2': return 2;
676 	case '3': return 3;
677 	case '4': return 4;
678 	case '5': return 5;
679 	case '6': return 6;
680 	case '7': return 7;
681 	case '8': return 8;
682 	case '9': return 9;
683 	case 'a': case 'A': return 10;
684 	case 'b': case 'B': return 11;
685 	case 'c': case 'C': return 12;
686 	case 'd': case 'D': return 13;
687 	case 'e': case 'E': return 14;
688 	case 'f': case 'F': return 15;
689 	default:
690 		abort();
691 	}
692 }
693 
694 /* Number of days per month (except for February in leap years). */
695 static const int mdays[] = {
696     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
697 };
698 
699 static int
700 is_leap_year(int year)
701 {
702     return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
703 }
704 
705 static int
706 leap_days(int y1, int y2)
707 {
708     --y1;
709     --y2;
710     return (y2/4 - y1/4) - (y2/100 - y1/100) + (y2/400 - y1/400);
711 }
712 
713 /*
714  * Code adapted from Python 2.4.1 sources (Lib/calendar.py).
715  */
716 time_t
717 mktime_from_utc(const struct tm *tm)
718 {
719     int year = 1900 + tm->tm_year;
720     time_t days = 365 * (year - 1970) + leap_days(1970, year);
721     time_t hours;
722     time_t minutes;
723     time_t seconds;
724     int i;
725 
726     for (i = 0; i < tm->tm_mon; ++i) {
727         days += mdays[i];
728     }
729     if (tm->tm_mon > 1 && is_leap_year(year)) {
730         ++days;
731     }
732     days += tm->tm_mday - 1;
733 
734     hours = days * 24 + tm->tm_hour;
735     minutes = hours * 60 + tm->tm_min;
736     seconds = minutes * 60 + tm->tm_sec;
737 
738     return seconds;
739 }
740 
741 /* code to calculate CRC. Lifted from BSD 4.4 crc.c in cksum(1). BSD license.
742    http://www.tsfr.org/~orc/Code/bsd/bsd-current/cksum/crc.c.
743    or http://gobsd.com/code/freebsd/usr.bin/cksum/crc.c
744    The polynomial is 0x04c11db7L. */
745 static u_long crctab[] = {
746 	0x0,
747 	0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
748 	0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
749 	0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
750 	0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
751 	0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
752 	0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
753 	0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
754 	0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
755 	0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
756 	0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
757 	0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
758 	0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
759 	0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
760 	0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
761 	0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
762 	0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
763 	0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
764 	0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
765 	0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
766 	0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
767 	0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
768 	0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
769 	0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
770 	0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
771 	0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
772 	0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
773 	0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
774 	0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
775 	0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
776 	0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
777 	0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
778 	0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
779 	0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
780 	0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
781 	0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
782 	0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
783 	0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
784 	0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
785 	0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
786 	0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
787 	0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
788 	0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
789 	0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
790 	0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
791 	0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
792 	0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
793 	0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
794 	0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
795 	0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
796 	0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
797 	0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
798 };
799 
800 #define	COMPUTE(var, ch)	(var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
801 
802 uint32_t
803 compute_crc(uint32_t crc, uint8_t* data, size_t len)
804 {
805 	size_t i;
806 	for(i=0; i<len; ++i)
807 		COMPUTE(crc, data[i]);
808 	return crc;
809 }
810 
811 int
812 write_data_crc(FILE *file, const void *data, size_t size, uint32_t* crc)
813 {
814 	int ret = write_data(file, data, size);
815 	*crc = compute_crc(*crc, (uint8_t*)data, size);
816 	return ret;
817 }
818 
819 #define SERIAL_BITS      32
820 int
821 compare_serial(uint32_t a, uint32_t b)
822 {
823         const uint32_t cutoff = ((uint32_t) 1 << (SERIAL_BITS - 1));
824 
825         if (a == b) {
826                 return 0;
827         } else if ((a < b && b - a < cutoff) || (a > b && a - b > cutoff)) {
828                 return -1;
829         } else {
830                 return 1;
831         }
832 }
833 
834 uint16_t
835 qid_generate(void)
836 {
837 #ifdef HAVE_ARC4RANDOM_UNIFORM
838     return (uint16_t) arc4random_uniform(65536);
839 #elif HAVE_ARC4RANDOM
840     return (uint16_t) arc4random();
841 #else
842     return (uint16_t) random();
843 #endif
844 }
845 
846 void
847 cleanup_region(void *data)
848 {
849 	region_type *region = (region_type *) data;
850 	region_destroy(region);
851 }
852 
853 struct state_pretty_rr*
854 create_pretty_rr(struct region* region)
855 {
856 	struct state_pretty_rr* state = (struct state_pretty_rr*)
857 		region_alloc(region, sizeof(struct state_pretty_rr));
858 	state->previous_owner_region = region_create(xalloc, free);
859 	state->previous_owner = NULL;
860 	state->previous_owner_origin = NULL;
861         region_add_cleanup(region, cleanup_region,
862 		state->previous_owner_region);
863 	return state;
864 }
865 
866 static void
867 set_previous_owner(struct state_pretty_rr *state, const dname_type *dname)
868 {
869 	region_free_all(state->previous_owner_region);
870 	state->previous_owner = dname_copy(state->previous_owner_region, dname);
871 	state->previous_owner_origin = dname_origin(
872 		state->previous_owner_region, state->previous_owner);
873 }
874 
875 int
876 print_rr(FILE *out,
877          struct state_pretty_rr *state,
878          rr_type *record)
879 {
880 	region_type *region = region_create(xalloc, free);
881         buffer_type *output = buffer_create(region, MAX_RDLENGTH);
882         rrtype_descriptor_type *descriptor
883                 = rrtype_descriptor_by_type(record->type);
884         int result;
885         const dname_type *owner = domain_dname(record->owner);
886         const dname_type *owner_origin
887                 = dname_origin(region, owner);
888         int owner_changed
889                 = (!state->previous_owner
890                    || dname_compare(state->previous_owner, owner) != 0);
891         if (owner_changed) {
892                 int origin_changed = (!state->previous_owner_origin
893                                       || dname_compare(
894                                               state->previous_owner_origin,
895                                               owner_origin) != 0);
896                 if (origin_changed) {
897                         buffer_printf(
898                                 output,
899                                 "$ORIGIN %s\n",
900                                 dname_to_string(owner_origin, NULL));
901                 }
902 
903                 set_previous_owner(state, owner);
904                 buffer_printf(output,
905                               "%s",
906                               dname_to_string(owner,
907                                               state->previous_owner_origin));
908         }
909 
910         buffer_printf(output,
911                       "\t%lu\t%s\t%s",
912                       (unsigned long) record->ttl,
913                       rrclass_to_string(record->klass),
914                       rrtype_to_string(record->type));
915 
916         result = print_rdata(output, descriptor, record);
917         if (!result) {
918                 /*
919                  * Some RDATA failed to print, so print the record's
920                  * RDATA in unknown format.
921                  */
922                 result = rdata_atoms_to_unknown_string(output,
923                                                        descriptor,
924                                                        record->rdata_count,
925                                                        record->rdatas);
926         }
927 
928         if (result) {
929                 buffer_printf(output, "\n");
930                 buffer_flip(output);
931 		(void)write_data(out, buffer_current(output), buffer_remaining(output));
932 /*              fflush(out); */
933         }
934 
935 	region_destroy(region);
936         return result;
937 }
938 
939 const char*
940 rcode2str(int rc)
941 {
942         switch(rc)
943         {
944         case RCODE_OK:
945                 return "NO ERROR";
946         case RCODE_FORMAT:
947                 return "FORMAT ERROR";
948         case RCODE_SERVFAIL:
949                 return "SERV FAIL";
950         case RCODE_NXDOMAIN:
951                 return "NAME ERROR";
952         case RCODE_IMPL:
953                 return "NOT IMPL";
954         case RCODE_REFUSE:
955                 return "REFUSED";
956 	case RCODE_YXDOMAIN:
957 		return "YXDOMAIN";
958 	case RCODE_YXRRSET:
959 		return "YXRRSET";
960 	case RCODE_NXRRSET:
961 		return "NXRRSET";
962         case RCODE_NOTAUTH:
963                 return "SERVER NOT AUTHORITATIVE FOR ZONE";
964 	case RCODE_NOTZONE:
965 		return "NOTZONE";
966         default:
967                 return "UNKNOWN ERROR";
968         }
969         return NULL; /* ENOREACH */
970 }
971 
972 stack_type*
973 stack_create(struct region* region, size_t size)
974 {
975 	stack_type* stack = (stack_type*)region_alloc(region,
976 		sizeof(stack_type));
977 	stack->capacity = size;
978 	stack->num = 0;
979 	stack->data = (void**) region_alloc(region, sizeof(void*)*size);
980 	memset(stack->data, 0, sizeof(void*)*size);
981 	return stack;
982 }
983 
984 void
985 stack_push(stack_type* stack, void* elem)
986 {
987 	assert(stack);
988 	if(stack->num >= stack->capacity) {
989 		/* stack out of capacity, elem falls off stack */
990 		return;
991 	}
992 	stack->data[stack->num] = elem;
993 	stack->num ++;
994 }
995 
996 void*
997 stack_pop(stack_type* stack)
998 {
999 	void* elem;
1000 	assert(stack);
1001 	if(stack->num <= 0)
1002 		return NULL;
1003 	stack->num --;
1004 	elem = stack->data[stack->num];
1005 	stack->data[stack->num] = NULL;
1006 	return elem;
1007 }
1008 
1009 int
1010 addr2ip(
1011 #ifdef INET6
1012         struct sockaddr_storage addr
1013 #else
1014         struct sockaddr_in addr
1015 #endif
1016 , char *address, socklen_t size)
1017 {
1018 #ifdef INET6
1019 	if (addr.ss_family == AF_INET6) {
1020 		if (!inet_ntop(AF_INET6,
1021 			&((struct sockaddr_in6 *)&addr)->sin6_addr,
1022 			address, size))
1023 			return (1);
1024 #else
1025 	if (0) {
1026 #endif
1027 	} else {
1028 		if (!inet_ntop(AF_INET,
1029 			&((struct sockaddr_in *)&addr)->sin_addr,
1030 			address, size))
1031 			return (1);
1032 	}
1033 
1034 	return (0);
1035 }
1036