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