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