db_test.c 19.9 KB
Newer Older
Bob Halley's avatar
Bob Halley committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
 * Copyright (C) 1999  Internet Software Consortium.
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM 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.
 */

Bob Halley's avatar
Bob Halley committed
18
19
20
21
/*
 * Principal Author: Bob Halley
 */

Bob Halley's avatar
Bob Halley committed
22
23
24
#include <config.h>

#include <stddef.h>
Bob Halley's avatar
Bob Halley committed
25
26
#include <stdlib.h>
#include <string.h>
27
28
#include <time.h>
#include <sys/time.h>	/* XXX Naughty. */
29
#include <unistd.h>	/* XXX Naughty. */
Bob Halley's avatar
Bob Halley committed
30
31
32
33
34

#include <isc/assertions.h>
#include <isc/error.h>
#include <isc/boolean.h>
#include <isc/region.h>
Bob Halley's avatar
Bob Halley committed
35
#include <isc/list.h>
Bob Halley's avatar
Bob Halley committed
36
37
38
39

#include <dns/types.h>
#include <dns/result.h>
#include <dns/name.h>
Bob Halley's avatar
Bob Halley committed
40
#include <dns/fixedname.h>
Bob Halley's avatar
Bob Halley committed
41
42
43
44
45
#include <dns/rdata.h>
#include <dns/rdataclass.h>
#include <dns/rdatatype.h>
#include <dns/rdatalist.h>
#include <dns/rdataset.h>
Bob Halley's avatar
Bob Halley committed
46
#include <dns/rdatasetiter.h>
Bob Halley's avatar
Bob Halley committed
47
48
#include <dns/compress.h>
#include <dns/db.h>
Bob Halley's avatar
Bob Halley committed
49
#include <dns/dbiterator.h>
50
#include <dns/dbtable.h>
Bob Halley's avatar
Bob Halley committed
51

52
53
#define MAXHOLD			100
#define MAXVERSIONS		100
Bob Halley's avatar
Bob Halley committed
54

Bob Halley's avatar
Bob Halley committed
55
56
57
58
59
60
61
62
typedef struct dbinfo {
	dns_db_t *		db;
	dns_dbversion_t *	version;
	dns_dbversion_t *	wversion;
	dns_dbversion_t *	rversions[MAXVERSIONS];
	int			rcount;
	dns_dbnode_t *		hold_nodes[MAXHOLD];
	int			hold_count;
63
64
65
	dns_dbiterator_t *	dbiterator;
	dns_dbversion_t *	iversion;
	int			pause_every;
Bob Halley's avatar
Bob Halley committed
66
67
68
	ISC_LINK(struct dbinfo)	link;
} dbinfo;

69
70
71
static isc_mem_t *		mctx = NULL;
static char			dbtype[128];
static dns_dbtable_t *		dbtable;
Bob Halley's avatar
Bob Halley committed
72
73
74
static ISC_LIST(dbinfo)		dbs;
static dbinfo *			cache_dbi = NULL;
static int			pause_every = 0;
Bob Halley's avatar
Bob Halley committed
75

Bob Halley's avatar
Bob Halley committed
76
77
78
79
80
81
82
83
static void
print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
	isc_buffer_t text;
	char t[1000];
	dns_result_t result;
	isc_region_t r;

	isc_buffer_init(&text, t, sizeof t, ISC_BUFFERTYPE_TEXT);
84
85
	result = dns_rdataset_totext(rdataset, name, ISC_FALSE, ISC_FALSE,
				     &text);
Bob Halley's avatar
Bob Halley committed
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
	isc_buffer_used(&text, &r);
	if (result == DNS_R_SUCCESS)
		printf("%.*s", (int)r.length, (char *)r.base);
	else
		printf("%s\n", dns_result_totext(result));
}

static void
print_rdatasets(dns_name_t *name, dns_rdatasetiter_t *rdsiter) {
	dns_result_t result;
	dns_rdataset_t rdataset;

	dns_rdataset_init(&rdataset);
	result = dns_rdatasetiter_first(rdsiter);
	while (result == DNS_R_SUCCESS) {
		dns_rdatasetiter_current(rdsiter, &rdataset);
		print_rdataset(name, &rdataset);
		dns_rdataset_disassociate(&rdataset);
		result = dns_rdatasetiter_next(rdsiter);
	}
	if (result != DNS_R_NOMORE)
		printf("%s\n", dns_result_totext(result));
}

