named-checkzone.c 14.5 KB
Newer Older
Mark Andrews's avatar
Mark Andrews committed
1
/*
Mark Andrews's avatar
Mark Andrews committed
2
 * Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
Mark Andrews's avatar
Mark Andrews committed
3
 * Copyright (C) 1999-2003  Internet Software Consortium.
Mark Andrews's avatar
Mark Andrews committed
4
 *
Automatic Updater's avatar
Automatic Updater committed
5
 * Permission to use, copy, modify, and/or distribute this software for any
Mark Andrews's avatar
Mark Andrews committed
6 7 8
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
Mark Andrews's avatar
Mark Andrews committed
9 10 11 12 13 14 15
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
Mark Andrews's avatar
Mark Andrews committed
16 17
 */

18
/* $Id: named-checkzone.c,v 1.65.32.2 2012/02/07 02:45:21 each Exp $ */
19 20

/*! \file */
Mark Andrews's avatar
Mark Andrews committed
21 22 23 24 25 26 27

#include <config.h>

#include <stdlib.h>

#include <isc/app.h>
#include <isc/commandline.h>
28
#include <isc/dir.h>
29 30
#include <isc/entropy.h>
#include <isc/hash.h>
Mark Andrews's avatar
Mark Andrews committed
31 32 33 34 35 36 37 38 39 40 41
#include <isc/log.h>
#include <isc/mem.h>
#include <isc/socket.h>
#include <isc/string.h>
#include <isc/task.h>
#include <isc/timer.h>
#include <isc/util.h>

#include <dns/db.h>
#include <dns/fixedname.h>
#include <dns/log.h>
42
#include <dns/master.h>
43
#include <dns/masterdump.h>
44
#include <dns/name.h>
Mark Andrews's avatar
Mark Andrews committed
45 46 47
#include <dns/rdataclass.h>
#include <dns/rdataset.h>
#include <dns/result.h>
48
#include <dns/types.h>
Mark Andrews's avatar
Mark Andrews committed
49 50
#include <dns/zone.h>

Mark Andrews's avatar
cleanup  
Mark Andrews committed
51 52
#include "check-tool.h"

Mark Andrews's avatar
Mark Andrews committed
53 54
static int quiet = 0;
static isc_mem_t *mctx = NULL;
55
static isc_entropy_t *ectx = NULL;
Mark Andrews's avatar
Mark Andrews committed
56 57
dns_zone_t *zone = NULL;
dns_zonetype_t zonetype = dns_zone_master;
58 59
static int dumpzone = 0;
static const char *output_filename;
60
static char *prog_name = NULL;
61
static const dns_master_style_t *outputstyle = NULL;
62
static enum { progmode_check, progmode_compile } progmode;
Mark Andrews's avatar
Mark Andrews committed
63 64 65 66

#define ERRRET(result, function) \
	do { \
		if (result != ISC_R_SUCCESS) { \
Mark Andrews's avatar
Mark Andrews committed
67 68 69
			if (!quiet) \
				fprintf(stderr, "%s() returned %s\n", \
					function, dns_result_totext(result)); \
Mark Andrews's avatar
Mark Andrews committed
70 71 72 73
			return (result); \
		} \
	} while (0)

Francis Dupont's avatar
Francis Dupont committed
74 75 76
ISC_PLATFORM_NORETURN_PRE static void
usage(void) ISC_PLATFORM_NORETURN_POST;

Mark Andrews's avatar
Mark Andrews committed
77
static void
Brian Wellington's avatar
Brian Wellington committed
78
usage(void) {
Mark Andrews's avatar
Mark Andrews committed
79
	fprintf(stderr,
80
		"usage: %s [-djqvD] [-c class] "
81
		"[-f inputformat] [-F outputformat] [-J filename] "
82
		"[-t directory] [-w directory] [-k (ignore|warn|fail)] "
83
		"[-n (ignore|warn|fail)] [-m (ignore|warn|fail)] "
84
		"[-r (ignore|warn|fail)] "
Mark Andrews's avatar
Mark Andrews committed
85 86 87
		"[-i (full|full-sibling|local|local-sibling|none)] "
		"[-M (ignore|warn|fail)] [-S (ignore|warn|fail)] "
		"[-W (ignore|warn)] "
88 89
		"%s zonename filename\n",
		prog_name,
90
		progmode == progmode_check ? "[-o filename]" : "-o filename");
Mark Andrews's avatar
Mark Andrews committed
91 92 93 94 95
	exit(1);
}

