summaryrefslogtreecommitdiffstats
path: root/bin/tools
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 07:24:22 +0000
commit45d6379135504814ab723b57f0eb8be23393a51d (patch)
treed4f2ec4acca824a8446387a758b0ce4238a4dffa /bin/tools
parentInitial commit. (diff)
downloadbind9-45d6379135504814ab723b57f0eb8be23393a51d.tar.xz
bind9-45d6379135504814ab723b57f0eb8be23393a51d.zip
Adding upstream version 1:9.16.44.upstream/1%9.16.44upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--bin/tools/Makefile.in136
-rw-r--r--bin/tools/arpaname.c48
-rw-r--r--bin/tools/arpaname.rst33
-rw-r--r--bin/tools/dnstap-read.c429
-rw-r--r--bin/tools/dnstap-read.rst52
-rw-r--r--bin/tools/mdig.c2285
-rw-r--r--bin/tools/mdig.rst322
-rw-r--r--bin/tools/named-journalprint.c134
-rw-r--r--bin/tools/named-journalprint.rst64
-rw-r--r--bin/tools/named-nzd2nzf.c103
-rw-r--r--bin/tools/named-nzd2nzf.rst42
-rw-r--r--bin/tools/named-rrchecker.c335
-rw-r--r--bin/tools/named-rrchecker.rst55
-rw-r--r--bin/tools/nsec3hash.c193
-rw-r--r--bin/tools/nsec3hash.rst63
-rw-r--r--bin/tools/win32/arpaname.vcxproj.filters.in22
-rw-r--r--bin/tools/win32/arpaname.vcxproj.in119
-rw-r--r--bin/tools/win32/arpaname.vcxproj.user3
-rw-r--r--bin/tools/win32/journalprint.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/journalprint.vcxproj.in121
-rw-r--r--bin/tools/win32/journalprint.vcxproj.user3
-rw-r--r--bin/tools/win32/mdig.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/mdig.vcxproj.in119
-rw-r--r--bin/tools/win32/mdig.vcxproj.user3
-rw-r--r--bin/tools/win32/nsec3hash.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/nsec3hash.vcxproj.in119
-rw-r--r--bin/tools/win32/nsec3hash.vcxproj.user3
-rw-r--r--bin/tools/win32/rrchecker.vcxproj.filters.in18
-rw-r--r--bin/tools/win32/rrchecker.vcxproj.in121
-rw-r--r--bin/tools/win32/rrchecker.vcxproj.user3
30 files changed, 5002 insertions, 0 deletions
diff --git a/bin/tools/Makefile.in b/bin/tools/Makefile.in
new file mode 100644
index 0000000..8c22340
--- /dev/null
+++ b/bin/tools/Makefile.in
@@ -0,0 +1,136 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# SPDX-License-Identifier: MPL-2.0
+#
+# 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 https://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = ${DNS_INCLUDES} ${ISC_INCLUDES} ${ISCCFG_INCLUDES} \
+ ${BIND9_INCLUDES} \
+ ${LMDB_CFLAGS} ${OPENSSL_CFLAGS} \
+ ${PROTOBUF_C_CFLAGS} \
+ ${MAXMINDDB_CFLAGS} \
+ ${LMDB_CFLAGS}
+
+CDEFINES = -DVERSION=\"${VERSION}\"
+CWARNINGS =
+
+DNSLIBS = ../../lib/dns/libdns.@A@ @NO_LIBTOOL_DNSLIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@ @NO_LIBTOOL_ISCLIBS@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@ @NO_LIBTOOL_ISCLIBS@
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+
+LIBS = ${ISCLIBS} @LIBS@
+NOSYMLIBS = ${ISCNOSYMLIBS} @LIBS@
+
+SUBDIRS =
+
+DNSTAPTARGETS = dnstap-read@EXEEXT@
+NZDTARGETS = named-nzd2nzf@EXEEXT@
+TARGETS = arpaname@EXEEXT@ named-journalprint@EXEEXT@ \
+ named-rrchecker@EXEEXT@ nsec3hash@EXEEXT@ \
+ mdig@EXEEXT@ \
+ @DNSTAPTARGETS@ @NZDTARGETS@
+
+DNSTAPSRCS = dnstap-read.c
+NZDSRCS = named-nzd2nzf.c
+SRCS = arpaname.c named-journalprint.c named-rrchecker.c \
+ nsec3hash.c mdig.c \
+ @DNSTAPSRCS@ @NZDSRCS@
+
+@BIND9_MAKE_RULES@
+
+arpaname@EXEEXT@: arpaname.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} \
+ -o $@ arpaname.@O@ ${ISCLIBS} ${LIBS}
+
+named-journalprint@EXEEXT@: named-journalprint.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="named-journalprint.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+named-rrchecker@EXEEXT@: named-rrchecker.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="named-rrchecker.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+nsec3hash@EXEEXT@: nsec3hash.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="nsec3hash.@O@"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+mdig@EXEEXT@: mdig.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCCFGDEPLIBS}
+ export BASEOBJS="mdig.@O@"; \
+ export LIBS0="${BIND9LIBS} ${ISCCFGLIBS} ${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+dnstap-read@EXEEXT@: dnstap-read.@O@ ${ISCDEPLIBS} ${DNSDEPLIBS}
+ export BASEOBJS="dnstap-read.@O@"; \
+ export LIBS0="${DNSLIBS} ${PROTOBUF_C_LIBS}"; \
+ ${FINALBUILDCMD}
+
+named-nzd2nzf@EXEEXT@: named-nzd2nzf.@O@ ${ISCDEPLIBS}
+ export BASEOBJS="named-nzd2nzf.@O@"; \
+ export LIBS0="${LMDB_LIBS}"; \
+ ${FINALBUILDCMD}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${sbindir}
+
+nzd:
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-nzd2nzf@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+
+dnstap:
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} dnstap-read@EXEEXT@ \
+ ${DESTDIR}${bindir}
+
+install:: ${TARGETS} installdirs @DNSTAP@ @NZD_TOOLS@
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} arpaname@EXEEXT@ \
+ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-journalprint@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} named-rrchecker@EXEEXT@ \
+ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} nsec3hash@EXEEXT@ \
+ ${DESTDIR}${sbindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} mdig@EXEEXT@ \
+ ${DESTDIR}${bindir}
+
+uninstall::
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/mdig@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/nsec3hash@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/named-rrchecker@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/named-journalprint@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/arpaname@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${bindir}/dnstap-read@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f \
+ ${DESTDIR}${sbindir}/named-nzd2nzf@EXEEXT@
+
+clean distclean::
+ rm -f ${TARGETS}
diff --git a/bin/tools/arpaname.c b/bin/tools/arpaname.c
new file mode 100644
index 0000000..cfbe187
--- /dev/null
+++ b/bin/tools/arpaname.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdio.h>
+
+#include <isc/net.h>
+#include <isc/print.h>
+
+#define UNUSED(x) (void)(x)
+
+int
+main(int argc, char *argv[]) {
+ unsigned char buf[16];
+ int i;
+
+ UNUSED(argc);
+
+ while (argv[1]) {
+ if (inet_pton(AF_INET6, argv[1], buf) == 1) {
+ for (i = 15; i >= 0; i--) {
+ fprintf(stdout, "%X.%X.", buf[i] & 0xf,
+ (buf[i] >> 4) & 0xf);
+ }
+ fprintf(stdout, "IP6.ARPA\n");
+ argv++;
+ continue;
+ }
+ if (inet_pton(AF_INET, argv[1], buf) == 1) {
+ fprintf(stdout, "%u.%u.%u.%u.IN-ADDR.ARPA\n", buf[3],
+ buf[2], buf[1], buf[0]);
+ argv++;
+ continue;
+ }
+ return (1);
+ }
+ fflush(stdout);
+ return (ferror(stdout));
+}
diff --git a/bin/tools/arpaname.rst b/bin/tools/arpaname.rst
new file mode 100644
index 0000000..c932f6e
--- /dev/null
+++ b/bin/tools/arpaname.rst
@@ -0,0 +1,33 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. 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 https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. _man_arpaname:
+
+arpaname - translate IP addresses to the corresponding ARPA names
+-----------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`arpaname` {*ipaddress* ...}
+
+Description
+~~~~~~~~~~~
+
+``arpaname`` translates IP addresses (IPv4 and IPv6) to the
+corresponding IN-ADDR.ARPA or IP6.ARPA names.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/dnstap-read.c b/bin/tools/dnstap-read.c
new file mode 100644
index 0000000..50985d4
--- /dev/null
+++ b/bin/tools/dnstap-read.c
@@ -0,0 +1,429 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Portions of this code were adapted from dnstap-ldns:
+ *
+ * Copyright (c) 2014 by Farsight Security, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <protobuf-c/protobuf-c.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/hex.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/dnstap.h>
+#include <dns/fixedname.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/result.h>
+
+#include "lib/dns/dnstap.pb-c.h"
+
+isc_mem_t *mctx = NULL;
+bool memrecord = false;
+bool printmessage = false;
+bool hexmessage = false;
+bool yaml = false;
+
+const char *program = "dnstap-read";
+
+#define CHECKM(op, msg) \
+ do { \
+ result = (op); \
+ if (result != ISC_R_SUCCESS) { \
+ fprintf(stderr, "%s: %s: %s\n", program, msg, \
+ isc_result_totext(result)); \
+ goto cleanup; \
+ } \
+ } while (0)
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: fatal: ", program);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static void
+usage(void) {
+ fprintf(stderr, "dnstap-read [-mpxy] [filename]\n");
+ fprintf(stderr, "\t-m\ttrace memory allocations\n");
+ fprintf(stderr, "\t-p\tprint the full DNS message\n");
+ fprintf(stderr, "\t-x\tuse hex format to print DNS message\n");
+ fprintf(stderr, "\t-y\tprint YAML format (implies -p)\n");
+}
+
+static void
+print_dtdata(dns_dtdata_t *dt) {
+ isc_result_t result;
+ isc_buffer_t *b = NULL;
+
+ isc_buffer_allocate(mctx, &b, 2048);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ CHECKM(dns_dt_datatotext(dt, &b), "dns_dt_datatotext");
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+
+cleanup:
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+}
+
+static void
+print_hex(dns_dtdata_t *dt) {
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ size_t textlen;
+
+ if (dt->msg == NULL) {
+ return;
+ }
+
+ textlen = (dt->msgdata.length * 2) + 1;
+ isc_buffer_allocate(mctx, &b, textlen);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ result = isc_hex_totext(&dt->msgdata, 0, "", b);
+ CHECKM(result, "isc_hex_totext");
+
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+
+cleanup:
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+}
+
+static void
+print_packet(dns_dtdata_t *dt, const dns_master_style_t *style) {
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+
+ if (dt->msg != NULL) {
+ size_t textlen = 2048;
+
+ isc_buffer_allocate(mctx, &b, textlen);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ for (;;) {
+ isc_buffer_reserve(&b, textlen);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ result = dns_message_totext(dt->msg, style, 0, b);
+ if (result == ISC_R_NOSPACE) {
+ isc_buffer_clear(b);
+ textlen *= 2;
+ continue;
+ } else if (result == ISC_R_SUCCESS) {
+ printf("%.*s", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+ isc_buffer_free(&b);
+ } else {
+ isc_buffer_free(&b);
+ CHECKM(result, "dns_message_totext");
+ }
+ break;
+ }
+ }
+
+cleanup:
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+}
+
+static void
+print_yaml(dns_dtdata_t *dt) {
+ Dnstap__Dnstap *frame = dt->frame;
+ Dnstap__Message *m = frame->message;
+ const ProtobufCEnumValue *ftype, *mtype;
+ static bool first = true;
+
+ ftype = protobuf_c_enum_descriptor_get_value(
+ &dnstap__dnstap__type__descriptor, frame->type);
+ if (ftype == NULL) {
+ return;
+ }
+
+ if (!first) {
+ printf("---\n");
+ } else {
+ first = false;
+ }
+
+ printf("type: %s\n", ftype->name);
+
+ if (frame->has_identity) {
+ printf("identity: %.*s\n", (int)frame->identity.len,
+ frame->identity.data);
+ }
+
+ if (frame->has_version) {
+ printf("version: %.*s\n", (int)frame->version.len,
+ frame->version.data);
+ }
+
+ if (frame->type != DNSTAP__DNSTAP__TYPE__MESSAGE) {
+ return;
+ }
+
+ printf("message:\n");
+
+ mtype = protobuf_c_enum_descriptor_get_value(
+ &dnstap__message__type__descriptor, m->type);
+ if (mtype == NULL) {
+ return;
+ }
+
+ printf(" type: %s\n", mtype->name);
+
+ if (!isc_time_isepoch(&dt->qtime)) {
+ char buf[100];
+ isc_time_formatISO8601(&dt->qtime, buf, sizeof(buf));
+ printf(" query_time: !!timestamp %s\n", buf);
+ }
+
+ if (!isc_time_isepoch(&dt->rtime)) {
+ char buf[100];
+ isc_time_formatISO8601(&dt->rtime, buf, sizeof(buf));
+ printf(" response_time: !!timestamp %s\n", buf);
+ }
+
+ if (dt->msgdata.base != NULL) {
+ printf(" message_size: %zub\n", (size_t)dt->msgdata.length);
+ } else {
+ printf(" message_size: 0b\n");
+ }
+
+ if (m->has_socket_family) {
+ const ProtobufCEnumValue *type =
+ protobuf_c_enum_descriptor_get_value(
+ &dnstap__socket_family__descriptor,
+ m->socket_family);
+ if (type != NULL) {
+ printf(" socket_family: %s\n", type->name);
+ }
+ }
+
+ printf(" socket_protocol: %s\n", dt->tcp ? "TCP" : "UDP");
+
+ if (m->has_query_address) {
+ ProtobufCBinaryData *ip = &m->query_address;
+ char buf[100];
+
+ (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data,
+ buf, sizeof(buf));
+ printf(" query_address: \"%s\"\n", buf);
+ }
+
+ if (m->has_response_address) {
+ ProtobufCBinaryData *ip = &m->response_address;
+ char buf[100];
+
+ (void)inet_ntop(ip->len == 4 ? AF_INET : AF_INET6, ip->data,
+ buf, sizeof(buf));
+ printf(" response_address: \"%s\"\n", buf);
+ }
+
+ if (m->has_query_port) {
+ printf(" query_port: %u\n", m->query_port);
+ }
+
+ if (m->has_response_port) {
+ printf(" response_port: %u\n", m->response_port);
+ }
+
+ if (m->has_query_zone) {
+ isc_result_t result;
+ dns_fixedname_t fn;
+ dns_name_t *name;
+ isc_buffer_t b;
+ dns_decompress_t dctx;
+
+ name = dns_fixedname_initname(&fn);
+
+ isc_buffer_init(&b, m->query_zone.data, m->query_zone.len);
+ isc_buffer_add(&b, m->query_zone.len);
+
+ dns_decompress_init(&dctx, -1, DNS_DECOMPRESS_NONE);
+ result = dns_name_fromwire(name, &b, &dctx, 0, NULL);
+ if (result == ISC_R_SUCCESS) {
+ printf(" query_zone: ");
+ dns_name_print(name, stdout);
+ printf("\n");
+ }
+ }
+
+ if (dt->msg != NULL) {
+ dt->msg->indent.count = 2;
+ dt->msg->indent.string = " ";
+ printf(" %s:\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
+ ? "query_message_data"
+ : "response_message_data");
+
+ print_packet(dt, &dns_master_style_yaml);
+
+ printf(" %s: |\n", ((dt->type & DNS_DTTYPE_QUERY) != 0)
+ ? "query_message"
+ : "response_message");
+ print_packet(dt, &dns_master_style_indent);
+ }
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_result_t result;
+ dns_message_t *message = NULL;
+ isc_buffer_t *b = NULL;
+ dns_dtdata_t *dt = NULL;
+ dns_dthandle_t *handle = NULL;
+ int rv = 0, ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, "mpxy")) != -1) {
+ switch (ch) {
+ case 'm':
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ memrecord = true;
+ break;
+ case 'p':
+ printmessage = true;
+ break;
+ case 'x':
+ hexmessage = true;
+ break;
+ case 'y':
+ yaml = true;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc < 1) {
+ fatal("no file specified");
+ }
+
+ isc_mem_create(&mctx);
+
+ dns_result_register();
+
+ CHECKM(dns_dt_open(argv[0], dns_dtmode_file, mctx, &handle),
+ "dns_dt_openfile");
+
+ for (;;) {
+ isc_region_t input;
+ uint8_t *data;
+ size_t datalen;
+
+ result = dns_dt_getframe(handle, &data, &datalen);
+ if (result == ISC_R_NOMORE) {
+ break;
+ } else {
+ CHECKM(result, "dns_dt_getframe");
+ }
+
+ input.base = data;
+ input.length = datalen;
+
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+ isc_buffer_allocate(mctx, &b, 2048);
+ if (b == NULL) {
+ fatal("out of memory");
+ }
+
+ result = dns_dt_parse(mctx, &input, &dt);
+ if (result != ISC_R_SUCCESS) {
+ isc_buffer_free(&b);
+ continue;
+ }
+
+ if (yaml) {
+ print_yaml(dt);
+ } else if (hexmessage) {
+ print_dtdata(dt);
+ print_hex(dt);
+ } else if (printmessage) {
+ print_dtdata(dt);
+ print_packet(dt, &dns_master_style_debug);
+ } else {
+ print_dtdata(dt);
+ }
+
+ dns_dtdata_free(&dt);
+ }
+
+cleanup:
+ if (dt != NULL) {
+ dns_dtdata_free(&dt);
+ }
+ if (handle != NULL) {
+ dns_dt_close(&handle);
+ }
+ if (message != NULL) {
+ dns_message_detach(&message);
+ }
+ if (b != NULL) {
+ isc_buffer_free(&b);
+ }
+ isc_mem_destroy(&mctx);
+
+ exit(rv);
+}
diff --git a/bin/tools/dnstap-read.rst b/bin/tools/dnstap-read.rst
new file mode 100644
index 0000000..104c05f
--- /dev/null
+++ b/bin/tools/dnstap-read.rst
@@ -0,0 +1,52 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. 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 https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. _man_dnstap-read:
+
+dnstap-read - print dnstap data in human-readable form
+------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`dnstap-read` [**-m**] [**-p**] [**-x**] [**-y**] {file}
+
+Description
+~~~~~~~~~~~
+
+``dnstap-read`` reads ``dnstap`` data from a specified file and prints
+it in a human-readable format. By default, ``dnstap`` data is printed in
+a short summary format, but if the ``-y`` option is specified, a
+longer and more detailed YAML format is used.
+
+Options
+~~~~~~~
+
+``-m``
+ This option indicates trace memory allocations, and is used for debugging memory leaks.
+
+``-p``
+ This option prints the text form of the DNS
+ message that was encapsulated in the ``dnstap`` frame, after printing the ``dnstap`` data.
+
+``-x``
+ This option prints a hex dump of the wire form
+ of the DNS message that was encapsulated in the ``dnstap`` frame, after printing the ``dnstap`` data.
+
+``-y``
+ This option prints ``dnstap`` data in a detailed YAML format.
+
+See Also
+~~~~~~~~
+
+:manpage:`named(8)`, :manpage:`rndc(8)`, BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/mdig.c b/bin/tools/mdig.c
new file mode 100644
index 0000000..5da9d89
--- /dev/null
+++ b/bin/tools/mdig.c
@@ -0,0 +1,2285 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/hash.h>
+#include <isc/hex.h>
+#include <isc/log.h>
+#include <isc/managers.h>
+#include <isc/mem.h>
+#include <isc/net.h>
+#include <isc/nonce.h>
+#include <isc/parseint.h>
+#include <isc/portset.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/util.h>
+
+#include <dns/byaddr.h>
+#include <dns/dispatch.h>
+#include <dns/events.h>
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/request.h>
+#include <dns/resolver.h>
+#include <dns/result.h>
+#include <dns/types.h>
+#include <dns/view.h>
+
+#include <dst/result.h>
+
+#include <bind9/getaddresses.h>
+
+#define CHECK(str, x) \
+ { \
+ if ((x) != ISC_R_SUCCESS) { \
+ fprintf(stderr, "mdig: %s failed with %s\n", (str), \
+ isc_result_totext(x)); \
+ exit(-1); \
+ } \
+ }
+
+#define RUNCHECK(x) RUNTIME_CHECK((x) == ISC_R_SUCCESS)
+
+#define ADD_STRING(b, s) \
+ { \
+ if (strlen(s) >= isc_buffer_availablelength(b)) \
+ return ((ISC_R_NOSPACE)); \
+ else \
+ isc_buffer_putstr(b, s); \
+ }
+
+#define MXNAME (DNS_NAME_MAXTEXT + 1)
+#define COMMSIZE 0xffff
+#define OUTPUTBUF 32767
+#define MAXPORT 0xffff
+#define PORT 53
+#define MAXTIMEOUT 0xffff
+#define TCPTIMEOUT 10
+#define UDPTIMEOUT 5
+#define MAXTRIES 0xffffffff
+
+#define NS_PER_US 1000 /*%< Nanoseconds per microsecond. */
+#define US_PER_SEC 1000000 /*%< Microseconds per second. */
+#define US_PER_MS 1000 /*%< Microseconds per millisecond. */
+
+static isc_mem_t *mctx = NULL;
+static dns_requestmgr_t *requestmgr = NULL;
+static const char *batchname = NULL;
+static FILE *batchfp = NULL;
+static bool burst = false;
+static bool have_ipv4 = false;
+static bool have_ipv6 = false;
+static bool have_src = false;
+static bool tcp_mode = false;
+static bool besteffort = true;
+static bool display_short_form = false;
+static bool display_headers = true;
+static bool display_comments = true;
+static int display_rrcomments = 0;
+static bool display_ttlunits = true;
+static bool display_ttl = true;
+static bool display_class = true;
+static bool display_crypto = true;
+static bool display_multiline = false;
+static bool display_question = true;
+static bool display_answer = true;
+static bool display_authority = true;
+static bool display_additional = true;
+static bool display_unknown_format = false;
+static bool yaml = false;
+static bool continue_on_error = false;
+static uint32_t display_splitwidth = 0xffffffff;
+static isc_sockaddr_t srcaddr;
+static char *server = NULL;
+static isc_sockaddr_t dstaddr;
+static in_port_t port = 53;
+static isc_dscp_t dscp = -1;
+static unsigned char cookie_secret[33];
+static int onfly = 0;
+static char hexcookie[81];
+
+struct query {
+ char textname[MXNAME]; /*% Name we're going to be
+ * looking up */
+ bool recurse;
+ bool have_aaonly;
+ bool have_adflag;
+ bool have_cdflag;
+ bool have_zflag;
+ bool dnssec;
+ bool expire;
+ bool send_cookie;
+ char *cookie;
+ bool nsid;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ uint16_t udpsize;
+ int16_t edns;
+ dns_ednsopt_t *ednsopts;
+ unsigned int ednsoptscnt;
+ unsigned int ednsflags;
+ isc_sockaddr_t *ecs_addr;
+ unsigned int timeout;
+ unsigned int udptimeout;
+ unsigned int udpretries;
+ ISC_LINK(struct query) link;
+};
+static struct query default_query;
+static ISC_LIST(struct query) queries;
+
+#define EDNSOPTS 100U
+/*% opcode text */
+static const char *const opcodetext[] = {
+ "QUERY", "IQUERY", "STATUS", "RESERVED3",
+ "NOTIFY", "UPDATE", "RESERVED6", "RESERVED7",
+ "RESERVED8", "RESERVED9", "RESERVED10", "RESERVED11",
+ "RESERVED12", "RESERVED13", "RESERVED14", "RESERVED15"
+};
+
+/*% return code text */
+static const char *const rcodetext[] = {
+ "NOERROR", "FORMERR", "SERVFAIL", "NXDOMAIN", "NOTIMP",
+ "REFUSED", "YXDOMAIN", "YXRRSET", "NXRRSET", "NOTAUTH",
+ "NOTZONE", "RESERVED11", "RESERVED12", "RESERVED13", "RESERVED14",
+ "RESERVED15", "BADVERS"
+};
+
+/*% safe rcodetext[] */
+static char *
+rcode_totext(dns_rcode_t rcode) {
+ static char buf[sizeof("?65535")];
+ union {
+ const char *consttext;
+ char *deconsttext;
+ } totext;
+
+ if (rcode >= (sizeof(rcodetext) / sizeof(rcodetext[0]))) {
+ snprintf(buf, sizeof(buf), "?%u", rcode);
+ totext.deconsttext = buf;
+ } else {
+ totext.consttext = rcodetext[rcode];
+ }
+ return (totext.deconsttext);
+}
+
+/* receive response event handler */
+static void
+recvresponse(isc_task_t *task, isc_event_t *event) {
+ dns_requestevent_t *reqev = (dns_requestevent_t *)event;
+ isc_result_t result;
+ dns_message_t *query = NULL, *response = NULL;
+ unsigned int parseflags = 0;
+ isc_buffer_t *msgbuf = NULL, *buf = NULL;
+ unsigned int len = OUTPUTBUF;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+ dns_messagetextflag_t flags;
+
+ UNUSED(task);
+
+ REQUIRE(reqev != NULL);
+ query = reqev->ev_arg;
+
+ if (reqev->result != ISC_R_SUCCESS) {
+ fprintf(stderr, "response failed with %s\n",
+ isc_result_totext(reqev->result));
+ if (continue_on_error) {
+ goto cleanup;
+ } else {
+ exit(-1);
+ }
+ }
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &response);
+
+ parseflags |= DNS_MESSAGEPARSE_PRESERVEORDER;
+ if (besteffort) {
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
+ }
+
+ msgbuf = dns_request_getanswer(reqev->request);
+ result = dns_request_getresponse(reqev->request, response, parseflags);
+ CHECK("dns_request_getresponse", result);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (yaml) {
+ styleflags |= DNS_STYLEFLAG_YAML;
+ response->indent.string = " ";
+ response->indent.count = 3;
+ } else {
+ if (display_comments) {
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ }
+ if (display_unknown_format) {
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ }
+ if (display_rrcomments > 0) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (display_ttlunits) {
+ styleflags |= DNS_STYLEFLAG_TTL_UNITS;
+ }
+ if (!display_ttl) {
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ }
+ if (!display_class) {
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ }
+ if (!display_crypto) {
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ }
+ if (display_multiline) {
+ styleflags |= DNS_STYLEFLAG_OMIT_OWNER;
+ styleflags |= DNS_STYLEFLAG_OMIT_CLASS;
+ styleflags |= DNS_STYLEFLAG_REL_DATA;
+ styleflags |= DNS_STYLEFLAG_OMIT_TTL;
+ styleflags |= DNS_STYLEFLAG_TTL;
+ styleflags |= DNS_STYLEFLAG_MULTILINE;
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ /* Turn on rrcomments unless explicitly disabled */
+ if (display_rrcomments >= 0) {
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ }
+ }
+ if (display_multiline || (!display_ttl && !display_class)) {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 24,
+ 32, 80, 8, display_splitwidth,
+ mctx);
+ } else if (!display_ttl || !display_class) {
+ result = dns_master_stylecreate(&style, styleflags, 24, 24, 32,
+ 40, 80, 8, display_splitwidth,
+ mctx);
+ } else {
+ result = dns_master_stylecreate(&style, styleflags, 24, 32, 40,
+ 48, 80, 8, display_splitwidth,
+ mctx);
+ }
+ CHECK("dns_master_stylecreate2", result);
+
+ flags = 0;
+ if (!display_headers) {
+ flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+ if (!display_comments) {
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+
+ isc_buffer_allocate(mctx, &buf, len);
+
+ if (yaml) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ uint16_t sport;
+ char *hash;
+ int pf;
+
+ printf("-\n");
+ printf(" type: MESSAGE\n");
+ printf(" message:\n");
+
+ if (((response->flags & DNS_MESSAGEFLAG_RD) != 0) &&
+ ((response->flags & DNS_MESSAGEFLAG_RA) != 0))
+ {
+ printf(" type: RECURSIVE_RESPONSE\n");
+ } else {
+ printf(" type: AUTH_RESPONSE\n");
+ }
+
+ printf(" message_size: %ub\n",
+ isc_buffer_usedlength(msgbuf));
+
+ pf = isc_sockaddr_pf(&dstaddr);
+ if (pf == PF_INET || pf == PF_INET6) {
+ printf(" socket_family: %s\n",
+ pf == PF_INET ? "INET" : "INET6");
+
+ printf(" socket_protocol: %s\n",
+ tcp_mode ? "TCP" : "UDP");
+
+ sport = isc_sockaddr_getport(&dstaddr);
+ isc_sockaddr_format(&dstaddr, sockstr, sizeof(sockstr));
+ hash = strchr(sockstr, '#');
+ if (hash != NULL) {
+ *hash = '\0';
+ }
+ printf(" response_address: \"%s\"\n", sockstr);
+ printf(" response_port: %u\n", sport);
+ }
+
+ if (have_src) {
+ sport = isc_sockaddr_getport(&srcaddr);
+ isc_sockaddr_format(&srcaddr, sockstr, sizeof(sockstr));
+ hash = strchr(sockstr, '#');
+ if (hash != NULL) {
+ *hash = '\0';
+ }
+ printf(" query_address: \"%s\"\n", sockstr);
+ printf(" query_port: %u\n", sport);
+ }
+
+ printf(" %s:\n", "response_message_data");
+ result = dns_message_headertotext(response, style, flags, buf);
+ CHECK("dns_message_headertotext", result);
+ } else if (display_comments && !display_short_form) {
+ printf(";; Got answer:\n");
+
+ if (display_headers) {
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, "
+ "id: %u\n",
+ opcodetext[response->opcode],
+ rcode_totext(response->rcode), response->id);
+ printf(";; flags:");
+ if ((response->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf(" qr");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf(" aa");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf(" tc");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf(" rd");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf(" ra");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf(" ad");
+ }
+ if ((response->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf(" cd");
+ }
+ if ((response->flags & 0x0040U) != 0) {
+ printf("; MBZ: 0x4");
+ }
+
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ response->counts[DNS_SECTION_QUESTION],
+ response->counts[DNS_SECTION_ANSWER],
+ response->counts[DNS_SECTION_AUTHORITY],
+ response->counts[DNS_SECTION_ADDITIONAL]);
+
+ if ((response->flags & DNS_MESSAGEFLAG_RD) != 0 &&
+ (response->flags & DNS_MESSAGEFLAG_RA) == 0)
+ {
+ printf(";; WARNING: recursion requested "
+ "but not available\n");
+ }
+ }
+ }
+
+repopulate_buffer:
+
+ if (display_comments && display_headers && !display_short_form) {
+ result = dns_message_pseudosectiontotext(
+ response, DNS_PSEUDOSECTION_OPT, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ buftoosmall:
+ len += OUTPUTBUF;
+ isc_buffer_free(&buf);
+ isc_buffer_allocate(mctx, &buf, len);
+ goto repopulate_buffer;
+ }
+ CHECK("dns_message_pseudosectiontotext", result);
+ }
+
+ if (display_question && display_headers && !display_short_form) {
+ result = dns_message_sectiontotext(
+ response, DNS_SECTION_QUESTION, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ }
+
+ if (display_answer && !display_short_form) {
+ result = dns_message_sectiontotext(response, DNS_SECTION_ANSWER,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ } else if (display_answer) {
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_result_t loopresult;
+ dns_name_t empty_name;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int answerstyleflags = 0;
+
+ if (!display_crypto) {
+ answerstyleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ }
+ if (display_unknown_format) {
+ answerstyleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ }
+
+ dns_name_init(&empty_name, NULL);
+ result = dns_message_firstname(response, DNS_SECTION_ANSWER);
+ if (result != ISC_R_NOMORE) {
+ CHECK("dns_message_firstname", result);
+ }
+
+ for (;;) {
+ if (result == ISC_R_NOMORE) {
+ break;
+ }
+ CHECK("dns_message_nextname", result);
+ name = NULL;
+ dns_message_currentname(response, DNS_SECTION_ANSWER,
+ &name);
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link))
+ {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tofmttext(
+ &rdata, NULL, answerstyleflags,
+ 0, 60, " ", buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_rdata_tofmttext", result);
+ loopresult =
+ dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ if (strlen("\n") >=
+ isc_buffer_availablelength(buf))
+ {
+ goto buftoosmall;
+ }
+ isc_buffer_putstr(buf, "\n");
+ }
+ }
+ result = dns_message_nextname(response,
+ DNS_SECTION_ANSWER);
+ }
+ }
+
+ if (display_authority && !display_short_form) {
+ result = dns_message_sectiontotext(
+ response, DNS_SECTION_AUTHORITY, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ }
+
+ if (display_additional && !display_short_form) {
+ result = dns_message_sectiontotext(
+ response, DNS_SECTION_ADDITIONAL, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_sectiontotext", result);
+ }
+
+ if (display_additional && !display_short_form && display_headers) {
+ /*
+ * Only print the signature on the first record.
+ */
+ result = dns_message_pseudosectiontotext(
+ response, DNS_PSEUDOSECTION_TSIG, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_pseudosectiontotext", result);
+ result = dns_message_pseudosectiontotext(
+ response, DNS_PSEUDOSECTION_SIG0, style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+ goto buftoosmall;
+ }
+ CHECK("dns_message_pseudosectiontotext", result);
+ }
+
+ if (display_headers && display_comments && !display_short_form && !yaml)
+ {
+ printf("\n");
+ }
+
+ printf("%.*s", (int)isc_buffer_usedlength(buf),
+ (char *)isc_buffer_base(buf));
+ isc_buffer_free(&buf);
+
+cleanup:
+ fflush(stdout);
+ if (style != NULL) {
+ dns_master_styledestroy(&style, mctx);
+ }
+ if (query != NULL) {
+ dns_message_detach(&query);
+ }
+ if (response != NULL) {
+ dns_message_detach(&response);
+ }
+ dns_request_destroy(&reqev->request);
+ isc_event_free(&event);
+
+ if (--onfly == 0) {
+ isc_app_shutdown();
+ }
+ return;
+}
+
+/*%
+ * Add EDNS0 option record to a message. Currently, the only supported
+ * options are UDP buffer size, the DO bit, and EDNS options
+ * (e.g., NSID, COOKIE, client-subnet)
+ */
+static void
+add_opt(dns_message_t *msg, uint16_t udpsize, uint16_t edns, unsigned int flags,
+ dns_ednsopt_t *opts, size_t count) {
+ dns_rdataset_t *rdataset = NULL;
+ isc_result_t result;
+
+ result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
+ opts, count);
+ CHECK("dns_message_buildopt", result);
+ result = dns_message_setopt(msg, rdataset);
+ CHECK("dns_message_setopt", result);
+}
+
+static void
+compute_cookie(unsigned char *cookie, size_t len) {
+ /* XXXMPA need to fix, should be per server. */
+ INSIST(len >= 8U);
+ memmove(cookie, cookie_secret, 8);
+}
+
+static isc_result_t
+sendquery(struct query *query, isc_task_t *task) {
+ dns_request_t *request = NULL;
+ dns_message_t *message = NULL;
+ dns_name_t *qname = NULL;
+ dns_rdataset_t *qrdataset = NULL;
+ isc_result_t result;
+ dns_fixedname_t queryname;
+ isc_buffer_t buf;
+ unsigned int options;
+
+ onfly++;
+
+ dns_fixedname_init(&queryname);
+ isc_buffer_init(&buf, query->textname, strlen(query->textname));
+ isc_buffer_add(&buf, strlen(query->textname));
+ result = dns_name_fromtext(dns_fixedname_name(&queryname), &buf,
+ dns_rootname, 0, NULL);
+ CHECK("dns_name_fromtext", result);
+
+ dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &message);
+
+ message->opcode = dns_opcode_query;
+ if (query->recurse) {
+ message->flags |= DNS_MESSAGEFLAG_RD;
+ }
+ if (query->have_aaonly) {
+ message->flags |= DNS_MESSAGEFLAG_AA;
+ }
+ if (query->have_adflag) {
+ message->flags |= DNS_MESSAGEFLAG_AD;
+ }
+ if (query->have_cdflag) {
+ message->flags |= DNS_MESSAGEFLAG_CD;
+ }
+ if (query->have_zflag) {
+ message->flags |= 0x0040U;
+ }
+ message->rdclass = query->rdclass;
+ message->id = (unsigned short)(random() & 0xFFFF);
+
+ result = dns_message_gettempname(message, &qname);
+ CHECK("dns_message_gettempname", result);
+
+ result = dns_message_gettemprdataset(message, &qrdataset);
+ CHECK("dns_message_gettemprdataset", result);
+
+ dns_name_clone(dns_fixedname_name(&queryname), qname);
+ dns_rdataset_makequestion(qrdataset, query->rdclass, query->rdtype);
+ ISC_LIST_APPEND(qname->list, qrdataset, link);
+ dns_message_addname(message, qname, DNS_SECTION_QUESTION);
+
+ if (query->udpsize > 0 || query->dnssec || query->edns > -1 ||
+ query->ecs_addr != NULL)
+ {
+ dns_ednsopt_t opts[EDNSOPTS + DNS_EDNSOPTIONS];
+ unsigned int flags;
+ int i = 0;
+ char ecsbuf[20];
+ unsigned char cookie[40];
+
+ if (query->udpsize == 0) {
+ query->udpsize = 4096;
+ }
+ if (query->edns < 0) {
+ query->edns = 0;
+ }
+
+ if (query->nsid) {
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_NSID;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (query->ecs_addr != NULL) {
+ uint8_t addr[16], family;
+ uint32_t plen;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ size_t addrl;
+ isc_buffer_t b;
+
+ sa = &query->ecs_addr->type.sa;
+ plen = query->ecs_addr->length;
+
+ /* Round up prefix len to a multiple of 8 */
+ addrl = (plen + 7) / 8;
+
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_CLIENT_SUBNET;
+ opts[i].length = (uint16_t)addrl + 4;
+ CHECK("isc_buffer_allocate", result);
+ isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
+ if (sa->sa_family == AF_INET) {
+ family = 1;
+ sin = (struct sockaddr_in *)sa;
+ memmove(addr, &sin->sin_addr, 4);
+ if ((plen % 8) != 0) {
+ addr[addrl - 1] &= ~0U
+ << (8 - (plen % 8));
+ }
+ } else {
+ family = 2;
+ sin6 = (struct sockaddr_in6 *)sa;
+ memmove(addr, &sin6->sin6_addr, 16);
+ }
+
+ /* Mask off last address byte */
+ if (addrl > 0 && (plen % 8) != 0) {
+ addr[addrl - 1] &= ~0U << (8 - (plen % 8));
+ }
+
+ /* family */
+ isc_buffer_putuint16(&b, family);
+ /* source prefix-length */
+ isc_buffer_putuint8(&b, plen);
+ /* scope prefix-length */
+ isc_buffer_putuint8(&b, 0);
+ /* address */
+ if (addrl > 0) {
+ isc_buffer_putmem(&b, addr, (unsigned)addrl);
+ }
+
+ opts[i].value = (uint8_t *)ecsbuf;
+ i++;
+ }
+
+ if (query->send_cookie) {
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_COOKIE;
+ if (query->cookie != NULL) {
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, cookie, sizeof(cookie));
+ result = isc_hex_decodestring(query->cookie,
+ &b);
+ CHECK("isc_hex_decodestring", result);
+ opts[i].value = isc_buffer_base(&b);
+ opts[i].length = isc_buffer_usedlength(&b);
+ } else {
+ compute_cookie(cookie, 8);
+ opts[i].length = 8;
+ opts[i].value = cookie;
+ }
+ i++;
+ }
+
+ if (query->expire) {
+ INSIST(i < DNS_EDNSOPTIONS);
+ opts[i].code = DNS_OPT_EXPIRE;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (query->ednsoptscnt != 0) {
+ memmove(&opts[i], query->ednsopts,
+ sizeof(dns_ednsopt_t) * query->ednsoptscnt);
+ i += query->ednsoptscnt;
+ }
+
+ flags = query->ednsflags;
+ flags &= ~DNS_MESSAGEEXTFLAG_DO;
+ if (query->dnssec) {
+ flags |= DNS_MESSAGEEXTFLAG_DO;
+ }
+ add_opt(message, query->udpsize, query->edns, flags, opts, i);
+ }
+
+ options = 0;
+ if (tcp_mode) {
+ options |= DNS_REQUESTOPT_TCP | DNS_REQUESTOPT_SHARE;
+ }
+ request = NULL;
+ result = dns_request_createvia(
+ requestmgr, message, have_src ? &srcaddr : NULL, &dstaddr, dscp,
+ options, NULL, query->timeout, query->udptimeout,
+ query->udpretries, task, recvresponse, message, &request);
+ CHECK("dns_request_createvia4", result);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+sendqueries(isc_task_t *task, isc_event_t *event) {
+ struct query *query = (struct query *)event->ev_arg;
+
+ isc_event_free(&event);
+
+ while (query != NULL) {
+ struct query *next = ISC_LIST_NEXT(query, link);
+
+ sendquery(query, task);
+ query = next;
+ }
+
+ if (onfly == 0) {
+ isc_app_shutdown();
+ }
+ return;
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fputs("Usage: mdig @server {global-opt} host\n"
+ " {local-opt} [ host {local-opt} [...]]\n",
+ stderr);
+ fputs("\nUse \"mdig -h\" (or \"mdig -h | more\") "
+ "for complete list of options\n",
+ stderr);
+ exit(1);
+}
+
+/*% help */
+static void
+help(void) {
+ fputs("Usage: mdig @server {global-opt} host\n"
+ " {local-opt} [ host {local-opt} [...]]\n",
+ stdout);
+ fputs("Where:\n"
+ " anywhere opt is one of:\n"
+ " -f filename (batch mode)\n"
+ " -h (print help and exit)\n"
+ " -v (print version and exit)\n"
+ " global opt is one of:\n"
+ " -4 (use IPv4 query transport "
+ "only)\n"
+ " -6 (use IPv6 query transport "
+ "only)\n"
+ " -b address[#port] (bind to source "
+ "address/port)\n"
+ " -p port (specify port number)\n"
+ " -m (enable memory usage "
+ "debugging)\n"
+ " +[no]dscp[=###] (Set the DSCP value to ### "
+ "[0..63])\n"
+ " +[no]vc (TCP mode)\n"
+ " +[no]tcp (TCP mode, alternate "
+ "syntax)\n"
+ " +[no]besteffort (Try to parse even illegal "
+ "messages)\n"
+ " +[no]cl (Control display of class "
+ "in records)\n"
+ " +[no]comments (Control display of "
+ "comment lines)\n"
+ " +[no]rrcomments (Control display of "
+ "per-record "
+ "comments)\n"
+ " +[no]crypto (Control display of "
+ "cryptographic "
+ "fields in records)\n"
+ " +[no]question (Control display of "
+ "question)\n"
+ " +[no]answer (Control display of "
+ "answer)\n"
+ " +[no]authority (Control display of "
+ "authority)\n"
+ " +[no]additional (Control display of "
+ "additional)\n"
+ " +[no]short (Disable everything except "
+ "short\n"
+ " form of answer)\n"
+ " +[no]ttlid (Control display of ttls "
+ "in records)\n"
+ " +[no]ttlunits (Display TTLs in "
+ "human-readable units)\n"
+ " +[no]unknownformat (Print RDATA in RFC 3597 "
+ "\"unknown\" format)\n"
+ " +[no]all (Set or clear all display "
+ "flags)\n"
+ " +[no]multiline (Print records in an "
+ "expanded format)\n"
+ " +[no]split=## (Split hex/base64 fields "
+ "into chunks)\n"
+ " local opt is one of:\n"
+ " -c class (specify query class)\n"
+ " -t type (specify query type)\n"
+ " -x dot-notation (shortcut for reverse "
+ "lookups)\n"
+ " +timeout=### (Set query timeout) "
+ "[UDP=5,TCP=10]\n"
+ " +udptimeout=### (Set timeout before UDP "
+ "retry)\n"
+ " +tries=### (Set number of UDP "
+ "attempts) [3]\n"
+ " +retry=### (Set number of UDP "
+ "retries) [2]\n"
+ " +bufsize=### (Set EDNS0 Max UDP packet "
+ "size)\n"
+ " +subnet=addr (Set edns-client-subnet "
+ "option)\n"
+ " +[no]edns[=###] (Set EDNS version) [0]\n"
+ " +ednsflags=### (Set EDNS flag bits)\n"
+ " +ednsopt=###[:value] (Send specified EDNS "
+ "option)\n"
+ " +noednsopt (Clear list of +ednsopt "
+ "options)\n"
+ " +[no]recurse (Recursive mode)\n"
+ " +[no]aaonly (Set AA flag in query "
+ "(+[no]aaflag))\n"
+ " +[no]adflag (Set AD flag in query)\n"
+ " +[no]cdflag (Set CD flag in query)\n"
+ " +[no]zflag (Set Z flag in query)\n"
+ " +[no]dnssec (Request DNSSEC records)\n"
+ " +[no]expire (Request time to expire)\n"
+ " +[no]cookie[=###] (Send a COOKIE option)\n"
+ " +[no]nsid (Request Name Server ID)\n",
+ stdout);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...)
+ ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "mdig: ");
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(-2);
+}
+
+static isc_result_t
+parse_uint_helper(uint32_t *uip, const char *value, uint32_t max,
+ const char *desc, int base) {
+ uint32_t n;
+ isc_result_t result = isc_parse_uint32(&n, value, base);
+ if (result == ISC_R_SUCCESS && n > max) {
+ result = ISC_R_RANGE;
+ }
+ if (result != ISC_R_SUCCESS) {
+ printf("invalid %s '%s': %s\n", desc, value,
+ isc_result_totext(result));
+ return (result);
+ }
+ *uip = n;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+parse_uint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
+ return (parse_uint_helper(uip, value, max, desc, 10));
+}
+
+static isc_result_t
+parse_xint(uint32_t *uip, const char *value, uint32_t max, const char *desc) {
+ return (parse_uint_helper(uip, value, max, desc, 0));
+}
+
+static void
+newopts(struct query *query) {
+ size_t len = sizeof(query->ednsopts[0]) * EDNSOPTS;
+ size_t i;
+
+ query->ednsopts = isc_mem_allocate(mctx, len);
+
+ for (i = 0; i < EDNSOPTS; i++) {
+ query->ednsopts[i].code = 0;
+ query->ednsopts[i].length = 0;
+ query->ednsopts[i].value = NULL;
+ }
+}
+
+static void
+save_opt(struct query *query, char *code, char *value) {
+ uint32_t num;
+ isc_buffer_t b;
+ isc_result_t result;
+
+ if (query->ednsopts == NULL) {
+ newopts(query);
+ }
+
+ if (query->ednsoptscnt == EDNSOPTS) {
+ fatal("too many ednsopts");
+ }
+
+ result = parse_uint(&num, code, 65535, "ednsopt");
+ if (result != ISC_R_SUCCESS) {
+ fatal("bad edns code point: %s", code);
+ }
+
+ query->ednsopts[query->ednsoptscnt].code = num;
+ query->ednsopts[query->ednsoptscnt].length = 0;
+ query->ednsopts[query->ednsoptscnt].value = NULL;
+
+ if (value != NULL) {
+ char *buf;
+ buf = isc_mem_allocate(mctx, strlen(value) / 2 + 1);
+ isc_buffer_init(&b, buf, strlen(value) / 2 + 1);
+ result = isc_hex_decodestring(value, &b);
+ CHECK("isc_hex_decodestring", result);
+ query->ednsopts[query->ednsoptscnt].value = isc_buffer_base(&b);
+ query->ednsopts[query->ednsoptscnt].length =
+ isc_buffer_usedlength(&b);
+ }
+
+ query->ednsoptscnt++;
+}
+
+static isc_result_t
+parse_netprefix(isc_sockaddr_t **sap, const char *value) {
+ isc_sockaddr_t *sa = NULL;
+ struct in_addr in4;
+ struct in6_addr in6;
+ uint32_t netmask = 0xffffffff;
+ char *slash = NULL;
+ bool parsed = false;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")];
+
+ if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf)) {
+ fatal("invalid prefix '%s'\n", value);
+ }
+
+ slash = strchr(buf, '/');
+ if (slash != NULL) {
+ isc_result_t result;
+ *slash = '\0';
+ result = isc_parse_uint32(&netmask, slash + 1, 10);
+ if (result != ISC_R_SUCCESS) {
+ fatal("invalid prefix length in '%s': %s\n", value,
+ isc_result_totext(result));
+ }
+ } else if (strcmp(value, "0") == 0) {
+ netmask = 0;
+ }
+
+ sa = isc_mem_allocate(mctx, sizeof(*sa));
+ if (inet_pton(AF_INET6, buf, &in6) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin6(sa, &in6, 0);
+ if (netmask > 128) {
+ netmask = 128;
+ }
+ } else if (inet_pton(AF_INET, buf, &in4) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin(sa, &in4, 0);
+ if (netmask > 32) {
+ netmask = 32;
+ }
+ } else if (netmask != 0xffffffff) {
+ int i;
+
+ for (i = 0; i < 3 && strlen(buf) < sizeof(buf) - 2; i++) {
+ strlcat(buf, ".0", sizeof(buf));
+ if (inet_pton(AF_INET, buf, &in4) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin(sa, &in4, 0);
+ break;
+ }
+ }
+
+ if (netmask > 32) {
+ netmask = 32;
+ }
+ }
+
+ if (!parsed) {
+ fatal("invalid address '%s'", value);
+ }
+
+ sa->length = netmask;
+ *sap = sa;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * Append 'len' bytes of 'text' at '*p', failing with
+ * ISC_R_NOSPACE if that would advance p past 'end'.
+ */
+static isc_result_t
+append(const char *text, int len, char **p, char *end) {
+ if (len > end - *p) {
+ return (ISC_R_NOSPACE);
+ }
+ memmove(*p, text, len);
+ *p += len;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+reverse_octets(const char *in, char **p, char *end) {
+ const char *dot = strchr(in, '.');
+ int len;
+ if (dot != NULL) {
+ isc_result_t result;
+ result = reverse_octets(dot + 1, p, end);
+ CHECK("reverse_octets", result);
+ result = append(".", 1, p, end);
+ CHECK("append", result);
+ len = (int)(dot - in);
+ } else {
+ len = strlen(in);
+ }
+ return (append(in, len, p, end));
+}
+
+static void
+get_reverse(char *reverse, size_t len, const char *value) {
+ int r;
+ isc_result_t result;
+ isc_netaddr_t addr;
+
+ addr.family = AF_INET6;
+ r = inet_pton(AF_INET6, value, &addr.type.in6);
+ if (r > 0) {
+ /* This is a valid IPv6 address. */
+ dns_fixedname_t fname;
+ dns_name_t *name;
+ unsigned int options = 0;
+
+ name = dns_fixedname_initname(&fname);
+ result = dns_byaddr_createptrname(&addr, options, name);
+ CHECK("dns_byaddr_createptrname2", result);
+ dns_name_format(name, reverse, (unsigned int)len);
+ return;
+ } else {
+ /*
+ * Not a valid IPv6 address. Assume IPv4.
+ * Construct the in-addr.arpa name by blindly
+ * reversing octets whether or not they look like
+ * integers, so that this can be used for RFC2317
+ * names and such.
+ */
+ char *p = reverse;
+ char *end = reverse + len;
+ result = reverse_octets(value, &p, end);
+ CHECK("reverse_octets", result);
+ /* Append .in-addr.arpa. and a terminating NUL. */
+ result = append(".in-addr.arpa.", 15, &p, end);
+ CHECK("append", result);
+ return;
+ }
+}
+
+/*%
+ * We're not using isc_commandline_parse() here since the command line
+ * syntax of mdig is quite a bit different from that which can be described
+ * by that routine.
+ * XXX doc options
+ */
+
+static void
+plus_option(char *option, struct query *query, bool global) {
+ isc_result_t result;
+ char *cmd, *value, *last = NULL, *code;
+ uint32_t num;
+ bool state = true;
+ size_t n;
+
+ INSIST(option != NULL);
+
+ if ((cmd = strtok_r(option, "=", &last)) == NULL) {
+ printf(";; Invalid option %s\n", option);
+ return;
+ }
+ if (strncasecmp(cmd, "no", 2) == 0) {
+ cmd += 2;
+ state = false;
+ }
+ /* parse the rest of the string */
+ value = strtok_r(NULL, "", &last);
+
+#define FULLCHECK(A) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \
+ goto invalid_option; \
+ } while (0)
+#define FULLCHECK2(A, B) \
+ do { \
+ size_t _l = strlen(cmd); \
+ if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \
+ (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \
+ goto invalid_option; \
+ } while (0)
+#define GLOBAL() \
+ do { \
+ if (!global) \
+ goto global_option; \
+ } while (0)
+
+ switch (cmd[0]) {
+ case 'a':
+ switch (cmd[1]) {
+ case 'a': /* aaonly / aaflag */
+ FULLCHECK2("aaonly", "aaflag");
+ query->have_aaonly = state;
+ break;
+ case 'd':
+ switch (cmd[2]) {
+ case 'd': /* additional */
+ FULLCHECK("additional");
+ display_additional = state;
+ break;
+ case 'f': /* adflag */
+ case '\0': /* +ad is a synonym for +adflag */
+ FULLCHECK("adflag");
+ query->have_adflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* all */
+ FULLCHECK("all");
+ GLOBAL();
+ display_question = state;
+ display_answer = state;
+ display_authority = state;
+ display_additional = state;
+ display_comments = state;
+ display_rrcomments = state ? 1 : -1;
+ break;
+ case 'n': /* answer */
+ FULLCHECK("answer");
+ GLOBAL();
+ display_answer = state;
+ break;
+ case 'u': /* authority */
+ FULLCHECK("authority");
+ GLOBAL();
+ display_authority = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'b':
+ switch (cmd[1]) {
+ case 'e': /* besteffort */
+ FULLCHECK("besteffort");
+ GLOBAL();
+ besteffort = state;
+ break;
+ case 'u':
+ switch (cmd[2]) {
+ case 'f': /* bufsize */
+ FULLCHECK("bufsize");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&num, value, COMMSIZE,
+ "buffer size");
+ CHECK("parse_uint(buffer size)", result);
+ query->udpsize = num;
+ break;
+ case 'r': /* burst */
+ FULLCHECK("burst");
+ GLOBAL();
+ burst = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'c':
+ switch (cmd[1]) {
+ case 'd': /* cdflag */
+ switch (cmd[2]) {
+ case 'f': /* cdflag */
+ case '\0': /* +cd is a synonym for +cdflag */
+ FULLCHECK("cdflag");
+ query->have_cdflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* cl */
+ FULLCHECK("cl");
+ GLOBAL();
+ display_class = state;
+ break;
+ case 'o': /* comments */
+ switch (cmd[2]) {
+ case 'm':
+ FULLCHECK("comments");
+ GLOBAL();
+ display_comments = state;
+ break;
+ case 'n':
+ FULLCHECK("continue");
+ GLOBAL();
+ continue_on_error = state;
+ break;
+ case 'o':
+ FULLCHECK("cookie");
+ if (state && query->edns == -1) {
+ query->edns = 0;
+ }
+ query->send_cookie = state;
+ if (value != NULL) {
+ n = strlcpy(hexcookie, value,
+ sizeof(hexcookie));
+ if (n >= sizeof(hexcookie)) {
+ fatal("COOKIE data too large");
+ }
+ query->cookie = hexcookie;
+ } else {
+ query->cookie = NULL;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("crypto");
+ GLOBAL();
+ display_crypto = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'd':
+ switch (cmd[1]) {
+ case 'n': /* dnssec */
+ FULLCHECK("dnssec");
+ if (state && query->edns == -1) {
+ query->edns = 0;
+ }
+ query->dnssec = state;
+ break;
+ case 's': /* dscp */
+ FULLCHECK("dscp");
+ GLOBAL();
+ if (!state) {
+ dscp = -1;
+ break;
+ }
+ if (value == NULL) {
+ goto need_value;
+ }
+ result = parse_uint(&num, value, 0x3f, "DSCP");
+ CHECK("parse_uint(DSCP)", result);
+ dscp = num;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'e':
+ switch (cmd[1]) {
+ case 'd':
+ switch (cmd[2]) {
+ case 'n':
+ switch (cmd[3]) {
+ case 's':
+ switch (cmd[4]) {
+ case 0:
+ FULLCHECK("edns");
+ if (!state) {
+ query->edns = -1;
+ break;
+ }
+ if (value == NULL) {
+ query->edns = 0;
+ break;
+ }
+ result = parse_uint(&num, value,
+ 255,
+ "edns");
+ CHECK("parse_uint(edns)",
+ result);
+ query->edns = num;
+ break;
+ case 'f':
+ FULLCHECK("ednsflags");
+ if (!state) {
+ query->ednsflags = 0;
+ break;
+ }
+ if (value == NULL) {
+ query->ednsflags = 0;
+ break;
+ }
+ result = parse_xint(
+ &num, value, 0xffff,
+ "ednsflags");
+ CHECK("parse_xint(ednsflags)",
+ result);
+ query->ednsflags = num;
+ break;
+ case 'o':
+ FULLCHECK("ednsopt");
+ if (!state) {
+ query->ednsoptscnt = 0;
+ break;
+ }
+ code = NULL;
+ if (value != NULL) {
+ code = strtok_r(value,
+ ":",
+ &last);
+ }
+ if (code == NULL) {
+ fatal("ednsopt no "
+ "code point "
+ "specified");
+ }
+ value = strtok_r(NULL, "\0",
+ &last);
+ save_opt(query, code, value);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'x':
+ FULLCHECK("expire");
+ query->expire = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'm': /* multiline */
+ FULLCHECK("multiline");
+ GLOBAL();
+ display_multiline = state;
+ break;
+ case 'n':
+ FULLCHECK("nsid");
+ if (state && query->edns == -1) {
+ query->edns = 0;
+ }
+ query->nsid = state;
+ break;
+ case 'q':
+ FULLCHECK("question");
+ GLOBAL();
+ display_question = state;
+ break;
+ case 'r':
+ switch (cmd[1]) {
+ case 'e':
+ switch (cmd[2]) {
+ case 'c': /* recurse */
+ FULLCHECK("recurse");
+ query->recurse = state;
+ break;
+ case 't': /* retry / retries */
+ FULLCHECK2("retry", "retries");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->udpretries, value,
+ MAXTRIES - 1, "udpretries");
+ CHECK("parse_uint(udpretries)", result);
+ query->udpretries++;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("rrcomments");
+ GLOBAL();
+ display_rrcomments = state ? 1 : -1;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 's':
+ switch (cmd[1]) {
+ case 'h':
+ FULLCHECK("short");
+ GLOBAL();
+ display_short_form = state;
+ if (state) {
+ display_question = false;
+ display_answer = true;
+ display_authority = false;
+ display_additional = false;
+ display_comments = false;
+ display_rrcomments = -1;
+ }
+ break;
+ case 'p': /* split */
+ FULLCHECK("split");
+ GLOBAL();
+ if (value != NULL && !state) {
+ goto invalid_option;
+ }
+ if (!state) {
+ display_splitwidth = 0;
+ break;
+ } else if (value == NULL) {
+ break;
+ }
+
+ result = parse_uint(&display_splitwidth, value, 1023,
+ "split");
+ if ((display_splitwidth % 4) != 0) {
+ display_splitwidth =
+ ((display_splitwidth + 3) / 4) * 4;
+ fprintf(stderr,
+ ";; Warning, split must be "
+ "a multiple of 4; adjusting "
+ "to %u\n",
+ display_splitwidth);
+ }
+ /*
+ * There is an adjustment done in the
+ * totext_<rrtype>() functions which causes
+ * splitwidth to shrink. This is okay when we're
+ * using the default width but incorrect in this
+ * case, so we correct for it
+ */
+ if (display_splitwidth) {
+ display_splitwidth += 3;
+ }
+ CHECK("parse_uint(split)", result);
+ break;
+ case 'u': /* subnet */
+ FULLCHECK("subnet");
+ if (state && value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ if (query->ecs_addr != NULL) {
+ isc_mem_free(mctx, query->ecs_addr);
+ query->ecs_addr = NULL;
+ }
+ break;
+ }
+ if (query->edns == -1) {
+ query->edns = 0;
+ }
+ result = parse_netprefix(&query->ecs_addr, value);
+ CHECK("parse_netprefix", result);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ FULLCHECK("tcp");
+ GLOBAL();
+ tcp_mode = state;
+ break;
+ case 'i': /* timeout */
+ FULLCHECK("timeout");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->timeout, value, MAXTIMEOUT,
+ "timeout");
+ CHECK("parse_uint(timeout)", result);
+ if (query->timeout == 0) {
+ query->timeout = 1;
+ }
+ break;
+ case 'r':
+ FULLCHECK("tries");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->udpretries, value, MAXTRIES,
+ "udpretries");
+ CHECK("parse_uint(udpretries)", result);
+ if (query->udpretries == 0) {
+ query->udpretries = 1;
+ }
+ break;
+ case 't':
+ switch (cmd[2]) {
+ case 'l':
+ switch (cmd[3]) {
+ case 0:
+ case 'i': /* ttlid */
+ FULLCHECK2("ttl", "ttlid");
+ GLOBAL();
+ display_ttl = state;
+ break;
+ case 'u': /* ttlunits */
+ FULLCHECK("ttlunits");
+ GLOBAL();
+ display_ttl = true;
+ display_ttlunits = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'u':
+ switch (cmd[1]) {
+ case 'd':
+ FULLCHECK("udptimeout");
+ if (value == NULL) {
+ goto need_value;
+ }
+ if (!state) {
+ goto invalid_option;
+ }
+ result = parse_uint(&query->udptimeout, value,
+ MAXTIMEOUT, "udptimeout");
+ CHECK("parse_uint(udptimeout)", result);
+ break;
+ case 'n':
+ FULLCHECK("unknownformat");
+ display_unknown_format = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'v':
+ FULLCHECK("vc");
+ GLOBAL();
+ tcp_mode = state;
+ break;
+ case 'y': /* yaml */
+ FULLCHECK("yaml");
+ yaml = state;
+ if (state) {
+ display_rrcomments = state;
+ }
+ break;
+ case 'z': /* zflag */
+ FULLCHECK("zflag");
+ query->have_zflag = state;
+ break;
+ global_option:
+ fprintf(stderr, "Ignored late global option: +%s\n", option);
+ break;
+ default:
+ invalid_option:
+ need_value:
+ fprintf(stderr, "Invalid option: +%s\n", option);
+ usage();
+ }
+ return;
+}
+
+/*%
+ * #true returned if value was used
+ */
+static const char *single_dash_opts = "46himv";
+static const char *dash_opts = "46bcfhiptvx";
+static bool
+dash_option(const char *option, char *next, struct query *query, bool global,
+ bool *setname) {
+ char opt;
+ const char *value;
+ isc_result_t result;
+ bool value_from_next;
+ isc_consttextregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char textname[MXNAME];
+ struct in_addr in4;
+ struct in6_addr in6;
+ in_port_t srcport;
+ char *hash;
+ uint32_t num;
+
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ /*
+ * Since the -[46hiv] options do not take an argument,
+ * account for them (in any number and/or combination)
+ * if they appear as the first character(s) of an opt.
+ */
+ opt = option[0];
+ switch (opt) {
+ case '4':
+ GLOBAL();
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else {
+ fatal("can't find IPv4 networking");
+ UNREACHABLE();
+ return (false);
+ }
+ break;
+ case '6':
+ GLOBAL();
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ UNREACHABLE();
+ return (false);
+ }
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'i':
+ /* deprecated */
+ break;
+ case 'm':
+ /*
+ * handled by preparse_args()
+ */
+ break;
+ case 'v':
+ fputs("mDiG " VERSION "\n", stderr);
+ exit(0);
+ break;
+ }
+ if (strlen(option) > 1U) {
+ option = &option[1];
+ } else {
+ return (false);
+ }
+ }
+ opt = option[0];
+ if (strlen(option) > 1U) {
+ value_from_next = false;
+ value = &option[1];
+ } else {
+ value_from_next = true;
+ value = next;
+ }
+ if (value == NULL) {
+ goto invalid_option;
+ }
+ switch (opt) {
+ case 'b':
+ GLOBAL();
+ hash = strchr(value, '#');
+ if (hash != NULL) {
+ result = parse_uint(&num, hash + 1, MAXPORT,
+ "port number");
+ CHECK("parse_uint(srcport)", result);
+ srcport = num;
+ *hash = '\0';
+ } else {
+ srcport = 0;
+ }
+ if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) {
+ isc_sockaddr_fromin6(&srcaddr, &in6, srcport);
+ isc_net_disableipv4();
+ } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
+ isc_sockaddr_fromin(&srcaddr, &in4, srcport);
+ isc_net_disableipv6();
+ } else {
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ fatal("invalid address %s", value);
+ }
+ if (hash != NULL) {
+ *hash = '#';
+ }
+ have_src = true;
+ return (value_from_next);
+ case 'c':
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ CHECK("dns_rdataclass_fromtext", result);
+ query->rdclass = rdclass;
+ return (value_from_next);
+ case 'f':
+ batchname = value;
+ return (value_from_next);
+ case 'p':
+ GLOBAL();
+ result = parse_uint(&num, value, MAXPORT, "port number");
+ CHECK("parse_uint(port)", result);
+ port = num;
+ return (value_from_next);
+ case 't':
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ CHECK("dns_rdatatype_fromtext", result);
+ query->rdtype = rdtype;
+ return (value_from_next);
+ case 'x':
+ get_reverse(textname, sizeof(textname), value);
+ strlcpy(query->textname, textname, sizeof(query->textname));
+ query->rdtype = dns_rdatatype_ptr;
+ query->rdclass = dns_rdataclass_in;
+ *setname = true;
+ return (value_from_next);
+ global_option:
+ fprintf(stderr, "Ignored late global option: -%s\n", option);
+ usage();
+ default:
+ invalid_option:
+ fprintf(stderr, "Invalid option: -%s\n", option);
+ usage();
+ }
+ UNREACHABLE();
+ return (false);
+}
+
+static struct query *
+clone_default_query() {
+ struct query *query;
+
+ query = isc_mem_allocate(mctx, sizeof(struct query));
+ memmove(query, &default_query, sizeof(struct query));
+ if (default_query.ecs_addr != NULL) {
+ size_t len = sizeof(isc_sockaddr_t);
+
+ query->ecs_addr = isc_mem_allocate(mctx, len);
+ memmove(query->ecs_addr, default_query.ecs_addr, len);
+ }
+
+ if (query->timeout == 0) {
+ query->timeout = tcp_mode ? TCPTIMEOUT : UDPTIMEOUT;
+ }
+
+ return (query);
+}
+
+/*%
+ * Because we may be trying to do memory allocation recording, we're going
+ * to need to parse the arguments for the -m *before* we start the main
+ * argument parsing routine.
+ *
+ * I'd prefer not to have to do this, but I am not quite sure how else to
+ * fix the problem. Argument parsing in mdig involves memory allocation
+ * by its nature, so it can't be done in the main argument parser.
+ */
+static void
+preparse_args(int argc, char **argv) {
+ int rc;
+ char **rv;
+ char *option;
+ bool ipv4only = false, ipv6only = false;
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ if (rv[0][0] != '-') {
+ continue;
+ }
+ option = &rv[0][1];
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ switch (option[0]) {
+ case 'm':
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ break;
+ case '4':
+ if (ipv6only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv4only = true;
+ break;
+ case '6':
+ if (ipv4only) {
+ fatal("only one of -4 and -6 allowed");
+ }
+ ipv6only = true;
+ break;
+ }
+ option = &option[1];
+ }
+ if (strlen(option) == 0U) {
+ continue;
+ }
+ /* Look for dash value option. */
+ if (strpbrk(option, dash_opts) != &option[0] ||
+ strlen(option) > 1U)
+ {
+ /* Error or value in option. */
+ continue;
+ }
+ /* Dash value is next argument so we need to skip it. */
+ rc--, rv++;
+ /* Handle missing argument */
+ if (rc == 0) {
+ break;
+ }
+ }
+}
+
+static void
+parse_args(bool is_batchfile, int argc, char **argv) {
+ struct query *query = NULL;
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[64];
+ int rc;
+ char **rv;
+ bool global = true;
+ char *last;
+
+ /*
+ * The semantics for parsing the args is a bit complex; if
+ * we don't have a host yet, make the arg apply globally,
+ * otherwise make it apply to the latest host. This is
+ * a bit different than the previous versions, but should
+ * form a consistent user interface.
+ *
+ * First, create a "default query" which won't actually be used
+ * anywhere, except for cloning into new queries
+ */
+
+ if (!is_batchfile) {
+ default_query.textname[0] = 0;
+ default_query.recurse = true;
+ default_query.have_aaonly = false;
+ default_query.have_adflag = true; /*XXX*/
+ default_query.have_cdflag = false;
+ default_query.have_zflag = false;
+ default_query.dnssec = false;
+ default_query.expire = false;
+ default_query.send_cookie = false;
+ default_query.cookie = NULL;
+ default_query.nsid = false;
+ default_query.rdtype = dns_rdatatype_a;
+ default_query.rdclass = dns_rdataclass_in;
+ default_query.udpsize = 0;
+ default_query.edns = 0; /*XXX*/
+ default_query.ednsopts = NULL;
+ default_query.ednsoptscnt = 0;
+ default_query.ednsflags = 0;
+ default_query.ecs_addr = NULL;
+ default_query.timeout = 0;
+ default_query.udptimeout = 0;
+ default_query.udpretries = 3;
+ ISC_LINK_INIT(&default_query, link);
+ }
+
+ if (is_batchfile) {
+ /* Processing '-f batchfile'. */
+ query = clone_default_query();
+ global = false;
+ } else {
+ query = &default_query;
+ }
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ if (strncmp(rv[0], "%", 1) == 0) {
+ break;
+ }
+ if (rv[0][0] == '@') {
+ if (server != NULL) {
+ fatal("server already set to @%s", server);
+ }
+ server = &rv[0][1];
+ } else if (rv[0][0] == '+') {
+ plus_option(&rv[0][1], query, global);
+ } else if (rv[0][0] == '-') {
+ bool setname = false;
+
+ if (rc <= 1) {
+ if (dash_option(&rv[0][1], NULL, query, global,
+ &setname))
+ {
+ rc--;
+ rv++;
+ }
+ } else {
+ if (dash_option(&rv[0][1], rv[1], query, global,
+ &setname))
+ {
+ rc--;
+ rv++;
+ }
+ }
+ if (setname) {
+ if (query == &default_query) {
+ query = clone_default_query();
+ }
+ ISC_LIST_APPEND(queries, query, link);
+
+ default_query.textname[0] = 0;
+ query = clone_default_query();
+ global = false;
+ }
+ } else {
+ /*
+ * Anything which isn't an option
+ */
+ if (query == &default_query) {
+ query = clone_default_query();
+ }
+ strlcpy(query->textname, rv[0],
+ sizeof(query->textname));
+ ISC_LIST_APPEND(queries, query, link);
+
+ query = clone_default_query();
+ global = false;
+ /* XXX Error message */
+ }
+ }
+
+ /*
+ * If we have a batchfile, read the query list from it.
+ */
+ if ((batchname != NULL) && !is_batchfile) {
+ if (strcmp(batchname, "-") == 0) {
+ batchfp = stdin;
+ } else {
+ batchfp = fopen(batchname, "r");
+ }
+ if (batchfp == NULL) {
+ perror(batchname);
+ fatal("couldn't open batch file '%s'", batchname);
+ }
+ while (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ if (batchline[0] == '\r' || batchline[0] == '\n' ||
+ batchline[0] == '#' || batchline[0] == ';')
+ {
+ continue;
+ }
+ for (bargc = 1, bargv[bargc] = strtok_r(
+ batchline, " \t\r\n", &last);
+ (bargc < 14) && bargv[bargc]; bargc++,
+ bargv[bargc] = strtok_r(NULL, " \t\r\n", &last))
+ {
+ /* empty body */
+ }
+
+ bargv[0] = argv[0];
+ parse_args(true, bargc, (char **)bargv);
+ }
+ if (batchfp != stdin) {
+ fclose(batchfp);
+ }
+ }
+ if (query != &default_query) {
+ if (query->ecs_addr != NULL) {
+ isc_mem_free(mctx, query->ecs_addr);
+ }
+ isc_mem_free(mctx, query);
+ }
+}
+
+/*
+ * Try honoring the operating system's preferred ephemeral port range.
+ */
+static void
+set_source_ports(dns_dispatchmgr_t *manager) {
+ isc_portset_t *v4portset = NULL, *v6portset = NULL;
+ in_port_t udpport_low, udpport_high;
+ isc_result_t result;
+
+ result = isc_portset_create(mctx, &v4portset);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_portset_create (v4) failed");
+ }
+
+ result = isc_net_getudpportrange(AF_INET, &udpport_low, &udpport_high);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_net_getudpportrange (v4) failed");
+ }
+
+ isc_portset_addrange(v4portset, udpport_low, udpport_high);
+
+ result = isc_portset_create(mctx, &v6portset);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_portset_create (v6) failed");
+ }
+ result = isc_net_getudpportrange(AF_INET6, &udpport_low, &udpport_high);
+ if (result != ISC_R_SUCCESS) {
+ fatal("isc_net_getudpportrange (v6) failed");
+ }
+
+ isc_portset_addrange(v6portset, udpport_low, udpport_high);
+
+ result = dns_dispatchmgr_setavailports(manager, v4portset, v6portset);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_dispatchmgr_setavailports failed");
+ }
+
+ isc_portset_destroy(mctx, &v4portset);
+ isc_portset_destroy(mctx, &v6portset);
+}
+
+/*% Main processing routine for mdig */
+int
+main(int argc, char *argv[]) {
+ struct query *query = NULL;
+ isc_result_t result;
+ isc_sockaddr_t bind_any;
+ isc_log_t *lctx = NULL;
+ isc_logconfig_t *lcfg = NULL;
+ isc_nm_t *netmgr = NULL;
+ isc_taskmgr_t *taskmgr = NULL;
+ isc_task_t *task = NULL;
+ isc_timermgr_t *timermgr = NULL;
+ isc_socketmgr_t *socketmgr = NULL;
+ dns_dispatchmgr_t *dispatchmgr = NULL;
+ unsigned int attrs, attrmask;
+ dns_dispatch_t *dispatchvx = NULL;
+ dns_view_t *view = NULL;
+ int ns;
+ unsigned int i;
+
+ RUNCHECK(isc_app_start());
+
+ dns_result_register();
+
+ if (isc_net_probeipv4() == ISC_R_SUCCESS) {
+ have_ipv4 = true;
+ }
+ if (isc_net_probeipv6() == ISC_R_SUCCESS) {
+ have_ipv6 = true;
+ }
+ if (!have_ipv4 && !have_ipv6) {
+ fatal("could not find either IPv4 or IPv6");
+ }
+
+ preparse_args(argc, argv);
+
+ isc_mem_create(&mctx);
+
+ isc_log_create(mctx, &lctx, &lcfg);
+
+ RUNCHECK(dst_lib_init(mctx, NULL));
+ isc_nonce_buf(cookie_secret, sizeof(cookie_secret));
+
+ ISC_LIST_INIT(queries);
+ parse_args(false, argc, argv);
+ if (server == NULL) {
+ fatal("a server '@xxx' is required");
+ }
+
+ ns = 0;
+ result = bind9_getaddresses(server, port, &dstaddr, 1, &ns);
+ if (result != ISC_R_SUCCESS) {
+ fatal("couldn't get address for '%s': %s", server,
+ isc_result_totext(result));
+ }
+
+ if (isc_sockaddr_pf(&dstaddr) == PF_INET && have_ipv6) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else if (isc_sockaddr_pf(&dstaddr) == PF_INET6 && have_ipv4) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ }
+ if (have_ipv4 && have_ipv6) {
+ fatal("can't choose between IPv4 and IPv6");
+ }
+
+ RUNCHECK(isc_managers_create(mctx, 1, 0, &netmgr, &taskmgr));
+ RUNCHECK(isc_task_create(taskmgr, 0, &task));
+ RUNCHECK(isc_timermgr_create(mctx, &timermgr));
+ RUNCHECK(isc_socketmgr_create(mctx, &socketmgr));
+ RUNCHECK(dns_dispatchmgr_create(mctx, &dispatchmgr));
+
+ set_source_ports(dispatchmgr);
+
+ attrs = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_MAKEQUERY;
+
+ if (have_ipv4) {
+ isc_sockaddr_any(&bind_any);
+ attrs |= DNS_DISPATCHATTR_IPV4;
+ } else {
+ isc_sockaddr_any6(&bind_any);
+ attrs |= DNS_DISPATCHATTR_IPV6;
+ }
+ attrmask = DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP |
+ DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;
+ RUNCHECK(dns_dispatch_getudp(dispatchmgr, socketmgr, taskmgr,
+ have_src ? &srcaddr : &bind_any, 4096, 100,
+ 100, 17, 19, attrs, attrmask,
+ &dispatchvx));
+ RUNCHECK(dns_requestmgr_create(
+ mctx, timermgr, socketmgr, taskmgr, dispatchmgr,
+ have_ipv4 ? dispatchvx : NULL, have_ipv6 ? dispatchvx : NULL,
+ &requestmgr));
+
+ RUNCHECK(dns_view_create(mctx, 0, "_test", &view));
+
+ query = ISC_LIST_HEAD(queries);
+ RUNCHECK(isc_app_onrun(mctx, task, sendqueries, query));
+
+ /*
+ * Stall to the start of a new second.
+ */
+ if (burst) {
+ isc_time_t start, now;
+ RUNCHECK(isc_time_now(&start));
+ /*
+ * Sleep to 1ms of the end of the second then run a busy loop
+ * until the second changes.
+ */
+ do {
+ RUNCHECK(isc_time_now(&now));
+ if (isc_time_seconds(&start) == isc_time_seconds(&now))
+ {
+ int us = US_PER_SEC -
+ (isc_time_nanoseconds(&now) /
+ NS_PER_US);
+ if (us > US_PER_MS) {
+ usleep(us - US_PER_MS);
+ }
+ } else {
+ break;
+ }
+ } while (1);
+ }
+
+ (void)isc_app_run();
+
+ dns_view_detach(&view);
+
+ dns_requestmgr_shutdown(requestmgr);
+ dns_requestmgr_detach(&requestmgr);
+
+ dns_dispatch_detach(&dispatchvx);
+ dns_dispatchmgr_destroy(&dispatchmgr);
+
+ isc_socketmgr_destroy(&socketmgr);
+ isc_timermgr_destroy(&timermgr);
+
+ isc_task_shutdown(task);
+ isc_task_detach(&task);
+ isc_managers_destroy(&netmgr, &taskmgr);
+
+ dst_lib_destroy();
+
+ isc_log_destroy(&lctx);
+
+ query = ISC_LIST_HEAD(queries);
+ while (query != NULL) {
+ struct query *next = ISC_LIST_NEXT(query, link);
+
+ if (query->ednsopts != NULL) {
+ for (i = 0; i < EDNSOPTS; i++) {
+ if (query->ednsopts[i].value != NULL) {
+ isc_mem_free(mctx,
+ query->ednsopts[i].value);
+ }
+ }
+ isc_mem_free(mctx, query->ednsopts);
+ }
+ if (query->ecs_addr != NULL) {
+ isc_mem_free(mctx, query->ecs_addr);
+ query->ecs_addr = NULL;
+ }
+ isc_mem_free(mctx, query);
+ query = next;
+ }
+
+ if (default_query.ecs_addr != NULL) {
+ isc_mem_free(mctx, default_query.ecs_addr);
+ }
+
+ isc_mem_destroy(&mctx);
+
+ isc_app_finish();
+
+ return (0);
+}
diff --git a/bin/tools/mdig.rst b/bin/tools/mdig.rst
new file mode 100644
index 0000000..50aa588
--- /dev/null
+++ b/bin/tools/mdig.rst
@@ -0,0 +1,322 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. 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 https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. _man_mdig:
+
+mdig - DNS pipelined lookup utility
+-----------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`mdig` {@server} [**-f** filename] [**-h**] [**-v**] [ [**-4**] | [**-6**] ] [**-m**] [**-b** address] [**-p** port#] [**-c** class] [**-t** type] [**-i**] [**-x** addr] [plusopt...]
+
+:program:`mdig` {**-h**}
+
+:program:`mdig` [@server] {global-opt...} { {local-opt...} {query} ...}
+
+Description
+~~~~~~~~~~~
+
+``mdig`` is a multiple/pipelined query version of ``dig``: instead of
+waiting for a response after sending each query, it begins by sending
+all queries. Responses are displayed in the order in which they are
+received, not in the order the corresponding queries were sent.
+
+``mdig`` options are a subset of the ``dig`` options, and are divided
+into "anywhere options," which can occur anywhere, "global options," which
+must occur before the query name (or they are ignored with a warning),
+and "local options," which apply to the next query on the command line.
+
+The ``@server`` option is a mandatory global option. It is the name or IP
+address of the name server to query. (Unlike ``dig``, this value is not
+retrieved from ``/etc/resolv.conf``.) It can be an IPv4 address in
+dotted-decimal notation, an IPv6 address in colon-delimited notation, or
+a hostname. When the supplied ``server`` argument is a hostname,
+``mdig`` resolves that name before querying the name server.
+
+``mdig`` provides a number of query options which affect the way in
+which lookups are made and the results displayed. Some of these set or
+reset flag bits in the query header, some determine which sections of
+the answer get printed, and others determine the timeout and retry
+strategies.
+
+Each query option is identified by a keyword preceded by a plus sign
+(``+``). Some keywords set or reset an option. These may be preceded by
+the string ``no`` to negate the meaning of that keyword. Other keywords
+assign values to options like the timeout interval. They have the form
+``+keyword=value``.
+
+Anywhere Options
+~~~~~~~~~~~~~~~~
+
+``-f``
+ This option makes ``mdig`` operate in batch mode by reading a list
+ of lookup requests to process from the file ``filename``. The file
+ contains a number of queries, one per line. Each entry in the file
+ should be organized in the same way they would be presented as queries
+ to ``mdig`` using the command-line interface.
+
+``-h``
+ This option causes ``mdig`` to print detailed help information, with the full list
+ of options, and exit.
+
+``-v``
+ This option causes ``mdig`` to print the version number and exit.
+
+Global Options
+~~~~~~~~~~~~~~
+
+``-4``
+ This option forces ``mdig`` to only use IPv4 query transport.
+
+``-6``
+ This option forces ``mdig`` to only use IPv6 query transport.
+
+``-b address``
+ This option sets the source IP address of the query to
+ ``address``. This must be a valid address on one of the host's network
+ interfaces or "0.0.0.0" or "::". An optional port may be specified by
+ appending "#<port>"
+
+``-m``
+ This option enables memory usage debugging.
+
+``-p port#``
+ This option is used when a non-standard port number is to be
+ queried. ``port#`` is the port number that ``mdig`` sends its
+ queries to, instead of the standard DNS port number 53. This option is
+ used to test a name server that has been configured to listen for
+ queries on a non-standard port number.
+
+The global query options are:
+
+``+[no]additional``
+ This option displays [or does not display] the additional section of a reply. The
+ default is to display it.
+
+``+[no]all``
+ This option sets or clears all display flags.
+
+``+[no]answer``
+ This option displays [or does not display] the answer section of a reply. The default
+ is to display it.
+
+``+[no]authority``
+ This option displays [or does not display] the authority section of a reply. The
+ default is to display it.
+
+``+[no]besteffort``
+ This option attempts to display [or does not display] the contents of messages which are malformed. The
+ default is to not display malformed answers.
+
+``+burst``
+ This option delays queries until the start of the next second.
+
+``+[no]cl``
+ This option displays [or does not display] the CLASS when printing the record.
+
+``+[no]comments``
+ This option toggles the display of comment lines in the output. The default is to
+ print comments.
+
+``+[no]continue``
+ This option toggles continuation on errors (e.g. timeouts).
+
+``+[no]crypto``
+ This option toggles the display of cryptographic fields in DNSSEC records. The
+ contents of these fields are unnecessary to debug most DNSSEC
+ validation failures and removing them makes it easier to see the
+ common failures. The default is to display the fields. When omitted,
+ they are replaced by the string "[omitted]"; in the DNSKEY case, the
+ key ID is displayed as the replacement, e.g., ``[ key id = value ]``.
+
+``+dscp[=value]``
+ This option sets the DSCP code point to be used when sending the query. Valid DSCP
+ code points are in the range [0...63]. By default no code point is
+ explicitly set.
+
+``+[no]multiline``
+ This option toggles printing of records, like the SOA records, in a verbose multi-line format
+ with human-readable comments. The default is to print each record on
+ a single line, to facilitate machine parsing of the ``mdig`` output.
+
+``+[no]question``
+ This option prints [or does not print] the question section of a query when an answer
+ is returned. The default is to print the question section as a
+ comment.
+
+``+[no]rrcomments``
+ This option toggles the display of per-record comments in the output (for example,
+ human-readable key information about DNSKEY records). The default is
+ not to print record comments unless multiline mode is active.
+
+``+[no]short``
+ This option provides [or does not provide] a terse answer. The default is to print the answer in a
+ verbose form.
+
+``+split=W``
+ This option splits long hex- or base64-formatted fields in resource records into
+ chunks of ``W`` characters (where ``W`` is rounded up to the nearest
+ multiple of 4). ``+nosplit`` or ``+split=0`` causes fields not to be
+ split. The default is 56 characters, or 44 characters when
+ multiline mode is active.
+
+``+[no]tcp``
+ This option uses [or does not use] TCP when querying name servers. The default behavior
+ is to use UDP.
+
+``+[no]ttlid``
+ This option displays [or does not display] the TTL when printing the record.
+
+``+[no]ttlunits``
+ This option displays [or does not display] the TTL in friendly human-readable time
+ units of "s", "m", "h", "d", and "w", representing seconds, minutes,
+ hours, days, and weeks. This implies +ttlid.
+
+``+[no]vc``
+ This option uses [or does not use] TCP when querying name servers. This alternate
+ syntax to ``+[no]tcp`` is provided for backwards compatibility. The
+ ``vc`` stands for "virtual circuit".
+
+Local Options
+~~~~~~~~~~~~~
+
+``-c class``
+ This option sets the query class to ``class``. It can be any valid
+ query class which is supported in BIND 9. The default query class is
+ "IN".
+
+``-t type``
+ This option sets the query type to ``type``. It can be any valid
+ query type which is supported in BIND 9. The default query type is "A",
+ unless the ``-x`` option is supplied to indicate a reverse lookup with
+ the "PTR" query type.
+
+``-x addr``
+ Reverse lookups - mapping addresses to names - are simplified by
+ this option. ``addr`` is an IPv4 address in dotted-decimal
+ notation, or a colon-delimited IPv6 address. ``mdig`` automatically
+ performs a lookup for a query name like ``11.12.13.10.in-addr.arpa`` and
+ sets the query type and class to PTR and IN respectively. By default,
+ IPv6 addresses are looked up using nibble format under the IP6.ARPA
+ domain.
+
+The local query options are:
+
+``+[no]aaflag``
+ This is a synonym for ``+[no]aaonly``.
+
+``+[no]aaonly``
+ This sets the ``aa`` flag in the query.
+
+``+[no]adflag``
+ This sets [or does not set] the AD (authentic data) bit in the query. This
+ requests the server to return whether all of the answer and authority
+ sections have all been validated as secure, according to the security
+ policy of the server. AD=1 indicates that all records have been
+ validated as secure and the answer is not from a OPT-OUT range. AD=0
+ indicates that some part of the answer was insecure or not validated.
+ This bit is set by default.
+
+``+bufsize=B``
+ This sets the UDP message buffer size advertised using EDNS0 to ``B``
+ bytes. The maximum and minimum sizes of this buffer are 65535 and 0
+ respectively. Values outside this range are rounded up or down
+ appropriately. Values other than zero cause a EDNS query to be
+ sent.
+
+``+[no]cdflag``
+ This sets [or does not set] the CD (checking disabled) bit in the query. This
+ requests the server to not perform DNSSEC validation of responses.
+
+``+[no]cookie=####``
+ This sends [or does not send] a COOKIE EDNS option, with an optional value. Replaying a COOKIE
+ from a previous response allows the server to identify a previous
+ client. The default is ``+nocookie``.
+
+``+[no]dnssec``
+ This requests that DNSSEC records be sent by setting the DNSSEC OK (DO) bit in
+ the OPT record in the additional section of the query.
+
+``+[no]edns[=#]``
+ This specifies [or does not specify] the EDNS version to query with. Valid values are 0 to 255.
+ Setting the EDNS version causes an EDNS query to be sent.
+ ``+noedns`` clears the remembered EDNS version. EDNS is set to 0 by
+ default.
+
+``+[no]ednsflags[=#]``
+ This sets the must-be-zero EDNS flag bits (Z bits) to the specified value.
+ Decimal, hex, and octal encodings are accepted. Setting a named flag
+ (e.g. DO) is silently ignored. By default, no Z bits are set.
+
+``+[no]ednsopt[=code[:value]]``
+ This specifies [or does not specify] an EDNS option with code point ``code`` and an optional payload
+ of ``value`` as a hexadecimal string. ``+noednsopt`` clears the EDNS
+ options to be sent.
+
+``+[no]expire``
+ This toggles sending of an EDNS Expire option.
+
+``+[no]nsid``
+ This toggles inclusion of an EDNS name server ID request when sending a query.
+
+``+[no]recurse``
+ This toggles the setting of the RD (recursion desired) bit in the query.
+ This bit is set by default, which means ``mdig`` normally sends
+ recursive queries.
+
+``+retry=T``
+ This sets the number of times to retry UDP queries to server to ``T``
+ instead of the default, 2. Unlike ``+tries``, this does not include
+ the initial query.
+
+``+[no]subnet=addr[/prefix-length]``
+ This sends [or does not send] an EDNS Client Subnet option with the specified IP
+ address or network prefix.
+
+``mdig +subnet=0.0.0.0/0``, or simply ``mdig +subnet=0``
+ This sends an EDNS client-subnet option with an empty address and a source
+ prefix-length of zero, which signals a resolver that the client's
+ address information must *not* be used when resolving this query.
+
+``+timeout=T``
+ This sets the timeout for a query to ``T`` seconds. The default timeout is
+ 5 seconds for UDP transport and 10 for TCP. An attempt to set ``T``
+ to less than 1 results in a query timeout of 1 second being
+ applied.
+
+``+tries=T``
+ This sets the number of times to try UDP queries to server to ``T``
+ instead of the default, 3. If ``T`` is less than or equal to zero,
+ the number of tries is silently rounded up to 1.
+
+``+udptimeout=T``
+ This sets the timeout between UDP query retries to ``T``.
+
+``+[no]unknownformat``
+ This prints [or does not print] all RDATA in unknown RR-type presentation format (see :rfc:`3597`).
+ The default is to print RDATA for known types in the type's
+ presentation format.
+
+``+[no]yaml``
+ This toggles printing of the responses in a detailed YAML format.
+
+``+[no]zflag``
+ This sets [or does not set] the last unassigned DNS header flag in a DNS query.
+ This flag is off by default.
+
+See Also
+~~~~~~~~
+
+:manpage:`dig(1)`, :rfc:`1035`.
diff --git a/bin/tools/named-journalprint.c b/bin/tools/named-journalprint.c
new file mode 100644
index 0000000..61df022
--- /dev/null
+++ b/bin/tools/named-journalprint.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <stdlib.h>
+
+#include <isc/commandline.h>
+#include <isc/log.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/util.h>
+
+#include <dns/journal.h>
+#include <dns/log.h>
+#include <dns/result.h>
+#include <dns/types.h>
+
+const char *progname = NULL;
+
+static void
+usage(void) {
+ fprintf(stderr, "Usage: %s [-dux] journal\n", progname);
+ exit(1);
+}
+
+/*
+ * Setup logging to use stderr.
+ */
+static isc_result_t
+setup_logging(isc_mem_t *mctx, FILE *errout, isc_log_t **logp) {
+ isc_logdestination_t destination;
+ isc_logconfig_t *logconfig = NULL;
+ isc_log_t *log = NULL;
+
+ isc_log_create(mctx, &log, &logconfig);
+ isc_log_setcontext(log);
+ dns_log_init(log);
+ dns_log_setcontext(log);
+
+ destination.file.stream = errout;
+ destination.file.name = NULL;
+ destination.file.versions = ISC_LOG_ROLLNEVER;
+ destination.file.maximum_size = 0;
+ isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC,
+ ISC_LOG_DYNAMIC, &destination, 0);
+
+ RUNTIME_CHECK(isc_log_usechannel(logconfig, "stderr", NULL, NULL) ==
+ ISC_R_SUCCESS);
+
+ *logp = log;
+ return (ISC_R_SUCCESS);
+}
+
+int
+main(int argc, char **argv) {
+ char *file;
+ isc_mem_t *mctx = NULL;
+ isc_result_t result;
+ isc_log_t *lctx = NULL;
+ uint32_t flags = 0U;
+ int ch;
+ bool compact = false;
+ bool downgrade = false;
+ bool upgrade = false;
+ unsigned int serial = 0;
+ char *endp = NULL;
+
+ progname = argv[0];
+ while ((ch = isc_commandline_parse(argc, argv, "c:dux")) != -1) {
+ switch (ch) {
+ case 'c':
+ compact = true;
+ serial = strtoul(isc_commandline_argument, &endp, 0);
+ if (endp == isc_commandline_argument || *endp != 0) {
+ fprintf(stderr, "invalid serial: %s\n",
+ isc_commandline_argument);
+ exit(1);
+ }
+ break;
+ case 'd':
+ downgrade = true;
+ break;
+ case 'u':
+ upgrade = true;
+ break;
+ case 'x':
+ flags |= DNS_JOURNAL_PRINTXHDR;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (argc != 1) {
+ usage();
+ }
+ file = argv[0];
+
+ isc_mem_create(&mctx);
+ RUNTIME_CHECK(setup_logging(mctx, stderr, &lctx) == ISC_R_SUCCESS);
+
+ if (upgrade) {
+ flags = DNS_JOURNAL_COMPACTALL;
+ result = dns_journal_compact(mctx, file, 0, flags, 0);
+ } else if (downgrade) {
+ flags = DNS_JOURNAL_COMPACTALL | DNS_JOURNAL_VERSION1;
+ result = dns_journal_compact(mctx, file, 0, flags, 0);
+ } else if (compact) {
+ flags = 0;
+ result = dns_journal_compact(mctx, file, serial, flags, 0);
+ } else {
+ result = dns_journal_print(mctx, flags, file, stdout);
+ if (result == DNS_R_NOJOURNAL) {
+ fprintf(stderr, "%s\n", dns_result_totext(result));
+ }
+ }
+ isc_log_destroy(&lctx);
+ isc_mem_detach(&mctx);
+ return (result != ISC_R_SUCCESS ? 1 : 0);
+}
diff --git a/bin/tools/named-journalprint.rst b/bin/tools/named-journalprint.rst
new file mode 100644
index 0000000..1b9b057
--- /dev/null
+++ b/bin/tools/named-journalprint.rst
@@ -0,0 +1,64 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. 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 https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. _man_named-journalprint:
+
+named-journalprint - print zone journal in human-readable form
+--------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-journalprint` [-c serial] [**-dux**] {journal}
+
+Description
+~~~~~~~~~~~
+
+``named-journalprint`` scans the contents of a zone journal file,
+printing it in a human-readable form, or, optionally, converting it
+to a different journal file format.
+
+Journal files are automatically created by ``named`` when changes are
+made to dynamic zones (e.g., by ``nsupdate``). They record each addition
+or deletion of a resource record, in binary format, allowing the changes
+to be re-applied to the zone when the server is restarted after a
+shutdown or crash. By default, the name of the journal file is formed by
+appending the extension ``.jnl`` to the name of the corresponding zone
+file.
+
+``named-journalprint`` converts the contents of a given journal file
+into a human-readable text format. Each line begins with ``add`` or ``del``,
+to indicate whether the record was added or deleted, and continues with
+the resource record in master-file format.
+
+The ``-c`` (compact) option provides a mechanism to reduce the size of
+a journal by removing (most/all) transactions prior to the specified
+serial number. Note: this option *must not* be used while ``named`` is
+running, and can cause data loss if the zone file has not been updated
+to contain the data being removed from the journal. Use with extreme caution.
+
+The ``-x`` option causes additional data about the journal file to be
+printed at the beginning of the output and before each group of changes.
+
+The ``-u`` (upgrade) and ``-d`` (downgrade) options recreate the journal
+file with a modified format version. The existing journal file is
+replaced. ``-d`` writes out the journal in the format used by
+versions of BIND up to 9.16.11; ``-u`` writes it out in the format used
+by versions since 9.16.13. (9.16.12 is omitted due to a journal-formatting
+bug in that release.) Note that these options *must not* be used while
+``named`` is running.
+
+See Also
+~~~~~~~~
+
+:manpage:`named(8)`, :manpage:`nsupdate(1)`, BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/named-nzd2nzf.c b/bin/tools/named-nzd2nzf.c
new file mode 100644
index 0000000..519f6fd
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef HAVE_LMDB
+#error This program requires the LMDB library.
+#endif /* ifndef HAVE_LMDB */
+
+#include <lmdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <isc/print.h>
+
+#include <dns/lmdb.h>
+#include <dns/view.h>
+
+int
+main(int argc, char *argv[]) {
+ int status;
+ const char *path;
+ MDB_env *env = NULL;
+ MDB_txn *txn = NULL;
+ MDB_cursor *cursor = NULL;
+ MDB_dbi dbi;
+ MDB_val key, data;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: named-nzd2nzf <nzd-path>\n");
+ exit(1);
+ }
+
+ path = argv[1];
+
+ status = mdb_env_create(&env);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_env_create: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_env_open(env, path, DNS_LMDB_FLAGS, 0600);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_env_open: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_txn_begin(env, 0, MDB_RDONLY, &txn);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_txn_begin: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_dbi_open(txn, NULL, 0, &dbi);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_dbi_open: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ status = mdb_cursor_open(txn, dbi, &cursor);
+ if (status != MDB_SUCCESS) {
+ fprintf(stderr, "named-nzd2nzf: mdb_cursor_open: %s",
+ mdb_strerror(status));
+ exit(1);
+ }
+
+ for (status = mdb_cursor_get(cursor, &key, &data, MDB_FIRST);
+ status == MDB_SUCCESS;
+ status = mdb_cursor_get(cursor, &key, &data, MDB_NEXT))
+ {
+ if (key.mv_data == NULL || key.mv_size == 0 ||
+ data.mv_data == NULL || data.mv_size == 0)
+ {
+ fprintf(stderr,
+ "named-nzd2nzf: empty column found in "
+ "database '%s'",
+ path);
+ exit(1);
+ }
+
+ /* zone zonename { config; }; */
+ printf("zone \"%.*s\" %.*s;\n", (int)key.mv_size,
+ (char *)key.mv_data, (int)data.mv_size,
+ (char *)data.mv_data);
+ }
+
+ mdb_cursor_close(cursor);
+ mdb_txn_abort(txn);
+ mdb_env_close(env);
+ exit(0);
+}
diff --git a/bin/tools/named-nzd2nzf.rst b/bin/tools/named-nzd2nzf.rst
new file mode 100644
index 0000000..d20fc36
--- /dev/null
+++ b/bin/tools/named-nzd2nzf.rst
@@ -0,0 +1,42 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. 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 https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. _man_named-nzd2nzf:
+
+named-nzd2nzf - convert an NZD database to NZF text format
+----------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-nzd2nzf` {filename}
+
+Description
+~~~~~~~~~~~
+
+``named-nzd2nzf`` converts an NZD database to NZF format and prints it
+to standard output. This can be used to review the configuration of
+zones that were added to ``named`` via ``rndc addzone``. It can also be
+used to restore the old file format when rolling back from a newer
+version of BIND to an older version.
+
+Arguments
+~~~~~~~~~
+
+``filename``
+ This is the name of the ``.nzd`` file whose contents should be printed.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual.
diff --git a/bin/tools/named-rrchecker.c b/bin/tools/named-rrchecker.c
new file mode 100644
index 0000000..d0081ca
--- /dev/null
+++ b/bin/tools/named-rrchecker.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/lex.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+
+static isc_mem_t *mctx;
+static isc_lex_t *lex;
+
+static isc_lexspecials_t specials;
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ fprintf(stderr, "usage: named-rrchecker [-o origin] [-hpCPTu]\n");
+ fprintf(stderr, "\t-h: print this help message\n");
+ fprintf(stderr, "\t-o origin: set origin to be used when "
+ "interpreting the record\n");
+ fprintf(stderr, "\t-p: print the record in canonical format\n");
+ fprintf(stderr, "\t-C: list the supported class names\n");
+ fprintf(stderr, "\t-P: list the supported private type names\n");
+ fprintf(stderr, "\t-T: list the supported standard type names\n");
+ fprintf(stderr, "\t-u: print the record in unknown record format\n");
+ exit(0);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "named-rrchecker: ");
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputc('\n', stderr);
+ exit(1);
+}
+
+int
+main(int argc, char *argv[]) {
+ isc_token_t token;
+ isc_result_t result;
+ int c;
+ unsigned int options = 0;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char text[256 * 1024];
+ char data[64 * 1024];
+ isc_buffer_t tbuf;
+ isc_buffer_t dbuf;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ bool doexit = false;
+ bool once = false;
+ bool print = false;
+ bool unknown = false;
+ unsigned int t;
+ char *origin = NULL;
+ dns_fixedname_t fixed;
+ dns_name_t *name = NULL;
+
+ while ((c = isc_commandline_parse(argc, argv, "ho:puCPT")) != -1) {
+ switch (c) {
+ case 'o':
+ origin = isc_commandline_argument;
+ break;
+
+ case 'p':
+ print = true;
+ break;
+
+ case 'u':
+ unknown = true;
+ break;
+
+ case 'C':
+ for (t = 1; t <= 0xfeffu; t++) {
+ if (dns_rdataclass_ismeta(t)) {
+ continue;
+ }
+ dns_rdataclass_format(t, text, sizeof(text));
+ if (strncmp(text, "CLASS", 4) != 0) {
+ fprintf(stdout, "%s\n", text);
+ }
+ }
+ exit(0);
+
+ case 'P':
+ for (t = 0xff00; t <= 0xfffeu; t++) {
+ if (dns_rdatatype_ismeta(t)) {
+ continue;
+ }
+ dns_rdatatype_format(t, text, sizeof(text));
+ if (strncmp(text, "TYPE", 4) != 0) {
+ fprintf(stdout, "%s\n", text);
+ }
+ }
+ doexit = true;
+ break;
+
+ case 'T':
+ for (t = 1; t <= 0xfeffu; t++) {
+ if (dns_rdatatype_ismeta(t)) {
+ continue;
+ }
+ dns_rdatatype_format(t, text, sizeof(text));
+ if (strncmp(text, "TYPE", 4) != 0) {
+ fprintf(stdout, "%s\n", text);
+ }
+ }
+ doexit = true;
+ break;
+
+ case '?':
+ case 'h':
+ /* Does not return. */
+ usage();
+
+ default:
+ fprintf(stderr, "%s: unhandled option -%c\n", argv[0],
+ isc_commandline_option);
+ exit(1);
+ }
+ }
+ if (doexit) {
+ exit(0);
+ }
+
+ isc_mem_create(&mctx);
+ RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS);
+
+ /*
+ * Set up to lex DNS master file.
+ */
+
+ specials['('] = 1;
+ specials[')'] = 1;
+ specials['"'] = 1;
+ isc_lex_setspecials(lex, specials);
+ options = ISC_LEXOPT_EOL;
+ isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);
+
+ RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS);
+
+ if (origin != NULL) {
+ name = dns_fixedname_initname(&fixed);
+ result = dns_name_fromstring(name, origin, 0, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_name_fromstring: %s",
+ dns_result_totext(result));
+ }
+ }
+
+ while ((result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
+ &token)) == ISC_R_SUCCESS)
+ {
+ if (token.type == isc_tokentype_eof) {
+ break;
+ }
+ if (token.type == isc_tokentype_eol) {
+ continue;
+ }
+ if (once) {
+ fatal("extra data");
+ }
+ /*
+ * Get class.
+ */
+ if (token.type == isc_tokentype_number) {
+ rdclass = (dns_rdataclass_t)token.value.as_ulong;
+ if (token.value.as_ulong > 0xffffu) {
+ fatal("class value too big %lu",
+ token.value.as_ulong);
+ }
+ if (dns_rdataclass_ismeta(rdclass)) {
+ fatal("class %lu is a meta value",
+ token.value.as_ulong);
+ }
+ } else if (token.type == isc_tokentype_string) {
+ result = dns_rdataclass_fromtext(
+ &rdclass, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdataclass_fromtext: %s",
+ dns_result_totext(result));
+ }
+ if (dns_rdataclass_ismeta(rdclass)) {
+ fatal("class %.*s(%d) is a meta value",
+ (int)token.value.as_textregion.length,
+ token.value.as_textregion.base, rdclass);
+ }
+ } else {
+ fatal("unexpected token %u", token.type);
+ }
+
+ result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
+ &token);
+ if (result != ISC_R_SUCCESS) {
+ break;
+ }
+ if (token.type == isc_tokentype_eol) {
+ continue;
+ }
+ if (token.type == isc_tokentype_eof) {
+ break;
+ }
+
+ /*
+ * Get type.
+ */
+ if (token.type == isc_tokentype_number) {
+ rdtype = (dns_rdatatype_t)token.value.as_ulong;
+ if (token.value.as_ulong > 0xffffu) {
+ fatal("type value too big %lu",
+ token.value.as_ulong);
+ }
+ if (dns_rdatatype_ismeta(rdtype)) {
+ fatal("type %lu is a meta value",
+ token.value.as_ulong);
+ }
+ } else if (token.type == isc_tokentype_string) {
+ result = dns_rdatatype_fromtext(
+ &rdtype, &token.value.as_textregion);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_fromtext: %s",
+ dns_result_totext(result));
+ }
+ if (dns_rdatatype_ismeta(rdtype)) {
+ fatal("type %.*s(%d) is a meta value",
+ (int)token.value.as_textregion.length,
+ token.value.as_textregion.base, rdtype);
+ }
+ } else {
+ fatal("unexpected token %u", token.type);
+ }
+
+ isc_buffer_init(&dbuf, data, sizeof(data));
+ result = dns_rdata_fromtext(&rdata, rdclass, rdtype, lex, name,
+ 0, mctx, &dbuf, NULL);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdata_fromtext: %s",
+ dns_result_totext(result));
+ }
+ once = true;
+ }
+ if (result != ISC_R_EOF) {
+ fatal("eof not found");
+ }
+ if (!once) {
+ fatal("no records found");
+ }
+
+ if (print) {
+ isc_buffer_init(&tbuf, text, sizeof(text));
+ result = dns_rdataclass_totext(rdclass, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdataclass_totext: %s",
+ dns_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdatatype_totext(rdtype, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_totext: %s",
+ dns_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdata_totext(&rdata, NULL, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdata_totext: %s",
+ dns_result_totext(result));
+ }
+
+ printf("%.*s\n", (int)tbuf.used, (char *)tbuf.base);
+ fflush(stdout);
+ }
+
+ if (unknown) {
+ isc_buffer_init(&tbuf, text, sizeof(text));
+ result = dns_rdataclass_tounknowntext(rdclass, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdataclass_tounknowntext: %s",
+ dns_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdatatype_tounknowntext(rdtype, &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdatatype_tounknowntext: %s",
+ dns_result_totext(result));
+ }
+ isc_buffer_putstr(&tbuf, "\t");
+ result = dns_rdata_tofmttext(&rdata, NULL,
+ DNS_STYLEFLAG_UNKNOWNFORMAT, 0, 0,
+ "", &tbuf);
+ if (result != ISC_R_SUCCESS) {
+ fatal("dns_rdata_tofmttext: %sn",
+ dns_result_totext(result));
+ }
+
+ printf("%.*s\n", (int)tbuf.used, (char *)tbuf.base);
+ fflush(stdout);
+ }
+
+ isc_lex_close(lex);
+ isc_lex_destroy(&lex);
+ isc_mem_destroy(&mctx);
+ return (0);
+}
diff --git a/bin/tools/named-rrchecker.rst b/bin/tools/named-rrchecker.rst
new file mode 100644
index 0000000..191f229
--- /dev/null
+++ b/bin/tools/named-rrchecker.rst
@@ -0,0 +1,55 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. 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 https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. _man_named-rrchecker:
+
+named-rrchecker - syntax checker for individual DNS resource records
+--------------------------------------------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`named-rrchecker` [**-h**] [**-o** origin] [**-p**] [**-u**] [**-C**] [**-T**] [**-P**]
+
+Description
+~~~~~~~~~~~
+
+``named-rrchecker`` reads a individual DNS resource record from standard
+input and checks whether it is syntactically correct.
+
+Options
+~~~~~~~
+
+``-h``
+ This option prints out the help menu.
+
+``-o origin``
+ This option specifies the origin to be used when interpreting
+ the record.
+
+``-p``
+ This option prints out the resulting record in canonical form. If there
+ is no canonical form defined, the record is printed in unknown
+ record format.
+
+``-u``
+ This option prints out the resulting record in unknown record form.
+
+``-C``, ``-T``, and ``-P``
+ These options print out the known class, standard type,
+ and private type mnemonics, respectively.
+
+See Also
+~~~~~~~~
+
+:rfc:`1034`, :rfc:`1035`, :manpage:`named(8)`.
diff --git a/bin/tools/nsec3hash.c b/bin/tools/nsec3hash.c
new file mode 100644
index 0000000..2441bf1
--- /dev/null
+++ b/bin/tools/nsec3hash.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * 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 https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include <isc/base32.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/file.h>
+#include <isc/hex.h>
+#include <isc/iterated_hash.h>
+#include <isc/print.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <dns/fixedname.h>
+#include <dns/name.h>
+#include <dns/nsec3.h>
+#include <dns/types.h>
+
+const char *program = "nsec3hash";
+
+ISC_PLATFORM_NORETURN_PRE static void
+fatal(const char *format, ...) ISC_PLATFORM_NORETURN_POST;
+
+static void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fprintf(stderr, "%s: ", program);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+static void
+check_result(isc_result_t result, const char *message) {
+ if (result != ISC_R_SUCCESS) {
+ fatal("%s: %s", message, isc_result_totext(result));
+ }
+}
+
+static void
+usage() {
+ fprintf(stderr, "Usage: %s salt algorithm iterations domain\n",
+ program);
+ fprintf(stderr, " %s -r algorithm flags iterations salt domain\n",
+ program);
+ exit(1);
+}
+
+typedef void
+nsec3printer(unsigned algo, unsigned flags, unsigned iters, const char *saltstr,
+ const char *domain, const char *digest);
+
+static void
+nsec3hash(nsec3printer *nsec3print, const char *algostr, const char *flagstr,
+ const char *iterstr, const char *saltstr, const char *domain) {
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_buffer_t buffer;
+ isc_region_t region;
+ isc_result_t result;
+ unsigned char hash[NSEC3_MAX_HASH_LENGTH];
+ unsigned char salt[DNS_NSEC3_SALTSIZE];
+ unsigned char text[1024];
+ unsigned int hash_alg;
+ unsigned int flags;
+ unsigned int length;
+ unsigned int iterations;
+ unsigned int salt_length;
+ const char dash[] = "-";
+
+ if (strcmp(saltstr, "-") == 0) {
+ salt_length = 0;
+ salt[0] = 0;
+ } else {
+ isc_buffer_init(&buffer, salt, sizeof(salt));
+ result = isc_hex_decodestring(saltstr, &buffer);
+ check_result(result, "isc_hex_decodestring(salt)");
+ salt_length = isc_buffer_usedlength(&buffer);
+ if (salt_length > DNS_NSEC3_SALTSIZE) {
+ fatal("salt too long");
+ }
+ if (salt_length == 0) {
+ saltstr = dash;
+ }
+ }
+ hash_alg = atoi(algostr);
+ if (hash_alg > 255U) {
+ fatal("hash algorithm too large");
+ }
+ flags = flagstr == NULL ? 0 : atoi(flagstr);
+ if (flags > 255U) {
+ fatal("flags too large");
+ }
+ iterations = atoi(iterstr);
+ if (iterations > 0xffffU) {
+ fatal("iterations to large");
+ }
+
+ name = dns_fixedname_initname(&fixed);
+ isc_buffer_constinit(&buffer, domain, strlen(domain));
+ isc_buffer_add(&buffer, strlen(domain));
+ result = dns_name_fromtext(name, &buffer, dns_rootname, 0, NULL);
+ check_result(result, "dns_name_fromtext() failed");
+
+ dns_name_downcase(name, name, NULL);
+ length = isc_iterated_hash(hash, hash_alg, iterations, salt,
+ salt_length, name->ndata, name->length);
+ if (length == 0) {
+ fatal("isc_iterated_hash failed");
+ }
+ region.base = hash;
+ region.length = length;
+ isc_buffer_init(&buffer, text, sizeof(text));
+ isc_base32hexnp_totext(&region, 1, "", &buffer);
+ isc_buffer_putuint8(&buffer, '\0');
+
+ nsec3print(hash_alg, flags, iterations, saltstr, domain, (char *)text);
+}
+
+static void
+nsec3hash_print(unsigned algo, unsigned flags, unsigned iters,
+ const char *saltstr, const char *domain, const char *digest) {
+ UNUSED(flags);
+ UNUSED(domain);
+
+ fprintf(stdout, "%s (salt=%s, hash=%u, iterations=%u)\n", digest,
+ saltstr, algo, iters);
+}
+
+static void
+nsec3hash_rdata_print(unsigned algo, unsigned flags, unsigned iters,
+ const char *saltstr, const char *domain,
+ const char *digest) {
+ fprintf(stdout, "%s NSEC3 %u %u %u %s %s\n", domain, algo, flags, iters,
+ saltstr, digest);
+}
+
+int
+main(int argc, char *argv[]) {
+ bool rdata_format = false;
+ int ch;
+
+ while ((ch = isc_commandline_parse(argc, argv, "-r")) != -1) {
+ switch (ch) {
+ case 'r':
+ rdata_format = true;
+ break;
+ case '-':
+ isc_commandline_index -= 1;
+ goto skip;
+ default:
+ break;
+ }
+ }
+
+skip:
+ argc -= isc_commandline_index;
+ argv += isc_commandline_index;
+
+ if (rdata_format) {
+ if (argc != 5) {
+ usage();
+ }
+ nsec3hash(nsec3hash_rdata_print, argv[0], argv[1], argv[2],
+ argv[3], argv[4]);
+ } else {
+ if (argc != 4) {
+ usage();
+ }
+ nsec3hash(nsec3hash_print, argv[1], NULL, argv[2], argv[0],
+ argv[3]);
+ }
+ return (0);
+}
diff --git a/bin/tools/nsec3hash.rst b/bin/tools/nsec3hash.rst
new file mode 100644
index 0000000..9b174ce
--- /dev/null
+++ b/bin/tools/nsec3hash.rst
@@ -0,0 +1,63 @@
+.. Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+..
+.. SPDX-License-Identifier: MPL-2.0
+..
+.. 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 https://mozilla.org/MPL/2.0/.
+..
+.. See the COPYRIGHT file distributed with this work for additional
+.. information regarding copyright ownership.
+
+.. highlight: console
+
+.. _man_nsec3hash:
+
+nsec3hash - generate NSEC3 hash
+-------------------------------
+
+Synopsis
+~~~~~~~~
+
+:program:`nsec3hash` {salt} {algorithm} {iterations} {domain}
+
+:program:`nsec3hash` **-r** {algorithm} {flags} {iterations} {salt} {domain}
+
+Description
+~~~~~~~~~~~
+
+``nsec3hash`` generates an NSEC3 hash based on a set of NSEC3
+parameters. This can be used to check the validity of NSEC3 records in a
+signed zone.
+
+If this command is invoked as ``nsec3hash -r``, it takes arguments in
+order, matching the first four fields of an NSEC3 record followed by the
+domain name: ``algorithm``, ``flags``, ``iterations``, ``salt``, ``domain``. This makes it
+convenient to copy and paste a portion of an NSEC3 or NSEC3PARAM record
+into a command line to confirm the correctness of an NSEC3 hash.
+
+Arguments
+~~~~~~~~~
+
+``salt``
+ This is the salt provided to the hash algorithm.
+
+``algorithm``
+ This is a number indicating the hash algorithm. Currently the only supported
+ hash algorithm for NSEC3 is SHA-1, which is indicated by the number
+ 1; consequently "1" is the only useful value for this argument.
+
+``flags``
+ This is provided for compatibility with NSEC3 record presentation format, but
+ is ignored since the flags do not affect the hash.
+
+``iterations``
+ This is the number of additional times the hash should be performed.
+
+``domain``
+ This is the domain name to be hashed.
+
+See Also
+~~~~~~~~
+
+BIND 9 Administrator Reference Manual, :rfc:`5155`.
diff --git a/bin/tools/win32/arpaname.vcxproj.filters.in b/bin/tools/win32/arpaname.vcxproj.filters.in
new file mode 100644
index 0000000..129b93e
--- /dev/null
+++ b/bin/tools/win32/arpaname.vcxproj.filters.in
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\arpaname.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/arpaname.vcxproj.in b/bin/tools/win32/arpaname.vcxproj.in
new file mode 100644
index 0000000..45772b2
--- /dev/null
+++ b/bin/tools/win32/arpaname.vcxproj.in
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{91E60FDA-E48C-4DA0-92A2-97F963348E00}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>arpaname</RootNamespace>
+ @WINDOWS_TARGET_PLATFORM_VERSION@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>false</TreatWarningAsError>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <BrowseInformation>true</BrowseInformation>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level1</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\arpaname.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/arpaname.vcxproj.user b/bin/tools/win32/arpaname.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/bin/tools/win32/arpaname.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/journalprint.vcxproj.filters.in b/bin/tools/win32/journalprint.vcxproj.filters.in
new file mode 100644
index 0000000..cb89470
--- /dev/null
+++ b/bin/tools/win32/journalprint.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-journalprint.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/journalprint.vcxproj.in b/bin/tools/win32/journalprint.vcxproj.in
new file mode 100644
index 0000000..dc610b5
--- /dev/null
+++ b/bin/tools/win32/journalprint.vcxproj.in
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{B19042CE-D3D9-469B-BCD2-C3140150939A}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>journalprint</RootNamespace>
+ @WINDOWS_TARGET_PLATFORM_VERSION@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>false</TreatWarningAsError>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level1</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(ProjectName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-journalprint.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/journalprint.vcxproj.user b/bin/tools/win32/journalprint.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/bin/tools/win32/journalprint.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/mdig.vcxproj.filters.in b/bin/tools/win32/mdig.vcxproj.filters.in
new file mode 100644
index 0000000..fbb8ba4
--- /dev/null
+++ b/bin/tools/win32/mdig.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\mdig.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/bin/tools/win32/mdig.vcxproj.in b/bin/tools/win32/mdig.vcxproj.in
new file mode 100644
index 0000000..abbf682
--- /dev/null
+++ b/bin/tools/win32/mdig.vcxproj.in
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{3115091C-8135-481F-9757-F013A26255E0}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>mdig</RootNamespace>
+ @WINDOWS_TARGET_PLATFORM_VERSION@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>false</TreatWarningAsError>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level1</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;libbind9.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\mdig.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/mdig.vcxproj.user b/bin/tools/win32/mdig.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/bin/tools/win32/mdig.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/nsec3hash.vcxproj.filters.in b/bin/tools/win32/nsec3hash.vcxproj.filters.in
new file mode 100644
index 0000000..009e970
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\nsec3hash.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/nsec3hash.vcxproj.in b/bin/tools/win32/nsec3hash.vcxproj.in
new file mode 100644
index 0000000..04b7b6a
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.vcxproj.in
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{4EE91023-94C3-48C0-B71C-5333B726C2EE}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>nsec3hash</RootNamespace>
+ @WINDOWS_TARGET_PLATFORM_VERSION@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>false</TreatWarningAsError>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level1</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\nsec3hash.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/nsec3hash.vcxproj.user b/bin/tools/win32/nsec3hash.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/bin/tools/win32/nsec3hash.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/bin/tools/win32/rrchecker.vcxproj.filters.in b/bin/tools/win32/rrchecker.vcxproj.filters.in
new file mode 100644
index 0000000..d7f077d
--- /dev/null
+++ b/bin/tools/win32/rrchecker.vcxproj.filters.in
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-rrchecker.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project>
diff --git a/bin/tools/win32/rrchecker.vcxproj.in b/bin/tools/win32/rrchecker.vcxproj.in
new file mode 100644
index 0000000..b878dd7
--- /dev/null
+++ b/bin/tools/win32/rrchecker.vcxproj.in
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="@TOOLS_VERSION@" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|@PLATFORM@">
+ <Configuration>Debug</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|@PLATFORM@">
+ <Configuration>Release</Configuration>
+ <Platform>@PLATFORM@</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{98743A7C-6AF8-467f-9911-FA69C451AF2B}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>rrchecker</RootNamespace>
+ @WINDOWS_TARGET_PLATFORM_VERSION@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ @PLATFORM_TOOLSET@
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <LinkIncremental>true</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ <IntDirSharingDetected>None</IntDirSharingDetected>
+ <TargetName>named-$(ProjectName)</TargetName>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level4</WarningLevel>
+ <TreatWarningAsError>false</TreatWarningAsError>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <BrowseInformation>true</BrowseInformation>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level1</WarningLevel>
+ <TreatWarningAsError>true</TreatWarningAsError>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
+ <WholeProgramOptimization>false</WholeProgramOptimization>
+ <StringPooling>true</StringPooling>
+ <PrecompiledHeaderOutputFile>.\$(Configuration)\$(TargetName).pch</PrecompiledHeaderOutputFile>
+ <AssemblerListingLocation>.\$(Configuration)\</AssemblerListingLocation>
+ <ObjectFileName>.\$(Configuration)\</ObjectFileName>
+ <ProgramDataBaseFileName>$(OutDir)$(TargetName).pdb</ProgramDataBaseFileName>
+ <ForcedIncludeFiles>..\..\..\config.h</ForcedIncludeFiles>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\dns\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>false</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <LinkTimeCodeGeneration>Default</LinkTimeCodeGeneration>
+ <AdditionalLibraryDirectories>..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@OPENSSL_LIBCRYPTO@@OPENSSL_LIBSSL@libisc.lib;libdns.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\named-rrchecker.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/tools/win32/rrchecker.vcxproj.user b/bin/tools/win32/rrchecker.vcxproj.user
new file mode 100644
index 0000000..ace9a86
--- /dev/null
+++ b/bin/tools/win32/rrchecker.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file