Bob Halley's avatar
Bob Halley committed
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
static dbinfo *
select_db(char *origintext) {
	dns_fixedname_t forigin;
	dns_name_t *origin;
	isc_buffer_t source;
	size_t len;
	dbinfo *dbi;
	dns_result_t result;

	if (strcasecmp(origintext, "cache") == 0) {
		if (cache_dbi == NULL)
			printf("the cache does not exist\n");
		return (cache_dbi);
	}
	len = strlen(origintext);
	isc_buffer_init(&source, origintext, len, ISC_BUFFERTYPE_TEXT);
	isc_buffer_add(&source, len);
	dns_fixedname_init(&forigin);
	origin = dns_fixedname_name(&forigin);
	result = dns_name_fromtext(origin, &source, dns_rootname, ISC_FALSE,
				   NULL);
	if (result != DNS_R_SUCCESS) {
		printf("bad name: %s\n", dns_result_totext(result));
		return (NULL);
	}

	for (dbi = ISC_LIST_HEAD(dbs);
	     dbi != NULL;
	     dbi = ISC_LIST_NEXT(dbi, link)) {
		if (dns_name_compare(dns_db_origin(dbi->db), origin) == 0)
			break;
	}

	return (dbi);
}

static void
dump(dbinfo *dbi) {
	dns_fixedname_t fname;
	dns_name_t *name;
	dns_dbnode_t *node;
	dns_rdatasetiter_t *rdsiter;
	dns_result_t result;
	int i;

155
156
157
158
159
160
161
162
163
164
165
	dns_fixedname_init(&fname);
	name = dns_fixedname_name(&fname);

	if (dbi->dbiterator == NULL) {
		INSIST(dbi->iversion == NULL);
		if (dns_db_iszone(dbi->db)) {
			if (dbi->version != NULL)
				dns_db_attachversion(dbi->db, dbi->version,
						     &dbi->iversion);
			else
				dns_db_currentversion(dbi->db, &dbi->iversion);
Bob Halley's avatar
Bob Halley committed
166
167
		}
		
168
169
170
171
172
173
		result = dns_db_createiterator(dbi->db, ISC_FALSE,
					       &dbi->dbiterator);
		if (result == DNS_R_SUCCESS)
			result = dns_dbiterator_first(dbi->dbiterator);
	} else
		result = DNS_R_SUCCESS;
Bob Halley's avatar
Bob Halley committed
174
175
176
177
178

	node = NULL;
	rdsiter = NULL;
	i = 0;
	while (result == DNS_R_SUCCESS) {
179
		result = dns_dbiterator_current(dbi->dbiterator, &node, name);
Bob Halley's avatar
Bob Halley committed
180
181
		if (result != DNS_R_SUCCESS && result != DNS_R_NEWORIGIN)
			break;
182
		result = dns_db_allrdatasets(dbi->db, node, dbi->iversion, 0,
Bob Halley's avatar
Bob Halley committed
183
184
185
186
187
188
189
190
					     &rdsiter);
		if (result != DNS_R_SUCCESS) {
			dns_db_detachnode(dbi->db, &node);
			break;
		}
		print_rdatasets(name, rdsiter);
		dns_rdatasetiter_destroy(&rdsiter);
		dns_db_detachnode(dbi->db, &node);
191
		result = dns_dbiterator_next(dbi->dbiterator);
Bob Halley's avatar
Bob Halley committed
192
		i++;
193
194
195
196
197
		if (result == DNS_R_SUCCESS && i == dbi->pause_every) {
			printf("[more...]\n");
			result = dns_dbiterator_pause(dbi->dbiterator);
			if (result == DNS_R_SUCCESS)
				return;
Bob Halley's avatar
Bob Halley committed
198
199
200
201
202
		}
	}
	if (result != DNS_R_NOMORE)
		printf("%s\n", dns_result_totext(result));

203
204
205
	dns_dbiterator_destroy(&dbi->dbiterator);
	if (dbi->iversion != NULL)
		dns_db_closeversion(dbi->db, &dbi->iversion, ISC_FALSE);
Bob Halley's avatar
Bob Halley committed
206
207
}

