]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/bin/check/check-tool.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / bind9 / bin / check / check-tool.c
1 /*
2  * Copyright (C) 2004-2010  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         memset(&hints, 0, sizeof(hints));
200         hints.ai_flags = AI_CANONNAME;
201         hints.ai_family = PF_UNSPEC;
202         hints.ai_socktype = SOCK_STREAM;
203         hints.ai_protocol = IPPROTO_TCP;
204
205         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
206         /*
207          * Turn off search.
208          */
209         if (dns_name_countlabels(name) > 1U)
210                 strcat(namebuf, ".");
211         dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
212
213         result = getaddrinfo(namebuf, NULL, &hints, &ai);
214         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
215         switch (result) {
216         case 0:
217                 /*
218                  * Work around broken getaddrinfo() implementations that
219                  * fail to set ai_canonname on first entry.
220                  */
221                 cur = ai;
222                 while (cur != NULL && cur->ai_canonname == NULL &&
223                        cur->ai_next != NULL)
224                         cur = cur->ai_next;
225                 if (cur != NULL && cur->ai_canonname != NULL &&
226                     strcasecmp(cur->ai_canonname, namebuf) != 0 &&
227                     !logged(namebuf, ERR_IS_CNAME)) {
228                         dns_zone_log(zone, ISC_LOG_ERROR,
229                                      "%s/NS '%s' (out of zone) "
230                                      "is a CNAME '%s' (illegal)",
231                                      ownerbuf, namebuf,
232                                      cur->ai_canonname);
233                         /* XXX950 make fatal for 9.5.0 */
234                         /* answer = ISC_FALSE; */
235                         add(namebuf, ERR_IS_CNAME);
236                 }
237                 break;
238         case EAI_NONAME:
239 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
240         case EAI_NODATA:
241 #endif
242                 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
243                         dns_zone_log(zone, ISC_LOG_ERROR,
244                                      "%s/NS '%s' (out of zone) "
245                                      "has no addresses records (A or AAAA)",
246                                      ownerbuf, namebuf);
247                         add(namebuf, ERR_NO_ADDRESSES);
248                 }
249                 /* XXX950 make fatal for 9.5.0 */
250                 return (ISC_TRUE);
251
252         default:
253                 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
254                         dns_zone_log(zone, ISC_LOG_WARNING,
255                                      "getaddrinfo(%s) failed: %s",
256                                      namebuf, gai_strerror(result));
257                         add(namebuf, ERR_LOOKUP_FAILURE);
258                 }
259                 return (ISC_TRUE);
260         }
261         if (a == NULL || aaaa == NULL)
262                 return (answer);
263         /*
264          * Check that all glue records really exist.
265          */
266         if (!dns_rdataset_isassociated(a))
267                 goto checkaaaa;
268         result = dns_rdataset_first(a);
269         while (result == ISC_R_SUCCESS) {
270                 dns_rdataset_current(a, &rdata);
271                 match = ISC_FALSE;
272                 for (cur = ai; cur != NULL; cur = cur->ai_next) {
273                         if (cur->ai_family != AF_INET)
274                                 continue;
275                         ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
276                         if (memcmp(ptr, rdata.data, rdata.length) == 0) {
277                                 match = ISC_TRUE;
278                                 break;
279                         }
280                 }
281                 if (!match && !logged(namebuf, ERR_EXTRA_A)) {
282                         dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
283                                      "extra GLUE A record (%s)",
284                                      ownerbuf, namebuf,
285                                      inet_ntop(AF_INET, rdata.data,
286                                                addrbuf, sizeof(addrbuf)));
287                         add(namebuf, ERR_EXTRA_A);
288                         /* XXX950 make fatal for 9.5.0 */
289                         /* answer = ISC_FALSE; */
290                 }
291                 dns_rdata_reset(&rdata);
292                 result = dns_rdataset_next(a);
293         }
294
295  checkaaaa:
296         if (!dns_rdataset_isassociated(aaaa))
297                 goto checkmissing;
298         result = dns_rdataset_first(aaaa);
299         while (result == ISC_R_SUCCESS) {
300                 dns_rdataset_current(aaaa, &rdata);
301                 match = ISC_FALSE;
302                 for (cur = ai; cur != NULL; cur = cur->ai_next) {
303                         if (cur->ai_family != AF_INET6)
304                                 continue;
305                         ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
306                         if (memcmp(ptr, rdata.data, rdata.length) == 0) {
307                                 match = ISC_TRUE;
308                                 break;
309                         }
310                 }
311                 if (!match && !logged(namebuf, ERR_EXTRA_AAAA)) {
312                         dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
313                                      "extra GLUE AAAA record (%s)",
314                                      ownerbuf, namebuf,
315                                      inet_ntop(AF_INET6, rdata.data,
316                                                addrbuf, sizeof(addrbuf)));
317                         add(namebuf, ERR_EXTRA_AAAA);
318                         /* XXX950 make fatal for 9.5.0. */
319                         /* answer = ISC_FALSE; */
320                 }
321                 dns_rdata_reset(&rdata);
322                 result = dns_rdataset_next(aaaa);
323         }
324
325  checkmissing:
326         /*
327          * Check that all addresses appear in the glue.
328          */
329         if (!logged(namebuf, ERR_MISSING_GLUE)) {
330                 isc_boolean_t missing_glue = ISC_FALSE;
331                 for (cur = ai; cur != NULL; cur = cur->ai_next) {
332                         switch (cur->ai_family) {
333                         case AF_INET:
334                                 rdataset = a;
335                                 ptr = &((struct sockaddr_in *)(cur->ai_addr))->sin_addr;
336                                 type = "A";
337                                 break;
338                         case AF_INET6:
339                                 rdataset = aaaa;
340                                 ptr = &((struct sockaddr_in6 *)(cur->ai_addr))->sin6_addr;
341                                 type = "AAAA";
342                                 break;
343                         default:
344                                  continue;
345                         }
346                         match = ISC_FALSE;
347                         if (dns_rdataset_isassociated(rdataset))
348                                 result = dns_rdataset_first(rdataset);
349                         else
350                                 result = ISC_R_FAILURE;
351                         while (result == ISC_R_SUCCESS && !match) {
352                                 dns_rdataset_current(rdataset, &rdata);
353                                 if (memcmp(ptr, rdata.data, rdata.length) == 0)
354                                         match = ISC_TRUE;
355                                 dns_rdata_reset(&rdata);
356                                 result = dns_rdataset_next(rdataset);
357                         }
358                         if (!match) {
359                                 dns_zone_log(zone, ISC_LOG_ERROR, "%s/NS '%s' "
360                                              "missing GLUE %s record (%s)",
361                                              ownerbuf, namebuf, type,
362                                              inet_ntop(cur->ai_family, ptr,
363                                                        addrbuf, sizeof(addrbuf)));
364                                 /* XXX950 make fatal for 9.5.0. */
365                                 /* answer = ISC_FALSE; */
366                                 missing_glue = ISC_TRUE;
367                         }
368                 }
369                 if (missing_glue)
370                         add(namebuf, ERR_MISSING_GLUE);
371         }
372         freeaddrinfo(ai);
373         return (answer);
374 #else
375         return (ISC_TRUE);
376 #endif
377 }
378
379 static isc_boolean_t
380 checkmx(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
381 #ifdef USE_GETADDRINFO
382         struct addrinfo hints, *ai, *cur;
383         char namebuf[DNS_NAME_FORMATSIZE + 1];
384         char ownerbuf[DNS_NAME_FORMATSIZE];
385         int result;
386         int level = ISC_LOG_ERROR;
387         isc_boolean_t answer = ISC_TRUE;
388
389         memset(&hints, 0, sizeof(hints));
390         hints.ai_flags = AI_CANONNAME;
391         hints.ai_family = PF_UNSPEC;
392         hints.ai_socktype = SOCK_STREAM;
393         hints.ai_protocol = IPPROTO_TCP;
394
395         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
396         /*
397          * Turn off search.
398          */
399         if (dns_name_countlabels(name) > 1U)
400                 strcat(namebuf, ".");
401         dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
402
403         result = getaddrinfo(namebuf, NULL, &hints, &ai);
404         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
405         switch (result) {
406         case 0:
407                 /*
408                  * Work around broken getaddrinfo() implementations that
409                  * fail to set ai_canonname on first entry.
410                  */
411                 cur = ai;
412                 while (cur != NULL && cur->ai_canonname == NULL &&
413                        cur->ai_next != NULL)
414                         cur = cur->ai_next;
415                 if (cur != NULL && cur->ai_canonname != NULL &&
416                     strcasecmp(cur->ai_canonname, namebuf) != 0) {
417                         if ((zone_options & DNS_ZONEOPT_WARNMXCNAME) != 0)
418                                 level = ISC_LOG_WARNING;
419                         if ((zone_options & DNS_ZONEOPT_IGNOREMXCNAME) == 0) {
420                                 if (!logged(namebuf, ERR_IS_MXCNAME)) {
421                                         dns_zone_log(zone, level,
422                                                      "%s/MX '%s' (out of zone)"
423                                                      " is a CNAME '%s' "
424                                                      "(illegal)",
425                                                      ownerbuf, namebuf,
426                                                      cur->ai_canonname);
427                                         add(namebuf, ERR_IS_MXCNAME);
428                                 }
429                                 if (level == ISC_LOG_ERROR)
430                                         answer = ISC_FALSE;
431                         }
432                 }
433                 freeaddrinfo(ai);
434                 return (answer);
435
436         case EAI_NONAME:
437 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
438         case EAI_NODATA:
439 #endif
440                 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
441                         dns_zone_log(zone, ISC_LOG_ERROR,
442                                      "%s/MX '%s' (out of zone) "
443                                      "has no addresses records (A or AAAA)",
444                                      ownerbuf, namebuf);
445                         add(namebuf, ERR_NO_ADDRESSES);
446                 }
447                 /* XXX950 make fatal for 9.5.0. */
448                 return (ISC_TRUE);
449
450         default:
451                 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
452                         dns_zone_log(zone, ISC_LOG_WARNING,
453                              "getaddrinfo(%s) failed: %s",
454                              namebuf, gai_strerror(result));
455                         add(namebuf, ERR_LOOKUP_FAILURE);
456                 }
457                 return (ISC_TRUE);
458         }
459 #else
460         return (ISC_TRUE);
461 #endif
462 }
463
464 static isc_boolean_t
465 checksrv(dns_zone_t *zone, dns_name_t *name, dns_name_t *owner) {
466 #ifdef USE_GETADDRINFO
467         struct addrinfo hints, *ai, *cur;
468         char namebuf[DNS_NAME_FORMATSIZE + 1];
469         char ownerbuf[DNS_NAME_FORMATSIZE];
470         int result;
471         int level = ISC_LOG_ERROR;
472         isc_boolean_t answer = ISC_TRUE;
473
474         memset(&hints, 0, sizeof(hints));
475         hints.ai_flags = AI_CANONNAME;
476         hints.ai_family = PF_UNSPEC;
477         hints.ai_socktype = SOCK_STREAM;
478         hints.ai_protocol = IPPROTO_TCP;
479
480         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
481         /*
482          * Turn off search.
483          */
484         if (dns_name_countlabels(name) > 1U)
485                 strcat(namebuf, ".");
486         dns_name_format(owner, ownerbuf, sizeof(ownerbuf));
487
488         result = getaddrinfo(namebuf, NULL, &hints, &ai);
489         dns_name_format(name, namebuf, sizeof(namebuf) - 1);
490         switch (result) {
491         case 0:
492                 /*
493                  * Work around broken getaddrinfo() implementations that
494                  * fail to set ai_canonname on first entry.
495                  */
496                 cur = ai;
497                 while (cur != NULL && cur->ai_canonname == NULL &&
498                        cur->ai_next != NULL)
499                         cur = cur->ai_next;
500                 if (cur != NULL && cur->ai_canonname != NULL &&
501                     strcasecmp(cur->ai_canonname, namebuf) != 0) {
502                         if ((zone_options & DNS_ZONEOPT_WARNSRVCNAME) != 0)
503                                 level = ISC_LOG_WARNING;
504                         if ((zone_options & DNS_ZONEOPT_IGNORESRVCNAME) == 0) {
505                                 if (!logged(namebuf, ERR_IS_SRVCNAME)) {
506                                         dns_zone_log(zone, level, "%s/SRV '%s'"
507                                                      " (out of zone) is a "
508                                                      "CNAME '%s' (illegal)",
509                                                      ownerbuf, namebuf,
510                                                      cur->ai_canonname);
511                                         add(namebuf, ERR_IS_SRVCNAME);
512                                 }
513                                 if (level == ISC_LOG_ERROR)
514                                         answer = ISC_FALSE;
515                         }
516                 }
517                 freeaddrinfo(ai);
518                 return (answer);
519
520         case EAI_NONAME:
521 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
522         case EAI_NODATA:
523 #endif
524                 if (!logged(namebuf, ERR_NO_ADDRESSES)) {
525                         dns_zone_log(zone, ISC_LOG_ERROR,
526                                      "%s/SRV '%s' (out of zone) "
527                                      "has no addresses records (A or AAAA)",
528                                      ownerbuf, namebuf);
529                         add(namebuf, ERR_NO_ADDRESSES);
530                 }
531                 /* XXX950 make fatal for 9.5.0. */
532                 return (ISC_TRUE);
533
534         default:
535                 if (!logged(namebuf, ERR_LOOKUP_FAILURE)) {
536                         dns_zone_log(zone, ISC_LOG_WARNING,
537                                      "getaddrinfo(%s) failed: %s",
538                                      namebuf, gai_strerror(result));
539                         add(namebuf, ERR_LOOKUP_FAILURE);
540                 }
541                 return (ISC_TRUE);
542         }
543 #else
544         return (ISC_TRUE);
545 #endif
546 }
547
548 isc_result_t
549 setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
550         isc_logdestination_t destination;
551         isc_logconfig_t *logconfig = NULL;
552         isc_log_t *log = NULL;
553
554         RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) == ISC_R_SUCCESS);
555         isc_log_registercategories(log, categories);
556         isc_log_setcontext(log);
557         dns_log_init(log);
558         dns_log_setcontext(log);
559         cfg_log_init(log);
560
561         destination.file.stream = errout;
562         destination.file.name = NULL;
563         destination.file.versions = ISC_LOG_ROLLNEVER;
564         destination.file.maximum_size = 0;
565         RUNTIME_CHECK(isc_log_createchannel(logconfig, "stderr",
566                                        ISC_LOG_TOFILEDESC,
567                                        ISC_LOG_DYNAMIC,
568                                        &destination, 0) == ISC_R_SUCCESS);
569         RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr",
570                                          NULL, NULL) == ISC_R_SUCCESS);
571
572         *logp = log;
573         return (ISC_R_SUCCESS);
574 }
575
576 /*% load the zone */
577 isc_result_t
578 load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
579           dns_masterformat_t fileformat, const char *classname,
580           dns_zone_t **zonep)
581 {
582         isc_result_t result;
583         dns_rdataclass_t rdclass;
584         isc_textregion_t region;
585         isc_buffer_t buffer;
586         dns_fixedname_t fixorigin;
587         dns_name_t *origin;
588         dns_zone_t *zone = NULL;
589
590         REQUIRE(zonep == NULL || *zonep == NULL);
591
592         if (debug)
593                 fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
594                         zonename, filename, classname);
595
596         CHECK(dns_zone_create(&zone, mctx));
597
598         dns_zone_settype(zone, dns_zone_master);
599
600         isc_buffer_init(&buffer, zonename, strlen(zonename));
601         isc_buffer_add(&buffer, strlen(zonename));
602         dns_fixedname_init(&fixorigin);
603         origin = dns_fixedname_name(&fixorigin);
604         CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
605         CHECK(dns_zone_setorigin(zone, origin));
606         CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
607         CHECK(dns_zone_setfile2(zone, filename, fileformat));
608
609         DE_CONST(classname, region.base);
610         region.length = strlen(classname);
611         CHECK(dns_rdataclass_fromtext(&rdclass, &region));
612
613         dns_zone_setclass(zone, rdclass);
614         dns_zone_setoption(zone, zone_options, ISC_TRUE);
615         dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
616         if (docheckmx)
617                 dns_zone_setcheckmx(zone, checkmx);
618         if (docheckns)
619                 dns_zone_setcheckns(zone, checkns);
620         if (dochecksrv)
621                 dns_zone_setchecksrv(zone, checksrv);
622
623         CHECK(dns_zone_load(zone));
624         if (zonep != NULL) {
625                 *zonep = zone;
626                 zone = NULL;
627         }
628
629  cleanup:
630         if (zone != NULL)
631                 dns_zone_detach(&zone);
632         return (result);
633 }
634
635 /*% dump the zone */
636 isc_result_t
637 dump_zone(const char *zonename, dns_zone_t *zone, const char *filename,
638           dns_masterformat_t fileformat, const dns_master_style_t *style)
639 {
640         isc_result_t result;
641         FILE *output = stdout;
642         const char *flags;
643
644         flags = (fileformat == dns_masterformat_text) ? "w+" : "wb+";
645
646         if (debug) {
647                 if (filename != NULL && strcmp(filename, "-") != 0)
648                         fprintf(stderr, "dumping \"%s\" to \"%s\"\n",
649                                 zonename, filename);
650                 else
651                         fprintf(stderr, "dumping \"%s\"\n", zonename);
652         }
653
654         if (filename != NULL && strcmp(filename, "-") != 0) {
655                 result = isc_stdio_open(filename, flags, &output);
656
657                 if (result != ISC_R_SUCCESS) {
658                         fprintf(stderr, "could not open output "
659                                 "file \"%s\" for writing\n", filename);
660                         return (ISC_R_FAILURE);
661                 }
662         }
663
664         result = dns_zone_dumptostream2(zone, output, fileformat, style);
665
666         if (output != stdout)
667                 (void)isc_stdio_close(output);
668
669         return (result);
670 }
671
672 #ifdef _WIN32
673 void
674 InitSockets(void) {
675         WORD wVersionRequested;
676         WSADATA wsaData;
677         int err;
678
679         wVersionRequested = MAKEWORD(2, 0);
680
681         err = WSAStartup( wVersionRequested, &wsaData );
682         if (err != 0) {
683                 fprintf(stderr, "WSAStartup() failed: %d\n", err);
684                 exit(1);
685         }
686 }
687
688 void
689 DestroySockets(void) {
690         WSACleanup();
691 }
692 #endif
693