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