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