1 /* $NetBSD: check-tool.c,v 1.7 2014/12/10 04:37:51 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 2000-2002 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id: check-tool.c,v 1.44 2011/12/22 07:32:39 each Exp */ 21 22 /*! \file */ 23 24 #include <config.h> 25 26 #include <stdio.h> 27 28 #ifdef _WIN32 29 #include <Winsock2.h> 30 #endif 31 32 #include "check-tool.h" 33 #include <isc/buffer.h> 34 #include <isc/log.h> 35 #include <isc/mem.h> 36 #include <isc/netdb.h> 37 #include <isc/net.h> 38 #include <isc/region.h> 39 #include <isc/stdio.h> 40 #include <isc/string.h> 41 #include <isc/symtab.h> 42 #include <isc/types.h> 43 #include <isc/util.h> 44 45 #include <dns/db.h> 46 #include <dns/dbiterator.h> 47 #include <dns/fixedname.h> 48 #include <dns/log.h> 49 #include <dns/name.h> 50 #include <dns/rdata.h> 51 #include <dns/rdataclass.h> 52 #include <dns/rdataset.h> 53 #include <dns/rdatasetiter.h> 54 #include <dns/rdatatype.h> 55 #include <dns/result.h> 56 #include <dns/types.h> 57 #include <dns/zone.h> 58 59 #include <isccfg/log.h> 60 61 #ifndef CHECK_SIBLING 62 #define CHECK_SIBLING 1 63 #endif 64 65 #ifndef CHECK_LOCAL 66 #define CHECK_LOCAL 1 67 #endif 68 69 #ifdef HAVE_ADDRINFO 70 #ifdef HAVE_GETADDRINFO 71 #ifdef HAVE_GAISTRERROR 72 #define USE_GETADDRINFO 73 #endif 74 #endif 75 #endif 76 77 #define CHECK(r) \ 78 do { \ 79 result = (r); \ 80 if (result != ISC_R_SUCCESS) \ 81 goto cleanup; \ 82 } while (/*CONSTCOND*/0) 83 84 #define ERR_IS_CNAME 1 85 #define ERR_NO_ADDRESSES 2 86 #define ERR_LOOKUP_FAILURE 3 87 #define ERR_EXTRA_A 4 88 #define ERR_EXTRA_AAAA 5 89 #define ERR_MISSING_GLUE 5 90 #define ERR_IS_MXCNAME 6 91 #define ERR_IS_SRVCNAME 7 92 93 static const char *dbtype[] = { "rbt" }; 94 95 int debug = 0; 96 const char *journal = NULL; 97 isc_boolean_t nomerge = ISC_TRUE; 98 #if CHECK_LOCAL 99 isc_boolean_t docheckmx = ISC_TRUE; 100 isc_boolean_t dochecksrv = ISC_TRUE; 101 isc_boolean_t docheckns = ISC_TRUE; 102 #else 103 isc_boolean_t docheckmx = ISC_FALSE; 104 isc_boolean_t dochecksrv = ISC_FALSE; 105 isc_boolean_t docheckns = ISC_FALSE; 106 #endif 107 unsigned int zone_options = DNS_ZONEOPT_CHECKNS | 108 DNS_ZONEOPT_CHECKMX | 109 DNS_ZONEOPT_MANYERRORS | 110 DNS_ZONEOPT_CHECKNAMES | 111 DNS_ZONEOPT_CHECKINTEGRITY | 112 #if CHECK_SIBLING 113 DNS_ZONEOPT_CHECKSIBLING | 114 #endif 115 DNS_ZONEOPT_CHECKWILDCARD | 116 DNS_ZONEOPT_WARNMXCNAME | 117 DNS_ZONEOPT_WARNSRVCNAME; 118 unsigned int zone_options2 = 0; 119 120 /* 121 * This needs to match the list in bin/named/log.c. 122 */ 123 static isc_logcategory_t categories[] = { 124 { "", 0 }, 125 { "client", 0 }, 126 { "network", 0 }, 127 { "update", 0 }, 128 { "queries", 0 }, 129 { "unmatched", 0 }, 130 { "update-security", 0 }, 131 { "query-errors", 0 }, 132 { NULL, 0 } 133 }; 134 135 static isc_symtab_t *symtab = NULL; 136 static isc_mem_t *sym_mctx; 137 138 static void 139 freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) { 140 UNUSED(type); 141 UNUSED(value); 142 isc_mem_free(userarg, key); 143 } 144 145 static void 146 add(char *key, int value) { 147 isc_result_t result; 148 isc_symvalue_t symvalue; 149 150 if (sym_mctx == NULL) { 151 result = isc_mem_create(0, 0, &sym_mctx); 152 if (result != ISC_R_SUCCESS) 153 return; 154 } 155 156 if (symtab == NULL) { 157 result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx, 158 ISC_FALSE, &symtab); 159 if (result != ISC_R_SUCCESS) 160 return; 161 } 162 163 key = isc_mem_strdup(sym_mctx, key); 164 if (key == NULL) 165 return; 166 167 symvalue.as_pointer = NULL; 168 result = isc_symtab_define(symtab, key, value, symvalue, 169 isc_symexists_reject); 170 if (result != ISC_R_SUCCESS) 171 isc_mem_free(sym_mctx, key); 172 } 173 174 static isc_boolean_t 175 logged(char *key, int value) { 176 isc_result_t result; 177 178 if (symtab == NULL) 179 return (ISC_FALSE); 180 181 result = isc_symtab_lookup(symtab, key, value, NULL); 182 if (result == ISC_R_SUCCESS) 183 return (ISC_TRUE); 184 return (ISC_FALSE); 185 } 186 187 static isc_boolean_t 188 checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner, 189 dns_rdataset_t *a, dns_rdataset_t *aaaa) 190 { 191 #ifdef USE_GETADDRINFO 192 dns_rdataset_t *rdataset; 193 dns_rdata_t rdata = DNS_RDATA_INIT; 194 struct addrinfo hints, *ai, *cur; 195 char namebuf[DNS_NAME_FORMATSIZE + 1]; 196 char ownerbuf[DNS_NAME_FORMATSIZE]; 197 char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")]; 198 isc_boolean_t answer = ISC_TRUE; 199 isc_boolean_t match; 200 const char *type; 201 void *ptr = NULL; 202 int result; 203 204 REQUIRE(a == NULL || !dns_rdataset_isassociated(a) || 205 a->type == dns_rdatatype_a); 206 REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) || 207 aaaa->type == dns_rdatatype_aaaa); 208 209 if (a == NULL || aaaa == NULL) 210 return (answer); 211 212 memset(&hints, 0, sizeof(hints)); 213 hints.ai_flags = AI_CANONNAME; 214 hints.ai_family = PF_UNSPEC; 215 hints.ai_socktype = SOCK_STREAM; 216 hints.ai_protocol = IPPROTO_TCP; 217 218 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 219 /* 220 * Turn off search. 221 */ 222 if (dns_name_countlabels(name) > 1U) 223 strcat(namebuf, "."); 224 dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); 225 226 result = getaddrinfo(namebuf, NULL, &hints, &ai); 227 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 228 switch (result) { 229 case 0: 230 /* 231 * Work around broken getaddrinfo() implementations that 232 * fail to set ai_canonname on first entry. 233 */ 234 cur = ai; 235 while (cur != NULL && cur->ai_canonname == NULL && 236 cur->ai_next != NULL) 237 cur = cur->ai_next; 238 if (cur != NULL && cur->ai_canonname != NULL && 239 strcasecmp(cur->ai_canonname, namebuf) != 0 && 240 !logged(namebuf, ERR_IS_CNAME)) { 241 dns_zone_log(zone, ISC_LOG_ERROR, 242 "%s/NS '%s' (out of zone) " 243 "is a CNAME '%s' (illegal)", 244 ownerbuf, namebuf, 245 cur->ai_canonname); 246 /* XXX950 make fatal for 9.5.0 */ 247 /* answer = ISC_FALSE; */ 248 add(namebuf, ERR_IS_CNAME); 249 } 250 break; 251 case EAI_NONAME: 252 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) 253 case EAI_NODATA: 254 #endif 255 if (!logged(namebuf, ERR_NO_ADDRESSES)) { 256 dns_zone_log(zone, ISC_LOG_ERROR, 257 "%s/NS '%s' (out of zone) " 258 "has no addresses records (A or AAAA)", 259 ownerbuf, namebuf); 260 add(namebuf, ERR_NO_ADDRESSES); 261 } 262 /* XXX950 make fatal for 9.5.0 */ 263 return (ISC_TRUE); 264 265 default: 266 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { 267 dns_zone_log(zone, ISC_LOG_WARNING, 268 "getaddrinfo(%s) failed: %s", 269 namebuf, gai_strerror(result)); 270 add(namebuf, ERR_LOOKUP_FAILURE); 271 } 272 return (ISC_TRUE); 273 } 274 275 /* 276 * Check that all glue records really exist. 277 */ 278 if (!dns_rdataset_isassociated(a)) 279 goto checkaaaa; 280 result = dns_rdataset_first(a); 281 while (result == ISC_R_SUCCESS) { 282 dns_rdataset_current(a, &rdata); 283 match = ISC_FALSE; 284 for (cur = ai; cur != NULL; cur = cur->ai_next) { 285 if (cur->ai_family != AF_INET) 286 continue; 287 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr; 288 if (memcmp(ptr, rdata.data, rdata.length) == 0) { 289 match = ISC_TRUE; 290 break; 291 } 292 } 293 if (!match && !logged(namebuf, ERR_EXTRA_A)) { 294 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " 295 "extra GLUE A record (%s)", 296 ownerbuf, namebuf, 297 inet_ntop(AF_INET, rdata.data, 298 addrbuf, sizeof(addrbuf))); 299 add(namebuf, ERR_EXTRA_A); 300 /* XXX950 make fatal for 9.5.0 */ 301 /* answer = ISC_FALSE; */ 302 } 303 dns_rdata_reset(&rdata); 304 result = dns_rdataset_next(a); 305 } 306 307 checkaaaa: 308 if (!dns_rdataset_isassociated(aaaa)) 309 goto checkmissing; 310 result = dns_rdataset_first(aaaa); 311 while (result == ISC_R_SUCCESS) { 312 dns_rdataset_current(aaaa, &rdata); 313 match = ISC_FALSE; 314 for (cur = ai; cur != NULL; cur = cur->ai_next) { 315 if (cur->ai_family != AF_INET6) 316 continue; 317 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr; 318 if (memcmp(ptr, rdata.data, rdata.length) == 0) { 319 match = ISC_TRUE; 320 break; 321 } 322 } 323 if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) { 324 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " 325 "extra GLUE AAAA record (%s)", 326 ownerbuf, namebuf, 327 inet_ntop(AF_INET6, rdata.data, 328 addrbuf, sizeof(addrbuf))); 329 add(namebuf, ERR_EXTRA_AAAA); 330 /* XXX950 make fatal for 9.5.0. */ 331 /* answer = ISC_FALSE; */ 332 } 333 dns_rdata_reset(&rdata); 334 result = dns_rdataset_next(aaaa); 335 } 336 337 checkmissing: 338 /* 339 * Check that all addresses appear in the glue. 340 */ 341 if (!logged(namebuf, ERR_MISSING_GLUE)) { 342 isc_boolean_t missing_glue = ISC_FALSE; 343 for (cur = ai; cur != NULL; cur = cur->ai_next) { 344 switch (cur->ai_family) { 345 case AF_INET: 346 rdataset = a; 347 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr; 348 type = "A"; 349 break; 350 case AF_INET6: 351 rdataset = aaaa; 352 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr; 353 type = "AAAA"; 354 break; 355 default: 356 continue; 357 } 358 match = ISC_FALSE; 359 if (dns_rdataset_isassociated(rdataset)) 360 result = dns_rdataset_first(rdataset); 361 else 362 result = ISC_R_FAILURE; 363 while (result == ISC_R_SUCCESS && !match) { 364 dns_rdataset_current(rdataset, &rdata); 365 if (memcmp(ptr, rdata.data, rdata.length) == 0) 366 match = ISC_TRUE; 367 dns_rdata_reset(&rdata); 368 result = dns_rdataset_next(rdataset); 369 } 370 if (!match) { 371 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' " 372 "missing GLUE %s record (%s)", 373 ownerbuf, namebuf, type, 374 inet_ntop(cur->ai_family, ptr, 375 addrbuf, sizeof(addrbuf))); 376 /* XXX950 make fatal for 9.5.0. */ 377 /* answer = ISC_FALSE; */ 378 missing_glue = ISC_TRUE; 379 } 380 } 381 if (missing_glue) 382 add(namebuf, ERR_MISSING_GLUE); 383 } 384 freeaddrinfo(ai); 385 return (answer); 386 #else 387 return (ISC_TRUE); 388 #endif 389 } 390 391 static isc_boolean_t 392 checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) { 393 #ifdef USE_GETADDRINFO 394 struct addrinfo hints, *ai, *cur; 395 char namebuf[DNS_NAME_FORMATSIZE + 1]; 396 char ownerbuf[DNS_NAME_FORMATSIZE]; 397 int result; 398 int level = ISC_LOG_ERROR; 399 isc_boolean_t answer = ISC_TRUE; 400 401 memset(&hints, 0, sizeof(hints)); 402 hints.ai_flags = AI_CANONNAME; 403 hints.ai_family = PF_UNSPEC; 404 hints.ai_socktype = SOCK_STREAM; 405 hints.ai_protocol = IPPROTO_TCP; 406 407 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 408 /* 409 * Turn off search. 410 */ 411 if (dns_name_countlabels(name) > 1U) 412 strcat(namebuf, "."); 413 dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); 414 415 result = getaddrinfo(namebuf, NULL, &hints, &ai); 416 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 417 switch (result) { 418 case 0: 419 /* 420 * Work around broken getaddrinfo() implementations that 421 * fail to set ai_canonname on first entry. 422 */ 423 cur = ai; 424 while (cur != NULL && cur->ai_canonname == NULL && 425 cur->ai_next != NULL) 426 cur = cur->ai_next; 427 if (cur != NULL && cur->ai_canonname != NULL && 428 strcasecmp(cur->ai_canonname, namebuf) != 0) { 429 if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0) 430 level = ISC_LOG_WARNING; 431 if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) { 432 if (!logged(namebuf, ERR_IS_MXCNAME)) { 433 dns_zone_log(zone, level, 434 "%s/MX '%s' (out of zone)" 435 " is a CNAME '%s' " 436 "(illegal)", 437 ownerbuf, namebuf, 438 cur->ai_canonname); 439 add(namebuf, ERR_IS_MXCNAME); 440 } 441 if (level == ISC_LOG_ERROR) 442 answer = ISC_FALSE; 443 } 444 } 445 freeaddrinfo(ai); 446 return (answer); 447 448 case EAI_NONAME: 449 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) 450 case EAI_NODATA: 451 #endif 452 if (!logged(namebuf, ERR_NO_ADDRESSES)) { 453 dns_zone_log(zone, ISC_LOG_ERROR, 454 "%s/MX '%s' (out of zone) " 455 "has no addresses records (A or AAAA)", 456 ownerbuf, namebuf); 457 add(namebuf, ERR_NO_ADDRESSES); 458 } 459 /* XXX950 make fatal for 9.5.0. */ 460 return (ISC_TRUE); 461 462 default: 463 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { 464 dns_zone_log(zone, ISC_LOG_WARNING, 465 "getaddrinfo(%s) failed: %s", 466 namebuf, gai_strerror(result)); 467 add(namebuf, ERR_LOOKUP_FAILURE); 468 } 469 return (ISC_TRUE); 470 } 471 #else 472 return (ISC_TRUE); 473 #endif 474 } 475 476 static isc_boolean_t 477 checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) { 478 #ifdef USE_GETADDRINFO 479 struct addrinfo hints, *ai, *cur; 480 char namebuf[DNS_NAME_FORMATSIZE + 1]; 481 char ownerbuf[DNS_NAME_FORMATSIZE]; 482 int result; 483 int level = ISC_LOG_ERROR; 484 isc_boolean_t answer = ISC_TRUE; 485 486 memset(&hints, 0, sizeof(hints)); 487 hints.ai_flags = AI_CANONNAME; 488 hints.ai_family = PF_UNSPEC; 489 hints.ai_socktype = SOCK_STREAM; 490 hints.ai_protocol = IPPROTO_TCP; 491 492 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 493 /* 494 * Turn off search. 495 */ 496 if (dns_name_countlabels(name) > 1U) 497 strcat(namebuf, "."); 498 dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); 499 500 result = getaddrinfo(namebuf, NULL, &hints, &ai); 501 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 502 switch (result) { 503 case 0: 504 /* 505 * Work around broken getaddrinfo() implementations that 506 * fail to set ai_canonname on first entry. 507 */ 508 cur = ai; 509 while (cur != NULL && cur->ai_canonname == NULL && 510 cur->ai_next != NULL) 511 cur = cur->ai_next; 512 if (cur != NULL && cur->ai_canonname != NULL && 513 strcasecmp(cur->ai_canonname, namebuf) != 0) { 514 if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0) 515 level = ISC_LOG_WARNING; 516 if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) { 517 if (!logged(namebuf, ERR_IS_SRVCNAME)) { 518 dns_zone_log(zone, level, "%s/SRV '%s'" 519 " (out of zone) is a " 520 "CNAME '%s' (illegal)", 521 ownerbuf, namebuf, 522 cur->ai_canonname); 523 add(namebuf, ERR_IS_SRVCNAME); 524 } 525 if (level == ISC_LOG_ERROR) 526 answer = ISC_FALSE; 527 } 528 } 529 freeaddrinfo(ai); 530 return (answer); 531 532 case EAI_NONAME: 533 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) 534 case EAI_NODATA: 535 #endif 536 if (!logged(namebuf, ERR_NO_ADDRESSES)) { 537 dns_zone_log(zone, ISC_LOG_ERROR, 538 "%s/SRV '%s' (out of zone) " 539 "has no addresses records (A or AAAA)", 540 ownerbuf, namebuf); 541 add(namebuf, ERR_NO_ADDRESSES); 542 } 543 /* XXX950 make fatal for 9.5.0. */ 544 return (ISC_TRUE); 545 546 default: 547 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { 548 dns_zone_log(zone, ISC_LOG_WARNING, 549 "getaddrinfo(%s) failed: %s", 550 namebuf, gai_strerror(result)); 551 add(namebuf, ERR_LOOKUP_FAILURE); 552 } 553 return (ISC_TRUE); 554 } 555 #else 556 return (ISC_TRUE); 557 #endif 558 } 559 560 isc_result_t 561 setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) { 562 isc_logdestination_t destination; 563 isc_logconfig_t *logconfig = NULL; 564 isc_log_t *log = NULL; 565 566 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS); 567 isc_log_registercategories(log, categories); 568 isc_log_setcontext(log); 569 dns_log_init(log); 570 dns_log_setcontext(log); 571 cfg_log_init(log); 572 573 destination.file.stream = errout; 574 destination.file.name = NULL; 575 destination.file.versions = ISC_LOG_ROLLNEVER; 576 destination.file.maximum_size = 0; 577 RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr", 578 ISC_LOG_TOFILEDESC, 579 ISC_LOG_DYNAMIC, 580 &destination, 0) == ISC_R_SUCCESS); 581 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", 582 NULL, NULL) == ISC_R_SUCCESS); 583 584 *logp = log; 585 return (ISC_R_SUCCESS); 586 } 587 588 /*% scan the zone for oversize TTLs */ 589 static isc_result_t 590 check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) { 591 isc_result_t result; 592 dns_db_t *db = NULL; 593 dns_dbversion_t *version = NULL; 594 dns_dbnode_t *node = NULL; 595 dns_dbiterator_t *dbiter = NULL; 596 dns_rdatasetiter_t *rdsiter = NULL; 597 dns_rdataset_t rdataset; 598 dns_fixedname_t fname; 599 dns_name_t *name; 600 dns_fixedname_init(&fname); 601 name = dns_fixedname_name(&fname); 602 dns_rdataset_init(&rdataset); 603 604 CHECK(dns_zone_getdb(zone, &db)); 605 INSIST(db != NULL); 606 607 CHECK(dns_db_newversion(db, &version)); 608 CHECK(dns_db_createiterator(db, 0, &dbiter)); 609 610 for (result = dns_dbiterator_first(dbiter); 611 result == ISC_R_SUCCESS; 612 result = dns_dbiterator_next(dbiter)) { 613 result = dns_dbiterator_current(dbiter, &node, name); 614 if (result == DNS_R_NEWORIGIN) 615 result = ISC_R_SUCCESS; 616 CHECK(result); 617 618 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter)); 619 for (result = dns_rdatasetiter_first(rdsiter); 620 result == ISC_R_SUCCESS; 621 result = dns_rdatasetiter_next(rdsiter)) { 622 dns_rdatasetiter_current(rdsiter, &rdataset); 623 if (rdataset.ttl > maxttl) { 624 char nbuf[DNS_NAME_FORMATSIZE]; 625 char tbuf[255]; 626 isc_buffer_t b; 627 isc_region_t r; 628 629 dns_name_format(name, nbuf, sizeof(nbuf)); 630 isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1); 631 CHECK(dns_rdatatype_totext(rdataset.type, &b)); 632 isc_buffer_usedregion(&b, &r); 633 r.base[r.length] = 0; 634 635 dns_zone_log(zone, ISC_LOG_ERROR, 636 "%s/%s TTL %d exceeds " 637 "maximum TTL %d", 638 nbuf, tbuf, rdataset.ttl, maxttl); 639 dns_rdataset_disassociate(&rdataset); 640 CHECK(ISC_R_RANGE); 641 } 642 dns_rdataset_disassociate(&rdataset); 643 } 644 if (result == ISC_R_NOMORE) 645 result = ISC_R_SUCCESS; 646 CHECK(result); 647 648 dns_rdatasetiter_destroy(&rdsiter); 649 dns_db_detachnode(db, &node); 650 } 651 652 if (result == ISC_R_NOMORE) 653 result = ISC_R_SUCCESS; 654 655 cleanup: 656 if (node != NULL) 657 dns_db_detachnode(db, &node); 658 if (rdsiter != NULL) 659 dns_rdatasetiter_destroy(&rdsiter); 660 if (dbiter != NULL) 661 dns_dbiterator_destroy(&dbiter); 662 if (version != NULL) 663 dns_db_closeversion(db, &version, ISC_FALSE); 664 if (db != NULL) 665 dns_db_detach(&db); 666 667 return (result); 668 } 669 670 /*% load the zone */ 671 isc_result_t 672 load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, 673 dns_masterformat_t fileformat, const char *classname, 674 dns_ttl_t maxttl, dns_zone_t **zonep) 675 { 676 isc_result_t result; 677 dns_rdataclass_t rdclass; 678 isc_textregion_t region; 679 isc_buffer_t buffer; 680 dns_fixedname_t fixorigin; 681 dns_name_t *origin; 682 dns_zone_t *zone = NULL; 683 684 REQUIRE(zonep == NULL || *zonep == NULL); 685 686 if (debug) 687 fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n", 688 zonename, filename, classname); 689 690 CHECK(dns_zone_create(&zone, mctx)); 691 692 dns_zone_settype(zone, dns_zone_master); 693 694 isc_buffer_constinit(&buffer, zonename, strlen(zonename)); 695 isc_buffer_add(&buffer, strlen(zonename)); 696 dns_fixedname_init(&fixorigin); 697 origin = dns_fixedname_name(&fixorigin); 698 CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); 699 CHECK(dns_zone_setorigin(zone, origin)); 700 CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype)); 701 CHECK(dns_zone_setfile2(zone, filename, fileformat)); 702 if (journal != NULL) 703 CHECK(dns_zone_setjournal(zone, journal)); 704 705 DE_CONST(classname, region.base); 706 region.length = strlen(classname); 707 CHECK(dns_rdataclass_fromtext(&rdclass, ®ion)); 708 709 dns_zone_setclass(zone, rdclass); 710 dns_zone_setoption(zone, zone_options, ISC_TRUE); 711 dns_zone_setoption2(zone, zone_options2, ISC_TRUE); 712 dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge); 713 714 dns_zone_setmaxttl(zone, maxttl); 715 716 if (docheckmx) 717 dns_zone_setcheckmx(zone, checkmx); 718 if (docheckns) 719 dns_zone_setcheckns(zone, checkns); 720 if (dochecksrv) 721 dns_zone_setchecksrv(zone, checksrv); 722 723 CHECK(dns_zone_load(zone)); 724 725 /* 726 * When loading map files we can't catch oversize TTLs during 727 * load, so we check for them here. 728 */ 729 if (fileformat == dns_masterformat_map && maxttl != 0) { 730 CHECK(check_ttls(zone, maxttl)); 731 } 732 733 if (zonep != NULL) { 734 *zonep = zone; 735 zone = NULL; 736 } 737 738 cleanup: 739 if (zone != NULL) 740 dns_zone_detach(&zone); 741 return (result); 742 } 743 744 /*% dump the zone */ 745 isc_result_t 746 dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, 747 dns_masterformat_t fileformat, const dns_master_style_t *style, 748 const isc_uint32_t rawversion) 749 { 750 isc_result_t result; 751 FILE *output = stdout; 752 const char *flags; 753 754 flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+"; 755 756 if (debug) { 757 if (filename != NULL && strcmp(filename, "-") != 0) 758 fprintf(stderr, "dumping \"%s\" to \"%s\"\n", 759 zonename, filename); 760 else 761 fprintf(stderr, "dumping \"%s\"\n", zonename); 762 } 763 764 if (filename != NULL && strcmp(filename, "-") != 0) { 765 result = isc_stdio_open(filename, flags, &output); 766 767 if (result != ISC_R_SUCCESS) { 768 fprintf(stderr, "could not open output " 769 "file \"%s\" for writing\n", filename); 770 return (ISC_R_FAILURE); 771 } 772 } 773 774 result = dns_zone_dumptostream3(zone, output, fileformat, style, 775 rawversion); 776 if (output != stdout) 777 (void)isc_stdio_close(output); 778 779 return (result); 780 } 781 782 #ifdef _WIN32 783 void 784 InitSockets(void) { 785 WORD wVersionRequested; 786 WSADATA wsaData; 787 int err; 788 789 wVersionRequested = MAKEWORD(2, 0); 790 791 err = WSAStartup( wVersionRequested, &wsaData ); 792 if (err != 0) { 793 fprintf(stderr, "WSAStartup() failed: %d\n", err); 794 exit(1); 795 } 796 } 797 798 void 799 DestroySockets(void) { 800 WSACleanup(); 801 } 802 #endif 803 804