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