zone_test.c 7.58 KB
Newer Older
Michael Graff's avatar
Michael Graff committed
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4 5 6
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 8 9
 *
 * See the COPYRIGHT file distributed with this work for additional
 * information regarding copyright ownership.
Michael Graff's avatar
Michael Graff committed
10 11
 */

12 13
#include <config.h>

14
#include <sys/param.h>
15 16 17 18
#include <sys/types.h>
#include <sys/time.h>

#include <unistd.h>
19 20
#include <stdlib.h>

21
#include <isc/app.h>
22
#include <isc/commandline.h>
23
#include <isc/mem.h>
24
#include <isc/print.h>
Andreas Gustafsson's avatar
Andreas Gustafsson committed
25
#include <isc/socket.h>
26 27
#include <isc/string.h>
#include <isc/task.h>
28
#include <isc/timer.h>
Brian Wellington's avatar
Brian Wellington committed
29
#include <isc/util.h>
30 31

#include <dns/db.h>
32
#include <dns/fixedname.h>
33
#include <dns/rdataclass.h>
34
#include <dns/rdataset.h>
35
#include <dns/result.h>
36
#include <dns/zone.h>
37

38 39 40 41
#ifdef ISC_PLATFORM_NEEDSYSSELECTH
#include <sys/select.h>
#endif

42 43 44 45 46
static int debug = 0;
static int quiet = 0;
static int stats = 0;
static isc_mem_t *mctx = NULL;
dns_zone_t *zone = NULL;
47 48 49 50
isc_taskmgr_t *taskmgr = NULL;
isc_timermgr_t *timermgr = NULL;
isc_socketmgr_t *socketmgr = NULL;
dns_zonemgr_t *zonemgr = NULL;
51 52 53 54 55
dns_zonetype_t zonetype = dns_zone_master;
isc_sockaddr_t addr;

#define ERRRET(result, function) \
	do { \
56
		if (result != ISC_R_SUCCESS) { \
57 58 59 60 61 62 63
			fprintf(stderr, "%s() returned %s\n", \
				function, dns_result_totext(result)); \
			return; \
		} \
	} while (0)

#define ERRCONT(result, function) \
64
		if (result != ISC_R_SUCCESS) { \
65 66 67 68 69 70 71
			fprintf(stderr, "%s() returned %s\n", \
				function, dns_result_totext(result)); \
			continue; \
		} else \
			(void)NULL

static void
72
usage(void) {
73
	fprintf(stderr,
74
		"usage: zone_test [-dqsSM] [-c class] [-f file] zone\n");
75 76 77 78
	exit(1);
}

static void
Brian Wellington's avatar
Brian Wellington committed
79
setup(const char *zonename, const char *filename, const char *classname) {
80
	isc_result_t result;
81
	dns_rdataclass_t rdclass;
Brian Wellington's avatar
Brian Wellington committed
82
	isc_consttextregion_t region;
83 84 85
	isc_buffer_t buffer;
	dns_fixedname_t fixorigin;
	dns_name_t *origin;
Brian Wellington's avatar
Brian Wellington committed
86
	const char *rbt = "rbt";
87 88 89 90 91 92 93 94 95

	if (debug)
		fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
			zonename, filename, classname);
	result = dns_zone_create(&zone, mctx);
	ERRRET(result, "dns_zone_new");

	dns_zone_settype(zone, zonetype);

96
	isc_buffer_constinit(&buffer, zonename, strlen(zonename));
97 98 99
	isc_buffer_add(&buffer, strlen(zonename));
	dns_fixedname_init(&fixorigin);
	result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
Automatic Updater's avatar
Automatic Updater committed
100
				   &buffer, dns_rootname, 0, NULL);
101 102
	ERRRET(result, "dns_name_fromtext");
	origin = dns_fixedname_name(&fixorigin);
103

104
	result = dns_zone_setorigin(zone, origin);
105 106
	ERRRET(result, "dns_zone_setorigin");

Brian Wellington's avatar
Brian Wellington committed
107
	result = dns_zone_setdbtype(zone, 1, &rbt);