static void
destroy(void) {
Mark Andrews's avatar
Mark Andrews committed
96 97
	if (zone != NULL)
		dns_zone_detach(&zone);
98
	dns_name_destroy();
Mark Andrews's avatar
Mark Andrews committed
99 100
}

101
/*% main processing routine */
Mark Andrews's avatar
Mark Andrews committed
102 103 104
int
main(int argc, char **argv) {
	int c;
Mark Andrews's avatar
Mark Andrews committed
105
	char *origin = NULL;
Mark Andrews's avatar
Mark Andrews committed
106 107 108
	char *filename = NULL;
	isc_log_t *lctx = NULL;
	isc_result_t result;
109
	char classname_in[] = "IN";
110
	char *classname = classname_in;
111
	const char *workdir = NULL;
112 113 114 115
	const char *inputformatstr = NULL;
	const char *outputformatstr = NULL;
	dns_masterformat_t inputformat = dns_masterformat_text;
	dns_masterformat_t outputformat = dns_masterformat_text;
116 117
	dns_masterrawheader_t header;
	isc_uint32_t rawversion = 1, serialnum = 0;
Evan Hunt's avatar
Evan Hunt committed
118
	dns_ttl_t maxttl = 0;
119
	isc_boolean_t snset = ISC_FALSE;
120
	isc_boolean_t logdump = ISC_FALSE;
121
	FILE *errout = stdout;
122
	char *endp;
123

124 125 126 127 128
	/*
	 * Uncomment the following line if memory debugging is needed:
	 * isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
	 */

129 130
	outputstyle = &dns_master_style_full;

131
	prog_name = strrchr(argv[0], '/');
132 133
	if (prog_name == NULL)
		prog_name = strrchr(argv[0], '\\');
134 135 136 137
	if (prog_name != NULL)
		prog_name++;
	else
		prog_name = argv[0];
Mark Andrews's avatar
Mark Andrews committed
138 139 140 141 142 143
	/*
	 * Libtool doesn't preserve the program name prior to final
	 * installation.  Remove the libtool prefix ("lt-").
	 */
	if (strncmp(prog_name, "lt-", 3) == 0)
		prog_name += 3;
144 145 146 147 148

#define PROGCMP(X) \
	(strcasecmp(prog_name, X) == 0 || strcasecmp(prog_name, X ".exe") == 0)

	if (PROGCMP("named-checkzone"))
149
		progmode = progmode_check;
150
	else if (PROGCMP("named-compilezone"))
151 152 153 154 155 156 157 158
		progmode = progmode_compile;
	else
		INSIST(0);

	/* Compilation specific defaults */
	if (progmode == progmode_compile) {
		zone_options |= (DNS_ZONEOPT_CHECKNS |
				 DNS_ZONEOPT_FATALNS |
159
				 DNS_ZONEOPT_CHECKSPF |
160
				 DNS_ZONEOPT_CHECKDUPRR |
161 162 163
				 DNS_ZONEOPT_CHECKNAMES |
				 DNS_ZONEOPT_CHECKNAMESFAIL |
				 DNS_ZONEOPT_CHECKWILDCARD);
Automatic Updater's avatar
Automatic Updater committed
164
	} else
165 166
		zone_options |= (DNS_ZONEOPT_CHECKDUPRR |
				 DNS_ZONEOPT_CHECKSPF);
Mark Andrews's avatar
Mark Andrews committed
167

168 169
#define ARGCMP(X) (strcmp(isc_commandline_argument, X) == 0)

170 171
	isc_commandline_errprint = ISC_FALSE;

172
	while ((c = isc_commandline_parse(argc, argv,
Evan Hunt's avatar
Evan Hunt committed
173
			       "c:df:hi:jJ:k:L:l:m:n:qr:s:t:o:vw:DF:M:S:T:W:"))
174
	       != EOF) {
Mark Andrews's avatar
Mark Andrews committed
175 176 177 178
		switch (c) {
		case 'c':
			classname = isc_commandline_argument;
			break;
179

Mark Andrews's avatar
Mark Andrews committed
180 181 182
		case 'd':
			debug++;
			break;
183

184
		case 'i':
185
			if (ARGCMP("full")) {
186 187 188 189 190
				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY |
						DNS_ZONEOPT_CHECKSIBLING;
				docheckmx = ISC_TRUE;
				docheckns = ISC_TRUE;
				dochecksrv = ISC_TRUE;
191
			} else if (ARGCMP("full-sibling")) {
192 193
				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
194 195 196
				docheckmx = ISC_TRUE;
				docheckns = ISC_TRUE;
				dochecksrv = ISC_TRUE;
197
			} else if (ARGCMP("local")) {
198 199 200 201 202
				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
				zone_options |= DNS_ZONEOPT_CHECKSIBLING;
				docheckmx = ISC_FALSE;
				docheckns = ISC_FALSE;
				dochecksrv = ISC_FALSE;
203
			} else if (ARGCMP("local-sibling")) {
204 205
				zone_options |= DNS_ZONEOPT_CHECKINTEGRITY;
				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
206 207 208
				docheckmx = ISC_FALSE;
				docheckns = ISC_FALSE;
				dochecksrv = ISC_FALSE;
209
			} else if (ARGCMP("none")) {
210 211
				zone_options &= ~DNS_ZONEOPT_CHECKINTEGRITY;
				zone_options &= ~DNS_ZONEOPT_CHECKSIBLING;
212 213 214 215 216 217 218 219 220 221
				docheckmx = ISC_FALSE;
				docheckns = ISC_FALSE;
				dochecksrv = ISC_FALSE;
			} else {
				fprintf(stderr, "invalid argument to -i: %s\n",
					isc_commandline_argument);
				exit(1);
			}
			break;

222 223 224 225 226 227 228 229
		case 'f':
			inputformatstr = isc_commandline_argument;
			break;

		case 'F':
			outputformatstr = isc_commandline_argument;
			break;

230
		case 'j':
231 232 233
			nomerge = ISC_FALSE;
			break;

234 235 236 237 238
		case 'J':
			journal = isc_commandline_argument;
			nomerge = ISC_FALSE;
			break;

239
		case 'k':
240
			if (ARGCMP("warn")) {
241 242
				zone_options |= DNS_ZONEOPT_CHECKNAMES;
				zone_options &= ~DNS_ZONEOPT_CHECKNAMESFAIL;
243
			} else if (ARGCMP("fail")) {
244 245
				zone_options |= DNS_ZONEOPT_CHECKNAMES |
						DNS_ZONEOPT_CHECKNAMESFAIL;
246
			} else if (ARGCMP("ignore")) {
247 248 249 250 251 252 253 254 255
				zone_options &= ~(DNS_ZONEOPT_CHECKNAMES |
						  DNS_ZONEOPT_CHECKNAMESFAIL);
			} else {
				fprintf(stderr, "invalid argument to -k: %s\n",
					isc_commandline_argument);
				exit(1);
			}
			break;

256 257 258 259 260 261 262 263 264 265 266
		case 'L':
			snset = ISC_TRUE;
			endp = NULL;
			serialnum = strtol(isc_commandline_argument, &endp, 0);
			if (*endp != '\0') {
				fprintf(stderr, "source serial number "
						"must be numeric");
				exit(1);
			}
			break;

Evan Hunt's avatar
Evan Hunt committed
267 268 269 270 271 272 273 274 275 276 277 278
		case 'l':
			zone_options2 |= DNS_ZONEOPT2_CHECKTTL;
			endp = NULL;
			maxttl = strtol(isc_commandline_argument, &endp, 0);
			if (*endp != '\0') {
				fprintf(stderr, "maximum TTL "
						"must be numeric");
				exit(1);
			}
			break;


279
		case 'n':
280
			if (ARGCMP("ignore")) {
281 282
				zone_options &= ~(DNS_ZONEOPT_CHECKNS|
						  DNS_ZONEOPT_FATALNS);
283
			} else if (ARGCMP("warn")) {
284 285
				zone_options |= DNS_ZONEOPT_CHECKNS;
				zone_options &= ~DNS_ZONEOPT_FATALNS;
286
			} else if (ARGCMP("fail")) {
287
				zone_options |= DNS_ZONEOPT_CHECKNS|
Automatic Updater's avatar
Automatic Updater committed
288
						DNS_ZONEOPT_FATALNS;
289 290 291 292 293
			} else {
				fprintf(stderr, "invalid argument to -n: %s\n",
					isc_commandline_argument);
				exit(1);
			}
294 295
			break;

296
		case 'm':
297
			if (ARGCMP("warn")) {
298 299
				zone_options |= DNS_ZONEOPT_CHECKMX;
				zone_options &= ~DNS_ZONEOPT_CHECKMXFAIL;
300
			} else if (ARGCMP("fail")) {
301 302
				zone_options |= DNS_ZONEOPT_CHECKMX |
						DNS_ZONEOPT_CHECKMXFAIL;
303
			} else if (ARGCMP("ignore")) {
304 305 306 307 308 309
				zone_options &= ~(DNS_ZONEOPT_CHECKMX |
						  DNS_ZONEOPT_CHECKMXFAIL);
			} else {
				fprintf(stderr, "invalid argument to -m: %s\n",
					isc_commandline_argument);
				exit(1);
310 311 312
			}
			break;

313 314 315 316
		case 'o':
			output_filename = isc_commandline_argument;
			break;

Mark Andrews's avatar
Mark Andrews committed
317 318 319
		case 'q':
			quiet++;
			break;
320

321 322 323 324 325 326 327 328 329 330 331 332 333
		case 'r':
			if (ARGCMP("warn")) {
				zone_options |= DNS_ZONEOPT_CHECKDUPRR;
				zone_options &= ~DNS_ZONEOPT_CHECKDUPRRFAIL;
			} else if (ARGCMP("fail")) {
				zone_options |= DNS_ZONEOPT_CHECKDUPRR |
						DNS_ZONEOPT_CHECKDUPRRFAIL;
			} else if (ARGCMP("ignore")) {
				zone_options &= ~(DNS_ZONEOPT_CHECKDUPRR |
						  DNS_ZONEOPT_CHECKDUPRRFAIL);
			} else {
				fprintf(stderr, "invalid argument to -r: %s\n",
					isc_commandline_argument);
334 335 336 337
				exit(1);
			}
			break;

338
		case 's':
339
			if (ARGCMP("full"))
340
				outputstyle = &dns_master_style_full;
341
			else if (ARGCMP("relative")) {
342 343 344 345 346 347 348 349 350
				outputstyle = &dns_master_style_default;
			} else {
				fprintf(stderr,
					"unknown or unsupported style: %s\n",
					isc_commandline_argument);
				exit(1);
			}
			break;

351 352 353 354 355 356 357 358
		case 't':
			result = isc_dir_chroot(isc_commandline_argument);
			if (result != ISC_R_SUCCESS) {
				fprintf(stderr, "isc_dir_chroot: %s: %s\n",
					isc_commandline_argument,
					isc_result_totext(result));
				exit(1);
			}
359 360
			break;

361 362 363
		case 'v':
			printf(VERSION "\n");
			exit(0);
364 365 366 367 368

		case 'w':
			workdir = isc_commandline_argument;
			break;

369 370 371 372
		case 'D':
			dumpzone++;
			break;

373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
		case 'M':
			if (ARGCMP("fail")) {
				zone_options &= ~DNS_ZONEOPT_WARNMXCNAME;
				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
			} else if (ARGCMP("warn")) {
				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
				zone_options &= ~DNS_ZONEOPT_IGNOREMXCNAME;
			} else if (ARGCMP("ignore")) {
				zone_options |= DNS_ZONEOPT_WARNMXCNAME;
				zone_options |= DNS_ZONEOPT_IGNOREMXCNAME;
			} else {
				fprintf(stderr, "invalid argument to -M: %s\n",
					isc_commandline_argument);
				exit(1);
			}
			break;

		case 'S':
			if (ARGCMP("fail")) {
				zone_options &= ~DNS_ZONEOPT_WARNSRVCNAME;
				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
			} else if (ARGCMP("warn")) {
				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
				zone_options &= ~DNS_ZONEOPT_IGNORESRVCNAME;
			} else if (ARGCMP("ignore")) {
				zone_options |= DNS_ZONEOPT_WARNSRVCNAME;
				zone_options |= DNS_ZONEOPT_IGNORESRVCNAME;
			} else {
				fprintf(stderr, "invalid argument to -S: %s\n",
					isc_commandline_argument);
				exit(1);
			}
			break;

407 408 409 410 411 412 413 414 415 416 417 418
		case 'T':
			if (ARGCMP("warn")) {
				zone_options |= DNS_ZONEOPT_CHECKSPF;
			} else if (ARGCMP("ignore")) {
				zone_options &= ~DNS_ZONEOPT_CHECKSPF;
			} else {
				fprintf(stderr, "invalid argument to -T: %s\n",
					isc_commandline_argument);
				exit(1);
			}
			break;

419
		case 'W':
420
			if (ARGCMP("warn"))
421
				zone_options |= DNS_ZONEOPT_CHECKWILDCARD;
422
			else if (ARGCMP("ignore"))
423 424 425
				zone_options &= ~DNS_ZONEOPT_CHECKWILDCARD;
			break;

426 427 428 429
		case '?':
			if (isc_commandline_option != '?')
				fprintf(stderr, "%s: invalid argument -%c\n",
					prog_name, isc_commandline_option);
Evan Hunt's avatar
Evan Hunt committed
430
			/* FALLTHROUGH */
431
		case 'h':
Mark Andrews's avatar
Mark Andrews committed
432 433
			usage();

434 435
		default:
			fprintf(stderr, "%s: unhandled option -%c\n",
Automatic Updater's avatar
Automatic Updater committed
436
				prog_name, isc_commandline_option);
437
			exit(1);
438 439 440
		}
	}

441 442 443 444 445 446 447 448 449
	if (workdir != NULL) {
		result = isc_dir_chdir(workdir);
		if (result != ISC_R_SUCCESS) {
			fprintf(stderr, "isc_dir_chdir: %s: %s\n",
				workdir, isc_result_totext(result));
			exit(1);
		}
	}

450 451 452 453 454
	if (inputformatstr != NULL) {
		if (strcasecmp(inputformatstr, "text") == 0)
			inputformat = dns_masterformat_text;
		else if (strcasecmp(inputformatstr, "raw") == 0)
			inputformat = dns_masterformat_raw;
455 456 457 458
		else if (strncasecmp(inputformatstr, "raw=", 4) == 0) {
			inputformat = dns_masterformat_raw;
			fprintf(stderr,
				"WARNING: input format raw, version ignored\n");
Evan Hunt's avatar
Evan Hunt committed
459 460
		} else if (strcasecmp(inputformatstr, "map") == 0) {
			inputformat = dns_masterformat_map;
461
		} else {
462 463 464 465 466 467 468
			fprintf(stderr, "unknown file format: %s\n",
			    inputformatstr);
			exit(1);
		}
	}

	if (outputformatstr != NULL) {
469
		if (strcasecmp(outputformatstr, "text") == 0) {
470
			outputformat = dns_masterformat_text;
471 472 473 474 475
		} else if (strcasecmp(outputformatstr, "raw") == 0) {
			outputformat = dns_masterformat_raw;
		} else if (strncasecmp(outputformatstr, "raw=", 4) == 0) {
			char *end;

476
			outputformat = dns_masterformat_raw;
477 478 479 480 481 482 483
			rawversion = strtol(outputformatstr + 4, &end, 10);
			if (end == outputformatstr + 4 || *end != '\0' ||
			    rawversion > 1U) {
				fprintf(stderr,
					"unknown raw format version\n");
				exit(1);
			}
Evan Hunt's avatar
Evan Hunt committed
484 485
		} else if (strcasecmp(outputformatstr, "map") == 0) {
			outputformat = dns_masterformat_map;
486
		} else {
487 488 489 490 491 492
			fprintf(stderr, "unknown file format: %s\n",
				outputformatstr);
			exit(1);
		}
	}

493 494
	if (progmode == progmode_compile) {
		dumpzone = 1;	/* always dump */
495
		logdump = !quiet;
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
		if (output_filename == NULL) {
			fprintf(stderr,
				"output file required, but not specified\n");
			usage();
		}
	}

	if (output_filename != NULL)
		dumpzone = 1;

	/*
	 * If we are outputing to stdout then send the informational
	 * output to stderr.
	 */
	if (dumpzone &&
	    (output_filename == NULL ||
	     strcmp(output_filename, "-") == 0 ||
	     strcmp(output_filename, "/dev/fd/1") == 0 ||
514
	     strcmp(output_filename, "/dev/stdout") == 0)) {
515
		errout = stderr;
516 517
		logdump = ISC_FALSE;
	}
518 519

	if (isc_commandline_index + 2 != argc)
Mark Andrews's avatar
Mark Andrews committed
520 521
		usage();

522 523 524 525
#ifdef _WIN32
	InitSockets();
#endif

Mark Andrews's avatar
Mark Andrews committed
526
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
527
	if (!quiet)
528 529
		RUNTIME_CHECK(setup_logging(mctx, errout, &lctx)
			      == ISC_R_SUCCESS);
530 531 532
	RUNTIME_CHECK(isc_entropy_create(mctx, &ectx) == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_hash_create(mctx, ectx, DNS_NAME_MAXWIRE)
		      == ISC_R_SUCCESS);
Mark Andrews's avatar
Mark Andrews committed
533

534 535
	dns_result_register();

536 537
	origin = argv[isc_commandline_index++];
	filename = argv[isc_commandline_index++];
538
	result = load_zone(mctx, origin, filename, inputformat, classname,
Evan Hunt's avatar
Evan Hunt committed
539
			   maxttl, &zone);
540

541 542 543 544 545 546 547
	if (snset) {
		dns_master_initrawheader(&header);
		header.flags = DNS_MASTERRAW_SOURCESERIALSET;
		header.sourceserial = serialnum;
		dns_zone_setrawdata(zone, &header);
	}

548
	if (result == ISC_R_SUCCESS && dumpzone) {
549
		if (logdump) {
550 551
			fprintf(errout, "dump zone to %s...", output_filename);
			fflush(errout);
552 553
		}
		result = dump_zone(origin, zone, output_filename,
554
				   outputformat, outputstyle, rawversion);
555
		if (logdump)
556
			fprintf(errout, "done\n");
557 558
	}

Mark Andrews's avatar
Mark Andrews committed
559
	if (!quiet && result == ISC_R_SUCCESS)
560
		fprintf(errout, "OK\n");
Mark Andrews's avatar
Mark Andrews committed
561
	destroy();
Mark Andrews's avatar
Mark Andrews committed
562 563
	if (lctx != NULL)
		isc_log_destroy(&lctx);
564 565
	isc_hash_destroy();
	isc_entropy_detach(&ectx);
Mark Andrews's avatar
Mark Andrews committed
566
	isc_mem_destroy(&mctx);
567 568 569
#ifdef _WIN32
	DestroySockets();
#endif
Mark Andrews's avatar
Mark Andrews committed
570
	return ((result == ISC_R_SUCCESS) ? 0 : 1);
Mark Andrews's avatar
Mark Andrews committed
571
}