xref: /openbsd-src/usr.sbin/nsd/nsd-checkzone.c (revision b71395ea3d4830c6fd338870b804059761b8292d)
115ed76cbSbrad /*
215ed76cbSbrad  * nsd-checkzone.c -- nsd-checkzone(8) checks zones for syntax errors
315ed76cbSbrad  *
415ed76cbSbrad  * Copyright (c) 2013, NLnet Labs. All rights reserved.
515ed76cbSbrad  *
615ed76cbSbrad  * See LICENSE for the license.
715ed76cbSbrad  *
815ed76cbSbrad  */
915ed76cbSbrad 
1015ed76cbSbrad #include "config.h"
1115ed76cbSbrad 
1215ed76cbSbrad #include <assert.h>
1315ed76cbSbrad #include <stdio.h>
1415ed76cbSbrad #include <stdlib.h>
1515ed76cbSbrad #include <string.h>
1615ed76cbSbrad #include <time.h>
1715ed76cbSbrad #include <unistd.h>
1815ed76cbSbrad #include <errno.h>
1915ed76cbSbrad 
2015ed76cbSbrad #include "nsd.h"
2115ed76cbSbrad #include "options.h"
2215ed76cbSbrad #include "util.h"
2315ed76cbSbrad #include "zonec.h"
244564029fSflorian #include "ixfr.h"
254564029fSflorian #include "ixfrcreate.h"
264564029fSflorian #include "difffile.h"
2715ed76cbSbrad 
2815ed76cbSbrad struct nsd nsd;
2915ed76cbSbrad 
3015ed76cbSbrad /*
3115ed76cbSbrad  * Print the help text.
3215ed76cbSbrad  *
3315ed76cbSbrad  */
3415ed76cbSbrad static void
usage(void)3515ed76cbSbrad usage (void)
3615ed76cbSbrad {
378d298c9fSsthen 	fprintf(stderr, "Usage: nsd-checkzone [-p] <zone name> <zone file>\n");
388d298c9fSsthen 	fprintf(stderr, "\t-p\tprint the zone if the zone is ok\n");
394564029fSflorian 	fprintf(stderr, "\t-i <old zone file>\tcreate an IXFR from the differences between the\n\t\told zone file and the new zone file. Writes to \n\t\t<zonefile>.ixfr and renames other <zonefile>.ixfr files to\n\t\t<zonefile>.ixfr.num+1.\n");
404564029fSflorian 	fprintf(stderr, "\t-n <ixfr number>\tnumber of IXFR versions to store, at most.\n\t\tdefault %d.\n", (int)IXFR_NUMBER_DEFAULT);
414564029fSflorian 	fprintf(stderr, "\t-s <ixfr size>\tsize of IXFR to store, at most. default %d.\n", (int)IXFR_SIZE_DEFAULT);
4215ed76cbSbrad 	fprintf(stderr, "Version %s. Report bugs to <%s>.\n",
4315ed76cbSbrad 		PACKAGE_VERSION, PACKAGE_BUGREPORT);
4415ed76cbSbrad }
4515ed76cbSbrad 
4615ed76cbSbrad static void
check_zone(struct nsd * nsd,const char * name,const char * fname,FILE * out,const char * oldzone,uint32_t ixfr_number,uint64_t ixfr_size)474564029fSflorian check_zone(struct nsd* nsd, const char* name, const char* fname, FILE *out,
484564029fSflorian 	const char* oldzone, uint32_t ixfr_number, uint64_t ixfr_size)
4915ed76cbSbrad {
5015ed76cbSbrad 	const dname_type* dname;
51fe5fe5f6Sflorian 	zone_options_type* zo;
5215ed76cbSbrad 	zone_type* zone;
5315ed76cbSbrad 	unsigned errors;
544564029fSflorian 	struct ixfr_create* ixfrcr = NULL;
5515ed76cbSbrad 
5615ed76cbSbrad 	/* init*/
57*b71395eaSflorian 	nsd->db = namedb_open(nsd->options);
5815ed76cbSbrad 	dname = dname_parse(nsd->options->region, name);
5915ed76cbSbrad 	if(!dname) {
6015ed76cbSbrad 		/* parse failure */
6115ed76cbSbrad 		error("cannot parse zone name '%s'", name);
6215ed76cbSbrad 	}
6315ed76cbSbrad 	zo = zone_options_create(nsd->options->region);
6415ed76cbSbrad 	memset(zo, 0, sizeof(*zo));
6515ed76cbSbrad 	zo->node.key = dname;
6615ed76cbSbrad 	zo->name = name;
6715ed76cbSbrad 	zone = namedb_zone_create(nsd->db, dname, zo);
6815ed76cbSbrad 
694564029fSflorian 	if(oldzone) {
704564029fSflorian 		errors = zonec_read(name, oldzone, zone);
714564029fSflorian 		if(errors > 0) {
724564029fSflorian 			printf("zone %s file %s has %u errors\n", name, oldzone, errors);
734564029fSflorian 			exit(1);
744564029fSflorian 		}
754564029fSflorian 		ixfrcr = ixfr_create_start(zone, fname, ixfr_size, 1);
764564029fSflorian 		if(!ixfrcr) {
774564029fSflorian 			error("out of memory");
784564029fSflorian 		}
794564029fSflorian 		delete_zone_rrs(nsd->db, zone);
804564029fSflorian 	}
814564029fSflorian 
8215ed76cbSbrad 	/* read the zone */
8315ed76cbSbrad 	errors = zonec_read(name, fname, zone);
8415ed76cbSbrad 	if(errors > 0) {
8515ed76cbSbrad 		printf("zone %s file %s has %u errors\n", name, fname, errors);
864564029fSflorian 		ixfr_create_cancel(ixfrcr);
87eab1363eSsthen #ifdef MEMCLEAN /* otherwise, the OS collects memory pages */
88eab1363eSsthen 		namedb_close(nsd->db);
89eab1363eSsthen 		region_destroy(nsd->options->region);
90eab1363eSsthen #endif
9115ed76cbSbrad 		exit(1);
9215ed76cbSbrad 	}
934564029fSflorian 	if(ixfrcr) {
944564029fSflorian 		if(!ixfr_create_perform(ixfrcr, zone, 0, nsd, fname,
954564029fSflorian 			ixfr_number)) {
964564029fSflorian #ifdef MEMCLEAN /* otherwise, the OS collects memory pages */
974564029fSflorian 			namedb_close(nsd->db);
984564029fSflorian 			region_destroy(nsd->options->region);
994564029fSflorian 			ixfr_create_free(ixfrcr);
1004564029fSflorian #endif
1014564029fSflorian 			error("could not create IXFR");
1024564029fSflorian 		}
1034564029fSflorian 		printf("zone %s created IXFR %s.ixfr\n", name, fname);
1044564029fSflorian 		ixfr_create_free(ixfrcr);
1054564029fSflorian 	}
1068d298c9fSsthen 	if (out) {
1078d298c9fSsthen 		print_rrs(out, zone);
1088d298c9fSsthen 		printf("; ");
1098d298c9fSsthen 	}
11015ed76cbSbrad 	printf("zone %s is ok\n", name);
11115ed76cbSbrad 	namedb_close(nsd->db);
11215ed76cbSbrad }
11315ed76cbSbrad 
11415ed76cbSbrad /* dummy functions to link */
writepid(struct nsd * ATTR_UNUSED (nsd))11515ed76cbSbrad int writepid(struct nsd * ATTR_UNUSED(nsd))
11615ed76cbSbrad {
11715ed76cbSbrad 	        return 0;
11815ed76cbSbrad }
unlinkpid(const char * ATTR_UNUSED (file))11915ed76cbSbrad void unlinkpid(const char * ATTR_UNUSED(file))
12015ed76cbSbrad {
12115ed76cbSbrad }
bind8_stats(struct nsd * ATTR_UNUSED (nsd))12215ed76cbSbrad void bind8_stats(struct nsd * ATTR_UNUSED(nsd))
12315ed76cbSbrad {
12415ed76cbSbrad }
12515ed76cbSbrad 
sig_handler(int ATTR_UNUSED (sig))12615ed76cbSbrad void sig_handler(int ATTR_UNUSED(sig))
12715ed76cbSbrad {
12815ed76cbSbrad }
12915ed76cbSbrad 
13015ed76cbSbrad extern char *optarg;
13115ed76cbSbrad extern int optind;
13215ed76cbSbrad 
13315ed76cbSbrad int
main(int argc,char * argv[])13415ed76cbSbrad main(int argc, char *argv[])
13515ed76cbSbrad {
13615ed76cbSbrad 	/* Scratch variables... */
13715ed76cbSbrad 	int c;
1388d298c9fSsthen 	int print_zone = 0;
1394564029fSflorian 	uint32_t ixfr_number = IXFR_NUMBER_DEFAULT;
1404564029fSflorian 	uint64_t ixfr_size = IXFR_SIZE_DEFAULT;
1414564029fSflorian 	char* oldzone = NULL;
14215ed76cbSbrad 	struct nsd nsd;
14315ed76cbSbrad 	memset(&nsd, 0, sizeof(nsd));
14415ed76cbSbrad 
14515ed76cbSbrad 	log_init("nsd-checkzone");
14615ed76cbSbrad 
14715ed76cbSbrad 	/* Parse the command line... */
1484564029fSflorian 	while ((c = getopt(argc, argv, "hi:n:ps:")) != -1) {
14915ed76cbSbrad 		switch (c) {
15015ed76cbSbrad 		case 'h':
15115ed76cbSbrad 			usage();
15215ed76cbSbrad 			exit(0);
1534564029fSflorian 		case 'i':
1544564029fSflorian 			oldzone = optarg;
1554564029fSflorian 			break;
1564564029fSflorian 		case 'n':
1574564029fSflorian 			ixfr_number = (uint32_t)atoi(optarg);
1584564029fSflorian 			break;
1598d298c9fSsthen 		case 'p':
1608d298c9fSsthen 			print_zone = 1;
1618d298c9fSsthen 			break;
1624564029fSflorian 		case 's':
1634564029fSflorian 			ixfr_size = (uint64_t)atoi(optarg);
1644564029fSflorian 			break;
16515ed76cbSbrad 		case '?':
16615ed76cbSbrad 		default:
16715ed76cbSbrad 			usage();
16815ed76cbSbrad 			exit(1);
16915ed76cbSbrad 		}
17015ed76cbSbrad 	}
17115ed76cbSbrad 	argc -= optind;
17215ed76cbSbrad 	argv += optind;
17315ed76cbSbrad 
17415ed76cbSbrad 	/* Commandline parse error */
17515ed76cbSbrad 	if (argc != 2) {
17615ed76cbSbrad 		fprintf(stderr, "wrong number of arguments.\n");
17715ed76cbSbrad 		usage();
17815ed76cbSbrad 		exit(1);
17915ed76cbSbrad 	}
18015ed76cbSbrad 
18115ed76cbSbrad 	nsd.options = nsd_options_create(region_create_custom(xalloc, free,
18215ed76cbSbrad 		DEFAULT_CHUNK_SIZE, DEFAULT_LARGE_OBJECT_SIZE,
18315ed76cbSbrad 		DEFAULT_INITIAL_CLEANUP_SIZE, 1));
18415ed76cbSbrad 	if (verbosity == 0)
18515ed76cbSbrad 		verbosity = nsd.options->verbosity;
18615ed76cbSbrad 
1874564029fSflorian 	check_zone(&nsd, argv[0], argv[1], print_zone ? stdout : NULL,
1884564029fSflorian 		oldzone, ixfr_number, ixfr_size);
18915ed76cbSbrad 	region_destroy(nsd.options->region);
19015ed76cbSbrad 	/* yylex_destroy(); but, not available in all versions of flex */
19115ed76cbSbrad 
19215ed76cbSbrad 	exit(0);
19315ed76cbSbrad }
194