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