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