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