1135446Strhodes/*
2254402Serwin * Copyright (C) 2004-2013  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 1999-2003  Internet Software Consortium.
4135446Strhodes *
5174187Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18254897Serwin/* $Id: named-checkzone.c,v 1.65 2011/12/22 17:29:22 each Exp $ */
19135446Strhodes
20170222Sdougb/*! \file */
21170222Sdougb
22135446Strhodes#include <config.h>
23135446Strhodes
24135446Strhodes#include <stdlib.h>
25135446Strhodes
26135446Strhodes#include <isc/app.h>
27135446Strhodes#include <isc/commandline.h>
28135446Strhodes#include <isc/dir.h>
29143731Sdougb#include <isc/entropy.h>
30143731Sdougb#include <isc/hash.h>
31135446Strhodes#include <isc/log.h>
32135446Strhodes#include <isc/mem.h>
33135446Strhodes#include <isc/socket.h>
34135446Strhodes#include <isc/string.h>
35135446Strhodes#include <isc/task.h>
36135446Strhodes#include <isc/timer.h>
37135446Strhodes#include <isc/util.h>
38135446Strhodes
39135446Strhodes#include <dns/db.h>
40135446Strhodes#include <dns/fixedname.h>
41135446Strhodes#include <dns/log.h>
42254897Serwin#include <dns/master.h>
43170222Sdougb#include <dns/masterdump.h>
44170222Sdougb#include <dns/name.h>
45135446Strhodes#include <dns/rdataclass.h>
46135446Strhodes#include <dns/rdataset.h>
47135446Strhodes#include <dns/result.h>
48170222Sdougb#include <dns/types.h>
49135446Strhodes#include <dns/zone.h>
50135446Strhodes
51135446Strhodes#include "check-tool.h"
52135446Strhodes
53135446Strhodesstatic int quiet = 0;
54135446Strhodesstatic isc_mem_t *mctx = NULL;
55143731Sdougbstatic isc_entropy_t *ectx = NULL;
56135446Strhodesdns_zone_t *zone = NULL;
57135446Strhodesdns_zonetype_t zonetype = dns_zone_master;
58135446Strhodesstatic int dumpzone = 0;
59135446Strhodesstatic const char *output_filename;
60170222Sdougbstatic char *prog_name = NULL;
61170222Sdougbstatic const dns_master_style_t *outputstyle = NULL;
62170222Sdougbstatic enum { progmode_check, progmode_compile } progmode;
63135446Strhodes
64135446Strhodes#define ERRRET(result, function) \
65135446Strhodes	do { \
66135446Strhodes		if (result != ISC_R_SUCCESS) { \
67135446Strhodes			if (!quiet) \
68135446Strhodes				fprintf(stderr, "%s() returned %s\n", \
69135446Strhodes					function, dns_result_totext(result)); \
70135446Strhodes			return (result); \
71135446Strhodes		} \
72135446Strhodes	} while (0)
73135446Strhodes
74224092SdougbISC_PLATFORM_NORETURN_PRE static void
75224092Sdougbusage(void) ISC_PLATFORM_NORETURN_POST;
76224092Sdougb
77135446Strhodesstatic void
78135446Strhodesusage(void) {
79135446Strhodes	fprintf(stderr,
80204619Sdougb		"usage: %s [-djqvD] [-c class] "
81170222Sdougb		"[-f inputformat] [-F outputformat] "
82143731Sdougb		"[-t directory] [-w directory] [-k (ignore|warn|fail)] "
83170222Sdougb		"[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
84224092Sdougb		"[-r (ignore|warn|fail)] "
85186462Sdougb		"[-i (full|full-sibling|local|local-sibling|none)] "
86186462Sdougb		"[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
87186462Sdougb		"[-W (ignore|warn)] "
88204619Sdougb		"%s zonename filename\n",
89204619Sdougb		prog_name,
90224092Sdougb		progmode == progmode_check ? "[-o filename]" : "-o filename");
91135446Strhodes	exit(1);
92135446Strhodes}
93135446Strhodes
94135446Strhodesstatic void
95135446Strhodesdestroy(void) {
96135446Strhodes	if (zone != NULL)
97135446Strhodes		dns_zone_detach(&zone);
98170222Sdougb	dns_name_destroy();
99135446Strhodes}
100135446Strhodes
101170222Sdougb/*% main processing routine */
102135446Strhodesint
103135446Strhodesmain(int argc, char **argv) {
104135446Strhodes	int c;
105135446Strhodes	char *origin = NULL;
106135446Strhodes	char *filename = NULL;
107135446Strhodes	isc_log_t *lctx = NULL;
108135446Strhodes	isc_result_t result;
109135446Strhodes	char classname_in[] = "IN";
110135446Strhodes	char *classname = classname_in;
111135446Strhodes	const char *workdir = NULL;
112170222Sdougb	const char *inputformatstr = NULL;
113170222Sdougb	const char *outputformatstr = NULL;
114170222Sdougb	dns_masterformat_t inputformat = dns_masterformat_text;
115170222Sdougb	dns_masterformat_t outputformat = dns_masterformat_text;
116254897Serwin	dns_masterrawheader_t header;
117254897Serwin	isc_uint32_t rawversion = 1, serialnum = 0;
118254897Serwin	isc_boolean_t snset = ISC_FALSE;
119234010Sdougb	isc_boolean_t logdump = ISC_FALSE;
120193149Sdougb	FILE *errout = stdout;
121254897Serwin	char *endp;
122135446Strhodes
123170222Sdougb	outputstyle = &dns_master_style_full;
124170222Sdougb
125170222Sdougb	prog_name = strrchr(argv[0], '/');
126174187Sdougb	if (prog_name == NULL)
127174187Sdougb		prog_name = strrchr(argv[0], '\\');
128170222Sdougb	if (prog_name != NULL)
129170222Sdougb		prog_name++;
130170222Sdougb	else
131170222Sdougb		prog_name = argv[0];
132170222Sdougb	/*
133170222Sdougb	 * Libtool doesn't preserve the program name prior to final
134170222Sdougb	 * installation.  Remove the libtool prefix ("lt-").
135170222Sdougb	 */
136170222Sdougb	if (strncmp(prog_name, "lt-", 3) == 0)
137170222Sdougb		prog_name += 3;
138194995Sdougb
139194995Sdougb#define PROGCMP(X) \
140194995Sdougb	(strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
141194995Sdougb
142194995Sdougb	if (PROGCMP("named-checkzone"))
143170222Sdougb		progmode = progmode_check;
144194995Sdougb	else if (PROGCMP("named-compilezone"))
145170222Sdougb		progmode = progmode_compile;
146170222Sdougb	else
147170222Sdougb		INSIST(0);
148170222Sdougb
149170222Sdougb	/* Compilation specific defaults */
150170222Sdougb	if (progmode == progmode_compile) {
151170222Sdougb		zone_options |= (DNS_ZONEOPT_CHECKNS |
152170222Sdougb				 DNS_ZONEOPT_FATALNS |
153254402Serwin				 DNS_ZONEOPT_CHECKSPF |
154224092Sdougb				 DNS_ZONEOPT_CHECKDUPRR |
155170222Sdougb				 DNS_ZONEOPT_CHECKNAMES |
156170222Sdougb				 DNS_ZONEOPT_CHECKNAMESFAIL |
157170222Sdougb				 DNS_ZONEOPT_CHECKWILDCARD);
158224092Sdougb	} else
159254402Serwin		zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
160254402Serwin				 DNS_ZONEOPT_CHECKSPF);
161170222Sdougb
162170222Sdougb#define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
163170222Sdougb
164193149Sdougb	isc_commandline_errprint = ISC_FALSE;
165193149Sdougb
166170222Sdougb	while ((c = isc_commandline_parse(argc, argv,
167254897Serwin			       "c:df:hi:jk:L:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
168170222Sdougb	       != EOF) {
169135446Strhodes		switch (c) {
170135446Strhodes		case 'c':
171135446Strhodes			classname = isc_commandline_argument;
172135446Strhodes			break;
173135446Strhodes
174135446Strhodes		case 'd':
175135446Strhodes			debug++;
176135446Strhodes			break;
177135446Strhodes
178170222Sdougb		case 'i':
179170222Sdougb			if (ARGCMP("full")) {
180170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
181170222Sdougb						DNS_ZONEOPT_CHECKSIBLING;
182170222Sdougb				docheckmx = ISC_TRUE;
183170222Sdougb				docheckns = ISC_TRUE;
184170222Sdougb				dochecksrv = ISC_TRUE;
185170222Sdougb			} else if (ARGCMP("full-sibling")) {
186170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
187170222Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
188170222Sdougb				docheckmx = ISC_TRUE;
189170222Sdougb				docheckns = ISC_TRUE;
190170222Sdougb				dochecksrv = ISC_TRUE;
191170222Sdougb			} else if (ARGCMP("local")) {
192170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
193170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKSIBLING;
194170222Sdougb				docheckmx = ISC_FALSE;
195170222Sdougb				docheckns = ISC_FALSE;
196170222Sdougb				dochecksrv = ISC_FALSE;
197170222Sdougb			} else if (ARGCMP("local-sibling")) {
198170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
199170222Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
200170222Sdougb				docheckmx = ISC_FALSE;
201170222Sdougb				docheckns = ISC_FALSE;
202170222Sdougb				dochecksrv = ISC_FALSE;
203170222Sdougb			} else if (ARGCMP("none")) {
204170222Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
205170222Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
206170222Sdougb				docheckmx = ISC_FALSE;
207170222Sdougb				docheckns = ISC_FALSE;
208170222Sdougb				dochecksrv = ISC_FALSE;
209170222Sdougb			} else {
210170222Sdougb				fprintf(stderr, "invalid argument to -i: %s\n",
211170222Sdougb					isc_commandline_argument);
212170222Sdougb				exit(1);
213170222Sdougb			}
214170222Sdougb			break;
215170222Sdougb
216170222Sdougb		case 'f':
217170222Sdougb			inputformatstr = isc_commandline_argument;
218170222Sdougb			break;
219170222Sdougb
220170222Sdougb		case 'F':
221170222Sdougb			outputformatstr = isc_commandline_argument;
222170222Sdougb			break;
223170222Sdougb
224135446Strhodes		case 'j':
225135446Strhodes			nomerge = ISC_FALSE;
226135446Strhodes			break;
227135446Strhodes
228170222Sdougb		case 'k':
229170222Sdougb			if (ARGCMP("warn")) {
230170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKNAMES;
231170222Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
232170222Sdougb			} else if (ARGCMP("fail")) {
233170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKNAMES |
234170222Sdougb						DNS_ZONEOPT_CHECKNAMESFAIL;
235170222Sdougb			} else if (ARGCMP("ignore")) {
236170222Sdougb				zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
237170222Sdougb						  DNS_ZONEOPT_CHECKNAMESFAIL);
238170222Sdougb			} else {
239170222Sdougb				fprintf(stderr, "invalid argument to -k: %s\n",
240170222Sdougb					isc_commandline_argument);
241170222Sdougb				exit(1);
242170222Sdougb			}
243170222Sdougb			break;
244170222Sdougb
245254897Serwin		case 'L':
246254897Serwin			snset = ISC_TRUE;
247254897Serwin			endp = NULL;
248254897Serwin			serialnum = strtol(isc_commandline_argument, &endp, 0);
249254897Serwin			if (*endp != '\0') {
250254897Serwin				fprintf(stderr, "source serial number "
251254897Serwin						"must be numeric");
252254897Serwin				exit(1);
253254897Serwin			}
254254897Serwin			break;
255254897Serwin
256135446Strhodes		case 'n':
257170222Sdougb			if (ARGCMP("ignore")) {
258135446Strhodes				zone_options &= ~(DNS_ZONEOPT_CHECKNS|
259135446Strhodes						  DNS_ZONEOPT_FATALNS);
260170222Sdougb			} else if (ARGCMP("warn")) {
261135446Strhodes				zone_options |= DNS_ZONEOPT_CHECKNS;
262135446Strhodes				zone_options &= ~DNS_ZONEOPT_FATALNS;
263170222Sdougb			} else if (ARGCMP("fail")) {
264135446Strhodes				zone_options |= DNS_ZONEOPT_CHECKNS|
265186462Sdougb						DNS_ZONEOPT_FATALNS;
266170222Sdougb			} else {
267170222Sdougb				fprintf(stderr, "invalid argument to -n: %s\n",
268170222Sdougb					isc_commandline_argument);
269170222Sdougb				exit(1);
270170222Sdougb			}
271135446Strhodes			break;
272135446Strhodes
273170222Sdougb		case 'm':
274170222Sdougb			if (ARGCMP("warn")) {
275170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKMX;
276170222Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
277170222Sdougb			} else if (ARGCMP("fail")) {
278170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKMX |
279170222Sdougb						DNS_ZONEOPT_CHECKMXFAIL;
280170222Sdougb			} else if (ARGCMP("ignore")) {
281170222Sdougb				zone_options &= ~(DNS_ZONEOPT_CHECKMX |
282170222Sdougb						  DNS_ZONEOPT_CHECKMXFAIL);
283170222Sdougb			} else {
284170222Sdougb				fprintf(stderr, "invalid argument to -m: %s\n",
285170222Sdougb					isc_commandline_argument);
286170222Sdougb				exit(1);
287135446Strhodes			}
288135446Strhodes			break;
289135446Strhodes
290224092Sdougb		case 'o':
291224092Sdougb			output_filename = isc_commandline_argument;
292224092Sdougb			break;
293224092Sdougb
294135446Strhodes		case 'q':
295135446Strhodes			quiet++;
296135446Strhodes			break;
297135446Strhodes
298224092Sdougb		case 'r':
299224092Sdougb			if (ARGCMP("warn")) {
300224092Sdougb				zone_options |= DNS_ZONEOPT_CHECKDUPRR;
301224092Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
302224092Sdougb			} else if (ARGCMP("fail")) {
303224092Sdougb				zone_options |= DNS_ZONEOPT_CHECKDUPRR |
304224092Sdougb						DNS_ZONEOPT_CHECKDUPRRFAIL;
305224092Sdougb			} else if (ARGCMP("ignore")) {
306224092Sdougb				zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
307224092Sdougb						  DNS_ZONEOPT_CHECKDUPRRFAIL);
308224092Sdougb			} else {
309224092Sdougb				fprintf(stderr, "invalid argument to -r: %s\n",
310224092Sdougb					isc_commandline_argument);
311135446Strhodes				exit(1);
312135446Strhodes			}
313135446Strhodes			break;
314135446Strhodes
315170222Sdougb		case 's':
316170222Sdougb			if (ARGCMP("full"))
317170222Sdougb				outputstyle = &dns_master_style_full;
318170222Sdougb			else if (ARGCMP("relative")) {
319170222Sdougb				outputstyle = &dns_master_style_default;
320170222Sdougb			} else {
321170222Sdougb				fprintf(stderr,
322170222Sdougb					"unknown or unsupported style: %s\n",
323170222Sdougb					isc_commandline_argument);
324170222Sdougb				exit(1);
325170222Sdougb			}
326170222Sdougb			break;
327170222Sdougb
328224092Sdougb		case 't':
329224092Sdougb			result = isc_dir_chroot(isc_commandline_argument);
330224092Sdougb			if (result != ISC_R_SUCCESS) {
331224092Sdougb				fprintf(stderr, "isc_dir_chroot: %s: %s\n",
332224092Sdougb					isc_commandline_argument,
333224092Sdougb					isc_result_totext(result));
334224092Sdougb				exit(1);
335224092Sdougb			}
336135446Strhodes			break;
337135446Strhodes
338135446Strhodes		case 'v':
339135446Strhodes			printf(VERSION "\n");
340135446Strhodes			exit(0);
341135446Strhodes
342135446Strhodes		case 'w':
343135446Strhodes			workdir = isc_commandline_argument;
344135446Strhodes			break;
345135446Strhodes
346135446Strhodes		case 'D':
347135446Strhodes			dumpzone++;
348135446Strhodes			break;
349135446Strhodes
350170222Sdougb		case 'M':
351170222Sdougb			if (ARGCMP("fail")) {
352170222Sdougb				zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
353170222Sdougb				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
354170222Sdougb			} else if (ARGCMP("warn")) {
355170222Sdougb				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
356170222Sdougb				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
357170222Sdougb			} else if (ARGCMP("ignore")) {
358170222Sdougb				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
359170222Sdougb				zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
360170222Sdougb			} else {
361170222Sdougb				fprintf(stderr, "invalid argument to -M: %s\n",
362170222Sdougb					isc_commandline_argument);
363170222Sdougb				exit(1);
364170222Sdougb			}
365170222Sdougb			break;
366170222Sdougb
367170222Sdougb		case 'S':
368170222Sdougb			if (ARGCMP("fail")) {
369170222Sdougb				zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
370170222Sdougb				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
371170222Sdougb			} else if (ARGCMP("warn")) {
372170222Sdougb				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
373170222Sdougb				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
374170222Sdougb			} else if (ARGCMP("ignore")) {
375170222Sdougb				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
376170222Sdougb				zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
377170222Sdougb			} else {
378170222Sdougb				fprintf(stderr, "invalid argument to -S: %s\n",
379170222Sdougb					isc_commandline_argument);
380170222Sdougb				exit(1);
381170222Sdougb			}
382170222Sdougb			break;
383170222Sdougb
384254402Serwin		case 'T':
385254402Serwin			if (ARGCMP("warn")) {
386254402Serwin				zone_options |= DNS_ZONEOPT_CHECKSPF;
387254402Serwin			} else if (ARGCMP("ignore")) {
388254402Serwin				zone_options &= ~DNS_ZONEOPT_CHECKSPF;
389254402Serwin			} else {
390254402Serwin				fprintf(stderr, "invalid argument to -T: %s\n",
391254402Serwin					isc_commandline_argument);
392254402Serwin				exit(1);
393254402Serwin			}
394254402Serwin			break;
395254402Serwin
396170222Sdougb		case 'W':
397170222Sdougb			if (ARGCMP("warn"))
398170222Sdougb				zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
399170222Sdougb			else if (ARGCMP("ignore"))
400170222Sdougb				zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
401170222Sdougb			break;
402170222Sdougb
403193149Sdougb		case '?':
404193149Sdougb			if (isc_commandline_option != '?')
405193149Sdougb				fprintf(stderr, "%s: invalid argument -%c\n",
406193149Sdougb					prog_name, isc_commandline_option);
407254402Serwin			/* FALLTHROUGH */
408193149Sdougb		case 'h':
409135446Strhodes			usage();
410135446Strhodes
411193149Sdougb		default:
412193149Sdougb			fprintf(stderr, "%s: unhandled option -%c\n",
413193149Sdougb				prog_name, isc_commandline_option);
414193149Sdougb			exit(1);
415170222Sdougb		}
416170222Sdougb	}
417170222Sdougb
418135446Strhodes	if (workdir != NULL) {
419135446Strhodes		result = isc_dir_chdir(workdir);
420135446Strhodes		if (result != ISC_R_SUCCESS) {
421135446Strhodes			fprintf(stderr, "isc_dir_chdir: %s: %s\n",
422135446Strhodes				workdir, isc_result_totext(result));
423135446Strhodes			exit(1);
424135446Strhodes		}
425135446Strhodes	}
426135446Strhodes
427170222Sdougb	if (inputformatstr != NULL) {
428170222Sdougb		if (strcasecmp(inputformatstr, "text") == 0)
429170222Sdougb			inputformat = dns_masterformat_text;
430170222Sdougb		else if (strcasecmp(inputformatstr, "raw") == 0)
431170222Sdougb			inputformat = dns_masterformat_raw;
432254897Serwin		else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
433254897Serwin			inputformat = dns_masterformat_raw;
434254897Serwin			fprintf(stderr,
435254897Serwin				"WARNING: input format raw, version ignored\n");
436254897Serwin		} else {
437170222Sdougb			fprintf(stderr, "unknown file format: %s\n",
438170222Sdougb			    inputformatstr);
439170222Sdougb			exit(1);
440170222Sdougb		}
441170222Sdougb	}
442170222Sdougb
443170222Sdougb	if (outputformatstr != NULL) {
444254897Serwin		if (strcasecmp(outputformatstr, "text") == 0) {
445170222Sdougb			outputformat = dns_masterformat_text;
446254897Serwin		} else if (strcasecmp(outputformatstr, "raw") == 0) {
447170222Sdougb			outputformat = dns_masterformat_raw;
448254897Serwin		} else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
449254897Serwin			char *end;
450254897Serwin
451254897Serwin			outputformat = dns_masterformat_raw;
452254897Serwin			rawversion = strtol(outputformatstr + 4, &end, 10);
453254897Serwin			if (end == outputformatstr + 4 || *end != '\0' ||
454254897Serwin			    rawversion > 1U) {
455254897Serwin				fprintf(stderr,
456254897Serwin					"unknown raw format version\n");
457254897Serwin				exit(1);
458254897Serwin			}
459254897Serwin		} else {
460170222Sdougb			fprintf(stderr, "unknown file format: %s\n",
461170222Sdougb				outputformatstr);
462170222Sdougb			exit(1);
463170222Sdougb		}
464170222Sdougb	}
465170222Sdougb
466193149Sdougb	if (progmode == progmode_compile) {
467193149Sdougb		dumpzone = 1;	/* always dump */
468234010Sdougb		logdump = !quiet;
469193149Sdougb		if (output_filename == NULL) {
470193149Sdougb			fprintf(stderr,
471193149Sdougb				"output file required, but not specified\n");
472193149Sdougb			usage();
473193149Sdougb		}
474193149Sdougb	}
475193149Sdougb
476193149Sdougb	if (output_filename != NULL)
477193149Sdougb		dumpzone = 1;
478193149Sdougb
479193149Sdougb	/*
480193149Sdougb	 * If we are outputing to stdout then send the informational
481193149Sdougb	 * output to stderr.
482193149Sdougb	 */
483193149Sdougb	if (dumpzone &&
484193149Sdougb	    (output_filename == NULL ||
485193149Sdougb	     strcmp(output_filename, "-") == 0 ||
486193149Sdougb	     strcmp(output_filename, "/dev/fd/1") == 0 ||
487234010Sdougb	     strcmp(output_filename, "/dev/stdout") == 0)) {
488193149Sdougb		errout = stderr;
489234010Sdougb		logdump = ISC_FALSE;
490234010Sdougb	}
491193149Sdougb
492193149Sdougb	if (isc_commandline_index + 2 != argc)
493135446Strhodes		usage();
494135446Strhodes
495216175Sdougb#ifdef _WIN32
496216175Sdougb	InitSockets();
497216175Sdougb#endif
498216175Sdougb
499135446Strhodes	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
500170222Sdougb	if (!quiet)
501193149Sdougb		RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
502193149Sdougb			      == ISC_R_SUCCESS);
503143731Sdougb	RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
504143731Sdougb	RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
505143731Sdougb		      == ISC_R_SUCCESS);
506135446Strhodes
507135446Strhodes	dns_result_register();
508135446Strhodes
509135446Strhodes	origin = argv[isc_commandline_index++];
510135446Strhodes	filename = argv[isc_commandline_index++];
511170222Sdougb	result = load_zone(mctx, origin, filename, inputformat, classname,
512170222Sdougb			   &zone);
513135446Strhodes
514254897Serwin	if (snset) {
515254897Serwin		dns_master_initrawheader(&header);
516254897Serwin		header.flags = DNS_MASTERRAW_SOURCESERIALSET;
517254897Serwin		header.sourceserial = serialnum;
518254897Serwin		dns_zone_setrawdata(zone, &header);
519254897Serwin	}
520254897Serwin
521135446Strhodes	if (result == ISC_R_SUCCESS && dumpzone) {
522234010Sdougb		if (logdump) {
523193149Sdougb			fprintf(errout, "dump zone to %s...", output_filename);
524193149Sdougb			fflush(errout);
525170222Sdougb		}
526170222Sdougb		result = dump_zone(origin, zone, output_filename,
527254897Serwin				   outputformat, outputstyle, rawversion);
528234010Sdougb		if (logdump)
529193149Sdougb			fprintf(errout, "done\n");
530135446Strhodes	}
531135446Strhodes
532135446Strhodes	if (!quiet && result == ISC_R_SUCCESS)
533193149Sdougb		fprintf(errout, "OK\n");
534135446Strhodes	destroy();
535135446Strhodes	if (lctx != NULL)
536135446Strhodes		isc_log_destroy(&lctx);
537143731Sdougb	isc_hash_destroy();
538143731Sdougb	isc_entropy_detach(&ectx);
539135446Strhodes	isc_mem_destroy(&mctx);
540216175Sdougb#ifdef _WIN32
541216175Sdougb	DestroySockets();
542216175Sdougb#endif
543135446Strhodes	return ((result == ISC_R_SUCCESS) ? 0 : 1);
544135446Strhodes}
545