1 /* 2 * zonec.c -- zone compiler. 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 <fcntl.h> 14 #include <ctype.h> 15 #include <errno.h> 16 #include <limits.h> 17 #include <stdio.h> 18 #include <string.h> 19 #ifdef HAVE_STRINGS_H 20 #include <strings.h> 21 #endif 22 #include <unistd.h> 23 #include <stdlib.h> 24 #include <time.h> 25 26 #include <netinet/in.h> 27 28 #ifdef HAVE_NETDB_H 29 #include <netdb.h> 30 #endif 31 32 #include "zonec.h" 33 34 #include "dname.h" 35 #include "dns.h" 36 #include "namedb.h" 37 #include "rdata.h" 38 #include "region-allocator.h" 39 #include "util.h" 40 #include "zparser.h" 41 #include "options.h" 42 #include "nsec3.h" 43 44 const dname_type *error_dname; 45 domain_type *error_domain; 46 47 /* The database file... */ 48 static const char *dbfile = 0; 49 50 /* Some global flags... */ 51 static int vflag = 0; 52 /* if -v then print progress each 'progress' RRs */ 53 static int progress = 10000; 54 55 /* Total errors counter */ 56 static long int totalerrors = 0; 57 static long int totalrrs = 0; 58 59 extern uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE]; 60 extern uint16_t nsec_highest_rcode; 61 62 63 /* 64 * Allocate SIZE+sizeof(uint16_t) bytes and store SIZE in the first 65 * element. Return a pointer to the allocation. 66 */ 67 static uint16_t * 68 alloc_rdata(region_type *region, size_t size) 69 { 70 uint16_t *result = region_alloc(region, sizeof(uint16_t) + size); 71 *result = size; 72 return result; 73 } 74 75 uint16_t * 76 alloc_rdata_init(region_type *region, const void *data, size_t size) 77 { 78 uint16_t *result = region_alloc(region, sizeof(uint16_t) + size); 79 *result = size; 80 memcpy(result + 1, data, size); 81 return result; 82 } 83 84 /* 85 * These are parser function for generic zone file stuff. 86 */ 87 uint16_t * 88 zparser_conv_hex(region_type *region, const char *hex, size_t len) 89 { 90 /* convert a hex value to wireformat */ 91 uint16_t *r = NULL; 92 uint8_t *t; 93 int i; 94 95 if (len % 2 != 0) { 96 zc_error_prev_line("number of hex digits must be a multiple of 2"); 97 } else if (len > MAX_RDLENGTH * 2) { 98 zc_error_prev_line("hex data exceeds maximum rdata length (%d)", 99 MAX_RDLENGTH); 100 } else { 101 /* the length part */ 102 r = alloc_rdata(region, len/2); 103 t = (uint8_t *)(r + 1); 104 105 /* Now process octet by octet... */ 106 while (*hex) { 107 *t = 0; 108 for (i = 16; i >= 1; i -= 15) { 109 if (isxdigit((int)*hex)) { 110 *t += hexdigit_to_int(*hex) * i; 111 } else { 112 zc_error_prev_line( 113 "illegal hex character '%c'", 114 (int) *hex); 115 return NULL; 116 } 117 ++hex; 118 } 119 ++t; 120 } 121 } 122 return r; 123 } 124 125 /* convert hex, precede by a 1-byte length */ 126 uint16_t * 127 zparser_conv_hex_length(region_type *region, const char *hex, size_t len) 128 { 129 uint16_t *r = NULL; 130 uint8_t *t; 131 int i; 132 if (len % 2 != 0) { 133 zc_error_prev_line("number of hex digits must be a multiple of 2"); 134 } else if (len > 255 * 2) { 135 zc_error_prev_line("hex data exceeds 255 bytes"); 136 } else { 137 uint8_t *l; 138 139 /* the length part */ 140 r = alloc_rdata(region, len/2+1); 141 t = (uint8_t *)(r + 1); 142 143 l = t++; 144 *l = '\0'; 145 146 /* Now process octet by octet... */ 147 while (*hex) { 148 *t = 0; 149 for (i = 16; i >= 1; i -= 15) { 150 if (isxdigit((int)*hex)) { 151 *t += hexdigit_to_int(*hex) * i; 152 } else { 153 zc_error_prev_line( 154 "illegal hex character '%c'", 155 (int) *hex); 156 return NULL; 157 } 158 ++hex; 159 } 160 ++t; 161 ++*l; 162 } 163 } 164 return r; 165 } 166 167 uint16_t * 168 zparser_conv_time(region_type *region, const char *time) 169 { 170 /* convert a time YYHM to wireformat */ 171 uint16_t *r = NULL; 172 struct tm tm; 173 174 /* Try to scan the time... */ 175 if (!strptime(time, "%Y%m%d%H%M%S", &tm)) { 176 zc_error_prev_line("date and time is expected"); 177 } else { 178 uint32_t l = htonl(mktime_from_utc(&tm)); 179 r = alloc_rdata_init(region, &l, sizeof(l)); 180 } 181 return r; 182 } 183 184 uint16_t * 185 zparser_conv_services(region_type *region, const char *protostr, 186 char *servicestr) 187 { 188 /* 189 * Convert a protocol and a list of service port numbers 190 * (separated by spaces) in the rdata to wireformat 191 */ 192 uint16_t *r = NULL; 193 uint8_t *p; 194 uint8_t bitmap[65536/8]; 195 char sep[] = " "; 196 char *word; 197 int max_port = -8; 198 /* convert a protocol in the rdata to wireformat */ 199 struct protoent *proto; 200 201 memset(bitmap, 0, sizeof(bitmap)); 202 203 proto = getprotobyname(protostr); 204 if (!proto) { 205 proto = getprotobynumber(atoi(protostr)); 206 } 207 if (!proto) { 208 zc_error_prev_line("unknown protocol '%s'", protostr); 209 return NULL; 210 } 211 212 for (word = strtok(servicestr, sep); word; word = strtok(NULL, sep)) { 213 struct servent *service; 214 int port; 215 216 service = getservbyname(word, proto->p_name); 217 if (service) { 218 /* Note: ntohs not ntohl! Strange but true. */ 219 port = ntohs((uint16_t) service->s_port); 220 } else { 221 char *end; 222 port = strtol(word, &end, 10); 223 if (*end != '\0') { 224 zc_error_prev_line("unknown service '%s' for protocol '%s'", 225 word, protostr); 226 continue; 227 } 228 } 229 230 if (port < 0 || port > 65535) { 231 zc_error_prev_line("bad port number %d", port); 232 } else { 233 set_bit(bitmap, port); 234 if (port > max_port) 235 max_port = port; 236 } 237 } 238 239 r = alloc_rdata(region, sizeof(uint8_t) + max_port / 8 + 1); 240 p = (uint8_t *) (r + 1); 241 *p = proto->p_proto; 242 memcpy(p + 1, bitmap, *r); 243 244 return r; 245 } 246 247 uint16_t * 248 zparser_conv_serial(region_type *region, const char *serialstr) 249 { 250 uint16_t *r = NULL; 251 uint32_t serial; 252 const char *t; 253 254 serial = strtoserial(serialstr, &t); 255 if (*t != '\0') { 256 zc_error_prev_line("serial is expected"); 257 } else { 258 serial = htonl(serial); 259 r = alloc_rdata_init(region, &serial, sizeof(serial)); 260 } 261 return r; 262 } 263 264 uint16_t * 265 zparser_conv_period(region_type *region, const char *periodstr) 266 { 267 /* convert a time period (think TTL's) to wireformat) */ 268 uint16_t *r = NULL; 269 uint32_t period; 270 const char *end; 271 272 /* Allocate required space... */ 273 period = strtottl(periodstr, &end); 274 if (*end != '\0') { 275 zc_error_prev_line("time period is expected"); 276 } else { 277 period = htonl(period); 278 r = alloc_rdata_init(region, &period, sizeof(period)); 279 } 280 return r; 281 } 282 283 uint16_t * 284 zparser_conv_short(region_type *region, const char *text) 285 { 286 uint16_t *r = NULL; 287 uint16_t value; 288 char *end; 289 290 value = htons((uint16_t) strtol(text, &end, 10)); 291 if (*end != '\0') { 292 zc_error_prev_line("integer value is expected"); 293 } else { 294 r = alloc_rdata_init(region, &value, sizeof(value)); 295 } 296 return r; 297 } 298 299 uint16_t * 300 zparser_conv_byte(region_type *region, const char *text) 301 { 302 uint16_t *r = NULL; 303 uint8_t value; 304 char *end; 305 306 value = (uint8_t) strtol(text, &end, 10); 307 if (*end != '\0') { 308 zc_error_prev_line("integer value is expected"); 309 } else { 310 r = alloc_rdata_init(region, &value, sizeof(value)); 311 } 312 return r; 313 } 314 315 uint16_t * 316 zparser_conv_algorithm(region_type *region, const char *text) 317 { 318 const lookup_table_type *alg; 319 uint8_t id; 320 321 alg = lookup_by_name(dns_algorithms, text); 322 if (alg) { 323 id = (uint8_t) alg->id; 324 } else { 325 char *end; 326 id = (uint8_t) strtol(text, &end, 10); 327 if (*end != '\0') { 328 zc_error_prev_line("algorithm is expected"); 329 return NULL; 330 } 331 } 332 333 return alloc_rdata_init(region, &id, sizeof(id)); 334 } 335 336 uint16_t * 337 zparser_conv_certificate_type(region_type *region, const char *text) 338 { 339 /* convert a algoritm string to integer */ 340 const lookup_table_type *type; 341 uint16_t id; 342 343 type = lookup_by_name(dns_certificate_types, text); 344 if (type) { 345 id = htons((uint16_t) type->id); 346 } else { 347 char *end; 348 id = htons((uint16_t) strtol(text, &end, 10)); 349 if (*end != '\0') { 350 zc_error_prev_line("certificate type is expected"); 351 return NULL; 352 } 353 } 354 355 return alloc_rdata_init(region, &id, sizeof(id)); 356 } 357 358 uint16_t * 359 zparser_conv_a(region_type *region, const char *text) 360 { 361 in_addr_t address; 362 uint16_t *r = NULL; 363 364 if (inet_pton(AF_INET, text, &address) != 1) { 365 zc_error_prev_line("invalid IPv4 address '%s'", text); 366 } else { 367 r = alloc_rdata_init(region, &address, sizeof(address)); 368 } 369 return r; 370 } 371 372 uint16_t * 373 zparser_conv_aaaa(region_type *region, const char *text) 374 { 375 uint8_t address[IP6ADDRLEN]; 376 uint16_t *r = NULL; 377 378 if (inet_pton(AF_INET6, text, address) != 1) { 379 zc_error_prev_line("invalid IPv6 address '%s'", text); 380 } else { 381 r = alloc_rdata_init(region, address, sizeof(address)); 382 } 383 return r; 384 } 385 386 uint16_t * 387 zparser_conv_text(region_type *region, const char *text, size_t len) 388 { 389 uint16_t *r = NULL; 390 391 if (len > 255) { 392 zc_error_prev_line("text string is longer than 255 characters," 393 " try splitting it into multiple parts"); 394 } else { 395 uint8_t *p; 396 r = alloc_rdata(region, len + 1); 397 p = (uint8_t *) (r + 1); 398 *p = len; 399 memcpy(p + 1, text, len); 400 } 401 return r; 402 } 403 404 uint16_t * 405 zparser_conv_dns_name(region_type *region, const uint8_t* name, size_t len) 406 { 407 uint16_t* r = NULL; 408 uint8_t* p = NULL; 409 r = alloc_rdata(region, len); 410 p = (uint8_t *) (r + 1); 411 memcpy(p, name, len); 412 413 return r; 414 } 415 416 uint16_t * 417 zparser_conv_b32(region_type *region, const char *b32) 418 { 419 uint8_t buffer[B64BUFSIZE]; 420 uint16_t *r = NULL; 421 int i; 422 423 if(strcmp(b32, "-") == 0) { 424 return alloc_rdata_init(region, "", 1); 425 } 426 i = b32_pton(b32, buffer+1, B64BUFSIZE-1); 427 if (i == -1 || i > 255) { 428 zc_error_prev_line("invalid base32 data"); 429 } else { 430 buffer[0] = i; /* store length byte */ 431 r = alloc_rdata_init(region, buffer, i+1); 432 } 433 return r; 434 } 435 436 uint16_t * 437 zparser_conv_b64(region_type *region, const char *b64) 438 { 439 uint8_t buffer[B64BUFSIZE]; 440 uint16_t *r = NULL; 441 int i; 442 443 i = b64_pton(b64, buffer, B64BUFSIZE); 444 if (i == -1) { 445 zc_error_prev_line("invalid base64 data"); 446 } else { 447 r = alloc_rdata_init(region, buffer, i); 448 } 449 return r; 450 } 451 452 uint16_t * 453 zparser_conv_rrtype(region_type *region, const char *text) 454 { 455 uint16_t *r = NULL; 456 uint16_t type = rrtype_from_string(text); 457 458 if (type == 0) { 459 zc_error_prev_line("unrecognized RR type '%s'", text); 460 } else { 461 type = htons(type); 462 r = alloc_rdata_init(region, &type, sizeof(type)); 463 } 464 return r; 465 } 466 467 uint16_t * 468 zparser_conv_nxt(region_type *region, uint8_t nxtbits[]) 469 { 470 /* nxtbits[] consists of 16 bytes with some zero's in it 471 * copy every byte with zero to r and write the length in 472 * the first byte 473 */ 474 uint16_t i; 475 uint16_t last = 0; 476 477 for (i = 0; i < 16; i++) { 478 if (nxtbits[i] != 0) 479 last = i + 1; 480 } 481 482 return alloc_rdata_init(region, nxtbits, last); 483 } 484 485 486 /* we potentially have 256 windows, each one is numbered. empty ones 487 * should be discarded 488 */ 489 uint16_t * 490 zparser_conv_nsec(region_type *region, 491 uint8_t nsecbits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE]) 492 { 493 /* nsecbits contains up to 64K of bits which represent the 494 * types available for a name. Walk the bits according to 495 * nsec++ draft from jakob 496 */ 497 uint16_t *r; 498 uint8_t *ptr; 499 size_t i,j; 500 uint16_t window_count = 0; 501 uint16_t total_size = 0; 502 uint16_t window_max = 0; 503 504 /* The used windows. */ 505 int used[NSEC_WINDOW_COUNT]; 506 /* The last byte used in each the window. */ 507 int size[NSEC_WINDOW_COUNT]; 508 509 window_max = 1 + (nsec_highest_rcode / 256); 510 511 /* used[i] is the i-th window included in the nsec 512 * size[used[0]] is the size of window 0 513 */ 514 515 /* walk through the 256 windows */ 516 for (i = 0; i < window_max; ++i) { 517 int empty_window = 1; 518 /* check each of the 32 bytes */ 519 for (j = 0; j < NSEC_WINDOW_BITS_SIZE; ++j) { 520 if (nsecbits[i][j] != 0) { 521 size[i] = j + 1; 522 empty_window = 0; 523 } 524 } 525 if (!empty_window) { 526 used[window_count] = i; 527 window_count++; 528 } 529 } 530 531 for (i = 0; i < window_count; ++i) { 532 total_size += sizeof(uint16_t) + size[used[i]]; 533 } 534 535 r = alloc_rdata(region, total_size); 536 ptr = (uint8_t *) (r + 1); 537 538 /* now walk used and copy it */ 539 for (i = 0; i < window_count; ++i) { 540 ptr[0] = used[i]; 541 ptr[1] = size[used[i]]; 542 memcpy(ptr + 2, &nsecbits[used[i]], size[used[i]]); 543 ptr += size[used[i]] + 2; 544 } 545 546 return r; 547 } 548 549 /* Parse an int terminated in the specified range. */ 550 static int 551 parse_int(const char *str, 552 char **end, 553 int *result, 554 const char *name, 555 int min, 556 int max) 557 { 558 *result = (int) strtol(str, end, 10); 559 if (*result < min || *result > max) { 560 zc_error_prev_line("%s must be within the range [%d .. %d]", 561 name, 562 min, 563 max); 564 return 0; 565 } else { 566 return 1; 567 } 568 } 569 570 /* RFC1876 conversion routines */ 571 static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000, 572 1000000,10000000,100000000,1000000000}; 573 574 /* 575 * Converts ascii size/precision X * 10**Y(cm) to 0xXY. 576 * Sets the given pointer to the last used character. 577 * 578 */ 579 static uint8_t 580 precsize_aton (char *cp, char **endptr) 581 { 582 unsigned int mval = 0, cmval = 0; 583 uint8_t retval = 0; 584 int exponent; 585 int mantissa; 586 587 while (isdigit((int)*cp)) 588 mval = mval * 10 + hexdigit_to_int(*cp++); 589 590 if (*cp == '.') { /* centimeters */ 591 cp++; 592 if (isdigit((int)*cp)) { 593 cmval = hexdigit_to_int(*cp++) * 10; 594 if (isdigit((int)*cp)) { 595 cmval += hexdigit_to_int(*cp++); 596 } 597 } 598 } 599 600 if(mval >= poweroften[7]) { 601 /* integer overflow possible for *100 */ 602 mantissa = mval / poweroften[7]; 603 exponent = 9; /* max */ 604 } 605 else { 606 cmval = (mval * 100) + cmval; 607 608 for (exponent = 0; exponent < 9; exponent++) 609 if (cmval < poweroften[exponent+1]) 610 break; 611 612 mantissa = cmval / poweroften[exponent]; 613 } 614 if (mantissa > 9) 615 mantissa = 9; 616 617 retval = (mantissa << 4) | exponent; 618 619 if (*cp == 'm') cp++; 620 621 *endptr = cp; 622 623 return (retval); 624 } 625 626 /* 627 * Parses a specific part of rdata. 628 * 629 * Returns: 630 * 631 * number of elements parsed 632 * zero on error 633 * 634 */ 635 uint16_t * 636 zparser_conv_loc(region_type *region, char *str) 637 { 638 uint16_t *r; 639 uint32_t *p; 640 int i; 641 int deg, min, secs; /* Secs is stored times 1000. */ 642 uint32_t lat = 0, lon = 0, alt = 0; 643 /* encoded defaults: version=0 sz=1m hp=10000m vp=10m */ 644 uint8_t vszhpvp[4] = {0, 0x12, 0x16, 0x13}; 645 char *start; 646 double d; 647 648 for(;;) { 649 deg = min = secs = 0; 650 651 /* Degrees */ 652 if (*str == '\0') { 653 zc_error_prev_line("unexpected end of LOC data"); 654 return NULL; 655 } 656 657 if (!parse_int(str, &str, °, "degrees", 0, 180)) 658 return NULL; 659 if (!isspace((int)*str)) { 660 zc_error_prev_line("space expected after degrees"); 661 return NULL; 662 } 663 ++str; 664 665 /* Minutes? */ 666 if (isdigit((int)*str)) { 667 if (!parse_int(str, &str, &min, "minutes", 0, 60)) 668 return NULL; 669 if (!isspace((int)*str)) { 670 zc_error_prev_line("space expected after minutes"); 671 return NULL; 672 } 673 ++str; 674 } 675 676 /* Seconds? */ 677 if (isdigit((int)*str)) { 678 start = str; 679 if (!parse_int(str, &str, &i, "seconds", 0, 60)) { 680 return NULL; 681 } 682 683 if (*str == '.' && !parse_int(str + 1, &str, &i, "seconds fraction", 0, 999)) { 684 return NULL; 685 } 686 687 if (!isspace((int)*str)) { 688 zc_error_prev_line("space expected after seconds"); 689 return NULL; 690 } 691 692 if (sscanf(start, "%lf", &d) != 1) { 693 zc_error_prev_line("error parsing seconds"); 694 } 695 696 if (d < 0.0 || d > 60.0) { 697 zc_error_prev_line("seconds not in range 0.0 .. 60.0"); 698 } 699 700 secs = (int) (d * 1000.0 + 0.5); 701 ++str; 702 } 703 704 switch(*str) { 705 case 'N': 706 case 'n': 707 lat = ((uint32_t)1<<31) + (deg * 3600000 + min * 60000 + secs); 708 break; 709 case 'E': 710 case 'e': 711 lon = ((uint32_t)1<<31) + (deg * 3600000 + min * 60000 + secs); 712 break; 713 case 'S': 714 case 's': 715 lat = ((uint32_t)1<<31) - (deg * 3600000 + min * 60000 + secs); 716 break; 717 case 'W': 718 case 'w': 719 lon = ((uint32_t)1<<31) - (deg * 3600000 + min * 60000 + secs); 720 break; 721 default: 722 zc_error_prev_line("invalid latitude/longtitude: '%c'", *str); 723 return NULL; 724 } 725 ++str; 726 727 if (lat != 0 && lon != 0) 728 break; 729 730 if (!isspace((int)*str)) { 731 zc_error_prev_line("space expected after latitude/longitude"); 732 return NULL; 733 } 734 ++str; 735 } 736 737 /* Altitude */ 738 if (*str == '\0') { 739 zc_error_prev_line("unexpected end of LOC data"); 740 return NULL; 741 } 742 743 if (!isspace((int)*str)) { 744 zc_error_prev_line("space expected before altitude"); 745 return NULL; 746 } 747 ++str; 748 749 start = str; 750 751 /* Sign */ 752 if (*str == '+' || *str == '-') { 753 ++str; 754 } 755 756 /* Meters of altitude... */ 757 (void) strtol(str, &str, 10); 758 switch(*str) { 759 case ' ': 760 case '\0': 761 case 'm': 762 break; 763 case '.': 764 if (!parse_int(str + 1, &str, &i, "altitude fraction", 0, 99)) { 765 return NULL; 766 } 767 if (!isspace((int)*str) && *str != '\0' && *str != 'm') { 768 zc_error_prev_line("altitude fraction must be a number"); 769 return NULL; 770 } 771 break; 772 default: 773 zc_error_prev_line("altitude must be expressed in meters"); 774 return NULL; 775 } 776 if (!isspace((int)*str) && *str != '\0') 777 ++str; 778 779 if (sscanf(start, "%lf", &d) != 1) { 780 zc_error_prev_line("error parsing altitude"); 781 } 782 783 alt = (uint32_t) (10000000.0 + d * 100 + 0.5); 784 785 if (!isspace((int)*str) && *str != '\0') { 786 zc_error_prev_line("unexpected character after altitude"); 787 return NULL; 788 } 789 790 /* Now parse size, horizontal precision and vertical precision if any */ 791 for(i = 1; isspace((int)*str) && i <= 3; i++) { 792 vszhpvp[i] = precsize_aton(str + 1, &str); 793 794 if (!isspace((int)*str) && *str != '\0') { 795 zc_error_prev_line("invalid size or precision"); 796 return NULL; 797 } 798 } 799 800 /* Allocate required space... */ 801 r = alloc_rdata(region, 16); 802 p = (uint32_t *) (r + 1); 803 804 memmove(p, vszhpvp, 4); 805 write_uint32(p + 1, lat); 806 write_uint32(p + 2, lon); 807 write_uint32(p + 3, alt); 808 809 return r; 810 } 811 812 /* 813 * Convert an APL RR RDATA element. 814 */ 815 uint16_t * 816 zparser_conv_apl_rdata(region_type *region, char *str) 817 { 818 int negated = 0; 819 uint16_t address_family; 820 uint8_t prefix; 821 uint8_t maximum_prefix; 822 uint8_t length; 823 uint8_t address[IP6ADDRLEN]; 824 char *colon = strchr(str, ':'); 825 char *slash = strchr(str, '/'); 826 int af; 827 int rc; 828 uint16_t rdlength; 829 uint16_t *r; 830 uint8_t *t; 831 char *end; 832 long p; 833 834 if (!colon) { 835 zc_error("address family separator is missing"); 836 return NULL; 837 } 838 if (!slash) { 839 zc_error("prefix separator is missing"); 840 return NULL; 841 } 842 843 *colon = '\0'; 844 *slash = '\0'; 845 846 if (*str == '!') { 847 negated = 1; 848 ++str; 849 } 850 851 if (strcmp(str, "1") == 0) { 852 address_family = htons(1); 853 af = AF_INET; 854 length = sizeof(in_addr_t); 855 maximum_prefix = length * 8; 856 } else if (strcmp(str, "2") == 0) { 857 address_family = htons(2); 858 af = AF_INET6; 859 length = IP6ADDRLEN; 860 maximum_prefix = length * 8; 861 } else { 862 zc_error("invalid address family '%s'", str); 863 return NULL; 864 } 865 866 rc = inet_pton(af, colon + 1, address); 867 if (rc == 0) { 868 zc_error("invalid address '%s'", colon + 1); 869 return NULL; 870 } else if (rc == -1) { 871 zc_error("inet_pton failed: %s", strerror(errno)); 872 return NULL; 873 } 874 875 /* Strip trailing zero octets. */ 876 while (length > 0 && address[length - 1] == 0) 877 --length; 878 879 880 p = strtol(slash + 1, &end, 10); 881 if (p < 0 || p > maximum_prefix) { 882 zc_error("prefix not in the range 0 .. %d", maximum_prefix); 883 return NULL; 884 } else if (*end != '\0') { 885 zc_error("invalid prefix '%s'", slash + 1); 886 return NULL; 887 } 888 prefix = (uint8_t) p; 889 890 rdlength = (sizeof(address_family) + sizeof(prefix) + sizeof(length) 891 + length); 892 r = alloc_rdata(region, rdlength); 893 t = (uint8_t *) (r + 1); 894 895 memcpy(t, &address_family, sizeof(address_family)); 896 t += sizeof(address_family); 897 memcpy(t, &prefix, sizeof(prefix)); 898 t += sizeof(prefix); 899 memcpy(t, &length, sizeof(length)); 900 if (negated) { 901 *t |= APL_NEGATION_MASK; 902 } 903 t += sizeof(length); 904 memcpy(t, address, length); 905 906 return r; 907 } 908 909 /* 910 * Below some function that also convert but not to wireformat 911 * but to "normal" (int,long,char) types 912 */ 913 914 uint32_t 915 zparser_ttl2int(const char *ttlstr, int* error) 916 { 917 /* convert a ttl value to a integer 918 * return the ttl in a int 919 * -1 on error 920 */ 921 922 uint32_t ttl; 923 const char *t; 924 925 ttl = strtottl(ttlstr, &t); 926 if (*t != 0) { 927 zc_error_prev_line("invalid TTL value: %s",ttlstr); 928 *error = 1; 929 } 930 931 return ttl; 932 } 933 934 935 void 936 zadd_rdata_wireformat(uint16_t *data) 937 { 938 if (parser->current_rr.rdata_count >= MAXRDATALEN) { 939 zc_error_prev_line("too many rdata elements"); 940 } else { 941 parser->current_rr.rdatas[parser->current_rr.rdata_count].data 942 = data; 943 ++parser->current_rr.rdata_count; 944 } 945 } 946 947 /** 948 * Used for TXT RR's to grow with undefined number of strings. 949 */ 950 void 951 zadd_rdata_txt_wireformat(uint16_t *data, int first) 952 { 953 rdata_atom_type *rd; 954 955 /* First STR in str_seq, allocate 65K in first unused rdata 956 * else find last used rdata */ 957 if (first) { 958 rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count]; 959 if ((rd->data = (uint16_t *) region_alloc(parser->rr_region, 960 sizeof(uint16_t) + 65535 * sizeof(uint8_t))) == NULL) { 961 zc_error_prev_line("Could not allocate memory for TXT RR"); 962 return; 963 } 964 parser->current_rr.rdata_count++; 965 rd->data[0] = 0; 966 } 967 else 968 rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1]; 969 970 if ((size_t)rd->data[0] + (size_t)data[0] > 65535) { 971 zc_error_prev_line("too large rdata element"); 972 return; 973 } 974 975 memcpy((uint8_t *)rd->data + 2 + rd->data[0], data + 1, data[0]); 976 rd->data[0] += data[0]; 977 } 978 979 /** 980 * Clean up after last call of zadd_rdata_txt_wireformat 981 */ 982 void 983 zadd_rdata_txt_clean_wireformat() 984 { 985 uint16_t *tmp_data; 986 rdata_atom_type *rd = &parser->current_rr.rdatas[parser->current_rr.rdata_count-1]; 987 if ((tmp_data = (uint16_t *) region_alloc(parser->region, 988 rd->data[0] + 2)) != NULL) { 989 memcpy(tmp_data, rd->data, rd->data[0] + 2); 990 rd->data = tmp_data; 991 } 992 else { 993 /* We could not get memory in non-volatile region */ 994 zc_error_prev_line("could not allocate memory for rdata"); 995 return; 996 } 997 } 998 999 void 1000 zadd_rdata_domain(domain_type *domain) 1001 { 1002 if (parser->current_rr.rdata_count >= MAXRDATALEN) { 1003 zc_error_prev_line("too many rdata elements"); 1004 } else { 1005 parser->current_rr.rdatas[parser->current_rr.rdata_count].domain 1006 = domain; 1007 ++parser->current_rr.rdata_count; 1008 } 1009 } 1010 1011 void 1012 parse_unknown_rdata(uint16_t type, uint16_t *wireformat) 1013 { 1014 buffer_type packet; 1015 uint16_t size; 1016 ssize_t rdata_count; 1017 ssize_t i; 1018 rdata_atom_type *rdatas; 1019 1020 if (wireformat) { 1021 size = *wireformat; 1022 } else { 1023 return; 1024 } 1025 1026 buffer_create_from(&packet, wireformat + 1, *wireformat); 1027 rdata_count = rdata_wireformat_to_rdata_atoms(parser->region, 1028 parser->db->domains, 1029 type, 1030 size, 1031 &packet, 1032 &rdatas); 1033 if (rdata_count == -1) { 1034 zc_error_prev_line("bad unknown RDATA"); 1035 return; 1036 } 1037 1038 for (i = 0; i < rdata_count; ++i) { 1039 if (rdata_atom_is_domain(type, i)) { 1040 zadd_rdata_domain(rdatas[i].domain); 1041 } else { 1042 zadd_rdata_wireformat(rdatas[i].data); 1043 } 1044 } 1045 } 1046 1047 1048 /* 1049 * Compares two rdata arrays. 1050 * 1051 * Returns: 1052 * 1053 * zero if they are equal 1054 * non-zero if not 1055 * 1056 */ 1057 static int 1058 zrdatacmp(uint16_t type, rr_type *a, rr_type *b) 1059 { 1060 int i = 0; 1061 1062 assert(a); 1063 assert(b); 1064 1065 /* One is shorter than another */ 1066 if (a->rdata_count != b->rdata_count) 1067 return 1; 1068 1069 /* Compare element by element */ 1070 for (i = 0; i < a->rdata_count; ++i) { 1071 if (rdata_atom_is_domain(type, i)) { 1072 if (rdata_atom_domain(a->rdatas[i]) 1073 != rdata_atom_domain(b->rdatas[i])) 1074 { 1075 return 1; 1076 } 1077 } else { 1078 if (rdata_atom_size(a->rdatas[i]) 1079 != rdata_atom_size(b->rdatas[i])) 1080 { 1081 return 1; 1082 } 1083 if (memcmp(rdata_atom_data(a->rdatas[i]), 1084 rdata_atom_data(b->rdatas[i]), 1085 rdata_atom_size(a->rdatas[i])) != 0) 1086 { 1087 return 1; 1088 } 1089 } 1090 } 1091 1092 /* Otherwise they are equal */ 1093 return 0; 1094 } 1095 1096 /* 1097 * 1098 * Opens a zone file. 1099 * 1100 * Returns: 1101 * 1102 * - pointer to the parser structure 1103 * - NULL on error and errno set 1104 * 1105 */ 1106 static int 1107 zone_open(const char *filename, uint32_t ttl, uint16_t klass, 1108 const dname_type *origin) 1109 { 1110 /* Open the zone file... */ 1111 if (strcmp(filename, "-") == 0) { 1112 yyin = stdin; 1113 filename = "<stdin>"; 1114 } else if (!(yyin = fopen(filename, "r"))) { 1115 return 0; 1116 } 1117 1118 /* Open the network database */ 1119 setprotoent(1); 1120 setservent(1); 1121 1122 zparser_init(filename, ttl, klass, origin); 1123 1124 return 1; 1125 } 1126 1127 1128 void 1129 set_bitnsec(uint8_t bits[NSEC_WINDOW_COUNT][NSEC_WINDOW_BITS_SIZE], 1130 uint16_t index) 1131 { 1132 /* 1133 * The bits are counted from left to right, so bit #0 is the 1134 * left most bit. 1135 */ 1136 uint8_t window = index / 256; 1137 uint8_t bit = index % 256; 1138 1139 bits[window][bit / 8] |= (1 << (7 - bit % 8)); 1140 } 1141 1142 1143 static void 1144 cleanup_rrset(void *r) 1145 { 1146 rrset_type *rrset = (rrset_type *) r; 1147 if (rrset) { 1148 free(rrset->rrs); 1149 } 1150 } 1151 1152 int 1153 process_rr(void) 1154 { 1155 zone_type *zone = parser->current_zone; 1156 rr_type *rr = &parser->current_rr; 1157 rrset_type *rrset; 1158 size_t max_rdlength; 1159 int i; 1160 rrtype_descriptor_type *descriptor 1161 = rrtype_descriptor_by_type(rr->type); 1162 1163 /* We only support IN class */ 1164 if (rr->klass != CLASS_IN) { 1165 if(zone->opts && zone->opts->request_xfr) 1166 zc_warning_prev_line("only class IN is supported"); 1167 else 1168 zc_error_prev_line("only class IN is supported"); 1169 return 0; 1170 } 1171 1172 /* Make sure the maximum RDLENGTH does not exceed 65535 bytes. */ 1173 max_rdlength = rdata_maximum_wireformat_size( 1174 descriptor, rr->rdata_count, rr->rdatas); 1175 1176 if (max_rdlength > MAX_RDLENGTH) { 1177 zc_error_prev_line("maximum rdata length exceeds %d octets", MAX_RDLENGTH); 1178 return 0; 1179 } 1180 1181 /* Do we have the zone already? */ 1182 if (!zone) 1183 { 1184 zone = (zone_type *) region_alloc(parser->region, 1185 sizeof(zone_type)); 1186 zone->apex = parser->default_apex; 1187 zone->soa_rrset = NULL; 1188 zone->soa_nx_rrset = NULL; 1189 zone->ns_rrset = NULL; 1190 zone->opts = NULL; 1191 zone->is_secure = 0; 1192 zone->updated = 1; 1193 1194 zone->next = parser->db->zones; 1195 parser->db->zones = zone; 1196 parser->current_zone = zone; 1197 } 1198 1199 if (rr->type == TYPE_SOA) { 1200 /* 1201 * This is a SOA record, start a new zone or continue 1202 * an existing one. 1203 */ 1204 if (rr->owner->is_apex) { 1205 if(zone->opts && zone->opts->request_xfr) 1206 zc_warning_prev_line("this SOA record was already encountered"); 1207 else 1208 zc_error_prev_line("this SOA record was already encountered"); 1209 } else if (rr->owner == parser->default_apex) { 1210 zone->apex = rr->owner; 1211 rr->owner->is_apex = 1; 1212 } 1213 1214 /* parser part */ 1215 parser->current_zone = zone; 1216 } 1217 1218 if (!dname_is_subdomain(domain_dname(rr->owner), 1219 domain_dname(zone->apex))) 1220 { 1221 if(zone->opts && zone->opts->request_xfr) 1222 zc_warning_prev_line("out of zone data"); 1223 else 1224 zc_error_prev_line("out of zone data"); 1225 return 0; 1226 } 1227 1228 /* Do we have this type of rrset already? */ 1229 rrset = domain_find_rrset(rr->owner, zone, rr->type); 1230 if (!rrset) { 1231 rrset = (rrset_type *) region_alloc(parser->region, 1232 sizeof(rrset_type)); 1233 rrset->zone = zone; 1234 rrset->rr_count = 1; 1235 rrset->rrs = (rr_type *) xalloc(sizeof(rr_type)); 1236 rrset->rrs[0] = *rr; 1237 1238 region_add_cleanup(parser->region, cleanup_rrset, rrset); 1239 1240 /* Add it */ 1241 domain_add_rrset(rr->owner, rrset); 1242 } else { 1243 if (rr->type != TYPE_RRSIG && rrset->rrs[0].ttl != rr->ttl) { 1244 zc_warning_prev_line( 1245 "TTL does not match the TTL of the RRset"); 1246 } 1247 1248 /* Search for possible duplicates... */ 1249 for (i = 0; i < rrset->rr_count; i++) { 1250 if (!zrdatacmp(rr->type, rr, &rrset->rrs[i])) { 1251 break; 1252 } 1253 } 1254 1255 /* Discard the duplicates... */ 1256 if (i < rrset->rr_count) { 1257 return 0; 1258 } 1259 1260 /* Add it... */ 1261 rrset->rrs = (rr_type *) xrealloc( 1262 rrset->rrs, 1263 (rrset->rr_count + 1) * sizeof(rr_type)); 1264 rrset->rrs[rrset->rr_count] = *rr; 1265 ++rrset->rr_count; 1266 } 1267 1268 if(rr->type == TYPE_DNAME && rrset->rr_count > 1) { 1269 if(zone->opts && zone->opts->request_xfr) 1270 zc_warning_prev_line("multiple DNAMEs at the same name"); 1271 else 1272 zc_error_prev_line("multiple DNAMEs at the same name"); 1273 } 1274 if(rr->type == TYPE_CNAME && rrset->rr_count > 1) { 1275 if(zone->opts && zone->opts->request_xfr) 1276 zc_warning_prev_line("multiple CNAMEs at the same name"); 1277 else 1278 zc_error_prev_line("multiple CNAMEs at the same name"); 1279 } 1280 if((rr->type == TYPE_DNAME && domain_find_rrset(rr->owner, zone, TYPE_CNAME)) 1281 ||(rr->type == TYPE_CNAME && domain_find_rrset(rr->owner, zone, TYPE_DNAME))) { 1282 if(zone->opts && zone->opts->request_xfr) 1283 zc_warning_prev_line("DNAME and CNAME at the same name"); 1284 else 1285 zc_error_prev_line("DNAME and CNAME at the same name"); 1286 } 1287 if(domain_find_rrset(rr->owner, zone, TYPE_CNAME) && 1288 domain_find_non_cname_rrset(rr->owner, zone)) { 1289 if(zone->opts && zone->opts->request_xfr) 1290 zc_warning_prev_line("CNAME and other data at the same name"); 1291 else 1292 zc_error_prev_line("CNAME and other data at the same name"); 1293 } 1294 1295 if (rr->type == TYPE_RRSIG && rr_rrsig_type_covered(rr) == TYPE_DNSKEY) { 1296 rrset->zone->is_secure = 1; 1297 } 1298 1299 /* Check we have SOA */ 1300 if (zone->soa_rrset == NULL) { 1301 if (rr->type == TYPE_SOA) { 1302 if (rr->owner != zone->apex) { 1303 zc_error_prev_line( 1304 "SOA record with invalid domain name"); 1305 } else { 1306 zone->soa_rrset = rrset; 1307 } 1308 } 1309 } 1310 else if (rr->type == TYPE_SOA) { 1311 if(zone->opts && zone->opts->request_xfr) 1312 zc_warning_prev_line("duplicate SOA record discarded"); 1313 else 1314 zc_error_prev_line("duplicate SOA record discarded"); 1315 --rrset->rr_count; 1316 } 1317 1318 /* Is this a zone NS? */ 1319 if (rr->type == TYPE_NS && rr->owner == zone->apex) { 1320 zone->ns_rrset = rrset; 1321 } 1322 if (vflag > 1 && totalrrs > 0 && (totalrrs % progress == 0)) { 1323 fprintf(stdout, "%ld\n", totalrrs); 1324 } 1325 ++totalrrs; 1326 return 1; 1327 } 1328 1329 /* 1330 * Find rrset type for any zone 1331 */ 1332 static rrset_type* 1333 domain_find_rrset_any(domain_type *domain, uint16_t type) 1334 { 1335 rrset_type *result = domain->rrsets; 1336 while (result) { 1337 if (rrset_rrtype(result) == type) { 1338 return result; 1339 } 1340 result = result->next; 1341 } 1342 return NULL; 1343 } 1344 1345 /* 1346 * Check for DNAME type. Nothing is allowed below it 1347 */ 1348 static void 1349 check_dname(namedb_type* db) 1350 { 1351 domain_type* domain; 1352 RBTREE_FOR(domain, domain_type*, db->domains->names_to_domains) 1353 { 1354 if(domain->is_existing) { 1355 /* there may not be DNAMEs above it */ 1356 domain_type* parent = domain->parent; 1357 #ifdef NSEC3 1358 if(domain_has_only_NSEC3(domain, NULL)) 1359 continue; 1360 #endif 1361 while(parent) { 1362 if(domain_find_rrset_any(parent, TYPE_DNAME)) { 1363 zc_error("While checking node %s,", 1364 dname_to_string(domain_dname(domain), NULL)); 1365 zc_error("DNAME at %s has data below it. " 1366 "This is not allowed (rfc 2672).", 1367 dname_to_string(domain_dname(parent), NULL)); 1368 exit(1); 1369 } 1370 parent = parent->parent; 1371 } 1372 } 1373 } 1374 } 1375 1376 /* 1377 * Reads the specified zone into the memory 1378 * nsd_options can be NULL if no config file is passed. 1379 * 1380 */ 1381 static void 1382 zone_read(const char *name, const char *zonefile, nsd_options_t* nsd_options) 1383 { 1384 const dname_type *dname; 1385 1386 dname = dname_parse(parser->region, name); 1387 if (!dname) { 1388 zc_error("incorrect zone name '%s'", name); 1389 return; 1390 } 1391 1392 #ifndef ROOT_SERVER 1393 /* Is it a root zone? Are we a root server then? Idiot proof. */ 1394 if (dname->label_count == 1) { 1395 zc_error("not configured as a root server"); 1396 return; 1397 } 1398 #endif 1399 1400 /* Open the zone file */ 1401 if (!zone_open(zonefile, 3600, CLASS_IN, dname)) { 1402 if(nsd_options) { 1403 /* check for secondary zone, they can start with no zone info */ 1404 zone_options_t* zopt = zone_options_find(nsd_options, dname); 1405 if(zopt && zone_is_slave(zopt)) { 1406 zc_warning("slave zone %s with no zonefile '%s'(%s) will " 1407 "force zone transfer.", 1408 name, zonefile, strerror(errno)); 1409 return; 1410 } 1411 } 1412 /* cannot happen with stdin - so no fix needed for zonefile */ 1413 zc_error("cannot open '%s': %s", zonefile, strerror(errno)); 1414 return; 1415 } 1416 1417 /* Parse and process all RRs. */ 1418 yyparse(); 1419 1420 /* check if zone file contained a correct SOA record */ 1421 if (parser->current_zone && parser->current_zone->soa_rrset 1422 && parser->current_zone->soa_rrset->rr_count!=0) 1423 { 1424 if(dname_compare(domain_dname( 1425 parser->current_zone->soa_rrset->rrs[0].owner), 1426 dname) != 0) { 1427 zc_error("zone configured as '%s', but SOA has owner '%s'.", 1428 name, dname_to_string( 1429 domain_dname(parser->current_zone-> 1430 soa_rrset->rrs[0].owner), NULL)); 1431 } 1432 } 1433 1434 fclose(yyin); 1435 1436 fflush(stdout); 1437 totalerrors += parser->errors; 1438 parser->filename = NULL; 1439 } 1440 1441 static void 1442 usage (void) 1443 { 1444 #ifndef NDEBUG 1445 fprintf(stderr, "usage: nsd-zonec [-v|-h|-C|-F|-L] [-c configfile] [-o origin] [-d directory] [-f database] [-z zonefile]\n\n"); 1446 #else 1447 fprintf(stderr, "usage: nsd-zonec [-v|-h|-C] [-c configfile] [-o origin] [-d directory] [-f database] [-z zonefile]\n\n"); 1448 #endif 1449 fprintf(stderr, "\tNSD zone compiler, creates database from zone files.\n"); 1450 fprintf(stderr, "\tVersion %s. Report bugs to <%s>.\n\n", 1451 PACKAGE_VERSION, PACKAGE_BUGREPORT); 1452 fprintf(stderr, "\t-v\tBe more verbose.\n"); 1453 fprintf(stderr, "\t-h\tPrint this help information.\n"); 1454 fprintf(stderr, "\t-c\tSpecify config file to read instead of default nsd.conf.\n"); 1455 fprintf(stderr, "\t-C\tNo config file is read.\n"); 1456 fprintf(stderr, "\t-d\tSet working directory to open files from.\n"); 1457 fprintf(stderr, "\t-o\tSpecify a zone's origin (only used with -z).\n"); 1458 fprintf(stderr, "\t-f\tSpecify database file to use.\n"); 1459 fprintf(stderr, "\t-z\tSpecify a zonefile to read (read from stdin with \'-\').\n"); 1460 #ifndef NDEBUG 1461 fprintf(stderr, "\t-F\tSet debug facilities.\n"); 1462 fprintf(stderr, "\t-L\tSet debug level.\n"); 1463 #endif 1464 } 1465 1466 extern char *optarg; 1467 extern int optind; 1468 1469 int 1470 main (int argc, char **argv) 1471 { 1472 struct namedb *db; 1473 char *origin = NULL; 1474 int c; 1475 region_type *global_region; 1476 region_type *rr_region; 1477 const char* configfile= CONFIGFILE; 1478 const char* zonesdir = NULL; 1479 const char* singlefile = NULL; 1480 nsd_options_t* nsd_options = NULL; 1481 1482 log_init("nsd-zonec"); 1483 1484 global_region = region_create(xalloc, free); 1485 rr_region = region_create(xalloc, free); 1486 totalerrors = 0; 1487 1488 /* Parse the command line... */ 1489 while ((c = getopt(argc, argv, "d:f:vhCF:L:o:c:z:")) != -1) { 1490 switch (c) { 1491 case 'c': 1492 configfile = optarg; 1493 break; 1494 case 'v': 1495 ++vflag; 1496 break; 1497 case 'f': 1498 dbfile = optarg; 1499 break; 1500 case 'd': 1501 zonesdir = optarg; 1502 break; 1503 case 'C': 1504 configfile = 0; 1505 break; 1506 #ifndef NDEBUG 1507 case 'F': 1508 sscanf(optarg, "%x", &nsd_debug_facilities); 1509 break; 1510 case 'L': 1511 sscanf(optarg, "%d", &nsd_debug_level); 1512 break; 1513 #endif /* NDEBUG */ 1514 case 'o': 1515 origin = optarg; 1516 break; 1517 case 'z': 1518 singlefile = optarg; 1519 break; 1520 case 'h': 1521 usage(); 1522 exit(0); 1523 case '?': 1524 default: 1525 usage(); 1526 exit(1); 1527 } 1528 } 1529 1530 argc -= optind; 1531 argv += optind; 1532 1533 if (argc != 0) { 1534 usage(); 1535 exit(1); 1536 } 1537 1538 /* Read options */ 1539 if(configfile != 0) { 1540 nsd_options = nsd_options_create(global_region); 1541 if(!parse_options_file(nsd_options, configfile)) 1542 { 1543 fprintf(stderr, "nsd-zonec: could not read config: %s\n", configfile); 1544 exit(1); 1545 } 1546 } 1547 if(nsd_options && zonesdir == 0) zonesdir = nsd_options->zonesdir; 1548 if(zonesdir && zonesdir[0]) { 1549 if (chdir(zonesdir)) { 1550 fprintf(stderr, "nsd-zonec: cannot chdir to %s: %s\n", zonesdir, strerror(errno)); 1551 exit(1); 1552 } 1553 } 1554 if(dbfile == 0) { 1555 if(nsd_options && nsd_options->database) dbfile = nsd_options->database; 1556 else dbfile = DBFILE; 1557 } 1558 1559 /* Create the database */ 1560 if ((db = namedb_new(dbfile)) == NULL) { 1561 fprintf(stderr, "nsd-zonec: error creating the database (%s): %s\n", 1562 dbfile, strerror(errno)); 1563 exit(1); 1564 } 1565 1566 parser = zparser_create(global_region, rr_region, db); 1567 if (!parser) { 1568 fprintf(stderr, "nsd-zonec: error creating the parser\n"); 1569 exit(1); 1570 } 1571 1572 /* Unique pointers used to mark errors. */ 1573 error_dname = (dname_type *) region_alloc(global_region, 0); 1574 error_domain = (domain_type *) region_alloc(global_region, 0); 1575 1576 if (singlefile || origin) { 1577 /* 1578 * Read a single zone file with the specified origin 1579 */ 1580 if(!singlefile) { 1581 fprintf(stderr, "nsd-zonec: must have -z zonefile when reading single zone.\n"); 1582 exit(1); 1583 } 1584 if(!origin) { 1585 fprintf(stderr, "nsd-zonec: must have -o origin when reading single zone.\n"); 1586 exit(1); 1587 } 1588 if (vflag > 0) 1589 fprintf(stdout, "nsd-zonec: reading zone \"%s\".\n", origin); 1590 zone_read(origin, singlefile, nsd_options); 1591 if (vflag > 0) 1592 fprintf(stdout, "nsd-zonec: processed %ld RRs in \"%s\".\n", totalrrs, origin); 1593 } else { 1594 zone_options_t* zone; 1595 if(!nsd_options) { 1596 fprintf(stderr, "nsd-zonec: no zones specified.\n"); 1597 exit(1); 1598 } 1599 /* read all zones */ 1600 RBTREE_FOR(zone, zone_options_t*, nsd_options->zone_options) 1601 { 1602 if (vflag > 0) 1603 fprintf(stdout, "nsd-zonec: reading zone \"%s\".\n", 1604 zone->name); 1605 zone_read(zone->name, zone->zonefile, nsd_options); 1606 if (vflag > 0) 1607 fprintf(stdout, 1608 "nsd-zonec: processed %ld RRs in \"%s\".\n", 1609 totalrrs, zone->name); 1610 totalrrs = 0; 1611 } 1612 } 1613 check_dname(db); 1614 1615 #ifndef NDEBUG 1616 if (vflag > 0) { 1617 fprintf(stdout, "global_region: "); 1618 region_dump_stats(global_region, stdout); 1619 fprintf(stdout, "\n"); 1620 fprintf(stdout, "db->region: "); 1621 region_dump_stats(db->region, stdout); 1622 fprintf(stdout, "\n"); 1623 } 1624 #endif /* NDEBUG */ 1625 1626 /* Close the database */ 1627 if (namedb_save(db) != 0) { 1628 fprintf(stderr, "nsd-zonec: error writing the database (%s): %s\n", db->filename, strerror(errno)); 1629 namedb_discard(db); 1630 exit(1); 1631 } 1632 1633 /* Print the total number of errors */ 1634 if (vflag > 0 || totalerrors > 0) { 1635 if (totalerrors > 0) { 1636 fprintf(stderr, "\nnsd-zonec: done with %ld errors.\n", 1637 totalerrors); 1638 } else { 1639 fprintf(stdout, "\nnsd-zonec: done with no errors.\n"); 1640 } 1641 } 1642 1643 /* Disable this to save some time. */ 1644 #if 0 1645 region_destroy(global_region); 1646 #endif 1647 1648 return totalerrors ? 1 : 0; 1649 } 1650