108 109
	ERRRET(result, "dns_zone_setdatabase");

110 111
	result = dns_zone_setfile(zone, filename, dns_masterformat_text,
				  &dns_master_style_default);
Brian Wellington's avatar
Brian Wellington committed
112
	ERRRET(result, "dns_zone_setfile");
113 114 115

	region.base = classname;
	region.length = strlen(classname);
Brian Wellington's avatar
Brian Wellington committed
116
	result = dns_rdataclass_fromtext(&rdclass,
Mark Andrews's avatar
Mark Andrews committed
117
					 (isc_textregion_t *)(void*)&region);
118 119 120 121
	ERRRET(result, "dns_rdataclass_fromtext");

	dns_zone_setclass(zone, rdclass);

David Lawrence's avatar
David Lawrence committed
122
	if (zonetype == dns_zone_slave)
123
		dns_zone_setmasters(zone, &addr, 1);
124

125
	result = dns_zone_load(zone, false);
126 127
	ERRRET(result, "dns_zone_load");

128 129
	result = dns_zonemgr_managezone(zonemgr, zone);
	ERRRET(result, "dns_zonemgr_managezone");
130 131 132 133
}

static void
print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
Automatic Updater's avatar
Automatic Updater committed
134 135 136 137
	isc_buffer_t text;
	char t[1000];
	isc_result_t result;
	isc_region_t r;
138

Automatic Updater's avatar
Automatic Updater committed
139
	isc_buffer_init(&text, t, sizeof(t));
140
	result = dns_rdataset_totext(rdataset, name, false, false,
141
				     &text);
Automatic Updater's avatar
Automatic Updater committed
142 143 144 145 146
	isc_buffer_usedregion(&text, &r);
	if (result == ISC_R_SUCCESS)
		printf("%.*s", (int)r.length, (char *)r.base);
	else
		printf("%s\n", dns_result_totext(result));
147 148 149 150 151 152 153 154 155 156
}

static void
query(void) {
	char buf[1024];
	dns_fixedname_t name;
	dns_fixedname_t found;
	dns_db_t *db;
	char *s;
	isc_buffer_t buffer;
157
	isc_result_t result;
158
	dns_rdataset_t rdataset;
159
	dns_rdataset_t sigset;
160 161
	fd_set rfdset;

162 163
	db = NULL;
	result = dns_zone_getdb(zone, &db);
164
	if (result != ISC_R_SUCCESS) {
165 166
		fprintf(stderr, "%s() returned %s\n", "dns_zone_getdb",
			dns_result_totext(result));
167 168 169 170 171
		return;
	}

	dns_fixedname_init(&found);
	dns_rdataset_init(&rdataset);
172
	dns_rdataset_init(&sigset);
173 174

	do {
175

176 177 178 179 180
		fprintf(stdout, "zone_test ");
		fflush(stdout);
		FD_ZERO(&rfdset);
		FD_SET(0, &rfdset);
		select(1, &rfdset, NULL, NULL, NULL);
Andreas Gustafsson's avatar
Andreas Gustafsson committed
181
		if (fgets(buf, sizeof(buf), stdin) == NULL) {
182 183 184 185
			fprintf(stdout, "\n");
			break;
		}
		buf[sizeof(buf) - 1] = '\0';
186

187 188 189 190 191 192 193
		s = strchr(buf, '\n');
		if (s != NULL)
			*s = '\0';
		s = strchr(buf, '\r');
		if (s != NULL)
			*s = '\0';
		if (strcmp(buf, "dump") == 0) {
194 195 196
			dns_zone_dumptostream(zone, stdout,
					      dns_masterformat_text,
					      &dns_master_style_default, 0);
197 198
			continue;
		}
Mark Andrews's avatar
Mark Andrews committed
199
		if (strlen(buf) == 0U)
200 201
			continue;
		dns_fixedname_init(&name);
202
		isc_buffer_init(&buffer, buf, strlen(buf));
203 204
		isc_buffer_add(&buffer, strlen(buf));
		result = dns_name_fromtext(dns_fixedname_name(&name),
205
				  &buffer, dns_rootname, 0, NULL);
206
		ERRCONT(result, "dns_name_fromtext");
207

208 209 210 211 212 213 214
		result = dns_db_find(db, dns_fixedname_name(&name),
				     NULL /*vesion*/,
				     dns_rdatatype_a,
				     0 /*options*/,
				     0 /*time*/,
				     NULL /*nodep*/,
				     dns_fixedname_name(&found),
215
				     &rdataset, &sigset);
216 217 218 219 220 221
		fprintf(stderr, "%s() returned %s\n", "dns_db_find",
			dns_result_totext(result));
		switch (result) {
		case DNS_R_DELEGATION:
			print_rdataset(dns_fixedname_name(&found), &rdataset);
			break;
222
		case ISC_R_SUCCESS:
223 224 225
			print_rdataset(dns_fixedname_name(&name), &rdataset);
			break;
		default:
226
			break;
227 228
		}

229 230 231 232
		if (dns_rdataset_isassociated(&rdataset))
			dns_rdataset_disassociate(&rdataset);
		if (dns_rdataset_isassociated(&sigset))
			dns_rdataset_disassociate(&sigset);
233 234
	} while (1);
	dns_rdataset_invalidate(&rdataset);
235
	dns_db_detach(&db);
236 237 238 239 240 241
}

