]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/bind9/bin/check/check-tool.c
MFC 253983, 253984:
[FreeBSD/stable/9.git] / contrib / bind9 / bin / check / check-tool.c
1 /*
2  * Copyright (C) 2004-2010, 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.41 2010/09/07 23:46:59 tbox 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
86 static const char *dbtype[] = { "rbt" };
87
88 int debug = 0;
89 isc_boolean_t nomerge = ISC_TRUE;
90 #if CHECK_LOCAL
91 isc_boolean_t docheckmx = ISC_TRUE;
92 isc_boolean_t dochecksrv = ISC_TRUE;
93 isc_boolean_t docheckns = ISC_TRUE;
94 #else
95 isc_boolean_t docheckmx = ISC_FALSE;
96 isc_boolean_t dochecksrv = ISC_FALSE;
97 isc_boolean_t docheckns = ISC_FALSE;
98 #endif
99 unsigned 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  */
114 static 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
126 static isc_symtab_t *symtab = NULL;
127 static isc_mem_t *sym_mctx;
128
129 static void
130 freekey(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
136 static void
137 add(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
165 static isc_boolean_t
166 logged(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
178 static isc_boolean_t
179 checkns(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
382 static isc_boolean_t
383 checkmx(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
467 static isc_boolean_t
468 checksrv(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
551 isc_result_t
552 setup_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 */
580 isc_result_t
581 load_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, &region));
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 */
639 isc_result_t
640 dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
641           dns_masterformat_t fileformat, const dns_master_style_t *style)
642 {
643         isc_result_t result;
644         FILE *output = stdout;
645         const char *flags;
646
647         flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+";
648
649         if (debug) {
650                 if (filename != NULL && strcmp(filename, "-") != 0)
651                         fprintf(stderr, "dumping \"%s\" to \"%s\"\n",
652                                 zonename, filename);
653                 else
654                         fprintf(stderr, "dumping \"%s\"\n", zonename);
655         }
656
657         if (filename != NULL && strcmp(filename, "-") != 0) {
658                 result = isc_stdio_open(filename, flags, &output);
659
660                 if (result != ISC_R_SUCCESS) {
661                         fprintf(stderr, "could not open output "
662                                 "file \"%s\" for writing\n", filename);
663                         return (ISC_R_FAILURE);
664                 }
665         }
666
667         result = dns_zone_dumptostream2(zone, output, fileformat, style);
668
669         if (output != stdout)
670                 (void)isc_stdio_close(output);
671
672         return (result);
673 }
674
675 #ifdef _WIN32
676 void
677 InitSockets(void) {
678         WORD wVersionRequested;
679         WSADATA wsaData;
680         int err;
681
682         wVersionRequested = MAKEWORD(2, 0);
683
684         err = WSAStartup( wVersionRequested, &wsaData );
685         if (err != 0) {
686                 fprintf(stderr, "WSAStartup() failed: %d\n", err);
687                 exit(1);
688         }
689 }
690
691 void
692 DestroySockets(void) {
693         WSACleanup();
694 }
695 #endif
696