1/* 2 * Copyright (C) 2004-2012 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.44 2011/12/22 07:32:39 each 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 200 if (a == NULL || aaaa == NULL) 201 return (answer); 202 203 memset(&hints, 0, sizeof(hints)); 204 hints.ai_flags = AI_CANONNAME; 205 hints.ai_family = PF_UNSPEC; 206 hints.ai_socktype = SOCK_STREAM; 207 hints.ai_protocol = IPPROTO_TCP; 208 209 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 210 /* 211 * Turn off search. 212 */ 213 if (dns_name_countlabels(name) > 1U) 214 strcat(namebuf, "."); 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, dns_name_t *name, 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 strcat(namebuf, "."); 404 dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); 405 406 result = getaddrinfo(namebuf, NULL, &hints, &ai); 407 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 408 switch (result) { 409 case 0: 410 /* 411 * Work around broken getaddrinfo() implementations that 412 * fail to set ai_canonname on first entry. 413 */ 414 cur = ai; 415 while (cur != NULL && cur->ai_canonname == NULL && 416 cur->ai_next != NULL) 417 cur = cur->ai_next; 418 if (cur != NULL && cur->ai_canonname != NULL && 419 strcasecmp(cur->ai_canonname, namebuf) != 0) { 420 if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0) 421 level = ISC_LOG_WARNING; 422 if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) { 423 if (!logged(namebuf, ERR_IS_MXCNAME)) { 424 dns_zone_log(zone, level, 425 "%s/MX '%s' (out of zone)" 426 " is a CNAME '%s' " 427 "(illegal)", 428 ownerbuf, namebuf, 429 cur->ai_canonname); 430 add(namebuf, ERR_IS_MXCNAME); 431 } 432 if (level == ISC_LOG_ERROR) 433 answer = ISC_FALSE; 434 } 435 } 436 freeaddrinfo(ai); 437 return (answer); 438 439 case EAI_NONAME: 440#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) 441 case EAI_NODATA: 442#endif 443 if (!logged(namebuf, ERR_NO_ADDRESSES)) { 444 dns_zone_log(zone, ISC_LOG_ERROR, 445 "%s/MX '%s' (out of zone) " 446 "has no addresses records (A or AAAA)", 447 ownerbuf, namebuf); 448 add(namebuf, ERR_NO_ADDRESSES); 449 } 450 /* XXX950 make fatal for 9.5.0. */ 451 return (ISC_TRUE); 452 453 default: 454 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { 455 dns_zone_log(zone, ISC_LOG_WARNING, 456 "getaddrinfo(%s) failed: %s", 457 namebuf, gai_strerror(result)); 458 add(namebuf, ERR_LOOKUP_FAILURE); 459 } 460 return (ISC_TRUE); 461 } 462#else 463 return (ISC_TRUE); 464#endif 465} 466 467static isc_boolean_t 468checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) { 469#ifdef USE_GETADDRINFO 470 struct addrinfo hints, *ai, *cur; 471 char namebuf[DNS_NAME_FORMATSIZE + 1]; 472 char ownerbuf[DNS_NAME_FORMATSIZE]; 473 int result; 474 int level = ISC_LOG_ERROR; 475 isc_boolean_t answer = ISC_TRUE; 476 477 memset(&hints, 0, sizeof(hints)); 478 hints.ai_flags = AI_CANONNAME; 479 hints.ai_family = PF_UNSPEC; 480 hints.ai_socktype = SOCK_STREAM; 481 hints.ai_protocol = IPPROTO_TCP; 482 483 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 484 /* 485 * Turn off search. 486 */ 487 if (dns_name_countlabels(name) > 1U) 488 strcat(namebuf, "."); 489 dns_name_format(owner, ownerbuf, sizeof(ownerbuf)); 490 491 result = getaddrinfo(namebuf, NULL, &hints, &ai); 492 dns_name_format(name, namebuf, sizeof(namebuf) - 1); 493 switch (result) { 494 case 0: 495 /* 496 * Work around broken getaddrinfo() implementations that 497 * fail to set ai_canonname on first entry. 498 */ 499 cur = ai; 500 while (cur != NULL && cur->ai_canonname == NULL && 501 cur->ai_next != NULL) 502 cur = cur->ai_next; 503 if (cur != NULL && cur->ai_canonname != NULL && 504 strcasecmp(cur->ai_canonname, namebuf) != 0) { 505 if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0) 506 level = ISC_LOG_WARNING; 507 if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) { 508 if (!logged(namebuf, ERR_IS_SRVCNAME)) { 509 dns_zone_log(zone, level, "%s/SRV '%s'" 510 " (out of zone) is a " 511 "CNAME '%s' (illegal)", 512 ownerbuf, namebuf, 513 cur->ai_canonname); 514 add(namebuf, ERR_IS_SRVCNAME); 515 } 516 if (level == ISC_LOG_ERROR) 517 answer = ISC_FALSE; 518 } 519 } 520 freeaddrinfo(ai); 521 return (answer); 522 523 case EAI_NONAME: 524#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) 525 case EAI_NODATA: 526#endif 527 if (!logged(namebuf, ERR_NO_ADDRESSES)) { 528 dns_zone_log(zone, ISC_LOG_ERROR, 529 "%s/SRV '%s' (out of zone) " 530 "has no addresses records (A or AAAA)", 531 ownerbuf, namebuf); 532 add(namebuf, ERR_NO_ADDRESSES); 533 } 534 /* XXX950 make fatal for 9.5.0. */ 535 return (ISC_TRUE); 536 537 default: 538 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) { 539 dns_zone_log(zone, ISC_LOG_WARNING, 540 "getaddrinfo(%s) failed: %s", 541 namebuf, gai_strerror(result)); 542 add(namebuf, ERR_LOOKUP_FAILURE); 543 } 544 return (ISC_TRUE); 545 } 546#else 547 return (ISC_TRUE); 548#endif 549} 550 551isc_result_t 552setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) { 553 isc_logdestination_t destination; 554 isc_logconfig_t *logconfig = NULL; 555 isc_log_t *log = NULL; 556 557 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS); 558 isc_log_registercategories(log, categories); 559 isc_log_setcontext(log); 560 dns_log_init(log); 561 dns_log_setcontext(log); 562 cfg_log_init(log); 563 564 destination.file.stream = errout; 565 destination.file.name = NULL; 566 destination.file.versions = ISC_LOG_ROLLNEVER; 567 destination.file.maximum_size = 0; 568 RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr", 569 ISC_LOG_TOFILEDESC, 570 ISC_LOG_DYNAMIC, 571 &destination, 0) == ISC_R_SUCCESS); 572 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", 573 NULL, NULL) == ISC_R_SUCCESS); 574 575 *logp = log; 576 return (ISC_R_SUCCESS); 577} 578 579/*% load the zone */ 580isc_result_t 581load_zone(isc_mem_t *mctx, const char *zonename, const char *filename, 582 dns_masterformat_t fileformat, const char *classname, 583 dns_zone_t **zonep) 584{ 585 isc_result_t result; 586 dns_rdataclass_t rdclass; 587 isc_textregion_t region; 588 isc_buffer_t buffer; 589 dns_fixedname_t fixorigin; 590 dns_name_t *origin; 591 dns_zone_t *zone = NULL; 592 593 REQUIRE(zonep == NULL || *zonep == NULL); 594 595 if (debug) 596 fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n", 597 zonename, filename, classname); 598 599 CHECK(dns_zone_create(&zone, mctx)); 600 601 dns_zone_settype(zone, dns_zone_master); 602 603 isc_buffer_constinit(&buffer, zonename, strlen(zonename)); 604 isc_buffer_add(&buffer, strlen(zonename)); 605 dns_fixedname_init(&fixorigin); 606 origin = dns_fixedname_name(&fixorigin); 607 CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL)); 608 CHECK(dns_zone_setorigin(zone, origin)); 609 CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype)); 610 CHECK(dns_zone_setfile2(zone, filename, fileformat)); 611 612 DE_CONST(classname, region.base); 613 region.length = strlen(classname); 614 CHECK(dns_rdataclass_fromtext(&rdclass, ®ion)); 615 616 dns_zone_setclass(zone, rdclass); 617 dns_zone_setoption(zone, zone_options, ISC_TRUE); 618 dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge); 619 if (docheckmx) 620 dns_zone_setcheckmx(zone, checkmx); 621 if (docheckns) 622 dns_zone_setcheckns(zone, checkns); 623 if (dochecksrv) 624 dns_zone_setchecksrv(zone, checksrv); 625 626 CHECK(dns_zone_load(zone)); 627 if (zonep != NULL) { 628 *zonep = zone; 629 zone = NULL; 630 } 631 632 cleanup: 633 if (zone != NULL) 634 dns_zone_detach(&zone); 635 return (result); 636} 637 638/*% dump the zone */ 639isc_result_t 640dump_zone(const char *zonename, dns_zone_t *zone, const char *filename, 641 dns_masterformat_t fileformat, const dns_master_style_t *style, 642 const isc_uint32_t rawversion) 643{ 644 isc_result_t result; 645 FILE *output = stdout; 646 const char *flags; 647 648 flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+"; 649 650 if (debug) { 651 if (filename != NULL && strcmp(filename, "-") != 0) 652 fprintf(stderr, "dumping \"%s\" to \"%s\"\n", 653 zonename, filename); 654 else 655 fprintf(stderr, "dumping \"%s\"\n", zonename); 656 } 657 658 if (filename != NULL && strcmp(filename, "-") != 0) { 659 result = isc_stdio_open(filename, flags, &output); 660 661 if (result != ISC_R_SUCCESS) { 662 fprintf(stderr, "could not open output " 663 "file \"%s\" for writing\n", filename); 664 return (ISC_R_FAILURE); 665 } 666 } 667 668 result = dns_zone_dumptostream3(zone, output, fileformat, style, 669 rawversion); 670 if (output != stdout) 671 (void)isc_stdio_close(output); 672 673 return (result); 674} 675 676#ifdef _WIN32 677void 678InitSockets(void) { 679 WORD wVersionRequested; 680 WSADATA wsaData; 681 int err; 682 683 wVersionRequested = MAKEWORD(2, 0); 684 685 err = WSAStartup( wVersionRequested, &wsaData ); 686 if (err != 0) { 687 fprintf(stderr, "WSAStartup() failed: %d\n", err); 688 exit(1); 689 } 690} 691 692void 693DestroySockets(void) { 694 WSACleanup(); 695} 696#endif 697 698