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