208
209
210
211
212
213
214
static dns_result_t
load(char *filename, char *origintext, isc_boolean_t cache) {
	dns_fixedname_t forigin;
	dns_name_t *origin;
	dns_result_t result;
	isc_buffer_t source;
	size_t len;
Bob Halley's avatar
Bob Halley committed
215
216
217
218
219
220
	dbinfo *dbi;
	unsigned int i;

	dbi = isc_mem_get(mctx, sizeof *dbi);
	if (dbi == NULL)
		return (DNS_R_NOMEMORY);
221

Bob Halley's avatar
Bob Halley committed
222
223
224
225
226
227
228
229
	dbi->db = NULL;
	dbi->version = NULL;
	dbi->wversion = NULL;
	for (i = 0; i < MAXVERSIONS; i++)
		dbi->rversions[i] = NULL;
	dbi->hold_count = 0;
	for (i = 0; i < MAXHOLD; i++)
		dbi->hold_nodes[i] = NULL;
230
231
232
	dbi->dbiterator = NULL;
	dbi->iversion = NULL;
	dbi->pause_every = pause_every;
233
234
235
236
237
238
239
240
241
242
243
244
	
	len = strlen(origintext);
	isc_buffer_init(&source, origintext, len, ISC_BUFFERTYPE_TEXT);
	isc_buffer_add(&source, len);
	dns_fixedname_init(&forigin);
	origin = dns_fixedname_name(&forigin);
	result = dns_name_fromtext(origin, &source, dns_rootname, ISC_FALSE,
				   NULL);
	if (result != DNS_R_SUCCESS)
		return (result);

	result = dns_db_create(mctx, dbtype, origin, cache, dns_rdataclass_in,
Bob Halley's avatar
Bob Halley committed
245
246
247
			       0, NULL, &dbi->db);
	if (result != DNS_R_SUCCESS) {
		isc_mem_put(mctx, dbi, sizeof *dbi);
248
		return (result);
Bob Halley's avatar
Bob Halley committed
249
	}
250
251

	printf("loading %s (%s)\n", filename, origintext);
Bob Halley's avatar
Bob Halley committed
252
253
254
255
	result = dns_db_load(dbi->db, filename);
	if (result != DNS_R_SUCCESS) {
		dns_db_detach(&dbi->db);
		isc_mem_put(mctx, dbi, sizeof *dbi);
256
		return (result);
Bob Halley's avatar
Bob Halley committed
257
	}
258
259
260
	printf("loaded\n");

	if (cache) {
Bob Halley's avatar
Bob Halley committed
261
262
263
		INSIST(cache_dbi == NULL);
		dns_dbtable_adddefault(dbtable, dbi->db);
		cache_dbi = dbi;
264
	} else {
Bob Halley's avatar
Bob Halley committed
265
266
267
		if (dns_dbtable_add(dbtable, dbi->db) != DNS_R_SUCCESS) {
			dns_db_detach(&dbi->db);
			isc_mem_put(mctx, dbi, sizeof *dbi);
268
			return (result);
Bob Halley's avatar
Bob Halley committed
269
270
271
		}
	}
	ISC_LIST_APPEND(dbs, dbi, link);
272
273
274
275
276
277

	return (DNS_R_SUCCESS);
}

static void
unload_all(void) {
Bob Halley's avatar
Bob Halley committed
278
	dbinfo *dbi, *dbi_next;
279
	
Bob Halley's avatar
Bob Halley committed
280
281
282
283
284
285
286
287
288
289
290
291
	for (dbi = ISC_LIST_HEAD(dbs); dbi != NULL; dbi = dbi_next) {
		dbi_next = ISC_LIST_NEXT(dbi, link);
		if (dns_db_iszone(dbi->db))
			dns_dbtable_remove(dbtable, dbi->db);
		else {
			INSIST(dbi == cache_dbi);
			dns_dbtable_removedefault(dbtable);
			cache_dbi = NULL;
		}
		dns_db_detach(&dbi->db);
		ISC_LIST_UNLINK(dbs, dbi, link);
		isc_mem_put(mctx, dbi, sizeof *dbi);
292
293
294
	}
}

Bob Halley's avatar
Bob Halley committed
295
296
297
298
299
300
#define DBI_CHECK(dbi) \
if ((dbi) == NULL) { \
	printf("You must first select a database with !DB\n"); \
	continue; \
}
 
