summaryrefslogtreecommitdiffstats
path: root/bin/tests/optional/db_test.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bin/tests/optional/db_test.c936
1 files changed, 936 insertions, 0 deletions
diff --git a/bin/tests/optional/db_test.c b/bin/tests/optional/db_test.c
new file mode 100644
index 0000000..c69af66
--- /dev/null
+++ b/bin/tests/optional/db_test.c
@@ -0,0 +1,936 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/time.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/db.h>
+#include <dns/dbiterator.h>
+#include <dns/dbtable.h>
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/rdataset.h>
+#include <dns/rdatasetiter.h>
+#include <dns/result.h>
+
+#define MAXHOLD 100
+#define MAXVERSIONS 100
+
+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;
+ dns_dbiterator_t * dbiterator;
+ dns_dbversion_t * iversion;
+ int pause_every;
+ bool ascending;
+ ISC_LINK(struct dbinfo) link;
+} dbinfo;
+
+static isc_mem_t * mctx = NULL;
+static char dbtype[128];
+static dns_dbtable_t * dbtable;
+static ISC_LIST(dbinfo) dbs;
+static dbinfo * cache_dbi = NULL;
+static int pause_every = 0;
+static bool ascending = true;
+
+static void
+print_result(const char *message, isc_result_t result) {
+
+ if (message == NULL)
+ message = "";
+ printf("%s%sresult %08x: %s\n", message, (*message == '\0') ? "" : " ",
+ result, isc_result_totext(result));
+}
+
+static void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset) {
+ isc_buffer_t text;
+ char t[1000];
+ isc_result_t result;
+ isc_region_t r;
+
+ isc_buffer_init(&text, t, sizeof(t));
+ result = dns_rdataset_totext(rdataset, name, false, false,
+ &text);
+ isc_buffer_usedregion(&text, &r);
+ if (result == ISC_R_SUCCESS)
+ printf("%.*s", (int)r.length, (char *)r.base);
+ else
+ print_result("", result);
+}
+
+static void
+print_rdatasets(dns_name_t *name, dns_rdatasetiter_t *rdsiter) {
+ isc_result_t result;
+ dns_rdataset_t rdataset;
+
+ dns_rdataset_init(&rdataset);
+ result = dns_rdatasetiter_first(rdsiter);
+ while (result == ISC_R_SUCCESS) {
+ dns_rdatasetiter_current(rdsiter, &rdataset);
+ print_rdataset(name, &rdataset);
+ dns_rdataset_disassociate(&rdataset);
+ result = dns_rdatasetiter_next(rdsiter);
+ }
+ if (result != ISC_R_NOMORE)
+ print_result("", result);
+}
+
+static dbinfo *
+select_db(char *origintext) {
+ dns_fixedname_t forigin;
+ dns_name_t *origin;
+ isc_buffer_t source;
+ size_t len;
+ dbinfo *dbi;
+ isc_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_buffer_add(&source, len);
+ origin = dns_fixedname_initname(&forigin);
+ result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ print_result("bad name", 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
+list(dbinfo *dbi, char *seektext) {
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ dns_dbnode_t *node;
+ dns_rdatasetiter_t *rdsiter;
+ isc_result_t result;
+ int i;
+ size_t len;
+ dns_fixedname_t fseekname;
+ dns_name_t *seekname;
+ isc_buffer_t source;
+
+ name = dns_fixedname_initname(&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);
+ }
+
+ result = dns_db_createiterator(dbi->db, 0, &dbi->dbiterator);
+ if (result == ISC_R_SUCCESS) {
+ if (seektext != NULL) {
+ len = strlen(seektext);
+ isc_buffer_init(&source, seektext, len);
+ isc_buffer_add(&source, len);
+ seekname = dns_fixedname_initname(&fseekname);
+ result = dns_name_fromtext(seekname, &source,
+ dns_db_origin(
+ dbi->db),
+ 0, NULL);
+ if (result == ISC_R_SUCCESS)
+ result = dns_dbiterator_seek(
+ dbi->dbiterator,
+ seekname);
+ } else if (dbi->ascending)
+ result = dns_dbiterator_first(dbi->dbiterator);
+ else
+ result = dns_dbiterator_last(dbi->dbiterator);
+ }
+ } else
+ result = ISC_R_SUCCESS;
+
+ node = NULL;
+ rdsiter = NULL;
+ i = 0;
+ while (result == ISC_R_SUCCESS) {
+ result = dns_dbiterator_current(dbi->dbiterator, &node, name);
+ if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
+ break;
+ result = dns_db_allrdatasets(dbi->db, node, dbi->iversion, 0,
+ &rdsiter);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detachnode(dbi->db, &node);
+ break;
+ }
+ print_rdatasets(name, rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ dns_db_detachnode(dbi->db, &node);
+ if (dbi->ascending)
+ result = dns_dbiterator_next(dbi->dbiterator);
+ else
+ result = dns_dbiterator_prev(dbi->dbiterator);
+ i++;
+ if (result == ISC_R_SUCCESS && i == dbi->pause_every) {
+ printf("[more...]\n");
+ result = dns_dbiterator_pause(dbi->dbiterator);
+ if (result == ISC_R_SUCCESS)
+ return;
+ }
+ }
+ if (result != ISC_R_NOMORE)
+ print_result("", result);
+
+ dns_dbiterator_destroy(&dbi->dbiterator);
+ if (dbi->iversion != NULL)
+ dns_db_closeversion(dbi->db, &dbi->iversion, false);
+}
+
+static isc_result_t
+load(const char *filename, const char *origintext, bool cache) {
+ dns_fixedname_t forigin;
+ dns_name_t *origin;
+ isc_result_t result;
+ isc_buffer_t source;
+ size_t len;
+ dbinfo *dbi;
+ unsigned int i;
+
+ dbi = isc_mem_get(mctx, sizeof(*dbi));
+ if (dbi == NULL)
+ return (ISC_R_NOMEMORY);
+
+ 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;
+ dbi->dbiterator = NULL;
+ dbi->iversion = NULL;
+ dbi->pause_every = pause_every;
+ dbi->ascending = ascending;
+ ISC_LINK_INIT(dbi, link);
+
+ len = strlen(origintext);
+ isc_buffer_constinit(&source, origintext, len);
+ isc_buffer_add(&source, len);
+ origin = dns_fixedname_initname(&forigin);
+ result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+
+ result = dns_db_create(mctx, dbtype, origin,
+ cache ? dns_dbtype_cache : dns_dbtype_zone,
+ dns_rdataclass_in,
+ 0, NULL, &dbi->db);
+ if (result != ISC_R_SUCCESS) {
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+
+ printf("loading %s (%s)\n", filename, origintext);
+ result = dns_db_load(dbi->db, filename);
+ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
+ dns_db_detach(&dbi->db);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+ printf("loaded\n");
+
+ if (cache) {
+ INSIST(cache_dbi == NULL);
+ dns_dbtable_adddefault(dbtable, dbi->db);
+ cache_dbi = dbi;
+ } else {
+ result = dns_dbtable_add(dbtable, dbi->db);
+ if (result != ISC_R_SUCCESS) {
+ dns_db_detach(&dbi->db);
+ isc_mem_put(mctx, dbi, sizeof(*dbi));
+ return (result);
+ }
+ }
+ ISC_LIST_APPEND(dbs, dbi, link);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+unload_all(void) {
+ dbinfo *dbi, *dbi_next;
+
+ 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));
+ }
+}
+
+#define DBI_CHECK(dbi) \
+if ((dbi) == NULL) { \
+ printf("You must first select a database with !DB\n"); \
+ continue; \
+}
+
+int
+main(int argc, char *argv[]) {
+ dns_db_t *db;
+ dns_dbnode_t *node;
+ isc_result_t result;
+ dns_name_t name;
+ dns_offsets_t offsets;
+ size_t len;
+ isc_buffer_t source, target;
+ char s[1000];
+ char b[255];
+ dns_rdataset_t rdataset, sigrdataset;
+ int ch;
+ dns_rdatatype_t type = 1;
+ bool printnode = false;
+ bool addmode = false;
+ bool delmode = false;
+ bool holdmode = false;
+ bool verbose = false;
+ bool done = false;
+ bool quiet = false;
+ bool time_lookups = false;
+ bool found_as;
+ bool find_zonecut = false;
+ bool noexact_zonecut = false;
+ int i, v;
+ dns_rdatasetiter_t *rdsiter;
+ 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, zcoptions;
+ isc_time_t start, finish;
+ const char *origintext;
+ dbinfo *dbi;
+ dns_dbversion_t *version;
+ dns_name_t *origin;
+ size_t memory_quota = 0;
+ dns_trust_t trust = 0;
+ unsigned int addopts;
+ isc_log_t *lctx = NULL;
+ size_t n;
+
+ dns_result_register();
+
+ RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
+ RUNTIME_CHECK(dns_dbtable_create(mctx, dns_rdataclass_in, &dbtable) ==
+ ISC_R_SUCCESS);
+
+ snprintf(dbtype, sizeof(dbtype), "rbt");
+ while ((ch = isc_commandline_parse(argc, argv, "c:d:t:z:P:Q:glpqvT"))
+ != -1) {
+ switch (ch) {
+ case 'c':
+ result = load(isc_commandline_argument, ".", true);
+ if (result != ISC_R_SUCCESS)
+ printf("cache load(%s) %08x: %s\n",
+ isc_commandline_argument, result,
+ isc_result_totext(result));
+ break;
+ case 'd':
+ n = strlcpy(dbtype, isc_commandline_argument,
+ sizeof(dbtype));
+ if (n >= sizeof(dbtype)) {
+ fprintf(stderr, "bad db type '%s'\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'g':
+ options |= (DNS_DBFIND_GLUEOK|DNS_DBFIND_VALIDATEGLUE);
+ break;
+ case 'l':
+ RUNTIME_CHECK(isc_log_create(mctx, &lctx,
+ NULL) == ISC_R_SUCCESS);
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+ break;
+ case 'q':
+ quiet = true;
+ verbose = false;
+ break;
+ case 'p':
+ printnode = true;
+ break;
+ case 'P':
+ pause_every = atoi(isc_commandline_argument);
+ break;
+ case 'Q':
+ memory_quota = atoi(isc_commandline_argument);
+ isc_mem_setquota(mctx, memory_quota);
+ break;
+ case 't':
+ type = atoi(isc_commandline_argument);
+ break;
+ case 'T':
+ time_lookups = true;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ case 'z':
+ origintext = strrchr(isc_commandline_argument, '/');
+ if (origintext == NULL)
+ origintext = isc_commandline_argument;
+ else
+ origintext++; /* Skip '/'. */
+ result = load(isc_commandline_argument, origintext,
+ false);
+ if (result != ISC_R_SUCCESS)
+ printf("zone load(%s) %08x: %s\n",
+ isc_commandline_argument, result,
+ isc_result_totext(result));
+ break;
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+ POST(argv);
+
+ if (argc != 0)
+ printf("ignoring trailing arguments\n");
+
+ /*
+ * Some final initialization...
+ */
+ fname = dns_fixedname_initname(&foundname);
+ dbi = NULL;
+ origin = dns_rootname;
+ version = NULL;
+
+ if (time_lookups) {
+ TIME_NOW(&start);
+ }
+
+ while (!done) {
+ if (!quiet)
+ printf("\n");
+ if (fgets(s, sizeof(s), stdin) == NULL) {
+ done = true;
+ continue;
+ }
+ len = strlen(s);
+ if (len > 0U && 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)
+ printf("open version %d (%p)\n", i,
+ dbi->rversions[i]);
+ }
+ dns_name_init(&name, offsets);
+ if (strcmp(s, "!R") == 0) {
+ DBI_CHECK(dbi);
+ if (dbi->rcount == MAXVERSIONS) {
+ printf("too many open versions\n");
+ continue;
+ }
+ 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++;
+ continue;
+ } else if (strcmp(s, "!W") == 0) {
+ DBI_CHECK(dbi);
+ if (dbi->wversion != NULL) {
+ printf("using existing future version\n");
+ dbi->version = dbi->wversion;
+ version = dbi->version;
+ continue;
+ }
+ result = dns_db_newversion(dbi->db, &dbi->wversion);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ else
+ printf("newversion\n");
+ dbi->version = dbi->wversion;
+ version = dbi->version;
+ continue;
+ } else if (strcmp(s, "!C") == 0) {
+ DBI_CHECK(dbi);
+ addmode = false;
+ delmode = false;
+ if (dbi->version == NULL)
+ continue;
+ if (dbi->version == dbi->wversion) {
+ printf("closing future version\n");
+ dbi->wversion = NULL;
+ } else {
+ for (i = 0; i < dbi->rcount; i++) {
+ if (dbi->version ==
+ dbi->rversions[i]) {
+ dbi->rversions[i] = NULL;
+ printf("closing open version %d\n",
+ i);
+ break;
+ }
+ }
+ }
+ dns_db_closeversion(dbi->db, &dbi->version, true);
+ version = NULL;
+ continue;
+ } else if (strcmp(s, "!X") == 0) {
+ DBI_CHECK(dbi);
+ addmode = false;
+ delmode = false;
+ if (dbi->version == NULL)
+ continue;
+ if (dbi->version == dbi->wversion) {
+ printf("aborting future version\n");
+ dbi->wversion = NULL;
+ } else {
+ for (i = 0; i < dbi->rcount; i++) {
+ if (dbi->version ==
+ dbi->rversions[i]) {
+ dbi->rversions[i] = NULL;
+ printf("closing open version %d\n",
+ i);
+ break;
+ }
+ }
+ }
+ dns_db_closeversion(dbi->db, &dbi->version, false);
+ version = NULL;
+ continue;
+ } else if (strcmp(s, "!A") == 0) {
+ DBI_CHECK(dbi);
+ delmode = false;
+ if (addmode)
+ addmode = false;
+ else
+ addmode = true;
+ printf("addmode = %s\n", addmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!D") == 0) {
+ DBI_CHECK(dbi);
+ addmode = false;
+ if (delmode)
+ delmode = false;
+ else
+ delmode = true;
+ printf("delmode = %s\n", delmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!H") == 0) {
+ DBI_CHECK(dbi);
+ if (holdmode)
+ holdmode = false;
+ else
+ holdmode = true;
+ printf("holdmode = %s\n", holdmode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!HR") == 0) {
+ DBI_CHECK(dbi);
+ for (i = 0; i < dbi->hold_count; i++)
+ dns_db_detachnode(dbi->db,
+ &dbi->hold_nodes[i]);
+ dbi->hold_count = 0;
+ holdmode = false;
+ printf("held nodes have been detached\n");
+ continue;
+ } else if (strcmp(s, "!VC") == 0) {
+ DBI_CHECK(dbi);
+ printf("switching to current version\n");
+ dbi->version = NULL;
+ version = NULL;
+ continue;
+ } else if (strstr(s, "!V") == s) {
+ DBI_CHECK(dbi);
+ v = atoi(&s[2]);
+ if (v >= dbi->rcount || v < 0) {
+ printf("unknown open version %d\n", v);
+ continue;
+ }
+ if (dbi->rversions[v] == NULL) {
+ printf("version %d is not open\n", v);
+ continue;
+ }
+ printf("switching to open version %d\n", v);
+ dbi->version = dbi->rversions[v];
+ version = dbi->version;
+ continue;
+ } else if (strstr(s, "!TR") == s) {
+ trust = (unsigned int)atoi(&s[3]);
+ printf("trust level is now %u\n", (unsigned int)trust);
+ continue;
+ } 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;
+ } 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;
+ } else if (strcmp(s, "!WC") == 0) {
+ if ((options & DNS_DBFIND_NOWILD) != 0)
+ options &= ~DNS_DBFIND_NOWILD;
+ else
+ options |= DNS_DBFIND_NOWILD;
+ printf("wildcard matching = %s\n",
+ ((options & DNS_DBFIND_NOWILD) == 0) ?
+ "TRUE" : "FALSE");
+ continue;
+ } else if (strstr(s, "!LS ") == s) {
+ DBI_CHECK(dbi);
+ list(dbi, &s[4]);
+ continue;
+ } else if (strcmp(s, "!LS") == 0) {
+ DBI_CHECK(dbi);
+ list(dbi, NULL);
+ continue;
+ } else if (strstr(s, "!DU ") == s) {
+ DBI_CHECK(dbi);
+ result = dns_db_dump(dbi->db, dbi->version, s+4);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n");
+ print_result("", result);
+ }
+ continue;
+ } else if (strcmp(s, "!PN") == 0) {
+ if (printnode)
+ printnode = false;
+ else
+ printnode = true;
+ printf("printnode = %s\n",
+ printnode ? "TRUE" : "FALSE");
+ continue;
+ } else if (strstr(s, "!P") == s) {
+ DBI_CHECK(dbi);
+ v = atoi(&s[2]);
+ dbi->pause_every = v;
+ continue;
+ } else if (strcmp(s, "!+") == 0) {
+ DBI_CHECK(dbi);
+ dbi->ascending = true;
+ continue;
+ } else if (strcmp(s, "!-") == 0) {
+ DBI_CHECK(dbi);
+ dbi->ascending = false;
+ continue;
+ } 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 = false;
+ delmode = false;
+ holdmode = false;
+ } else {
+ db = NULL;
+ version = NULL;
+ origin = dns_rootname;
+ printf("database not found; "
+ "now searching all databases\n");
+ }
+ continue;
+ } else if (strcmp(s, "!ZC") == 0) {
+ if (find_zonecut)
+ find_zonecut = false;
+ else
+ find_zonecut = true;
+ printf("find_zonecut = %s\n",
+ find_zonecut ? "TRUE" : "FALSE");
+ continue;
+ } else if (strcmp(s, "!NZ") == 0) {
+ if (noexact_zonecut)
+ noexact_zonecut = false;
+ else
+ noexact_zonecut = true;
+ printf("noexact_zonecut = %s\n",
+ noexact_zonecut ? "TRUE" : "FALSE");
+ continue;
+ }
+
+ isc_buffer_init(&source, s, len);
+ isc_buffer_add(&source, len);
+ isc_buffer_init(&target, b, sizeof(b));
+ result = dns_name_fromtext(&name, &source, origin, 0, &target);
+ if (result != ISC_R_SUCCESS) {
+ print_result("bad name: ", result);
+ continue;
+ }
+
+ if (dbi == NULL) {
+ zcoptions = 0;
+ if (noexact_zonecut)
+ zcoptions |= DNS_DBTABLEFIND_NOEXACT;
+ db = NULL;
+ result = dns_dbtable_find(dbtable, &name, zcoptions,
+ &db);
+ if (result != ISC_R_SUCCESS &&
+ result != DNS_R_PARTIALMATCH) {
+ if (!quiet) {
+ printf("\n");
+ print_result("", result);
+ }
+ continue;
+ }
+ isc_buffer_init(&tb1, t1, sizeof(t1));
+ result = dns_name_totext(dns_db_origin(db), false,
+ &tb1);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n");
+ print_result("", result);
+ dns_db_detach(&db);
+ continue;
+ }
+ isc_buffer_usedregion(&tb1, &r1);
+ printf("\ndatabase = %.*s (%s)\n",
+ (int)r1.length, r1.base,
+ (dns_db_iszone(db)) ? "zone" : "cache");
+ }
+ node = NULL;
+ dns_rdataset_init(&rdataset);
+ dns_rdataset_init(&sigrdataset);
+
+ if (find_zonecut && dns_db_iscache(db)) {
+ zcoptions = options;
+ if (noexact_zonecut)
+ zcoptions |= DNS_DBFIND_NOEXACT;
+ result = dns_db_findzonecut(db, &name, zcoptions,
+ 0, &node, fname,
+ &rdataset, &sigrdataset);
+ } else {
+ result = dns_db_find(db, &name, version, type,
+ options, 0, &node, fname,
+ &rdataset, &sigrdataset);
+ }
+
+ if (!quiet) {
+ if (dbi != NULL)
+ printf("\n");
+ print_result("", result);
+ }
+
+ found_as = false;
+ switch (result) {
+ case ISC_R_SUCCESS:
+ case DNS_R_GLUE:
+ case DNS_R_CNAME:
+ case DNS_R_ZONECUT:
+ break;
+ case DNS_R_DNAME:
+ case DNS_R_DELEGATION:
+ found_as = true;
+ break;
+ case DNS_R_NXRRSET:
+ if (dns_rdataset_isassociated(&rdataset))
+ break;
+ 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);
+ } else {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ }
+ continue;
+ case DNS_R_NXDOMAIN:
+ if (dns_rdataset_isassociated(&rdataset))
+ break;
+ /* FALLTHROUGH */
+ default:
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ if (quiet)
+ print_result("", result);
+ continue;
+ }
+ if (found_as && !quiet) {
+ isc_buffer_init(&tb1, t1, sizeof(t1));
+ isc_buffer_init(&tb2, t2, sizeof(t2));
+ result = dns_name_totext(&name, false, &tb1);
+ if (result != ISC_R_SUCCESS) {
+ print_result("", result);
+ dns_db_detachnode(db, &node);
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ continue;
+ }
+ result = dns_name_totext(fname, false, &tb2);
+ if (result != ISC_R_SUCCESS) {
+ print_result("", result);
+ dns_db_detachnode(db, &node);
+ if (dbi == NULL)
+ dns_db_detach(&db);
+ continue;
+ }
+ isc_buffer_usedregion(&tb1, &r1);
+ isc_buffer_usedregion(&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;
+ result = dns_db_allrdatasets(db, node, version, 0,
+ &rdsiter);
+ if (result == ISC_R_SUCCESS) {
+ if (!quiet)
+ print_rdatasets(fname, rdsiter);
+ dns_rdatasetiter_destroy(&rdsiter);
+ } else
+ print_result("", result);
+ } else {
+ if (!quiet)
+ print_rdataset(fname, &rdataset);
+ if (dns_rdataset_isassociated(&sigrdataset)) {
+ if (!quiet)
+ print_rdataset(fname, &sigrdataset);
+ dns_rdataset_disassociate(&sigrdataset);
+ }
+ if (dbi != NULL && addmode && !found_as) {
+ rdataset.ttl++;
+ rdataset.trust = trust;
+ if (dns_db_iszone(db))
+ addopts = DNS_DBADD_MERGE;
+ else
+ addopts = 0;
+ result = dns_db_addrdataset(db, node, version,
+ 0, &rdataset,
+ addopts, NULL);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+ } else if (dbi != NULL && delmode && !found_as) {
+ result = dns_db_deleterdataset(db, node,
+ version, type,
+ 0);
+ if (result != ISC_R_SUCCESS)
+ print_result("", result);
+ if (printnode)
+ dns_db_printnode(db, node, stdout);
+ }
+ dns_rdataset_disassociate(&rdataset);
+ }
+
+ 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);
+ } else {
+ dns_db_detachnode(db, &node);
+ dns_db_detach(&db);
+ }
+ }
+
+ if (time_lookups) {
+ uint64_t usec;
+
+ TIME_NOW(&finish);
+
+ usec = isc_time_microdiff(&finish, &start);
+
+ printf("elapsed time: %lu.%06lu seconds\n",
+ (unsigned long)(usec / 1000000),
+ (unsigned long)(usec % 1000000));
+ }
+
+ unload_all();
+
+ dns_dbtable_detach(&dbtable);
+
+ if (lctx != NULL)
+ isc_log_destroy(&lctx);
+
+ if (!quiet)
+ isc_mem_stats(mctx, stdout);
+
+ return (0);
+}