PageRenderTime 40ms CodeModel.GetById 14ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/bind9/bin/check/named-checkzone.c

https://bitbucket.org/freebsd/freebsd-head/
C | 491 lines | 408 code | 55 blank | 28 comment | 131 complexity | e2d01eb47c34f1a7c541271ee08e71b3 MD5 | raw file
  1/*
  2 * Copyright (C) 2004-2011  Internet Systems Consortium, Inc. ("ISC")
  3 * Copyright (C) 1999-2003  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: named-checkzone.c,v 1.61.62.2 2011/12/22 23:45:54 tbox Exp $ */
 19
 20/*! \file */
 21
 22#include <config.h>
 23
 24#include <stdlib.h>
 25
 26#include <isc/app.h>
 27#include <isc/commandline.h>
 28#include <isc/dir.h>
 29#include <isc/entropy.h>
 30#include <isc/hash.h>
 31#include <isc/log.h>
 32#include <isc/mem.h>
 33#include <isc/socket.h>
 34#include <isc/string.h>
 35#include <isc/task.h>
 36#include <isc/timer.h>
 37#include <isc/util.h>
 38
 39#include <dns/db.h>
 40#include <dns/fixedname.h>
 41#include <dns/log.h>
 42#include <dns/masterdump.h>
 43#include <dns/name.h>
 44#include <dns/rdataclass.h>
 45#include <dns/rdataset.h>
 46#include <dns/result.h>
 47#include <dns/types.h>
 48#include <dns/zone.h>
 49
 50#include "check-tool.h"
 51
 52static int quiet = 0;
 53static isc_mem_t *mctx = NULL;
 54static isc_entropy_t *ectx = NULL;
 55dns_zone_t *zone = NULL;
 56dns_zonetype_t zonetype = dns_zone_master;
 57static int dumpzone = 0;
 58static const char *output_filename;
 59static char *prog_name = NULL;
 60static const dns_master_style_t *outputstyle = NULL;
 61static enum { progmode_check, progmode_compile } progmode;
 62
 63#define ERRRET(result, function) \
 64	do { \
 65		if (result != ISC_R_SUCCESS) { \
 66			if (!quiet) \
 67				fprintf(stderr, "%s() returned %s\n", \
 68					function, dns_result_totext(result)); \
 69			return (result); \
 70		} \
 71	} while (0)
 72
 73ISC_PLATFORM_NORETURN_PRE static void
 74usage(void) ISC_PLATFORM_NORETURN_POST;
 75
 76static void
 77usage(void) {
 78	fprintf(stderr,
 79		"usage: %s [-djqvD] [-c class] "
 80		"[-f inputformat] [-F outputformat] "
 81		"[-t directory] [-w directory] [-k (ignore|warn|fail)] "
 82		"[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
 83		"[-r (ignore|warn|fail)] "
 84		"[-i (full|full-sibling|local|local-sibling|none)] "
 85		"[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
 86		"[-W (ignore|warn)] "
 87		"%s zonename filename\n",
 88		prog_name,
 89		progmode == progmode_check ? "[-o filename]" : "-o filename");
 90	exit(1);
 91}
 92
 93static void
 94destroy(void) {
 95	if (zone != NULL)
 96		dns_zone_detach(&zone);
 97	dns_name_destroy();
 98}
 99