Bob Halley's avatar
Bob Halley committed
301
302
303
304
305
int
main(int argc, char *argv[]) {
	dns_db_t *db;
	dns_dbnode_t *node;
	dns_result_t result;
306
	dns_name_t name;
Bob Halley's avatar
Bob Halley committed
307
308
	dns_offsets_t offsets;
	size_t len;
Bob Halley's avatar
Bob Halley committed
309
	isc_buffer_t source, target;
Bob Halley's avatar
Bob Halley committed
310
	char s[1000];
Bob Halley's avatar
Bob Halley committed
311
	char b[255];
Bob Halley's avatar
Bob Halley committed
312
	dns_rdataset_t rdataset;
313
	int ch;
Bob Halley's avatar
Bob Halley committed
314
	dns_rdatatype_t type = 1;
Bob Halley's avatar
Bob Halley committed
315
316
	isc_boolean_t printnode = ISC_FALSE;
	isc_boolean_t addmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
317
	isc_boolean_t delmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
318
	isc_boolean_t holdmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
319
	isc_boolean_t verbose = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
320
	isc_boolean_t done = ISC_FALSE;
321
322
	isc_boolean_t quiet = ISC_FALSE;
	isc_boolean_t time_lookups = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
323
	isc_boolean_t found_as;
Bob Halley's avatar
Bob Halley committed
324
	int i, v;
Bob Halley's avatar
Bob Halley committed
325
	dns_rdatasetiter_t *rdsiter;
Bob Halley's avatar
Bob Halley committed
326
327
328
329
330
331
332
	char t1[256];
	char t2[256];
	isc_buffer_t tb1, tb2;
	isc_region_t r1, r2;
	dns_fixedname_t foundname;
	dns_name_t *fname;
	unsigned int options = 0;
333
	struct timeval start, finish;
334
	char *origintext;
Bob Halley's avatar
Bob Halley committed
335
336
337
	dbinfo *dbi;
	dns_dbversion_t *version;
	dns_name_t *origin;
338
	size_t memory_quota = 0;
339
340

	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
Bob Halley's avatar
Bob Halley committed
341
342
	RUNTIME_CHECK(dns_dbtable_create(mctx, dns_rdataclass_in, &dbtable) ==
		      DNS_R_SUCCESS);
343

Bob Halley's avatar
Bob Halley committed
344
	strcpy(dbtype, "rbt");
345
	while ((ch = getopt(argc, argv, "c:d:t:z:P:Q:gpqvT")) != -1) {
346
		switch (ch) {
Bob Halley's avatar
Bob Halley committed
347
		case 'c':
348
349
350
			result = load(optarg, ".", ISC_TRUE);
			if (result != DNS_R_SUCCESS)
				printf("%s\n", dns_result_totext(result));
351
			break;
Bob Halley's avatar
Bob Halley committed
352
353
354
		case 'd':
			strcpy(dbtype, optarg);
			break;
Bob Halley's avatar
Bob Halley committed
355
		case 'g':
356
357
358
359
360
			options |= (DNS_DBFIND_GLUEOK|DNS_DBFIND_VALIDATEGLUE);
			break;
		case 'q':
			quiet = ISC_TRUE;
			verbose = ISC_FALSE;
361
			break;
Bob Halley's avatar
Bob Halley committed
362
363
364
		case 'p':
			printnode = ISC_TRUE;
			break;
Bob Halley's avatar
Bob Halley committed
365
366
367
		case 'P':
			pause_every = atoi(optarg);
			break;
368
369
370
371
		case 'Q':
			memory_quota = atoi(optarg);
			isc_mem_setquota(mctx, memory_quota);
			break;
Bob Halley's avatar
Bob Halley committed
372
373
374
		case 't':
			type = atoi(optarg);
			break;
375
376
377
		case 'T':
			time_lookups = ISC_TRUE;
			break;
Bob Halley's avatar
Bob Halley committed
378
379
380
		case 'v':
			verbose = ISC_TRUE;
			break;
Bob Halley's avatar
Bob Halley committed
381
		case 'z':
382
383
384
385
386
387
388
389
			origintext = strrchr(optarg, '/');
			if (origintext == NULL)
				origintext = optarg;
			else
				origintext++;	/* Skip '/'. */
			result = load(optarg, origintext, ISC_FALSE);
			if (result != DNS_R_SUCCESS)
				printf("%s\n", dns_result_totext(result));
Bob Halley's avatar
Bob Halley committed
390
			break;
391
392
393
394
395
		}
	}

	argc -= optind;
	argv += optind;
Bob Halley's avatar
Bob Halley committed
396

397
398
	if (argc != 0)
		printf("ignoring trailing arguments\n");
Bob Halley's avatar
Bob Halley committed
399

400
401
402
	/*
	 * Some final initialization...
	 */
Bob Halley's avatar
Bob Halley committed
403
404
	dns_fixedname_init(&foundname);
	fname = dns_fixedname_name(&foundname);
Bob Halley's avatar
Bob Halley committed
405
406
407
	dbi = NULL;
	origin = dns_rootname;
	version = NULL;
Bob Halley's avatar
Bob Halley committed
408

409
410
411
412
413
	if (time_lookups) {
		/* Naughty */
		(void)gettimeofday(&start, NULL);
	}

Bob Halley's avatar
Bob Halley committed
414
	while (!done) {
415
416
		if (!quiet)
			printf("\n");
Bob Halley's avatar
Bob Halley committed
417
		if (fgets(s, sizeof s, stdin) == NULL) {
Bob Halley's avatar
Bob Halley committed
418
419
420
			done = ISC_TRUE;
			continue;
		}
Bob Halley's avatar
Bob Halley committed
421
422
423
424
425
426
427
428
429
430
		len = strlen(s);
		if (len > 0 && s[len - 1] == '\n') {
			s[len - 1] = '\0';
			len--;
		}
		if (verbose && dbi != NULL) {
			if (dbi->wversion != NULL)
				printf("future version (%p)\n", dbi->wversion);
			for (i = 0; i < dbi->rcount; i++)
				if (dbi->rversions[i] != NULL)
Bob Halley's avatar
Bob Halley committed
431
					printf("open version %d (%p)\n", i,
Bob Halley's avatar
Bob Halley committed
432
					       dbi->rversions[i]);
Bob Halley's avatar
Bob Halley committed
433
		}
Bob Halley's avatar
Bob Halley committed
434
		dns_name_init(&name, offsets);
Bob Halley's avatar
Bob Halley committed
435
		if (strcmp(s, "!R") == 0) {
Bob Halley's avatar
Bob Halley committed
436
437
			DBI_CHECK(dbi);
			if (dbi->rcount == MAXVERSIONS) {
Bob Halley's avatar
Bob Halley committed
438
439
440
				printf("too many open versions\n");
				continue;
			}
Bob Halley's avatar
Bob Halley committed
441
442
443
444
445
446
			dns_db_currentversion(dbi->db,
					      &dbi->rversions[dbi->rcount]);
			printf("opened version %d\n", dbi->rcount);
			dbi->version = dbi->rversions[dbi->rcount];
			version = dbi->version;
			dbi->rcount++;
Bob Halley's avatar
Bob Halley committed
447
448
			continue;
		} else if (strcmp(s, "!W") == 0) {
Bob Halley's avatar
Bob Halley committed
449
450
			DBI_CHECK(dbi);
			if (dbi->wversion != NULL) {
Bob Halley's avatar
Bob Halley committed
451
				printf("using existing future version\n");
Bob Halley's avatar
Bob Halley committed
452
453
				dbi->version = dbi->wversion;
				version = dbi->version;
Bob Halley's avatar
Bob Halley committed
454
455
				continue;
			}
Bob Halley's avatar
Bob Halley committed
456
			result = dns_db_newversion(dbi->db, &dbi->wversion);
Bob Halley's avatar
Bob Halley committed
457
458
459
460
			if (result != DNS_R_SUCCESS)
				printf("%s\n", dns_result_totext(result));
			else
				printf("newversion\n");
Bob Halley's avatar
Bob Halley committed
461
462
			dbi->version = dbi->wversion;
			version = dbi->version;
Bob Halley's avatar
Bob Halley committed
463
464
			continue;
		} else if (strcmp(s, "!C") == 0) {
Bob Halley's avatar
Bob Halley committed
465
			DBI_CHECK(dbi);
Bob Halley's avatar
Bob Halley committed
466
			addmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
467
			delmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
468
			if (dbi->version == NULL)
Bob Halley's avatar
Bob Halley committed
469
				continue;
Bob Halley's avatar
Bob Halley committed
470
			if (dbi->version == dbi->wversion) {
Bob Halley's avatar
Bob Halley committed
471
				printf("closing future version\n");
Bob Halley's avatar
Bob Halley committed
472
				dbi->wversion = NULL;
Bob Halley's avatar
Bob Halley committed
473
			} else {
Bob Halley's avatar
Bob Halley committed
474
475
476
477
				for (i = 0; i < dbi->rcount; i++) {
					if (dbi->version ==
					    dbi->rversions[i]) {
						dbi->rversions[i] = NULL;
Bob Halley's avatar
Bob Halley committed
478
479
480
481
482
483
					  printf("closing open version %d\n",
						 i);
						break;
					}
				}
			}
Bob Halley's avatar
Bob Halley committed
484
485
			dns_db_closeversion(dbi->db, &dbi->version, ISC_TRUE);
			version = NULL;
Bob Halley's avatar
Bob Halley committed
486
487
			continue;
		} else if (strcmp(s, "!X") == 0) {
Bob Halley's avatar
Bob Halley committed
488
			DBI_CHECK(dbi);
Bob Halley's avatar
Bob Halley committed
489
			addmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
490
			delmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
491
			if (dbi->version == NULL)
Bob Halley's avatar
Bob Halley committed
492
				continue;
Bob Halley's avatar
Bob Halley committed
493
			if (dbi->version == dbi->wversion) {
Bob Halley's avatar
Bob Halley committed
494
				printf("aborting future version\n");
Bob Halley's avatar
Bob Halley committed
495
				dbi->wversion = NULL;
Bob Halley's avatar
Bob Halley committed
496
			} else {
Bob Halley's avatar
Bob Halley committed
497
498
499
500
				for (i = 0; i < dbi->rcount; i++) {
					if (dbi->version ==
					    dbi->rversions[i]) {
						dbi->rversions[i] = NULL;
Bob Halley's avatar
Bob Halley committed
501
502
503
504
505
506
					  printf("closing open version %d\n",
						 i);
						break;
					}
				}
			}
Bob Halley's avatar
Bob Halley committed
507
508
			dns_db_closeversion(dbi->db, &dbi->version, ISC_FALSE);
			version = NULL;
Bob Halley's avatar
Bob Halley committed
509
510
			continue;
		} else if (strcmp(s, "!A") == 0) {
Bob Halley's avatar
Bob Halley committed
511
			DBI_CHECK(dbi);
Bob Halley's avatar
Bob Halley committed
512
			delmode = ISC_FALSE;
Bob Halley's avatar
Bob Halley committed
513
514
515
516
517
518
			if (addmode)
				addmode = ISC_FALSE;
			else
				addmode = ISC_TRUE;
			printf("addmode = %s\n", addmode ? "TRUE" : "FALSE");
			continue;
Bob Halley's avatar
Bob Halley committed
519
		} else if (strcmp(s, "!D") == 0) {
Bob Halley's avatar
Bob Halley committed
520
			DBI_CHECK(dbi);
Bob Halley's avatar
Bob Halley committed
521
522
523
524
525
526
527
			addmode = ISC_FALSE;
			if (delmode)
				delmode = ISC_FALSE;
			else
				delmode = ISC_TRUE;
			printf("delmode = %s\n", delmode ? "TRUE" : "FALSE");
			continue;
Bob Halley's avatar
Bob Halley committed
528
		} else if (strcmp(s, "!H") == 0) {
Bob Halley's avatar
Bob Halley committed
529
			DBI_CHECK(dbi);
Bob Halley's avatar
Bob Halley committed
530
531
532
533
534
535
536
			if (holdmode)
				holdmode = ISC_FALSE;
			else
				holdmode = ISC_TRUE;
			printf("holdmode = %s\n", holdmode ? "TRUE" : "FALSE");
			continue;
		} else if (strcmp(s, "!HR") == 0) {
Bob Halley's avatar
Bob Halley committed
537
538
539
540
541
			DBI_CHECK(dbi);
			for (i = 0; i < dbi->hold_count; i++)
				dns_db_detachnode(dbi->db,
						  &dbi->hold_nodes[i]);
			dbi->hold_count = 0;
Bob Halley's avatar
Bob Halley committed
542
543
544
545
			holdmode = ISC_FALSE;
			printf("held nodes have been detached\n");
			continue;
		} else if (strcmp(s, "!VC") == 0) {
Bob Halley's avatar
Bob Halley committed
546
			DBI_CHECK(dbi);
Bob Halley's avatar
Bob Halley committed
547
			printf("switching to current version\n");
Bob Halley's avatar
Bob Halley committed
548
			dbi->version = NULL;
Bob Halley's avatar
Bob Halley committed
549
550
			version = NULL;
			continue;
Bob Halley's avatar
Bob Halley committed
551
		} else if (strstr(s, "!V") == s) {
Bob Halley's avatar
Bob Halley committed
552
			DBI_CHECK(dbi);
Bob Halley's avatar
Bob Halley committed
553
			v = atoi(&s[2]);
Bob Halley's avatar
Bob Halley committed
554
			if (v >= dbi->rcount) {
Bob Halley's avatar
Bob Halley committed
555
556
				printf("unknown open version %d\n", v);
				continue;
Bob Halley's avatar
Bob Halley committed
557
			} else if (dbi->rversions[v] == NULL) {
Bob Halley's avatar
Bob Halley committed
558
559
560
561
				printf("version %d is not open\n", v);
				continue;
			}
			printf("switching to open version %d\n", v);
Bob Halley's avatar
Bob Halley committed
562
563
			dbi->version = dbi->rversions[v];
			version = dbi->version;
Bob Halley's avatar
Bob Halley committed
564
			continue;
Bob Halley's avatar
Bob Halley committed
565
566
567
568
569
570
571
572
573
574
575
576
577
		} else if (strstr(s, "!T") == s) {
			type = (unsigned int)atoi(&s[2]);
			printf("now searching for type %u\n", type);
			continue;
		} else if (strcmp(s, "!G") == 0) {
			if ((options & DNS_DBFIND_GLUEOK) != 0)
				options &= ~DNS_DBFIND_GLUEOK;
			else
				options |= DNS_DBFIND_GLUEOK;
			printf("glue ok = %s\n",
			       ((options & DNS_DBFIND_GLUEOK) != 0) ?
			       "TRUE" : "FALSE");
			continue;
578
579
580
581
582
583
584
585
586
		} else if (strcmp(s, "!GV") == 0) {
			if ((options & DNS_DBFIND_VALIDATEGLUE) != 0)
				options &= ~DNS_DBFIND_VALIDATEGLUE;
			else
				options |= DNS_DBFIND_VALIDATEGLUE;
			printf("validate glue = %s\n",
			       ((options & DNS_DBFIND_VALIDATEGLUE) != 0) ?
			       "TRUE" : "FALSE");
			continue;
Bob Halley's avatar
Bob Halley committed
587
588
589
590
		} else if (strcmp(s, "!LS") == 0) {
			DBI_CHECK(dbi);
			dump(dbi);
			continue;
591
592
593
594
595
		} else if (strstr(s, "!P") == s) {
			DBI_CHECK(dbi);
			v = atoi(&s[2]);
			dbi->pause_every = v;
			continue;
Bob Halley's avatar
Bob Halley committed
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
		} else if (strcmp(s, "!DB") == 0) {
			dbi = NULL;
			origin = dns_rootname;
			version = NULL;
			printf("now searching all databases\n");
			continue;
		} else if (strncmp(s, "!DB ", 4) == 0) {
			dbi = select_db(s+4);
			if (dbi != NULL) {
				db = dbi->db;
				origin = dns_db_origin(dbi->db);
				version = dbi->version;
				addmode = ISC_FALSE;
				delmode = ISC_FALSE;
				holdmode = ISC_FALSE;
			} else {
				db = NULL;
				version = NULL;
				origin = dns_rootname;
				printf("database not found; "
				       "now searching all databases\n");
			}
			continue;
Bob Halley's avatar
Bob Halley committed
619
		}
Bob Halley's avatar
Bob Halley committed
620

Bob Halley's avatar
Bob Halley committed
621
622
623
		isc_buffer_init(&source, s, len, ISC_BUFFERTYPE_TEXT);
		isc_buffer_add(&source, len);
		isc_buffer_init(&target, b, sizeof b, ISC_BUFFERTYPE_BINARY);
Bob Halley's avatar
Bob Halley committed
624
		result = dns_name_fromtext(&name, &source, origin,
625
					   ISC_FALSE, &target);
Bob Halley's avatar
Bob Halley committed
626
627
628
629
		if (result != DNS_R_SUCCESS) {
			printf("bad name: %s\n", dns_result_totext(result));
			continue;
		}
Bob Halley's avatar
Bob Halley committed
630

Bob Halley's avatar
Bob Halley committed
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
		if (dbi == NULL) {
			db = NULL;
			result = dns_dbtable_find(dbtable, &name, &db);
			if (result != DNS_R_SUCCESS &&
			    result != DNS_R_PARTIALMATCH) {
				if (!quiet)
					printf("\n%s\n",
					       dns_result_totext(result));
				continue;
			}
			isc_buffer_init(&tb1, t1, sizeof t1,
					ISC_BUFFERTYPE_TEXT);
			result = dns_name_totext(dns_db_origin(db), ISC_FALSE,
						 &tb1);
			if (result != DNS_R_SUCCESS) {
646
				printf("\n%s\n", dns_result_totext(result));
Bob Halley's avatar
Bob Halley committed
647
648
649
650
651
652
653
				dns_db_detach(&db);
				continue;
			}
			isc_buffer_used(&tb1, &r1);
			printf("\ndatabase = %.*s (%s)\n",
			       (int)r1.length, r1.base,
			       (dns_db_iszone(db)) ? "zone" : "cache");
654
		}
Bob Halley's avatar
Bob Halley committed
655
		node = NULL;
Bob Halley's avatar
Bob Halley committed
656
		dns_rdataset_init(&rdataset);
657
		result = dns_db_find(db, &name, version, type, options, 0,
Bob Halley's avatar
Bob Halley committed
658
				     &node, fname, &rdataset);
Bob Halley's avatar
Bob Halley committed
659
660
661
662
663
		if (!quiet) {
			if (dbi != NULL)
				printf("\n");
			printf("%s\n", dns_result_totext(result));
		}
Bob Halley's avatar
Bob Halley committed
664
665
666
667
668
669

		found_as = ISC_FALSE;
		switch (result) {
		case DNS_R_SUCCESS:
		case DNS_R_GLUE:
		case DNS_R_CNAME:
Bob Halley's avatar
Bob Halley committed
670
		case DNS_R_ZONECUT:
Bob Halley's avatar
Bob Halley committed
671
672
673
674
675
676
			break;
		case DNS_R_DNAME:
		case DNS_R_DELEGATION:
			found_as = ISC_TRUE;
			break;
		case DNS_R_NXRDATASET:
Bob Halley's avatar
Bob Halley committed
677
678
679
680
681
682
683
684
685
			if (dbi != NULL) {
				if (holdmode) {
					RUNTIME_CHECK(dbi->hold_count <
						      MAXHOLD);
					dbi->hold_nodes[dbi->hold_count++] =
						node;
					node = NULL;
				} else
					dns_db_detachnode(db, &node);
686
			} else {
Bob Halley's avatar
Bob Halley committed
687
				dns_db_detachnode(db, &node);
688
689
				dns_db_detach(&db);
			}
Bob Halley's avatar
Bob Halley committed
690
691
			continue;
		default:
Bob Halley's avatar
Bob Halley committed
692
693
			if (dbi == NULL)
				dns_db_detach(&db);
694
695
			if (quiet)
				printf("%s\n", dns_result_totext(result));
Bob Halley's avatar
Bob Halley committed
696
697
			continue;
		}
698
		if (found_as && !quiet) {
Bob Halley's avatar
Bob Halley committed
699
700
701
702
703
704
705
			isc_buffer_init(&tb1, t1, sizeof t1,
					ISC_BUFFERTYPE_TEXT);
			isc_buffer_init(&tb2, t2, sizeof t2,
					ISC_BUFFERTYPE_TEXT);
			result = dns_name_totext(&name, ISC_FALSE, &tb1);
			if (result != DNS_R_SUCCESS) {
				printf("%s\n", dns_result_totext(result));
706
				dns_db_detachnode(db, &node);
Bob Halley's avatar
Bob Halley committed
707
708
				if (dbi == NULL)
					dns_db_detach(&db);
Bob Halley's avatar
Bob Halley committed
709
710
711
712
713
				continue;
			}
			result = dns_name_totext(fname, ISC_FALSE, &tb2);
			if (result != DNS_R_SUCCESS) {
				printf("%s\n", dns_result_totext(result));
714
				dns_db_detachnode(db, &node);
Bob Halley's avatar
Bob Halley committed
715
716
				if (dbi == NULL)
					dns_db_detach(&db);
Bob Halley's avatar
Bob Halley committed
717
718
719
720
721
722
723
724
725
726
727
728
729
730
				continue;
			}
			isc_buffer_used(&tb1, &r1);
			isc_buffer_used(&tb2, &r2);
			printf("found %.*s as %.*s\n",
			       (int)r1.length, r1.base,
			       (int)r2.length, r2.base);
		}

		if (printnode)
			dns_db_printnode(db, node, stdout);

		if (!found_as && type == dns_rdatatype_any) {
			rdsiter = NULL;
731
			result = dns_db_allrdatasets(db, node, version, 0,
Bob Halley's avatar
Bob Halley committed
732
733
						     &rdsiter);
			if (result == DNS_R_SUCCESS) {
734
735
				if (!quiet)
					print_rdatasets(fname, rdsiter);
Bob Halley's avatar
Bob Halley committed
736
737
738
739
				dns_rdatasetiter_destroy(&rdsiter);
			} else
				printf("%s\n", dns_result_totext(result));
		} else {
740
741
			if (!quiet)
				print_rdataset(fname, &rdataset);
Bob Halley's avatar
Bob Halley committed
742
			if (dbi != NULL && addmode && !found_as) {
Bob Halley's avatar
Bob Halley committed
743
744
				rdataset.ttl++;
				result = dns_db_addrdataset(db, node, version,
745
							    0, &rdataset);
Bob Halley's avatar
Bob Halley committed
746
				if (result != DNS_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
747
748
					printf("%s\n",
					       dns_result_totext(result));
749
750
				if (printnode)
					dns_db_printnode(db, node, stdout);
Bob Halley's avatar
Bob Halley committed
751
			} else if (dbi != NULL && delmode && !found_as) {
Bob Halley's avatar
Bob Halley committed
752
753
754
				result = dns_db_deleterdataset(db, node,
							       version, type);
				if (result != DNS_R_SUCCESS)
Bob Halley's avatar
Bob Halley committed
755
756
					printf("%s\n",
					       dns_result_totext(result));
757
758
				if (printnode)
					dns_db_printnode(db, node, stdout);
Bob Halley's avatar
Bob Halley committed
759
			}
Bob Halley's avatar
Bob Halley committed
760
			dns_rdataset_disassociate(&rdataset);
Bob Halley's avatar
Bob Halley committed
761
		}
Bob Halley's avatar
Bob Halley committed
762

Bob Halley's avatar
Bob Halley committed
763
764
765
766
767
768
769
		if (dbi != NULL) {
			if (holdmode) {
				RUNTIME_CHECK(dbi->hold_count < MAXHOLD);
				dbi->hold_nodes[dbi->hold_count++] = node;
				node = NULL;
			} else
				dns_db_detachnode(db, &node);
770
		} else {
Bob Halley's avatar
Bob Halley committed
771
			dns_db_detachnode(db, &node);
772
773
			dns_db_detach(&db);
		}
Bob Halley's avatar
Bob Halley committed
774
775
	}

776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
	if (time_lookups) {
		struct timeval interval;

		/* Naughty */
		(void)gettimeofday(&finish, NULL);
		if (start.tv_usec > finish.tv_usec) {
			finish.tv_sec--;
			interval.tv_usec = 1000000 -
				start.tv_usec + finish.tv_usec;
		} else
			interval.tv_usec = finish.tv_usec - start.tv_usec;
		interval.tv_sec = finish.tv_sec - start.tv_sec;
		printf("elapsed time: %lu.%06lu seconds\n",
		       (unsigned long)interval.tv_sec,
		       (unsigned long)interval.tv_usec);
	}

793
794
795
	unload_all();

	dns_dbtable_destroy(&dbtable);
Bob Halley's avatar
Bob Halley committed
796

797
798
	if (!quiet)
		isc_mem_stats(mctx, stdout);
Bob Halley's avatar
Bob Halley committed
799
800
801

	return (0);
}