etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / check / check-tool.c
blob29426691beab2ea5bdaeec3feb5a5a43d7c5fd01
1 /* $NetBSD: check-tool.c,v 1.7 2014/12/10 04:37:51 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: check-tool.c,v 1.44 2011/12/22 07:32:39 each Exp */
22 /*! \file */
24 #include <config.h>
26 #include <stdio.h>
28 #ifdef _WIN32
29 #include <Winsock2.h>
30 #endif
32 #include "check-tool.h"
33 #include <isc/buffer.h>
34 #include <isc/log.h>
35 #include <isc/mem.h>
36 #include <isc/netdb.h>
37 #include <isc/net.h>
38 #include <isc/region.h>
39 #include <isc/stdio.h>
40 #include <isc/string.h>
41 #include <isc/symtab.h>
42 #include <isc/types.h>
43 #include <isc/util.h>
45 #include <dns/db.h>
46 #include <dns/dbiterator.h>
47 #include <dns/fixedname.h>
48 #include <dns/log.h>
49 #include <dns/name.h>
50 #include <dns/rdata.h>
51 #include <dns/rdataclass.h>
52 #include <dns/rdataset.h>
53 #include <dns/rdatasetiter.h>
54 #include <dns/rdatatype.h>
55 #include <dns/result.h>
56 #include <dns/types.h>
57 #include <dns/zone.h>
59 #include <isccfg/log.h>
61 #ifndef CHECK_SIBLING
62 #define CHECK_SIBLING 1
63 #endif
65 #ifndef CHECK_LOCAL
66 #define CHECK_LOCAL 1
67 #endif
69 #ifdef HAVE_ADDRINFO
70 #ifdef HAVE_GETADDRINFO
71 #ifdef HAVE_GAISTRERROR
72 #define USE_GETADDRINFO
73 #endif
74 #endif
75 #endif
77 #define CHECK(r) \
78 do { \
79 result = (r); \
80 if (result != ISC_R_SUCCESS) \
81 goto cleanup; \
82 } while (/*CONSTCOND*/0)
84 #define ERR_IS_CNAME 1
85 #define ERR_NO_ADDRESSES 2
86 #define ERR_LOOKUP_FAILURE 3
87 #define ERR_EXTRA_A 4
88 #define ERR_EXTRA_AAAA 5
89 #define ERR_MISSING_GLUE 5
90 #define ERR_IS_MXCNAME 6
91 #define ERR_IS_SRVCNAME 7
93 static const char *dbtype[] = { "rbt" };
95 int debug = 0;
96 const char *journal = NULL;
97 isc_boolean_t nomerge = ISC_TRUE;
98 #if CHECK_LOCAL
99 isc_boolean_t docheckmx = ISC_TRUE;
100 isc_boolean_t dochecksrv = ISC_TRUE;
101 isc_boolean_t docheckns = ISC_TRUE;
102 #else
103 isc_boolean_t docheckmx = ISC_FALSE;
104 isc_boolean_t dochecksrv = ISC_FALSE;
105 isc_boolean_t docheckns = ISC_FALSE;
106 #endif
107 unsigned int zone_options = DNS_ZONEOPT_CHECKNS |
108 DNS_ZONEOPT_CHECKMX |
109 DNS_ZONEOPT_MANYERRORS |
110 DNS_ZONEOPT_CHECKNAMES |
111 DNS_ZONEOPT_CHECKINTEGRITY |
112 #if CHECK_SIBLING
113 DNS_ZONEOPT_CHECKSIBLING |
114 #endif
115 DNS_ZONEOPT_CHECKWILDCARD |
116 DNS_ZONEOPT_WARNMXCNAME |
117 DNS_ZONEOPT_WARNSRVCNAME;
118 unsigned int zone_options2 = 0;
121 * This needs to match the list in bin/named/log.c.
123 static isc_logcategory_t categories[] = {
124 { "", 0 },
125 { "client", 0 },
126 { "network", 0 },
127 { "update", 0 },
128 { "queries", 0 },
129 { "unmatched", 0 },
130 { "update-security", 0 },
131 { "query-errors", 0 },
132 { NULL, 0 }
135 static isc_symtab_t *symtab = NULL;
136 static isc_mem_t *sym_mctx;
138 static void
139 freekey(char *key, unsigned int type, isc_symvalue_t value, void *userarg) {
140 UNUSED(type);
141 UNUSED(value);
142 isc_mem_free(userarg, key);
145 static void
146 add(char *key, int value) {
147 isc_result_t result;
148 isc_symvalue_t symvalue;
150 if (sym_mctx == NULL) {
151 result = isc_mem_create(0, 0, &sym_mctx);
152 if (result != ISC_R_SUCCESS)
153 return;
156 if (symtab == NULL) {
157 result = isc_symtab_create(sym_mctx, 100, freekey, sym_mctx,
158 ISC_FALSE, &symtab);
159 if (result != ISC_R_SUCCESS)
160 return;
163 key = isc_mem_strdup(sym_mctx, key);
164 if (key == NULL)
165 return;
167 symvalue.as_pointer = NULL;
168 result = isc_symtab_define(symtab, key, value, symvalue,
169 isc_symexists_reject);
170 if (result != ISC_R_SUCCESS)
171 isc_mem_free(sym_mctx, key);
174 static isc_boolean_t
175 logged(char *key, int value) {
176 isc_result_t result;
178 if (symtab == NULL)
179 return (ISC_FALSE);
181 result = isc_symtab_lookup(symtab, key, value, NULL);
182 if (result == ISC_R_SUCCESS)
183 return (ISC_TRUE);
184 return (ISC_FALSE);
187 static isc_boolean_t
188 checkns(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner,
189 dns_rdataset_t *a, dns_rdataset_t *aaaa)
191 #ifdef USE_GETADDRINFO
192 dns_rdataset_t *rdataset;
193 dns_rdata_t rdata = DNS_RDATA_INIT;
194 struct addrinfo hints, *ai, *cur;
195 char namebuf[DNS_NAME_FORMATSIZE + 1];
196 char ownerbuf[DNS_NAME_FORMATSIZE];
197 char addrbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
198 isc_boolean_t answer = ISC_TRUE;
199 isc_boolean_t match;
200 const char *type;
201 void *ptr = NULL;
202 int result;
204 REQUIRE(a == NULL || !dns_rdataset_isassociated(a) ||
205 a->type == dns_rdatatype_a);
206 REQUIRE(aaaa == NULL || !dns_rdataset_isassociated(aaaa) ||
207 aaaa->type == dns_rdatatype_aaaa);
209 if (a == NULL || aaaa == NULL)
210 return (answer);
212 memset(&hints, 0, sizeof(hints));
213 hints.ai_flags = AI_CANONNAME;
214 hints.ai_family = PF_UNSPEC;
215 hints.ai_socktype = SOCK_STREAM;
216 hints.ai_protocol = IPPROTO_TCP;
218 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
220 * Turn off search.
222 if (dns_name_countlabels(name) > 1U)
223 strcat(namebuf, ".");
224 dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
226 result = getaddrinfo(namebuf, NULL, &hints, &ai);
227 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
228 switch (result) {
229 case 0:
231 * Work around broken getaddrinfo() implementations that
232 * fail to set ai_canonname on first entry.
234 cur = ai;
235 while (cur != NULL && cur->ai_canonname == NULL &&
236 cur->ai_next != NULL)
237 cur = cur->ai_next;
238 if (cur != NULL && cur->ai_canonname != NULL &&
239 strcasecmp(cur->ai_canonname, namebuf) != 0 &&
240 !logged(namebuf, ERR_IS_CNAME)) {
241 dns_zone_log(zone, ISC_LOG_ERROR,
242 "%s/NS '%s' (out of zone) "
243 "is a CNAME '%s' (illegal)",
244 ownerbuf, namebuf,
245 cur->ai_canonname);
246 /* XXX950 make fatal for 9.5.0 */
247 /* answer = ISC_FALSE; */
248 add(namebuf, ERR_IS_CNAME);
250 break;
251 case EAI_NONAME:
252 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
253 case EAI_NODATA:
254 #endif
255 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
256 dns_zone_log(zone, ISC_LOG_ERROR,
257 "%s/NS '%s' (out of zone) "
258 "has no addresses records (A or AAAA)",
259 ownerbuf, namebuf);
260 add(namebuf, ERR_NO_ADDRESSES);
262 /* XXX950 make fatal for 9.5.0 */
263 return (ISC_TRUE);
265 default:
266 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
267 dns_zone_log(zone, ISC_LOG_WARNING,
268 "getaddrinfo(%s) failed: %s",
269 namebuf, gai_strerror(result));
270 add(namebuf, ERR_LOOKUP_FAILURE);
272 return (ISC_TRUE);
276 * Check that all glue records really exist.
278 if (!dns_rdataset_isassociated(a))
279 goto checkaaaa;
280 result = dns_rdataset_first(a);
281 while (result == ISC_R_SUCCESS) {
282 dns_rdataset_current(a, &rdata);
283 match = ISC_FALSE;
284 for (cur = ai; cur != NULL; cur = cur->ai_next) {
285 if (cur->ai_family != AF_INET)
286 continue;
287 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
288 if (memcmp(ptr, rdata.data, rdata.length) == 0) {
289 match = ISC_TRUE;
290 break;
293 if (!match && !logged(namebuf, ERR_EXTRA_A)) {
294 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
295 "extra GLUE A record (%s)",
296 ownerbuf, namebuf,
297 inet_ntop(AF_INET, rdata.data,
298 addrbuf, sizeof(addrbuf)));
299 add(namebuf, ERR_EXTRA_A);
300 /* XXX950 make fatal for 9.5.0 */
301 /* answer = ISC_FALSE; */
303 dns_rdata_reset(&rdata);
304 result = dns_rdataset_next(a);
307 checkaaaa:
308 if (!dns_rdataset_isassociated(aaaa))
309 goto checkmissing;
310 result = dns_rdataset_first(aaaa);
311 while (result == ISC_R_SUCCESS) {
312 dns_rdataset_current(aaaa, &rdata);
313 match = ISC_FALSE;
314 for (cur = ai; cur != NULL; cur = cur->ai_next) {
315 if (cur->ai_family != AF_INET6)
316 continue;
317 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
318 if (memcmp(ptr, rdata.data, rdata.length) == 0) {
319 match = ISC_TRUE;
320 break;
323 if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
324 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
325 "extra GLUE AAAA record (%s)",
326 ownerbuf, namebuf,
327 inet_ntop(AF_INET6, rdata.data,
328 addrbuf, sizeof(addrbuf)));
329 add(namebuf, ERR_EXTRA_AAAA);
330 /* XXX950 make fatal for 9.5.0. */
331 /* answer = ISC_FALSE; */
333 dns_rdata_reset(&rdata);
334 result = dns_rdataset_next(aaaa);
337 checkmissing:
339 * Check that all addresses appear in the glue.
341 if (!logged(namebuf, ERR_MISSING_GLUE)) {
342 isc_boolean_t missing_glue = ISC_FALSE;
343 for (cur = ai; cur != NULL; cur = cur->ai_next) {
344 switch (cur->ai_family) {
345 case AF_INET:
346 rdataset = a;
347 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
348 type = "A";
349 break;
350 case AF_INET6:
351 rdataset = aaaa;
352 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
353 type = "AAAA";
354 break;
355 default:
356 continue;
358 match = ISC_FALSE;
359 if (dns_rdataset_isassociated(rdataset))
360 result = dns_rdataset_first(rdataset);
361 else
362 result = ISC_R_FAILURE;
363 while (result == ISC_R_SUCCESS && !match) {
364 dns_rdataset_current(rdataset, &rdata);
365 if (memcmp(ptr, rdata.data, rdata.length) == 0)
366 match = ISC_TRUE;
367 dns_rdata_reset(&rdata);
368 result = dns_rdataset_next(rdataset);
370 if (!match) {
371 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
372 "missing GLUE %s record (%s)",
373 ownerbuf, namebuf, type,
374 inet_ntop(cur->ai_family, ptr,
375 addrbuf, sizeof(addrbuf)));
376 /* XXX950 make fatal for 9.5.0. */
377 /* answer = ISC_FALSE; */
378 missing_glue = ISC_TRUE;
381 if (missing_glue)
382 add(namebuf, ERR_MISSING_GLUE);
384 freeaddrinfo(ai);
385 return (answer);
386 #else
387 return (ISC_TRUE);
388 #endif
391 static isc_boolean_t
392 checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
393 #ifdef USE_GETADDRINFO
394 struct addrinfo hints, *ai, *cur;
395 char namebuf[DNS_NAME_FORMATSIZE + 1];
396 char ownerbuf[DNS_NAME_FORMATSIZE];
397 int result;
398 int level = ISC_LOG_ERROR;
399 isc_boolean_t answer = ISC_TRUE;
401 memset(&hints, 0, sizeof(hints));
402 hints.ai_flags = AI_CANONNAME;
403 hints.ai_family = PF_UNSPEC;
404 hints.ai_socktype = SOCK_STREAM;
405 hints.ai_protocol = IPPROTO_TCP;
407 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
409 * Turn off search.
411 if (dns_name_countlabels(name) > 1U)
412 strcat(namebuf, ".");
413 dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
415 result = getaddrinfo(namebuf, NULL, &hints, &ai);
416 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
417 switch (result) {
418 case 0:
420 * Work around broken getaddrinfo() implementations that
421 * fail to set ai_canonname on first entry.
423 cur = ai;
424 while (cur != NULL && cur->ai_canonname == NULL &&
425 cur->ai_next != NULL)
426 cur = cur->ai_next;
427 if (cur != NULL && cur->ai_canonname != NULL &&
428 strcasecmp(cur->ai_canonname, namebuf) != 0) {
429 if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0)
430 level = ISC_LOG_WARNING;
431 if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
432 if (!logged(namebuf, ERR_IS_MXCNAME)) {
433 dns_zone_log(zone, level,
434 "%s/MX '%s' (out of zone)"
435 " is a CNAME '%s' "
436 "(illegal)",
437 ownerbuf, namebuf,
438 cur->ai_canonname);
439 add(namebuf, ERR_IS_MXCNAME);
441 if (level == ISC_LOG_ERROR)
442 answer = ISC_FALSE;
445 freeaddrinfo(ai);
446 return (answer);
448 case EAI_NONAME:
449 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
450 case EAI_NODATA:
451 #endif
452 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
453 dns_zone_log(zone, ISC_LOG_ERROR,
454 "%s/MX '%s' (out of zone) "
455 "has no addresses records (A or AAAA)",
456 ownerbuf, namebuf);
457 add(namebuf, ERR_NO_ADDRESSES);
459 /* XXX950 make fatal for 9.5.0. */
460 return (ISC_TRUE);
462 default:
463 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
464 dns_zone_log(zone, ISC_LOG_WARNING,
465 "getaddrinfo(%s) failed: %s",
466 namebuf, gai_strerror(result));
467 add(namebuf, ERR_LOOKUP_FAILURE);
469 return (ISC_TRUE);
471 #else
472 return (ISC_TRUE);
473 #endif
476 static isc_boolean_t
477 checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
478 #ifdef USE_GETADDRINFO
479 struct addrinfo hints, *ai, *cur;
480 char namebuf[DNS_NAME_FORMATSIZE + 1];
481 char ownerbuf[DNS_NAME_FORMATSIZE];
482 int result;
483 int level = ISC_LOG_ERROR;
484 isc_boolean_t answer = ISC_TRUE;
486 memset(&hints, 0, sizeof(hints));
487 hints.ai_flags = AI_CANONNAME;
488 hints.ai_family = PF_UNSPEC;
489 hints.ai_socktype = SOCK_STREAM;
490 hints.ai_protocol = IPPROTO_TCP;
492 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
494 * Turn off search.
496 if (dns_name_countlabels(name) > 1U)
497 strcat(namebuf, ".");
498 dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
500 result = getaddrinfo(namebuf, NULL, &hints, &ai);
501 dns_name_format(name, namebuf, sizeof(namebuf) - 1);
502 switch (result) {
503 case 0:
505 * Work around broken getaddrinfo() implementations that
506 * fail to set ai_canonname on first entry.
508 cur = ai;
509 while (cur != NULL && cur->ai_canonname == NULL &&
510 cur->ai_next != NULL)
511 cur = cur->ai_next;
512 if (cur != NULL && cur->ai_canonname != NULL &&
513 strcasecmp(cur->ai_canonname, namebuf) != 0) {
514 if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
515 level = ISC_LOG_WARNING;
516 if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
517 if (!logged(namebuf, ERR_IS_SRVCNAME)) {
518 dns_zone_log(zone, level, "%s/SRV '%s'"
519 " (out of zone) is a "
520 "CNAME '%s' (illegal)",
521 ownerbuf, namebuf,
522 cur->ai_canonname);
523 add(namebuf, ERR_IS_SRVCNAME);
525 if (level == ISC_LOG_ERROR)
526 answer = ISC_FALSE;
529 freeaddrinfo(ai);
530 return (answer);
532 case EAI_NONAME:
533 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
534 case EAI_NODATA:
535 #endif
536 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
537 dns_zone_log(zone, ISC_LOG_ERROR,
538 "%s/SRV '%s' (out of zone) "
539 "has no addresses records (A or AAAA)",
540 ownerbuf, namebuf);
541 add(namebuf, ERR_NO_ADDRESSES);
543 /* XXX950 make fatal for 9.5.0. */
544 return (ISC_TRUE);
546 default:
547 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
548 dns_zone_log(zone, ISC_LOG_WARNING,
549 "getaddrinfo(%s) failed: %s",
550 namebuf, gai_strerror(result));
551 add(namebuf, ERR_LOOKUP_FAILURE);
553 return (ISC_TRUE);
555 #else
556 return (ISC_TRUE);
557 #endif
560 isc_result_t
561 setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
562 isc_logdestination_t destination;
563 isc_logconfig_t *logconfig = NULL;
564 isc_log_t *log = NULL;
566 RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
567 isc_log_registercategories(log, categories);
568 isc_log_setcontext(log);
569 dns_log_init(log);
570 dns_log_setcontext(log);
571 cfg_log_init(log);
573 destination.file.stream = errout;
574 destination.file.name = NULL;
575 destination.file.versions = ISC_LOG_ROLLNEVER;
576 destination.file.maximum_size = 0;
577 RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr",
578 ISC_LOG_TOFILEDESC,
579 ISC_LOG_DYNAMIC,
580 &destination, 0) == ISC_R_SUCCESS);
581 RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
582 NULL, NULL) == ISC_R_SUCCESS);
584 *logp = log;
585 return (ISC_R_SUCCESS);
588 /*% scan the zone for oversize TTLs */
589 static isc_result_t
590 check_ttls(dns_zone_t *zone, dns_ttl_t maxttl) {
591 isc_result_t result;
592 dns_db_t *db = NULL;
593 dns_dbversion_t *version = NULL;
594 dns_dbnode_t *node = NULL;
595 dns_dbiterator_t *dbiter = NULL;
596 dns_rdatasetiter_t *rdsiter = NULL;
597 dns_rdataset_t rdataset;
598 dns_fixedname_t fname;
599 dns_name_t *name;
600 dns_fixedname_init(&fname);
601 name = dns_fixedname_name(&fname);
602 dns_rdataset_init(&rdataset);
604 CHECK(dns_zone_getdb(zone, &db));
605 INSIST(db != NULL);
607 CHECK(dns_db_newversion(db, &version));
608 CHECK(dns_db_createiterator(db, 0, &dbiter));
610 for (result = dns_dbiterator_first(dbiter);
611 result == ISC_R_SUCCESS;
612 result = dns_dbiterator_next(dbiter)) {
613 result = dns_dbiterator_current(dbiter, &node, name);
614 if (result == DNS_R_NEWORIGIN)
615 result = ISC_R_SUCCESS;
616 CHECK(result);
618 CHECK(dns_db_allrdatasets(db, node, version, 0, &rdsiter));
619 for (result = dns_rdatasetiter_first(rdsiter);
620 result == ISC_R_SUCCESS;
621 result = dns_rdatasetiter_next(rdsiter)) {
622 dns_rdatasetiter_current(rdsiter, &rdataset);
623 if (rdataset.ttl > maxttl) {
624 char nbuf[DNS_NAME_FORMATSIZE];
625 char tbuf[255];
626 isc_buffer_t b;
627 isc_region_t r;
629 dns_name_format(name, nbuf, sizeof(nbuf));
630 isc_buffer_init(&b, tbuf, sizeof(tbuf) - 1);
631 CHECK(dns_rdatatype_totext(rdataset.type, &b));
632 isc_buffer_usedregion(&b, &r);
633 r.base[r.length] = 0;
635 dns_zone_log(zone, ISC_LOG_ERROR,
636 "%s/%s TTL %d exceeds "
637 "maximum TTL %d",
638 nbuf, tbuf, rdataset.ttl, maxttl);
639 dns_rdataset_disassociate(&rdataset);
640 CHECK(ISC_R_RANGE);
642 dns_rdataset_disassociate(&rdataset);
644 if (result == ISC_R_NOMORE)
645 result = ISC_R_SUCCESS;
646 CHECK(result);
648 dns_rdatasetiter_destroy(&rdsiter);
649 dns_db_detachnode(db, &node);
652 if (result == ISC_R_NOMORE)
653 result = ISC_R_SUCCESS;
655 cleanup:
656 if (node != NULL)
657 dns_db_detachnode(db, &node);
658 if (rdsiter != NULL)
659 dns_rdatasetiter_destroy(&rdsiter);
660 if (dbiter != NULL)
661 dns_dbiterator_destroy(&dbiter);
662 if (version != NULL)
663 dns_db_closeversion(db, &version, ISC_FALSE);
664 if (db != NULL)
665 dns_db_detach(&db);
667 return (result);
670 /*% load the zone */
671 isc_result_t
672 load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
673 dns_masterformat_t fileformat, const char *classname,
674 dns_ttl_t maxttl, dns_zone_t **zonep)
676 isc_result_t result;
677 dns_rdataclass_t rdclass;
678 isc_textregion_t region;
679 isc_buffer_t buffer;
680 dns_fixedname_t fixorigin;
681 dns_name_t *origin;
682 dns_zone_t *zone = NULL;
684 REQUIRE(zonep == NULL || *zonep == NULL);
686 if (debug)
687 fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
688 zonename, filename, classname);
690 CHECK(dns_zone_create(&zone, mctx));
692 dns_zone_settype(zone, dns_zone_master);
694 isc_buffer_constinit(&buffer, zonename, strlen(zonename));
695 isc_buffer_add(&buffer, strlen(zonename));
696 dns_fixedname_init(&fixorigin);
697 origin = dns_fixedname_name(&fixorigin);
698 CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
699 CHECK(dns_zone_setorigin(zone, origin));
700 CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
701 CHECK(dns_zone_setfile2(zone, filename, fileformat));
702 if (journal != NULL)
703 CHECK(dns_zone_setjournal(zone, journal));
705 DE_CONST(classname, region.base);
706 region.length = strlen(classname);
707 CHECK(dns_rdataclass_fromtext(&rdclass, &region));
709 dns_zone_setclass(zone, rdclass);
710 dns_zone_setoption(zone, zone_options, ISC_TRUE);
711 dns_zone_setoption2(zone, zone_options2, ISC_TRUE);
712 dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
714 dns_zone_setmaxttl(zone, maxttl);
716 if (docheckmx)
717 dns_zone_setcheckmx(zone, checkmx);
718 if (docheckns)
719 dns_zone_setcheckns(zone, checkns);
720 if (dochecksrv)
721 dns_zone_setchecksrv(zone, checksrv);
723 CHECK(dns_zone_load(zone));
726 * When loading map files we can't catch oversize TTLs during
727 * load, so we check for them here.
729 if (fileformat == dns_masterformat_map && maxttl != 0) {
730 CHECK(check_ttls(zone, maxttl));
733 if (zonep != NULL) {
734 *zonep = zone;
735 zone = NULL;
738 cleanup:
739 if (zone != NULL)
740 dns_zone_detach(&zone);
741 return (result);
744 /*% dump the zone */
745 isc_result_t
746 dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
747 dns_masterformat_t fileformat, const dns_master_style_t *style,
748 const isc_uint32_t rawversion)
750 isc_result_t result;
751 FILE *output = stdout;
752 const char *flags;
754 flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+";
756 if (debug) {
757 if (filename != NULL && strcmp(filename, "-") != 0)
758 fprintf(stderr, "dumping \"%s\" to \"%s\"\n",
759 zonename, filename);
760 else
761 fprintf(stderr, "dumping \"%s\"\n", zonename);
764 if (filename != NULL && strcmp(filename, "-") != 0) {
765 result = isc_stdio_open(filename, flags, &output);
767 if (result != ISC_R_SUCCESS) {
768 fprintf(stderr, "could not open output "
769 "file \"%s\" for writing\n", filename);
770 return (ISC_R_FAILURE);
774 result = dns_zone_dumptostream3(zone, output, fileformat, style,
775 rawversion);
776 if (output != stdout)
777 (void)isc_stdio_close(output);
779 return (result);
782 #ifdef _WIN32
783 void
784 InitSockets(void) {
785 WORD wVersionRequested;
786 WSADATA wsaData;
787 int err;
789 wVersionRequested = MAKEWORD(2, 0);
791 err = WSAStartup( wVersionRequested, &wsaData );
792 if (err != 0) {
793 fprintf(stderr, "WSAStartup() failed: %d\n", err);
794 exit(1);
798 void
799 DestroySockets(void) {
800 WSACleanup();
802 #endif