100/*% main processing routine */
101int
102main(int argc, char **argv) {
103	int c;
104	char *origin = NULL;
105	char *filename = NULL;
106	isc_log_t *lctx = NULL;
107	isc_result_t result;
108	char classname_in[] = "IN";
109	char *classname = classname_in;
110	const char *workdir = NULL;
111	const char *inputformatstr = NULL;
112	const char *outputformatstr = NULL;
113	dns_masterformat_t inputformat = dns_masterformat_text;
114	dns_masterformat_t outputformat = dns_masterformat_text;
115	isc_boolean_t logdump = ISC_FALSE;
116	FILE *errout = stdout;
117
118	outputstyle = &dns_master_style_full;
119
120	prog_name = strrchr(argv[0], '/');
121	if (prog_name == NULL)
122		prog_name = strrchr(argv[0], '\\');
123	if (prog_name != NULL)
124		prog_name++;
125	else
126		prog_name = argv[0];
127	/*
128	 * Libtool doesn't preserve the program name prior to final
129	 * installation.  Remove the libtool prefix ("lt-").
130	 */
131	if (strncmp(prog_name, "lt-", 3) == 0)
132		prog_name += 3;
133
134#define PROGCMP(X) \
135	(strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)
136
137	if (PROGCMP("named-checkzone"))
138		progmode = progmode_check;
139	else if (PROGCMP("named-compilezone"))
140		progmode = progmode_compile;
141	else
142		INSIST(0);
143
144	/* Compilation specific defaults */
145	if (progmode == progmode_compile) {
146		zone_options |= (DNS_ZONEOPT_CHECKNS |
147				 DNS_ZONEOPT_FATALNS |
148				 DNS_ZONEOPT_CHECKDUPRR |
149				 DNS_ZONEOPT_CHECKNAMES |
150				 DNS_ZONEOPT_CHECKNAMESFAIL |
151				 DNS_ZONEOPT_CHECKWILDCARD);
152	} else
153		zone_options |= DNS_ZONEOPT_CHECKDUPRR;
154
155#define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)
156
157	isc_commandline_errprint = ISC_FALSE;
158
159	while ((c = isc_commandline_parse(argc, argv,
160				       "c:df:hi:jk:m:n:qr:s:t:o:vw:DF:M:S:W:"))
161	       != EOF) {
162		switch (c) {
163		case 'c':
164			classname = isc_commandline_argument;
165			break;
166
167		case 'd':
168			debug++;
169			break;
170
171		case 'i':
172			if (ARGCMP("full")) {
173				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
174						DNS_ZONEOPT_CHECKSIBLING;
175				docheckmx = ISC_TRUE;
176				docheckns = ISC_TRUE;
177				dochecksrv = ISC_TRUE;
178			} else if (ARGCMP("full-sibling")) {
179				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
180				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
181				docheckmx = ISC_TRUE;
182				docheckns = ISC_TRUE;
183				dochecksrv = ISC_TRUE;
184			} else if (ARGCMP("local")) {
185				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
186				zone_options |= DNS_ZONEOPT_CHECKSIBLING;
187				docheckmx = ISC_FALSE;
188				docheckns = ISC_FALSE;
189				dochecksrv = ISC_FALSE;
190			} else if (ARGCMP("local-sibling")) {
191				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
192				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
193				docheckmx = ISC_FALSE;
194				docheckns = ISC_FALSE;
195				dochecksrv = ISC_FALSE;
196			} else if (ARGCMP("none")) {
197				zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
198				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
199				docheckmx = ISC_FALSE;
200				docheckns = ISC_FALSE;
201				dochecksrv = ISC_FALSE;
202			} else {
203				fprintf(stderr, "invalid argument to -i: %s\n",
204					isc_commandline_argument);
205				exit(1);
206			}
207			break;
208
209		case 'f':
210			inputformatstr = isc_commandline_argument;
211			break;
212
213		case 'F':
214			outputformatstr = isc_commandline_argument;
215			break;
216
217		case 'j':
218			nomerge = ISC_FALSE;
219			break;
220
221		case 'k':
222			if (ARGCMP("warn")) {
223				zone_options |= DNS_ZONEOPT_CHECKNAMES;
224				zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
225			} else if (ARGCMP("fail")) {
226				zone_options |= DNS_ZONEOPT_CHECKNAMES |
227						DNS_ZONEOPT_CHECKNAMESFAIL;
228			} else if (ARGCMP("ignore")) {
229				zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
230						  DNS_ZONEOPT_CHECKNAMESFAIL);
231			} else {
232				fprintf(stderr, "invalid argument to -k: %s\n",
233					isc_commandline_argument);
234				exit(1);
235			}
236			break;
237
238		case 'n':
239			if (ARGCMP("ignore")) {
240				zone_options &= ~(DNS_ZONEOPT_CHECKNS|
241						  DNS_ZONEOPT_FATALNS);
242			} else if (ARGCMP("warn")) {
243				zone_options |= DNS_ZONEOPT_CHECKNS;
244				zone_options &= ~DNS_ZONEOPT_FATALNS;
245			} else if (ARGCMP("fail")) {
246				zone_options |= DNS_ZONEOPT_CHECKNS|
247						DNS_ZONEOPT_FATALNS;
248			} else {
249				fprintf(stderr, "invalid argument to -n: %s\n",
250					isc_commandline_argument);
251				exit(1);
252			}
253			break;
254
255		case 'm':
256			if (ARGCMP("warn")) {
257				zone_options |= DNS_ZONEOPT_CHECKMX;
258				zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
259			} else if (ARGCMP("fail")) {
260				zone_options |= DNS_ZONEOPT_CHECKMX |
261						DNS_ZONEOPT_CHECKMXFAIL;
262			} else if (ARGCMP("ignore")) {
263				zone_options &= ~(DNS_ZONEOPT_CHECKMX |
264						  DNS_ZONEOPT_CHECKMXFAIL);
265			} else {
266				fprintf(stderr, "invalid argument to -m: %s\n",
267					isc_commandline_argument);
268				exit(1);
269			}
270			break;
271
272		case 'o':
273			output_filename = isc_commandline_argument;
274			break;
275
276		case 'q':
277			quiet++;
278			break;
279
280		case 'r':
281			if (ARGCMP("warn")) {
282				zone_options |= DNS_ZONEOPT_CHECKDUPRR;
283				zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
284			} else if (ARGCMP("fail")) {
285				zone_options |= DNS_ZONEOPT_CHECKDUPRR |
286						DNS_ZONEOPT_CHECKDUPRRFAIL;
287			} else if (ARGCMP("ignore")) {
288				zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
289						  DNS_ZONEOPT_CHECKDUPRRFAIL);
290			} else {
291				fprintf(stderr, "invalid argument to -r: %s\n",
292					isc_commandline_argument);
293				exit(1);
294			}
295			break;
296
297		case 's':
298			if (ARGCMP("full"))
299				outputstyle = &dns_master_style_full;
300			else if (ARGCMP("relative")) {
301				outputstyle = &dns_master_style_default;
302			} else {
303				fprintf(stderr,
304					"unknown or unsupported style: %s\n",
305					isc_commandline_argument);
306				exit(1);
307			}
308			break;
309
310		case 't':
311			result = isc_dir_chroot(isc_commandline_argument);
312			if (result != ISC_R_SUCCESS) {
313				fprintf(stderr, "isc_dir_chroot: %s: %s\n",
314					isc_commandline_argument,
315					isc_result_totext(result));
316				exit(1);
317			}
318			break;
319
320		case 'v':
321			printf(VERSION "\n");
322			exit(0);
323
324		case 'w':
325			workdir = isc_commandline_argument;
326			break;
327
328		case 'D':
329			dumpzone++;
330			break;
331
332		case 'M':
333			if (ARGCMP("fail")) {
334				zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
335				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
336			} else if (ARGCMP("warn")) {
337				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
338				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
339			} else if (ARGCMP("ignore")) {
340				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
341				zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
342			} else {
343				fprintf(stderr, "invalid argument to -M: %s\n",
344					isc_commandline_argument);
345				exit(1);
346			}
347			break;
348
349		case 'S':
350			if (ARGCMP("fail")) {
351				zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
352				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
353			} else if (ARGCMP("warn")) {
354				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
355				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
356			} else if (ARGCMP("ignore")) {
357				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
358				zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
359			} else {
360				fprintf(stderr, "invalid argument to -S: %s\n",
361					isc_commandline_argument);
362				exit(1);
363			}
364			break;
365
366		case 'W':
367			if (ARGCMP("warn"))
368				zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
369			else if (ARGCMP("ignore"))
370				zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
371			break;
372
373		case '?':
374			if (isc_commandline_option != '?')
375				fprintf(stderr, "%s: invalid argument -%c\n",
376					prog_name, isc_commandline_option);
377		case 'h':
378			usage();
379
380		default:
381			fprintf(stderr, "%s: unhandled option -%c\n",
382				prog_name, isc_commandline_option);
383			exit(1);
384		}
385	}
386
387	if (workdir != NULL) {
388		result = isc_dir_chdir(workdir);
389		if (result != ISC_R_SUCCESS) {
390			fprintf(stderr, "isc_dir_chdir: %s: %s\n",
391				workdir, isc_result_totext(result));
392			exit(1);
393		}
394	}
395
396	if (inputformatstr != NULL) {
397		if (strcasecmp(inputformatstr, "text") == 0)
398			inputformat = dns_masterformat_text;
399		else if (strcasecmp(inputformatstr, "raw") == 0)
400			inputformat = dns_masterformat_raw;
401		else {
402			fprintf(stderr, "unknown file format: %s\n",
403			    inputformatstr);
404			exit(1);
405		}
406	}
407
408	if (outputformatstr != NULL) {
409		if (strcasecmp(outputformatstr, "text") == 0)
410			outputformat = dns_masterformat_text;
411		else if (strcasecmp(outputformatstr, "raw") == 0)
412			outputformat = dns_masterformat_raw;
413		else {
414			fprintf(stderr, "unknown file format: %s\n",
415				outputformatstr);
416			exit(1);
417		}
418	}
419
420	if (progmode == progmode_compile) {
421		dumpzone = 1;	/* always dump */
422		logdump = !quiet;
423		if (output_filename == NULL) {
424			fprintf(stderr,
425				"output file required, but not specified\n");
426			usage();
427		}
428	}
429
430	if (output_filename != NULL)
431		dumpzone = 1;
432
433	/*
434	 * If we are outputing to stdout then send the informational
435	 * output to stderr.
436	 */
437	if (dumpzone &&
438	    (output_filename == NULL ||
439	     strcmp(output_filename, "-") == 0 ||
440	     strcmp(output_filename, "/dev/fd/1") == 0 ||
441	     strcmp(output_filename, "/dev/stdout") == 0)) {
442		errout = stderr;
443		logdump = ISC_FALSE;
444	}
445
446	if (isc_commandline_index + 2 != argc)
447		usage();
448
449#ifdef _WIN32
450	InitSockets();
451#endif
452
453	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
454	if (!quiet)
455		RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
456			      == ISC_R_SUCCESS);
457	RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
458	RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
459		      == ISC_R_SUCCESS);
460
461	dns_result_register();
462
463	origin = argv[isc_commandline_index++];
464	filename = argv[isc_commandline_index++];
465	result = load_zone(mctx, origin, filename, inputformat, classname,
466			   &zone);
467
468	if (result == ISC_R_SUCCESS && dumpzone) {
469		if (logdump) {
470			fprintf(errout, "dump zone to %s...", output_filename);
471			fflush(errout);
472		}
473		result = dump_zone(origin, zone, output_filename,
474				   outputformat, outputstyle);
475		if (logdump)
476			fprintf(errout, "done\n");
477	}
478
479	if (!quiet && result == ISC_R_SUCCESS)
480		fprintf(errout, "OK\n");
481	destroy();
482	if (lctx != NULL)
483		isc_log_destroy(&lctx);
484	isc_hash_destroy();
485	isc_entropy_detach(&ectx);
486	isc_mem_destroy(&mctx);
487#ifdef _WIN32
488	DestroySockets();
489#endif
490	return ((result == ISC_R_SUCCESS) ? 0 : 1);
491}