xref: /minix3/external/bsd/bind/dist/bin/check/named-checkzone.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: named-checkzone.c,v 1.7 2014/12/10 04:37:51 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 1999-2003  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: named-checkzone.c,v 1.65.32.2 2012/02/07 02:45:21 each Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file */
23*00b67f09SDavid van Moolenbroek 
24*00b67f09SDavid van Moolenbroek #include <config.h>
25*00b67f09SDavid van Moolenbroek 
26*00b67f09SDavid van Moolenbroek #include <stdlib.h>
27*00b67f09SDavid van Moolenbroek 
28*00b67f09SDavid van Moolenbroek #include <isc/app.h>
29*00b67f09SDavid van Moolenbroek #include <isc/commandline.h>
30*00b67f09SDavid van Moolenbroek #include <isc/dir.h>
31*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
32*00b67f09SDavid van Moolenbroek #include <isc/hash.h>
33*00b67f09SDavid van Moolenbroek #include <isc/log.h>
34*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
35*00b67f09SDavid van Moolenbroek #include <isc/socket.h>
36*00b67f09SDavid van Moolenbroek #include <isc/string.h>
37*00b67f09SDavid van Moolenbroek #include <isc/task.h>
38*00b67f09SDavid van Moolenbroek #include <isc/timer.h>
39*00b67f09SDavid van Moolenbroek #include <isc/util.h>
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek #include <dns/db.h>
42*00b67f09SDavid van Moolenbroek #include <dns/fixedname.h>
43*00b67f09SDavid van Moolenbroek #include <dns/log.h>
44*00b67f09SDavid van Moolenbroek #include <dns/master.h>
45*00b67f09SDavid van Moolenbroek #include <dns/masterdump.h>
46*00b67f09SDavid van Moolenbroek #include <dns/name.h>
47*00b67f09SDavid van Moolenbroek #include <dns/rdataclass.h>
48*00b67f09SDavid van Moolenbroek #include <dns/rdataset.h>
49*00b67f09SDavid van Moolenbroek #include <dns/result.h>
50*00b67f09SDavid van Moolenbroek #include <dns/types.h>
51*00b67f09SDavid van Moolenbroek #include <dns/zone.h>
52*00b67f09SDavid van Moolenbroek 
53*00b67f09SDavid van Moolenbroek #include "check-tool.h"
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek static int quiet = 0;
56*00b67f09SDavid van Moolenbroek static isc_mem_t *mctx = NULL;
57*00b67f09SDavid van Moolenbroek static isc_entropy_t *ectx = NULL;
58*00b67f09SDavid van Moolenbroek dns_zone_t *zone = NULL;
59*00b67f09SDavid van Moolenbroek dns_zonetype_t zonetype = dns_zone_master;
60*00b67f09SDavid van Moolenbroek static int dumpzone = 0;
61*00b67f09SDavid van Moolenbroek static const char *output_filename;
62*00b67f09SDavid van Moolenbroek static char *prog_name = NULL;
63*00b67f09SDavid van Moolenbroek static const dns_master_style_t *outputstyle = NULL;
64*00b67f09SDavid van Moolenbroek static enum { progmode_check, progmode_compile } progmode;
65*00b67f09SDavid van Moolenbroek 
66*00b67f09SDavid van Moolenbroek #define ERRRET(result, function) \
67*00b67f09SDavid van Moolenbroek 	do { \
68*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) { \
69*00b67f09SDavid van Moolenbroek 			if (!quiet) \
70*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "%s() returned %s\n", \
71*00b67f09SDavid van Moolenbroek 					function, dns_result_totext(result)); \
72*00b67f09SDavid van Moolenbroek 			return (result); \
73*00b67f09SDavid van Moolenbroek 		} \
74*00b67f09SDavid van Moolenbroek 	} while (/*CONSTCOND*/0)
75*00b67f09SDavid van Moolenbroek 
76*00b67f09SDavid van Moolenbroek ISC_PLATFORM_NORETURN_PRE static void
77*00b67f09SDavid van Moolenbroek usage(void) ISC_PLATFORM_NORETURN_POST;
78*00b67f09SDavid van Moolenbroek 
79*00b67f09SDavid van Moolenbroek static void
usage(void)80*00b67f09SDavid van Moolenbroek usage(void) {
81*00b67f09SDavid van Moolenbroek 	fprintf(stderr,
82*00b67f09SDavid van Moolenbroek 		"usage: %s [-djqvD] [-c class] "
83*00b67f09SDavid van Moolenbroek 		"[-f inputformat] [-F outputformat] [-J filename] "
84*00b67f09SDavid van Moolenbroek 		"[-t directory] [-w directory] [-k (ignore|warn|fail)] "
85*00b67f09SDavid van Moolenbroek 		"[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
86*00b67f09SDavid van Moolenbroek 		"[-r (ignore|warn|fail)] "
87*00b67f09SDavid van Moolenbroek 		"[-i (full|full-sibling|local|local-sibling|none)] "
88*00b67f09SDavid van Moolenbroek 		"[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
89*00b67f09SDavid van Moolenbroek 		"[-W (ignore|warn)] "
90*00b67f09SDavid van Moolenbroek 		"%s zonename filename\n",
91*00b67f09SDavid van Moolenbroek 		prog_name,
92*00b67f09SDavid van Moolenbroek 		progmode == progmode_check ? "[-o filename]" : "-o filename");
93*00b67f09SDavid van Moolenbroek 	exit(1);
94*00b67f09SDavid van Moolenbroek }
95*00b67f09SDavid van Moolenbroek 
96*00b67f09SDavid van Moolenbroek static void
destroy(void)97*00b67f09SDavid van Moolenbroek destroy(void) {
98*00b67f09SDavid van Moolenbroek 	if (zone != NULL)
99*00b67f09SDavid van Moolenbroek 		dns_zone_detach(&zone);
100*00b67f09SDavid van Moolenbroek 	dns_name_destroy();
101*00b67f09SDavid van Moolenbroek }
102*00b67f09SDavid van Moolenbroek 
103*00b67f09SDavid van Moolenbroek /*% main processing routine */
104*00b67f09SDavid van Moolenbroek int
main(int argc,char ** argv)105*00b67f09SDavid van Moolenbroek main(int argc, char **argv) {
106*00b67f09SDavid van Moolenbroek 	int c;
107*00b67f09SDavid van Moolenbroek 	char *origin = NULL;
108*00b67f09SDavid van Moolenbroek 	char *filename = NULL;
109*00b67f09SDavid van Moolenbroek 	isc_log_t *lctx = NULL;
110*00b67f09SDavid van Moolenbroek 	isc_result_t result;
111*00b67f09SDavid van Moolenbroek 	char classname_in[] = "IN";
112*00b67f09SDavid van Moolenbroek 	char *classname = classname_in;
113*00b67f09SDavid van Moolenbroek 	const char *workdir = NULL;
114*00b67f09SDavid van Moolenbroek 	const char *inputformatstr = NULL;
115*00b67f09SDavid van Moolenbroek 	const char *outputformatstr = NULL;
116*00b67f09SDavid van Moolenbroek 	dns_masterformat_t inputformat = dns_masterformat_text;
117*00b67f09SDavid van Moolenbroek 	dns_masterformat_t outputformat = dns_masterformat_text;
118*00b67f09SDavid van Moolenbroek 	dns_masterrawheader_t header;
119*00b67f09SDavid van Moolenbroek 	isc_uint32_t rawversion = 1, serialnum = 0;
120*00b67f09SDavid van Moolenbroek 	dns_ttl_t maxttl = 0;
121*00b67f09SDavid van Moolenbroek 	isc_boolean_t snset = ISC_FALSE;
122*00b67f09SDavid van Moolenbroek 	isc_boolean_t logdump = ISC_FALSE;
123*00b67f09SDavid van Moolenbroek 	FILE *errout = stdout;
124*00b67f09SDavid van Moolenbroek 	char *endp;
125*00b67f09SDavid van Moolenbroek 
126*00b67f09SDavid van Moolenbroek 	/*
127*00b67f09SDavid van Moolenbroek 	 * Uncomment the following line if memory debugging is needed:
128*00b67f09SDavid van Moolenbroek 	 * isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
129*00b67f09SDavid van Moolenbroek 	 */
130*00b67f09SDavid van Moolenbroek 
131*00b67f09SDavid van Moolenbroek 	outputstyle = &dns_master_style_full;
132*00b67f09SDavid van Moolenbroek 
133*00b67f09SDavid van Moolenbroek 	prog_name = strrchr(argv[0], '/');
134*00b67f09SDavid van Moolenbroek 	if (prog_name == NULL)
135*00b67f09SDavid van Moolenbroek 		prog_name = strrchr(argv[0], '\\');
136*00b67f09SDavid van Moolenbroek 	if (prog_name != NULL)
137*00b67f09SDavid van Moolenbroek 		prog_name++;
138*00b67f09SDavid van Moolenbroek 	else
139*00b67f09SDavid van Moolenbroek 		prog_name = argv[0];
140*00b67f09SDavid van Moolenbroek 	/*
141*00b67f09SDavid van Moolenbroek 	 * Libtool doesn't preserve the program name prior to final
142*00b67f09SDavid van Moolenbroek 	 * installation.  Remove the libtool prefix ("lt-").
143*00b67f09SDavid van Moolenbroek 	 */
144*00b67f09SDavid van Moolenbroek 	if (strncmp(prog_name, "lt-", 3) == 0)
145*00b67f09SDavid van Moolenbroek 		prog_name += 3;
146*00b67f09SDavid van Moolenbroek 
147*00b67f09SDavid van Moolenbroek #define PROGCMP(X) \
148*00b67f09SDavid van Moolenbroek 	(strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
149*00b67f09SDavid van Moolenbroek 
150*00b67f09SDavid van Moolenbroek 	if (PROGCMP("named-checkzone"))
151*00b67f09SDavid van Moolenbroek 		progmode = progmode_check;
152*00b67f09SDavid van Moolenbroek 	else if (PROGCMP("named-compilezone"))
153*00b67f09SDavid van Moolenbroek 		progmode = progmode_compile;
154*00b67f09SDavid van Moolenbroek 	else
155*00b67f09SDavid van Moolenbroek 		INSIST(0);
156*00b67f09SDavid van Moolenbroek 
157*00b67f09SDavid van Moolenbroek 	/* Compilation specific defaults */
158*00b67f09SDavid van Moolenbroek 	if (progmode == progmode_compile) {
159*00b67f09SDavid van Moolenbroek 		zone_options |= (DNS_ZONEOPT_CHECKNS |
160*00b67f09SDavid van Moolenbroek 				 DNS_ZONEOPT_FATALNS |
161*00b67f09SDavid van Moolenbroek 				 DNS_ZONEOPT_CHECKSPF |
162*00b67f09SDavid van Moolenbroek 				 DNS_ZONEOPT_CHECKDUPRR |
163*00b67f09SDavid van Moolenbroek 				 DNS_ZONEOPT_CHECKNAMES |
164*00b67f09SDavid van Moolenbroek 				 DNS_ZONEOPT_CHECKNAMESFAIL |
165*00b67f09SDavid van Moolenbroek 				 DNS_ZONEOPT_CHECKWILDCARD);
166*00b67f09SDavid van Moolenbroek 	} else
167*00b67f09SDavid van Moolenbroek 		zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
168*00b67f09SDavid van Moolenbroek 				 DNS_ZONEOPT_CHECKSPF);
169*00b67f09SDavid van Moolenbroek 
170*00b67f09SDavid van Moolenbroek #define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
171*00b67f09SDavid van Moolenbroek 
172*00b67f09SDavid van Moolenbroek 	isc_commandline_errprint = ISC_FALSE;
173*00b67f09SDavid van Moolenbroek 
174*00b67f09SDavid van Moolenbroek 	while ((c = isc_commandline_parse(argc, argv,
175*00b67f09SDavid van Moolenbroek 			       "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
176*00b67f09SDavid van Moolenbroek 	       != EOF) {
177*00b67f09SDavid van Moolenbroek 		switch (c) {
178*00b67f09SDavid van Moolenbroek 		case 'c':
179*00b67f09SDavid van Moolenbroek 			classname = isc_commandline_argument;
180*00b67f09SDavid van Moolenbroek 			break;
181*00b67f09SDavid van Moolenbroek 
182*00b67f09SDavid van Moolenbroek 		case 'd':
183*00b67f09SDavid van Moolenbroek 			debug++;
184*00b67f09SDavid van Moolenbroek 			break;
185*00b67f09SDavid van Moolenbroek 
186*00b67f09SDavid van Moolenbroek 		case 'i':
187*00b67f09SDavid van Moolenbroek 			if (ARGCMP("full")) {
188*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
189*00b67f09SDavid van Moolenbroek 						DNS_ZONEOPT_CHECKSIBLING;
190*00b67f09SDavid van Moolenbroek 				docheckmx = ISC_TRUE;
191*00b67f09SDavid van Moolenbroek 				docheckns = ISC_TRUE;
192*00b67f09SDavid van Moolenbroek 				dochecksrv = ISC_TRUE;
193*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("full-sibling")) {
194*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
195*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
196*00b67f09SDavid van Moolenbroek 				docheckmx = ISC_TRUE;
197*00b67f09SDavid van Moolenbroek 				docheckns = ISC_TRUE;
198*00b67f09SDavid van Moolenbroek 				dochecksrv = ISC_TRUE;
199*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("local")) {
200*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
201*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKSIBLING;
202*00b67f09SDavid van Moolenbroek 				docheckmx = ISC_FALSE;
203*00b67f09SDavid van Moolenbroek 				docheckns = ISC_FALSE;
204*00b67f09SDavid van Moolenbroek 				dochecksrv = ISC_FALSE;
205*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("local-sibling")) {
206*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
207*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
208*00b67f09SDavid van Moolenbroek 				docheckmx = ISC_FALSE;
209*00b67f09SDavid van Moolenbroek 				docheckns = ISC_FALSE;
210*00b67f09SDavid van Moolenbroek 				dochecksrv = ISC_FALSE;
211*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("none")) {
212*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
213*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
214*00b67f09SDavid van Moolenbroek 				docheckmx = ISC_FALSE;
215*00b67f09SDavid van Moolenbroek 				docheckns = ISC_FALSE;
216*00b67f09SDavid van Moolenbroek 				dochecksrv = ISC_FALSE;
217*00b67f09SDavid van Moolenbroek 			} else {
218*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -i: %s\n",
219*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
220*00b67f09SDavid van Moolenbroek 				exit(1);
221*00b67f09SDavid van Moolenbroek 			}
222*00b67f09SDavid van Moolenbroek 			break;
223*00b67f09SDavid van Moolenbroek 
224*00b67f09SDavid van Moolenbroek 		case 'f':
225*00b67f09SDavid van Moolenbroek 			inputformatstr = isc_commandline_argument;
226*00b67f09SDavid van Moolenbroek 			break;
227*00b67f09SDavid van Moolenbroek 
228*00b67f09SDavid van Moolenbroek 		case 'F':
229*00b67f09SDavid van Moolenbroek 			outputformatstr = isc_commandline_argument;
230*00b67f09SDavid van Moolenbroek 			break;
231*00b67f09SDavid van Moolenbroek 
232*00b67f09SDavid van Moolenbroek 		case 'j':
233*00b67f09SDavid van Moolenbroek 			nomerge = ISC_FALSE;
234*00b67f09SDavid van Moolenbroek 			break;
235*00b67f09SDavid van Moolenbroek 
236*00b67f09SDavid van Moolenbroek 		case 'J':
237*00b67f09SDavid van Moolenbroek 			journal = isc_commandline_argument;
238*00b67f09SDavid van Moolenbroek 			nomerge = ISC_FALSE;
239*00b67f09SDavid van Moolenbroek 			break;
240*00b67f09SDavid van Moolenbroek 
241*00b67f09SDavid van Moolenbroek 		case 'k':
242*00b67f09SDavid van Moolenbroek 			if (ARGCMP("warn")) {
243*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKNAMES;
244*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
245*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("fail")) {
246*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKNAMES |
247*00b67f09SDavid van Moolenbroek 						DNS_ZONEOPT_CHECKNAMESFAIL;
248*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("ignore")) {
249*00b67f09SDavid van Moolenbroek 				zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
250*00b67f09SDavid van Moolenbroek 						  DNS_ZONEOPT_CHECKNAMESFAIL);
251*00b67f09SDavid van Moolenbroek 			} else {
252*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -k: %s\n",
253*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
254*00b67f09SDavid van Moolenbroek 				exit(1);
255*00b67f09SDavid van Moolenbroek 			}
256*00b67f09SDavid van Moolenbroek 			break;
257*00b67f09SDavid van Moolenbroek 
258*00b67f09SDavid van Moolenbroek 		case 'L':
259*00b67f09SDavid van Moolenbroek 			snset = ISC_TRUE;
260*00b67f09SDavid van Moolenbroek 			endp = NULL;
261*00b67f09SDavid van Moolenbroek 			serialnum = strtol(isc_commandline_argument, &endp, 0);
262*00b67f09SDavid van Moolenbroek 			if (*endp != '\0') {
263*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "source serial number "
264*00b67f09SDavid van Moolenbroek 						"must be numeric");
265*00b67f09SDavid van Moolenbroek 				exit(1);
266*00b67f09SDavid van Moolenbroek 			}
267*00b67f09SDavid van Moolenbroek 			break;
268*00b67f09SDavid van Moolenbroek 
269*00b67f09SDavid van Moolenbroek 		case 'l':
270*00b67f09SDavid van Moolenbroek 			zone_options2 |= DNS_ZONEOPT2_CHECKTTL;
271*00b67f09SDavid van Moolenbroek 			endp = NULL;
272*00b67f09SDavid van Moolenbroek 			maxttl = strtol(isc_commandline_argument, &endp, 0);
273*00b67f09SDavid van Moolenbroek 			if (*endp != '\0') {
274*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "maximum TTL "
275*00b67f09SDavid van Moolenbroek 						"must be numeric");
276*00b67f09SDavid van Moolenbroek 				exit(1);
277*00b67f09SDavid van Moolenbroek 			}
278*00b67f09SDavid van Moolenbroek 			break;
279*00b67f09SDavid van Moolenbroek 
280*00b67f09SDavid van Moolenbroek 
281*00b67f09SDavid van Moolenbroek 		case 'n':
282*00b67f09SDavid van Moolenbroek 			if (ARGCMP("ignore")) {
283*00b67f09SDavid van Moolenbroek 				zone_options &= ~(DNS_ZONEOPT_CHECKNS|
284*00b67f09SDavid van Moolenbroek 						  DNS_ZONEOPT_FATALNS);
285*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("warn")) {
286*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKNS;
287*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_FATALNS;
288*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("fail")) {
289*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKNS|
290*00b67f09SDavid van Moolenbroek 						DNS_ZONEOPT_FATALNS;
291*00b67f09SDavid van Moolenbroek 			} else {
292*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -n: %s\n",
293*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
294*00b67f09SDavid van Moolenbroek 				exit(1);
295*00b67f09SDavid van Moolenbroek 			}
296*00b67f09SDavid van Moolenbroek 			break;
297*00b67f09SDavid van Moolenbroek 
298*00b67f09SDavid van Moolenbroek 		case 'm':
299*00b67f09SDavid van Moolenbroek 			if (ARGCMP("warn")) {
300*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKMX;
301*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
302*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("fail")) {
303*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKMX |
304*00b67f09SDavid van Moolenbroek 						DNS_ZONEOPT_CHECKMXFAIL;
305*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("ignore")) {
306*00b67f09SDavid van Moolenbroek 				zone_options &= ~(DNS_ZONEOPT_CHECKMX |
307*00b67f09SDavid van Moolenbroek 						  DNS_ZONEOPT_CHECKMXFAIL);
308*00b67f09SDavid van Moolenbroek 			} else {
309*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -m: %s\n",
310*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
311*00b67f09SDavid van Moolenbroek 				exit(1);
312*00b67f09SDavid van Moolenbroek 			}
313*00b67f09SDavid van Moolenbroek 			break;
314*00b67f09SDavid van Moolenbroek 
315*00b67f09SDavid van Moolenbroek 		case 'o':
316*00b67f09SDavid van Moolenbroek 			output_filename = isc_commandline_argument;
317*00b67f09SDavid van Moolenbroek 			break;
318*00b67f09SDavid van Moolenbroek 
319*00b67f09SDavid van Moolenbroek 		case 'q':
320*00b67f09SDavid van Moolenbroek 			quiet++;
321*00b67f09SDavid van Moolenbroek 			break;
322*00b67f09SDavid van Moolenbroek 
323*00b67f09SDavid van Moolenbroek 		case 'r':
324*00b67f09SDavid van Moolenbroek 			if (ARGCMP("warn")) {
325*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKDUPRR;
326*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
327*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("fail")) {
328*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKDUPRR |
329*00b67f09SDavid van Moolenbroek 						DNS_ZONEOPT_CHECKDUPRRFAIL;
330*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("ignore")) {
331*00b67f09SDavid van Moolenbroek 				zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
332*00b67f09SDavid van Moolenbroek 						  DNS_ZONEOPT_CHECKDUPRRFAIL);
333*00b67f09SDavid van Moolenbroek 			} else {
334*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -r: %s\n",
335*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
336*00b67f09SDavid van Moolenbroek 				exit(1);
337*00b67f09SDavid van Moolenbroek 			}
338*00b67f09SDavid van Moolenbroek 			break;
339*00b67f09SDavid van Moolenbroek 
340*00b67f09SDavid van Moolenbroek 		case 's':
341*00b67f09SDavid van Moolenbroek 			if (ARGCMP("full"))
342*00b67f09SDavid van Moolenbroek 				outputstyle = &dns_master_style_full;
343*00b67f09SDavid van Moolenbroek 			else if (ARGCMP("relative")) {
344*00b67f09SDavid van Moolenbroek 				outputstyle = &dns_master_style_default;
345*00b67f09SDavid van Moolenbroek 			} else {
346*00b67f09SDavid van Moolenbroek 				fprintf(stderr,
347*00b67f09SDavid van Moolenbroek 					"unknown or unsupported style: %s\n",
348*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
349*00b67f09SDavid van Moolenbroek 				exit(1);
350*00b67f09SDavid van Moolenbroek 			}
351*00b67f09SDavid van Moolenbroek 			break;
352*00b67f09SDavid van Moolenbroek 
353*00b67f09SDavid van Moolenbroek 		case 't':
354*00b67f09SDavid van Moolenbroek 			result = isc_dir_chroot(isc_commandline_argument);
355*00b67f09SDavid van Moolenbroek 			if (result != ISC_R_SUCCESS) {
356*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "isc_dir_chroot: %s: %s\n",
357*00b67f09SDavid van Moolenbroek 					isc_commandline_argument,
358*00b67f09SDavid van Moolenbroek 					isc_result_totext(result));
359*00b67f09SDavid van Moolenbroek 				exit(1);
360*00b67f09SDavid van Moolenbroek 			}
361*00b67f09SDavid van Moolenbroek 			break;
362*00b67f09SDavid van Moolenbroek 
363*00b67f09SDavid van Moolenbroek 		case 'v':
364*00b67f09SDavid van Moolenbroek 			printf(VERSION "\n");
365*00b67f09SDavid van Moolenbroek 			exit(0);
366*00b67f09SDavid van Moolenbroek 
367*00b67f09SDavid van Moolenbroek 		case 'w':
368*00b67f09SDavid van Moolenbroek 			workdir = isc_commandline_argument;
369*00b67f09SDavid van Moolenbroek 			break;
370*00b67f09SDavid van Moolenbroek 
371*00b67f09SDavid van Moolenbroek 		case 'D':
372*00b67f09SDavid van Moolenbroek 			dumpzone++;
373*00b67f09SDavid van Moolenbroek 			break;
374*00b67f09SDavid van Moolenbroek 
375*00b67f09SDavid van Moolenbroek 		case 'M':
376*00b67f09SDavid van Moolenbroek 			if (ARGCMP("fail")) {
377*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
378*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
379*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("warn")) {
380*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
381*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
382*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("ignore")) {
383*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
384*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
385*00b67f09SDavid van Moolenbroek 			} else {
386*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -M: %s\n",
387*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
388*00b67f09SDavid van Moolenbroek 				exit(1);
389*00b67f09SDavid van Moolenbroek 			}
390*00b67f09SDavid van Moolenbroek 			break;
391*00b67f09SDavid van Moolenbroek 
392*00b67f09SDavid van Moolenbroek 		case 'S':
393*00b67f09SDavid van Moolenbroek 			if (ARGCMP("fail")) {
394*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
395*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
396*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("warn")) {
397*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
398*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
399*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("ignore")) {
400*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
401*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
402*00b67f09SDavid van Moolenbroek 			} else {
403*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -S: %s\n",
404*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
405*00b67f09SDavid van Moolenbroek 				exit(1);
406*00b67f09SDavid van Moolenbroek 			}
407*00b67f09SDavid van Moolenbroek 			break;
408*00b67f09SDavid van Moolenbroek 
409*00b67f09SDavid van Moolenbroek 		case 'T':
410*00b67f09SDavid van Moolenbroek 			if (ARGCMP("warn")) {
411*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKSPF;
412*00b67f09SDavid van Moolenbroek 			} else if (ARGCMP("ignore")) {
413*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKSPF;
414*00b67f09SDavid van Moolenbroek 			} else {
415*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "invalid argument to -T: %s\n",
416*00b67f09SDavid van Moolenbroek 					isc_commandline_argument);
417*00b67f09SDavid van Moolenbroek 				exit(1);
418*00b67f09SDavid van Moolenbroek 			}
419*00b67f09SDavid van Moolenbroek 			break;
420*00b67f09SDavid van Moolenbroek 
421*00b67f09SDavid van Moolenbroek 		case 'W':
422*00b67f09SDavid van Moolenbroek 			if (ARGCMP("warn"))
423*00b67f09SDavid van Moolenbroek 				zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
424*00b67f09SDavid van Moolenbroek 			else if (ARGCMP("ignore"))
425*00b67f09SDavid van Moolenbroek 				zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
426*00b67f09SDavid van Moolenbroek 			break;
427*00b67f09SDavid van Moolenbroek 
428*00b67f09SDavid van Moolenbroek 		case '?':
429*00b67f09SDavid van Moolenbroek 			if (isc_commandline_option != '?')
430*00b67f09SDavid van Moolenbroek 				fprintf(stderr, "%s: invalid argument -%c\n",
431*00b67f09SDavid van Moolenbroek 					prog_name, isc_commandline_option);
432*00b67f09SDavid van Moolenbroek 			/* FALLTHROUGH */
433*00b67f09SDavid van Moolenbroek 		case 'h':
434*00b67f09SDavid van Moolenbroek 			usage();
435*00b67f09SDavid van Moolenbroek 
436*00b67f09SDavid van Moolenbroek 		default:
437*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "%s: unhandled option -%c\n",
438*00b67f09SDavid van Moolenbroek 				prog_name, isc_commandline_option);
439*00b67f09SDavid van Moolenbroek 			exit(1);
440*00b67f09SDavid van Moolenbroek 		}
441*00b67f09SDavid van Moolenbroek 	}
442*00b67f09SDavid van Moolenbroek 
443*00b67f09SDavid van Moolenbroek 	if (workdir != NULL) {
444*00b67f09SDavid van Moolenbroek 		result = isc_dir_chdir(workdir);
445*00b67f09SDavid van Moolenbroek 		if (result != ISC_R_SUCCESS) {
446*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "isc_dir_chdir: %s: %s\n",
447*00b67f09SDavid van Moolenbroek 				workdir, isc_result_totext(result));
448*00b67f09SDavid van Moolenbroek 			exit(1);
449*00b67f09SDavid van Moolenbroek 		}
450*00b67f09SDavid van Moolenbroek 	}
451*00b67f09SDavid van Moolenbroek 
452*00b67f09SDavid van Moolenbroek 	if (inputformatstr != NULL) {
453*00b67f09SDavid van Moolenbroek 		if (strcasecmp(inputformatstr, "text") == 0)
454*00b67f09SDavid van Moolenbroek 			inputformat = dns_masterformat_text;
455*00b67f09SDavid van Moolenbroek 		else if (strcasecmp(inputformatstr, "raw") == 0)
456*00b67f09SDavid van Moolenbroek 			inputformat = dns_masterformat_raw;
457*00b67f09SDavid van Moolenbroek 		else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
458*00b67f09SDavid van Moolenbroek 			inputformat = dns_masterformat_raw;
459*00b67f09SDavid van Moolenbroek 			fprintf(stderr,
460*00b67f09SDavid van Moolenbroek 				"WARNING: input format raw, version ignored\n");
461*00b67f09SDavid van Moolenbroek 		} else if (strcasecmp(inputformatstr, "map") == 0) {
462*00b67f09SDavid van Moolenbroek 			inputformat = dns_masterformat_map;
463*00b67f09SDavid van Moolenbroek 		} else {
464*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "unknown file format: %s\n",
465*00b67f09SDavid van Moolenbroek 			    inputformatstr);
466*00b67f09SDavid van Moolenbroek 			exit(1);
467*00b67f09SDavid van Moolenbroek 		}
468*00b67f09SDavid van Moolenbroek 	}
469*00b67f09SDavid van Moolenbroek 
470*00b67f09SDavid van Moolenbroek 	if (outputformatstr != NULL) {
471*00b67f09SDavid van Moolenbroek 		if (strcasecmp(outputformatstr, "text") == 0) {
472*00b67f09SDavid van Moolenbroek 			outputformat = dns_masterformat_text;
473*00b67f09SDavid van Moolenbroek 		} else if (strcasecmp(outputformatstr, "raw") == 0) {
474*00b67f09SDavid van Moolenbroek 			outputformat = dns_masterformat_raw;
475*00b67f09SDavid van Moolenbroek 		} else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
476*00b67f09SDavid van Moolenbroek 			char *end;
477*00b67f09SDavid van Moolenbroek 
478*00b67f09SDavid van Moolenbroek 			outputformat = dns_masterformat_raw;
479*00b67f09SDavid van Moolenbroek 			rawversion = strtol(outputformatstr + 4, &end, 10);
480*00b67f09SDavid van Moolenbroek 			if (end == outputformatstr + 4 || *end != '\0' ||
481*00b67f09SDavid van Moolenbroek 			    rawversion > 1U) {
482*00b67f09SDavid van Moolenbroek 				fprintf(stderr,
483*00b67f09SDavid van Moolenbroek 					"unknown raw format version\n");
484*00b67f09SDavid van Moolenbroek 				exit(1);
485*00b67f09SDavid van Moolenbroek 			}
486*00b67f09SDavid van Moolenbroek 		} else if (strcasecmp(outputformatstr, "map") == 0) {
487*00b67f09SDavid van Moolenbroek 			outputformat = dns_masterformat_map;
488*00b67f09SDavid van Moolenbroek 		} else {
489*00b67f09SDavid van Moolenbroek 			fprintf(stderr, "unknown file format: %s\n",
490*00b67f09SDavid van Moolenbroek 				outputformatstr);
491*00b67f09SDavid van Moolenbroek 			exit(1);
492*00b67f09SDavid van Moolenbroek 		}
493*00b67f09SDavid van Moolenbroek 	}
494*00b67f09SDavid van Moolenbroek 
495*00b67f09SDavid van Moolenbroek 	if (progmode == progmode_compile) {
496*00b67f09SDavid van Moolenbroek 		dumpzone = 1;	/* always dump */
497*00b67f09SDavid van Moolenbroek 		logdump = !quiet;
498*00b67f09SDavid van Moolenbroek 		if (output_filename == NULL) {
499*00b67f09SDavid van Moolenbroek 			fprintf(stderr,
500*00b67f09SDavid van Moolenbroek 				"output file required, but not specified\n");
501*00b67f09SDavid van Moolenbroek 			usage();
502*00b67f09SDavid van Moolenbroek 		}
503*00b67f09SDavid van Moolenbroek 	}
504*00b67f09SDavid van Moolenbroek 
505*00b67f09SDavid van Moolenbroek 	if (output_filename != NULL)
506*00b67f09SDavid van Moolenbroek 		dumpzone = 1;
507*00b67f09SDavid van Moolenbroek 
508*00b67f09SDavid van Moolenbroek 	/*
509*00b67f09SDavid van Moolenbroek 	 * If we are outputing to stdout then send the informational
510*00b67f09SDavid van Moolenbroek 	 * output to stderr.
511*00b67f09SDavid van Moolenbroek 	 */
512*00b67f09SDavid van Moolenbroek 	if (dumpzone &&
513*00b67f09SDavid van Moolenbroek 	    (output_filename == NULL ||
514*00b67f09SDavid van Moolenbroek 	     strcmp(output_filename, "-") == 0 ||
515*00b67f09SDavid van Moolenbroek 	     strcmp(output_filename, "/dev/fd/1") == 0 ||
516*00b67f09SDavid van Moolenbroek 	     strcmp(output_filename, "/dev/stdout") == 0)) {
517*00b67f09SDavid van Moolenbroek 		errout = stderr;
518*00b67f09SDavid van Moolenbroek 		logdump = ISC_FALSE;
519*00b67f09SDavid van Moolenbroek 	}
520*00b67f09SDavid van Moolenbroek 
521*00b67f09SDavid van Moolenbroek 	if (isc_commandline_index + 2 != argc)
522*00b67f09SDavid van Moolenbroek 		usage();
523*00b67f09SDavid van Moolenbroek 
524*00b67f09SDavid van Moolenbroek #ifdef _WIN32
525*00b67f09SDavid van Moolenbroek 	InitSockets();
526*00b67f09SDavid van Moolenbroek #endif
527*00b67f09SDavid van Moolenbroek 
528*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
529*00b67f09SDavid van Moolenbroek 	if (!quiet)
530*00b67f09SDavid van Moolenbroek 		RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
531*00b67f09SDavid van Moolenbroek 			      == ISC_R_SUCCESS);
532*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
533*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
534*00b67f09SDavid van Moolenbroek 		      == ISC_R_SUCCESS);
535*00b67f09SDavid van Moolenbroek 
536*00b67f09SDavid van Moolenbroek 	dns_result_register();
537*00b67f09SDavid van Moolenbroek 
538*00b67f09SDavid van Moolenbroek 	origin = argv[isc_commandline_index++];
539*00b67f09SDavid van Moolenbroek 	filename = argv[isc_commandline_index++];
540*00b67f09SDavid van Moolenbroek 	result = load_zone(mctx, origin, filename, inputformat, classname,
541*00b67f09SDavid van Moolenbroek 			   maxttl, &zone);
542*00b67f09SDavid van Moolenbroek 
543*00b67f09SDavid van Moolenbroek 	if (snset) {
544*00b67f09SDavid van Moolenbroek 		dns_master_initrawheader(&header);
545*00b67f09SDavid van Moolenbroek 		header.flags = DNS_MASTERRAW_SOURCESERIALSET;
546*00b67f09SDavid van Moolenbroek 		header.sourceserial = serialnum;
547*00b67f09SDavid van Moolenbroek 		dns_zone_setrawdata(zone, &header);
548*00b67f09SDavid van Moolenbroek 	}
549*00b67f09SDavid van Moolenbroek 
550*00b67f09SDavid van Moolenbroek 	if (result == ISC_R_SUCCESS && dumpzone) {
551*00b67f09SDavid van Moolenbroek 		if (logdump) {
552*00b67f09SDavid van Moolenbroek 			fprintf(errout, "dump zone to %s...", output_filename);
553*00b67f09SDavid van Moolenbroek 			fflush(errout);
554*00b67f09SDavid van Moolenbroek 		}
555*00b67f09SDavid van Moolenbroek 		result = dump_zone(origin, zone, output_filename,
556*00b67f09SDavid van Moolenbroek 				   outputformat, outputstyle, rawversion);
557*00b67f09SDavid van Moolenbroek 		if (logdump)
558*00b67f09SDavid van Moolenbroek 			fprintf(errout, "done\n");
559*00b67f09SDavid van Moolenbroek 	}
560*00b67f09SDavid van Moolenbroek 
561*00b67f09SDavid van Moolenbroek 	if (!quiet && result == ISC_R_SUCCESS)
562*00b67f09SDavid van Moolenbroek 		fprintf(errout, "OK\n");
563*00b67f09SDavid van Moolenbroek 	destroy();
564*00b67f09SDavid van Moolenbroek 	if (lctx != NULL)
565*00b67f09SDavid van Moolenbroek 		isc_log_destroy(&lctx);
566*00b67f09SDavid van Moolenbroek 	isc_hash_destroy();
567*00b67f09SDavid van Moolenbroek 	isc_entropy_detach(&ectx);
568*00b67f09SDavid van Moolenbroek 	isc_mem_destroy(&mctx);
569*00b67f09SDavid van Moolenbroek #ifdef _WIN32
570*00b67f09SDavid van Moolenbroek 	DestroySockets();
571*00b67f09SDavid van Moolenbroek #endif
572*00b67f09SDavid van Moolenbroek 	return ((result == ISC_R_SUCCESS) ? 0 : 1);
573*00b67f09SDavid van Moolenbroek }
574