00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <stdio.h>
00025
00026 #ifdef _WIN32
00027 #include <Winsock2.h>
00028 #endif
00029
00030 #include "check-tool.h"
00031 #include <isc/buffer.h>
00032 #include <isc/log.h>
00033 #include <isc/mem.h>
00034 #include <isc/netdb.h>
00035 #include <isc/net.h>
00036 #include <isc/region.h>
00037 #include <isc/stdio.h>
00038 #include <isc/string.h>
00039 #include <isc/symtab.h>
00040 #include <isc/types.h>
00041 #include <isc/util.h>
00042
00043 #include <dns/db.h>
00044 #include <dns/dbiterator.h>
00045 #include <dns/fixedname.h>
00046 #include <dns/log.h>
00047 #include <dns/name.h>
00048 #include <dns/rdata.h>
00049 #include <dns/rdataclass.h>
00050 #include <dns/rdataset.h>
00051 #include <dns/rdatasetiter.h>
00052 #include <dns/rdatatype.h>
00053 #include <dns/result.h>
00054 #include <dns/types.h>
00055 #include <dns/zone.h>
00056
00057 #include <isccfg/log.h>
00058
00059 #ifndef CHECK_SIBLING
00060 #define CHECK_SIBLING 1
00061 #endif
00062
00063 #ifndef CHECK_LOCAL
00064 #define CHECK_LOCAL 1
00065 #endif
00066
00067 #ifdef HAVE_ADDRINFO
00068 #ifdef HAVE_GETADDRINFO
00069 #ifdef HAVE_GAISTRERROR
00070 #define USE_GETADDRINFO
00071 #endif
00072 #endif
00073 #endif
00074
00075 #define CHECK(r) \
00076 do { \
00077 result = (r); \
00078 if (result != ISC_R_SUCCESS) \
00079 goto cleanup; \
00080 } while (0)
00081
00082 #define ERR_IS_CNAME 1
00083 #define ERR_NO_ADDRESSES 2
00084 #define ERR_LOOKUP_FAILURE 3
00085 #define ERR_EXTRA_A 4
00086 #define ERR_EXTRA_AAAA 5
00087 #define ERR_MISSING_GLUE 5
00088 #define ERR_IS_MXCNAME 6
00089 #define ERR_IS_SRVCNAME 7
00090
00091 static const char *dbtype[] = { "rbt" };
00092
00093 int debug = 0;
00094 const char *journal = NULL;
00095 isc_boolean_t nomerge = ISC_TRUE;
00096 #if CHECK_LOCAL
00097 isc_boolean_t docheckmx = ISC_TRUE;
00098 isc_boolean_t dochecksrv = ISC_TRUE;
00099 isc_boolean_t docheckns = ISC_TRUE;
00100 #else
00101 isc_boolean_t docheckmx = ISC_FALSE;
00102 isc_boolean_t dochecksrv = ISC_FALSE;
00103 isc_boolean_t docheckns = ISC_FALSE;
00104 #endif
00105 unsigned int zone_options = DNS_ZONEOPT_CHECKNS |
00106 DNS_ZONEOPT_CHECKMX |
00107 DNS_ZONEOPT_MANYERRORS |
00108 DNS_ZONEOPT_CHECKNAMES |
00109 DNS_ZONEOPT_CHECKINTEGRITY |
00110 #if CHECK_SIBLING
00111 DNS_ZONEOPT_CHECKSIBLING |
00112 #endif
00113 DNS_ZONEOPT_CHECKWILDCARD |
00114 DNS_ZONEOPT_WARNMXCNAME |
00115 DNS_ZONEOPT_WARNSRVCNAME;
00116 unsigned int zone_options2 = 0;
00117
00118
00119
00120
00121 static isc_logcategory_t categories[] = {
00122 { "", 0 },
00123 { "client", 0 },
00124 { "network", 0 },
00125 { "update", 0 },
00126 { "queries", 0 },
00127 { "unmatched", 0 },
00128 { "update-security", 0 },
00129 { "query-errors", 0 },
00130 { NULL, 0 }
00131 };
00132
00133 static isc_symtab_t *symtab = NULL;
00134 static isc_mem_t *sym_mctx;
00135
00136 static void
00137 freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
00138 UNUSED(type);
00139 UNUSED(value);
00140 isc_mem_free(userarg, key);
00141 }
00142
00143 static void
00144 add(char *key, int value) {
00145 isc_result_t result;
00146 isc_symvalue_t symvalue;
00147
00148 if (sym_mctx == NULL) {
00149 result = isc_mem_create(0, 0, &sym_mctx);
00150 if (result != ISC_R_SUCCESS)
00151 return;
00152 }
00153
00154 if (symtab == NULL) {
00155 result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx,
00156 ISC_FALSE, &symtab);
00157 if (result != ISC_R_SUCCESS)
00158 return;
00159 }
00160
00161 key = isc_mem_strdup(sym_mctx, key);
00162 if (key == NULL)
00163 return;
00164
00165 symvalue.as_pointer = NULL;
00166 result = isc_symtab_define(symtab, key, value, symvalue,
00167 isc_symexists_reject);
00168 if (result != ISC_R_SUCCESS)
00169 isc_mem_free(sym_mctx, key);
00170 }
00171
00172 static isc_boolean_t
00173 logged(char *key, int value) {
00174 isc_result_t result;
00175
00176 if (symtab == NULL)
00177 return (ISC_FALSE);
00178
00179 result = isc_symtab_lookup(symtab, key, value, NULL);
00180 if (result == ISC_R_SUCCESS)
00181 return (ISC_TRUE);
00182 return (ISC_FALSE);
00183 }
00184
00185 static isc_boolean_t
00186 checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner,
00187 dns_rdataset_t *a, dns_rdataset_t *aaaa)
00188 {
00189 #ifdef USE_GETADDRINFO
00190 dns_rdataset_t *rdataset;
00191 dns_rdata_t rdata = DNS_RDATA_INIT;
00192 struct addrinfo hints, *ai, *cur;
00193 char namebuf[DNS_NAME_FORMATSIZE + 1];
00194 char ownerbuf[DNS_NAME_FORMATSIZE];
00195 char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
00196 isc_boolean_t answer = ISC_TRUE;
00197 isc_boolean_t match;
00198 const char *type;
00199 void *ptr = NULL;
00200 int result;
00201
00202 REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
00203 a->type == dns_rdatatype_a);
00204 REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
00205 aaaa->type == dns_rdatatype_aaaa);
00206
00207 if (a == NULL || aaaa == NULL)
00208 return (answer);
00209
00210 memset(&hints, 0, sizeof(hints));
00211 hints.ai_flags = AI_CANONNAME;
00212 hints.ai_family = PF_UNSPEC;
00213 hints.ai_socktype = SOCK_STREAM;
00214 hints.ai_protocol = IPPROTO_TCP;
00215
00216 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00217
00218
00219
00220 if (dns_name_countlabels(name) > 1U)
00221 strcat(namebuf, ".");
00222 dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
00223
00224 result = getaddrinfo(namebuf, NULL, &hints, &ai);
00225 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00226 switch (result) {
00227 case 0:
00228
00229
00230
00231
00232 cur = ai;
00233 while (cur != NULL && cur->ai_canonname == NULL &&
00234 cur->ai_next != NULL)
00235 cur = cur->ai_next;
00236 if (cur != NULL && cur->ai_canonname != NULL &&
00237 strcasecmp(cur->ai_canonname, namebuf) != 0 &&
00238 !logged(namebuf, ERR_IS_CNAME)) {
00239 dns_zone_log(zone, ISC_LOG_ERROR,
00240 "%s/NS '%s' (out of zone) "
00241 "is a CNAME '%s' (illegal)",
00242 ownerbuf, namebuf,
00243 cur->ai_canonname);
00244
00245
00246 add(namebuf, ERR_IS_CNAME);
00247 }
00248 break;
00249 case EAI_NONAME:
00250 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
00251 case EAI_NODATA:
00252 #endif
00253 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
00254 dns_zone_log(zone, ISC_LOG_ERROR,
00255 "%s/NS '%s' (out of zone) "
00256 "has no addresses records (A or AAAA)",
00257 ownerbuf, namebuf);
00258 add(namebuf, ERR_NO_ADDRESSES);
00259 }
00260
00261 return (ISC_TRUE);
00262
00263 default:
00264 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
00265 dns_zone_log(zone, ISC_LOG_WARNING,
00266 "getaddrinfo(%s) failed: %s",
00267 namebuf, gai_strerror(result));
00268 add(namebuf, ERR_LOOKUP_FAILURE);
00269 }
00270 return (ISC_TRUE);
00271 }
00272
00273
00274
00275
00276 if (!dns_rdataset_isassociated(a))
00277 goto checkaaaa;
00278 result = dns_rdataset_first(a);
00279 while (result == ISC_R_SUCCESS) {
00280 dns_rdataset_current(a, &rdata);
00281 match = ISC_FALSE;
00282 for (cur = ai; cur != NULL; cur = cur->ai_next) {
00283 if (cur->ai_family != AF_INET)
00284 continue;
00285 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
00286 if (memcmp(ptr, rdata.data, rdata.length) == 0) {
00287 match = ISC_TRUE;
00288 break;
00289 }
00290 }
00291 if (!match && !logged(namebuf, ERR_EXTRA_A)) {
00292 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
00293 "extra GLUE A record (%s)",
00294 ownerbuf, namebuf,
00295 inet_ntop(AF_INET, rdata.data,
00296 addrbuf, sizeof(addrbuf)));
00297 add(namebuf, ERR_EXTRA_A);
00298
00299
00300 }
00301 dns_rdata_reset(&rdata);
00302 result = dns_rdataset_next(a);
00303 }
00304
00305 checkaaaa:
00306 if (!dns_rdataset_isassociated(aaaa))
00307 goto checkmissing;
00308 result = dns_rdataset_first(aaaa);
00309 while (result == ISC_R_SUCCESS) {
00310 dns_rdataset_current(aaaa, &rdata);
00311 match = ISC_FALSE;
00312 for (cur = ai; cur != NULL; cur = cur->ai_next) {
00313 if (cur->ai_family != AF_INET6)
00314 continue;
00315 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
00316 if (memcmp(ptr, rdata.data, rdata.length) == 0) {
00317 match = ISC_TRUE;
00318 break;
00319 }
00320 }
00321 if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
00322 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
00323 "extra GLUE AAAA record (%s)",
00324 ownerbuf, namebuf,
00325 inet_ntop(AF_INET6, rdata.data,
00326 addrbuf, sizeof(addrbuf)));
00327 add(namebuf, ERR_EXTRA_AAAA);
00328
00329
00330 }
00331 dns_rdata_reset(&rdata);
00332 result = dns_rdataset_next(aaaa);
00333 }
00334
00335 checkmissing:
00336
00337
00338
00339 if (!logged(namebuf, ERR_MISSING_GLUE)) {
00340 isc_boolean_t missing_glue = ISC_FALSE;
00341 for (cur = ai; cur != NULL; cur = cur->ai_next) {
00342 switch (cur->ai_family) {
00343 case AF_INET:
00344 rdataset = a;
00345 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
00346 type = "A";
00347 break;
00348 case AF_INET6:
00349 rdataset = aaaa;
00350 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
00351 type = "AAAA";
00352 break;
00353 default:
00354 continue;
00355 }
00356 match = ISC_FALSE;
00357 if (dns_rdataset_isassociated(rdataset))
00358 result = dns_rdataset_first(rdataset);
00359 else
00360 result = ISC_R_FAILURE;
00361 while (result == ISC_R_SUCCESS && !match) {
00362 dns_rdataset_current(rdataset, &rdata);
00363 if (memcmp(ptr, rdata.data, rdata.length) == 0)
00364 match = ISC_TRUE;
00365 dns_rdata_reset(&rdata);
00366 result = dns_rdataset_next(rdataset);
00367 }
00368 if (!match) {
00369 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
00370 "missing GLUE %s record (%s)",
00371 ownerbuf, namebuf, type,
00372 inet_ntop(cur->ai_family, ptr,
00373 addrbuf, sizeof(addrbuf)));
00374
00375
00376 missing_glue = ISC_TRUE;
00377 }
00378 }
00379 if (missing_glue)
00380 add(namebuf, ERR_MISSING_GLUE);
00381 }
00382 freeaddrinfo(ai);
00383 return (answer);
00384 #else
00385 return (ISC_TRUE);
00386 #endif
00387 }
00388
00389 static isc_boolean_t
00390 checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
00391 #ifdef USE_GETADDRINFO
00392 struct addrinfo hints, *ai, *cur;
00393 char namebuf[DNS_NAME_FORMATSIZE + 1];
00394 char ownerbuf[DNS_NAME_FORMATSIZE];
00395 int result;
00396 int level = ISC_LOG_ERROR;
00397 isc_boolean_t answer = ISC_TRUE;
00398
00399 memset(&hints, 0, sizeof(hints));
00400 hints.ai_flags = AI_CANONNAME;
00401 hints.ai_family = PF_UNSPEC;
00402 hints.ai_socktype = SOCK_STREAM;
00403 hints.ai_protocol = IPPROTO_TCP;
00404
00405 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00406
00407
00408
00409 if (dns_name_countlabels(name) > 1U)
00410 strcat(namebuf, ".");
00411 dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
00412
00413 result = getaddrinfo(namebuf, NULL, &hints, &ai);
00414 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00415 switch (result) {
00416 case 0:
00417
00418
00419
00420
00421 cur = ai;
00422 while (cur != NULL && cur->ai_canonname == NULL &&
00423 cur->ai_next != NULL)
00424 cur = cur->ai_next;
00425 if (cur != NULL && cur->ai_canonname != NULL &&
00426 strcasecmp(cur->ai_canonname, namebuf) != 0) {
00427 if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0)
00428 level = ISC_LOG_WARNING;
00429 if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
00430 if (!logged(namebuf, ERR_IS_MXCNAME)) {
00431 dns_zone_log(zone, level,
00432 "%s/MX '%s' (out of zone)"
00433 " is a CNAME '%s' "
00434 "(illegal)",
00435 ownerbuf, namebuf,
00436 cur->ai_canonname);
00437 add(namebuf, ERR_IS_MXCNAME);
00438 }
00439 if (level == ISC_LOG_ERROR)
00440 answer = ISC_FALSE;
00441 }
00442 }
00443 freeaddrinfo(ai);
00444 return (answer);
00445
00446 case EAI_NONAME:
00447 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
00448 case EAI_NODATA:
00449 #endif
00450 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
00451 dns_zone_log(zone, ISC_LOG_ERROR,
00452 "%s/MX '%s' (out of zone) "
00453 "has no addresses records (A or AAAA)",
00454 ownerbuf, namebuf);
00455 add(namebuf, ERR_NO_ADDRESSES);
00456 }
00457
00458 return (ISC_TRUE);
00459
00460 default:
00461 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
00462 dns_zone_log(zone, ISC_LOG_WARNING,
00463 "getaddrinfo(%s) failed: %s",
00464 namebuf, gai_strerror(result));
00465 add(namebuf, ERR_LOOKUP_FAILURE);
00466 }
00467 return (ISC_TRUE);
00468 }
00469 #else
00470 return (ISC_TRUE);
00471 #endif
00472 }
00473
00474 static isc_boolean_t
00475 checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
00476 #ifdef USE_GETADDRINFO
00477 struct addrinfo hints, *ai, *cur;
00478 char namebuf[DNS_NAME_FORMATSIZE + 1];
00479 char ownerbuf[DNS_NAME_FORMATSIZE];
00480 int result;
00481 int level = ISC_LOG_ERROR;
00482 isc_boolean_t answer = ISC_TRUE;
00483
00484 memset(&hints, 0, sizeof(hints));
00485 hints.ai_flags = AI_CANONNAME;
00486 hints.ai_family = PF_UNSPEC;
00487 hints.ai_socktype = SOCK_STREAM;
00488 hints.ai_protocol = IPPROTO_TCP;
00489
00490 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00491
00492
00493
00494 if (dns_name_countlabels(name) > 1U)
00495 strcat(namebuf, ".");
00496 dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
00497
00498 result = getaddrinfo(namebuf, NULL, &hints, &ai);
00499 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
00500 switch (result) {
00501 case 0:
00502
00503
00504
00505
00506 cur = ai;
00507 while (cur != NULL && cur->ai_canonname == NULL &&
00508 cur->ai_next != NULL)
00509 cur = cur->ai_next;
00510 if (cur != NULL && cur->ai_canonname != NULL &&
00511 strcasecmp(cur->ai_canonname, namebuf) != 0) {
00512 if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
00513 level = ISC_LOG_WARNING;
00514 if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
00515 if (!logged(namebuf, ERR_IS_SRVCNAME)) {
00516 dns_zone_log(zone, level, "%s/SRV '%s'"
00517 " (out of zone) is a "
00518 "CNAME '%s' (illegal)",
00519 ownerbuf, namebuf,
00520 cur->ai_canonname);
00521 add(namebuf, ERR_IS_SRVCNAME);
00522 }
00523 if (level == ISC_LOG_ERROR)
00524 answer = ISC_FALSE;
00525 }
00526 }
00527 freeaddrinfo(ai);
00528 return (answer);
00529
00530 case EAI_NONAME:
00531 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
00532 case EAI_NODATA:
00533 #endif
00534 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
00535 dns_zone_log(zone, ISC_LOG_ERROR,
00536 "%s/SRV '%s' (out of zone) "
00537 "has no addresses records (A or AAAA)",
00538 ownerbuf, namebuf);
00539 add(namebuf, ERR_NO_ADDRESSES);
00540 }
00541
00542 return (ISC_TRUE);
00543
00544 default:
00545 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
00546 dns_zone_log(zone, ISC_LOG_WARNING,
00547 "getaddrinfo(%s) failed: %s",
00548 namebuf, gai_strerror(result));
00549 add(namebuf, ERR_LOOKUP_FAILURE);
00550 }
00551 return (ISC_TRUE);
00552 }
00553 #else
00554 return (ISC_TRUE);
00555 #endif
00556 }
00557
00558 isc_result_t
00559 setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
00560 isc_logdestination_t destination;
00561 isc_logconfig_t *logconfig = NULL;
00562 isc_log_t *log = NULL;
00563
00564 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
00565 isc_log_registercategories(log, categories);
00566 isc_log_setcontext(log);
00567 dns_log_init(log);
00568 dns_log_setcontext(log);
00569 cfg_log_init(log);
00570
00571 destination.file.stream = errout;
00572 destination.file.name = NULL;
00573 destination.file.versions = ISC_LOG_ROLLNEVER;
00574 destination.file.maximum_size = 0;
00575 RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr",
00576 ISC_LOG_TOFILEDESC,
00577 ISC_LOG_DYNAMIC,
00578 &destination, 0) == ISC_R_SUCCESS);
00579 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
00580 NULL, NULL) == ISC_R_SUCCESS);
00581
00582 *logp = log;
00583 return (ISC_R_SUCCESS);
00584 }
00585
00586
00587 static isc_result_t
00588 check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) {
00589 isc_result_t result;
00590 dns_db_t *db = NULL;
00591 dns_dbversion_t *version = NULL;
00592 dns_dbnode_t *node = NULL;
00593 dns_dbiterator_t *dbiter = NULL;
00594 dns_rdatasetiter_t *rdsiter = NULL;
00595 dns_rdataset_t rdataset;
00596 dns_fixedname_t fname;
00597 dns_name_t *name;
00598 dns_fixedname_init(&fname);
00599 name = dns_fixedname_name(&fname);
00600 dns_rdataset_init(&rdataset);
00601
00602 CHECK(dns_zone_getdb(zone, &db));
00603 INSIST(db != NULL);
00604
00605 CHECK(dns_db_newversion(db, &version));
00606 CHECK(dns_db_createiterator(db, 0, &dbiter));
00607
00608 for (result = dns_dbiterator_first(dbiter);
00609 result == ISC_R_SUCCESS;
00610 result = dns_dbiterator_next(dbiter)) {
00611 result = dns_dbiterator_current(dbiter, &node, name);
00612 if (result == DNS_R_NEWORIGIN)
00613 result = ISC_R_SUCCESS;
00614 CHECK(result);
00615
00616 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter));
00617 for (result = dns_rdatasetiter_first(rdsiter);
00618 result == ISC_R_SUCCESS;
00619 result = dns_rdatasetiter_next(rdsiter)) {
00620 dns_rdatasetiter_current(rdsiter, &rdataset);
00621 if (rdataset.ttl > maxttl) {
00622 char nbuf[DNS_NAME_FORMATSIZE];
00623 char tbuf[255];
00624 isc_buffer_t b;
00625 isc_region_t r;
00626
00627 dns_name_format(name, nbuf, sizeof(nbuf));
00628 isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1);
00629 CHECK(dns_rdatatype_totext(rdataset.type, &b));
00630 isc_buffer_usedregion(&b, &r);
00631 r.base[r.length] = 0;
00632
00633 dns_zone_log(zone, ISC_LOG_ERROR,
00634 "%s/%s TTL %d exceeds "
00635 "maximum TTL %d",
00636 nbuf, tbuf, rdataset.ttl, maxttl);
00637 dns_rdataset_disassociate(&rdataset);
00638 CHECK(ISC_R_RANGE);
00639 }
00640 dns_rdataset_disassociate(&rdataset);
00641 }
00642 if (result == ISC_R_NOMORE)
00643 result = ISC_R_SUCCESS;
00644 CHECK(result);
00645
00646 dns_rdatasetiter_destroy(&rdsiter);
00647 dns_db_detachnode(db, &node);
00648 }
00649
00650 if (result == ISC_R_NOMORE)
00651 result = ISC_R_SUCCESS;
00652
00653 cleanup:
00654 if (node != NULL)
00655 dns_db_detachnode(db, &node);
00656 if (rdsiter != NULL)
00657 dns_rdatasetiter_destroy(&rdsiter);
00658 if (dbiter != NULL)
00659 dns_dbiterator_destroy(&dbiter);
00660 if (version != NULL)
00661 dns_db_closeversion(db, &version, ISC_FALSE);
00662 if (db != NULL)
00663 dns_db_detach(&db);
00664
00665 return (result);
00666 }
00667
00668
00669 isc_result_t
00670 load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
00671 dns_masterformat_t fileformat, const char *classname,
00672 dns_ttl_t maxttl, dns_zone_t **zonep)
00673 {
00674 isc_result_t result;
00675 dns_rdataclass_t rdclass;
00676 isc_textregion_t region;
00677 isc_buffer_t buffer;
00678 dns_fixedname_t fixorigin;
00679 dns_name_t *origin;
00680 dns_zone_t *zone = NULL;
00681
00682 REQUIRE(zonep == NULL || *zonep == NULL);
00683
00684 if (debug)
00685 fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
00686 zonename, filename, classname);
00687
00688 CHECK(dns_zone_create(&zone, mctx));
00689
00690 dns_zone_settype(zone, dns_zone_master);
00691
00692 isc_buffer_constinit(&buffer, zonename, strlen(zonename));
00693 isc_buffer_add(&buffer, strlen(zonename));
00694 dns_fixedname_init(&fixorigin);
00695 origin = dns_fixedname_name(&fixorigin);
00696 CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
00697 CHECK(dns_zone_setorigin(zone, origin));
00698 CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
00699 CHECK(dns_zone_setfile2(zone, filename, fileformat));
00700 if (journal != NULL)
00701 CHECK(dns_zone_setjournal(zone, journal));
00702
00703 DE_CONST(classname, region.base);
00704 region.length = strlen(classname);
00705 CHECK(dns_rdataclass_fromtext(&rdclass, ®ion));
00706
00707 dns_zone_setclass(zone, rdclass);
00708 dns_zone_setoption(zone, zone_options, ISC_TRUE);
00709 dns_zone_setoption2(zone, zone_options2, ISC_TRUE);
00710 dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
00711
00712 dns_zone_setmaxttl(zone, maxttl);
00713
00714 if (docheckmx)
00715 dns_zone_setcheckmx(zone, checkmx);
00716 if (docheckns)
00717 dns_zone_setcheckns(zone, checkns);
00718 if (dochecksrv)
00719 dns_zone_setchecksrv(zone, checksrv);
00720
00721 CHECK(dns_zone_load(zone));
00722
00723
00724
00725
00726
00727 if (fileformat == dns_masterformat_map && maxttl != 0) {
00728 CHECK(check_ttls(zone, maxttl));
00729 }
00730
00731 if (zonep != NULL) {
00732 *zonep = zone;
00733 zone = NULL;
00734 }
00735
00736 cleanup:
00737 if (zone != NULL)
00738 dns_zone_detach(&zone);
00739 return (result);
00740 }
00741
00742
00743 isc_result_t
00744 dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
00745 dns_masterformat_t fileformat, const dns_master_style_t *style,
00746 const isc_uint32_t rawversion)
00747 {
00748 isc_result_t result;
00749 FILE *output = stdout;
00750 const char *flags;
00751
00752 flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+";
00753
00754 if (debug) {
00755 if (filename != NULL && strcmp(filename, "-") != 0)
00756 fprintf(stderr, "dumping \"%s\" to \"%s\"\n",
00757 zonename, filename);
00758 else
00759 fprintf(stderr, "dumping \"%s\"\n", zonename);
00760 }
00761
00762 if (filename != NULL && strcmp(filename, "-") != 0) {
00763 result = isc_stdio_open(filename, flags, &output);
00764
00765 if (result != ISC_R_SUCCESS) {
00766 fprintf(stderr, "could not open output "
00767 "file \"%s\" for writing\n", filename);
00768 return (ISC_R_FAILURE);
00769 }
00770 }
00771
00772 result = dns_zone_dumptostream3(zone, output, fileformat, style,
00773 rawversion);
00774 if (output != stdout)
00775 (void)isc_stdio_close(output);
00776
00777 return (result);
00778 }
00779
00780 #ifdef _WIN32
00781 void
00782 InitSockets(void) {
00783 WORD wVersionRequested;
00784 WSADATA wsaData;
00785 int err;
00786
00787 wVersionRequested = MAKEWORD(2, 0);
00788
00789 err = WSAStartup( wVersionRequested, &wsaData );
00790 if (err != 0) {
00791 fprintf(stderr, "WSAStartup() failed: %d\n", err);
00792 exit(1);
00793 }
00794 }
00795
00796 void
00797 DestroySockets(void) {
00798 WSACleanup();
00799 }
00800 #endif
00801