int
main(int argc, char **argv) {
	int c;
	char *filename = NULL;
Brian Wellington's avatar
Brian Wellington committed
242
	const char *classname = "IN";
243

244
	while ((c = isc_commandline_parse(argc, argv, "cdf:m:qsMS")) != EOF) {
245 246
		switch (c) {
		case 'c':
247
			classname = isc_commandline_argument;
248 249 250 251 252 253 254
			break;
		case 'd':
			debug++;
			break;
		case 'f':
			if (filename != NULL)
				usage();
255
			filename = isc_commandline_argument;
256 257
			break;
		case 'm':
Andreas Gustafsson's avatar
Andreas Gustafsson committed
258
			memset(&addr, 0, sizeof(addr));
259
			addr.type.sin.sin_family = AF_INET;
260 261 262 263 264 265
			if (inet_pton(AF_INET, isc_commandline_argument,
				      &addr.type.sin.sin_addr) != 1) {
				fprintf(stderr, "bad master address '%s'\n",
					isc_commandline_argument);
				exit(1);
			}
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
			addr.type.sin.sin_port = htons(53);
			break;
		case 'q':
			quiet++;
			break;
		case 's':
			stats++;
			break;
		case 'S':
			zonetype = dns_zone_slave;
			break;
		case 'M':
			zonetype = dns_zone_master;
			break;
		default:
			usage();
		}
	}

285
	if (argv[isc_commandline_index] == NULL)
286 287 288 289
		usage();

	RUNTIME_CHECK(isc_app_start() == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
290
	RUNTIME_CHECK(isc_taskmgr_create(mctx, 2, 0, &taskmgr) ==
291
		      ISC_R_SUCCESS);
292 293 294 295
	RUNTIME_CHECK(isc_timermgr_create(mctx, &timermgr) == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS);
	RUNTIME_CHECK(dns_zonemgr_create(mctx, taskmgr, timermgr, socketmgr,
					 &zonemgr) == ISC_R_SUCCESS);
296
	if (filename == NULL)
297 298
		filename = argv[isc_commandline_index];
	setup(argv[isc_commandline_index], filename, classname);
299
	query();
300 301 302 303 304
	if (zone != NULL)
		dns_zone_detach(&zone);
	dns_zonemgr_shutdown(zonemgr);
	dns_zonemgr_detach(&zonemgr);
	isc_socketmgr_destroy(&socketmgr);
305
	isc_taskmgr_destroy(&taskmgr);
306
	isc_timermgr_destroy(&timermgr);
307 308 309 310
	if (!quiet && stats)
		isc_mem_stats(mctx, stdout);
	isc_mem_destroy(&mctx);

Mark Andrews's avatar
Mark Andrews committed
311
	return (0);
312
}