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