summaryrefslogtreecommitdiffstats
path: root/bin/dig
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 18:37:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 18:37:14 +0000
commitea648e70a989cca190cd7403fe892fd2dcc290b4 (patch)
treee2b6b1c647da68b0d4d66082835e256eb30970e8 /bin/dig
parentInitial commit. (diff)
downloadbind9-upstream.tar.xz
bind9-upstream.zip
Adding upstream version 1:9.11.5.P4+dfsg.upstream/1%9.11.5.P4+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
-rw-r--r--bin/dig/Makefile.in111
-rw-r--r--bin/dig/dig.1803
-rw-r--r--bin/dig/dig.c2293
-rw-r--r--bin/dig/dig.docbook1329
-rw-r--r--bin/dig/dig.html1075
-rw-r--r--bin/dig/dighost.c6676
-rw-r--r--bin/dig/host.1269
-rw-r--r--bin/dig/host.c921
-rw-r--r--bin/dig/host.docbook406
-rw-r--r--bin/dig/host.html333
-rw-r--r--bin/dig/include/dig/dig.h485
-rw-r--r--bin/dig/nslookup.1294
-rw-r--r--bin/dig/nslookup.c1037
-rw-r--r--bin/dig/nslookup.docbook501
-rw-r--r--bin/dig/nslookup.html386
-rw-r--r--bin/dig/win32/dig.dsp.in107
-rw-r--r--bin/dig/win32/dig.dsw29
-rw-r--r--bin/dig/win32/dig.mak.in427
-rw-r--r--bin/dig/win32/dig.vcxproj.filters.in27
-rw-r--r--bin/dig/win32/dig.vcxproj.in113
-rw-r--r--bin/dig/win32/dig.vcxproj.user3
-rw-r--r--bin/dig/win32/dighost.dsp.in113
-rw-r--r--bin/dig/win32/dighost.dsw29
-rw-r--r--bin/dig/win32/dighost.vcxproj.filters.in18
-rw-r--r--bin/dig/win32/dighost.vcxproj.in106
-rw-r--r--bin/dig/win32/dighost.vcxproj.user3
-rw-r--r--bin/dig/win32/host.dsp.in103
-rw-r--r--bin/dig/win32/host.dsw29
-rw-r--r--bin/dig/win32/host.mak.in427
-rw-r--r--bin/dig/win32/host.vcxproj.filters.in18
-rw-r--r--bin/dig/win32/host.vcxproj.in110
-rw-r--r--bin/dig/win32/host.vcxproj.user3
-rw-r--r--bin/dig/win32/nslookup.dsp.in107
-rw-r--r--bin/dig/win32/nslookup.dsw29
-rw-r--r--bin/dig/win32/nslookup.mak.in427
-rw-r--r--bin/dig/win32/nslookup.vcxproj.filters.in21
-rw-r--r--bin/dig/win32/nslookup.vcxproj.in111
-rw-r--r--bin/dig/win32/nslookup.vcxproj.user3
38 files changed, 19282 insertions, 0 deletions
diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
new file mode 100644
index 0000000..a9830a9
--- /dev/null
+++ b/bin/dig/Makefile.in
@@ -0,0 +1,111 @@
+# Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+# See the COPYRIGHT file distributed with this work for additional
+# information regarding copyright ownership.
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+VERSION=@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+READLINE_LIB = @READLINE_LIB@
+
+CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} \
+ ${BIND9_INCLUDES} ${ISC_INCLUDES} \
+ ${LWRES_INCLUDES} ${ISCCFG_INCLUDES} @LIBIDN2_CFLAGS@ @DST_OPENSSL_INC@
+
+CDEFINES = -DVERSION=\"${VERSION}\" @CRYPTO@
+CWARNINGS =
+
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@A@
+ISCNOSYMLIBS = ../../lib/isc/libisc-nosymtbl.@A@
+LWRESLIBS = ../../lib/lwres/liblwres.@A@
+
+ISCCFGDEPLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSDEPLIBS = ../../lib/dns/libdns.@A@
+BIND9DEPLIBS = ../../lib/bind9/libbind9.@A@
+ISCDEPLIBS = ../../lib/isc/libisc.@A@
+LWRESDEPLIBS = ../../lib/lwres/liblwres.@A@
+
+DEPLIBS = ${DNSDEPLIBS} ${BIND9DEPLIBS} ${ISCDEPLIBS} \
+ ${ISCCFGDEPLIBS} ${LWRESDEPLIBS}
+
+LIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
+ ${ISCLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@
+
+NOSYMLIBS = ${LWRESLIBS} ${BIND9LIBS} ${ISCCFGLIBS} \
+ ${ISCNOSYMLIBS} @IDNKIT_LIBS@ @LIBIDN2_LIBS@ @LIBS@
+
+SUBDIRS =
+
+TARGETS = dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@
+
+OBJS = dig.@O@ dighost.@O@ host.@O@ nslookup.@O@
+
+UOBJS =
+
+SRCS = dig.c dighost.c host.c nslookup.c
+
+MANPAGES = dig.1 host.1 nslookup.1
+
+HTMLPAGES = dig.html host.html nslookup.html
+
+MANOBJS = ${MANPAGES} ${HTMLPAGES}
+
+@BIND9_MAKE_RULES@
+
+dig@EXEEXT@: dig.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="dig.@O@ dighost.@O@ ${UOBJS}"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="host.@O@ dighost.@O@ ${UOBJS}"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ export BASEOBJS="nslookup.@O@ dighost.@O@ ${READLINE_LIB} ${UOBJS}"; \
+ export LIBS0="${DNSLIBS}"; \
+ ${FINALBUILDCMD}
+
+doc man:: ${MANOBJS}
+
+docclean manclean maintainer-clean::
+ rm -f ${MANOBJS}
+
+clean distclean maintainer-clean::
+ rm -f ${TARGETS}
+
+installdirs:
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${bindir}
+ $(SHELL) ${top_srcdir}/mkinstalldirs ${DESTDIR}${mandir}/man1
+
+install:: dig@EXEEXT@ host@EXEEXT@ nslookup@EXEEXT@ installdirs
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ dig@EXEEXT@ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ host@EXEEXT@ ${DESTDIR}${bindir}
+ ${LIBTOOL_MODE_INSTALL} ${INSTALL_PROGRAM} \
+ nslookup@EXEEXT@ ${DESTDIR}${bindir}
+ for m in ${MANPAGES}; do \
+ ${INSTALL_DATA} ${srcdir}/$$m ${DESTDIR}${mandir}/man1 || exit 1; \
+ done
+
+uninstall::
+ for m in ${MANPAGES}; do \
+ rm -f ${DESTDIR}${mandir}/man1/$$m || exit 1; \
+ done
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/nslookup@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/host@EXEEXT@
+ ${LIBTOOL_MODE_UNINSTALL} rm -f ${DESTDIR}${bindir}/dig@EXEEXT@
diff --git a/bin/dig/dig.1 b/bin/dig/dig.1
new file mode 100644
index 0000000..771f201
--- /dev/null
+++ b/bin/dig/dig.1
@@ -0,0 +1,803 @@
+.\" Copyright (C) 2000-2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: dig
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-02-19
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "DIG" "1" "2014\-02\-19" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+dig \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP \w'\fBdig\fR\ 'u
+\fBdig\fR [@server] [\fB\-b\ \fR\fB\fIaddress\fR\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-f\ \fR\fB\fIfilename\fR\fR] [\fB\-k\ \fR\fB\fIfilename\fR\fR] [\fB\-m\fR] [\fB\-p\ \fR\fB\fIport#\fR\fR] [\fB\-q\ \fR\fB\fIname\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-v\fR] [\fB\-x\ \fR\fB\fIaddr\fR\fR] [\fB\-y\ \fR\fB\fI[hmac:]\fR\fIname:key\fR\fR] [[\fB\-4\fR] | [\fB\-6\fR]] [name] [type] [class] [queryopt...]
+.HP \w'\fBdig\fR\ 'u
+\fBdig\fR [\fB\-h\fR]
+.HP \w'\fBdig\fR\ 'u
+\fBdig\fR [global\-queryopt...] [query...]
+.SH "DESCRIPTION"
+.PP
+\fBdig\fR
+is a flexible tool for interrogating DNS name servers\&. It performs DNS lookups and displays the answers that are returned from the name server(s) that were queried\&. Most DNS administrators use
+\fBdig\fR
+to troubleshoot DNS problems because of its flexibility, ease of use and clarity of output\&. Other lookup tools tend to have less functionality than
+\fBdig\fR\&.
+.PP
+Although
+\fBdig\fR
+is normally used with command\-line arguments, it also has a batch mode of operation for reading lookup requests from a file\&. A brief summary of its command\-line arguments and options is printed when the
+\fB\-h\fR
+option is given\&. Unlike earlier versions, the BIND 9 implementation of
+\fBdig\fR
+allows multiple lookups to be issued from the command line\&.
+.PP
+Unless it is told to query a specific name server,
+\fBdig\fR
+will try each of the servers listed in
+/etc/resolv\&.conf\&. If no usable server addresses are found,
+\fBdig\fR
+will send the query to the local host\&.
+.PP
+When no command line arguments or options are given,
+\fBdig\fR
+will perform an NS query for "\&." (the root)\&.
+.PP
+It is possible to set per\-user defaults for
+\fBdig\fR
+via
+${HOME}/\&.digrc\&. This file is read and any options in it are applied before the command line arguments\&.
+.PP
+The IN and CH class names overlap with the IN and CH top level domain names\&. Either use the
+\fB\-t\fR
+and
+\fB\-c\fR
+options to specify the type and class, use the
+\fB\-q\fR
+the specify the domain name, or use "IN\&." and "CH\&." when looking up these top level domains\&.
+.SH "SIMPLE USAGE"
+.PP
+A typical invocation of
+\fBdig\fR
+looks like:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ dig @server name type
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+where:
+.PP
+\fBserver\fR
+.RS 4
+is the name or IP address of the name server to query\&. This can be an IPv4 address in dotted\-decimal notation or an IPv6 address in colon\-delimited notation\&. When the supplied
+\fIserver\fR
+argument is a hostname,
+\fBdig\fR
+resolves that name before querying that name server\&.
+.sp
+If no
+\fIserver\fR
+argument is provided,
+\fBdig\fR
+consults
+/etc/resolv\&.conf; if an address is found there, it queries the name server at that address\&. If either of the
+\fB\-4\fR
+or
+\fB\-6\fR
+options are in use, then only addresses for the corresponding transport will be tried\&. If no usable addresses are found,
+\fBdig\fR
+will send the query to the local host\&. The reply from the name server that responds is displayed\&.
+.RE
+.PP
+\fBname\fR
+.RS 4
+is the name of the resource record that is to be looked up\&.
+.RE
+.PP
+\fBtype\fR
+.RS 4
+indicates what type of query is required \(em ANY, A, MX, SIG, etc\&.
+\fItype\fR
+can be any valid query type\&. If no
+\fItype\fR
+argument is supplied,
+\fBdig\fR
+will perform a lookup for an A record\&.
+.RE
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only\&.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only\&.
+.RE
+.PP
+\-b \fIaddress\fR\fI[#port]\fR
+.RS 4
+Set the source IP address of the query\&. The
+\fIaddress\fR
+must be a valid address on one of the host\*(Aqs network interfaces, or "0\&.0\&.0\&.0" or "::"\&. An optional port may be specified by appending "#<port>"
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Set the query class\&. The default
+\fIclass\fR
+is IN; other classes are HS for Hesiod records or CH for Chaosnet records\&.
+.RE
+.PP
+\-f \fIfile\fR
+.RS 4
+Batch mode:
+\fBdig\fR
+reads a list of lookup requests to process from the given
+\fIfile\fR\&. Each line in the file should be organized in the same way they would be presented as queries to
+\fBdig\fR
+using the command\-line interface\&.
+.RE
+.PP
+\-i
+.RS 4
+Do reverse IPv6 lookups using the obsolete RFC 1886 IP6\&.INT domain, which is no longer in use\&. Obsolete bit string label queries (RFC 2874) are not attempted\&.
+.RE
+.PP
+\-k \fIkeyfile\fR
+.RS 4
+Sign queries using TSIG using a key read from the given file\&. Key files can be generated using
+\fBtsig-keygen\fR(8)\&. When using TSIG authentication with
+\fBdig\fR, the name server that is queried needs to know the key and algorithm that is being used\&. In BIND, this is done by providing appropriate
+\fBkey\fR
+and
+\fBserver\fR
+statements in
+named\&.conf\&.
+.RE
+.PP
+\-m
+.RS 4
+Enable memory usage debugging\&.
+.RE
+.PP
+\-p \fIport\fR
+.RS 4
+Send the query to a non\-standard port on the server, instead of the default port 53\&. This option would be used to test a name server that has been configured to listen for queries on a non\-standard port number\&.
+.RE
+.PP
+\-q \fIname\fR
+.RS 4
+The domain name to query\&. This is useful to distinguish the
+\fIname\fR
+from other arguments\&.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+The resource record type to query\&. It can be any valid query type\&. If it is a resource record type supported in BIND 9, it can be given by the type mnemonic (such as "NS" or "AAAA")\&. The default query type is "A", unless the
+\fB\-x\fR
+option is supplied to indicate a reverse lookup\&. A zone transfer can be requested by specifying a type of AXFR\&. When an incremental zone transfer (IXFR) is required, set the
+\fItype\fR
+to
+ixfr=N\&. The incremental zone transfer will contain the changes made to the zone since the serial number in the zone\*(Aqs SOA record was
+\fIN\fR\&.
+.sp
+All resource record types can be expressed as "TYPEnn", where "nn" is the number of the type\&. If the resource record type is not supported in BIND 9, the result will be displayed as described in RFC 3597\&.
+.RE
+.PP
+\-u
+.RS 4
+Print query times in microseconds instead of milliseconds\&.
+.RE
+.PP
+\-v
+.RS 4
+Print the version number and exit\&.
+.RE
+.PP
+\-x \fIaddr\fR
+.RS 4
+Simplified reverse lookups, for mapping addresses to names\&. The
+\fIaddr\fR
+is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address\&. When the
+\fB\-x\fR
+is used, there is no need to provide the
+\fIname\fR,
+\fIclass\fR
+and
+\fItype\fR
+arguments\&.
+\fBdig\fR
+automatically performs a lookup for a name like
+94\&.2\&.0\&.192\&.in\-addr\&.arpa
+and sets the query type and class to PTR and IN respectively\&. IPv6 addresses are looked up using nibble format under the IP6\&.ARPA domain (but see also the
+\fB\-i\fR
+option)\&.
+.RE
+.PP
+\-y \fI[hmac:]\fR\fIkeyname:secret\fR
+.RS 4
+Sign queries using TSIG with the given authentication key\&.
+\fIkeyname\fR
+is the name of the key, and
+\fIsecret\fR
+is the base64 encoded shared secret\&.
+\fIhmac\fR
+is the name of the key algorithm; valid choices are
+hmac\-md5,
+hmac\-sha1,
+hmac\-sha224,
+hmac\-sha256,
+hmac\-sha384, or
+hmac\-sha512\&. If
+\fIhmac\fR
+is not specified, the default is
+hmac\-md5
+or if MD5 was disabled
+hmac\-sha256\&.
+.sp
+NOTE: You should use the
+\fB\-k\fR
+option and avoid the
+\fB\-y\fR
+option, because with
+\fB\-y\fR
+the shared secret is supplied as a command line argument in clear text\&. This may be visible in the output from
+\fBps\fR(1)
+or in a history file maintained by the user\*(Aqs shell\&.
+.RE
+.SH "QUERY OPTIONS"
+.PP
+\fBdig\fR
+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\&.
+.PP
+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
+\fB+keyword=value\fR\&. Keywords may be abbreviated, provided the abbreviation is unambiguous; for example,
++cd
+is equivalent to
++cdflag\&. The query options are:
+.PP
+\fB+[no]aaflag\fR
+.RS 4
+A synonym for
+\fI+[no]aaonly\fR\&.
+.RE
+.PP
+\fB+[no]aaonly\fR
+.RS 4
+Sets the "aa" flag in the query\&.
+.RE
+.PP
+\fB+[no]additional\fR
+.RS 4
+Display [do not display] the additional section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]adflag\fR
+.RS 4
+Set [do 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 indicate that some part of the answer was insecure or not validated\&. This bit is set by default\&.
+.RE
+.PP
+\fB+[no]all\fR
+.RS 4
+Set or clear all display flags\&.
+.RE
+.PP
+\fB+[no]answer\fR
+.RS 4
+Display [do not display] the answer section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]authority\fR
+.RS 4
+Display [do not display] the authority section of a reply\&. The default is to display it\&.
+.RE
+.PP
+\fB+[no]badcookie\fR
+.RS 4
+Retry lookup with the new server cookie if a BADCOOKIE response is received\&.
+.RE
+.PP
+\fB+[no]besteffort\fR
+.RS 4
+Attempt to display the contents of messages which are malformed\&. The default is to not display malformed answers\&.
+.RE
+.PP
+\fB+bufsize=B\fR
+.RS 4
+Set the UDP message buffer size advertised using EDNS0 to
+\fIB\fR
+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 will cause a EDNS query to be sent\&.
+.RE
+.PP
+\fB+[no]cdflag\fR
+.RS 4
+Set [do not set] the CD (checking disabled) bit in the query\&. This requests the server to not perform DNSSEC validation of responses\&.
+.RE
+.PP
+\fB+[no]class\fR
+.RS 4
+Display [do not display] the CLASS when printing the record\&.
+.RE
+.PP
+\fB+[no]cmd\fR
+.RS 4
+Toggles the printing of the initial comment in the output identifying the version of
+\fBdig\fR
+and the query options that have been applied\&. This comment is printed by default\&.
+.RE
+.PP
+\fB+[no]comments\fR
+.RS 4
+Toggle the display of comment lines in the output\&. The default is to print comments\&.
+.RE
+.PP
+\fB+[no]cookie\fR\fB[=####]\fR
+.RS 4
+Send a COOKIE EDNS option, with optional value\&. Replaying a COOKIE from a previous response will allow the server to identify a previous client\&. The default is
+\fB+cookie\fR\&.
+.sp
+\fB+cookie\fR
+is also set when +trace is set to better emulate the default queries from a nameserver\&.
+.RE
+.PP
+\fB+[no]crypto\fR
+.RS 4
+Toggle the display of cryptographic fields in DNSSEC records\&. The contents of these field 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]" or in the DNSKEY case the key id is displayed as the replacement, e\&.g\&. "[ key id = value ]"\&.
+.RE
+.PP
+\fB+[no]defname\fR
+.RS 4
+Deprecated, treated as a synonym for
+\fI+[no]search\fR
+.RE
+.PP
+\fB+[no]dnssec\fR
+.RS 4
+Requests DNSSEC records be sent by setting the DNSSEC OK bit (DO) in the OPT record in the additional section of the query\&.
+.RE
+.PP
+\fB+domain=somename\fR
+.RS 4
+Set the search list to contain the single domain
+\fIsomename\fR, as if specified in a
+\fBdomain\fR
+directive in
+/etc/resolv\&.conf, and enable search list processing as if the
+\fI+search\fR
+option were given\&.
+.RE
+.PP
+\fB+dscp=value\fR
+.RS 4
+Set 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\&.
+.RE
+.PP
+\fB+[no]edns[=#]\fR
+.RS 4
+Specify the EDNS version to query with\&. Valid values are 0 to 255\&. Setting the EDNS version will cause a EDNS query to be sent\&.
+\fB+noedns\fR
+clears the remembered EDNS version\&. EDNS is set to 0 by default\&.
+.RE
+.PP
+\fB+[no]ednsflags[=#]\fR
+.RS 4
+Set the must\-be\-zero EDNS flags bits (Z bits) to the specified value\&. Decimal, hex and octal encodings are accepted\&. Setting a named flag (e\&.g\&. DO) will silently be ignored\&. By default, no Z bits are set\&.
+.RE
+.PP
+\fB+[no]ednsnegotiation\fR
+.RS 4
+Enable / disable EDNS version negotiation\&. By default EDNS version negotiation is enabled\&.
+.RE
+.PP
+\fB+[no]ednsopt[=code[:value]]\fR
+.RS 4
+Specify EDNS option with code point
+\fBcode\fR
+and optionally payload of
+\fBvalue\fR
+as a hexadecimal string\&.
+\fBcode\fR
+can be either an EDNS option name (for example,
+NSID
+or
+ECS), or an arbitrary numeric value\&.
+\fB+noednsopt\fR
+clears the EDNS options to be sent\&.
+.RE
+.PP
+\fB+[no]expire\fR
+.RS 4
+Send an EDNS Expire option\&.
+.RE
+.PP
+\fB+[no]fail\fR
+.RS 4
+Do not try the next server if you receive a SERVFAIL\&. The default is to not try the next server which is the reverse of normal stub resolver behavior\&.
+.RE
+.PP
+\fB+[no]header\-only\fR
+.RS 4
+Send a query with a DNS header without a question section\&. The default is to add a question section\&. The query type and query name are ignored when this is set\&.
+.RE
+.PP
+\fB+[no]identify\fR
+.RS 4
+Show [or do not show] the IP address and port number that supplied the answer when the
+\fI+short\fR
+option is enabled\&. If short form answers are requested, the default is not to show the source address and port number of the server that provided the answer\&.
+.RE
+.PP
+\fB+[no]idnin\fR
+.RS 4
+Process [do not process] IDN domain names on input\&. This requires IDN SUPPORT to have been enabled at compile time\&. The default is to process IDN input\&.
+.RE
+.PP
+\fB+[no]idnout\fR
+.RS 4
+Convert [do not convert] puny code on output\&. This requires IDN SUPPORT to have been enabled at compile time\&. The default is to convert output\&.
+.RE
+.PP
+\fB+[no]ignore\fR
+.RS 4
+Ignore truncation in UDP responses instead of retrying with TCP\&. By default, TCP retries are performed\&.
+.RE
+.PP
+\fB+[no]keepopen\fR
+.RS 4
+Keep the TCP socket open between queries and reuse it rather than creating a new TCP socket for each lookup\&. The default is
+\fB+nokeepopen\fR\&.
+.RE
+.PP
+\fB+[no]mapped\fR
+.RS 4
+Allow mapped IPv4 over IPv6 addresses to be used\&. The default is
+\fB+mapped\fR\&.
+.RE
+.PP
+\fB+[no]multiline\fR
+.RS 4
+Print 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
+\fBdig\fR
+output\&.
+.RE
+.PP
+\fB+ndots=D\fR
+.RS 4
+Set the number of dots that have to appear in
+\fIname\fR
+to
+\fID\fR
+for it to be considered absolute\&. The default value is that defined using the ndots statement in
+/etc/resolv\&.conf, or 1 if no ndots statement is present\&. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the
+\fBsearch\fR
+or
+\fBdomain\fR
+directive in
+/etc/resolv\&.conf
+if
+\fB+search\fR
+is set\&.
+.RE
+.PP
+\fB+[no]nsid\fR
+.RS 4
+Include an EDNS name server ID request when sending a query\&.
+.RE
+.PP
+\fB+[no]nssearch\fR
+.RS 4
+When this option is set,
+\fBdig\fR
+attempts to find the authoritative name servers for the zone containing the name being looked up and display the SOA record that each name server has for the zone\&.
+.RE
+.PP
+\fB+[no]onesoa\fR
+.RS 4
+Print only one (starting) SOA record when performing an AXFR\&. The default is to print both the starting and ending SOA records\&.
+.RE
+.PP
+\fB+[no]opcode=value\fR
+.RS 4
+Set [restore] the DNS message opcode to the specified value\&. The default value is QUERY (0)\&.
+.RE
+.PP
+\fB+[no]qr\fR
+.RS 4
+Print [do not print] the query as it is sent\&. By default, the query is not printed\&.
+.RE
+.PP
+\fB+[no]question\fR
+.RS 4
+Print [do not print] the question section of a query when an answer is returned\&. The default is to print the question section as a comment\&.
+.RE
+.PP
+\fB+[no]rdflag\fR
+.RS 4
+A synonym for
+\fI+[no]recurse\fR\&.
+.RE
+.PP
+\fB+[no]recurse\fR
+.RS 4
+Toggle the setting of the RD (recursion desired) bit in the query\&. This bit is set by default, which means
+\fBdig\fR
+normally sends recursive queries\&. Recursion is automatically disabled when the
+\fI+nssearch\fR
+or
+\fI+trace\fR
+query options are used\&.
+.RE
+.PP
+\fB+retry=T\fR
+.RS 4
+Sets the number of times to retry UDP queries to server to
+\fIT\fR
+instead of the default, 2\&. Unlike
+\fI+tries\fR, this does not include the initial query\&.
+.RE
+.PP
+\fB+[no]rrcomments\fR
+.RS 4
+Toggle 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\&.
+.RE
+.PP
+\fB+[no]search\fR
+.RS 4
+Use [do not use] the search list defined by the searchlist or domain directive in
+resolv\&.conf
+(if any)\&. The search list is not used by default\&.
+.sp
+\*(Aqndots\*(Aq from
+resolv\&.conf
+(default 1) which may be overridden by
+\fI+ndots\fR
+determines if the name will be treated as relative or not and hence whether a search is eventually performed or not\&.
+.RE
+.PP
+\fB+[no]short\fR
+.RS 4
+Provide a terse answer\&. The default is to print the answer in a verbose form\&.
+.RE
+.PP
+\fB+[no]showsearch\fR
+.RS 4
+Perform [do not perform] a search showing intermediate results\&.
+.RE
+.PP
+\fB+[no]sigchase\fR
+.RS 4
+Chase DNSSEC signature chains\&. Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use
+\fBdelv\fR
+instead\&.
+.RE
+.PP
+\fB+split=W\fR
+.RS 4
+Split long hex\- or base64\-formatted fields in resource records into chunks of
+\fIW\fR
+characters (where
+\fIW\fR
+is rounded up to the nearest multiple of 4)\&.
+\fI+nosplit\fR
+or
+\fI+split=0\fR
+causes fields not to be split at all\&. The default is 56 characters, or 44 characters when multiline mode is active\&.
+.RE
+.PP
+\fB+[no]stats\fR
+.RS 4
+This query option toggles the printing of statistics: when the query was made, the size of the reply and so on\&. The default behavior is to print the query statistics\&.
+.RE
+.PP
+\fB+[no]subnet=addr[/prefix\-length]\fR
+.RS 4
+Send (don\*(Aqt send) an EDNS Client Subnet option with the specified IP address or network prefix\&.
+.sp
+\fBdig +subnet=0\&.0\&.0\&.0/0\fR, or simply
+\fBdig +subnet=0\fR
+for short, sends an EDNS CLIENT\-SUBNET option with an empty address and a source prefix\-length of zero, which signals a resolver that the client\*(Aqs address information must
+\fInot\fR
+be used when resolving this query\&.
+.RE
+.PP
+\fB+[no]tcp\fR
+.RS 4
+Use [do not use] TCP when querying name servers\&. The default behavior is to use UDP unless a type
+any
+or
+ixfr=N
+query is requested, in which case the default is TCP\&. AXFR queries always use TCP\&.
+.RE
+.PP
+\fB+timeout=T\fR
+.RS 4
+Sets the timeout for a query to
+\fIT\fR
+seconds\&. The default timeout is 5 seconds\&. An attempt to set
+\fIT\fR
+to less than 1 will result in a query timeout of 1 second being applied\&.
+.RE
+.PP
+\fB+[no]topdown\fR
+.RS 4
+When chasing DNSSEC signature chains perform a top\-down validation\&. Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use
+\fBdelv\fR
+instead\&.
+.RE
+.PP
+\fB+[no]trace\fR
+.RS 4
+Toggle tracing of the delegation path from the root name servers for the name being looked up\&. Tracing is disabled by default\&. When tracing is enabled,
+\fBdig\fR
+makes iterative queries to resolve the name being looked up\&. It will follow referrals from the root servers, showing the answer from each server that was used to resolve the lookup\&.
+.sp
+If @server is also specified, it affects only the initial query for the root zone name servers\&.
+.sp
+\fB+dnssec\fR
+is also set when +trace is set to better emulate the default queries from a nameserver\&.
+.RE
+.PP
+\fB+tries=T\fR
+.RS 4
+Sets the number of times to try UDP queries to server to
+\fIT\fR
+instead of the default, 3\&. If
+\fIT\fR
+is less than or equal to zero, the number of tries is silently rounded up to 1\&.
+.RE
+.PP
+\fB+trusted\-key=####\fR
+.RS 4
+Specifies a file containing trusted keys to be used with
+\fB+sigchase\fR\&. Each DNSKEY record must be on its own line\&.
+.sp
+If not specified,
+\fBdig\fR
+will look for
+/etc/trusted\-key\&.key
+then
+trusted\-key\&.key
+in the current directory\&.
+.sp
+Requires dig be compiled with \-DDIG_SIGCHASE\&. This feature is deprecated\&. Use
+\fBdelv\fR
+instead\&.
+.RE
+.PP
+\fB+[no]ttlid\fR
+.RS 4
+Display [do not display] the TTL when printing the record\&.
+.RE
+.PP
+\fB+[no]ttlunits\fR
+.RS 4
+Display [do not display] the TTL in friendly human\-readable time units of "s", "m", "h", "d", and "w", representing seconds, minutes, hours, days and weeks\&. Implies +ttlid\&.
+.RE
+.PP
+\fB+[no]unknownformat\fR
+.RS 4
+Print all RDATA in unknown RR type presentation format (RFC 3597)\&. The default is to print RDATA for known types in the type\*(Aqs presentation format\&.
+.RE
+.PP
+\fB+[no]vc\fR
+.RS 4
+Use [do not use] TCP when querying name servers\&. This alternate syntax to
+\fI+[no]tcp\fR
+is provided for backwards compatibility\&. The "vc" stands for "virtual circuit"\&.
+.RE
+.PP
+\fB+[no]zflag\fR
+.RS 4
+Set [do not set] the last unassigned DNS header flag in a DNS query\&. This flag is off by default\&.
+.RE
+.SH "MULTIPLE QUERIES"
+.PP
+The BIND 9 implementation of
+\fBdig \fR
+supports specifying multiple queries on the command line (in addition to supporting the
+\fB\-f\fR
+batch file option)\&. Each of those queries can be supplied with its own set of flags, options and query options\&.
+.PP
+In this case, each
+\fIquery\fR
+argument represent an individual query in the command\-line syntax described above\&. Each consists of any of the standard options and flags, the name to be looked up, an optional query type and class and any query options that should be applied to that query\&.
+.PP
+A global set of query options, which should be applied to all queries, can also be supplied\&. These global query options must precede the first tuple of name, class, type, options, flags, and query options supplied on the command line\&. Any global query options (except the
+\fB+[no]cmd\fR
+option) can be overridden by a query\-specific set of query options\&. For example:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+dig +qr www\&.isc\&.org any \-x 127\&.0\&.0\&.1 isc\&.org ns +noqr
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+shows how
+\fBdig\fR
+could be used from the command line to make three lookups: an ANY query for
+www\&.isc\&.org, a reverse lookup of 127\&.0\&.0\&.1 and a query for the NS records of
+isc\&.org\&. A global query option of
+\fI+qr\fR
+is applied, so that
+\fBdig\fR
+shows the initial query it made for each lookup\&. The final query has a local query option of
+\fI+noqr\fR
+which means that
+\fBdig\fR
+will not print the initial query when it looks up the NS records for
+isc\&.org\&.
+.SH "IDN SUPPORT"
+.PP
+If
+\fBdig\fR
+has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names\&.
+\fBdig\fR
+appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server\&. If you\*(Aqd like to turn off the IDN support for some reason, use parameters
+\fI+noidnin\fR
+and
+\fI+noidnout\fR\&.
+.SH "FILES"
+.PP
+/etc/resolv\&.conf
+.PP
+${HOME}/\&.digrc
+.SH "SEE ALSO"
+.PP
+\fBdelv\fR(1),
+\fBhost\fR(1),
+\fBnamed\fR(8),
+\fBdnssec-keygen\fR(8),
+RFC 1035\&.
+.SH "BUGS"
+.PP
+There are probably too many query options\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
new file mode 100644
index 0000000..39f74be
--- /dev/null
+++ b/bin/dig/dig.c
@@ -0,0 +1,2293 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <isc/app.h>
+#include <isc/netaddr.h>
+#include <isc/parseint.h>
+#include <isc/platform.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/util.h>
+
+#include <pk11/site.h>
+
+#include <dns/byaddr.h>
+#include <dns/fixedname.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataset.h>
+#include <dns/rdatatype.h>
+#include <dns/rdataclass.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+
+#include <dig/dig.h>
+
+#define ADD_STRING(b, s) { \
+ if (strlen(s) >= isc_buffer_availablelength(b)) \
+ return (ISC_R_NOSPACE); \
+ else \
+ isc_buffer_putstr(b, s); \
+}
+
+#define DIG_MAX_ADDRESSES 20
+
+dig_lookup_t *default_lookup = NULL;
+
+static char *batchname = NULL;
+static FILE *batchfp = NULL;
+static char *argv0;
+static int addresscount = 0;
+
+static char domainopt[DNS_NAME_MAXTEXT];
+static char hexcookie[81];
+
+static bool short_form = false, printcmd = true,
+ ip6_int = false, plusquest = false, pluscomm = false,
+ multiline = false, nottl = false, noclass = false,
+ onesoa = false, use_usec = false,
+ nocrypto = false, ttlunits = false,
+ ipv4only = false, ipv6only = false;
+static uint32_t splitwidth = 0xffffffff;
+
+/*% rrcomments are neither explicitly enabled nor disabled by default */
+static int rrcomments = 0;
+
+/*% opcode text */
+static const char * const opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static const char *
+rcode_totext(dns_rcode_t rcode) {
+ static char buf[64];
+ isc_buffer_t b;
+ isc_result_t result;
+
+ memset(buf, 0, sizeof(buf));
+ isc_buffer_init(&b, buf + 1, sizeof(buf) - 2);
+ result = dns_rcode_totext(rcode, &b);
+ RUNTIME_CHECK(result == ISC_R_SUCCESS);
+ if (strspn(buf + 1, "0123456789") == strlen(buf + 1)) {
+ buf[0] = '?';
+ return(buf);
+ }
+ return (buf + 1);
+}
+
+/*% print usage */
+static void
+print_usage(FILE *fp) {
+ fputs(
+"Usage: dig [@global-server] [domain] [q-type] [q-class] {q-opt}\n"
+" {global-d-opt} host [@local-server] {local-d-opt}\n"
+" [ host [@local-server] {local-d-opt} [...]]\n", fp);
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+usage(void) {
+ print_usage(stderr);
+ fputs("\nUse \"dig -h\" (or \"dig -h | more\") "
+ "for complete list of options\n", stderr);
+ exit(1);
+}
+
+/*% version */
+static void
+version(void) {
+ fputs("DiG " VERSION "\n", stderr);
+}
+
+/*% help */
+static void
+help(void) {
+ print_usage(stdout);
+ fputs(
+"Where: domain is in the Domain Name System\n"
+" q-class is one of (in,hs,ch,...) [default: in]\n"
+" q-type is one of (a,any,mx,ns,soa,hinfo,axfr,txt,...) [default:a]\n"
+" (Use ixfr=version for type ixfr)\n"
+" q-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"
+" -c class (specify query class)\n"
+" -f filename (batch mode)\n"
+" -i (use IP6.INT for IPv6 reverse lookups)\n"
+" -k keyfile (specify tsig key file)\n"
+" -m (enable memory usage debugging)\n"
+" -p port (specify port number)\n"
+" -q name (specify query name)\n"
+" -t type (specify query type)\n"
+" -u (display times in usec instead of msec)\n"
+" -x dot-notation (shortcut for reverse lookups)\n"
+" -y [hmac:]name:key (specify named base64 tsig key)\n"
+" d-opt is of the form +keyword[=value], where keyword is:\n"
+" +[no]aaflag (Set AA flag in query (+[no]aaflag))\n"
+" +[no]aaonly (Set AA flag in query (+[no]aaflag))\n"
+" +[no]additional (Control display of additional section)\n"
+" +[no]adflag (Set AD flag in query (default on))\n"
+" +[no]all (Set or clear all display flags)\n"
+" +[no]answer (Control display of answer section)\n"
+" +[no]authority (Control display of authority section)\n"
+" +[no]badcookie (Retry BADCOOKIE responses)\n"
+" +[no]besteffort (Try to parse even illegal messages)\n"
+" +bufsize=### (Set EDNS0 Max UDP packet size)\n"
+" +[no]cdflag (Set checking disabled flag in query)\n"
+" +[no]class (Control display of class in records)\n"
+" +[no]cmd (Control display of command line)\n"
+" +[no]comments (Control display of comment lines)\n"
+" +[no]cookie (Add a COOKIE option to the request)\n"
+" +[no]crypto (Control display of cryptographic "
+ "fields in records)\n"
+" +[no]defname (Use search list (+[no]search))\n"
+" +[no]dnssec (Request DNSSEC records)\n"
+" +domain=### (Set default domainname)\n"
+" +[no]dscp[=###] (Set the DSCP value to ### [0..63])\n"
+" +[no]edns[=###] (Set EDNS version) [0]\n"
+" +ednsflags=### (Set EDNS flag bits)\n"
+" +[no]ednsnegotiation (Set EDNS version negotiation)\n"
+" +ednsopt=###[:value] (Send specified EDNS option)\n"
+" +noednsopt (Clear list of +ednsopt options)\n"
+" +[no]expire (Request time to expire)\n"
+" +[no]fail (Don't try next server on SERVFAIL)\n"
+" +[no]header-only (Send query without a question section)\n"
+" +[no]identify (ID responders in short answers)\n"
+" +[no]idnin (Parse IDN names)\n"
+" +[no]idnout (Convert IDN response)\n"
+" +[no]ignore (Don't revert to TCP for TC responses.)\n"
+" +[no]keepopen (Keep the TCP socket open between queries)\n"
+" +[no]mapped (Allow mapped IPv4 over IPv6)\n"
+" +[no]multiline (Print records in an expanded format)\n"
+" +ndots=### (Set search NDOTS value)\n"
+" +[no]nsid (Request Name Server ID)\n"
+" +[no]nssearch (Search all authoritative nameservers)\n"
+" +[no]onesoa (AXFR prints only one soa record)\n"
+" +[no]opcode=### (Set the opcode of the request)\n"
+" +[no]qr (Print question before sending)\n"
+" +[no]question (Control display of question section)\n"
+" +[no]rdflag (Recursive mode (+[no]recurse))\n"
+" +[no]recurse (Recursive mode (+[no]rdflag))\n"
+" +retry=### (Set number of UDP retries) [2]\n"
+" +[no]rrcomments (Control display of per-record "
+ "comments)\n"
+" +[no]search (Set whether to use searchlist)\n"
+" +[no]short (Display nothing except short\n"
+" form of answer)\n"
+" +[no]showsearch (Search with intermediate results)\n"
+#ifdef DIG_SIGCHASE
+" +[no]sigchase (Chase DNSSEC signatures)\n"
+#endif
+" +[no]split=## (Split hex/base64 fields into chunks)\n"
+" +[no]stats (Control display of statistics)\n"
+" +subnet=addr (Set edns-client-subnet option)\n"
+" +[no]tcp (TCP mode (+[no]vc))\n"
+" +timeout=### (Set query timeout) [5]\n"
+#if defined(DIG_SIGCHASE) && DIG_SIGCHASE_TD
+" +[no]topdown (Do +sigchase in top-down mode)\n"
+#endif
+" +[no]trace (Trace delegation down from root [+dnssec])\n"
+#ifdef DIG_SIGCHASE
+" +trusted-key=#### (Trusted Key to use with +sigchase)\n"
+#endif
+" +tries=### (Set number of UDP attempts) [3]\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]vc (TCP mode (+[no]tcp))\n"
+" +[no]zflag (Set Z flag in query)\n"
+" global d-opts and servers (before host name) affect all queries.\n"
+" local d-opts and servers (after host name) affect only that lookup.\n"
+" -h (print help and exit)\n"
+" -v (print version and exit)\n",
+ stdout);
+}
+
+/*%
+ * Callback from dighost.c to print the received message.
+ */
+static void
+received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ uint64_t diff;
+ time_t tnow;
+ struct tm tmnow;
+#ifdef WIN32
+ wchar_t time_str[100];
+#else
+ char time_str[100];
+#endif
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+
+ if (query->lookup->stats && !short_form) {
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ if (use_usec)
+ printf(";; Query time: %ld usec\n", (long) diff);
+ else
+ printf(";; Query time: %ld msec\n", (long) diff / 1000);
+ printf(";; SERVER: %s(%s)\n", fromtext, query->servname);
+ time(&tnow);
+#if defined(ISC_PLATFORM_USETHREADS) && !defined(WIN32)
+ (void)localtime_r(&tnow, &tmnow);
+#else
+ tmnow = *localtime(&tnow);
+#endif
+
+#ifdef WIN32
+ /*
+ * On Windows, time zone name ("%Z") may be a localized
+ * wide-character string, which strftime() handles incorrectly.
+ */
+ if (wcsftime(time_str, sizeof(time_str)/sizeof(time_str[0]),
+ L"%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U)
+ printf(";; WHEN: %ls\n", time_str);
+#else
+ if (strftime(time_str, sizeof(time_str),
+ "%a %b %d %H:%M:%S %Z %Y", &tmnow) > 0U)
+ printf(";; WHEN: %s\n", time_str);
+#endif
+ if (query->lookup->doing_xfr) {
+ printf(";; XFR size: %u records (messages %u, "
+ "bytes %" PRIu64 ")\n",
+ query->rr_count, query->msg_count,
+ query->byte_count);
+ } else {
+ printf(";; MSG SIZE rcvd: %u\n", bytes);
+ }
+ if (tsigkey != NULL) {
+ if (!validated)
+ puts(";; WARNING -- Some TSIG could not "
+ "be validated");
+ }
+ if ((tsigkey == NULL) && (keysecret[0] != 0)) {
+ puts(";; WARNING -- TSIG key was not used.");
+ }
+ puts("");
+ } else if (query->lookup->identify && !short_form) {
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ if (use_usec)
+ printf(";; Received %" PRIu64 " bytes "
+ "from %s(%s) in %ld us\n\n",
+ query->lookup->doing_xfr
+ ? query->byte_count
+ : (uint64_t)bytes,
+ fromtext, query->userarg, (long) diff);
+ else
+ printf(";; Received %" PRIu64 " bytes "
+ "from %s(%s) in %ld ms\n\n",
+ query->lookup->doing_xfr
+ ? query->byte_count
+ : (uint64_t)bytes,
+ fromtext, query->userarg, (long) diff / 1000);
+ }
+}
+
+/*
+ * Callback from dighost.c to print that it is trying a server.
+ * Not used in dig.
+ * XXX print_trying
+ */
+static void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(frm);
+ UNUSED(lookup);
+}
+
+/*%
+ * Internal print routine used to print short form replies.
+ */
+static isc_result_t
+say_message(dns_rdata_t *rdata, dig_query_t *query, isc_buffer_t *buf) {
+ isc_result_t result;
+ uint64_t diff;
+ char store[sizeof(" in 18446744073709551616 us.")];
+ unsigned int styleflags = 0;
+
+ if (query->lookup->trace || query->lookup->ns_search_only) {
+ result = dns_rdatatype_totext(rdata->type, buf);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ ADD_STRING(buf, " ");
+ }
+
+ /* Turn on rrcomments if explicitly enabled */
+ if (rrcomments > 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ if (nocrypto)
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ if (query->lookup->print_unknown_format)
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ result = dns_rdata_tofmttext(rdata, NULL, styleflags, 0,
+ splitwidth, " ", buf);
+ if (result == ISC_R_NOSPACE)
+ return (result);
+ check_result(result, "dns_rdata_totext");
+ if (query->lookup->identify) {
+
+ diff = isc_time_microdiff(&query->time_recv, &query->time_sent);
+ ADD_STRING(buf, " from server ");
+ ADD_STRING(buf, query->servname);
+ if (use_usec)
+ snprintf(store, sizeof(store), " in %" PRIu64 " us.", diff);
+ else
+ snprintf(store, sizeof(store), " in %" PRIu64 " ms.", diff / 1000);
+ ADD_STRING(buf, store);
+ }
+ ADD_STRING(buf, "\n");
+ return (ISC_R_SUCCESS);
+}
+
+/*%
+ * short_form message print handler. Calls above say_message()
+ */
+static isc_result_t
+short_answer(dns_message_t *msg, dns_messagetextflag_t flags,
+ isc_buffer_t *buf, dig_query_t *query)
+{
+ dns_name_t *name;
+ dns_rdataset_t *rdataset;
+ isc_result_t result, loopresult;
+ dns_name_t empty_name;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ UNUSED(flags);
+
+ dns_name_init(&empty_name, NULL);
+ result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, 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 = say_message(&rdata, query,
+ buf);
+ if (result == ISC_R_NOSPACE)
+ return (result);
+ check_result(result, "say_message");
+ loopresult = dns_rdataset_next(rdataset);
+ dns_rdata_reset(&rdata);
+ }
+ }
+ result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+#ifdef DIG_SIGCHASE
+static isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ isc_result_t result;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+
+ if (rdataset == NULL || owner_name == NULL || target == NULL)
+ return(false);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (ttlunits)
+ styleflags |= DNS_STYLEFLAG_TTL_UNITS;
+ if (nottl)
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ if (noclass)
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ if (nocrypto)
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ /* Turn on rrcomments if explicitly enabled */
+ if (rrcomments > 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ if (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 if not explicitly disabled */
+ if (rrcomments >= 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 24, 32, 80, 8,
+ splitwidth, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 32, 40, 80, 8,
+ splitwidth, mctx);
+ else
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 32, 40, 48, 80, 8,
+ splitwidth, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ result = dns_master_rdatasettotext(owner_name, rdataset, style, target);
+
+ if (style != NULL)
+ dns_master_styledestroy(&style, mctx);
+
+ return(result);
+}
+#endif
+
+static bool
+isdotlocal(dns_message_t *msg) {
+ isc_result_t result;
+ static unsigned char local_ndata[] = { "\005local\0" };
+ static unsigned char local_offsets[] = { 0, 6 };
+ static dns_name_t local =
+ DNS_NAME_INITABSOLUTE(local_ndata, local_offsets);
+
+ for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(msg, DNS_SECTION_QUESTION))
+ {
+ dns_name_t *name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_QUESTION, &name);
+ if (dns_name_issubdomain(name, &local))
+ return (true);
+ }
+ return (false);
+}
+
+/*
+ * Callback from dighost.c to print the reply from a server
+ */
+static isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, bool headers) {
+ isc_result_t result;
+ dns_messagetextflag_t flags;
+ isc_buffer_t *buf = NULL;
+ unsigned int len = OUTPUTBUF;
+ dns_master_style_t *style = NULL;
+ unsigned int styleflags = 0;
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (query->lookup->comments)
+ styleflags |= DNS_STYLEFLAG_COMMENT;
+ if (query->lookup->print_unknown_format)
+ styleflags |= DNS_STYLEFLAG_UNKNOWNFORMAT;
+ /* Turn on rrcomments if explicitly enabled */
+ if (rrcomments > 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ if (ttlunits)
+ styleflags |= DNS_STYLEFLAG_TTL_UNITS;
+ if (nottl)
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ if (noclass)
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ if (nocrypto)
+ styleflags |= DNS_STYLEFLAG_NOCRYPTO;
+ if (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;
+ /* Turn on rrcomments unless explicitly disabled */
+ if (rrcomments >= 0)
+ styleflags |= DNS_STYLEFLAG_RRCOMMENT;
+ }
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 24, 32, 80, 8,
+ splitwidth, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 24, 32, 40, 80, 8,
+ splitwidth, mctx);
+ else
+ result = dns_master_stylecreate2(&style, styleflags,
+ 24, 32, 40, 48, 80, 8,
+ splitwidth, mctx);
+ check_result(result, "dns_master_stylecreate");
+
+ if (query->lookup->cmdline[0] != 0) {
+ if (!short_form)
+ fputs(query->lookup->cmdline, stdout);
+ query->lookup->cmdline[0]=0;
+ }
+ debug("printmessage(%s %s %s)", headers ? "headers" : "noheaders",
+ query->lookup->comments ? "comments" : "nocomments",
+ short_form ? "short_form" : "long_form");
+
+ flags = 0;
+ if (!headers) {
+ flags |= DNS_MESSAGETEXTFLAG_NOHEADERS;
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+ }
+ if (onesoa && query->lookup->rdtype == dns_rdatatype_axfr)
+ flags |= (query->msg_count == 0) ? DNS_MESSAGETEXTFLAG_ONESOA :
+ DNS_MESSAGETEXTFLAG_OMITSOA;
+ if (!query->lookup->comments)
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+
+ result = isc_buffer_allocate(mctx, &buf, len);
+ check_result(result, "isc_buffer_allocate");
+
+ if (query->lookup->comments && !short_form) {
+ if (query->lookup->cmdline[0] != 0)
+ printf("; %s\n", query->lookup->cmdline);
+ if (msg == query->lookup->sendmsg)
+ printf(";; Sending:\n");
+ else
+ printf(";; Got answer:\n");
+
+ if (headers) {
+ if (isdotlocal(msg)) {
+ printf(";; WARNING: .local is reserved for "
+ "Multicast DNS\n;; You are currently "
+ "testing what happens when an mDNS "
+ "query is leaked to DNS\n");
+ }
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, "
+ "id: %u\n",
+ opcodetext[msg->opcode],
+ rcode_totext(msg->rcode),
+ msg->id);
+ printf(";; flags:");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0)
+ printf(" qr");
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0)
+ printf(" aa");
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0)
+ printf(" tc");
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0)
+ printf(" rd");
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0)
+ printf(" ra");
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0)
+ printf(" ad");
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0)
+ printf(" cd");
+ if ((msg->flags & 0x0040U) != 0)
+ printf("; MBZ: 0x4");
+
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ msg->counts[DNS_SECTION_QUESTION],
+ msg->counts[DNS_SECTION_ANSWER],
+ msg->counts[DNS_SECTION_AUTHORITY],
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+
+ if (msg != query->lookup->sendmsg &&
+ (msg->flags & DNS_MESSAGEFLAG_RD) != 0 &&
+ (msg->flags & DNS_MESSAGEFLAG_RA) == 0)
+ printf(";; WARNING: recursion requested "
+ "but not available\n");
+ }
+ if (msg != query->lookup->sendmsg &&
+ query->lookup->edns != -1 && msg->opt == NULL &&
+ (msg->rcode == dns_rcode_formerr ||
+ msg->rcode == dns_rcode_notimp))
+ printf("\n;; WARNING: EDNS query returned status "
+ "%s - retry with '%s+noedns'\n",
+ rcode_totext(msg->rcode),
+ query->lookup->dnssec ? "+nodnssec ": "");
+ if (msg != query->lookup->sendmsg && extrabytes != 0U)
+ printf(";; WARNING: Message has %u extra byte%s at "
+ "end\n", extrabytes, extrabytes != 0 ? "s" : "");
+ }
+
+repopulate_buffer:
+
+ if (query->lookup->comments && headers && !short_form) {
+ result = dns_message_pseudosectiontotext(msg,
+ DNS_PSEUDOSECTION_OPT,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE) {
+buftoosmall:
+ len += OUTPUTBUF;
+ isc_buffer_free(&buf);
+ result = isc_buffer_allocate(mctx, &buf, len);
+ if (result == ISC_R_SUCCESS)
+ goto repopulate_buffer;
+ else
+ goto cleanup;
+ }
+ check_result(result,
+ "dns_message_pseudosectiontotext");
+ }
+
+ if (query->lookup->section_question && headers) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_QUESTION,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ }
+ }
+ if (query->lookup->section_answer) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_ANSWER,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ } else {
+ result = short_answer(msg, flags, buf, query);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "short_answer");
+ }
+ }
+ if (query->lookup->section_authority) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_AUTHORITY,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ }
+ }
+ if (query->lookup->section_additional) {
+ if (!short_form) {
+ result = dns_message_sectiontotext(msg,
+ DNS_SECTION_ADDITIONAL,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result, "dns_message_sectiontotext");
+ /*
+ * Only print the signature on the first record.
+ */
+ if (headers) {
+ result = dns_message_pseudosectiontotext(
+ msg,
+ DNS_PSEUDOSECTION_TSIG,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result,
+ "dns_message_pseudosectiontotext");
+ result = dns_message_pseudosectiontotext(
+ msg,
+ DNS_PSEUDOSECTION_SIG0,
+ style, flags, buf);
+ if (result == ISC_R_NOSPACE)
+ goto buftoosmall;
+ check_result(result,
+ "dns_message_pseudosectiontotext");
+ }
+ }
+ }
+
+ if (headers && query->lookup->comments && !short_form)
+ printf("\n");
+
+ printf("%.*s", (int)isc_buffer_usedlength(buf),
+ (char *)isc_buffer_base(buf));
+ isc_buffer_free(&buf);
+
+cleanup:
+ if (style != NULL)
+ dns_master_styledestroy(&style, mctx);
+ return (result);
+}
+
+/*%
+ * print the greeting message when the program first starts up.
+ */
+static void
+printgreeting(int argc, char **argv, dig_lookup_t *lookup) {
+ int i;
+ static bool first = true;
+ char append[MXNAME];
+
+ if (printcmd) {
+ snprintf(lookup->cmdline, sizeof(lookup->cmdline),
+ "%s; <<>> DiG " VERSION " <<>>",
+ first?"\n":"");
+ i = 1;
+ while (i < argc) {
+ snprintf(append, sizeof(append), " %s", argv[i++]);
+ strlcat(lookup->cmdline, append,
+ sizeof(lookup->cmdline));
+ }
+ strlcat(lookup->cmdline, "\n", sizeof(lookup->cmdline));
+ if (first && addresscount != 0) {
+ snprintf(append, sizeof(append),
+ "; (%d server%s found)\n",
+ addresscount,
+ addresscount > 1 ? "s" : "");
+ strlcat(lookup->cmdline, append,
+ sizeof(lookup->cmdline));
+ }
+ if (first) {
+ snprintf(append, sizeof(append),
+ ";; global options:%s%s\n",
+ short_form ? " +short" : "",
+ printcmd ? " +cmd" : "");
+ first = false;
+ strlcat(lookup->cmdline, append,
+ sizeof(lookup->cmdline));
+ }
+ }
+}
+
+/*%
+ * We're not using isc_commandline_parse() here since the command line
+ * syntax of dig is quite a bit different from that which can be described
+ * by that routine.
+ * XXX doc options
+ */
+
+static void
+plus_option(const char *option, bool is_batchfile,
+ dig_lookup_t *lookup)
+{
+ isc_result_t result;
+ char option_store[256];
+ char *cmd, *value, *ptr, *code;
+ uint32_t num;
+ bool state = true;
+ size_t n;
+
+ strlcpy(option_store, option, sizeof(option_store));
+ ptr = option_store;
+ cmd = next_token(&ptr, "=");
+ if (cmd == NULL) {
+ printf(";; Invalid option %s\n", option_store);
+ return;
+ }
+ value = ptr;
+ if (strncasecmp(cmd, "no", 2)==0) {
+ cmd += 2;
+ state = false;
+ }
+
+#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)
+
+ switch (cmd[0]) {
+ case 'a':
+ switch (cmd[1]) {
+ case 'a': /* aaonly / aaflag */
+ FULLCHECK2("aaonly", "aaflag");
+ lookup->aaonly = state;
+ break;
+ case 'd':
+ switch (cmd[2]) {
+ case 'd': /* additional */
+ FULLCHECK("additional");
+ lookup->section_additional = state;
+ break;
+ case 'f': /* adflag */
+ case '\0': /* +ad is a synonym for +adflag */
+ FULLCHECK("adflag");
+ lookup->adflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* all */
+ FULLCHECK("all");
+ lookup->section_question = state;
+ lookup->section_authority = state;
+ lookup->section_answer = state;
+ lookup->section_additional = state;
+ lookup->comments = state;
+ lookup->stats = state;
+ printcmd = state;
+ break;
+ case 'n': /* answer */
+ FULLCHECK("answer");
+ lookup->section_answer = state;
+ break;
+ case 'u': /* authority */
+ FULLCHECK("authority");
+ lookup->section_authority = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'b':
+ switch (cmd[1]) {
+ case 'a':/* badcookie */
+ FULLCHECK("badcookie");
+ lookup->badcookie = state;
+ break;
+ case 'e':/* besteffort */
+ FULLCHECK("besteffort");
+ lookup->besteffort = state;
+ break;
+ case 'u':/* bufsize */
+ FULLCHECK("bufsize");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ result = parse_uint(&num, value, COMMSIZE,
+ "buffer size");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse buffer size");
+ lookup->udpsize = num;
+ 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");
+ lookup->cdflag = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'l': /* class */
+ /* keep +cl for backwards compatibility */
+ FULLCHECK2("cl", "class");
+ noclass = !state;
+ break;
+ case 'm': /* cmd */
+ FULLCHECK("cmd");
+ printcmd = state;
+ break;
+ case 'o': /* comments */
+ switch (cmd[2]) {
+ case 'm':
+ FULLCHECK("comments");
+ lookup->comments = state;
+ if (lookup == default_lookup)
+ pluscomm = state;
+ break;
+ case 'o': /* cookie */
+ FULLCHECK("cookie");
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ lookup->sendcookie = state;
+ if (value != NULL) {
+ n = strlcpy(hexcookie, value,
+ sizeof(hexcookie));
+ if (n >= sizeof(hexcookie))
+ fatal("COOKIE data too large");
+ lookup->cookie = hexcookie;
+ } else
+ lookup->cookie = NULL;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ FULLCHECK("crypto");
+ nocrypto = !state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'd':
+ switch (cmd[1]) {
+ case 'e': /* defname */
+ FULLCHECK("defname");
+ if (!lookup->trace) {
+ usesearch = state;
+ }
+ break;
+ case 'n': /* dnssec */
+ FULLCHECK("dnssec");
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ lookup->dnssec = state;
+ break;
+ case 'o': /* domain */
+ FULLCHECK("domain");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ strlcpy(domainopt, value, sizeof(domainopt));
+ break;
+ case 's': /* dscp */
+ FULLCHECK("dscp");
+ if (!state) {
+ lookup->dscp = -1;
+ break;
+ }
+ if (value == NULL)
+ goto need_value;
+ result = parse_uint(&num, value, 0x3f, "DSCP");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse DSCP value");
+ lookup->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) {
+ lookup->edns = -1;
+ break;
+ }
+ if (value == NULL) {
+ lookup->edns = 0;
+ break;
+ }
+ result = parse_uint(&num,
+ value,
+ 255,
+ "edns");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse "
+ "edns");
+ lookup->edns = num;
+ break;
+ case 'f':
+ FULLCHECK("ednsflags");
+ if (!state) {
+ lookup->ednsflags = 0;
+ break;
+ }
+ if (value == NULL) {
+ lookup->ednsflags = 0;
+ break;
+ }
+ result = parse_xint(&num,
+ value,
+ 0xffff,
+ "ednsflags");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse "
+ "ednsflags");
+ lookup->ednsflags = num;
+ break;
+ case 'n':
+ FULLCHECK("ednsnegotiation");
+ lookup->ednsneg = state;
+ break;
+ case 'o':
+ FULLCHECK("ednsopt");
+ if (!state) {
+ lookup->ednsoptscnt = 0;
+ break;
+ }
+ code = NULL;
+ if (value != NULL) {
+ code = strtok(value,
+ ":");
+ }
+ if (code == NULL) {
+ fatal("ednsopt no "
+ "code point "
+ "specified");
+ }
+ value = strtok(NULL, "\0");
+ save_opt(lookup, code, value);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'x':
+ FULLCHECK("expire");
+ lookup->expire = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'f': /* fail */
+ FULLCHECK("fail");
+ lookup->servfail_stops = state;
+ break;
+ case 'h':
+ FULLCHECK("header-only");
+ lookup->header_only = state;
+ break;
+ case 'i':
+ switch (cmd[1]) {
+ case 'd': /* identify */
+ switch (cmd[2]) {
+ case 'e':
+ FULLCHECK("identify");
+ lookup->identify = state;
+ break;
+ case 'n':
+ switch (cmd[3]) {
+ case 'i':
+ FULLCHECK("idnin");
+#ifndef WITH_IDN_SUPPORT
+ fprintf(stderr, ";; IDN input support"
+ " not enabled\n");
+#else
+ lookup->idnin = state;
+#endif
+ break;
+ case 'o':
+ FULLCHECK("idnout");
+#ifndef WITH_IDN_OUT_SUPPORT
+ fprintf(stderr, ";; IDN output support"
+ " not enabled\n");
+#else
+ lookup->idnout = state;
+#endif
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'g': /* ignore */
+ default: /*
+ * Inherits default for compatibility (+[no]i*).
+ */
+ FULLCHECK("ignore");
+ lookup->ignore = state;
+ }
+ break;
+ case 'k':
+ FULLCHECK("keepopen");
+ keep_open = state;
+ break;
+ case 'm': /* multiline */
+ switch (cmd[1]) {
+ case 'a':
+ FULLCHECK("mapped");
+ lookup->mapped = state;
+ break;
+ case 'u':
+ FULLCHECK("multiline");
+ multiline = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'n':
+ switch (cmd[1]) {
+ case 'd': /* ndots */
+ FULLCHECK("ndots");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ result = parse_uint(&num, value, MAXNDOTS, "ndots");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse ndots");
+ ndots = num;
+ break;
+ case 's':
+ switch (cmd[2]) {
+ case 'i': /* nsid */
+ FULLCHECK("nsid");
+ if (state && lookup->edns == -1)
+ lookup->edns = 0;
+ lookup->nsid = state;
+ break;
+ case 's': /* nssearch */
+ FULLCHECK("nssearch");
+ lookup->ns_search_only = state;
+ if (state) {
+ lookup->trace_root = true;
+ lookup->recurse = true;
+ lookup->identify = true;
+ lookup->stats = false;
+ lookup->comments = false;
+ lookup->section_additional = false;
+ lookup->section_authority = false;
+ lookup->section_question = false;
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = true;
+ short_form = true;
+ rrcomments = 0;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'o':
+ switch (cmd[1]) {
+ case 'n':
+ FULLCHECK("onesoa");
+ onesoa = state;
+ break;
+ case 'p':
+ FULLCHECK("opcode");
+ if (!state) {
+ lookup->opcode = 0; /* default - query */
+ break;
+ }
+ if (value == NULL)
+ goto need_value;
+ for (num = 0;
+ num < sizeof(opcodetext)/sizeof(opcodetext[0]);
+ num++) {
+ if (strcasecmp(opcodetext[num], value) == 0)
+ break;
+ }
+ if (num < 16) {
+ lookup->opcode = (dns_opcode_t)num;
+ break;
+ }
+ result = parse_uint(&num, value, 15, "opcode");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse opcode");
+ lookup->opcode = (dns_opcode_t)num;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'q':
+ switch (cmd[1]) {
+ case 'r': /* qr */
+ FULLCHECK("qr");
+ qr = state;
+ break;
+ case 'u': /* question */
+ FULLCHECK("question");
+ lookup->section_question = state;
+ if (lookup == default_lookup)
+ plusquest = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r':
+ switch (cmd[1]) {
+ case 'd': /* rdflag */
+ FULLCHECK("rdflag");
+ lookup->recurse = state;
+ break;
+ case 'e':
+ switch (cmd[2]) {
+ case 'c': /* recurse */
+ FULLCHECK("recurse");
+ lookup->recurse = state;
+ break;
+ case 't': /* retry / retries */
+ FULLCHECK2("retry", "retries");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ result = parse_uint(&lookup->retries, value,
+ MAXTRIES - 1, "retries");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse retries");
+ lookup->retries++;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'r': /* rrcomments */
+ FULLCHECK("rrcomments");
+ rrcomments = state ? 1 : -1;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 's':
+ switch (cmd[1]) {
+ case 'e': /* search */
+ FULLCHECK("search");
+ if (!lookup->trace) {
+ usesearch = state;
+ }
+ break;
+ case 'h':
+ if (cmd[2] != 'o')
+ goto invalid_option;
+ switch (cmd[3]) {
+ case 'r': /* short */
+ FULLCHECK("short");
+ short_form = state;
+ if (state) {
+ printcmd = false;
+ lookup->section_additional = false;
+ lookup->section_answer = true;
+ lookup->section_authority = false;
+ lookup->section_question = false;
+ lookup->comments = false;
+ lookup->stats = false;
+ rrcomments = -1;
+ }
+ break;
+ case 'w': /* showsearch */
+ FULLCHECK("showsearch");
+ if (!lookup->trace) {
+ showsearch = state;
+ usesearch = state;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+#ifdef DIG_SIGCHASE
+ case 'i': /* sigchase */
+ FULLCHECK("sigchase");
+ lookup->sigchase = state;
+ if (lookup->sigchase)
+ lookup->dnssec = true;
+ break;
+#endif
+ case 'p': /* split */
+ FULLCHECK("split");
+ if (value != NULL && !state)
+ goto invalid_option;
+ if (!state) {
+ splitwidth = 0;
+ break;
+ } else if (value == NULL)
+ break;
+
+ result = parse_uint(&splitwidth, value,
+ 1023, "split");
+ if ((splitwidth % 4) != 0U) {
+ splitwidth = ((splitwidth + 3) / 4) * 4;
+ fprintf(stderr, ";; Warning, split must be "
+ "a multiple of 4; adjusting "
+ "to %u\n", 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 (splitwidth)
+ splitwidth += 3;
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse split");
+ break;
+ case 't': /* stats */
+ FULLCHECK("stats");
+ lookup->stats = state;
+ break;
+ case 'u': /* subnet */
+ FULLCHECK("subnet");
+ if (state && value == NULL)
+ goto need_value;
+ if (!state) {
+ if (lookup->ecs_addr != NULL) {
+ isc_mem_free(mctx, lookup->ecs_addr);
+ lookup->ecs_addr = NULL;
+ }
+ break;
+ }
+ if (lookup->edns == -1)
+ lookup->edns = 0;
+ if (lookup->ecs_addr != NULL) {
+ isc_mem_free(mctx, lookup->ecs_addr);
+ lookup->ecs_addr = NULL;
+ }
+ result = parse_netprefix(&lookup->ecs_addr, value);
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse client");
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ FULLCHECK("tcp");
+ if (!is_batchfile) {
+ lookup->tcp_mode = state;
+ lookup->tcp_mode_set = true;
+ }
+ break;
+ case 'i': /* timeout */
+ FULLCHECK("timeout");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ result = parse_uint(&timeout, value, MAXTIMEOUT,
+ "timeout");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse timeout");
+ if (timeout == 0)
+ timeout = 1;
+ break;
+#if DIG_SIGCHASE_TD
+ case 'o': /* topdown */
+ FULLCHECK("topdown");
+ lookup->do_topdown = state;
+ break;
+#endif
+ case 'r':
+ switch (cmd[2]) {
+ case 'a': /* trace */
+ FULLCHECK("trace");
+ lookup->trace = state;
+ lookup->trace_root = state;
+ if (state) {
+ lookup->recurse = false;
+ lookup->identify = true;
+ lookup->comments = false;
+ rrcomments = 0;
+ lookup->stats = false;
+ lookup->section_additional = false;
+ lookup->section_authority = true;
+ lookup->section_question = false;
+ lookup->dnssec = true;
+ lookup->sendcookie = true;
+ usesearch = false;
+ }
+ break;
+ case 'i': /* tries */
+ FULLCHECK("tries");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ result = parse_uint(&lookup->retries, value,
+ MAXTRIES, "tries");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse tries");
+ if (lookup->retries == 0)
+ lookup->retries = 1;
+ break;
+#ifdef DIG_SIGCHASE
+ case 'u': /* trusted-key */
+ FULLCHECK("trusted-key");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ n = strlcpy(trustedkey, ptr,
+ sizeof(trustedkey));
+ if (n >= sizeof(trustedkey))
+ fatal("trusted key too large");
+ break;
+#endif
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[2]) {
+ case 'l':
+ switch (cmd[3]) {
+ case 0:
+ case 'i': /* ttlid */
+ FULLCHECK2("ttl", "ttlid");
+ nottl = !state;
+ break;
+ case 'u': /* ttlunits */
+ FULLCHECK("ttlunits");
+ nottl = false;
+ ttlunits = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'u':
+ FULLCHECK("unknownformat");
+ lookup->print_unknown_format = state;
+ break;
+ case 'v':
+ FULLCHECK("vc");
+ if (!is_batchfile) {
+ lookup->tcp_mode = state;
+ lookup->tcp_mode_set = true;
+ }
+ break;
+ case 'z': /* zflag */
+ FULLCHECK("zflag");
+ lookup->zflag = state;
+ 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 = "46dhimnuv";
+static const char *dash_opts = "46bcdfhikmnptvyx";
+static bool
+dash_option(char *option, char *next, dig_lookup_t **lookup,
+ bool *open_type_class, bool *need_clone,
+ bool config_only, int argc, char **argv,
+ bool *firstarg)
+{
+ char opt, *value, *ptr, *ptr2, *ptr3;
+ isc_result_t result;
+ bool value_from_next;
+ isc_textregion_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, *cmd;
+ uint32_t num;
+
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ /*
+ * Since the -[46dhimnuv] options do not take an argument,
+ * account for them (in any number and/or combination)
+ * if they appear as the first character(s) of a q-opt.
+ */
+ opt = option[0];
+ switch (opt) {
+ case '4':
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else {
+ fatal("can't find IPv4 networking");
+ /* NOTREACHED */
+ return (false);
+ }
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ /* NOTREACHED */
+ return (false);
+ }
+ break;
+ case 'd':
+ ptr = strpbrk(&option[1], dash_opts);
+ if (ptr != &option[1]) {
+ cmd = option;
+ FULLCHECK("debug");
+ debugging = true;
+ return (false);
+ } else
+ debugging = true;
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'i':
+ ip6_int = true;
+ break;
+ case 'm': /* memdebug */
+ /* memdebug is handled in preparse_args() */
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'u':
+ use_usec = true;
+ break;
+ case 'v':
+ version();
+ 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':
+ hash = strchr(value, '#');
+ if (hash != NULL) {
+ result = parse_uint(&num, hash + 1, MAXPORT,
+ "port number");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse port number");
+ srcport = num;
+ *hash = '\0';
+ } else
+ srcport = 0;
+ if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) {
+ isc_sockaddr_fromin6(&bind_address, &in6, srcport);
+ isc_net_disableipv4();
+ } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
+ isc_sockaddr_fromin(&bind_address, &in4, srcport);
+ isc_net_disableipv6();
+ } else {
+ if (hash != NULL)
+ *hash = '#';
+ fatal("invalid address %s", value);
+ }
+ if (hash != NULL)
+ *hash = '#';
+ specified_source = true;
+ return (value_from_next);
+ case 'c':
+ if ((*lookup)->rdclassset) {
+ fprintf(stderr, ";; Warning, extra class option\n");
+ }
+ *open_type_class = false;
+ tr.base = value;
+ tr.length = (unsigned int) strlen(value);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ (*lookup)->rdclass = rdclass;
+ (*lookup)->rdclassset = true;
+ } else
+ fprintf(stderr, ";; Warning, ignoring "
+ "invalid class %s\n",
+ value);
+ return (value_from_next);
+ case 'f':
+ batchname = value;
+ return (value_from_next);
+ case 'k':
+ strlcpy(keyfile, value, sizeof(keyfile));
+ return (value_from_next);
+ case 'p':
+ result = parse_uint(&num, value, MAXPORT, "port number");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse port number");
+ port = num;
+ return (value_from_next);
+ case 'q':
+ if (!config_only) {
+ if (*need_clone)
+ (*lookup) = clone_lookup(default_lookup,
+ true);
+ *need_clone = true;
+ strlcpy((*lookup)->textname, value,
+ sizeof((*lookup)->textname));
+ (*lookup)->trace_root = ((*lookup)->trace ||
+ (*lookup)->ns_search_only);
+ (*lookup)->new_search = true;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, (*lookup), link);
+ debug("looking up %s", (*lookup)->textname);
+ }
+ return (value_from_next);
+ case 't':
+ *open_type_class = false;
+ if (strncasecmp(value, "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = value;
+ tr.length = (unsigned int) strlen(value);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS &&
+ rdtype == dns_rdatatype_ixfr) {
+ result = DNS_R_UNKNOWN;
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ if ((*lookup)->rdtypeset) {
+ fprintf(stderr, ";; Warning, "
+ "extra type option\n");
+ }
+ if (rdtype == dns_rdatatype_ixfr) {
+ uint32_t serial;
+ (*lookup)->rdtype = dns_rdatatype_ixfr;
+ (*lookup)->rdtypeset = true;
+ result = parse_uint(&serial, &value[5],
+ MAXSERIAL, "serial number");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse serial number");
+ (*lookup)->ixfr_serial = serial;
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ if (!(*lookup)->tcp_mode_set)
+ (*lookup)->tcp_mode = true;
+ } else {
+ (*lookup)->rdtype = rdtype;
+ if (!config_only)
+ (*lookup)->rdtypeset = true;
+ if (rdtype == dns_rdatatype_axfr) {
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ } else if (rdtype == dns_rdatatype_any) {
+ if (!(*lookup)->tcp_mode_set)
+ (*lookup)->tcp_mode = true;
+ }
+ (*lookup)->ixfr_serial = false;
+ }
+ } else
+ fprintf(stderr, ";; Warning, ignoring "
+ "invalid type %s\n",
+ value);
+ return (value_from_next);
+ case 'y':
+ ptr = next_token(&value, ":"); /* hmac type or name */
+ if (ptr == NULL) {
+ usage();
+ }
+ ptr2 = next_token(&value, ":"); /* name or secret */
+ if (ptr2 == NULL)
+ usage();
+ ptr3 = next_token(&value, ":"); /* secret or NULL */
+ if (ptr3 != NULL) {
+ parse_hmac(ptr);
+ ptr = ptr2;
+ ptr2 = ptr3;
+ } else {
+#ifndef PK11_MD5_DISABLE
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+#else
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+#endif
+ digestbits = 0;
+ }
+ strlcpy(keynametext, ptr, sizeof(keynametext));
+ strlcpy(keysecret, ptr2, sizeof(keysecret));
+ return (value_from_next);
+ case 'x':
+ if (*need_clone)
+ *lookup = clone_lookup(default_lookup, true);
+ *need_clone = true;
+ if (get_reverse(textname, sizeof(textname), value,
+ ip6_int, false) == ISC_R_SUCCESS) {
+ strlcpy((*lookup)->textname, textname,
+ sizeof((*lookup)->textname));
+ debug("looking up %s", (*lookup)->textname);
+ (*lookup)->trace_root = ((*lookup)->trace ||
+ (*lookup)->ns_search_only);
+ (*lookup)->ip6_int = ip6_int;
+ if (!(*lookup)->rdtypeset)
+ (*lookup)->rdtype = dns_rdatatype_ptr;
+ if (!(*lookup)->rdclassset)
+ (*lookup)->rdclass = dns_rdataclass_in;
+ (*lookup)->new_search = true;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, *lookup, link);
+ } else {
+ fprintf(stderr, "Invalid IP address %s\n", value);
+ exit(1);
+ }
+ return (value_from_next);
+ invalid_option:
+ default:
+ fprintf(stderr, "Invalid option: -%s\n", option);
+ usage();
+ }
+ /* NOTREACHED */
+ return (false);
+}
+
+/*%
+ * 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 dig 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;
+
+ 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':
+ memdebugging = true;
+ 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];
+ }
+ }
+}
+
+static void
+parse_args(bool is_batchfile, bool config_only,
+ int argc, char **argv)
+{
+ isc_result_t result;
+ isc_textregion_t tr;
+ bool firstarg = true;
+ dig_lookup_t *lookup = NULL;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ bool open_type_class = true;
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[64];
+ int rc;
+ char **rv;
+#ifndef NOPOSIX
+ char *homedir;
+ char rcfile[256];
+#endif
+ char *input;
+ int i;
+ bool need_clone = true;
+
+ /*
+ * 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 lookup" which won't actually be used
+ * anywhere, except for cloning into new lookups
+ */
+
+ debug("parse_args()");
+ if (!is_batchfile) {
+ debug("making new lookup");
+ default_lookup = make_empty_lookup();
+ default_lookup->adflag = true;
+ default_lookup->edns = 0;
+ default_lookup->sendcookie = true;
+
+#ifndef NOPOSIX
+ /*
+ * Treat ${HOME}/.digrc as a special batchfile
+ */
+ INSIST(batchfp == NULL);
+ homedir = getenv("HOME");
+ if (homedir != NULL) {
+ unsigned int n;
+ n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc",
+ homedir);
+ if (n < sizeof(rcfile))
+ batchfp = fopen(rcfile, "r");
+ }
+ if (batchfp != NULL) {
+ while (fgets(batchline, sizeof(batchline),
+ batchfp) != 0) {
+ debug("config line %s", batchline);
+ bargc = 1;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargc < 62) && (bargv[bargc] != NULL)) {
+ bargc++;
+ bargv[bargc] =
+ next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+
+ for(i = 0; i < bargc; i++)
+ debug(".digrc argv %d: %s",
+ i, bargv[i]);
+ parse_args(true, true, bargc,
+ (char **)bargv);
+ }
+ fclose(batchfp);
+ }
+#endif
+ }
+
+ if (is_batchfile && !config_only) {
+ /* Processing '-f batchfile'. */
+ lookup = clone_lookup(default_lookup, true);
+ need_clone = false;
+ } else
+ lookup = default_lookup;
+
+ rc = argc;
+ rv = argv;
+ for (rc--, rv++; rc > 0; rc--, rv++) {
+ debug("main parsing %s", rv[0]);
+ if (strncmp(rv[0], "%", 1) == 0)
+ break;
+ if (rv[0][0] == '@') {
+
+ if (is_batchfile && !config_only) {
+ addresscount = getaddresses(lookup, &rv[0][1],
+ &result);
+ if (addresscount == 0) {
+ fprintf(stderr, "couldn't get address "
+ "for '%s': %s: skipping "
+ "lookup\n", &rv[0][1],
+ isc_result_totext(result));
+ if (ISC_LINK_LINKED(lookup, link))
+ ISC_LIST_DEQUEUE(lookup_list,
+ lookup, link);
+ destroy_lookup(lookup);
+ return;
+ }
+ } else {
+ addresscount = getaddresses(lookup, &rv[0][1],
+ NULL);
+ if (addresscount == 0)
+ fatal("no valid addresses for '%s'\n",
+ &rv[0][1]);
+ }
+ } else if (rv[0][0] == '+') {
+ plus_option(&rv[0][1], is_batchfile,
+ lookup);
+ } else if (rv[0][0] == '-') {
+ if (rc <= 1) {
+ if (dash_option(&rv[0][1], NULL,
+ &lookup, &open_type_class,
+ &need_clone, config_only,
+ argc, argv, &firstarg)) {
+ rc--;
+ rv++;
+ }
+ } else {
+ if (dash_option(&rv[0][1], rv[1],
+ &lookup, &open_type_class,
+ &need_clone, config_only,
+ argc, argv, &firstarg)) {
+ rc--;
+ rv++;
+ }
+ }
+ } else {
+ /*
+ * Anything which isn't an option
+ */
+ if (open_type_class) {
+ if (strncasecmp(rv[0], "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = rv[0];
+ tr.length =
+ (unsigned int) strlen(rv[0]);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS &&
+ rdtype == dns_rdatatype_ixfr) {
+ fprintf(stderr, ";; Warning, "
+ "ixfr requires a "
+ "serial number\n");
+ continue;
+ }
+ }
+ if (result == ISC_R_SUCCESS) {
+ if (lookup->rdtypeset) {
+ fprintf(stderr, ";; Warning, "
+ "extra type option\n");
+ }
+ if (rdtype == dns_rdatatype_ixfr) {
+ uint32_t serial;
+ lookup->rdtype =
+ dns_rdatatype_ixfr;
+ lookup->rdtypeset = true;
+ result = parse_uint(&serial,
+ &rv[0][5],
+ MAXSERIAL,
+ "serial number");
+ if (result != ISC_R_SUCCESS)
+ fatal("Couldn't parse "
+ "serial number");
+ lookup->ixfr_serial = serial;
+ lookup->section_question =
+ plusquest;
+ lookup->comments = pluscomm;
+ if (!lookup->tcp_mode_set)
+ lookup->tcp_mode = true;
+ } else {
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = true;
+ if (rdtype ==
+ dns_rdatatype_axfr) {
+ lookup->section_question =
+ plusquest;
+ lookup->comments = pluscomm;
+ }
+ if (rdtype ==
+ dns_rdatatype_any &&
+ !lookup->tcp_mode_set)
+ lookup->tcp_mode = true;
+ lookup->ixfr_serial = false;
+ }
+ continue;
+ }
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ if (lookup->rdclassset) {
+ fprintf(stderr, ";; Warning, "
+ "extra class option\n");
+ }
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = true;
+ continue;
+ }
+ }
+
+ if (!config_only) {
+ if (need_clone)
+ lookup = clone_lookup(default_lookup,
+ true);
+ need_clone = true;
+ strlcpy(lookup->textname, rv[0],
+ sizeof(lookup->textname));
+ lookup->trace_root = (lookup->trace ||
+ lookup->ns_search_only);
+ lookup->new_search = true;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ debug("looking up %s", lookup->textname);
+ }
+ /* XXX Error message */
+ }
+ }
+
+ /*
+ * If we have a batchfile, seed the lookup list with the
+ * first entry, then trust the callback in dighost_shutdown
+ * to get the rest
+ */
+ if ((batchname != NULL) && !(is_batchfile)) {
+ if (strcmp(batchname, "-") == 0)
+ batchfp = stdin;
+ else
+ batchfp = fopen(batchname, "r");
+ if (batchfp == NULL) {
+ perror(batchname);
+ if (exitcode < 8)
+ exitcode = 8;
+ fatal("couldn't open specified batch file");
+ }
+ /* XXX Remove code dup from shutdown code */
+ next_line:
+ if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ bargc = 1;
+ debug("batch line %s", batchline);
+ if (batchline[0] == '\r' || batchline[0] == '\n'
+ || batchline[0] == '#' || batchline[0] == ';')
+ goto next_line;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargc < 14) && (bargv[bargc] != NULL)) {
+ bargc++;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv[0];
+ argv0 = argv[0];
+
+ for(i = 0; i < bargc; i++)
+ debug("batch argv %d: %s", i, bargv[i]);
+ parse_args(true, false, bargc, (char **)bargv);
+ return;
+ }
+ return;
+ }
+ /*
+ * If no lookup specified, search for root
+ */
+ if ((lookup_list.head == NULL) && !config_only) {
+ if (need_clone)
+ lookup = clone_lookup(default_lookup, true);
+ need_clone = true;
+ lookup->trace_root = (lookup->trace ||
+ lookup->ns_search_only);
+ lookup->new_search = true;
+ strlcpy(lookup->textname, ".", sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = true;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = false;
+ }
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ if (!need_clone)
+ destroy_lookup(lookup);
+}
+
+/*
+ * Callback from dighost.c to allow program-specific shutdown code.
+ * Here, we're possibly reading from a batch file, then shutting down
+ * for real if there's nothing in the batch file to read.
+ */
+static void
+query_finished(void) {
+ char batchline[MXNAME];
+ int bargc;
+ char *bargv[16];
+ char *input;
+ int i;
+
+ if (batchname == NULL) {
+ isc_app_shutdown();
+ return;
+ }
+
+ fflush(stdout);
+ if (feof(batchfp)) {
+ batchname = NULL;
+ isc_app_shutdown();
+ if (batchfp != stdin)
+ fclose(batchfp);
+ return;
+ }
+
+ if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
+ debug("batch line %s", batchline);
+ bargc = 1;
+ input = batchline;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ while ((bargc < 14) && (bargv[bargc] != NULL)) {
+ bargc++;
+ bargv[bargc] = next_token(&input, " \t\r\n");
+ }
+
+ bargv[0] = argv0;
+
+ for(i = 0; i < bargc; i++)
+ debug("batch argv %d: %s", i, bargv[i]);
+ parse_args(true, false, bargc, (char **)bargv);
+ start_lookup();
+ } else {
+ batchname = NULL;
+ if (batchfp != stdin)
+ fclose(batchfp);
+ isc_app_shutdown();
+ return;
+ }
+}
+
+void dig_setup(int argc, char **argv)
+{
+ isc_result_t result;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ debug("dig_setup()");
+
+ /* setup dighost callbacks */
+#ifdef DIG_SIGCHASE
+ dighost_printrdataset = printrdataset;
+#endif
+ dighost_printmessage = printmessage;
+ dighost_received = received;
+ dighost_trying = trying;
+ dighost_shutdown = query_finished;
+
+ progname = argv[0];
+ preparse_args(argc, argv);
+
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+
+ setup_libs();
+ setup_system(ipv4only, ipv6only);
+}
+
+void dig_query_setup(bool is_batchfile, bool config_only,
+ int argc, char **argv)
+{
+ debug("dig_query_setup");
+
+ parse_args(is_batchfile, config_only, argc, argv);
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+ setup_text_key();
+ if (domainopt[0] != '\0') {
+ set_search_domain(domainopt);
+ usesearch = true;
+ }
+}
+
+void dig_startup() {
+ isc_result_t result;
+
+ debug("dig_startup()");
+
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ check_result(result, "isc_app_onrun");
+ isc_app_run();
+}
+
+void dig_query_start()
+{
+ start_lookup();
+}
+
+void
+dig_shutdown() {
+ destroy_lookup(default_lookup);
+ if (batchname != NULL) {
+ if (batchfp != stdin)
+ fclose(batchfp);
+ batchname = NULL;
+ }
+
+#ifdef DIG_SIGCHASE
+ clean_trustedkey();
+#endif
+
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+}
+
+/*% Main processing routine for dig */
+int
+main(int argc, char **argv) {
+
+ dig_setup(argc, argv);
+ dig_query_setup(false, false, argc, argv);
+ dig_startup();
+ dig_shutdown();
+
+ return (exitcode);
+}
diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook
new file mode 100644
index 0000000..6b14a44
--- /dev/null
+++ b/bin/dig/dig.docbook
@@ -0,0 +1,1329 @@
+<!DOCTYPE book [
+<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.dig">
+ <info>
+ <date>2014-02-19</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>dig</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>dig</refname>
+ <refpurpose>DNS lookup utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2010</year>
+ <year>2011</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>dig</command>
+ <arg choice="opt" rep="norepeat">@server</arg>
+ <arg choice="opt" rep="norepeat"><option>-b <replaceable class="parameter">address</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-k <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-p <replaceable class="parameter">port#</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-q <replaceable class="parameter">name</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-x <replaceable class="parameter">addr</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-y <replaceable class="parameter"><optional>hmac:</optional>name:key</replaceable></option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat">name</arg>
+ <arg choice="opt" rep="norepeat">type</arg>
+ <arg choice="opt" rep="norepeat">class</arg>
+ <arg choice="opt" rep="repeat">queryopt</arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>dig</command>
+ <arg choice="opt" rep="norepeat"><option>-h</option></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis sepchar=" ">
+ <command>dig</command>
+ <arg choice="opt" rep="repeat">global-queryopt</arg>
+ <arg choice="opt" rep="repeat">query</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>dig</command> is a flexible tool
+ for interrogating DNS name servers. It performs DNS lookups and
+ displays the answers that are returned from the name server(s) that
+ were queried. Most DNS administrators use <command>dig</command> to
+ troubleshoot DNS problems because of its flexibility, ease of use and
+ clarity of output. Other lookup tools tend to have less functionality
+ than <command>dig</command>.
+ </para>
+
+ <para>
+ Although <command>dig</command> is normally used with
+ command-line
+ arguments, it also has a batch mode of operation for reading lookup
+ requests from a file. A brief summary of its command-line arguments
+ and options is printed when the <option>-h</option> option is given.
+ Unlike earlier versions, the BIND 9 implementation of
+ <command>dig</command> allows multiple lookups to be issued
+ from the
+ command line.
+ </para>
+
+ <para>
+ Unless it is told to query a specific name server,
+ <command>dig</command> will try each of the servers listed in
+ <filename>/etc/resolv.conf</filename>. If no usable server addresses
+ are found, <command>dig</command> will send the query to the local
+ host.
+ </para>
+
+ <para>
+ When no command line arguments or options are given,
+ <command>dig</command> will perform an NS query for "." (the root).
+ </para>
+
+ <para>
+ It is possible to set per-user defaults for <command>dig</command> via
+ <filename>${HOME}/.digrc</filename>. This file is read and
+ any options in it
+ are applied before the command line arguments.
+ </para>
+
+ <para>
+ The IN and CH class names overlap with the IN and CH top level
+ domain names. Either use the <option>-t</option> and
+ <option>-c</option> options to specify the type and class,
+ use the <option>-q</option> the specify the domain name, or
+ use "IN." and "CH." when looking up these top level domains.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>SIMPLE USAGE</title></info>
+
+
+ <para>
+ A typical invocation of <command>dig</command> looks like:
+ <programlisting> dig @server name type </programlisting>
+ where:
+
+ <variablelist>
+
+ <varlistentry>
+ <term><constant>server</constant></term>
+ <listitem>
+ <para>
+ is the name or IP address of the name server to query. This
+ can be an IPv4 address in dotted-decimal notation or an IPv6
+ address in colon-delimited notation. When the supplied
+ <parameter>server</parameter> argument is a hostname,
+ <command>dig</command> resolves that name before querying
+ that name server.
+ </para>
+ <para>
+ If no <parameter>server</parameter> argument is
+ provided, <command>dig</command> consults
+ <filename>/etc/resolv.conf</filename>; if an
+ address is found there, it queries the name server at
+ that address. If either of the <option>-4</option> or
+ <option>-6</option> options are in use, then
+ only addresses for the corresponding transport
+ will be tried. If no usable addresses are found,
+ <command>dig</command> will send the query to the
+ local host. The reply from the name server that
+ responds is displayed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>name</constant></term>
+ <listitem>
+ <para>
+ is the name of the resource record that is to be looked up.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>type</constant></term>
+ <listitem>
+ <para>
+ indicates what type of query is required &mdash;
+ ANY, A, MX, SIG, etc.
+ <parameter>type</parameter> can be any valid query
+ type. If no
+ <parameter>type</parameter> argument is supplied,
+ <command>dig</command> will perform a lookup for an
+ A record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+
+ <variablelist>
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-b <replaceable class="parameter">address<optional>#port</optional></replaceable></term>
+ <listitem>
+ <para>
+ Set the source IP address of the query.
+ The <parameter>address</parameter> 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 "#&lt;port&gt;"
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Set the query class. The
+ default <parameter>class</parameter> is IN; other classes
+ are HS for Hesiod records or CH for Chaosnet records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-f <replaceable class="parameter">file</replaceable></term>
+ <listitem>
+ <para>
+ Batch mode: <command>dig</command> reads a list of lookup
+ requests to process from the
+ given <parameter>file</parameter>. Each line in the file
+ should be organized in the same way they would be
+ presented as queries to
+ <command>dig</command> using the command-line interface.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i</term>
+ <listitem>
+ <para>
+ Do reverse IPv6 lookups using the obsolete RFC 1886 IP6.INT
+ domain, which is no longer in use. Obsolete bit string
+ label queries (RFC 2874) are not attempted.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-k <replaceable class="parameter">keyfile</replaceable></term>
+ <listitem>
+ <para>
+ Sign queries using TSIG using a key read from the given file.
+ Key files can be generated using
+ <citerefentry>
+ <refentrytitle>tsig-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ When using TSIG authentication with <command>dig</command>,
+ the name server that is queried needs to know the key and
+ algorithm that is being used. In BIND, this is done by
+ providing appropriate <command>key</command>
+ and <command>server</command> statements in
+ <filename>named.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m</term>
+ <listitem>
+ <para>
+ Enable memory usage debugging.
+ <!-- It enables ISC_MEM_DEBUGTRACE and ISC_MEM_DEBUGRECORD
+ documented in include/isc/mem.h -->
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-p <replaceable class="parameter">port</replaceable></term>
+ <listitem>
+ <para>
+ Send the query to a non-standard port on the server,
+ instead of the default port 53. This option would be used
+ to test a name server that has been configured to listen
+ for queries on a non-standard port number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-q <replaceable class="parameter">name</replaceable></term>
+ <listitem>
+ <para>
+ The domain name to query. This is useful to distinguish
+ the <parameter>name</parameter> from other arguments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ The resource record type to query. It can be any valid query
+ type. If it is a resource record type supported in BIND 9, it
+ can be given by the type mnemonic (such as "NS" or "AAAA").
+ The default query type is "A", unless the <option>-x</option>
+ option is supplied to indicate a reverse lookup. A zone
+ transfer can be requested by specifying a type of AXFR. When
+ an incremental zone transfer (IXFR) is required, set the
+ <parameter>type</parameter> to <literal>ixfr=N</literal>.
+ The incremental zone transfer will contain the changes
+ made to the zone since the serial number in the zone's SOA
+ record was
+ <parameter>N</parameter>.
+ </para>
+ <para>
+ All resource record types can be expressed as "TYPEnn", where
+ "nn" is the number of the type. If the resource record type is
+ not supported in BIND 9, the result will be displayed as
+ described in RFC 3597.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-u</term>
+ <listitem>
+ <para>
+ Print query times in microseconds instead of milliseconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Print the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-x <replaceable class="parameter">addr</replaceable></term>
+ <listitem>
+ <para>
+ Simplified reverse lookups, for mapping addresses to
+ names. The <parameter>addr</parameter> is an IPv4 address
+ in dotted-decimal notation, or a colon-delimited IPv6
+ address. When the <option>-x</option> is used, there is no
+ need to provide
+ the <parameter>name</parameter>, <parameter>class</parameter>
+ and <parameter>type</parameter>
+ arguments. <command>dig</command> automatically performs a
+ lookup for a name like
+ <literal>94.2.0.192.in-addr.arpa</literal> and sets the
+ query type and class to PTR and IN respectively. IPv6
+ addresses are looked up using nibble format under the
+ IP6.ARPA domain (but see also the <option>-i</option>
+ option).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-y <replaceable class="parameter"><optional>hmac:</optional>keyname:secret</replaceable></term>
+ <listitem>
+ <para>
+ Sign queries using TSIG with the given authentication key.
+ <parameter>keyname</parameter> is the name of the key, and
+ <parameter>secret</parameter> is the base64 encoded shared secret.
+ <parameter>hmac</parameter> is the name of the key algorithm;
+ valid choices are <literal>hmac-md5</literal>,
+ <literal>hmac-sha1</literal>, <literal>hmac-sha224</literal>,
+ <literal>hmac-sha256</literal>, <literal>hmac-sha384</literal>, or
+ <literal>hmac-sha512</literal>. If <parameter>hmac</parameter>
+ is not specified, the default is <literal>hmac-md5</literal>
+ or if MD5 was disabled <literal>hmac-sha256</literal>.
+ </para>
+ <para>
+ NOTE: You should use the <option>-k</option> option and
+ avoid the <option>-y</option> option, because
+ with <option>-y</option> the shared secret is supplied as
+ a command line argument in clear text. This may be visible
+ in the output from
+ <citerefentry>
+ <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>
+ or in a history file maintained by the user's shell.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>QUERY OPTIONS</title></info>
+
+
+ <para><command>dig</command>
+ 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.
+ </para>
+
+ <para>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<literal>+</literal>). Some keywords set or reset an
+ option. These may be preceded
+ by the string <literal>no</literal> to negate the meaning of
+ that keyword. Other
+ keywords assign values to options like the timeout interval. They
+ have the form <option>+keyword=value</option>.
+ Keywords may be abbreviated, provided the abbreviation is
+ unambiguous; for example, <literal>+cd</literal> is equivalent
+ to <literal>+cdflag</literal>.
+ The query options are:
+
+ <variablelist>
+
+ <varlistentry>
+ <term><option>+[no]aaflag</option></term>
+ <listitem>
+ <para>
+ A synonym for <parameter>+[no]aaonly</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]aaonly</option></term>
+ <listitem>
+ <para>
+ Sets the "aa" flag in the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]additional</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the additional section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]adflag</option></term>
+ <listitem>
+ <para>
+ Set [do 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 indicate that some part
+ of the answer was insecure or not validated. This
+ bit is set by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]all</option></term>
+ <listitem>
+ <para>
+ Set or clear all display flags.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]answer</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the answer section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]authority</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the authority section of a
+ reply. The default is to display it.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]badcookie</option></term>
+ <listitem>
+ <para>
+ Retry lookup with the new server cookie if a
+ BADCOOKIE response is received.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]besteffort</option></term>
+ <listitem>
+ <para>
+ Attempt to display the contents of messages which are
+ malformed. The default is to not display malformed
+ answers.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+bufsize=B</option></term>
+ <listitem>
+ <para>
+ Set the UDP message buffer size advertised using EDNS0
+ to <parameter>B</parameter> 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 will cause a
+ EDNS query to be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cdflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the CD (checking disabled) bit in
+ the query. This requests the server to not perform
+ DNSSEC validation of responses.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]class</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the CLASS when printing the
+ record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cmd</option></term>
+ <listitem>
+ <para>
+ Toggles the printing of the initial comment in the
+ output identifying the version of <command>dig</command>
+ and the query options that have been applied. This
+ comment is printed by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]comments</option></term>
+ <listitem>
+ <para>
+ Toggle the display of comment lines in the output.
+ The default is to print comments.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]cookie<optional>=####</optional></option></term>
+ <listitem>
+ <para>
+ Send a COOKIE EDNS option, with optional
+ value. Replaying a COOKIE from a previous response will
+ allow the server to identify a previous client. The
+ default is <option>+cookie</option>.
+ </para>
+ <para>
+ <command>+cookie</command> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]crypto</option></term>
+ <listitem>
+ <para>
+ Toggle the display of cryptographic fields in DNSSEC
+ records. The contents of these field 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]" or in the
+ DNSKEY case the key id is displayed as the replacement,
+ e.g. "[ key id = value ]".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]defname</option></term>
+ <listitem>
+ <para>
+ Deprecated, treated as a synonym for
+ <parameter>+[no]search</parameter>
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]dnssec</option></term>
+ <listitem>
+ <para>
+ Requests DNSSEC records be sent by setting the DNSSEC
+ OK bit (DO) in the OPT record in the additional section
+ of the query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+domain=somename</option></term>
+ <listitem>
+ <para>
+ Set the search list to contain the single domain
+ <parameter>somename</parameter>, as if specified in
+ a <command>domain</command> directive in
+ <filename>/etc/resolv.conf</filename>, and enable
+ search list processing as if the
+ <parameter>+search</parameter> option were given.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+dscp=value</option></term> <listitem>
+ <para>
+ Set 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]edns[=#]</option></term>
+ <listitem>
+ <para>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause
+ a EDNS query to be sent. <option>+noedns</option>
+ clears the remembered EDNS version. EDNS is set to
+ 0 by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsflags[=#]</option></term>
+ <listitem>
+ <para>
+ Set the must-be-zero EDNS flags bits (Z bits) to the
+ specified value. Decimal, hex and octal encodings are
+ accepted. Setting a named flag (e.g. DO) will silently be
+ ignored. By default, no Z bits are set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsnegotiation</option></term>
+ <listitem>
+ <para>
+ Enable / disable EDNS version negotiation. By default
+ EDNS version negotiation is enabled.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ednsopt[=code[:value]]</option></term>
+ <listitem>
+ <para>
+ Specify EDNS option with code point <option>code</option>
+ and optionally payload of <option>value</option> as a
+ hexadecimal string. <option>code</option> can be
+ either an EDNS option name (for example,
+ <literal>NSID</literal> or <literal>ECS</literal>),
+ or an arbitrary numeric value. <option>+noednsopt</option>
+ clears the EDNS options to be sent.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]expire</option></term>
+ <listitem>
+ <para>
+ Send an EDNS Expire option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]fail</option></term>
+ <listitem>
+ <para>
+ Do not try the next server if you receive a SERVFAIL.
+ The default is to not try the next server which is
+ the reverse of normal stub resolver behavior.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]header-only</option></term>
+ <listitem>
+ <para>
+ Send a query with a DNS header without a question section.
+ The default is to add a question section. The query type
+ and query name are ignored when this is set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]identify</option></term>
+ <listitem>
+ <para>
+ Show [or do not show] the IP address and port number
+ that supplied the answer when the
+ <parameter>+short</parameter> option is enabled. If
+ short form answers are requested, the default is not
+ to show the source address and port number of the
+ server that provided the answer.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]idnin</option></term>
+ <listitem>
+ <para>
+ Process [do not process] IDN domain names on input.
+ This requires IDN SUPPORT to have been enabled at
+ compile time. The default is to process IDN input.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]idnout</option></term>
+ <listitem>
+ <para>
+ Convert [do not convert] puny code on output.
+ This requires IDN SUPPORT to have been enabled at
+ compile time. The default is to convert output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ignore</option></term>
+ <listitem>
+ <para>
+ Ignore truncation in UDP responses instead of retrying
+ with TCP. By default, TCP retries are performed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]keepopen</option></term>
+ <listitem>
+ <para>
+ Keep the TCP socket open between queries and reuse
+ it rather than creating a new TCP socket for each
+ lookup. The default is <option>+nokeepopen</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]mapped</option></term>
+ <listitem>
+ <para>
+ Allow mapped IPv4 over IPv6 addresses to be used. The
+ default is <option>+mapped</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]multiline</option></term>
+ <listitem>
+ <para>
+ Print 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 <command>dig</command>
+ output.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+ndots=D</option></term>
+ <listitem>
+ <para>
+ Set the number of dots that have to appear in
+ <parameter>name</parameter> to <parameter>D</parameter>
+ for it to be considered absolute. The default value
+ is that defined using the ndots statement in
+ <filename>/etc/resolv.conf</filename>, or 1 if no
+ ndots statement is present. Names with fewer dots
+ are interpreted as relative names and will be searched
+ for in the domains listed in the <option>search</option>
+ or <option>domain</option> directive in
+ <filename>/etc/resolv.conf</filename> if
+ <option>+search</option> is set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]nsid</option></term>
+ <listitem>
+ <para>
+ Include an EDNS name server ID request when sending
+ a query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]nssearch</option></term>
+ <listitem>
+ <para>
+ When this option is set, <command>dig</command>
+ attempts to find the authoritative name servers for
+ the zone containing the name being looked up and
+ display the SOA record that each name server has for
+ the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]onesoa</option></term>
+ <listitem>
+ <para>
+ Print only one (starting) SOA record when performing
+ an AXFR. The default is to print both the starting
+ and ending SOA records.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]opcode=value</option></term>
+ <listitem>
+ <para>
+ Set [restore] the DNS message opcode to the specified
+ value. The default value is QUERY (0).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]qr</option></term>
+ <listitem>
+ <para>
+ Print [do not print] the query as it is sent. By
+ default, the query is not printed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]question</option></term>
+ <listitem>
+ <para>
+ Print [do not print] the question section of a query
+ when an answer is returned. The default is to print
+ the question section as a comment.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]rdflag</option></term>
+ <listitem>
+ <para>
+ A synonym for <parameter>+[no]recurse</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]recurse</option></term>
+ <listitem>
+ <para>
+ Toggle the setting of the RD (recursion desired) bit
+ in the query. This bit is set by default, which means
+ <command>dig</command> normally sends recursive
+ queries. Recursion is automatically disabled when
+ the <parameter>+nssearch</parameter> or
+ <parameter>+trace</parameter> query options are used.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+retry=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to retry UDP queries to
+ server to <parameter>T</parameter> instead of the
+ default, 2. Unlike <parameter>+tries</parameter>,
+ this does not include the initial query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]rrcomments</option></term>
+ <listitem>
+ <para>
+ Toggle 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.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]search</option></term>
+ <listitem>
+ <para>
+ Use [do not use] the search list defined by the
+ searchlist or domain directive in
+ <filename>resolv.conf</filename> (if any). The search
+ list is not used by default.
+ </para>
+ <para>
+ 'ndots' from <filename>resolv.conf</filename> (default 1)
+ which may be overridden by <parameter>+ndots</parameter>
+ determines if the name will be treated as relative
+ or not and hence whether a search is eventually
+ performed or not.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]short</option></term>
+ <listitem>
+ <para>
+ Provide a terse answer. The default is to print the
+ answer in a verbose form.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]showsearch</option></term>
+ <listitem>
+ <para>
+ Perform [do not perform] a search showing intermediate
+ results.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]sigchase</option></term>
+ <listitem>
+ <para>
+ Chase DNSSEC signature chains. Requires dig be compiled
+ with -DDIG_SIGCHASE. This feature is deprecated.
+ Use <command>delv</command> instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+split=W</option></term>
+ <listitem>
+ <para>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <parameter>W</parameter>
+ characters (where <parameter>W</parameter> is rounded
+ up to the nearest multiple of 4).
+ <parameter>+nosplit</parameter> or
+ <parameter>+split=0</parameter> causes fields not to
+ be split at all. The default is 56 characters, or
+ 44 characters when multiline mode is active.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]stats</option></term>
+ <listitem>
+ <para>
+ This query option toggles the printing of statistics:
+ when the query was made, the size of the reply and
+ so on. The default behavior is to print the query
+ statistics.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]subnet=addr[/prefix-length]</option></term>
+ <listitem>
+ <para>
+ Send (don't send) an EDNS Client Subnet option with the
+ specified IP address or network prefix.
+ </para>
+ <para>
+ <command>dig +subnet=0.0.0.0/0</command>, or simply
+ <command>dig +subnet=0</command> for short, 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
+ <emphasis>not</emphasis> be used when resolving
+ this query.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]tcp</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. The
+ default behavior is to use UDP unless a type
+ <literal>any</literal> or <literal>ixfr=N</literal>
+ query is requested, in which case the default is TCP.
+ AXFR queries always use TCP.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+timeout=T</option></term>
+ <listitem>
+ <para>
+
+ Sets the timeout for a query to
+ <parameter>T</parameter> seconds. The default
+ timeout is 5 seconds.
+ An attempt to set <parameter>T</parameter> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]topdown</option></term>
+ <listitem>
+ <para>
+ When chasing DNSSEC signature chains perform a top-down
+ validation. Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <command>delv</command> instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]trace</option></term>
+ <listitem>
+ <para>
+ Toggle tracing of the delegation path from the root
+ name servers for the name being looked up. Tracing
+ is disabled by default. When tracing is enabled,
+ <command>dig</command> makes iterative queries to
+ resolve the name being looked up. It will follow
+ referrals from the root servers, showing the answer
+ from each server that was used to resolve the lookup.
+ </para> <para>
+ If @server is also specified, it affects only the
+ initial query for the root zone name servers.
+ </para> <para>
+ <command>+dnssec</command> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+tries=T</option></term>
+ <listitem>
+ <para>
+ Sets the number of times to try UDP queries to server
+ to <parameter>T</parameter> instead of the default,
+ 3. If <parameter>T</parameter> is less than or equal
+ to zero, the number of tries is silently rounded up
+ to 1.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+trusted-key=####</option></term>
+ <listitem>
+ <para>
+ Specifies a file containing trusted keys to be used
+ with <option>+sigchase</option>. Each DNSKEY record
+ must be on its own line.
+ </para> <para>
+ If not specified, <command>dig</command> will look
+ for <filename>/etc/trusted-key.key</filename> then
+ <filename>trusted-key.key</filename> in the current
+ directory.
+ </para> <para>
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <command>delv</command> instead.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttlid</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the TTL when printing the
+ record.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]ttlunits</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the TTL in friendly human-readable
+ time units of "s", "m", "h", "d", and "w", representing
+ seconds, minutes, hours, days and weeks. Implies +ttlid.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]unknownformat</option></term>
+ <listitem>
+ <para>
+ Print all RDATA in unknown RR type presentation format
+ (RFC 3597). The default is to print RDATA for known types
+ in the type's presentation format.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]vc</option></term>
+ <listitem>
+ <para>
+ Use [do not use] TCP when querying name servers. This
+ alternate syntax to <parameter>+[no]tcp</parameter>
+ is provided for backwards compatibility. The "vc"
+ stands for "virtual circuit".
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]zflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the last unassigned DNS header flag in a
+ DNS query. This flag is off by default.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </para>
+ </refsection>
+
+ <refsection><info><title>MULTIPLE QUERIES</title></info>
+
+
+ <para>
+ The BIND 9 implementation of <command>dig </command>
+ supports
+ specifying multiple queries on the command line (in addition to
+ supporting the <option>-f</option> batch file option). Each of those
+ queries can be supplied with its own set of flags, options and query
+ options.
+ </para>
+
+ <para>
+ In this case, each <parameter>query</parameter> argument
+ represent an
+ individual query in the command-line syntax described above. Each
+ consists of any of the standard options and flags, the name to be
+ looked up, an optional query type and class and any query options that
+ should be applied to that query.
+ </para>
+
+ <para>
+ A global set of query options, which should be applied to all queries,
+ can also be supplied. These global query options must precede the
+ first tuple of name, class, type, options, flags, and query options
+ supplied on the command line. Any global query options (except
+ the <option>+[no]cmd</option> option) can be
+ overridden by a query-specific set of query options. For example:
+ <programlisting>
+dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+</programlisting>
+ shows how <command>dig</command> could be used from the
+ command line
+ to make three lookups: an ANY query for <literal>www.isc.org</literal>, a
+ reverse lookup of 127.0.0.1 and a query for the NS records of
+ <literal>isc.org</literal>.
+
+ A global query option of <parameter>+qr</parameter> is
+ applied, so
+ that <command>dig</command> shows the initial query it made
+ for each
+ lookup. The final query has a local query option of
+ <parameter>+noqr</parameter> which means that <command>dig</command>
+ will not print the initial query when it looks up the NS records for
+ <literal>isc.org</literal>.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>IDN SUPPORT</title></info>
+
+ <para>
+ If <command>dig</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>dig</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, use
+ parameters <parameter>+noidnin</parameter> and
+ <parameter>+noidnout</parameter>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ <para><filename>${HOME}/.digrc</filename>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>delv</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>host</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>,
+ <citetitle>RFC 1035</citetitle>.
+ </para>
+ </refsection>
+
+ <refsection><info><title>BUGS</title></info>
+
+ <para>
+ There are probably too many query options.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dig/dig.html b/bin/dig/dig.html
new file mode 100644
index 0000000..b749057
--- /dev/null
+++ b/bin/dig/dig.html
@@ -0,0 +1,1075 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2011, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dig</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.dig"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ dig
+ &#8212; DNS lookup utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">dig</code>
+ [@server]
+ [<code class="option">-b <em class="replaceable"><code>address</code></em></code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-f <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-k <em class="replaceable"><code>filename</code></em></code>]
+ [<code class="option">-m</code>]
+ [<code class="option">-p <em class="replaceable"><code>port#</code></em></code>]
+ [<code class="option">-q <em class="replaceable"><code>name</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-v</code>]
+ [<code class="option">-x <em class="replaceable"><code>addr</code></em></code>]
+ [<code class="option">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]name:key</code></em></code>]
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ [name]
+ [type]
+ [class]
+ [queryopt...]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">dig</code>
+ [<code class="option">-h</code>]
+ </p></div>
+
+ <div class="cmdsynopsis"><p>
+ <code class="command">dig</code>
+ [global-queryopt...]
+ [query...]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>dig</strong></span> is a flexible tool
+ for interrogating DNS name servers. It performs DNS lookups and
+ displays the answers that are returned from the name server(s) that
+ were queried. Most DNS administrators use <span class="command"><strong>dig</strong></span> to
+ troubleshoot DNS problems because of its flexibility, ease of use and
+ clarity of output. Other lookup tools tend to have less functionality
+ than <span class="command"><strong>dig</strong></span>.
+ </p>
+
+ <p>
+ Although <span class="command"><strong>dig</strong></span> is normally used with
+ command-line
+ arguments, it also has a batch mode of operation for reading lookup
+ requests from a file. A brief summary of its command-line arguments
+ and options is printed when the <code class="option">-h</code> option is given.
+ Unlike earlier versions, the BIND 9 implementation of
+ <span class="command"><strong>dig</strong></span> allows multiple lookups to be issued
+ from the
+ command line.
+ </p>
+
+ <p>
+ Unless it is told to query a specific name server,
+ <span class="command"><strong>dig</strong></span> will try each of the servers listed in
+ <code class="filename">/etc/resolv.conf</code>. If no usable server addresses
+ are found, <span class="command"><strong>dig</strong></span> will send the query to the local
+ host.
+ </p>
+
+ <p>
+ When no command line arguments or options are given,
+ <span class="command"><strong>dig</strong></span> will perform an NS query for "." (the root).
+ </p>
+
+ <p>
+ It is possible to set per-user defaults for <span class="command"><strong>dig</strong></span> via
+ <code class="filename">${HOME}/.digrc</code>. This file is read and
+ any options in it
+ are applied before the command line arguments.
+ </p>
+
+ <p>
+ The IN and CH class names overlap with the IN and CH top level
+ domain names. Either use the <code class="option">-t</code> and
+ <code class="option">-c</code> options to specify the type and class,
+ use the <code class="option">-q</code> the specify the domain name, or
+ use "IN." and "CH." when looking up these top level domains.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>SIMPLE USAGE</h2>
+
+
+ <p>
+ A typical invocation of <span class="command"><strong>dig</strong></span> looks like:
+ </p>
+<pre class="programlisting"> dig @server name type </pre>
+<p>
+ where:
+
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">server</code></span></dt>
+<dd>
+ <p>
+ is the name or IP address of the name server to query. This
+ can be an IPv4 address in dotted-decimal notation or an IPv6
+ address in colon-delimited notation. When the supplied
+ <em class="parameter"><code>server</code></em> argument is a hostname,
+ <span class="command"><strong>dig</strong></span> resolves that name before querying
+ that name server.
+ </p>
+ <p>
+ If no <em class="parameter"><code>server</code></em> argument is
+ provided, <span class="command"><strong>dig</strong></span> consults
+ <code class="filename">/etc/resolv.conf</code>; if an
+ address is found there, it queries the name server at
+ that address. If either of the <code class="option">-4</code> or
+ <code class="option">-6</code> options are in use, then
+ only addresses for the corresponding transport
+ will be tried. If no usable addresses are found,
+ <span class="command"><strong>dig</strong></span> will send the query to the
+ local host. The reply from the name server that
+ responds is displayed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">name</code></span></dt>
+<dd>
+ <p>
+ is the name of the resource record that is to be looked up.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">type</code></span></dt>
+<dd>
+ <p>
+ indicates what type of query is required &#8212;
+ ANY, A, MX, SIG, etc.
+ <em class="parameter"><code>type</code></em> can be any valid query
+ type. If no
+ <em class="parameter"><code>type</code></em> argument is supplied,
+ <span class="command"><strong>dig</strong></span> will perform a lookup for an
+ A record.
+ </p>
+ </dd>
+</dl></div>
+<p>
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>OPTIONS</h2>
+
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-4</span></dt>
+<dd>
+ <p>
+ Use IPv4 only.
+ </p>
+ </dd>
+<dt><span class="term">-6</span></dt>
+<dd>
+ <p>
+ Use IPv6 only.
+ </p>
+ </dd>
+<dt><span class="term">-b <em class="replaceable"><code>address[<span class="optional">#port</span>]</code></em></span></dt>
+<dd>
+ <p>
+ Set the source IP address of the query.
+ The <em class="parameter"><code>address</code></em> 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 "#&lt;port&gt;"
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Set the query class. The
+ default <em class="parameter"><code>class</code></em> is IN; other classes
+ are HS for Hesiod records or CH for Chaosnet records.
+ </p>
+ </dd>
+<dt><span class="term">-f <em class="replaceable"><code>file</code></em></span></dt>
+<dd>
+ <p>
+ Batch mode: <span class="command"><strong>dig</strong></span> reads a list of lookup
+ requests to process from the
+ given <em class="parameter"><code>file</code></em>. Each line in the file
+ should be organized in the same way they would be
+ presented as queries to
+ <span class="command"><strong>dig</strong></span> using the command-line interface.
+ </p>
+ </dd>
+<dt><span class="term">-i</span></dt>
+<dd>
+ <p>
+ Do reverse IPv6 lookups using the obsolete RFC 1886 IP6.INT
+ domain, which is no longer in use. Obsolete bit string
+ label queries (RFC 2874) are not attempted.
+ </p>
+ </dd>
+<dt><span class="term">-k <em class="replaceable"><code>keyfile</code></em></span></dt>
+<dd>
+ <p>
+ Sign queries using TSIG using a key read from the given file.
+ Key files can be generated using
+ <span class="citerefentry">
+ <span class="refentrytitle">tsig-keygen</span>(8)
+ </span>.
+ When using TSIG authentication with <span class="command"><strong>dig</strong></span>,
+ the name server that is queried needs to know the key and
+ algorithm that is being used. In BIND, this is done by
+ providing appropriate <span class="command"><strong>key</strong></span>
+ and <span class="command"><strong>server</strong></span> statements in
+ <code class="filename">named.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-m</span></dt>
+<dd>
+ <p>
+ Enable memory usage debugging.
+
+ </p>
+ </dd>
+<dt><span class="term">-p <em class="replaceable"><code>port</code></em></span></dt>
+<dd>
+ <p>
+ Send the query to a non-standard port on the server,
+ instead of the default port 53. This option would be used
+ to test a name server that has been configured to listen
+ for queries on a non-standard port number.
+ </p>
+ </dd>
+<dt><span class="term">-q <em class="replaceable"><code>name</code></em></span></dt>
+<dd>
+ <p>
+ The domain name to query. This is useful to distinguish
+ the <em class="parameter"><code>name</code></em> from other arguments.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd>
+ <p>
+ The resource record type to query. It can be any valid query
+ type. If it is a resource record type supported in BIND 9, it
+ can be given by the type mnemonic (such as "NS" or "AAAA").
+ The default query type is "A", unless the <code class="option">-x</code>
+ option is supplied to indicate a reverse lookup. A zone
+ transfer can be requested by specifying a type of AXFR. When
+ an incremental zone transfer (IXFR) is required, set the
+ <em class="parameter"><code>type</code></em> to <code class="literal">ixfr=N</code>.
+ The incremental zone transfer will contain the changes
+ made to the zone since the serial number in the zone's SOA
+ record was
+ <em class="parameter"><code>N</code></em>.
+ </p>
+ <p>
+ All resource record types can be expressed as "TYPEnn", where
+ "nn" is the number of the type. If the resource record type is
+ not supported in BIND 9, the result will be displayed as
+ described in RFC 3597.
+ </p>
+ </dd>
+<dt><span class="term">-u</span></dt>
+<dd>
+ <p>
+ Print query times in microseconds instead of milliseconds.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Print the version number and exit.
+ </p>
+ </dd>
+<dt><span class="term">-x <em class="replaceable"><code>addr</code></em></span></dt>
+<dd>
+ <p>
+ Simplified reverse lookups, for mapping addresses to
+ names. The <em class="parameter"><code>addr</code></em> is an IPv4 address
+ in dotted-decimal notation, or a colon-delimited IPv6
+ address. When the <code class="option">-x</code> is used, there is no
+ need to provide
+ the <em class="parameter"><code>name</code></em>, <em class="parameter"><code>class</code></em>
+ and <em class="parameter"><code>type</code></em>
+ arguments. <span class="command"><strong>dig</strong></span> automatically performs a
+ lookup for a name like
+ <code class="literal">94.2.0.192.in-addr.arpa</code> and sets the
+ query type and class to PTR and IN respectively. IPv6
+ addresses are looked up using nibble format under the
+ IP6.ARPA domain (but see also the <code class="option">-i</code>
+ option).
+ </p>
+ </dd>
+<dt><span class="term">-y <em class="replaceable"><code>[<span class="optional">hmac:</span>]keyname:secret</code></em></span></dt>
+<dd>
+ <p>
+ Sign queries using TSIG with the given authentication key.
+ <em class="parameter"><code>keyname</code></em> is the name of the key, and
+ <em class="parameter"><code>secret</code></em> is the base64 encoded shared secret.
+ <em class="parameter"><code>hmac</code></em> is the name of the key algorithm;
+ valid choices are <code class="literal">hmac-md5</code>,
+ <code class="literal">hmac-sha1</code>, <code class="literal">hmac-sha224</code>,
+ <code class="literal">hmac-sha256</code>, <code class="literal">hmac-sha384</code>, or
+ <code class="literal">hmac-sha512</code>. If <em class="parameter"><code>hmac</code></em>
+ is not specified, the default is <code class="literal">hmac-md5</code>
+ or if MD5 was disabled <code class="literal">hmac-sha256</code>.
+ </p>
+ <p>
+ NOTE: You should use the <code class="option">-k</code> option and
+ avoid the <code class="option">-y</code> option, because
+ with <code class="option">-y</code> the shared secret is supplied as
+ a command line argument in clear text. This may be visible
+ in the output from
+ <span class="citerefentry">
+ <span class="refentrytitle">ps</span>(1)
+ </span>
+ or in a history file maintained by the user's shell.
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>QUERY OPTIONS</h2>
+
+
+ <p><span class="command"><strong>dig</strong></span>
+ 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.
+ </p>
+
+ <p>
+ Each query option is identified by a keyword preceded by a plus sign
+ (<code class="literal">+</code>). Some keywords set or reset an
+ option. These may be preceded
+ by the string <code class="literal">no</code> to negate the meaning of
+ that keyword. Other
+ keywords assign values to options like the timeout interval. They
+ have the form <code class="option">+keyword=value</code>.
+ Keywords may be abbreviated, provided the abbreviation is
+ unambiguous; for example, <code class="literal">+cd</code> is equivalent
+ to <code class="literal">+cdflag</code>.
+ The query options are:
+
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="option">+[no]aaflag</code></span></dt>
+<dd>
+ <p>
+ A synonym for <em class="parameter"><code>+[no]aaonly</code></em>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]aaonly</code></span></dt>
+<dd>
+ <p>
+ Sets the "aa" flag in the query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]additional</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the additional section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]adflag</code></span></dt>
+<dd>
+ <p>
+ Set [do 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 indicate that some part
+ of the answer was insecure or not validated. This
+ bit is set by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]all</code></span></dt>
+<dd>
+ <p>
+ Set or clear all display flags.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]answer</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the answer section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]authority</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the authority section of a
+ reply. The default is to display it.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]badcookie</code></span></dt>
+<dd>
+ <p>
+ Retry lookup with the new server cookie if a
+ BADCOOKIE response is received.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]besteffort</code></span></dt>
+<dd>
+ <p>
+ Attempt to display the contents of messages which are
+ malformed. The default is to not display malformed
+ answers.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+bufsize=B</code></span></dt>
+<dd>
+ <p>
+ Set the UDP message buffer size advertised using EDNS0
+ to <em class="parameter"><code>B</code></em> 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 will cause a
+ EDNS query to be sent.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cdflag</code></span></dt>
+<dd>
+ <p>
+ Set [do not set] the CD (checking disabled) bit in
+ the query. This requests the server to not perform
+ DNSSEC validation of responses.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]class</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the CLASS when printing the
+ record.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cmd</code></span></dt>
+<dd>
+ <p>
+ Toggles the printing of the initial comment in the
+ output identifying the version of <span class="command"><strong>dig</strong></span>
+ and the query options that have been applied. This
+ comment is printed by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]comments</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of comment lines in the output.
+ The default is to print comments.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]cookie[<span class="optional">=####</span>]</code></span></dt>
+<dd>
+ <p>
+ Send a COOKIE EDNS option, with optional
+ value. Replaying a COOKIE from a previous response will
+ allow the server to identify a previous client. The
+ default is <code class="option">+cookie</code>.
+ </p>
+ <p>
+ <span class="command"><strong>+cookie</strong></span> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]crypto</code></span></dt>
+<dd>
+ <p>
+ Toggle the display of cryptographic fields in DNSSEC
+ records. The contents of these field 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]" or in the
+ DNSKEY case the key id is displayed as the replacement,
+ e.g. "[ key id = value ]".
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]defname</code></span></dt>
+<dd>
+ <p>
+ Deprecated, treated as a synonym for
+ <em class="parameter"><code>+[no]search</code></em>
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]dnssec</code></span></dt>
+<dd>
+ <p>
+ Requests DNSSEC records be sent by setting the DNSSEC
+ OK bit (DO) in the OPT record in the additional section
+ of the query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+domain=somename</code></span></dt>
+<dd>
+ <p>
+ Set the search list to contain the single domain
+ <em class="parameter"><code>somename</code></em>, as if specified in
+ a <span class="command"><strong>domain</strong></span> directive in
+ <code class="filename">/etc/resolv.conf</code>, and enable
+ search list processing as if the
+ <em class="parameter"><code>+search</code></em> option were given.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+dscp=value</code></span></dt>
+<dd>
+ <p>
+ Set 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]edns[=#]</code></span></dt>
+<dd>
+ <p>
+ Specify the EDNS version to query with. Valid values
+ are 0 to 255. Setting the EDNS version will cause
+ a EDNS query to be sent. <code class="option">+noedns</code>
+ clears the remembered EDNS version. EDNS is set to
+ 0 by default.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsflags[=#]</code></span></dt>
+<dd>
+ <p>
+ Set the must-be-zero EDNS flags bits (Z bits) to the
+ specified value. Decimal, hex and octal encodings are
+ accepted. Setting a named flag (e.g. DO) will silently be
+ ignored. By default, no Z bits are set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsnegotiation</code></span></dt>
+<dd>
+ <p>
+ Enable / disable EDNS version negotiation. By default
+ EDNS version negotiation is enabled.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ednsopt[=code[:value]]</code></span></dt>
+<dd>
+ <p>
+ Specify EDNS option with code point <code class="option">code</code>
+ and optionally payload of <code class="option">value</code> as a
+ hexadecimal string. <code class="option">code</code> can be
+ either an EDNS option name (for example,
+ <code class="literal">NSID</code> or <code class="literal">ECS</code>),
+ or an arbitrary numeric value. <code class="option">+noednsopt</code>
+ clears the EDNS options to be sent.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]expire</code></span></dt>
+<dd>
+ <p>
+ Send an EDNS Expire option.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]fail</code></span></dt>
+<dd>
+ <p>
+ Do not try the next server if you receive a SERVFAIL.
+ The default is to not try the next server which is
+ the reverse of normal stub resolver behavior.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]header-only</code></span></dt>
+<dd>
+ <p>
+ Send a query with a DNS header without a question section.
+ The default is to add a question section. The query type
+ and query name are ignored when this is set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]identify</code></span></dt>
+<dd>
+ <p>
+ Show [or do not show] the IP address and port number
+ that supplied the answer when the
+ <em class="parameter"><code>+short</code></em> option is enabled. If
+ short form answers are requested, the default is not
+ to show the source address and port number of the
+ server that provided the answer.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]idnin</code></span></dt>
+<dd>
+ <p>
+ Process [do not process] IDN domain names on input.
+ This requires IDN SUPPORT to have been enabled at
+ compile time. The default is to process IDN input.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]idnout</code></span></dt>
+<dd>
+ <p>
+ Convert [do not convert] puny code on output.
+ This requires IDN SUPPORT to have been enabled at
+ compile time. The default is to convert output.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ignore</code></span></dt>
+<dd>
+ <p>
+ Ignore truncation in UDP responses instead of retrying
+ with TCP. By default, TCP retries are performed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]keepopen</code></span></dt>
+<dd>
+ <p>
+ Keep the TCP socket open between queries and reuse
+ it rather than creating a new TCP socket for each
+ lookup. The default is <code class="option">+nokeepopen</code>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]mapped</code></span></dt>
+<dd>
+ <p>
+ Allow mapped IPv4 over IPv6 addresses to be used. The
+ default is <code class="option">+mapped</code>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]multiline</code></span></dt>
+<dd>
+ <p>
+ Print 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 <span class="command"><strong>dig</strong></span>
+ output.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+ndots=D</code></span></dt>
+<dd>
+ <p>
+ Set the number of dots that have to appear in
+ <em class="parameter"><code>name</code></em> to <em class="parameter"><code>D</code></em>
+ for it to be considered absolute. The default value
+ is that defined using the ndots statement in
+ <code class="filename">/etc/resolv.conf</code>, or 1 if no
+ ndots statement is present. Names with fewer dots
+ are interpreted as relative names and will be searched
+ for in the domains listed in the <code class="option">search</code>
+ or <code class="option">domain</code> directive in
+ <code class="filename">/etc/resolv.conf</code> if
+ <code class="option">+search</code> is set.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]nsid</code></span></dt>
+<dd>
+ <p>
+ Include an EDNS name server ID request when sending
+ a query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]nssearch</code></span></dt>
+<dd>
+ <p>
+ When this option is set, <span class="command"><strong>dig</strong></span>
+ attempts to find the authoritative name servers for
+ the zone containing the name being looked up and
+ display the SOA record that each name server has for
+ the zone.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]onesoa</code></span></dt>
+<dd>
+ <p>
+ Print only one (starting) SOA record when performing
+ an AXFR. The default is to print both the starting
+ and ending SOA records.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]opcode=value</code></span></dt>
+<dd>
+ <p>
+ Set [restore] the DNS message opcode to the specified
+ value. The default value is QUERY (0).
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]qr</code></span></dt>
+<dd>
+ <p>
+ Print [do not print] the query as it is sent. By
+ default, the query is not printed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]question</code></span></dt>
+<dd>
+ <p>
+ Print [do not print] the question section of a query
+ when an answer is returned. The default is to print
+ the question section as a comment.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]rdflag</code></span></dt>
+<dd>
+ <p>
+ A synonym for <em class="parameter"><code>+[no]recurse</code></em>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]recurse</code></span></dt>
+<dd>
+ <p>
+ Toggle the setting of the RD (recursion desired) bit
+ in the query. This bit is set by default, which means
+ <span class="command"><strong>dig</strong></span> normally sends recursive
+ queries. Recursion is automatically disabled when
+ the <em class="parameter"><code>+nssearch</code></em> or
+ <em class="parameter"><code>+trace</code></em> query options are used.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+retry=T</code></span></dt>
+<dd>
+ <p>
+ Sets the number of times to retry UDP queries to
+ server to <em class="parameter"><code>T</code></em> instead of the
+ default, 2. Unlike <em class="parameter"><code>+tries</code></em>,
+ this does not include the initial query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]rrcomments</code></span></dt>
+<dd>
+ <p>
+ Toggle 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.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]search</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] the search list defined by the
+ searchlist or domain directive in
+ <code class="filename">resolv.conf</code> (if any). The search
+ list is not used by default.
+ </p>
+ <p>
+ 'ndots' from <code class="filename">resolv.conf</code> (default 1)
+ which may be overridden by <em class="parameter"><code>+ndots</code></em>
+ determines if the name will be treated as relative
+ or not and hence whether a search is eventually
+ performed or not.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]short</code></span></dt>
+<dd>
+ <p>
+ Provide a terse answer. The default is to print the
+ answer in a verbose form.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]showsearch</code></span></dt>
+<dd>
+ <p>
+ Perform [do not perform] a search showing intermediate
+ results.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]sigchase</code></span></dt>
+<dd>
+ <p>
+ Chase DNSSEC signature chains. Requires dig be compiled
+ with -DDIG_SIGCHASE. This feature is deprecated.
+ Use <span class="command"><strong>delv</strong></span> instead.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+split=W</code></span></dt>
+<dd>
+ <p>
+ Split long hex- or base64-formatted fields in resource
+ records into chunks of <em class="parameter"><code>W</code></em>
+ characters (where <em class="parameter"><code>W</code></em> is rounded
+ up to the nearest multiple of 4).
+ <em class="parameter"><code>+nosplit</code></em> or
+ <em class="parameter"><code>+split=0</code></em> causes fields not to
+ be split at all. The default is 56 characters, or
+ 44 characters when multiline mode is active.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]stats</code></span></dt>
+<dd>
+ <p>
+ This query option toggles the printing of statistics:
+ when the query was made, the size of the reply and
+ so on. The default behavior is to print the query
+ statistics.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]subnet=addr[/prefix-length]</code></span></dt>
+<dd>
+ <p>
+ Send (don't send) an EDNS Client Subnet option with the
+ specified IP address or network prefix.
+ </p>
+ <p>
+ <span class="command"><strong>dig +subnet=0.0.0.0/0</strong></span>, or simply
+ <span class="command"><strong>dig +subnet=0</strong></span> for short, 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
+ <span class="emphasis"><em>not</em></span> be used when resolving
+ this query.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]tcp</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] TCP when querying name servers. The
+ default behavior is to use UDP unless a type
+ <code class="literal">any</code> or <code class="literal">ixfr=N</code>
+ query is requested, in which case the default is TCP.
+ AXFR queries always use TCP.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+timeout=T</code></span></dt>
+<dd>
+ <p>
+
+ Sets the timeout for a query to
+ <em class="parameter"><code>T</code></em> seconds. The default
+ timeout is 5 seconds.
+ An attempt to set <em class="parameter"><code>T</code></em> to less
+ than 1 will result
+ in a query timeout of 1 second being applied.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]topdown</code></span></dt>
+<dd>
+ <p>
+ When chasing DNSSEC signature chains perform a top-down
+ validation. Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <span class="command"><strong>delv</strong></span> instead.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]trace</code></span></dt>
+<dd>
+ <p>
+ Toggle tracing of the delegation path from the root
+ name servers for the name being looked up. Tracing
+ is disabled by default. When tracing is enabled,
+ <span class="command"><strong>dig</strong></span> makes iterative queries to
+ resolve the name being looked up. It will follow
+ referrals from the root servers, showing the answer
+ from each server that was used to resolve the lookup.
+ </p> <p>
+ If @server is also specified, it affects only the
+ initial query for the root zone name servers.
+ </p> <p>
+ <span class="command"><strong>+dnssec</strong></span> is also set when +trace
+ is set to better emulate the default queries from a
+ nameserver.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+tries=T</code></span></dt>
+<dd>
+ <p>
+ Sets the number of times to try UDP queries to server
+ to <em class="parameter"><code>T</code></em> instead of the default,
+ 3. If <em class="parameter"><code>T</code></em> is less than or equal
+ to zero, the number of tries is silently rounded up
+ to 1.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+trusted-key=####</code></span></dt>
+<dd>
+ <p>
+ Specifies a file containing trusted keys to be used
+ with <code class="option">+sigchase</code>. Each DNSKEY record
+ must be on its own line.
+ </p> <p>
+ If not specified, <span class="command"><strong>dig</strong></span> will look
+ for <code class="filename">/etc/trusted-key.key</code> then
+ <code class="filename">trusted-key.key</code> in the current
+ directory.
+ </p> <p>
+ Requires dig be compiled with -DDIG_SIGCHASE.
+ This feature is deprecated. Use <span class="command"><strong>delv</strong></span> instead.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ttlid</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the TTL when printing the
+ record.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]ttlunits</code></span></dt>
+<dd>
+ <p>
+ Display [do not display] the TTL in friendly human-readable
+ time units of "s", "m", "h", "d", and "w", representing
+ seconds, minutes, hours, days and weeks. Implies +ttlid.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]unknownformat</code></span></dt>
+<dd>
+ <p>
+ Print all RDATA in unknown RR type presentation format
+ (RFC 3597). The default is to print RDATA for known types
+ in the type's presentation format.
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]vc</code></span></dt>
+<dd>
+ <p>
+ Use [do not use] TCP when querying name servers. This
+ alternate syntax to <em class="parameter"><code>+[no]tcp</code></em>
+ is provided for backwards compatibility. The "vc"
+ stands for "virtual circuit".
+ </p>
+ </dd>
+<dt><span class="term"><code class="option">+[no]zflag</code></span></dt>
+<dd>
+ <p>
+ Set [do not set] the last unassigned DNS header flag in a
+ DNS query. This flag is off by default.
+ </p>
+ </dd>
+</dl></div>
+<p>
+
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>MULTIPLE QUERIES</h2>
+
+
+ <p>
+ The BIND 9 implementation of <span class="command"><strong>dig </strong></span>
+ supports
+ specifying multiple queries on the command line (in addition to
+ supporting the <code class="option">-f</code> batch file option). Each of those
+ queries can be supplied with its own set of flags, options and query
+ options.
+ </p>
+
+ <p>
+ In this case, each <em class="parameter"><code>query</code></em> argument
+ represent an
+ individual query in the command-line syntax described above. Each
+ consists of any of the standard options and flags, the name to be
+ looked up, an optional query type and class and any query options that
+ should be applied to that query.
+ </p>
+
+ <p>
+ A global set of query options, which should be applied to all queries,
+ can also be supplied. These global query options must precede the
+ first tuple of name, class, type, options, flags, and query options
+ supplied on the command line. Any global query options (except
+ the <code class="option">+[no]cmd</code> option) can be
+ overridden by a query-specific set of query options. For example:
+ </p>
+<pre class="programlisting">
+dig +qr www.isc.org any -x 127.0.0.1 isc.org ns +noqr
+</pre>
+<p>
+ shows how <span class="command"><strong>dig</strong></span> could be used from the
+ command line
+ to make three lookups: an ANY query for <code class="literal">www.isc.org</code>, a
+ reverse lookup of 127.0.0.1 and a query for the NS records of
+ <code class="literal">isc.org</code>.
+
+ A global query option of <em class="parameter"><code>+qr</code></em> is
+ applied, so
+ that <span class="command"><strong>dig</strong></span> shows the initial query it made
+ for each
+ lookup. The final query has a local query option of
+ <em class="parameter"><code>+noqr</code></em> which means that <span class="command"><strong>dig</strong></span>
+ will not print the initial query when it looks up the NS records for
+ <code class="literal">isc.org</code>.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>IDN SUPPORT</h2>
+
+ <p>
+ If <span class="command"><strong>dig</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span class="command"><strong>dig</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, use
+ parameters <em class="parameter"><code>+noidnin</code></em> and
+ <em class="parameter"><code>+noidnout</code></em>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.13"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/resolv.conf</code>
+ </p>
+ <p><code class="filename">${HOME}/.digrc</code>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.14"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">delv</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">host</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">dnssec-keygen</span>(8)
+ </span>,
+ <em class="citetitle">RFC 1035</em>.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.15"></a><h2>BUGS</h2>
+
+ <p>
+ There are probably too many query options.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c
new file mode 100644
index 0000000..aa5315d
--- /dev/null
+++ b/bin/dig/dighost.c
@@ -0,0 +1,6676 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file
+ * \note
+ * Notice to programmers: Do not use this code as an example of how to
+ * use the ISC library to perform DNS lookups. Dig and Host both operate
+ * on the request level, since they allow fine-tuning of output and are
+ * intended as debugging tools. As a result, they perform many of the
+ * functions which could be better handled using the dns_resolver
+ * functions in most applications.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDN_SUPPORT
+#ifdef WITH_IDNKIT
+#include <idn/result.h>
+#include <idn/log.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#endif
+
+#ifdef WITH_LIBIDN2
+#include <idn2.h>
+#endif
+#endif /* WITH_IDN_SUPPORT */
+
+#include <dns/byaddr.h>
+#ifdef DIG_SIGCHASE
+#include <dns/callbacks.h>
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/master.h>
+#include <dns/nsec.h>
+#include <isc/random.h>
+#include <ctype.h>
+#endif
+#include <dns/fixedname.h>
+#include <dns/log.h>
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/rcode.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdatalist.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/result.h>
+#include <dns/tsig.h>
+
+#include <dst/dst.h>
+#include <dst/result.h>
+
+#include <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/hex.h>
+#include <isc/lang.h>
+#include <isc/log.h>
+#include <isc/netaddr.h>
+#include <isc/netdb.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/safe.h>
+#include <isc/serial.h>
+#include <isc/sockaddr.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <pk11/site.h>
+
+#include <isccfg/namedconf.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+#include <bind9/getaddresses.h>
+
+#include <dig/dig.h>
+
+#ifdef PKCS11CRYPTO
+#include <pk11/result.h>
+#endif
+
+#if ! defined(NS_INADDRSZ)
+#define NS_INADDRSZ 4
+#endif
+
+#if ! defined(NS_IN6ADDRSZ)
+#define NS_IN6ADDRSZ 16
+#endif
+
+static lwres_context_t *lwctx = NULL;
+static lwres_conf_t *lwconf;
+
+dig_lookuplist_t lookup_list;
+dig_serverlist_t server_list;
+dig_searchlistlist_t search_list;
+
+bool
+ check_ra = false,
+ have_ipv4 = false,
+ have_ipv6 = false,
+ specified_source = false,
+ free_now = false,
+ cancel_now = false,
+ usesearch = false,
+ showsearch = false,
+ qr = false,
+ is_dst_up = false,
+ keep_open = false,
+ verbose = false;
+in_port_t port = 53;
+unsigned int timeout = 0;
+unsigned int extrabytes;
+isc_mem_t *mctx = NULL;
+isc_log_t *lctx = NULL;
+isc_taskmgr_t *taskmgr = NULL;
+isc_task_t *global_task = NULL;
+isc_timermgr_t *timermgr = NULL;
+isc_socketmgr_t *socketmgr = NULL;
+isc_sockaddr_t bind_address;
+isc_sockaddr_t bind_any;
+int sendcount = 0;
+int recvcount = 0;
+int sockcount = 0;
+int ndots = -1;
+int tries = 3;
+int lookup_counter = 0;
+
+static char servercookie[256];
+
+#ifdef WITH_IDN_SUPPORT
+static void idn_initialize(void);
+static isc_result_t idn_locale_to_ace(const char *from,
+ char *to,
+ size_t tolen);
+#endif /* WITH_IDN_SUPPORT */
+
+#ifdef WITH_IDN_OUT_SUPPORT
+static isc_result_t idn_ace_to_locale(const char *from,
+ char *to,
+ size_t tolen);
+static isc_result_t output_filter(isc_buffer_t *buffer,
+ unsigned int used_org,
+ bool absolute);
+#define MAXDLEN 256
+
+#ifdef WITH_IDNKIT
+int idnoptions = 0;
+#endif
+#endif /* WITH_IDN_OUT_SUPPORT */
+
+isc_socket_t *keep = NULL;
+isc_sockaddr_t keepaddr;
+
+/*%
+ * Exit Codes:
+ *
+ *\li 0 Everything went well, including things like NXDOMAIN
+ *\li 1 Usage error
+ *\li 7 Got too many RR's or Names
+ *\li 8 Couldn't open batch file
+ *\li 9 No reply from server
+ *\li 10 Internal error
+ */
+int exitcode = 0;
+int fatalexit = 0;
+char keynametext[MXNAME];
+char keyfile[MXNAME] = "";
+char keysecret[MXNAME] = "";
+unsigned char cookie_secret[33];
+unsigned char cookie[8];
+dns_name_t *hmacname = NULL;
+unsigned int digestbits = 0;
+isc_buffer_t *namebuf = NULL;
+dns_tsigkey_t *tsigkey = NULL;
+bool validated = true;
+isc_entropy_t *entp = NULL;
+isc_mempool_t *commctx = NULL;
+bool debugging = false;
+bool debugtiming = false;
+bool memdebugging = false;
+char *progname = NULL;
+isc_mutex_t lookup_lock;
+dig_lookup_t *current_lookup = NULL;
+
+#ifdef DIG_SIGCHASE
+
+isc_result_t get_trusted_key(void);
+dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ bool *lookedup,
+ dns_name_t *rdata_name);
+dns_rdataset_t * chase_scanname_section(dns_message_t *msg,
+ dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ int section);
+isc_result_t advanced_rrsearch(dns_rdataset_t **rdataset,
+ dns_name_t *name,
+ dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ bool *lookedup);
+isc_result_t sigchase_verify_sig_key(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dst_key_t* dnsseckey,
+ dns_rdataset_t *sigrdataset);
+isc_result_t sigchase_verify_sig(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset);
+isc_result_t sigchase_verify_ds(dns_name_t *name,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset);
+void sigchase(dns_message_t *msg);
+void print_rdata(dns_rdata_t *rdata, isc_mem_t *mctx);
+void print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset);
+void dup_name(dns_name_t *source, dns_name_t* target);
+void free_name(dns_name_t *name);
+void dump_database(void);
+void dump_database_section(dns_message_t *msg, int section);
+dns_rdataset_t * search_type(dns_name_t *name, dns_rdatatype_t type,
+ dns_rdatatype_t covers);
+isc_result_t contains_trusted_key(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset);
+void print_type(dns_rdatatype_t type);
+isc_result_t prove_nx_domain(dns_message_t * msg,
+ dns_name_t * name,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+isc_result_t prove_nx_type(dns_message_t * msg, dns_name_t *name,
+ dns_rdataset_t *nsec,
+ dns_rdataclass_t rdclass,
+ dns_rdatatype_t type,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+isc_result_t prove_nx(dns_message_t * msg, dns_name_t * name,
+ dns_rdataclass_t rdclass,
+ dns_rdatatype_t type,
+ dns_name_t * rdata_name,
+ dns_rdataset_t ** rdataset,
+ dns_rdataset_t ** sigrdataset);
+static void nameFromString(const char *str, dns_name_t *p_ret);
+int inf_name(dns_name_t * name1, dns_name_t * name2);
+isc_result_t removetmpkey(const char *file);
+void clean_trustedkey(void);
+isc_result_t insert_trustedkey(void *arg, dns_name_t *name,
+ dns_rdataset_t *rdataset);
+#if DIG_SIGCHASE_BU
+isc_result_t getneededrr(dns_message_t *msg);
+void sigchase_bottom_up(dns_message_t *msg);
+void sigchase_bu(dns_message_t *msg);
+#endif
+#if DIG_SIGCHASE_TD
+isc_result_t initialization(dns_name_t *name);
+isc_result_t prepare_lookup(dns_name_t *name);
+isc_result_t grandfather_pb_test(dns_name_t * zone_name,
+ dns_rdataset_t *sigrdataset);
+isc_result_t child_of_zone(dns_name_t *name,
+ dns_name_t *zone_name,
+ dns_name_t *child_name);
+void sigchase_td(dns_message_t *msg);
+#endif
+char trustedkey[MXNAME] = "";
+
+dns_rdataset_t *chase_rdataset = NULL;
+dns_rdataset_t *chase_sigrdataset = NULL;
+dns_rdataset_t *chase_dsrdataset = NULL;
+dns_rdataset_t *chase_sigdsrdataset = NULL;
+dns_rdataset_t *chase_keyrdataset = NULL;
+dns_rdataset_t *chase_sigkeyrdataset = NULL;
+dns_rdataset_t *chase_nsrdataset = NULL;
+
+dns_name_t chase_name; /* the query name */
+#if DIG_SIGCHASE_TD
+/*
+ * the current name is the parent name when we follow delegation
+ */
+dns_name_t chase_current_name;
+/*
+ * the child name is used for delegation (NS DS responses in AUTHORITY section)
+ */
+dns_name_t chase_authority_name;
+#endif
+#if DIG_SIGCHASE_BU
+dns_name_t chase_signame;
+#endif
+
+
+bool chase_siglookedup = false;
+bool chase_keylookedup = false;
+bool chase_sigkeylookedup = false;
+bool chase_dslookedup = false;
+bool chase_sigdslookedup = false;
+#if DIG_SIGCHASE_TD
+bool chase_nslookedup = false;
+bool chase_lookedup = false;
+
+
+bool delegation_follow = false;
+bool grandfather_pb = false;
+bool have_response = false;
+bool have_delegation_ns = false;
+dns_message_t * error_message = NULL;
+#endif
+
+bool dsvalidating = false;
+bool chase_name_dup = false;
+
+ISC_LIST(dig_message_t) chase_message_list;
+ISC_LIST(dig_message_t) chase_message_list2;
+
+
+#define MAX_TRUSTED_KEY 5
+typedef struct struct_trusted_key_list {
+ dst_key_t * key[MAX_TRUSTED_KEY];
+ int nb_tk;
+} struct_tk_list;
+
+struct_tk_list tk_list = { {NULL, NULL, NULL, NULL, NULL}, 0};
+
+#endif
+
+#define DIG_MAX_ADDRESSES 20
+
+/*%
+ * Apply and clear locks at the event level in global task.
+ * Can I get rid of these using shutdown events? XXX
+ */
+#define LOCK_LOOKUP {\
+ debug("lock_lookup %s:%d", __FILE__, __LINE__);\
+ check_result(isc_mutex_lock((&lookup_lock)), "isc_mutex_lock");\
+ debug("success");\
+}
+#define UNLOCK_LOOKUP {\
+ debug("unlock_lookup %s:%d", __FILE__, __LINE__);\
+ check_result(isc_mutex_unlock((&lookup_lock)),\
+ "isc_mutex_unlock");\
+}
+
+/* dynamic callbacks */
+
+#ifdef DIG_SIGCHASE
+isc_result_t
+(*dighost_printrdataset)(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target);
+#endif
+
+isc_result_t
+(*dighost_printmessage)(dig_query_t *query, dns_message_t *msg,
+ bool headers);
+
+void
+(*dighost_received)(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query);
+
+void
+(*dighost_trying)(char *frm, dig_lookup_t *lookup);
+
+void
+(*dighost_shutdown)(void);
+
+/* forward declarations */
+
+static void
+cancel_lookup(dig_lookup_t *lookup);
+
+static void
+recv_done(isc_task_t *task, isc_event_t *event);
+
+static void
+send_udp(dig_query_t *query);
+
+static void
+connect_timeout(isc_task_t *task, isc_event_t *event);
+
+static void
+launch_next_query(dig_query_t *query, bool include_question);
+
+static void
+check_next_lookup(dig_lookup_t *lookup);
+
+static bool
+next_origin(dig_lookup_t *oldlookup);
+
+static void *
+mem_alloc(void *arg, size_t size) {
+ return (isc_mem_get(arg, size));
+}
+
+static void
+mem_free(void *arg, void *mem, size_t size) {
+ isc_mem_put(arg, mem, size);
+}
+
+char *
+next_token(char **stringp, const char *delim) {
+ char *res;
+
+ do {
+ res = strsep(stringp, delim);
+ if (res == NULL)
+ break;
+ } while (*res == '\0');
+ return (res);
+}
+
+static int
+count_dots(char *string) {
+ char *s;
+ int i = 0;
+
+ s = string;
+ while (*s != '\0') {
+ if (*s == '.')
+ i++;
+ s++;
+ }
+ return (i);
+}
+
+static void
+hex_dump(isc_buffer_t *b) {
+ unsigned int len, i;
+ isc_region_t r;
+
+ isc_buffer_usedregion(b, &r);
+
+ printf("%u bytes\n", r.length);
+ for (len = 0; len < r.length; len++) {
+ printf("%02x ", r.base[len]);
+ if (len % 16 == 15) {
+ fputs(" ", stdout);
+ for (i = len - 15; i <= len; i++) {
+ if (r.base[i] >= '!' && r.base[i] <= '}')
+ putchar(r.base[i]);
+ else
+ putchar('.');
+ }
+ printf("\n");
+ }
+ }
+ if (len % 16 != 0) {
+ for (i = len; (i % 16) != 0; i++)
+ fputs(" ", stdout);
+ fputs(" ", stdout);
+ for (i = ((len>>4)<<4); i < len; i++) {
+ if (r.base[i] >= '!' && r.base[i] <= '}')
+ putchar(r.base[i]);
+ else
+ putchar('.');
+ }
+ printf("\n");
+ }
+}
+
+/*%
+ * 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, size_t len, char **p, char *end) {
+ if (*p + len > end)
+ 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, '.');
+ size_t len;
+ if (dot != NULL) {
+ isc_result_t result;
+ result = reverse_octets(dot + 1, p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ result = append(".", 1, p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ len = (int) (dot - in);
+ } else {
+ len = (int) strlen(in);
+ }
+ return (append(in, len, p, end));
+}
+
+isc_result_t
+get_reverse(char *reverse, size_t len, char *value, bool ip6_int,
+ bool strict)
+{
+ 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;
+
+ if (ip6_int)
+ options |= DNS_BYADDROPT_IPV6INT;
+ name = dns_fixedname_initname(&fname);
+ result = dns_byaddr_createptrname2(&addr, options, name);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_format(name, reverse, (unsigned int)len);
+ return (ISC_R_SUCCESS);
+ } else {
+ /*
+ * Not a valid IPv6 address. Assume IPv4.
+ * If 'strict' is not set, 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;
+ if (strict && inet_pton(AF_INET, value, &addr.type.in) != 1)
+ return (DNS_R_BADDOTTEDQUAD);
+ result = reverse_octets(value, &p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ /* Append .in-addr.arpa. and a terminating NUL. */
+ result = append(".in-addr.arpa.", 15, &p, end);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ return (ISC_R_SUCCESS);
+ }
+}
+
+void
+fatal(const char *format, ...) {
+ va_list args;
+
+ fflush(stdout);
+ fprintf(stderr, "%s: ", progname);
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ if (exitcode < 10)
+ exitcode = 10;
+ if (fatalexit != 0)
+ exitcode = fatalexit;
+ exit(exitcode);
+}
+
+void
+debug(const char *format, ...) {
+ va_list args;
+ isc_time_t t;
+
+ if (debugging) {
+ fflush(stdout);
+ if (debugtiming) {
+ TIME_NOW(&t);
+ fprintf(stderr, "%u.%06u: ", isc_time_seconds(&t),
+ isc_time_nanoseconds(&t) / 1000);
+ }
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+void
+check_result(isc_result_t result, const char *msg) {
+ if (result != ISC_R_SUCCESS) {
+ fatal("%s: %s", msg, isc_result_totext(result));
+ }
+}
+
+/*%
+ * Create a server structure, which is part of the lookup structure.
+ * This is little more than a linked list of servers to query in hopes
+ * of finding the answer the user is looking for
+ */
+dig_server_t *
+make_server(const char *servname, const char *userarg) {
+ dig_server_t *srv;
+
+ REQUIRE(servname != NULL);
+
+ debug("make_server(%s)", servname);
+ srv = isc_mem_allocate(mctx, sizeof(struct dig_server));
+ if (srv == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ strlcpy(srv->servername, servname, MXNAME);
+ strlcpy(srv->userarg, userarg, MXNAME);
+ ISC_LINK_INIT(srv, link);
+ return (srv);
+}
+
+static int
+addr2af(int lwresaddrtype)
+{
+ int af = 0;
+
+ switch (lwresaddrtype) {
+ case LWRES_ADDRTYPE_V4:
+ af = AF_INET;
+ break;
+
+ case LWRES_ADDRTYPE_V6:
+ af = AF_INET6;
+ break;
+ }
+
+ return (af);
+}
+
+/*%
+ * Create a copy of the server list from the lwres configuration structure.
+ * The dest list must have already had ISC_LIST_INIT applied.
+ */
+static void
+copy_server_list(lwres_conf_t *confdata, dig_serverlist_t *dest) {
+ dig_server_t *newsrv;
+ char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") +
+ sizeof("%4000000000")];
+ int af;
+ int i;
+
+ debug("copy_server_list()");
+ for (i = 0; i < confdata->nsnext; i++) {
+ af = addr2af(confdata->nameservers[i].family);
+
+ if (af == AF_INET && !have_ipv4)
+ continue;
+ if (af == AF_INET6 && !have_ipv6)
+ continue;
+
+ lwres_net_ntop(af, confdata->nameservers[i].address,
+ tmp, sizeof(tmp));
+ if (af == AF_INET6 && confdata->nameservers[i].zone != 0) {
+ char buf[sizeof("%4000000000")];
+ snprintf(buf, sizeof(buf), "%%%u",
+ confdata->nameservers[i].zone);
+ strlcat(tmp, buf, sizeof(tmp));
+ }
+ newsrv = make_server(tmp, tmp);
+ ISC_LINK_INIT(newsrv, link);
+ ISC_LIST_ENQUEUE(*dest, newsrv, link);
+ }
+}
+
+void
+flush_server_list(void) {
+ dig_server_t *s, *ps;
+
+ debug("flush_server_list()");
+ s = ISC_LIST_HEAD(server_list);
+ while (s != NULL) {
+ ps = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(server_list, ps, link);
+ isc_mem_free(mctx, ps);
+ }
+}
+
+void
+set_nameserver(char *opt) {
+ isc_result_t result;
+ isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
+ isc_netaddr_t netaddr;
+ int count, i;
+ dig_server_t *srv;
+ char tmp[ISC_NETADDR_FORMATSIZE];
+
+ if (opt == NULL)
+ return;
+
+ result = bind9_getaddresses(opt, 0, sockaddrs,
+ DIG_MAX_ADDRESSES, &count);
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ opt, isc_result_totext(result));
+
+ flush_server_list();
+
+ for (i = 0; i < count; i++) {
+ isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
+ isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
+ srv = make_server(tmp, opt);
+ if (srv == NULL)
+ fatal("memory allocation failure");
+ ISC_LIST_APPEND(server_list, srv, link);
+ }
+}
+
+static isc_result_t
+add_nameserver(lwres_conf_t *confdata, const char *addr, int af) {
+
+ int i = confdata->nsnext;
+
+ if (confdata->nsnext >= LWRES_CONFMAXNAMESERVERS)
+ return (ISC_R_FAILURE);
+
+ switch (af) {
+ case AF_INET:
+ confdata->nameservers[i].family = LWRES_ADDRTYPE_V4;
+ confdata->nameservers[i].length = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ confdata->nameservers[i].family = LWRES_ADDRTYPE_V6;
+ confdata->nameservers[i].length = NS_IN6ADDRSZ;
+ break;
+ default:
+ return (ISC_R_FAILURE);
+ }
+
+ if (lwres_net_pton(af, addr, &confdata->nameservers[i].address) == 1) {
+ confdata->nsnext++;
+ return (ISC_R_SUCCESS);
+ }
+ return (ISC_R_FAILURE);
+}
+
+/*%
+ * Produce a cloned server list. The dest list must have already had
+ * ISC_LIST_INIT applied.
+ */
+void
+clone_server_list(dig_serverlist_t src, dig_serverlist_t *dest) {
+ dig_server_t *srv, *newsrv;
+
+ debug("clone_server_list()");
+ srv = ISC_LIST_HEAD(src);
+ while (srv != NULL) {
+ newsrv = make_server(srv->servername, srv->userarg);
+ ISC_LINK_INIT(newsrv, link);
+ ISC_LIST_ENQUEUE(*dest, newsrv, link);
+ srv = ISC_LIST_NEXT(srv, link);
+ }
+}
+
+/*%
+ * Create an empty lookup structure, which holds all the information needed
+ * to get an answer to a user's question. This structure contains two
+ * linked lists: the server list (servers to query) and the query list
+ * (outstanding queries which have been made to the listed servers).
+ */
+dig_lookup_t *
+make_empty_lookup(void) {
+ dig_lookup_t *looknew;
+
+ debug("make_empty_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = isc_mem_allocate(mctx, sizeof(struct dig_lookup));
+ if (looknew == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ looknew->pending = true;
+ looknew->textname[0] = 0;
+ looknew->cmdline[0] = 0;
+ looknew->rdtype = dns_rdatatype_a;
+ looknew->qrdtype = dns_rdatatype_a;
+ looknew->rdclass = dns_rdataclass_in;
+ looknew->rdtypeset = false;
+ looknew->rdclassset = false;
+ looknew->sendspace = NULL;
+ looknew->sendmsg = NULL;
+ looknew->name = NULL;
+ looknew->oname = NULL;
+ looknew->xfr_q = NULL;
+ looknew->current_query = NULL;
+ looknew->doing_xfr = false;
+ looknew->ixfr_serial = 0;
+ looknew->trace = false;
+ looknew->trace_root = false;
+ looknew->identify = false;
+ looknew->identify_previous_line = false;
+ looknew->ignore = false;
+ looknew->servfail_stops = true;
+ looknew->besteffort = true;
+ looknew->dnssec = false;
+ looknew->ednsflags = 0;
+ looknew->opcode = dns_opcode_query;
+ looknew->expire = false;
+ looknew->nsid = false;
+ looknew->header_only = false;
+ looknew->sendcookie = false;
+ looknew->seenbadcookie = false;
+ looknew->badcookie = true;
+#ifdef WITH_IDN_SUPPORT
+ looknew->idnin = true;
+#else
+ looknew->idnin = false;
+#endif
+#ifdef WITH_IDN_OUT_SUPPORT
+ looknew->idnout = true;
+#else
+ looknew->idnout = false;
+#endif
+#ifdef DIG_SIGCHASE
+ looknew->sigchase = false;
+#if DIG_SIGCHASE_TD
+ looknew->do_topdown = false;
+ looknew->trace_root_sigchase = false;
+ looknew->rdtype_sigchaseset = false;
+ looknew->rdtype_sigchase = dns_rdatatype_any;
+ looknew->qrdtype_sigchase = dns_rdatatype_any;
+ looknew->rdclass_sigchase = dns_rdataclass_in;
+ looknew->rdclass_sigchaseset = false;
+#endif
+#endif
+ looknew->udpsize = 0;
+ looknew->edns = -1;
+ looknew->recurse = true;
+ looknew->aaonly = false;
+ looknew->adflag = false;
+ looknew->cdflag = false;
+ looknew->print_unknown_format = false;
+ looknew->zflag = false;
+ looknew->ns_search_only = false;
+ looknew->origin = NULL;
+ looknew->tsigctx = NULL;
+ looknew->querysig = NULL;
+ looknew->retries = tries;
+ looknew->nsfound = 0;
+ looknew->tcp_mode = false;
+ looknew->tcp_mode_set = false;
+ looknew->ip6_int = false;
+ looknew->comments = true;
+ looknew->stats = true;
+ looknew->section_question = true;
+ looknew->section_answer = true;
+ looknew->section_authority = true;
+ looknew->section_additional = true;
+ looknew->new_search = false;
+ looknew->done_as_is = false;
+ looknew->need_search = false;
+ looknew->ecs_addr = NULL;
+ looknew->cookie = NULL;
+ looknew->ednsopts = NULL;
+ looknew->ednsoptscnt = 0;
+ looknew->ednsneg = true;
+ looknew->mapped = true;
+ looknew->dscp = -1;
+ looknew->eoferr = 0;
+ dns_fixedname_init(&looknew->fdomain);
+ ISC_LINK_INIT(looknew, link);
+ ISC_LIST_INIT(looknew->q);
+ ISC_LIST_INIT(looknew->connecting);
+ ISC_LIST_INIT(looknew->my_server_list);
+ return (looknew);
+}
+
+#define EDNSOPT_OPTIONS 100U
+
+static void
+cloneopts(dig_lookup_t *looknew, dig_lookup_t *lookold) {
+ size_t len = sizeof(looknew->ednsopts[0]) * EDNSOPT_OPTIONS;
+ size_t i;
+ looknew->ednsopts = isc_mem_allocate(mctx, len);
+ if (looknew->ednsopts == NULL)
+ fatal("out of memory");
+ for (i = 0; i < EDNSOPT_OPTIONS; i++) {
+ looknew->ednsopts[i].code = 0;
+ looknew->ednsopts[i].length = 0;
+ looknew->ednsopts[i].value = NULL;
+ }
+ looknew->ednsoptscnt = 0;
+ if (lookold == NULL || lookold->ednsopts == NULL)
+ return;
+
+ for (i = 0; i < lookold->ednsoptscnt; i++) {
+ len = lookold->ednsopts[i].length;
+ if (len != 0) {
+ INSIST(lookold->ednsopts[i].value != NULL);
+ looknew->ednsopts[i].value =
+ isc_mem_allocate(mctx, len);
+ if (looknew->ednsopts[i].value == NULL)
+ fatal("out of memory");
+ memmove(looknew->ednsopts[i].value,
+ lookold->ednsopts[i].value, len);
+ }
+ looknew->ednsopts[i].code = lookold->ednsopts[i].code;
+ looknew->ednsopts[i].length = len;
+ }
+ looknew->ednsoptscnt = lookold->ednsoptscnt;
+}
+
+/*%
+ * Clone a lookup, perhaps copying the server list. This does not clone
+ * the query list, since it will be regenerated by the setup_lookup()
+ * function, nor does it queue up the new lookup for processing.
+ * Caution: If you don't clone the servers, you MUST clone the server
+ * list separately from somewhere else, or construct it by hand.
+ */
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, bool servers) {
+ dig_lookup_t *looknew;
+
+ debug("clone_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = make_empty_lookup();
+ INSIST(looknew != NULL);
+ strlcpy(looknew->textname, lookold->textname, MXNAME);
+#if DIG_SIGCHASE_TD
+ strlcpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
+#endif
+ strlcpy(looknew->cmdline, lookold->cmdline, MXNAME);
+ looknew->textname[MXNAME-1] = 0;
+ looknew->rdtype = lookold->rdtype;
+ looknew->qrdtype = lookold->qrdtype;
+ looknew->rdclass = lookold->rdclass;
+ looknew->rdtypeset = lookold->rdtypeset;
+ looknew->rdclassset = lookold->rdclassset;
+ looknew->doing_xfr = lookold->doing_xfr;
+ looknew->ixfr_serial = lookold->ixfr_serial;
+ looknew->trace = lookold->trace;
+ looknew->trace_root = lookold->trace_root;
+ looknew->identify = lookold->identify;
+ looknew->identify_previous_line = lookold->identify_previous_line;
+ looknew->ignore = lookold->ignore;
+ looknew->servfail_stops = lookold->servfail_stops;
+ looknew->besteffort = lookold->besteffort;
+ looknew->dnssec = lookold->dnssec;
+ looknew->ednsflags = lookold->ednsflags;
+ looknew->opcode = lookold->opcode;
+ looknew->expire = lookold->expire;
+ looknew->nsid = lookold->nsid;
+ looknew->header_only = lookold->header_only;
+ looknew->sendcookie = lookold->sendcookie;
+ looknew->seenbadcookie = lookold->seenbadcookie;
+ looknew->badcookie = lookold->badcookie;
+ looknew->cookie = lookold->cookie;
+ if (lookold->ednsopts != NULL) {
+ cloneopts(looknew, lookold);
+ } else {
+ looknew->ednsopts = NULL;
+ looknew->ednsoptscnt = 0;
+ }
+ looknew->ednsneg = lookold->ednsneg;
+ looknew->mapped = lookold->mapped;
+ looknew->idnin = lookold->idnin;
+ looknew->idnout = lookold->idnout;
+#ifdef DIG_SIGCHASE
+ looknew->sigchase = lookold->sigchase;
+#if DIG_SIGCHASE_TD
+ looknew->do_topdown = lookold->do_topdown;
+ looknew->trace_root_sigchase = lookold->trace_root_sigchase;
+ looknew->rdtype_sigchaseset = lookold->rdtype_sigchaseset;
+ looknew->rdtype_sigchase = lookold->rdtype_sigchase;
+ looknew->qrdtype_sigchase = lookold->qrdtype_sigchase;
+ looknew->rdclass_sigchase = lookold->rdclass_sigchase;
+ looknew->rdclass_sigchaseset = lookold->rdclass_sigchaseset;
+#endif
+#endif
+ looknew->udpsize = lookold->udpsize;
+ looknew->edns = lookold->edns;
+ looknew->recurse = lookold->recurse;
+ looknew->aaonly = lookold->aaonly;
+ looknew->adflag = lookold->adflag;
+ looknew->cdflag = lookold->cdflag;
+ looknew->print_unknown_format = lookold->print_unknown_format;
+ looknew->zflag = lookold->zflag;
+ looknew->ns_search_only = lookold->ns_search_only;
+ looknew->tcp_mode = lookold->tcp_mode;
+ looknew->tcp_mode_set = lookold->tcp_mode_set;
+ looknew->comments = lookold->comments;
+ looknew->stats = lookold->stats;
+ looknew->section_question = lookold->section_question;
+ looknew->section_answer = lookold->section_answer;
+ looknew->section_authority = lookold->section_authority;
+ looknew->section_additional = lookold->section_additional;
+ looknew->origin = lookold->origin;
+ looknew->retries = lookold->retries;
+ looknew->tsigctx = NULL;
+ looknew->need_search = lookold->need_search;
+ looknew->done_as_is = lookold->done_as_is;
+ looknew->dscp = lookold->dscp;
+ looknew->eoferr = lookold->eoferr;
+
+ if (lookold->ecs_addr != NULL) {
+ size_t len = sizeof(isc_sockaddr_t);
+ looknew->ecs_addr = isc_mem_allocate(mctx, len);
+ if (looknew->ecs_addr == NULL)
+ fatal("out of memory");
+ memmove(looknew->ecs_addr, lookold->ecs_addr, len);
+ }
+
+ dns_name_copy(dns_fixedname_name(&lookold->fdomain),
+ dns_fixedname_name(&looknew->fdomain), NULL);
+
+ if (servers)
+ clone_server_list(lookold->my_server_list,
+ &looknew->my_server_list);
+ return (looknew);
+}
+
+/*%
+ * Requeue a lookup for further processing, perhaps copying the server
+ * list. The new lookup structure is returned to the caller, and is
+ * queued for processing. If servers are not cloned in the requeue, they
+ * must be added before allowing the current event to complete, since the
+ * completion of the event may result in the next entry on the lookup
+ * queue getting run.
+ */
+dig_lookup_t *
+requeue_lookup(dig_lookup_t *lookold, bool servers) {
+ dig_lookup_t *looknew;
+
+ debug("requeue_lookup()");
+
+ lookup_counter++;
+ if (lookup_counter > LOOKUP_LIMIT)
+ fatal("too many lookups");
+
+ looknew = clone_lookup(lookold, servers);
+ INSIST(looknew != NULL);
+
+ debug("before insertion, init@%p -> %p, new@%p -> %p",
+ lookold, lookold->link.next, looknew, looknew->link.next);
+ ISC_LIST_PREPEND(lookup_list, looknew, link);
+ debug("after insertion, init -> %p, new = %p, new -> %p",
+ lookold, looknew, looknew->link.next);
+ return (looknew);
+}
+
+
+void
+setup_text_key(void) {
+ isc_result_t result;
+ dns_name_t keyname;
+ isc_buffer_t secretbuf;
+ unsigned int secretsize;
+ unsigned char *secretstore;
+
+ debug("setup_text_key()");
+ result = isc_buffer_allocate(mctx, &namebuf, MXNAME);
+ check_result(result, "isc_buffer_allocate");
+ dns_name_init(&keyname, NULL);
+ check_result(result, "dns_name_init");
+ isc_buffer_putstr(namebuf, keynametext);
+ secretsize = (unsigned int) strlen(keysecret) * 3 / 4;
+ secretstore = isc_mem_allocate(mctx, secretsize);
+ if (secretstore == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ isc_buffer_init(&secretbuf, secretstore, secretsize);
+ result = isc_base64_decodestring(keysecret, &secretbuf);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ secretsize = isc_buffer_usedlength(&secretbuf);
+
+ if (hmacname == NULL) {
+ result = DST_R_UNSUPPORTEDALG;
+ goto failure;
+ }
+
+ result = dns_name_fromtext(&keyname, namebuf, dns_rootname, 0, namebuf);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = dns_tsigkey_create(&keyname, hmacname, secretstore,
+ (int)secretsize, false, NULL, 0, 0,
+ mctx, NULL, &tsigkey);
+ failure:
+ if (result != ISC_R_SUCCESS)
+ printf(";; Couldn't create key %s: %s\n",
+ keynametext, isc_result_totext(result));
+ else
+ dst_key_setbits(tsigkey->key, digestbits);
+
+ isc_mem_free(mctx, secretstore);
+ dns_name_invalidate(&keyname);
+ isc_buffer_free(&namebuf);
+}
+
+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);
+}
+
+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));
+}
+
+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 uint32_t
+parse_bits(char *arg, const char *desc, uint32_t max) {
+ isc_result_t result;
+ uint32_t tmp;
+
+ result = parse_uint(&tmp, arg, max, desc);
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't parse digest bits");
+ tmp = (tmp + 7) & ~0x7U;
+ return (tmp);
+}
+
+isc_result_t
+parse_netprefix(isc_sockaddr_t **sap, const char *value) {
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_sockaddr_t *sa = NULL;
+ struct in_addr in4;
+ struct in6_addr in6;
+ uint32_t prefix_length = 0xffffffff;
+ char *slash = NULL;
+ bool parsed = false;
+ bool prefix_parsed = false;
+ char buf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:XXX.XXX.XXX.XXX/128")];
+
+ REQUIRE(sap != NULL && *sap == NULL);
+
+ if (strlcpy(buf, value, sizeof(buf)) >= sizeof(buf))
+ fatal("invalid prefix '%s'\n", value);
+
+ sa = isc_mem_allocate(mctx, sizeof(*sa));
+ if (sa == NULL)
+ fatal("out of memory");
+ memset(sa, 0, sizeof(*sa));
+
+ if (strcmp(buf, "0") == 0) {
+ sa->type.sa.sa_family = AF_UNSPEC;
+ prefix_length = 0;
+ goto done;
+ }
+
+ slash = strchr(buf, '/');
+ if (slash != NULL) {
+ *slash = '\0';
+ result = isc_parse_uint32(&prefix_length, slash + 1, 10);
+ if (result != ISC_R_SUCCESS) {
+ fatal("invalid prefix length in '%s': %s\n",
+ value, isc_result_totext(result));
+ }
+ prefix_parsed = true;
+ }
+
+ if (inet_pton(AF_INET6, buf, &in6) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin6(sa, &in6, 0);
+ if (prefix_length > 128)
+ prefix_length = 128;
+ } else if (inet_pton(AF_INET, buf, &in4) == 1) {
+ parsed = true;
+ isc_sockaddr_fromin(sa, &in4, 0);
+ if (prefix_length > 32)
+ prefix_length = 32;
+ } else if (prefix_parsed) {
+ 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 (prefix_length > 32)
+ prefix_length = 32;
+ }
+
+ if (!parsed)
+ fatal("invalid address '%s'", value);
+
+done:
+ sa->length = prefix_length;
+ *sap = sa;
+
+ return (ISC_R_SUCCESS);
+}
+
+/*
+ * Parse HMAC algorithm specification
+ */
+void
+parse_hmac(const char *hmac) {
+ char buf[20];
+ size_t len;
+
+ REQUIRE(hmac != NULL);
+
+ len = strlen(hmac);
+ if (len >= sizeof(buf))
+ fatal("unknown key type '%.*s'", (int)len, hmac);
+ strlcpy(buf, hmac, sizeof(buf));
+
+ digestbits = 0;
+
+#ifndef PK11_MD5_DISABLE
+ if (strcasecmp(buf, "hmac-md5") == 0) {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ } else if (strncasecmp(buf, "hmac-md5-", 9) == 0) {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ digestbits = parse_bits(&buf[9], "digest-bits [0..128]", 128);
+ } else
+#endif
+ if (strcasecmp(buf, "hmac-sha1") == 0) {
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(buf, "hmac-sha1-", 10) == 0) {
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ digestbits = parse_bits(&buf[10], "digest-bits [0..160]", 160);
+ } else if (strcasecmp(buf, "hmac-sha224") == 0) {
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ } else if (strncasecmp(buf, "hmac-sha224-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..224]", 224);
+ } else if (strcasecmp(buf, "hmac-sha256") == 0) {
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ } else if (strncasecmp(buf, "hmac-sha256-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..256]", 256);
+ } else if (strcasecmp(buf, "hmac-sha384") == 0) {
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ } else if (strncasecmp(buf, "hmac-sha384-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..384]", 384);
+ } else if (strcasecmp(buf, "hmac-sha512") == 0) {
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ } else if (strncasecmp(buf, "hmac-sha512-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ digestbits = parse_bits(&buf[12], "digest-bits [0..512]", 512);
+ } else {
+ fprintf(stderr, ";; Warning, ignoring "
+ "invalid TSIG algorithm %s\n", buf);
+ }
+}
+
+/*
+ * Get a key from a named.conf format keyfile
+ */
+static isc_result_t
+read_confkey(void) {
+ cfg_parser_t *pctx = NULL;
+ cfg_obj_t *file = NULL;
+ const cfg_obj_t *keyobj = NULL;
+ const cfg_obj_t *secretobj = NULL;
+ const cfg_obj_t *algorithmobj = NULL;
+ const char *keyname;
+ const char *secretstr;
+ const char *algorithm;
+ isc_result_t result;
+
+ if (! isc_file_exists(keyfile))
+ return (ISC_R_FILENOTFOUND);
+
+ result = cfg_parser_create(mctx, NULL, &pctx);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = cfg_parse_file(pctx, keyfile, &cfg_type_sessionkey,
+ &file);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ result = cfg_map_get(file, "key", &keyobj);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ (void) cfg_map_get(keyobj, "secret", &secretobj);
+ (void) cfg_map_get(keyobj, "algorithm", &algorithmobj);
+ if (secretobj == NULL || algorithmobj == NULL)
+ fatal("key must have algorithm and secret");
+
+ keyname = cfg_obj_asstring(cfg_map_getname(keyobj));
+ secretstr = cfg_obj_asstring(secretobj);
+ algorithm = cfg_obj_asstring(algorithmobj);
+
+ strlcpy(keynametext, keyname, sizeof(keynametext));
+ strlcpy(keysecret, secretstr, sizeof(keysecret));
+ parse_hmac(algorithm);
+ setup_text_key();
+
+ cleanup:
+ if (pctx != NULL) {
+ if (file != NULL)
+ cfg_obj_destroy(pctx, &file);
+ cfg_parser_destroy(&pctx);
+ }
+
+ return (result);
+}
+
+void
+setup_file_key(void) {
+ isc_result_t result;
+ dst_key_t *dstkey = NULL;
+
+ debug("setup_file_key()");
+
+ /* Try reading the key from a K* pair */
+ result = dst_key_fromnamedfile(keyfile, NULL,
+ DST_TYPE_PRIVATE | DST_TYPE_KEY, mctx,
+ &dstkey);
+
+ /* If that didn't work, try reading it as a session.key keyfile */
+ if (result != ISC_R_SUCCESS) {
+ result = read_confkey();
+ if (result == ISC_R_SUCCESS)
+ return;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ fprintf(stderr, "Couldn't read key from %s: %s\n",
+ keyfile, isc_result_totext(result));
+ goto failure;
+ }
+
+ switch (dst_key_alg(dstkey)) {
+#ifndef PK11_MD5_DISABLE
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+#endif
+ case DST_ALG_HMACSHA1:
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ break;
+ case DST_ALG_HMACSHA224:
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ break;
+ case DST_ALG_HMACSHA256:
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ break;
+ case DST_ALG_HMACSHA384:
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ break;
+ case DST_ALG_HMACSHA512:
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ break;
+ default:
+ printf(";; Couldn't create key %s: bad algorithm\n",
+ keynametext);
+ goto failure;
+ }
+ result = dns_tsigkey_createfromkey(dst_key_name(dstkey), hmacname,
+ dstkey, false, NULL, 0, 0,
+ mctx, NULL, &tsigkey);
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't create key %s: %s\n",
+ keynametext, isc_result_totext(result));
+ goto failure;
+ }
+ failure:
+ if (dstkey != NULL)
+ dst_key_free(&dstkey);
+}
+
+static dig_searchlist_t *
+make_searchlist_entry(char *domain) {
+ dig_searchlist_t *search;
+ search = isc_mem_allocate(mctx, sizeof(*search));
+ if (search == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ strlcpy(search->origin, domain, MXNAME);
+ search->origin[MXNAME-1] = 0;
+ ISC_LINK_INIT(search, link);
+ return (search);
+}
+
+static void
+clear_searchlist(void) {
+ dig_searchlist_t *search;
+ while ((search = ISC_LIST_HEAD(search_list)) != NULL) {
+ ISC_LIST_UNLINK(search_list, search, link);
+ isc_mem_free(mctx, search);
+ }
+}
+
+static void
+create_search_list(lwres_conf_t *confdata) {
+ int i;
+ dig_searchlist_t *search;
+
+ debug("create_search_list()");
+ clear_searchlist();
+
+ for (i = 0; i < confdata->searchnxt; i++) {
+ search = make_searchlist_entry(confdata->search[i]);
+ ISC_LIST_APPEND(search_list, search, link);
+ }
+}
+
+/*%
+ * Setup the system as a whole, reading key information and resolv.conf
+ * settings.
+ */
+void
+setup_system(bool ipv4only, bool ipv6only) {
+ dig_searchlist_t *domain = NULL;
+ lwres_result_t lwresult;
+ unsigned int lwresflags;
+ isc_result_t result;
+
+ debug("setup_system()");
+
+ if (ipv4only) {
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = false;
+ } else {
+ fatal("can't find IPv4 networking");
+ }
+ }
+
+ if (ipv6only) {
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = false;
+ } else {
+ fatal("can't find IPv6 networking");
+ }
+ }
+
+ lwresflags = LWRES_CONTEXT_SERVERMODE;
+ if (have_ipv4)
+ lwresflags |= LWRES_CONTEXT_USEIPV4;
+ if (have_ipv6)
+ lwresflags |= LWRES_CONTEXT_USEIPV6;
+
+ lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free,
+ lwresflags);
+ if (lwresult != LWRES_R_SUCCESS)
+ fatal("lwres_context_create failed");
+
+ lwresult = lwres_conf_parse(lwctx, RESOLV_CONF);
+ if (lwresult != LWRES_R_SUCCESS && lwresult != LWRES_R_NOTFOUND)
+ fatal("parse of %s failed", RESOLV_CONF);
+
+ lwconf = lwres_conf_get(lwctx);
+
+ /* Make the search list */
+ if (lwconf->searchnxt > 0)
+ create_search_list(lwconf);
+ else { /* No search list. Use the domain name if any */
+ if (lwconf->domainname != NULL) {
+ domain = make_searchlist_entry(lwconf->domainname);
+ ISC_LIST_APPEND(search_list, domain, link);
+ domain = NULL;
+ }
+ }
+
+ if (lwconf->resdebug) {
+ verbose = true;
+ debug("verbose is on");
+ }
+ if (ndots == -1) {
+ ndots = lwconf->ndots;
+ debug("ndots is %d.", ndots);
+ }
+ if (lwconf->attempts) {
+ tries = lwconf->attempts + 1;
+ if (tries < 2)
+ tries = 2;
+ debug("tries is %d.", tries);
+ }
+ if (lwconf->timeout) {
+ timeout = lwconf->timeout;
+ debug("timeout is %d.", timeout);
+ }
+
+ /* If user doesn't specify server use nameservers from resolv.conf. */
+ if (ISC_LIST_EMPTY(server_list))
+ copy_server_list(lwconf, &server_list);
+
+ /* If we don't find a nameserver fall back to localhost */
+ if (ISC_LIST_EMPTY(server_list)) {
+ if (have_ipv4) {
+ lwresult = add_nameserver(lwconf, "127.0.0.1", AF_INET);
+ if (lwresult != ISC_R_SUCCESS)
+ fatal("add_nameserver failed");
+ }
+ if (have_ipv6) {
+ lwresult = add_nameserver(lwconf, "::1", AF_INET6);
+ if (lwresult != ISC_R_SUCCESS)
+ fatal("add_nameserver failed");
+ }
+
+ copy_server_list(lwconf, &server_list);
+ }
+
+#ifdef HAVE_SETLOCALE
+ /* Set locale */
+ (void)setlocale(LC_ALL, "");
+#endif
+
+#ifdef WITH_IDN_SUPPORT
+ idn_initialize();
+#endif
+
+#ifdef WITH_IDN_OUT_SUPPORT
+ /* Set domain name -> text post-conversion filter. */
+ result = dns_name_settotextfilter(output_filter);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+ setup_text_key();
+#ifdef DIG_SIGCHASE
+ /* Setup the list of messages for +sigchase */
+ ISC_LIST_INIT(chase_message_list);
+ ISC_LIST_INIT(chase_message_list2);
+ dns_name_init(&chase_name, NULL);
+#if DIG_SIGCHASE_TD
+ dns_name_init(&chase_current_name, NULL);
+ dns_name_init(&chase_authority_name, NULL);
+#endif
+#if DIG_SIGCHASE_BU
+ dns_name_init(&chase_signame, NULL);
+#endif
+
+#endif
+ result = isc_entropy_getdata(entp, cookie_secret,
+ sizeof(cookie_secret), NULL, 0);
+ if (result != ISC_R_SUCCESS)
+ fatal("unable to generate cookie secret");
+}
+
+/*%
+ * Override the search list derived from resolv.conf by 'domain'.
+ */
+void
+set_search_domain(char *domain) {
+ dig_searchlist_t *search;
+
+ clear_searchlist();
+ search = make_searchlist_entry(domain);
+ ISC_LIST_APPEND(search_list, search, link);
+}
+
+/*%
+ * Setup the ISC and DNS libraries for use by the system.
+ */
+void
+setup_libs(void) {
+ isc_result_t result;
+ isc_logconfig_t *logconfig = NULL;
+
+ debug("setup_libs()");
+
+#ifdef PKCS11CRYPTO
+ pk11_result_register();
+#endif
+ dns_result_register();
+
+ result = isc_net_probeipv4();
+ if (result == ISC_R_SUCCESS)
+ have_ipv4 = true;
+
+ result = isc_net_probeipv6();
+ if (result == ISC_R_SUCCESS)
+ have_ipv6 = true;
+ if (!have_ipv6 && !have_ipv4)
+ fatal("can't find either v4 or v6 networking");
+
+ result = isc_mem_create(0, 0, &mctx);
+ check_result(result, "isc_mem_create");
+ isc_mem_setname(mctx, "dig", NULL);
+
+ result = isc_log_create(mctx, &lctx, &logconfig);
+ check_result(result, "isc_log_create");
+
+ isc_log_setcontext(lctx);
+ dns_log_init(lctx);
+ dns_log_setcontext(lctx);
+
+ result = isc_log_usechannel(logconfig, "default_debug", NULL, NULL);
+ check_result(result, "isc_log_usechannel");
+
+ isc_log_setdebuglevel(lctx, 0);
+
+ result = isc_taskmgr_create(mctx, 1, 0, &taskmgr);
+ check_result(result, "isc_taskmgr_create");
+
+ result = isc_task_create(taskmgr, 0, &global_task);
+ check_result(result, "isc_task_create");
+ isc_task_setname(global_task, "dig", NULL);
+
+ result = isc_timermgr_create(mctx, &timermgr);
+ check_result(result, "isc_timermgr_create");
+
+ result = isc_socketmgr_create(mctx, &socketmgr);
+ check_result(result, "isc_socketmgr_create");
+
+ result = isc_entropy_create(mctx, &entp);
+ check_result(result, "isc_entropy_create");
+
+ result = dst_lib_init(mctx, entp, 0);
+ check_result(result, "dst_lib_init");
+ is_dst_up = true;
+
+ result = isc_mempool_create(mctx, COMMSIZE, &commctx);
+ check_result(result, "isc_mempool_create");
+ isc_mempool_setname(commctx, "COMMPOOL");
+ /*
+ * 6 and 2 set as reasonable parameters for 3 or 4 nameserver
+ * systems.
+ */
+ isc_mempool_setfreemax(commctx, 6);
+ isc_mempool_setfillcount(commctx, 2);
+
+ result = isc_mutex_init(&lookup_lock);
+ check_result(result, "isc_mutex_init");
+}
+
+typedef struct dig_ednsoptname {
+ uint32_t code;
+ const char *name;
+} dig_ednsoptname_t;
+
+dig_ednsoptname_t optnames[] = {
+ { 3, "NSID" }, /* RFC 5001 */
+ { 5, "DAU" }, /* RFC 6975 */
+ { 6, "DHU" }, /* RFC 6975 */
+ { 7, "N3U" }, /* RFC 6975 */
+ { 8, "ECS" }, /* RFC 7871 */
+ { 9, "EXPIRE" }, /* RFC 7314 */
+ { 10, "COOKIE" }, /* RFC 7873 */
+ { 11, "KEEPALIVE" }, /* RFC 7828 */
+ { 12, "PADDING" }, /* RFC 7830 */
+ { 12, "PAD" }, /* shorthand */
+ { 13, "CHAIN" }, /* RFC 7901 */
+ { 14, "KEY-TAG" }, /* RFC 8145 */
+ { 26946, "DEVICEID" }, /* Brian Hartvigsen */
+};
+
+#define N_EDNS_OPTNAMES (sizeof(optnames) / sizeof(optnames[0]))
+
+void
+save_opt(dig_lookup_t *lookup, char *code, char *value) {
+ isc_result_t result;
+ uint32_t num = 0;
+ isc_buffer_t b;
+ bool found = false;
+ unsigned int i;
+
+ if (lookup->ednsoptscnt >= EDNSOPT_OPTIONS)
+ fatal("too many ednsopts");
+
+ for (i = 0; i < N_EDNS_OPTNAMES; i++) {
+ if (strcasecmp(code, optnames[i].name) == 0) {
+ num = optnames[i].code;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ result = parse_uint(&num, code, 65535, "ednsopt");
+ if (result != ISC_R_SUCCESS)
+ fatal("bad edns code point: %s", code);
+ }
+
+ if (lookup->ednsopts == NULL) {
+ cloneopts(lookup, NULL);
+ }
+
+ if (lookup->ednsopts[lookup->ednsoptscnt].value != NULL)
+ isc_mem_free(mctx, lookup->ednsopts[lookup->ednsoptscnt].value);
+
+ lookup->ednsopts[lookup->ednsoptscnt].code = num;
+ lookup->ednsopts[lookup->ednsoptscnt].length = 0;
+ lookup->ednsopts[lookup->ednsoptscnt].value = NULL;
+
+ if (value != NULL) {
+ char *buf;
+ buf = isc_mem_allocate(mctx, strlen(value)/2 + 1);
+ if (buf == NULL)
+ fatal("out of memory");
+ isc_buffer_init(&b, buf, (unsigned int) strlen(value)/2 + 1);
+ result = isc_hex_decodestring(value, &b);
+ check_result(result, "isc_hex_decodestring");
+ lookup->ednsopts[lookup->ednsoptscnt].value =
+ isc_buffer_base(&b);
+ lookup->ednsopts[lookup->ednsoptscnt].length =
+ isc_buffer_usedlength(&b);
+ }
+
+ lookup->ednsoptscnt++;
+}
+
+/*%
+ * 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;
+
+ debug("add_opt()");
+ result = dns_message_buildopt(msg, &rdataset, edns, udpsize, flags,
+ opts, count);
+ check_result(result, "dns_message_buildopt");
+ result = dns_message_setopt(msg, rdataset);
+ check_result(result, "dns_message_setopt");
+}
+
+/*%
+ * Add a question section to a message, asking for the specified name,
+ * type, and class.
+ */
+static void
+add_question(dns_message_t *message, dns_name_t *name,
+ dns_rdataclass_t rdclass, dns_rdatatype_t rdtype)
+{
+ dns_rdataset_t *rdataset;
+ isc_result_t result;
+
+ debug("add_question()");
+ rdataset = NULL;
+ result = dns_message_gettemprdataset(message, &rdataset);
+ check_result(result, "dns_message_gettemprdataset()");
+ dns_rdataset_makequestion(rdataset, rdclass, rdtype);
+ ISC_LIST_APPEND(name->list, rdataset, link);
+}
+
+/*%
+ * Check if we're done with all the queued lookups, which is true iff
+ * all sockets, sends, and recvs are accounted for (counters == 0),
+ * and the lookup list is empty.
+ * If we are done, pass control back out to dighost_shutdown() (which is
+ * part of dig.c, host.c, or nslookup.c) to either shutdown the system as
+ * a whole or reseed the lookup list.
+ */
+static void
+check_if_done(void) {
+ debug("check_if_done()");
+ debug("list %s", ISC_LIST_EMPTY(lookup_list) ? "empty" : "full");
+ if (ISC_LIST_EMPTY(lookup_list) && current_lookup == NULL &&
+ sendcount == 0) {
+ INSIST(sockcount == 0);
+ INSIST(recvcount == 0);
+ debug("shutting down");
+ dighost_shutdown();
+ }
+}
+
+/*%
+ * Clear out a query when we're done with it. WARNING: This routine
+ * WILL invalidate the query pointer.
+ */
+static void
+clear_query(dig_query_t *query) {
+ dig_lookup_t *lookup;
+
+ REQUIRE(query != NULL);
+
+ debug("clear_query(%p)", query);
+
+ if (query->timer != NULL)
+ isc_timer_detach(&query->timer);
+ lookup = query->lookup;
+
+ if (lookup->current_query == query)
+ lookup->current_query = NULL;
+
+ if (ISC_LINK_LINKED(query, link))
+ ISC_LIST_UNLINK(lookup->q, query, link);
+ if (ISC_LINK_LINKED(query, clink))
+ ISC_LIST_UNLINK(lookup->connecting, query, clink);
+ if (ISC_LINK_LINKED(&query->recvbuf, link))
+ ISC_LIST_DEQUEUE(query->recvlist, &query->recvbuf,
+ link);
+ if (ISC_LINK_LINKED(&query->lengthbuf, link))
+ ISC_LIST_DEQUEUE(query->lengthlist, &query->lengthbuf,
+ link);
+ INSIST(query->recvspace != NULL);
+
+ if (query->sock != NULL) {
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ }
+ isc_mempool_put(commctx, query->recvspace);
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_invalidate(&query->lengthbuf);
+ if (query->waiting_senddone)
+ query->pending_free = true;
+ else
+ isc_mem_free(mctx, query);
+}
+
+/*%
+ * Try and clear out a lookup if we're done with it. Return true if
+ * the lookup was successfully cleared. If true is returned, the
+ * lookup pointer has been invalidated.
+ */
+static bool
+try_clear_lookup(dig_lookup_t *lookup) {
+ dig_query_t *q;
+
+ REQUIRE(lookup != NULL);
+
+ debug("try_clear_lookup(%p)", lookup);
+
+ if (ISC_LIST_HEAD(lookup->q) != NULL ||
+ ISC_LIST_HEAD(lookup->connecting) != NULL)
+ {
+ if (debugging) {
+ q = ISC_LIST_HEAD(lookup->q);
+ while (q != NULL) {
+ debug("query to %s still pending", q->servname);
+ q = ISC_LIST_NEXT(q, link);
+ }
+
+ q = ISC_LIST_HEAD(lookup->connecting);
+ while (q != NULL) {
+ debug("query to %s still connecting",
+ q->servname);
+ q = ISC_LIST_NEXT(q, clink);
+ }
+ }
+ return (false);
+ }
+
+ /*
+ * At this point, we know there are no queries on the lookup,
+ * so can make it go away also.
+ */
+ destroy_lookup(lookup);
+ return (true);
+}
+
+void
+destroy_lookup(dig_lookup_t *lookup) {
+ dig_server_t *s;
+ void *ptr;
+
+ debug("destroy");
+ s = ISC_LIST_HEAD(lookup->my_server_list);
+ while (s != NULL) {
+ debug("freeing server %p belonging to %p", s, lookup);
+ ptr = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(lookup->my_server_list,
+ (dig_server_t *)ptr, link);
+ isc_mem_free(mctx, ptr);
+ }
+ if (lookup->sendmsg != NULL)
+ dns_message_destroy(&lookup->sendmsg);
+ if (lookup->querysig != NULL) {
+ debug("freeing buffer %p", lookup->querysig);
+ isc_buffer_free(&lookup->querysig);
+ }
+ if (lookup->sendspace != NULL)
+ isc_mempool_put(commctx, lookup->sendspace);
+
+ if (lookup->tsigctx != NULL)
+ dst_context_destroy(&lookup->tsigctx);
+
+ if (lookup->ecs_addr != NULL)
+ isc_mem_free(mctx, lookup->ecs_addr);
+
+ if (lookup->ednsopts != NULL) {
+ size_t i;
+ for (i = 0; i < EDNSOPT_OPTIONS; i++) {
+ if (lookup->ednsopts[i].value != NULL)
+ isc_mem_free(mctx, lookup->ednsopts[i].value);
+ }
+ isc_mem_free(mctx, lookup->ednsopts);
+ }
+
+ isc_mem_free(mctx, lookup);
+}
+
+/*%
+ * If we can, start the next lookup in the queue running.
+ * This assumes that the lookup on the head of the queue hasn't been
+ * started yet. It also removes the lookup from the head of the queue,
+ * setting the current_lookup pointer pointing to it.
+ */
+void
+start_lookup(void) {
+ debug("start_lookup()");
+ if (cancel_now)
+ return;
+
+ /*
+ * If there's a current lookup running, we really shouldn't get
+ * here.
+ */
+ INSIST(current_lookup == NULL);
+
+ current_lookup = ISC_LIST_HEAD(lookup_list);
+ /*
+ * Put the current lookup somewhere so cancel_all can find it
+ */
+ if (current_lookup != NULL) {
+ ISC_LIST_DEQUEUE(lookup_list, current_lookup, link);
+#if DIG_SIGCHASE_TD
+ if (current_lookup->do_topdown &&
+ !current_lookup->rdtype_sigchaseset) {
+ dst_key_t *dstkey = NULL;
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ dns_name_t query_name;
+ dns_name_t *key_name;
+ int i;
+
+ result = get_trusted_key();
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No trusted key, "
+ "+sigchase option is disabled\n");
+ current_lookup->sigchase = false;
+ goto novalidation;
+ }
+ dns_name_init(&query_name, NULL);
+ nameFromString(current_lookup->textname, &query_name);
+
+ for (i = 0; i < tk_list.nb_tk; i++) {
+ key_name = dst_key_name(tk_list.key[i]);
+
+ if (dns_name_issubdomain(&query_name,
+ key_name) == true)
+ dstkey = tk_list.key[i];
+ /*
+ * Verify temp is really the lowest
+ * WARNING
+ */
+ }
+ if (dstkey == NULL) {
+ printf("\n;; The queried zone: ");
+ dns_name_print(&query_name, stdout);
+ printf(" isn't a subdomain of any Trusted Keys"
+ ": +sigchase option is disable\n");
+ current_lookup->sigchase = false;
+ free_name(&query_name);
+ goto novalidation;
+ }
+ free_name(&query_name);
+
+ current_lookup->rdtype_sigchase
+ = current_lookup->rdtype;
+ current_lookup->rdtype_sigchaseset
+ = current_lookup->rdtypeset;
+ current_lookup->rdtype = dns_rdatatype_ns;
+
+ current_lookup->qrdtype_sigchase
+ = current_lookup->qrdtype;
+ current_lookup->qrdtype = dns_rdatatype_ns;
+
+ current_lookup->rdclass_sigchase
+ = current_lookup->rdclass;
+ current_lookup->rdclass_sigchaseset
+ = current_lookup->rdclassset;
+ current_lookup->rdclass = dns_rdataclass_in;
+
+ strlcpy(current_lookup->textnamesigchase,
+ current_lookup->textname, MXNAME);
+
+ current_lookup->trace_root_sigchase = true;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(dst_key_name(dstkey),
+ false, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(current_lookup->textname, (char*)r.base,
+ MXNAME);
+ isc_buffer_free(&b);
+
+ nameFromString(current_lookup->textnamesigchase,
+ &chase_name);
+
+ dns_name_init(&chase_authority_name, NULL);
+ }
+ novalidation:
+#endif
+ if (setup_lookup(current_lookup))
+ do_lookup(current_lookup);
+ else if (next_origin(current_lookup))
+ check_next_lookup(current_lookup);
+ } else {
+ check_if_done();
+ }
+}
+
+/*%
+ * If we can, clear the current lookup and start the next one running.
+ * This calls try_clear_lookup, so may invalidate the lookup pointer.
+ */
+static void
+check_next_lookup(dig_lookup_t *lookup) {
+
+ INSIST(!free_now);
+
+ debug("check_next_lookup(%p)", lookup);
+
+ if (ISC_LIST_HEAD(lookup->q) != NULL) {
+ debug("still have a worker");
+ return;
+ }
+ if (try_clear_lookup(lookup)) {
+ current_lookup = NULL;
+ start_lookup();
+ }
+}
+
+/*%
+ * Create and queue a new lookup as a followup to the current lookup,
+ * based on the supplied message and section. This is used in trace and
+ * name server search modes to start a new lookup using servers from
+ * NS records in a reply. Returns the number of followup lookups made.
+ */
+static int
+followup_lookup(dns_message_t *msg, dig_query_t *query, dns_section_t section)
+{
+ dig_lookup_t *lookup = NULL;
+ dig_server_t *srv = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_name_t *name = NULL;
+ isc_result_t result;
+ bool success = false;
+ int numLookups = 0;
+ int num;
+ isc_result_t lresult, addresses_result;
+ char bad_namestr[DNS_NAME_FORMATSIZE];
+ dns_name_t *domain;
+ bool horizontal = false, bad = false;
+
+ INSIST(!free_now);
+
+ debug("following up %s", query->lookup->textname);
+
+ addresses_result = ISC_R_SUCCESS;
+ bad_namestr[0] = '\0';
+ for (result = dns_message_firstname(msg, section);
+ result == ISC_R_SUCCESS;
+ result = dns_message_nextname(msg, section)) {
+ name = NULL;
+ dns_message_currentname(msg, section, &name);
+
+ if (section == DNS_SECTION_AUTHORITY) {
+ rdataset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_soa,
+ 0, &rdataset);
+ if (result == ISC_R_SUCCESS)
+ return (0);
+ }
+ rdataset = NULL;
+ result = dns_message_findtype(name, dns_rdatatype_ns, 0,
+ &rdataset);
+ if (result != ISC_R_SUCCESS)
+ continue;
+
+ debug("found NS set");
+
+ if (query->lookup->trace && !query->lookup->trace_root) {
+ dns_namereln_t namereln;
+ unsigned int nlabels;
+ int order;
+
+ domain = dns_fixedname_name(&query->lookup->fdomain);
+ namereln = dns_name_fullcompare(name, domain,
+ &order, &nlabels);
+ if (namereln == dns_namereln_equal) {
+ if (!horizontal)
+ printf(";; BAD (HORIZONTAL) REFERRAL\n");
+ horizontal = true;
+ } else if (namereln != dns_namereln_subdomain) {
+ if (!bad)
+ printf(";; BAD REFERRAL\n");
+ bad = true;
+ continue;
+ }
+ }
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_rdata_ns_t ns;
+
+ if (query->lookup->trace_root &&
+ query->lookup->nsfound >= MXSERV)
+ break;
+
+ dns_rdataset_current(rdataset, &rdata);
+
+ query->lookup->nsfound++;
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_format(&ns.name, namestr, sizeof(namestr));
+ dns_rdata_freestruct(&ns);
+
+ /* Initialize lookup if we've not yet */
+ debug("found NS %s", namestr);
+ if (!success) {
+ success = true;
+ lookup_counter++;
+ lookup = requeue_lookup(query->lookup,
+ false);
+ cancel_lookup(query->lookup);
+ lookup->doing_xfr = false;
+ if (!lookup->trace_root &&
+ section == DNS_SECTION_ANSWER)
+ lookup->trace = false;
+ else
+ lookup->trace = query->lookup->trace;
+ lookup->ns_search_only =
+ query->lookup->ns_search_only;
+ lookup->trace_root = false;
+ if (lookup->ns_search_only)
+ lookup->recurse = false;
+ domain = dns_fixedname_name(&lookup->fdomain);
+ dns_name_copy(name, domain, NULL);
+ }
+ debug("adding server %s", namestr);
+ num = getaddresses(lookup, namestr, &lresult);
+ if (lresult != ISC_R_SUCCESS) {
+ printf("couldn't get address for '%s': %s\n",
+ namestr, isc_result_totext(lresult));
+ if (addresses_result == ISC_R_SUCCESS) {
+ addresses_result = lresult;
+ strlcpy(bad_namestr, namestr,
+ sizeof(bad_namestr));
+ }
+ }
+ numLookups += num;
+ dns_rdata_reset(&rdata);
+ }
+ }
+ if (numLookups == 0 && addresses_result != ISC_R_SUCCESS) {
+ fatal("couldn't get address for '%s': %s",
+ bad_namestr, isc_result_totext(result));
+ }
+
+ if (lookup == NULL &&
+ section == DNS_SECTION_ANSWER &&
+ (query->lookup->trace || query->lookup->ns_search_only))
+ return (followup_lookup(msg, query, DNS_SECTION_AUTHORITY));
+
+ /*
+ * Randomize the order the nameserver will be tried.
+ */
+ if (numLookups > 1) {
+ uint32_t i, j;
+ dig_serverlist_t my_server_list;
+ dig_server_t *next;
+
+ ISC_LIST_INIT(my_server_list);
+
+ i = numLookups;
+ for (srv = ISC_LIST_HEAD(lookup->my_server_list);
+ srv != NULL;
+ srv = ISC_LIST_HEAD(lookup->my_server_list)) {
+ INSIST(i > 0);
+ isc_random_get(&j);
+ j %= i;
+ next = ISC_LIST_NEXT(srv, link);
+ while (j-- > 0 && next != NULL) {
+ srv = next;
+ next = ISC_LIST_NEXT(srv, link);
+ }
+ ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
+ ISC_LIST_APPEND(my_server_list, srv, link);
+ i--;
+ }
+ ISC_LIST_APPENDLIST(lookup->my_server_list,
+ my_server_list, link);
+ }
+
+ return (numLookups);
+}
+
+/*%
+ * Create and queue a new lookup using the next origin from the search
+ * list, read in setup_system().
+ *
+ * Return true iff there was another searchlist entry.
+ */
+static bool
+next_origin(dig_lookup_t *oldlookup) {
+ dig_lookup_t *newlookup;
+ dig_searchlist_t *search;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+ isc_result_t result;
+
+ INSIST(!free_now);
+
+ debug("next_origin()");
+ debug("following up %s", oldlookup->textname);
+
+ if (!usesearch)
+ /*
+ * We're not using a search list, so don't even think
+ * about finding the next entry.
+ */
+ return (false);
+
+ /*
+ * Check for a absolute name or ndots being met.
+ */
+ name = dns_fixedname_initname(&fixed);
+ result = dns_name_fromstring2(name, oldlookup->textname, NULL,
+ 0, NULL);
+ if (result == ISC_R_SUCCESS &&
+ (dns_name_isabsolute(name) ||
+ (int)dns_name_countlabels(name) > ndots))
+ return (false);
+
+ if (oldlookup->origin == NULL && !oldlookup->need_search)
+ /*
+ * Then we just did rootorg; there's nothing left.
+ */
+ return (false);
+ if (oldlookup->origin == NULL && oldlookup->need_search) {
+ newlookup = requeue_lookup(oldlookup, true);
+ newlookup->origin = ISC_LIST_HEAD(search_list);
+ newlookup->need_search = false;
+ } else {
+ search = ISC_LIST_NEXT(oldlookup->origin, link);
+ if (search == NULL && oldlookup->done_as_is)
+ return (false);
+ newlookup = requeue_lookup(oldlookup, true);
+ newlookup->origin = search;
+ }
+ cancel_lookup(oldlookup);
+ return (true);
+}
+
+/*%
+ * Insert an SOA record into the sendmessage in a lookup. Used for
+ * creating IXFR queries.
+ */
+static void
+insert_soa(dig_lookup_t *lookup) {
+ isc_result_t result;
+ dns_rdata_soa_t soa;
+ dns_rdata_t *rdata = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdataset_t *rdataset = NULL;
+ dns_name_t *soaname = NULL;
+
+ debug("insert_soa()");
+ soa.mctx = mctx;
+ soa.serial = lookup->ixfr_serial;
+ soa.refresh = 0;
+ soa.retry = 0;
+ soa.expire = 0;
+ soa.minimum = 0;
+ soa.common.rdclass = lookup->rdclass;
+ soa.common.rdtype = dns_rdatatype_soa;
+
+ dns_name_init(&soa.origin, NULL);
+ dns_name_init(&soa.contact, NULL);
+
+ dns_name_clone(dns_rootname, &soa.origin);
+ dns_name_clone(dns_rootname, &soa.contact);
+
+ isc_buffer_init(&lookup->rdatabuf, lookup->rdatastore,
+ sizeof(lookup->rdatastore));
+
+ result = dns_message_gettemprdata(lookup->sendmsg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ result = dns_rdata_fromstruct(rdata, lookup->rdclass,
+ dns_rdatatype_soa, &soa,
+ &lookup->rdatabuf);
+ check_result(result, "isc_rdata_fromstruct");
+
+ result = dns_message_gettemprdatalist(lookup->sendmsg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+
+ result = dns_message_gettemprdataset(lookup->sendmsg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+
+ dns_rdatalist_init(rdatalist);
+ rdatalist->type = dns_rdatatype_soa;
+ rdatalist->rdclass = lookup->rdclass;
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+
+ result = dns_message_gettempname(lookup->sendmsg, &soaname);
+ check_result(result, "dns_message_gettempname");
+ dns_name_init(soaname, NULL);
+ dns_name_clone(lookup->name, soaname);
+ ISC_LIST_INIT(soaname->list);
+ ISC_LIST_APPEND(soaname->list, rdataset, link);
+ dns_message_addname(lookup->sendmsg, soaname, DNS_SECTION_AUTHORITY);
+}
+
+static void
+compute_cookie(unsigned char *clientcookie, size_t len) {
+ /* XXXMPA need to fix, should be per server. */
+ INSIST(len >= 8U);
+ memmove(clientcookie, cookie_secret, 8);
+}
+
+/*%
+ * Setup the supplied lookup structure, making it ready to start sending
+ * queries to servers. Create and initialize the message to be sent as
+ * well as the query structures and buffer space for the replies. If the
+ * server list is empty, clone it from the system default list.
+ */
+bool
+setup_lookup(dig_lookup_t *lookup) {
+ isc_result_t result;
+ uint32_t id;
+ unsigned int len;
+ dig_server_t *serv;
+ dig_query_t *query;
+ isc_buffer_t b;
+ dns_compress_t cctx;
+ char store[MXNAME];
+ char ecsbuf[20];
+ char cookiebuf[256];
+ char *origin = NULL;
+ char *textname = NULL;
+#ifdef WITH_IDN_SUPPORT
+ char idn_origin[MXNAME], idn_textname[MXNAME];
+#endif
+
+#ifdef WITH_IDN_OUT_SUPPORT
+ result = dns_name_settotextfilter(lookup->idnout ?
+ output_filter : NULL);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+
+ REQUIRE(lookup != NULL);
+ INSIST(!free_now);
+
+ debug("setup_lookup(%p)", lookup);
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER,
+ &lookup->sendmsg);
+ check_result(result, "dns_message_create");
+
+ if (lookup->new_search) {
+ debug("resetting lookup counter.");
+ lookup_counter = 0;
+ }
+
+ if (ISC_LIST_EMPTY(lookup->my_server_list)) {
+ debug("cloning server list");
+ clone_server_list(server_list, &lookup->my_server_list);
+ }
+ result = dns_message_gettempname(lookup->sendmsg, &lookup->name);
+ check_result(result, "dns_message_gettempname");
+ dns_name_init(lookup->name, NULL);
+
+ isc_buffer_init(&lookup->namebuf, lookup->name_space,
+ sizeof(lookup->name_space));
+ isc_buffer_init(&lookup->onamebuf, lookup->oname_space,
+ sizeof(lookup->oname_space));
+
+ /*
+ * We cannot convert `textname' and `origin' separately.
+ * `textname' doesn't contain TLD, but local mapping needs
+ * TLD.
+ */
+ textname = lookup->textname;
+#ifdef WITH_IDN_SUPPORT
+ if (lookup->idnin) {
+ result = idn_locale_to_ace(textname, idn_textname, sizeof(idn_textname));
+ check_result(result, "convert textname to IDN encoding");
+ debug("idn_textname: %s", idn_textname);
+ textname = idn_textname;
+ }
+#endif
+
+ /*
+ * If the name has too many dots, force the origin to be NULL
+ * (which produces an absolute lookup). Otherwise, take the origin
+ * we have if there's one in the struct already. If it's NULL,
+ * take the first entry in the searchlist iff either usesearch
+ * is TRUE or we got a domain line in the resolv.conf file.
+ */
+ if (lookup->new_search) {
+ if ((count_dots(textname) >= ndots) || !usesearch)
+ {
+ lookup->origin = NULL; /* Force abs lookup */
+ lookup->done_as_is = true;
+ lookup->need_search = usesearch;
+ } else if (lookup->origin == NULL && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = false;
+ }
+ }
+
+ if (lookup->origin != NULL) {
+ debug("trying origin %s", lookup->origin->origin);
+ result = dns_message_gettempname(lookup->sendmsg,
+ &lookup->oname);
+ check_result(result, "dns_message_gettempname");
+ dns_name_init(lookup->oname, NULL);
+ /* XXX Helper funct to conv char* to name? */
+ origin = lookup->origin->origin;
+#ifdef WITH_IDN_SUPPORT
+ if (lookup->idnin) {
+ result = idn_locale_to_ace(origin, idn_origin, sizeof(idn_origin));
+ check_result(result, "convert origin to IDN encoding");
+ debug("trying idn origin %s", idn_origin);
+ origin = idn_origin;
+ }
+#endif
+ len = (unsigned int) strlen(origin);
+ isc_buffer_init(&b, origin, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
+ 0, &lookup->onamebuf);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->oname);
+ fatal("'%s' is not in legal name syntax (%s)",
+ origin,
+ isc_result_totext(result));
+ }
+ if (lookup->trace && lookup->trace_root) {
+ dns_name_clone(dns_rootname, lookup->name);
+ } else {
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ name = dns_fixedname_initname(&fixed);
+ len = (unsigned int) strlen(textname);
+ isc_buffer_init(&b, textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(name, &b, NULL, 0, NULL);
+ if (result == ISC_R_SUCCESS &&
+ !dns_name_isabsolute(name))
+ result = dns_name_concatenate(name,
+ lookup->oname,
+ lookup->name,
+ &lookup->namebuf);
+ else if (result == ISC_R_SUCCESS)
+ result = dns_name_copy(name, lookup->name,
+ &lookup->namebuf);
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->oname);
+ if (result == DNS_R_NAMETOOLONG)
+ return (false);
+ fatal("'%s' is not in legal name syntax (%s)",
+ lookup->textname,
+ isc_result_totext(result));
+ }
+ }
+ dns_message_puttempname(lookup->sendmsg, &lookup->oname);
+ } else {
+ debug("using root origin");
+ if (lookup->trace && lookup->trace_root)
+ dns_name_clone(dns_rootname, lookup->name);
+ else {
+ len = (unsigned int) strlen(textname);
+ isc_buffer_init(&b, textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
+ dns_rootname, 0,
+ &lookup->namebuf);
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ fatal("'%s' is not a legal name "
+ "(%s)", lookup->textname,
+ isc_result_totext(result));
+ }
+ }
+ dns_name_format(lookup->name, store, sizeof(store));
+ dighost_trying(store, lookup);
+ INSIST(dns_name_isabsolute(lookup->name));
+
+ isc_random_get(&id);
+ lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
+ lookup->sendmsg->opcode = lookup->opcode;
+ lookup->msgcounter = 0;
+ /*
+ * If this is a trace request, completely disallow recursion, since
+ * it's meaningless for traces.
+ */
+ if (lookup->trace || (lookup->ns_search_only && !lookup->trace_root))
+ lookup->recurse = false;
+
+ if (lookup->recurse &&
+ lookup->rdtype != dns_rdatatype_axfr &&
+ lookup->rdtype != dns_rdatatype_ixfr) {
+ debug("recursive query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_RD;
+ }
+
+ /* XXX aaflag */
+ if (lookup->aaonly) {
+ debug("AA query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AA;
+ }
+
+ if (lookup->adflag) {
+ debug("AD query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_AD;
+ }
+
+ if (lookup->cdflag) {
+ debug("CD query");
+ lookup->sendmsg->flags |= DNS_MESSAGEFLAG_CD;
+ }
+
+ if (lookup->zflag) {
+ debug("Z query");
+ lookup->sendmsg->flags |= 0x0040U;
+ }
+
+ dns_message_addname(lookup->sendmsg, lookup->name,
+ DNS_SECTION_QUESTION);
+
+ if (lookup->trace && lookup->trace_root) {
+ lookup->qrdtype = lookup->rdtype;
+ lookup->rdtype = dns_rdatatype_ns;
+ }
+
+ if ((lookup->rdtype == dns_rdatatype_axfr) ||
+ (lookup->rdtype == dns_rdatatype_ixfr)) {
+ /*
+ * Force TCP mode if we're doing an axfr.
+ */
+ if (lookup->rdtype == dns_rdatatype_axfr) {
+ lookup->doing_xfr = true;
+ lookup->tcp_mode = true;
+ } else if (lookup->tcp_mode) {
+ lookup->doing_xfr = true;
+ }
+ }
+
+ if (!lookup->header_only)
+ add_question(lookup->sendmsg, lookup->name, lookup->rdclass,
+ lookup->rdtype);
+
+ /* add_soa */
+ if (lookup->rdtype == dns_rdatatype_ixfr)
+ insert_soa(lookup);
+
+ /* XXX Insist this? */
+ lookup->tsigctx = NULL;
+ lookup->querysig = NULL;
+ if (tsigkey != NULL) {
+ debug("initializing keys");
+ result = dns_message_settsigkey(lookup->sendmsg, tsigkey);
+ check_result(result, "dns_message_settsigkey");
+ }
+
+ lookup->sendspace = isc_mempool_get(commctx);
+ if (lookup->sendspace == NULL)
+ fatal("memory allocation failure");
+
+ result = dns_compress_init(&cctx, -1, mctx);
+ check_result(result, "dns_compress_init");
+
+ debug("starting to render the message");
+ isc_buffer_init(&lookup->renderbuf, lookup->sendspace, COMMSIZE);
+ result = dns_message_renderbegin(lookup->sendmsg, &cctx,
+ &lookup->renderbuf);
+ check_result(result, "dns_message_renderbegin");
+ if (lookup->udpsize > 0 || lookup->dnssec ||
+ lookup->edns > -1 || lookup->ecs_addr != NULL)
+ {
+#define MAXOPTS (EDNSOPT_OPTIONS + DNS_EDNSOPTIONS)
+ dns_ednsopt_t opts[MAXOPTS];
+ unsigned int flags;
+ unsigned int i = 0;
+
+ if (lookup->udpsize == 0)
+ lookup->udpsize = 4096;
+ if (lookup->edns < 0)
+ lookup->edns = 0;
+
+ if (lookup->nsid) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_NSID;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (lookup->ecs_addr != NULL) {
+ uint8_t addr[16];
+ uint16_t family;
+ uint32_t plen;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ size_t addrl;
+
+ sa = &lookup->ecs_addr->type.sa;
+ plen = lookup->ecs_addr->length;
+
+ /* Round up prefix len to a multiple of 8 */
+ addrl = (plen + 7) / 8;
+
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_CLIENT_SUBNET;
+ opts[i].length = (uint16_t) addrl + 4;
+ check_result(result, "isc_buffer_allocate");
+
+ /*
+ * XXXMUKS: According to RFC7871, "If there is
+ * no ADDRESS set, i.e., SOURCE PREFIX-LENGTH is
+ * set to 0, then FAMILY SHOULD be set to the
+ * transport over which the query is sent."
+ *
+ * However, at this point we don't know what
+ * transport(s) we'll be using, so we can't
+ * set the value now. For now, we're using
+ * IPv4 as the default the +subnet option
+ * used an IPv4 prefix, or for +subnet=0,
+ * and IPv6 if the +subnet option used an
+ * IPv6 prefix.
+ *
+ * (For future work: preserve the offset into
+ * the buffer where the family field is;
+ * that way we can update it in send_udp()
+ * or send_tcp_connect() once we know
+ * what it outght to be.)
+ */
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ INSIST(plen == 0);
+ family = 1;
+ break;
+ case AF_INET:
+ INSIST(plen <= 32);
+ family = 1;
+ sin = (struct sockaddr_in *) sa;
+ memmove(addr, &sin->sin_addr, addrl);
+ break;
+ case AF_INET6:
+ INSIST(plen <= 128);
+ family = 2;
+ sin6 = (struct sockaddr_in6 *) sa;
+ memmove(addr, &sin6->sin6_addr, addrl);
+ break;
+ default:
+ INSIST(0);
+ }
+
+ isc_buffer_init(&b, ecsbuf, sizeof(ecsbuf));
+ /* 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) {
+ /* Mask off last address byte */
+ if ((plen % 8) != 0)
+ addr[addrl - 1] &=
+ ~0U << (8 - (plen % 8));
+ isc_buffer_putmem(&b, addr,
+ (unsigned)addrl);
+ }
+
+ opts[i].value = (uint8_t *) ecsbuf;
+ i++;
+ }
+
+ if (lookup->sendcookie) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_COOKIE;
+ if (lookup->cookie != NULL) {
+ isc_buffer_init(&b, cookiebuf,
+ sizeof(cookiebuf));
+ result = isc_hex_decodestring(lookup->cookie,
+ &b);
+ check_result(result, "isc_hex_decodestring");
+ opts[i].value = isc_buffer_base(&b);
+ opts[i].length = isc_buffer_usedlength(&b);
+ } else {
+ compute_cookie(cookie, sizeof(cookie));
+ opts[i].length = 8;
+ opts[i].value = cookie;
+ }
+ i++;
+ }
+
+ if (lookup->expire) {
+ INSIST(i < MAXOPTS);
+ opts[i].code = DNS_OPT_EXPIRE;
+ opts[i].length = 0;
+ opts[i].value = NULL;
+ i++;
+ }
+
+ if (lookup->ednsoptscnt != 0) {
+ INSIST(i + lookup->ednsoptscnt <= MAXOPTS);
+ memmove(&opts[i], lookup->ednsopts,
+ sizeof(dns_ednsopt_t) * lookup->ednsoptscnt);
+ i += lookup->ednsoptscnt;
+ }
+
+ flags = lookup->ednsflags;
+ flags &= ~DNS_MESSAGEEXTFLAG_DO;
+ if (lookup->dnssec)
+ flags |= DNS_MESSAGEEXTFLAG_DO;
+ add_opt(lookup->sendmsg, lookup->udpsize,
+ lookup->edns, flags, opts, i);
+ }
+
+ result = dns_message_rendersection(lookup->sendmsg,
+ DNS_SECTION_QUESTION, 0);
+ check_result(result, "dns_message_rendersection");
+ result = dns_message_rendersection(lookup->sendmsg,
+ DNS_SECTION_AUTHORITY, 0);
+ check_result(result, "dns_message_rendersection");
+ result = dns_message_renderend(lookup->sendmsg);
+ check_result(result, "dns_message_renderend");
+ debug("done rendering");
+
+ dns_compress_invalidate(&cctx);
+
+ /*
+ * Force TCP mode if the request is larger than 512 bytes.
+ */
+ if (isc_buffer_usedlength(&lookup->renderbuf) > 512)
+ lookup->tcp_mode = true;
+
+ lookup->pending = false;
+
+ for (serv = ISC_LIST_HEAD(lookup->my_server_list);
+ serv != NULL;
+ serv = ISC_LIST_NEXT(serv, link)) {
+ query = isc_mem_allocate(mctx, sizeof(dig_query_t));
+ if (query == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ debug("create query %p linked to lookup %p",
+ query, lookup);
+ query->lookup = lookup;
+ query->timer = NULL;
+ query->waiting_connect = false;
+ query->waiting_senddone = false;
+ query->pending_free = false;
+ query->recv_made = false;
+ query->first_pass = true;
+ query->first_soa_rcvd = false;
+ query->second_rr_rcvd = false;
+ query->first_repeat_rcvd = false;
+ query->warn_id = true;
+ query->timedout = false;
+ query->first_rr_serial = 0;
+ query->second_rr_serial = 0;
+ query->servname = serv->servername;
+ query->userarg = serv->userarg;
+ query->rr_count = 0;
+ query->msg_count = 0;
+ query->byte_count = 0;
+ query->ixfr_axfr = false;
+ ISC_LIST_INIT(query->recvlist);
+ ISC_LIST_INIT(query->lengthlist);
+ query->sock = NULL;
+ query->recvspace = isc_mempool_get(commctx);
+ if (query->recvspace == NULL)
+ fatal("memory allocation failure");
+
+ isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
+ isc_buffer_init(&query->lengthbuf, query->lengthspace, 2);
+ isc_buffer_init(&query->slbuf, query->slspace, 2);
+ query->sendbuf = lookup->renderbuf;
+
+ ISC_LINK_INIT(query, clink);
+ ISC_LINK_INIT(query, link);
+ ISC_LIST_ENQUEUE(lookup->q, query, link);
+ }
+
+ /* XXX qrflag, print_query, etc... */
+ if (!ISC_LIST_EMPTY(lookup->q) && qr) {
+ extrabytes = 0;
+ dighost_printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
+ true);
+ if (lookup->stats)
+ printf(";; QUERY SIZE: %u\n\n",
+ isc_buffer_usedlength(&lookup->renderbuf));
+ }
+ return (true);
+}
+
+/*%
+ * Event handler for send completion. Track send counter, and clear out
+ * the query if the send was canceled.
+ */
+static void
+send_done(isc_task_t *_task, isc_event_t *event) {
+ isc_socketevent_t *sevent = (isc_socketevent_t *)event;
+ isc_buffer_t *b = NULL;
+ dig_query_t *query, *next;
+ dig_lookup_t *l;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_SENDDONE);
+
+ UNUSED(_task);
+
+ LOCK_LOOKUP;
+
+ debug("send_done()");
+ sendcount--;
+ debug("sendcount=%d", sendcount);
+ INSIST(sendcount >= 0);
+
+ for (b = ISC_LIST_HEAD(sevent->bufferlist);
+ b != NULL;
+ b = ISC_LIST_HEAD(sevent->bufferlist)) {
+ ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+ isc_mem_free(mctx, b);
+ }
+
+ query = event->ev_arg;
+ query->waiting_senddone = false;
+ l = query->lookup;
+
+ if (l->ns_search_only && !l->trace_root && !l->tcp_mode) {
+ debug("sending next, since searching");
+ next = ISC_LIST_NEXT(query, link);
+ if (next != NULL)
+ send_udp(next);
+ }
+
+ isc_event_free(&event);
+
+ if (query->pending_free)
+ isc_mem_free(mctx, query);
+
+ check_if_done();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Cancel a lookup, sending isc_socket_cancel() requests to all outstanding
+ * IO sockets. The cancel handlers should take care of cleaning up the
+ * query and lookup structures
+ */
+static void
+cancel_lookup(dig_lookup_t *lookup) {
+ dig_query_t *query, *next;
+
+ debug("cancel_lookup()");
+ query = ISC_LIST_HEAD(lookup->q);
+ while (query != NULL) {
+ next = ISC_LIST_NEXT(query, link);
+ if (query->sock != NULL) {
+ isc_socket_cancel(query->sock, global_task,
+ ISC_SOCKCANCEL_ALL);
+ check_if_done();
+ } else {
+ clear_query(query);
+ }
+ query = next;
+ }
+ lookup->pending = false;
+ lookup->retries = 0;
+}
+
+static void
+bringup_timer(dig_query_t *query, unsigned int default_timeout) {
+ dig_lookup_t *l;
+ unsigned int local_timeout;
+ isc_result_t result;
+
+ debug("bringup_timer()");
+ /*
+ * If the timer already exists, that means we're calling this
+ * a second time (for a retry). Don't need to recreate it,
+ * just reset it.
+ */
+ l = query->lookup;
+ if (ISC_LINK_LINKED(query, link) && ISC_LIST_NEXT(query, link) != NULL)
+ local_timeout = SERVER_TIMEOUT;
+ else {
+ if (timeout == 0)
+ local_timeout = default_timeout;
+ else
+ local_timeout = timeout;
+ }
+ debug("have local timeout of %d", local_timeout);
+ isc_interval_set(&l->interval, local_timeout, 0);
+ if (query->timer != NULL)
+ isc_timer_detach(&query->timer);
+ result = isc_timer_create(timermgr, isc_timertype_once, NULL,
+ &l->interval, global_task, connect_timeout,
+ query, &query->timer);
+ check_result(result, "isc_timer_create");
+}
+
+static void
+force_timeout(dig_query_t *query) {
+ isc_event_t *event;
+
+ debug("force_timeout ()");
+ event = isc_event_allocate(mctx, query, ISC_TIMEREVENT_IDLE,
+ connect_timeout, query,
+ sizeof(isc_event_t));
+ if (event == NULL) {
+ fatal("isc_event_allocate: %s",
+ isc_result_totext(ISC_R_NOMEMORY));
+ }
+ isc_task_send(global_task, &event);
+
+ /*
+ * The timer may have expired if, for example, get_address() takes
+ * long time and the timer was running on a different thread.
+ * We need to cancel the possible timeout event not to confuse
+ * ourselves due to the duplicate events.
+ */
+ if (query->timer != NULL)
+ isc_timer_detach(&query->timer);
+}
+
+
+static void
+connect_done(isc_task_t *task, isc_event_t *event);
+
+/*%
+ * Unlike send_udp, this can't be called multiple times with the same
+ * query. When we retry TCP, we requeue the whole lookup, which should
+ * start anew.
+ */
+static void
+send_tcp_connect(dig_query_t *query) {
+ isc_result_t result;
+ dig_query_t *next;
+ dig_lookup_t *l;
+
+ debug("send_tcp_connect(%p)", query);
+
+ l = query->lookup;
+ query->waiting_connect = true;
+ query->lookup->current_query = query;
+ result = get_address(query->servname, port, &query->sockaddr);
+ if (result != ISC_R_SUCCESS) {
+ /*
+ * This servname doesn't have an address. Try the next server
+ * by triggering an immediate 'timeout' (we lie, but the effect
+ * is the same).
+ */
+ force_timeout(query);
+ return;
+ }
+
+ if (!l->mapped && isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) {
+ isc_netaddr_t netaddr;
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
+ isc_netaddr_format(&netaddr, buf, sizeof(buf));
+ printf(";; Skipping mapped address '%s'\n", buf);
+
+ query->waiting_connect = false;
+ if (ISC_LINK_LINKED(query, link))
+ next = ISC_LIST_NEXT(query, link);
+ else
+ next = NULL;
+ l = query->lookup;
+ clear_query(query);
+ if (next == NULL) {
+ printf(";; No acceptable nameservers\n");
+ check_next_lookup(l);
+ return;
+ }
+ send_tcp_connect(next);
+ return;
+ }
+
+ if (specified_source &&
+ (isc_sockaddr_pf(&query->sockaddr) !=
+ isc_sockaddr_pf(&bind_address))) {
+ printf(";; Skipping server %s, incompatible "
+ "address family\n", query->servname);
+ query->waiting_connect = false;
+ if (ISC_LINK_LINKED(query, link))
+ next = ISC_LIST_NEXT(query, link);
+ else
+ next = NULL;
+ l = query->lookup;
+ clear_query(query);
+ if (next == NULL) {
+ printf(";; No acceptable nameservers\n");
+ check_next_lookup(l);
+ return;
+ }
+ send_tcp_connect(next);
+ return;
+ }
+
+ INSIST(query->sock == NULL);
+
+ if (keep != NULL && isc_sockaddr_equal(&keepaddr, &query->sockaddr)) {
+ sockcount++;
+ isc_socket_attach(keep, &query->sock);
+ query->waiting_connect = false;
+ launch_next_query(query, true);
+ goto search;
+ }
+
+ result = isc_socket_create(socketmgr,
+ isc_sockaddr_pf(&query->sockaddr),
+ isc_sockettype_tcp, &query->sock);
+ check_result(result, "isc_socket_create");
+ sockcount++;
+ debug("sockcount=%d", sockcount);
+ if (query->lookup->dscp != -1)
+ isc_socket_dscp(query->sock, query->lookup->dscp);
+ isc_socket_ipv6only(query->sock, !query->lookup->mapped);
+ if (specified_source)
+ result = isc_socket_bind(query->sock, &bind_address,
+ ISC_SOCKET_REUSEADDRESS);
+ else {
+ if ((isc_sockaddr_pf(&query->sockaddr) == AF_INET) &&
+ have_ipv4)
+ isc_sockaddr_any(&bind_any);
+ else
+ isc_sockaddr_any6(&bind_any);
+ result = isc_socket_bind(query->sock, &bind_any, 0);
+ }
+ check_result(result, "isc_socket_bind");
+ bringup_timer(query, TCP_TIMEOUT);
+ result = isc_socket_connect(query->sock, &query->sockaddr,
+ global_task, connect_done, query);
+ check_result(result, "isc_socket_connect");
+ search:
+ /*
+ * If we're at the endgame of a nameserver search, we need to
+ * immediately bring up all the queries. Do it here.
+ */
+ if (l->ns_search_only && !l->trace_root) {
+ debug("sending next, since searching");
+ if (ISC_LINK_LINKED(query, link)) {
+ next = ISC_LIST_NEXT(query, link);
+ ISC_LIST_DEQUEUE(l->q, query, link);
+ } else
+ next = NULL;
+ ISC_LIST_ENQUEUE(l->connecting, query, clink);
+ if (next != NULL)
+ send_tcp_connect(next);
+ }
+}
+
+static isc_buffer_t *
+clone_buffer(isc_buffer_t *source) {
+ isc_buffer_t *buffer;
+ buffer = isc_mem_allocate(mctx, sizeof(*buffer));
+ if (buffer == NULL)
+ fatal("memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ *buffer = *source;
+ return (buffer);
+}
+
+/*%
+ * Send a UDP packet to the remote nameserver, possible starting the
+ * recv action as well. Also make sure that the timer is running and
+ * is properly reset.
+ */
+static void
+send_udp(dig_query_t *query) {
+ dig_lookup_t *l = NULL;
+ isc_result_t result;
+ isc_buffer_t *sendbuf;
+ dig_query_t *next;
+
+ debug("send_udp(%p)", query);
+
+ l = query->lookup;
+ bringup_timer(query, UDP_TIMEOUT);
+ l->current_query = query;
+ debug("working on lookup %p, query %p", query->lookup, query);
+ if (!query->recv_made) {
+ /* XXX Check the sense of this, need assertion? */
+ query->waiting_connect = false;
+ result = get_address(query->servname, port, &query->sockaddr);
+ if (result != ISC_R_SUCCESS) {
+ /* This servname doesn't have an address. */
+ force_timeout(query);
+ return;
+ }
+
+ if (!l->mapped &&
+ isc_sockaddr_pf(&query->sockaddr) == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&query->sockaddr.type.sin6.sin6_addr)) {
+ isc_netaddr_t netaddr;
+ char buf[ISC_NETADDR_FORMATSIZE];
+
+ isc_netaddr_fromsockaddr(&netaddr, &query->sockaddr);
+ isc_netaddr_format(&netaddr, buf, sizeof(buf));
+ printf(";; Skipping mapped address '%s'\n", buf);
+
+ next = ISC_LIST_NEXT(query, link);
+ l = query->lookup;
+ clear_query(query);
+ if (next == NULL) {
+ printf(";; No acceptable nameservers\n");
+ check_next_lookup(l);
+ } else {
+ send_udp(next);
+ }
+ return;
+ }
+
+ result = isc_socket_create(socketmgr,
+ isc_sockaddr_pf(&query->sockaddr),
+ isc_sockettype_udp, &query->sock);
+ check_result(result, "isc_socket_create");
+ sockcount++;
+ debug("sockcount=%d", sockcount);
+ if (query->lookup->dscp != -1)
+ isc_socket_dscp(query->sock, query->lookup->dscp);
+ isc_socket_ipv6only(query->sock,
+ !query->lookup->mapped);
+ if (specified_source) {
+ result = isc_socket_bind(query->sock, &bind_address,
+ ISC_SOCKET_REUSEADDRESS);
+ } else {
+ isc_sockaddr_anyofpf(&bind_any,
+ isc_sockaddr_pf(&query->sockaddr));
+ result = isc_socket_bind(query->sock, &bind_any, 0);
+ }
+ check_result(result, "isc_socket_bind");
+
+ query->recv_made = true;
+ ISC_LINK_INIT(&query->recvbuf, link);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf,
+ link);
+ debug("recving with lookup=%p, query=%p, sock=%p",
+ query->lookup, query, query->sock);
+ result = isc_socket_recvv(query->sock, &query->recvlist, 1,
+ global_task, recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("recvcount=%d", recvcount);
+ }
+ ISC_LIST_INIT(query->sendlist);
+ sendbuf = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, sendbuf, link);
+ debug("sending a request");
+ TIME_NOW(&query->time_sent);
+ INSIST(query->sock != NULL);
+ query->waiting_senddone = true;
+ result = isc_socket_sendtov2(query->sock, &query->sendlist,
+ global_task, send_done, query,
+ &query->sockaddr, NULL,
+ ISC_SOCKFLAG_NORETRY);
+ check_result(result, "isc_socket_sendtov");
+ sendcount++;
+}
+
+/*%
+ * IO timeout handler, used for both connect and recv timeouts. If
+ * retries are still allowed, either resend the UDP packet or queue a
+ * new TCP lookup. Otherwise, cancel the lookup.
+ */
+static void
+connect_timeout(isc_task_t *task, isc_event_t *event) {
+ dig_lookup_t *l = NULL;
+ dig_query_t *query = NULL, *cq;
+
+ UNUSED(task);
+ REQUIRE(event->ev_type == ISC_TIMEREVENT_IDLE);
+
+ debug("connect_timeout()");
+
+ LOCK_LOOKUP;
+ query = event->ev_arg;
+ l = query->lookup;
+ isc_event_free(&event);
+
+ INSIST(!free_now);
+
+ if ((query != NULL) && (query->lookup->current_query != NULL) &&
+ ISC_LINK_LINKED(query->lookup->current_query, link) &&
+ (ISC_LIST_NEXT(query->lookup->current_query, link) != NULL)) {
+ debug("trying next server...");
+ cq = query->lookup->current_query;
+ if (!l->tcp_mode)
+ send_udp(ISC_LIST_NEXT(cq, link));
+ else {
+ if (query->sock != NULL)
+ isc_socket_cancel(query->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ send_tcp_connect(ISC_LIST_NEXT(cq, link));
+ }
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (l->tcp_mode && query->sock != NULL) {
+ query->timedout = true;
+ isc_socket_cancel(query->sock, NULL, ISC_SOCKCANCEL_ALL);
+ }
+
+ if (l->retries > 1) {
+ if (!l->tcp_mode) {
+ l->retries--;
+ debug("resending UDP request to first server");
+ send_udp(ISC_LIST_HEAD(l->q));
+ } else {
+ debug("making new TCP request, %d tries left",
+ l->retries);
+ l->retries--;
+ requeue_lookup(l, true);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ }
+ } else {
+ if (!l->ns_search_only) {
+ fputs(l->cmdline, stdout);
+ printf(";; connection timed out; no servers could be "
+ "reached\n");
+ }
+ cancel_lookup(l);
+ check_next_lookup(l);
+ if (exitcode < 9)
+ exitcode = 9;
+ }
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Event handler for the TCP recv which gets the length header of TCP
+ * packets. Start the next recv of length bytes.
+ */
+static void
+tcp_length_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent;
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ dig_query_t *query = NULL;
+ dig_lookup_t *l, *n;
+ uint16_t length;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
+ INSIST(!free_now);
+
+ UNUSED(task);
+
+ debug("tcp_length_done()");
+
+ LOCK_LOOKUP;
+ sevent = (isc_socketevent_t *)event;
+ query = event->ev_arg;
+
+ recvcount--;
+ INSIST(recvcount >= 0);
+
+ b = ISC_LIST_HEAD(sevent->bufferlist);
+ INSIST(b == &query->lengthbuf);
+ ISC_LIST_DEQUEUE(sevent->bufferlist, b, link);
+
+ if (sevent->result == ISC_R_CANCELED) {
+ isc_event_free(&event);
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (sevent->result != ISC_R_SUCCESS) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(&query->sockaddr, sockstr,
+ sizeof(sockstr));
+ printf(";; communications error to %s: %s\n",
+ sockstr, isc_result_totext(sevent->result));
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ l = query->lookup;
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
+ n = requeue_lookup(l, true);
+ n->eoferr++;
+ }
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ length = isc_buffer_getuint16(b);
+ if (length == 0) {
+ isc_event_free(&event);
+ launch_next_query(query, false);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ /*
+ * Even though the buffer was already init'ed, we need
+ * to redo it now, to force the length we want.
+ */
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_init(&query->recvbuf, query->recvspace, length);
+ ENSURE(ISC_LIST_EMPTY(query->recvlist));
+ ISC_LINK_INIT(&query->recvbuf, link);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
+ debug("recving with lookup=%p, query=%p", query->lookup, query);
+ result = isc_socket_recvv(query->sock, &query->recvlist, length, task,
+ recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("resubmitted recv request with length %d, recvcount=%d",
+ length, recvcount);
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * For transfers that involve multiple recvs (XFR's in particular),
+ * launch the next recv.
+ */
+static void
+launch_next_query(dig_query_t *query, bool include_question) {
+ isc_result_t result;
+ dig_lookup_t *l;
+ isc_buffer_t *buffer;
+
+ INSIST(!free_now);
+
+ debug("launch_next_query()");
+
+ if (!query->lookup->pending) {
+ debug("ignoring launch_next_query because !pending");
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ query->waiting_connect = false;
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ return;
+ }
+
+ isc_buffer_clear(&query->slbuf);
+ isc_buffer_clear(&query->lengthbuf);
+ isc_buffer_putuint16(&query->slbuf, (uint16_t) query->sendbuf.used);
+ ISC_LIST_INIT(query->sendlist);
+ ISC_LINK_INIT(&query->slbuf, link);
+ if (!query->first_soa_rcvd) {
+ buffer = clone_buffer(&query->slbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ if (include_question) {
+ buffer = clone_buffer(&query->sendbuf);
+ ISC_LIST_ENQUEUE(query->sendlist, buffer, link);
+ }
+ }
+
+ ISC_LINK_INIT(&query->lengthbuf, link);
+ ISC_LIST_ENQUEUE(query->lengthlist, &query->lengthbuf, link);
+
+ result = isc_socket_recvv(query->sock, &query->lengthlist, 0,
+ global_task, tcp_length_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ debug("recvcount=%d", recvcount);
+ if (!query->first_soa_rcvd) {
+ debug("sending a request in launch_next_query");
+ TIME_NOW(&query->time_sent);
+ query->waiting_senddone = true;
+ result = isc_socket_sendv(query->sock, &query->sendlist,
+ global_task, send_done, query);
+ check_result(result, "isc_socket_sendv");
+ sendcount++;
+ debug("sendcount=%d", sendcount);
+ }
+ query->waiting_connect = false;
+#if 0
+ check_next_lookup(query->lookup);
+#endif
+ return;
+}
+
+/*%
+ * Event handler for TCP connect complete. Make sure the connection was
+ * successful, then pass into launch_next_query to actually send the
+ * question.
+ */
+static void
+connect_done(isc_task_t *task, isc_event_t *event) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+ isc_socketevent_t *sevent = NULL;
+ dig_query_t *query = NULL, *next;
+ dig_lookup_t *l;
+
+ UNUSED(task);
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_CONNECT);
+ INSIST(!free_now);
+
+ debug("connect_done()");
+
+ LOCK_LOOKUP;
+ sevent = (isc_socketevent_t *)event;
+ query = sevent->ev_arg;
+
+ INSIST(query->waiting_connect);
+
+ query->waiting_connect = false;
+
+ if (sevent->result == ISC_R_CANCELED) {
+ debug("in cancel handler");
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ if (query->timedout)
+ printf(";; Connection to %s(%s) for %s failed: %s.\n",
+ sockstr, query->servname,
+ query->lookup->textname,
+ isc_result_totext(ISC_R_TIMEDOUT));
+ isc_socket_detach(&query->sock);
+ INSIST(sockcount > 0);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = false;
+ isc_event_free(&event);
+ l = query->lookup;
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (sevent->result != ISC_R_SUCCESS) {
+
+ debug("unsuccessful connection: %s",
+ isc_result_totext(sevent->result));
+ isc_sockaddr_format(&query->sockaddr, sockstr, sizeof(sockstr));
+ if (sevent->result != ISC_R_CANCELED)
+ printf(";; Connection to %s(%s) for %s failed: "
+ "%s.\n", sockstr,
+ query->servname, query->lookup->textname,
+ isc_result_totext(sevent->result));
+ isc_socket_detach(&query->sock);
+ INSIST(sockcount > 0);
+ sockcount--;
+ /* XXX Clean up exitcodes */
+ if (exitcode < 9)
+ exitcode = 9;
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = false;
+ isc_event_free(&event);
+ l = query->lookup;
+ if ((l->current_query != NULL) &&
+ (ISC_LINK_LINKED(l->current_query, link)))
+ next = ISC_LIST_NEXT(l->current_query, link);
+ else
+ next = NULL;
+ clear_query(query);
+ if (next != NULL) {
+ bringup_timer(next, TCP_TIMEOUT);
+ send_tcp_connect(next);
+ } else
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ exitcode = 0;
+ if (keep_open) {
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ isc_socket_attach(query->sock, &keep);
+ keepaddr = query->sockaddr;
+ }
+ launch_next_query(query, true);
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Check if the ongoing XFR needs more data before it's complete, using
+ * the semantics of IXFR and AXFR protocols. Much of the complexity of
+ * this routine comes from determining when an IXFR is complete.
+ * false means more data is on the way, and the recv has been issued.
+ */
+static bool
+check_for_more_data(dig_query_t *query, dns_message_t *msg,
+ isc_socketevent_t *sevent)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dns_rdata_soa_t soa;
+ uint32_t ixfr_serial = query->lookup->ixfr_serial, serial;
+ isc_result_t result;
+ bool ixfr = query->lookup->rdtype == dns_rdatatype_ixfr;
+ bool axfr = query->lookup->rdtype == dns_rdatatype_axfr;
+
+ if (ixfr)
+ axfr = query->ixfr_axfr;
+
+ debug("check_for_more_data()");
+
+ /*
+ * By the time we're in this routine, we know we're doing
+ * either an AXFR or IXFR. If there's no second_rr_type,
+ * then we don't yet know which kind of answer we got back
+ * from the server. Here, we're going to walk through the
+ * rr's in the message, acting as necessary whenever we hit
+ * an SOA rr.
+ */
+
+ query->msg_count++;
+ query->byte_count += sevent->n;
+ result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
+ if (result != ISC_R_SUCCESS) {
+ puts("; Transfer failed.");
+ return (true);
+ }
+ do {
+ dns_name_t *name;
+ name = NULL;
+ dns_message_currentname(msg, DNS_SECTION_ANSWER,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ result = dns_rdataset_first(rdataset);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ do {
+ query->rr_count++;
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ /*
+ * If this is the first rr, make sure
+ * it's an SOA
+ */
+ if ((!query->first_soa_rcvd) &&
+ (rdata.type != dns_rdatatype_soa)) {
+ puts("; Transfer failed. "
+ "Didn't start with SOA answer.");
+ return (true);
+ }
+ if ((!query->second_rr_rcvd) &&
+ (rdata.type != dns_rdatatype_soa)) {
+ query->second_rr_rcvd = true;
+ query->second_rr_serial = 0;
+ debug("got the second rr as nonsoa");
+ axfr = query->ixfr_axfr = true;
+ goto next_rdata;
+ }
+
+ /*
+ * If the record is anything except an SOA
+ * now, just continue on...
+ */
+ if (rdata.type != dns_rdatatype_soa)
+ goto next_rdata;
+
+ /* Now we have an SOA. Work with it. */
+ debug("got an SOA");
+ result = dns_rdata_tostruct(&rdata, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ serial = soa.serial;
+ dns_rdata_freestruct(&soa);
+ if (!query->first_soa_rcvd) {
+ query->first_soa_rcvd = true;
+ query->first_rr_serial = serial;
+ debug("this is the first serial %u",
+ serial);
+ if (ixfr && isc_serial_ge(ixfr_serial,
+ serial)) {
+ debug("got up to date "
+ "response");
+ goto doexit;
+ }
+ goto next_rdata;
+ }
+ if (axfr) {
+ debug("doing axfr, got second SOA");
+ goto doexit;
+ }
+ if (!query->second_rr_rcvd) {
+ if (query->first_rr_serial == serial) {
+ debug("doing ixfr, got "
+ "empty zone");
+ goto doexit;
+ }
+ debug("this is the second serial %u",
+ serial);
+ query->second_rr_rcvd = true;
+ query->second_rr_serial = serial;
+ goto next_rdata;
+ }
+ /*
+ * If we get to this point, we're doing an
+ * IXFR and have to start really looking
+ * at serial numbers.
+ */
+ if (query->first_rr_serial == serial) {
+ debug("got a match for ixfr");
+ if (!query->first_repeat_rcvd) {
+ query->first_repeat_rcvd =
+ true;
+ goto next_rdata;
+ }
+ debug("done with ixfr");
+ goto doexit;
+ }
+ debug("meaningless soa %u", serial);
+ next_rdata:
+ result = dns_rdataset_next(rdataset);
+ } while (result == ISC_R_SUCCESS);
+ }
+ result = dns_message_nextname(msg, DNS_SECTION_ANSWER);
+ } while (result == ISC_R_SUCCESS);
+ launch_next_query(query, false);
+ return (false);
+ doexit:
+ dighost_received(sevent->n, &sevent->address, query);
+ return (true);
+}
+
+static void
+process_cookie(dig_lookup_t *l, dns_message_t *msg,
+ isc_buffer_t *optbuf, size_t optlen)
+{
+ char bb[256];
+ isc_buffer_t hexbuf;
+ size_t len;
+ const unsigned char *sent;
+ bool copy = true;
+ isc_result_t result;
+
+ if (l->cookie != NULL) {
+ isc_buffer_init(&hexbuf, bb, sizeof(bb));
+ result = isc_hex_decodestring(l->cookie, &hexbuf);
+ check_result(result, "isc_hex_decodestring");
+ sent = isc_buffer_base(&hexbuf);
+ len = isc_buffer_usedlength(&hexbuf);
+ } else {
+ sent = cookie;
+ len = sizeof(cookie);
+ }
+
+ INSIST(msg->cc_ok == 0 && msg->cc_bad == 0);
+ if (optlen >= len && optlen >= 8U) {
+ if (isc_safe_memequal(isc_buffer_current(optbuf), sent, 8)) {
+ msg->cc_ok = 1;
+ } else {
+ printf(";; Warning: Client COOKIE mismatch\n");
+ msg->cc_bad = 1;
+ copy = false;
+ }
+ } else {
+ printf(";; Warning: COOKIE bad token (too short)\n");
+ msg->cc_bad = 1;
+ copy = false;
+ }
+ if (copy) {
+ isc_region_t r;
+
+ r.base = isc_buffer_current(optbuf);
+ r.length = (unsigned int)optlen;
+ isc_buffer_init(&hexbuf, servercookie, sizeof(servercookie));
+ result = isc_hex_totext(&r, 2, "", &hexbuf);
+ check_result(result, "isc_hex_totext");
+ if (isc_buffer_availablelength(&hexbuf) > 0) {
+ isc_buffer_putuint8(&hexbuf, 0);
+ l->cookie = servercookie;
+ }
+ }
+ isc_buffer_forward(optbuf, (unsigned int)optlen);
+}
+
+static void
+process_opt(dig_lookup_t *l, dns_message_t *msg) {
+ dns_rdata_t rdata;
+ isc_result_t result;
+ isc_buffer_t optbuf;
+ uint16_t optcode, optlen;
+ dns_rdataset_t *opt = msg->opt;
+ bool seen_cookie = false;
+
+ result = dns_rdataset_first(opt);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_init(&rdata);
+ dns_rdataset_current(opt, &rdata);
+ isc_buffer_init(&optbuf, rdata.data, rdata.length);
+ isc_buffer_add(&optbuf, rdata.length);
+ while (isc_buffer_remaininglength(&optbuf) >= 4) {
+ optcode = isc_buffer_getuint16(&optbuf);
+ optlen = isc_buffer_getuint16(&optbuf);
+ switch (optcode) {
+ case DNS_OPT_COOKIE:
+ /*
+ * Only process the first cookie option.
+ */
+ if (seen_cookie) {
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ }
+ process_cookie(l, msg, &optbuf, optlen);
+ seen_cookie = true;
+ break;
+ default:
+ isc_buffer_forward(&optbuf, optlen);
+ break;
+ }
+ }
+ }
+}
+
+static int
+ednsvers(dns_rdataset_t *opt) {
+ return ((opt->ttl >> 16) & 0xff);
+}
+
+/*%
+ * Event handler for recv complete. Perform whatever actions are necessary,
+ * based on the specifics of the user's request.
+ */
+static void
+recv_done(isc_task_t *task, isc_event_t *event) {
+ isc_socketevent_t *sevent = NULL;
+ dig_query_t *query = NULL;
+ isc_buffer_t *b = NULL;
+ dns_message_t *msg = NULL;
+#ifdef DIG_SIGCHASE
+ dig_message_t *chase_msg = NULL;
+ dig_message_t *chase_msg2 = NULL;
+#endif
+ isc_result_t result;
+ dig_lookup_t *n, *l;
+ bool docancel = false;
+ bool match = true;
+ unsigned int parseflags;
+ dns_messageid_t id;
+ unsigned int msgflags;
+#ifdef DIG_SIGCHASE
+ isc_result_t do_sigchase = false;
+
+ dns_message_t *msg_temp = NULL;
+ isc_region_t r;
+ isc_buffer_t *buf = NULL;
+#endif
+ int newedns;
+
+ UNUSED(task);
+ INSIST(!free_now);
+
+ debug("recv_done()");
+
+ LOCK_LOOKUP;
+ recvcount--;
+ debug("recvcount=%d", recvcount);
+ INSIST(recvcount >= 0);
+
+ query = event->ev_arg;
+ TIME_NOW(&query->time_recv);
+ debug("lookup=%p, query=%p", query->lookup, query);
+
+ l = query->lookup;
+
+ REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
+ sevent = (isc_socketevent_t *)event;
+
+ b = ISC_LIST_HEAD(sevent->bufferlist);
+ INSIST(b == &query->recvbuf);
+ ISC_LIST_DEQUEUE(sevent->bufferlist, &query->recvbuf, link);
+
+ if ((l->tcp_mode) && (query->timer != NULL))
+ isc_timer_touch(query->timer);
+ if ((!l->pending && !l->ns_search_only) || cancel_now) {
+ debug("no longer pending. Got %s",
+ isc_result_totext(sevent->result));
+ query->waiting_connect = false;
+
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (sevent->result != ISC_R_SUCCESS) {
+ if (sevent->result == ISC_R_CANCELED) {
+ debug("in recv cancel handler");
+ query->waiting_connect = false;
+ } else {
+ printf(";; communications error: %s\n",
+ isc_result_totext(sevent->result));
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ }
+ if (sevent->result == ISC_R_EOF && l->eoferr == 0U) {
+ n = requeue_lookup(l, true);
+ n->eoferr++;
+ }
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ if (!l->tcp_mode &&
+ !isc_sockaddr_compare(&sevent->address, &query->sockaddr,
+ ISC_SOCKADDR_CMPADDR|
+ ISC_SOCKADDR_CMPPORT|
+ ISC_SOCKADDR_CMPSCOPE|
+ ISC_SOCKADDR_CMPSCOPEZERO)) {
+ char buf1[ISC_SOCKADDR_FORMATSIZE];
+ char buf2[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_t any;
+
+ if (isc_sockaddr_pf(&query->sockaddr) == AF_INET)
+ isc_sockaddr_any(&any);
+ else
+ isc_sockaddr_any6(&any);
+
+ /*
+ * We don't expect a match when the packet is
+ * sent to 0.0.0.0, :: or to a multicast addresses.
+ * XXXMPA broadcast needs to be handled here as well.
+ */
+ if ((!isc_sockaddr_eqaddr(&query->sockaddr, &any) &&
+ !isc_sockaddr_ismulticast(&query->sockaddr)) ||
+ isc_sockaddr_getport(&query->sockaddr) !=
+ isc_sockaddr_getport(&sevent->address)) {
+ isc_sockaddr_format(&sevent->address, buf1,
+ sizeof(buf1));
+ isc_sockaddr_format(&query->sockaddr, buf2,
+ sizeof(buf2));
+ printf(";; reply from unexpected source: %s,"
+ " expected %s\n", buf1, buf2);
+ match = false;
+ }
+ }
+
+ result = dns_message_peekheader(b, &id, &msgflags);
+ if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
+ match = false;
+ if (l->tcp_mode) {
+ bool fail = true;
+ if (result == ISC_R_SUCCESS) {
+ if (!query->first_soa_rcvd ||
+ query->warn_id)
+ printf(";; %s: ID mismatch: "
+ "expected ID %u, got %u\n",
+ query->first_soa_rcvd ?
+ "WARNING" : "ERROR",
+ l->sendmsg->id, id);
+ if (query->first_soa_rcvd)
+ fail = false;
+ query->warn_id = false;
+ } else
+ printf(";; ERROR: short "
+ "(< header size) message\n");
+ if (fail) {
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ match = true;
+ } else if (result == ISC_R_SUCCESS)
+ printf(";; Warning: ID mismatch: "
+ "expected ID %u, got %u\n", l->sendmsg->id, id);
+ else
+ printf(";; Warning: short "
+ "(< header size) message received\n");
+ }
+
+ if (result == ISC_R_SUCCESS && (msgflags & DNS_MESSAGEFLAG_QR) == 0)
+ printf(";; Warning: query response not set\n");
+
+ if (!match)
+ goto udp_mismatch;
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
+ check_result(result, "dns_message_create");
+
+ if (tsigkey != NULL) {
+ if (l->querysig == NULL) {
+ debug("getting initial querysig");
+ result = dns_message_getquerytsig(l->sendmsg, mctx,
+ &l->querysig);
+ check_result(result, "dns_message_getquerytsig");
+ }
+ result = dns_message_setquerytsig(msg, l->querysig);
+ check_result(result, "dns_message_setquerytsig");
+ result = dns_message_settsigkey(msg, tsigkey);
+ check_result(result, "dns_message_settsigkey");
+ msg->tsigctx = l->tsigctx;
+ l->tsigctx = NULL;
+ if (l->msgcounter != 0)
+ msg->tcp_continuation = 1;
+ l->msgcounter++;
+ }
+
+ debug("before parse starts");
+ parseflags = DNS_MESSAGEPARSE_PRESERVEORDER;
+#ifdef DIG_SIGCHASE
+ if (!l->sigchase) {
+ do_sigchase = false;
+ } else {
+ parseflags = 0;
+ do_sigchase = true;
+ }
+#endif
+ if (l->besteffort) {
+ parseflags |= DNS_MESSAGEPARSE_BESTEFFORT;
+ parseflags |= DNS_MESSAGEPARSE_IGNORETRUNCATION;
+ }
+ result = dns_message_parse(msg, b, parseflags);
+ if (result == DNS_R_RECOVERABLE) {
+ printf(";; Warning: Message parser reports malformed "
+ "message packet.\n");
+ result = ISC_R_SUCCESS;
+ }
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Got bad packet: %s\n", isc_result_totext(result));
+ hex_dump(b);
+ query->waiting_connect = false;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (msg->counts[DNS_SECTION_QUESTION] != 0) {
+ match = true;
+ for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION);
+ result == ISC_R_SUCCESS && match;
+ result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) {
+ dns_name_t *name = NULL;
+ dns_rdataset_t *rdataset;
+
+ dns_message_currentname(msg, DNS_SECTION_QUESTION,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (l->rdtype != rdataset->type ||
+ l->rdclass != rdataset->rdclass ||
+ !dns_name_equal(l->name, name)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char classbuf[DNS_RDATACLASS_FORMATSIZE];
+ dns_name_format(name, namestr,
+ sizeof(namestr));
+ dns_rdatatype_format(rdataset->type,
+ typebuf,
+ sizeof(typebuf));
+ dns_rdataclass_format(rdataset->rdclass,
+ classbuf,
+ sizeof(classbuf));
+ printf(";; Question section mismatch: "
+ "got %s/%s/%s\n",
+ namestr, typebuf, classbuf);
+ match = false;
+ }
+ }
+ }
+ if (!match) {
+ dns_message_destroy(&msg);
+ if (l->tcp_mode) {
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ } else
+ goto udp_mismatch;
+ }
+ }
+ if (msg->rcode == dns_rcode_badvers && msg->opt != NULL &&
+ (newedns = ednsvers(msg->opt)) < l->edns && l->ednsneg) {
+ /*
+ * Add minimum EDNS version required checks here if needed.
+ */
+ if (l->comments)
+ printf(";; BADVERS, retrying with EDNS version %u.\n",
+ (unsigned int)newedns);
+ l->edns = newedns;
+ n = requeue_lookup(l, true);
+ if (l->trace && l->trace_root)
+ n->rdtype = l->qrdtype;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0 &&
+ !l->ignore && !l->tcp_mode) {
+ if (l->cookie == NULL && l->sendcookie && msg->opt != NULL)
+ process_opt(l, msg);
+ if (l->comments)
+ printf(";; Truncated, retrying in TCP mode.\n");
+ n = requeue_lookup(l, true);
+ n->tcp_mode = true;
+ if (l->trace && l->trace_root)
+ n->rdtype = l->qrdtype;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (msg->rcode == dns_rcode_badcookie && !l->tcp_mode &&
+ l->sendcookie && l->badcookie) {
+ process_opt(l, msg);
+ if (msg->cc_ok) {
+ if (l->comments)
+ printf(";; BADCOOKIE, retrying%s.\n",
+ l->seenbadcookie ? " in TCP mode" : "");
+ n = requeue_lookup(l, true);
+ if (l->seenbadcookie)
+ n->tcp_mode = true;
+ n->seenbadcookie = true;
+ if (l->trace && l->trace_root)
+ n->rdtype = l->qrdtype;
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ }
+ if ((msg->rcode == dns_rcode_servfail && !l->servfail_stops) ||
+ (check_ra && (msg->flags & DNS_MESSAGEFLAG_RA) == 0 && l->recurse))
+ {
+ dig_query_t *next = ISC_LIST_NEXT(query, link);
+ if (l->current_query == query)
+ l->current_query = NULL;
+ if (next != NULL) {
+ debug("sending query %p\n", next);
+ if (l->tcp_mode)
+ send_tcp_connect(next);
+ else
+ send_udp(next);
+ }
+ /*
+ * If our query is at the head of the list and there
+ * is no next, we're the only one left, so fall
+ * through to print the message.
+ */
+ if ((ISC_LIST_HEAD(l->q) != query) ||
+ (ISC_LIST_NEXT(query, link) != NULL)) {
+ if (l->comments)
+ printf(";; Got %s from %s, "
+ "trying next server\n",
+ msg->rcode == dns_rcode_servfail ?
+ "SERVFAIL reply" :
+ "recursion not available",
+ query->servname);
+ clear_query(query);
+ check_next_lookup(l);
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ }
+
+ if (tsigkey != NULL) {
+ result = dns_tsig_verify(&query->recvbuf, msg, NULL, NULL);
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't verify signature: %s\n",
+ isc_result_totext(result));
+ validated = false;
+ }
+ l->tsigctx = msg->tsigctx;
+ msg->tsigctx = NULL;
+ if (l->querysig != NULL) {
+ debug("freeing querysig buffer %p", l->querysig);
+ isc_buffer_free(&l->querysig);
+ }
+ result = dns_message_getquerytsig(msg, mctx, &l->querysig);
+ check_result(result,"dns_message_getquerytsig");
+ }
+
+ extrabytes = isc_buffer_remaininglength(b);
+
+ debug("after parse");
+ if (l->doing_xfr && l->xfr_q == NULL) {
+ l->xfr_q = query;
+ /*
+ * Once we are in the XFR message, increase
+ * the timeout to much longer, so brief network
+ * outages won't cause the XFR to abort
+ */
+ if (timeout != INT_MAX && query->timer != NULL) {
+ unsigned int local_timeout;
+
+ if (timeout == 0) {
+ if (l->tcp_mode)
+ local_timeout = TCP_TIMEOUT * 4;
+ else
+ local_timeout = UDP_TIMEOUT * 4;
+ } else {
+ if (timeout < (INT_MAX / 4))
+ local_timeout = timeout * 4;
+ else
+ local_timeout = INT_MAX;
+ }
+ debug("have local timeout of %d", local_timeout);
+ isc_interval_set(&l->interval, local_timeout, 0);
+ result = isc_timer_reset(query->timer,
+ isc_timertype_once,
+ NULL,
+ &l->interval,
+ false);
+ check_result(result, "isc_timer_reset");
+ }
+ }
+
+ if (l->cookie != NULL) {
+ if (msg->opt == NULL)
+ printf(";; expected opt record in response\n");
+ else
+ process_opt(l, msg);
+ } else if (l->sendcookie && msg->opt != NULL)
+ process_opt(l, msg);
+ if (!l->doing_xfr || l->xfr_q == query) {
+ if (msg->rcode == dns_rcode_nxdomain &&
+ (l->origin != NULL || l->need_search)) {
+ if (!next_origin(query->lookup) || showsearch) {
+ dighost_printmessage(query, msg, true);
+ dighost_received(b->used, &sevent->address, query);
+ }
+ } else if (!l->trace && !l->ns_search_only) {
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ dighost_printmessage(query, msg, true);
+ } else if (l->trace) {
+ int nl = 0;
+ int count = msg->counts[DNS_SECTION_ANSWER];
+
+ debug("in TRACE code");
+ if (!l->ns_search_only)
+ dighost_printmessage(query, msg, true);
+
+ l->rdtype = l->qrdtype;
+ if (l->trace_root || (l->ns_search_only && count > 0)) {
+ if (!l->trace_root)
+ l->rdtype = dns_rdatatype_soa;
+ nl = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ l->trace_root = false;
+ } else if (count == 0)
+ nl = followup_lookup(msg, query,
+ DNS_SECTION_AUTHORITY);
+ if (nl == 0)
+ docancel = true;
+ } else {
+ debug("in NSSEARCH code");
+
+ if (l->trace_root) {
+ /*
+ * This is the initial NS query.
+ */
+ int nl;
+
+ l->rdtype = dns_rdatatype_soa;
+ nl = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ if (nl == 0)
+ docancel = true;
+ l->trace_root = false;
+ usesearch = false;
+ } else
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ dighost_printmessage(query, msg, true);
+ }
+#ifdef DIG_SIGCHASE
+ if (do_sigchase) {
+ chase_msg = isc_mem_allocate(mctx,
+ sizeof(dig_message_t));
+ if (chase_msg == NULL) {
+ fatal("Memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ }
+ ISC_LIST_INITANDAPPEND(chase_message_list, chase_msg,
+ link);
+ if (dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE,
+ &msg_temp) != ISC_R_SUCCESS) {
+ fatal("dns_message_create in %s:%d",
+ __FILE__, __LINE__);
+ }
+
+ isc_buffer_usedregion(b, &r);
+ result = isc_buffer_allocate(mctx, &buf, r.length);
+
+ check_result(result, "isc_buffer_allocate");
+ result = isc_buffer_copyregion(buf, &r);
+ check_result(result, "isc_buffer_copyregion");
+
+ result = dns_message_parse(msg_temp, buf, 0);
+
+ isc_buffer_free(&buf);
+ chase_msg->msg = msg_temp;
+
+ chase_msg2 = isc_mem_allocate(mctx,
+ sizeof(dig_message_t));
+ if (chase_msg2 == NULL) {
+ fatal("Memory allocation failure in %s:%d",
+ __FILE__, __LINE__);
+ }
+ ISC_LIST_INITANDAPPEND(chase_message_list2, chase_msg2,
+ link);
+ chase_msg2->msg = msg;
+ }
+#endif
+ }
+
+#ifdef DIG_SIGCHASE
+ if (l->sigchase && ISC_LIST_EMPTY(lookup_list)) {
+ sigchase(msg_temp);
+ }
+#endif
+
+ if (l->pending)
+ debug("still pending.");
+ if (l->doing_xfr) {
+ if (query != l->xfr_q) {
+ dns_message_destroy(&msg);
+ isc_event_free(&event);
+ query->waiting_connect = false;
+ UNLOCK_LOOKUP;
+ return;
+ }
+ if (!docancel)
+ docancel = check_for_more_data(query, msg, sevent);
+ if (docancel) {
+ dns_message_destroy(&msg);
+ clear_query(query);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ }
+ } else {
+
+ if (msg->rcode == dns_rcode_noerror || l->origin == NULL) {
+
+#ifdef DIG_SIGCHASE
+ if (!l->sigchase)
+#endif
+ dighost_received(b->used, &sevent->address, query);
+ }
+
+ if (!query->lookup->ns_search_only)
+ query->lookup->pending = false;
+ if (!query->lookup->ns_search_only ||
+ query->lookup->trace_root || docancel) {
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ dns_message_destroy(&msg);
+
+ cancel_lookup(l);
+ }
+ clear_query(query);
+ check_next_lookup(l);
+ }
+ if (msg != NULL) {
+#ifdef DIG_SIGCHASE
+ if (do_sigchase)
+ msg = NULL;
+ else
+#endif
+ dns_message_destroy(&msg);
+ }
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+
+ udp_mismatch:
+ isc_buffer_invalidate(&query->recvbuf);
+ isc_buffer_init(&query->recvbuf, query->recvspace, COMMSIZE);
+ ISC_LIST_ENQUEUE(query->recvlist, &query->recvbuf, link);
+ result = isc_socket_recvv(query->sock, &query->recvlist, 1,
+ global_task, recv_done, query);
+ check_result(result, "isc_socket_recvv");
+ recvcount++;
+ isc_event_free(&event);
+ UNLOCK_LOOKUP;
+ return;
+}
+
+/*%
+ * Turn a name into an address, using system-supplied routines. This is
+ * used in looking up server names, etc... and needs to use system-supplied
+ * routines, since they may be using a non-DNS system for these lookups.
+ */
+isc_result_t
+get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr) {
+ int count;
+ isc_result_t result;
+ bool is_running;
+
+ is_running = isc_app_isrunning();
+ if (is_running)
+ isc_app_block();
+ result = bind9_getaddresses(host, myport, sockaddr, 1, &count);
+ if (is_running)
+ isc_app_unblock();
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ INSIST(count == 1);
+
+ return (ISC_R_SUCCESS);
+}
+
+int
+getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp) {
+ isc_result_t result;
+ isc_sockaddr_t sockaddrs[DIG_MAX_ADDRESSES];
+ isc_netaddr_t netaddr;
+ int count, i;
+ dig_server_t *srv;
+ char tmp[ISC_NETADDR_FORMATSIZE];
+
+ result = bind9_getaddresses(host, 0, sockaddrs,
+ DIG_MAX_ADDRESSES, &count);
+ if (resultp != NULL)
+ *resultp = result;
+ if (result != ISC_R_SUCCESS) {
+ if (resultp == NULL)
+ fatal("couldn't get address for '%s': %s",
+ host, isc_result_totext(result));
+ return (0);
+ }
+
+ for (i = 0; i < count; i++) {
+ isc_netaddr_fromsockaddr(&netaddr, &sockaddrs[i]);
+ isc_netaddr_format(&netaddr, tmp, sizeof(tmp));
+ srv = make_server(tmp, host);
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+ }
+
+ return (count);
+}
+
+/*%
+ * Initiate either a TCP or UDP lookup
+ */
+void
+do_lookup(dig_lookup_t *lookup) {
+ dig_query_t *query;
+
+ REQUIRE(lookup != NULL);
+
+ debug("do_lookup()");
+ lookup->pending = true;
+ query = ISC_LIST_HEAD(lookup->q);
+ if (query != NULL) {
+ if (lookup->tcp_mode)
+ send_tcp_connect(query);
+ else
+ send_udp(query);
+ }
+}
+
+/*%
+ * Start everything in action upon task startup.
+ */
+void
+onrun_callback(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+
+ isc_event_free(&event);
+ LOCK_LOOKUP;
+ start_lookup();
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Make everything on the lookup queue go away. Mainly used by the
+ * SIGINT handler.
+ */
+void
+cancel_all(void) {
+ dig_lookup_t *l, *n;
+ dig_query_t *q, *nq;
+
+ debug("cancel_all()");
+
+ LOCK_LOOKUP;
+ if (free_now) {
+ UNLOCK_LOOKUP;
+ return;
+ }
+ cancel_now = true;
+ if (current_lookup != NULL) {
+ for (q = ISC_LIST_HEAD(current_lookup->q);
+ q != NULL;
+ q = nq)
+ {
+ nq = ISC_LIST_NEXT(q, link);
+ debug("canceling pending query %p, belonging to %p",
+ q, current_lookup);
+ if (q->sock != NULL)
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ else
+ clear_query(q);
+ }
+ for (q = ISC_LIST_HEAD(current_lookup->connecting);
+ q != NULL;
+ q = nq)
+ {
+ nq = ISC_LIST_NEXT(q, clink);
+ debug("canceling connecting query %p, belonging to %p",
+ q, current_lookup);
+ if (q->sock != NULL)
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ else
+ clear_query(q);
+ }
+ }
+ l = ISC_LIST_HEAD(lookup_list);
+ while (l != NULL) {
+ n = ISC_LIST_NEXT(l, link);
+ ISC_LIST_DEQUEUE(lookup_list, l, link);
+ try_clear_lookup(l);
+ l = n;
+ }
+ UNLOCK_LOOKUP;
+}
+
+/*%
+ * Destroy all of the libs we are using, and get everything ready for a
+ * clean shutdown.
+ */
+void
+destroy_libs(void) {
+#ifdef DIG_SIGCHASE
+ void * ptr;
+ dig_message_t *chase_msg;
+#endif
+#ifdef WITH_IDN_SUPPORT
+ isc_result_t result;
+#endif
+
+ if (keep != NULL)
+ isc_socket_detach(&keep);
+ debug("destroy_libs()");
+ if (global_task != NULL) {
+ debug("freeing task");
+ isc_task_detach(&global_task);
+ }
+ /*
+ * The taskmgr_destroy() call blocks until all events are cleared
+ * from the task.
+ */
+ if (taskmgr != NULL) {
+ debug("freeing taskmgr");
+ isc_taskmgr_destroy(&taskmgr);
+ }
+ LOCK_LOOKUP;
+ REQUIRE(sockcount == 0);
+ REQUIRE(recvcount == 0);
+ REQUIRE(sendcount == 0);
+
+ INSIST(ISC_LIST_HEAD(lookup_list) == NULL);
+ INSIST(current_lookup == NULL);
+ INSIST(!free_now);
+
+ free_now = true;
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ flush_server_list();
+
+ clear_searchlist();
+
+#ifdef WITH_IDN_SUPPORT
+ result = dns_name_settotextfilter(NULL);
+ check_result(result, "dns_name_settotextfilter");
+#endif
+ dns_name_destroy();
+
+ if (commctx != NULL) {
+ debug("freeing commctx");
+ isc_mempool_destroy(&commctx);
+ }
+ if (socketmgr != NULL) {
+ debug("freeing socketmgr");
+ isc_socketmgr_destroy(&socketmgr);
+ }
+ if (timermgr != NULL) {
+ debug("freeing timermgr");
+ isc_timermgr_destroy(&timermgr);
+ }
+ if (tsigkey != NULL) {
+ debug("freeing key %p", tsigkey);
+ dns_tsigkey_detach(&tsigkey);
+ }
+ if (namebuf != NULL)
+ isc_buffer_free(&namebuf);
+
+ if (is_dst_up) {
+ debug("destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = false;
+ }
+ if (entp != NULL) {
+ debug("detach from entropy");
+ isc_entropy_detach(&entp);
+ }
+
+ UNLOCK_LOOKUP;
+ DESTROYLOCK(&lookup_lock);
+#ifdef DIG_SIGCHASE
+
+ debug("Destroy the messages kept for sigchase");
+ /* Destroy the messages kept for sigchase */
+ chase_msg = ISC_LIST_HEAD(chase_message_list);
+
+ while (chase_msg != NULL) {
+ INSIST(chase_msg->msg != NULL);
+ dns_message_destroy(&(chase_msg->msg));
+ ptr = chase_msg;
+ chase_msg = ISC_LIST_NEXT(chase_msg, link);
+ isc_mem_free(mctx, ptr);
+ }
+
+ chase_msg = ISC_LIST_HEAD(chase_message_list2);
+
+ while (chase_msg != NULL) {
+ INSIST(chase_msg->msg != NULL);
+ dns_message_destroy(&(chase_msg->msg));
+ ptr = chase_msg;
+ chase_msg = ISC_LIST_NEXT(chase_msg, link);
+ isc_mem_free(mctx, ptr);
+ }
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+#if DIG_SIGCHASE_TD
+ if (dns_name_dynamic(&chase_current_name))
+ free_name(&chase_current_name);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name);
+#endif
+#if DIG_SIGCHASE_BU
+ if (dns_name_dynamic(&chase_signame))
+ free_name(&chase_signame);
+#endif
+
+#endif
+ debug("Removing log context");
+ isc_log_destroy(&lctx);
+
+ debug("Destroy memory");
+ if (memdebugging != 0)
+ isc_mem_stats(mctx, stderr);
+ if (mctx != NULL)
+ isc_mem_destroy(&mctx);
+}
+
+#ifdef WITH_IDN_OUT_SUPPORT
+static isc_result_t
+output_filter(isc_buffer_t *buffer, unsigned int used_org,
+ bool absolute)
+{
+ char tmp1[MAXDLEN], tmp2[MAXDLEN];
+ size_t fromlen, tolen;
+ bool end_with_dot;
+ isc_result_t result;
+
+ /*
+ * Copy contents of 'buffer' to 'tmp1', supply trailing dot
+ * if 'absolute' is true, and terminate with NUL.
+ */
+ fromlen = isc_buffer_usedlength(buffer) - used_org;
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+
+ memmove(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
+ end_with_dot = (tmp1[fromlen - 1] == '.') ? true : false;
+ if (absolute && !end_with_dot) {
+ fromlen++;
+ if (fromlen >= MAXDLEN)
+ return (ISC_R_SUCCESS);
+ tmp1[fromlen - 1] = '.';
+ }
+
+ tmp1[fromlen] = '\0';
+
+ /*
+ * Convert contents of 'tmp1' to local encoding.
+ */
+ result = idn_ace_to_locale(tmp1, tmp2, sizeof(tmp2));
+ if (result != ISC_R_SUCCESS) {
+ return (ISC_R_SUCCESS);
+ }
+ /*
+ * Copy the converted contents in 'tmp1' back to 'buffer'.
+ * If we have appended trailing dot, remove it.
+ */
+ tolen = strlen(tmp2);
+ if (absolute && !end_with_dot && tmp2[tolen - 1] == '.')
+ tolen--;
+
+ if (isc_buffer_length(buffer) < used_org + tolen)
+ return (ISC_R_NOSPACE);
+
+ isc_buffer_subtract(buffer, isc_buffer_usedlength(buffer) - used_org);
+ memmove(isc_buffer_used(buffer), tmp2, tolen);
+ isc_buffer_add(buffer, (unsigned int)tolen);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+#ifdef WITH_IDN_SUPPORT
+#ifdef WITH_IDNKIT
+static void
+idnkit_check_result(idn_result_t result, const char *msg) {
+ if (result != idn_success) {
+ fatal("%s: %s", msg, idn_result_tostring(result));
+ }
+}
+
+static void
+idn_initialize(void) {
+ idn_result_t result;
+
+ /* Create configuration context. */
+ result = idn_nameinit(1);
+ idnkit_check_result(result, "idnkit api initialization failed");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+idn_locale_to_ace(const char *from, char *to, size_t tolen) {
+ char utf8_textname[MXNAME];
+ idn_result_t result;
+
+ result = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, from,
+ utf8_textname, sizeof(utf8_textname));
+ idnkit_check_result(result, "idnkit idn_encodename to utf8 failed");
+
+ result = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
+ IDN_IDNCONV | IDN_LENCHECK,
+ utf8_textname, to, tolen);
+ idnkit_check_result(result, "idnkit idn_encodename to idn failed");
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+idn_ace_to_locale(const char *from, char *to, size_t tolen) {
+ idn_result_t result;
+
+ result = idn_decodename(IDN_DECODE_APP, from, to, tolen);
+ if (result != idn_success) {
+ debug("idnkit idn_decodename failed: %s",
+ idn_result_tostring(result));
+ return (ISC_R_FAILURE);
+ }
+ return (ISC_R_SUCCESS);
+}
+#endif /* WITH_IDNKIT */
+
+#ifdef WITH_LIBIDN2
+static void
+idn_initialize(void) {
+}
+
+static isc_result_t
+idn_locale_to_ace(const char *from, char *to, size_t tolen) {
+ int res;
+ char *tmp_str = NULL;
+
+ res = idn2_to_ascii_lz(from, &tmp_str, IDN2_NONTRANSITIONAL|IDN2_NFC_INPUT);
+ if (res == IDN2_DISALLOWED) {
+ res = idn2_to_ascii_lz(from, &tmp_str, IDN2_TRANSITIONAL|IDN2_NFC_INPUT);
+ }
+
+ if (res == IDN2_OK) {
+ /*
+ * idn2_to_ascii_lz() normalizes all strings to lowerl case,
+ * but we generally don't want to lowercase all input strings;
+ * make sure to return the original case if the two strings
+ * differ only in case
+ */
+ if (!strcasecmp(from, tmp_str)) {
+ if (strlen(from) >= tolen) {
+ debug("from string is too long");
+ idn2_free(tmp_str);
+ return ISC_R_NOSPACE;
+ }
+ idn2_free(tmp_str);
+ (void) strlcpy(to, from, tolen);
+ return ISC_R_SUCCESS;
+ }
+ /* check the length */
+ if (strlen(tmp_str) >= tolen) {
+ debug("ACE string is too long");
+ idn2_free(tmp_str);
+ return ISC_R_NOSPACE;
+ }
+
+ (void) strlcpy(to, tmp_str, tolen);
+ idn2_free(tmp_str);
+ return ISC_R_SUCCESS;
+ }
+
+ fatal("'%s' is not a legal IDN name (%s), use +noidnin", from, idn2_strerror(res));
+ return ISC_R_FAILURE;
+}
+
+#ifdef WITH_IDN_OUT_SUPPORT
+static isc_result_t
+idn_ace_to_locale(const char *from, char *to, size_t tolen) {
+ int res;
+ char *utf8_src, *tmp_str = NULL;
+
+ /*
+ * We need to:
+ *
+ * 1) check whether 'from' is a valid IDNA2008 name,
+ * 2) if it is, output it in the current locale's character encoding.
+ *
+ * Unlike idn2_to_ascii_*(), idn2_to_unicode_*() functions are unable
+ * to perform IDNA2008 validity checks. Thus, we need to decode any
+ * Punycode in 'from', check if the resulting name is a valid IDNA2008
+ * name, and only once we ensure it is, output that name in the current
+ * locale's character encoding.
+ *
+ * We could just use idn2_to_unicode_8zlz() + idn2_to_ascii_lz(), but
+ * then we would not be able to universally tell invalid names and
+ * character encoding errors apart (if the current locale uses ASCII
+ * for character encoding, the former function would fail even for a
+ * valid IDNA2008 name, as long as it contained any non-ASCII
+ * character). Thus, we need to take a longer route.
+ *
+ * First, convert 'from' to UTF-8, ignoring the current locale.
+ */
+ res = idn2_to_unicode_8z8z(from, &utf8_src, 0);
+ if (res != IDN2_OK) {
+ fatal("Bad ACE string '%s' (%s), use +noidnout",
+ from, idn2_strerror(res));
+ }
+
+ /*
+ * Then, check whether decoded 'from' is a valid IDNA2008 name.
+ */
+ res = idn2_to_ascii_8z(utf8_src, NULL, IDN2_NONTRANSITIONAL);
+ if (res != IDN2_OK) {
+ fatal("'%s' is not a legal IDNA2008 name (%s), use +noidnout",
+ from, idn2_strerror(res));
+ }
+
+ /*
+ * Finally, try converting the decoded 'from' into the current locale's
+ * character encoding.
+ */
+ res = idn2_to_unicode_8zlz(utf8_src, &tmp_str, 0);
+ if (res != IDN2_OK) {
+ fatal("Cannot represent '%s' in the current locale (%s), "
+ "use +noidnout or a different locale",
+ from, idn2_strerror(res));
+ }
+
+ /*
+ * Free the interim conversion result.
+ */
+ idn2_free(utf8_src);
+
+ /* check the length */
+ if (strlen(tmp_str) >= tolen) {
+ debug("encoded ASC string is too long");
+ idn2_free(tmp_str);
+ return (ISC_R_FAILURE);
+ }
+
+ (void) strlcpy(to, tmp_str, tolen);
+ idn2_free(tmp_str);
+ return (ISC_R_SUCCESS);
+}
+#endif /* WITH_IDN_OUT_SUPPORT */
+#endif /* WITH_LIBIDN2 */
+#endif /* WITH_IDN_SUPPORT */
+
+#ifdef DIG_SIGCHASE
+void
+print_type(dns_rdatatype_t type)
+{
+ isc_buffer_t * b = NULL;
+ isc_result_t result;
+ isc_region_t r;
+
+ result = isc_buffer_allocate(mctx, &b, 4000);
+ check_result(result, "isc_buffer_allocate");
+
+ result = dns_rdatatype_totext(type, b);
+ check_result(result, "print_type");
+
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+
+ printf("%s", r.base);
+
+ isc_buffer_free(&b);
+}
+
+void
+dump_database_section(dns_message_t *msg, int section)
+{
+ dns_name_t *msg_name=NULL;
+
+ dns_rdataset_t *rdataset;
+
+ do {
+ dns_message_currentname(msg, section, &msg_name);
+
+ for (rdataset = ISC_LIST_HEAD(msg_name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ dns_name_print(msg_name, stdout);
+ printf("\n");
+ print_rdataset(msg_name, rdataset);
+ printf("end\n");
+ }
+ msg_name = NULL;
+ } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+}
+
+void
+dump_database(void) {
+ dig_message_t * msg;
+
+ for (msg = ISC_LIST_HEAD(chase_message_list); msg != NULL;
+ msg = ISC_LIST_NEXT(msg, link)) {
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_ANSWER);
+
+ if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_AUTHORITY);
+
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+ == ISC_R_SUCCESS)
+ dump_database_section(msg->msg, DNS_SECTION_ADDITIONAL);
+ }
+}
+
+
+dns_rdataset_t *
+search_type(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers) {
+ dns_rdataset_t *rdataset;
+ dns_rdata_sig_t siginfo;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ isc_result_t result;
+
+ for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (type == dns_rdatatype_any) {
+ if (rdataset->type != dns_rdatatype_rrsig)
+ return (rdataset);
+ } else if ((type == dns_rdatatype_rrsig) &&
+ (rdataset->type == dns_rdatatype_rrsig)) {
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "empty rdataset");
+ dns_rdataset_current(rdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ if ((siginfo.covered == covers) ||
+ (covers == dns_rdatatype_any)) {
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&siginfo);
+ return (rdataset);
+ }
+ dns_rdata_reset(&sigrdata);
+ dns_rdata_freestruct(&siginfo);
+ } else if (rdataset->type == type)
+ return (rdataset);
+ }
+ return (NULL);
+}
+
+dns_rdataset_t *
+chase_scanname_section(dns_message_t *msg, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ int section)
+{
+ dns_rdataset_t *rdataset;
+ dns_name_t *msg_name = NULL;
+
+ if (msg->counts[section] == 0)
+ return (NULL);
+
+ do {
+ dns_message_currentname(msg, section, &msg_name);
+ if (dns_name_compare(msg_name, name) == 0) {
+ rdataset = search_type(msg_name, type, covers);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ msg_name = NULL;
+ } while (dns_message_nextname(msg, section) == ISC_R_SUCCESS);
+
+ return (NULL);
+}
+
+
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dig_message_t * msg;
+
+ for (msg = ISC_LIST_HEAD(chase_message_list2); msg != NULL;
+ msg = ISC_LIST_NEXT(msg, link)) {
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ANSWER)
+ == ISC_R_SUCCESS)
+ {
+ rdataset = chase_scanname_section(msg->msg, name,
+ type, covers,
+ DNS_SECTION_ANSWER);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ if (dns_message_firstname(msg->msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS)
+ {
+ rdataset =
+ chase_scanname_section(msg->msg, name,
+ type, covers,
+ DNS_SECTION_AUTHORITY);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ if (dns_message_firstname(msg->msg, DNS_SECTION_ADDITIONAL)
+ == ISC_R_SUCCESS)
+ {
+ rdataset =
+ chase_scanname_section(msg->msg, name, type,
+ covers,
+ DNS_SECTION_ADDITIONAL);
+ if (rdataset != NULL)
+ return (rdataset);
+ }
+ }
+
+ return (NULL);
+}
+
+dns_rdataset_t *
+sigchase_scanname(dns_rdatatype_t type, dns_rdatatype_t covers,
+ bool * lookedup, dns_name_t *rdata_name)
+{
+ dig_lookup_t *lookup;
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ isc_result_t result;
+ dns_rdataset_t * temp;
+ dns_rdatatype_t querytype;
+
+ temp = chase_scanname(rdata_name, type, covers);
+ if (temp != NULL)
+ return (temp);
+
+ if (*lookedup == true)
+ return (NULL);
+
+ lookup = clone_lookup(current_lookup, true);
+ lookup->trace_root = false;
+ lookup->new_search = true;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(rdata_name, false, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(lookup->textname, (char*)r.base, sizeof(lookup->textname));
+ isc_buffer_free(&b);
+
+ if (type == dns_rdatatype_rrsig)
+ querytype = covers;
+ else
+ querytype = type;
+
+ if (querytype == 0 || querytype == 255) {
+ printf("Error in the queried type: %d\n", querytype);
+ return (NULL);
+ }
+
+ lookup->rdtype = querytype;
+ lookup->rdtypeset = true;
+ lookup->qrdtype = querytype;
+ *lookedup = true;
+
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ printf("\n\nLaunch a query to find a RRset of type ");
+ print_type(type);
+ printf(" for zone: %s\n", lookup->textname);
+ return (NULL);
+}
+
+isc_result_t
+insert_trustedkey(void *arg, dns_name_t *name, dns_rdataset_t *rdataset)
+{
+ isc_result_t result;
+ dst_key_t *dstkey;
+
+ UNUSED(arg);
+
+ if (rdataset == NULL || rdataset->type != dns_rdatatype_dnskey)
+ return (ISC_R_SUCCESS);
+
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t b;
+
+ dns_rdataset_current(rdataset, &rdata);
+ isc_buffer_init(&b, rdata.data, rdata.length);
+ isc_buffer_add(&b, rdata.length);
+ if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
+ return (ISC_R_SUCCESS);
+ dstkey = NULL;
+ result = dst_key_fromdns(name, rdata.rdclass, &b, mctx, &dstkey);
+ if (result != ISC_R_SUCCESS)
+ continue;
+ tk_list.key[tk_list.nb_tk++] = dstkey;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+void
+clean_trustedkey()
+{
+ int i = 0;
+
+ for (i= 0; i < MAX_TRUSTED_KEY; i++) {
+ if (tk_list.key[i] != NULL) {
+ dst_key_free(&tk_list.key[i]);
+ tk_list.key[i] = NULL;
+ } else
+ break;
+ }
+ tk_list.nb_tk = 0;
+ return;
+}
+
+char alphnum[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+isc_result_t
+removetmpkey(const char *file)
+{
+ char *tempnamekey = NULL;
+ int tempnamekeylen;
+ isc_result_t result;
+
+ tempnamekeylen = strlen(file)+10;
+
+ tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
+ if (tempnamekey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(tempnamekey, 0, tempnamekeylen);
+
+ strcat(tempnamekey, file);
+ strcat(tempnamekey,".key");
+ isc_file_remove(tempnamekey);
+
+ result = isc_file_remove(tempnamekey);
+ isc_mem_free(mctx, tempnamekey);
+ return (result);
+}
+
+isc_result_t
+get_trusted_key(void) {
+ isc_result_t result;
+ const char *filename = NULL;
+ dns_rdatacallbacks_t callbacks;
+
+ result = isc_file_exists(trustedkey);
+ if (result != true) {
+ result = isc_file_exists("/etc/trusted-key.key");
+ if (result != true) {
+ result = isc_file_exists("./trusted-key.key");
+ if (result != true)
+ return (ISC_R_FAILURE);
+ else
+ filename = "./trusted-key.key";
+ } else
+ filename = "/etc/trusted-key.key";
+ } else
+ filename = trustedkey;
+
+ if (filename == NULL) {
+ printf("No trusted key\n");
+ return (ISC_R_FAILURE);
+ }
+
+ dns_rdatacallbacks_init_stdio(&callbacks);
+ callbacks.add = insert_trustedkey;
+ return (dns_master_loadfile(filename, dns_rootname, dns_rootname,
+ current_lookup->rdclass, DNS_MASTER_NOTTL,
+ &callbacks, mctx));
+}
+
+
+static void
+nameFromString(const char *str, dns_name_t *p_ret) {
+ size_t len = strlen(str);
+ isc_result_t result;
+ isc_buffer_t buffer;
+ dns_fixedname_t fixedname;
+
+ REQUIRE(p_ret != NULL);
+ REQUIRE(str != NULL);
+
+ isc_buffer_constinit(&buffer, str, len);
+ isc_buffer_add(&buffer, len);
+
+ dns_fixedname_init(&fixedname);
+ result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
+ dns_rootname, DNS_NAME_DOWNCASE, NULL);
+ check_result(result, "nameFromString");
+
+ if (dns_name_dynamic(p_ret))
+ free_name(p_ret);
+
+ result = dns_name_dup(dns_fixedname_name(&fixedname), mctx, p_ret);
+ check_result(result, "nameFromString");
+}
+
+
+#if DIG_SIGCHASE_TD
+isc_result_t
+prepare_lookup(dns_name_t *name)
+{
+ isc_result_t result;
+ dig_lookup_t *lookup = NULL;
+ dig_server_t *s;
+ void *ptr;
+
+ lookup = clone_lookup(current_lookup, true);
+ lookup->trace_root = false;
+ lookup->new_search = true;
+ lookup->trace_root_sigchase = false;
+
+ strlcpy(lookup->textname, lookup->textnamesigchase, MXNAME);
+
+ lookup->rdtype = lookup->rdtype_sigchase;
+ lookup->rdtypeset = true;
+ lookup->qrdtype = lookup->qrdtype_sigchase;
+
+ s = ISC_LIST_HEAD(lookup->my_server_list);
+ while (s != NULL) {
+ debug("freeing server %p belonging to %p",
+ s, lookup);
+ ptr = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(lookup->my_server_list,
+ (dig_server_t *)ptr, link);
+ isc_mem_free(mctx, ptr);
+ }
+
+
+ for (result = dns_rdataset_first(chase_nsrdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(chase_nsrdataset)) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_rdata_ns_t ns;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dig_server_t * srv = NULL;
+#define __FOLLOW_GLUE__
+#ifdef __FOLLOW_GLUE__
+ isc_buffer_t *b = NULL;
+ isc_region_t r;
+ dns_rdataset_t *rdataset = NULL;
+ bool t = true;
+#endif
+
+ memset(namestr, 0, DNS_NAME_FORMATSIZE);
+
+ dns_rdataset_current(chase_nsrdataset, &rdata);
+
+ result = dns_rdata_tostruct(&rdata, &ns, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+#ifdef __FOLLOW_GLUE__
+
+ result = advanced_rrsearch(&rdataset, &ns.name,
+ dns_rdatatype_aaaa,
+ dns_rdatatype_any, &t);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t aaaa = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &aaaa);
+
+ result = isc_buffer_allocate(mctx, &b, 80);
+ check_result(result, "isc_buffer_allocate");
+
+ dns_rdata_totext(&aaaa, &ns.name, b);
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(namestr, (char*)r.base,
+ DNS_NAME_FORMATSIZE);
+ isc_buffer_free(&b);
+ dns_rdata_reset(&aaaa);
+
+
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list,
+ srv, link);
+ }
+ }
+
+ rdataset = NULL;
+ result = advanced_rrsearch(&rdataset, &ns.name, dns_rdatatype_a,
+ dns_rdatatype_any, &t);
+ if (result == ISC_R_SUCCESS) {
+ for (result = dns_rdataset_first(rdataset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(rdataset)) {
+ dns_rdata_t a = DNS_RDATA_INIT;
+ dns_rdataset_current(rdataset, &a);
+
+ result = isc_buffer_allocate(mctx, &b, 80);
+ check_result(result, "isc_buffer_allocate");
+
+ dns_rdata_totext(&a, &ns.name, b);
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strlcpy(namestr, (char*)r.base,
+ DNS_NAME_FORMATSIZE);
+ isc_buffer_free(&b);
+ dns_rdata_reset(&a);
+ printf("ns name: %s\n", namestr);
+
+
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list,
+ srv, link);
+ }
+ }
+#else
+
+ dns_name_format(&ns.name, namestr, sizeof(namestr));
+ printf("ns name: ");
+ dns_name_print(&ns.name, stdout);
+ printf("\n");
+ srv = make_server(namestr, namestr);
+
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+
+#endif
+ dns_rdata_freestruct(&ns);
+ dns_rdata_reset(&rdata);
+
+ }
+
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ printf("\nLaunch a query to find a RRset of type ");
+ print_type(lookup->rdtype);
+ printf(" for zone: %s", lookup->textname);
+ printf(" with nameservers:");
+ printf("\n");
+ print_rdataset(name, chase_nsrdataset);
+ return (ISC_R_SUCCESS);
+}
+
+
+isc_result_t
+child_of_zone(dns_name_t * name, dns_name_t * zone_name,
+ dns_name_t * child_name)
+{
+ dns_namereln_t name_reln;
+ int orderp;
+ unsigned int nlabelsp;
+
+ name_reln = dns_name_fullcompare(name, zone_name, &orderp, &nlabelsp);
+ if (name_reln != dns_namereln_subdomain ||
+ dns_name_countlabels(name) <= dns_name_countlabels(zone_name) + 1) {
+ printf("\n;; ERROR : ");
+ dns_name_print(name, stdout);
+ printf(" is not a subdomain of: ");
+ dns_name_print(zone_name, stdout);
+ printf(" FAILED\n\n");
+ return (ISC_R_FAILURE);
+ }
+
+ dns_name_getlabelsequence(name,
+ dns_name_countlabels(name) -
+ dns_name_countlabels(zone_name) -1,
+ dns_name_countlabels(zone_name) +1,
+ child_name);
+ return (ISC_R_SUCCESS);
+}
+
+isc_result_t
+grandfather_pb_test(dns_name_t *zone_name, dns_rdataset_t *sigrdataset) {
+ dns_rdata_sig_t siginfo;
+ dns_rdataset_t mysigrdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&mysigrdataset);
+ dns_rdataset_clone(sigrdataset, &mysigrdataset);
+
+ result = dns_rdataset_first(&mysigrdataset);
+ check_result(result, "empty RRSIG dataset");
+
+ do {
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mysigrdataset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
+ result = ISC_R_SUCCESS;
+ goto cleanup;
+ }
+ } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_FAILURE;
+cleanup:
+ dns_rdataset_disassociate(&mysigrdataset);
+
+ return (result);
+}
+
+
+isc_result_t
+initialization(dns_name_t *name)
+{
+ isc_result_t result;
+ bool t = true;
+
+ chase_nsrdataset = NULL;
+ result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
+ dns_rdatatype_any, &t);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; NS RRset is missing to continue validation:"
+ " FAILED\n\n");
+ return (ISC_R_FAILURE);
+ }
+ INSIST(chase_nsrdataset != NULL);
+ prepare_lookup(name);
+
+ dup_name(name, &chase_current_name);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset)
+{
+ isc_buffer_t *b = NULL;
+ isc_result_t result;
+ isc_region_t r;
+
+ result = isc_buffer_allocate(mctx, &b, 9000);
+ check_result(result, "isc_buffer_allocate");
+
+ dighost_printrdataset(name, rdataset, b);
+
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+
+
+ printf("%s\n", r.base);
+
+ isc_buffer_free(&b);
+}
+
+
+void
+dup_name(dns_name_t *source, dns_name_t *target) {
+ isc_result_t result;
+
+ if (dns_name_dynamic(target))
+ free_name(target);
+ result = dns_name_dup(source, mctx, target);
+ check_result(result, "dns_name_dup");
+}
+
+void
+free_name(dns_name_t *name) {
+ dns_name_free(name, mctx);
+ dns_name_init(name, NULL);
+}
+
+/*
+ *
+ * take a DNSKEY RRset and the RRSIG RRset corresponding in parameter
+ * return ISC_R_SUCCESS if the DNSKEY RRset contains a trusted_key
+ * and the RRset is valid
+ * return ISC_R_NOTFOUND if not contains trusted key
+ or if the RRset isn't valid
+ * return ISC_R_FAILURE if problem
+ *
+ */
+isc_result_t
+contains_trusted_key(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rdataset_t myrdataset;
+ dst_key_t *dnsseckey = NULL;
+ int i;
+ isc_result_t result;
+
+ if (name == NULL || rdataset == NULL)
+ return (ISC_R_FAILURE);
+
+ dns_rdataset_init(&myrdataset);
+ dns_rdataset_clone(rdataset, &myrdataset);
+
+ result = dns_rdataset_first(&myrdataset);
+ check_result(result, "empty rdataset");
+
+ do {
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&myrdataset, &rdata);
+ INSIST(rdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &rdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ for (i = 0; i < tk_list.nb_tk; i++) {
+ if (dst_key_compare(tk_list.key[i], dnsseckey)
+ == true) {
+ dns_rdata_reset(&rdata);
+
+ printf(";; Ok, find a Trusted Key in the "
+ "DNSKEY RRset: %d\n",
+ dst_key_id(dnsseckey));
+ result = sigchase_verify_sig_key(name, rdataset,
+ dnsseckey,
+ sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ }
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(&myrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+cleanup:
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ dns_rdataset_disassociate(&myrdataset);
+
+ return (result);
+}
+
+isc_result_t
+sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset)
+{
+ dns_rdataset_t mykeyrdataset;
+ dst_key_t *dnsseckey = NULL;
+ isc_result_t result;
+
+ dns_rdataset_init(&mykeyrdataset);
+ dns_rdataset_clone(keyrdataset, &mykeyrdataset);
+
+ result = dns_rdataset_first(&mykeyrdataset);
+ check_result(result, "empty DNSKEY dataset");
+
+ do {
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mykeyrdataset, &keyrdata);
+ INSIST(keyrdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &keyrdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ result = sigchase_verify_sig_key(name, rdataset, dnsseckey,
+ sigrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+ cleanup:
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ dns_rdataset_disassociate(&mykeyrdataset);
+
+ return (result);
+}
+
+isc_result_t
+sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
+ dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset)
+{
+ dns_rdata_sig_t siginfo;
+ dns_rdataset_t myrdataset;
+ dns_rdataset_t mysigrdataset;
+ isc_result_t result;
+
+ dns_rdataset_init(&myrdataset);
+ dns_rdataset_clone(rdataset, &myrdataset);
+ dns_rdataset_init(&mysigrdataset);
+ dns_rdataset_clone(sigrdataset, &mysigrdataset);
+
+ result = dns_rdataset_first(&mysigrdataset);
+ check_result(result, "empty RRSIG dataset");
+
+ do {
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mysigrdataset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ /*
+ * Test if the id of the DNSKEY is
+ * the id of the DNSKEY signer's
+ */
+ if (siginfo.keyid == dst_key_id(dnsseckey)) {
+
+ result = dns_rdataset_first(&myrdataset);
+ check_result(result, "empty DS dataset");
+
+ result = dns_dnssec_verify(name, &myrdataset, dnsseckey,
+ false, mctx, &sigrdata);
+
+ printf(";; VERIFYING ");
+ print_type(rdataset->type);
+ printf(" RRset for ");
+ dns_name_print(name, stdout);
+ printf(" with DNSKEY:%d: %s\n", dst_key_id(dnsseckey),
+ isc_result_totext(result));
+
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ }
+ } while (dns_rdataset_next(&mysigrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+ cleanup:
+ dns_rdataset_disassociate(&myrdataset);
+ dns_rdataset_disassociate(&mysigrdataset);
+
+ return (result);
+}
+
+
+isc_result_t
+sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset)
+{
+ dns_rdata_ds_t dsinfo;
+ dns_rdataset_t mydsrdataset;
+ dns_rdataset_t mykeyrdataset;
+ dst_key_t *dnsseckey = NULL;
+ isc_result_t result;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+ dns_rdataset_init(&mydsrdataset);
+ dns_rdataset_clone(dsrdataset, &mydsrdataset);
+ dns_rdataset_init(&mykeyrdataset);
+ dns_rdataset_clone(keyrdataset, &mykeyrdataset);
+
+ result = dns_rdataset_first(&mydsrdataset);
+ check_result(result, "empty DSset dataset");
+ do {
+ dns_rdata_t dsrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mydsrdataset, &dsrdata);
+
+ result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
+ check_result(result, "dns_rdata_tostruct for DS");
+
+ result = dns_rdataset_first(&mykeyrdataset);
+ check_result(result, "empty KEY dataset");
+
+ do {
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+
+ dns_rdataset_current(&mykeyrdataset, &keyrdata);
+ INSIST(keyrdata.type == dns_rdatatype_dnskey);
+
+ result = dns_dnssec_keyfromrdata(name, &keyrdata,
+ mctx, &dnsseckey);
+ check_result(result, "dns_dnssec_keyfromrdata");
+
+ /*
+ * Test if the id of the DNSKEY is the
+ * id of DNSKEY referenced by the DS
+ */
+ if (dsinfo.key_tag == dst_key_id(dnsseckey)) {
+ dns_rdata_t newdsrdata = DNS_RDATA_INIT;
+
+ result = dns_ds_buildrdata(name, &keyrdata,
+ dsinfo.digest_type,
+ dsbuf, &newdsrdata);
+ dns_rdata_freestruct(&dsinfo);
+
+ if (result != ISC_R_SUCCESS) {
+ printf("Oops: impossible to build"
+ " new DS rdata\n");
+ goto cleanup;
+ }
+
+
+ if (dns_rdata_compare(&dsrdata,
+ &newdsrdata) == 0) {
+ printf(";; OK a DS valids a DNSKEY"
+ " in the RRset\n");
+ printf(";; Now verify that this"
+ " DNSKEY validates the "
+ "DNSKEY RRset\n");
+
+ result = sigchase_verify_sig_key(name,
+ keyrdataset,
+ dnsseckey,
+ chase_sigkeyrdataset);
+ if (result == ISC_R_SUCCESS)
+ goto cleanup;
+ } else {
+ printf(";; This DS is NOT the DS for"
+ " the chasing KEY: FAILED\n");
+ }
+ }
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(&mykeyrdataset) == ISC_R_SUCCESS);
+ } while (dns_rdataset_next(&mydsrdataset) == ISC_R_SUCCESS);
+
+ result = ISC_R_NOTFOUND;
+
+ cleanup:
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ dns_rdataset_disassociate(&mydsrdataset);
+ dns_rdataset_disassociate(&mykeyrdataset);
+
+ return (result);
+}
+
+/*
+ *
+ * take a pointer on a rdataset in parameter and try to resolv it.
+ * the searched rrset is a rrset on 'name' with type 'type'
+ * (and if the type is a rrsig the signature cover 'covers').
+ * the lookedup is to known if you have already done the query on the net.
+ * ISC_R_SUCCESS: if we found the rrset
+ * ISC_R_NOTFOUND: we do not found the rrset in cache
+ * and we do a query on the net
+ * ISC_R_FAILURE: rrset not found
+ */
+isc_result_t
+advanced_rrsearch(dns_rdataset_t **rdataset, dns_name_t *name,
+ dns_rdatatype_t type, dns_rdatatype_t covers,
+ bool *lookedup)
+{
+ bool tmplookedup;
+
+ INSIST(rdataset != NULL);
+
+ if (*rdataset != NULL)
+ return (ISC_R_SUCCESS);
+
+ tmplookedup = *lookedup;
+ if ((*rdataset = sigchase_scanname(type, covers,
+ lookedup, name)) == NULL) {
+ if (tmplookedup)
+ return (ISC_R_FAILURE);
+ return (ISC_R_NOTFOUND);
+ }
+ *lookedup = false;
+ return (ISC_R_SUCCESS);
+}
+
+
+
+#if DIG_SIGCHASE_TD
+void
+sigchase_td(dns_message_t *msg)
+{
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ bool have_answer = false;
+ bool t = true;
+
+ if (msg->rcode != dns_rcode_noerror &&
+ msg->rcode != dns_rcode_nxdomain) {
+ char buf[20];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, buf, sizeof(buf));
+ result = dns_rcode_totext(msg->rcode, &b);
+ check_result(result, "dns_rcode_totext failed");
+ printf("error response code %.*s\n",
+ (int)isc_buffer_usedlength(&b), buf);
+ error_message = msg;
+ return;
+ }
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+ == ISC_R_SUCCESS) {
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ if (current_lookup->trace_root_sigchase) {
+ initialization(name);
+ return;
+ }
+ have_answer = true;
+ } else {
+ if (!current_lookup->trace_root_sigchase) {
+ result = dns_message_firstname(msg,
+ DNS_SECTION_AUTHORITY);
+ if (result != ISC_R_SUCCESS) {
+ printf("no answer or authority section\n");
+ error_message = msg;
+ return;
+ }
+ dns_message_currentname(msg, DNS_SECTION_AUTHORITY,
+ &name);
+ chase_nsrdataset
+ = chase_scanname_section(msg, name,
+ dns_rdatatype_ns,
+ dns_rdatatype_any,
+ DNS_SECTION_AUTHORITY);
+ dup_name(name, &chase_authority_name);
+ if (chase_nsrdataset != NULL) {
+ have_delegation_ns = true;
+ printf("no response but there is a delegation"
+ " in authority section: ");
+ dns_name_print(name, stdout);
+ printf("\n");
+ } else {
+ printf("no response and no delegation in "
+ "authority section but a reference"
+ " to: ");
+ dns_name_print(name, stdout);
+ printf("\n");
+ error_message = msg;
+ }
+ } else {
+ printf(";; NO ANSWERS: %s\n",
+ isc_result_totext(result));
+ free_name(&chase_name);
+ clean_trustedkey();
+ return;
+ }
+ }
+
+
+ if (have_answer) {
+ chase_rdataset
+ = chase_scanname_section(msg, &chase_name,
+ current_lookup
+ ->rdtype_sigchase,
+ dns_rdatatype_any,
+ DNS_SECTION_ANSWER);
+ if (chase_rdataset != NULL)
+ have_response = true;
+ }
+
+ result = advanced_rrsearch(&chase_keyrdataset,
+ &chase_current_name,
+ dns_rdatatype_dnskey,
+ dns_rdatatype_any,
+ &chase_keylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_keyrdataset != NULL);
+ printf("\n;; DNSKEYset:\n");
+ print_rdataset(&chase_current_name , chase_keyrdataset);
+
+
+ result = advanced_rrsearch(&chase_sigkeyrdataset,
+ &chase_current_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey,
+ &chase_sigkeylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG of DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_sigkeyrdataset != NULL);
+ printf("\n;; RRSIG of the DNSKEYset:\n");
+ print_rdataset(&chase_current_name , chase_sigkeyrdataset);
+
+
+ if (!chase_dslookedup && !chase_nslookedup) {
+ if (!delegation_follow) {
+ result = contains_trusted_key(&chase_current_name,
+ chase_keyrdataset,
+ chase_sigkeyrdataset);
+ } else {
+ INSIST(chase_dsrdataset != NULL);
+ INSIST(chase_sigdsrdataset != NULL);
+ result = sigchase_verify_ds(&chase_current_name,
+ chase_keyrdataset,
+ chase_dsrdataset);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; chain of trust can't be validated:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ } else {
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ }
+ }
+
+ if (have_response || (!have_delegation_ns && !have_response)) {
+ /* test if it's a grand father case */
+
+ if (have_response) {
+ result = advanced_rrsearch(&chase_sigrdataset,
+ &chase_name,
+ dns_rdatatype_rrsig,
+ current_lookup
+ ->rdtype_sigchase,
+ &t);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRset is missing to continue"
+ " validation SHOULD NOT APPEND:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+
+ } else {
+ result = advanced_rrsearch(&chase_sigrdataset,
+ &chase_authority_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_any,
+ &t);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG is missing to continue"
+ " validation SHOULD NOT APPEND:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ }
+ result = grandfather_pb_test(&chase_current_name,
+ chase_sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ dns_name_t tmp_name;
+
+ printf("\n;; We are in a Grand Father Problem:"
+ " See 2.2.1 in RFC 3658\n");
+ chase_rdataset = NULL;
+ chase_sigrdataset = NULL;
+ have_response = false;
+ have_delegation_ns = false;
+
+ dns_name_init(&tmp_name, NULL);
+ result = child_of_zone(&chase_name, &chase_current_name,
+ &tmp_name);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name);
+ dup_name(&tmp_name, &chase_authority_name);
+ printf(";; and we try to continue chain of trust"
+ " validation of the zone: ");
+ dns_name_print(&chase_authority_name, stdout);
+ printf("\n");
+ have_delegation_ns = true;
+ } else {
+ if (have_response)
+ goto finalstep;
+ else
+ chase_sigrdataset = NULL;
+ }
+ }
+
+ if (have_delegation_ns) {
+ chase_nsrdataset = NULL;
+ result = advanced_rrsearch(&chase_nsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_ns,
+ dns_rdatatype_any,
+ &chase_nslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;;NSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND) {
+ return;
+ }
+ INSIST(chase_nsrdataset != NULL);
+
+ result = advanced_rrsearch(&chase_dsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_ds,
+ dns_rdatatype_any,
+ &chase_dslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ if (result == ISC_R_NOTFOUND)
+ return;
+ INSIST(chase_dsrdataset != NULL);
+ printf("\n;; DSset:\n");
+ print_rdataset(&chase_authority_name , chase_dsrdataset);
+
+ result = advanced_rrsearch(&chase_sigdsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds,
+ &t);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; DSset is missing to continue validation:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ printf("\n;; RRSIGset of DSset\n");
+ print_rdataset(&chase_authority_name, chase_sigdsrdataset);
+ INSIST(chase_sigdsrdataset != NULL);
+
+ result = sigchase_verify_sig(&chase_authority_name,
+ chase_dsrdataset,
+ chase_keyrdataset,
+ chase_sigdsrdataset);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the DSset:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+
+
+ prepare_lookup(&chase_authority_name);
+
+ have_response = false;
+ have_delegation_ns = false;
+ delegation_follow = true;
+ error_message = NULL;
+ dup_name(&chase_authority_name, &chase_current_name);
+ free_name(&chase_authority_name);
+ return;
+ }
+
+
+ if (error_message != NULL) {
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_name_t rdata_name;
+ isc_result_t ret = ISC_R_FAILURE;
+
+ dns_name_init(&rdata_name, NULL);
+ result = prove_nx(error_message, &chase_name,
+ current_lookup->rdclass_sigchase,
+ current_lookup->rdtype_sigchase, &rdata_name,
+ &rdataset, &sigrdataset);
+ if (rdataset == NULL || sigrdataset == NULL ||
+ dns_name_countlabels(&rdata_name) == 0) {
+ printf("\n;; Impossible to verify the non-existence,"
+ " the NSEC RRset can't be validated:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ }
+ ret = sigchase_verify_sig(&rdata_name, rdataset,
+ chase_keyrdataset,
+ sigrdataset);
+ if (ret != ISC_R_SUCCESS) {
+ free_name(&rdata_name);
+ printf("\n;; Impossible to verify the NSEC RR to prove"
+ " the non-existence : FAILED\n\n");
+ goto cleanandgo;
+ }
+ free_name(&rdata_name);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the non-existence:"
+ " FAILED\n\n");
+ goto cleanandgo;
+ } else {
+ printf("\n;; OK the query doesn't have response but"
+ " we have validate this fact : SUCCESS\n\n");
+ goto cleanandgo;
+ }
+ }
+
+ cleanandgo:
+ printf(";; cleanandgo \n");
+ if (dns_name_dynamic(&chase_current_name))
+ free_name(&chase_current_name);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name);
+ clean_trustedkey();
+ return;
+
+ finalstep :
+ result = advanced_rrsearch(&chase_rdataset, &chase_name,
+ current_lookup->rdtype_sigchase,
+ dns_rdatatype_any ,
+ &t);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRsig of RRset is missing to continue validation"
+ " SHOULD NOT APPEND: FAILED\n\n");
+ goto cleanandgo;
+ }
+ result = sigchase_verify_sig(&chase_name, chase_rdataset,
+ chase_keyrdataset,
+ chase_sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the RRset : FAILED\n\n");
+ /*
+ printf("RRset:\n");
+ print_rdataset(&chase_name , chase_rdataset);
+ printf("DNSKEYset:\n");
+ print_rdataset(&chase_name , chase_keyrdataset);
+ printf("RRSIG of RRset:\n");
+ print_rdataset(&chase_name , chase_sigrdataset);
+ printf("\n");
+ */
+ goto cleanandgo;
+ } else {
+ printf("\n;; The Answer:\n");
+ print_rdataset(&chase_name , chase_rdataset);
+
+ printf("\n;; FINISH : we have validate the DNSSEC chain"
+ " of trust: SUCCESS\n\n");
+ goto cleanandgo;
+ }
+}
+
+#endif
+
+
+#if DIG_SIGCHASE_BU
+
+isc_result_t
+getneededrr(dns_message_t *msg)
+{
+ isc_result_t result;
+ dns_name_t *name = NULL;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_sig_t siginfo;
+ bool t = true;
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_ANSWER))
+ != ISC_R_SUCCESS) {
+ printf(";; NO ANSWERS: %s\n", isc_result_totext(result));
+
+ if (chase_name.ndata == NULL)
+ return (ISC_R_ADDRNOTAVAIL);
+ } else {
+ dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
+ }
+
+ /* What do we chase? */
+ if (chase_rdataset == NULL) {
+ result = advanced_rrsearch(&chase_rdataset, name,
+ dns_rdatatype_any,
+ dns_rdatatype_any, &t);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No Answers: Validation FAILED\n\n");
+ return (ISC_R_NOTFOUND);
+ }
+ dup_name(name, &chase_name);
+ printf(";; RRset to chase:\n");
+ print_rdataset(&chase_name, chase_rdataset);
+ }
+ INSIST(chase_rdataset != NULL);
+
+
+ if (chase_sigrdataset == NULL) {
+ result = advanced_rrsearch(&chase_sigrdataset, name,
+ dns_rdatatype_rrsig,
+ chase_rdataset->type,
+ &chase_siglookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG is missing for continue validation:"
+ " FAILED\n\n");
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; RRSIG of the RRset to chase:\n");
+ print_rdataset(&chase_name, chase_sigrdataset);
+ }
+ INSIST(chase_sigrdataset != NULL);
+
+
+ /* first find the DNSKEY name */
+ result = dns_rdataset_first(chase_sigrdataset);
+ check_result(result, "empty RRSIG dataset");
+ dns_rdataset_current(chase_sigrdataset, &sigrdata);
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+ dup_name(&siginfo.signer, &chase_signame);
+ dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
+
+ /* Do we have a key? */
+ if (chase_keyrdataset == NULL) {
+ result = advanced_rrsearch(&chase_keyrdataset,
+ &chase_signame,
+ dns_rdatatype_dnskey,
+ dns_rdatatype_any,
+ &chase_keylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; DNSKEY is missing to continue validation:"
+ " FAILED\n\n");
+ free_name(&chase_signame);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; DNSKEYset that signs the RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_keyrdataset);
+ }
+ INSIST(chase_keyrdataset != NULL);
+
+ if (chase_sigkeyrdataset == NULL) {
+ result = advanced_rrsearch(&chase_sigkeyrdataset,
+ &chase_signame,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_dnskey,
+ &chase_sigkeylookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; RRSIG for DNSKEY is missing to continue"
+ " validation : FAILED\n\n");
+ free_name(&chase_signame);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; RRSIG of the DNSKEYset that signs the "
+ "RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_sigkeyrdataset);
+ }
+ INSIST(chase_sigkeyrdataset != NULL);
+
+
+ if (chase_dsrdataset == NULL) {
+ result = advanced_rrsearch(&chase_dsrdataset, &chase_signame,
+ dns_rdatatype_ds, dns_rdatatype_any,
+ &chase_dslookedup);
+ if (result == ISC_R_FAILURE) {
+ printf("\n;; WARNING There is no DS for the zone: ");
+ dns_name_print(&chase_signame, stdout);
+ printf("\n");
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame);
+ return (ISC_R_NOTFOUND);
+ }
+ if (chase_dsrdataset != NULL) {
+ printf("\n;; DSset of the DNSKEYset\n");
+ print_rdataset(&chase_signame, chase_dsrdataset);
+ }
+ }
+
+ if (chase_dsrdataset != NULL) {
+ /*
+ * if there is no RRSIG of DS,
+ * we don't want to search on the network
+ */
+ result = advanced_rrsearch(&chase_sigdsrdataset,
+ &chase_signame,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds, &t);
+ if (result == ISC_R_FAILURE) {
+ printf(";; WARNING : NO RRSIG DS : RRSIG DS"
+ " should come with DS\n");
+ /*
+ * We continue even the DS couldn't be validated,
+ * because the DNSKEY could be a Trusted Key.
+ */
+ chase_dsrdataset = NULL;
+ } else {
+ printf("\n;; RRSIG of the DSset of the DNSKEYset\n");
+ print_rdataset(&chase_signame, chase_sigdsrdataset);
+ }
+ }
+ return (1);
+}
+
+
+
+void
+sigchase_bu(dns_message_t *msg)
+{
+ isc_result_t result;
+ int ret;
+
+ if (tk_list.nb_tk == 0) {
+ result = get_trusted_key();
+ if (result != ISC_R_SUCCESS) {
+ printf("No trusted keys present\n");
+ return;
+ }
+ }
+
+
+ ret = getneededrr(msg);
+ if (ret == ISC_R_NOTFOUND)
+ return;
+
+ if (ret == ISC_R_ADDRNOTAVAIL) {
+ /* We have no response */
+ dns_rdataset_t *rdataset;
+ dns_rdataset_t *sigrdataset;
+ dns_name_t rdata_name;
+ dns_name_t query_name;
+
+
+ dns_name_init(&query_name, NULL);
+ dns_name_init(&rdata_name, NULL);
+ nameFromString(current_lookup->textname, &query_name);
+
+ result = prove_nx(msg, &query_name, current_lookup->rdclass,
+ current_lookup->rdtype, &rdata_name,
+ &rdataset, &sigrdataset);
+ free_name(&query_name);
+ if (rdataset == NULL || sigrdataset == NULL ||
+ dns_name_countlabels(&rdata_name) == 0) {
+ printf("\n;; Impossible to verify the Non-existence,"
+ " the NSEC RRset can't be validated: "
+ "FAILED\n\n");
+ clean_trustedkey();
+ return;
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ printf("\n No Answers and impossible to prove the"
+ " unsecurity : Validation FAILED\n\n");
+ clean_trustedkey();
+ return;
+ }
+ printf(";; An NSEC prove the non-existence of a answers,"
+ " Now we want validate this NSEC\n");
+
+ dup_name(&rdata_name, &chase_name);
+ free_name(&rdata_name);
+ chase_rdataset = rdataset;
+ chase_sigrdataset = sigrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = false;
+ chase_keylookedup = false;
+ chase_dslookedup = false;
+ chase_sigdslookedup = false;
+ sigchase(msg);
+ clean_trustedkey();
+ return;
+ }
+
+
+ printf("\n\n\n;; WE HAVE MATERIAL, WE NOW DO VALIDATION\n");
+
+ result = sigchase_verify_sig(&chase_name, chase_rdataset,
+ chase_keyrdataset,
+ chase_sigrdataset);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_name);
+ free_name(&chase_signame);
+ printf(";; No DNSKEY is valid to check the RRSIG"
+ " of the RRset: FAILED\n");
+ clean_trustedkey();
+ return;
+ }
+ printf(";; OK We found DNSKEY (or more) to validate the RRset\n");
+
+ result = contains_trusted_key(&chase_signame, chase_keyrdataset,
+ chase_sigkeyrdataset);
+ if (result == ISC_R_SUCCESS) {
+ free_name(&chase_name);
+ free_name(&chase_signame);
+ printf("\n;; Ok this DNSKEY is a Trusted Key,"
+ " DNSSEC validation is ok: SUCCESS\n\n");
+ clean_trustedkey();
+ return;
+ }
+
+ printf(";; Now, we are going to validate this DNSKEY by the DS\n");
+
+ if (chase_dsrdataset == NULL) {
+ free_name(&chase_name);
+ free_name(&chase_signame);
+ printf(";; the DNSKEY isn't trusted-key and there isn't"
+ " DS to validate the DNSKEY: FAILED\n");
+ clean_trustedkey();
+ return;
+ }
+
+ result = sigchase_verify_ds(&chase_signame, chase_keyrdataset,
+ chase_dsrdataset);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_signame);
+ free_name(&chase_name);
+ printf(";; ERROR no DS validates a DNSKEY in the"
+ " DNSKEY RRset: FAILED\n");
+ clean_trustedkey();
+ return;
+ } else
+ printf(";; OK this DNSKEY (validated by the DS) validates"
+ " the RRset of the DNSKEYs, thus the DNSKEY validates"
+ " the RRset\n");
+ INSIST(chase_sigdsrdataset != NULL);
+
+ dup_name(&chase_signame, &chase_name);
+ free_name(&chase_signame);
+ chase_rdataset = chase_dsrdataset;
+ chase_sigrdataset = chase_sigdsrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = chase_keylookedup = false;
+ chase_dslookedup = chase_sigdslookedup = false;
+
+ printf(";; Now, we want to validate the DS : recursive call\n");
+ sigchase(msg);
+ return;
+}
+#endif
+
+void
+sigchase(dns_message_t *msg) {
+#if DIG_SIGCHASE_TD
+ if (current_lookup->do_topdown) {
+ sigchase_td(msg);
+ return;
+ }
+#endif
+#if DIG_SIGCHASE_BU
+ sigchase_bu(msg);
+ return;
+#endif
+}
+
+
+/*
+ * return 1 if name1 < name2
+ * 0 if name1 == name2
+ * -1 if name1 > name2
+ * and -2 if problem
+ */
+int
+inf_name(dns_name_t *name1, dns_name_t *name2)
+{
+ dns_label_t label1;
+ dns_label_t label2;
+ unsigned int nblabel1;
+ unsigned int nblabel2;
+ int min_lum_label;
+ int i;
+ int ret = -2;
+
+ nblabel1 = dns_name_countlabels(name1);
+ nblabel2 = dns_name_countlabels(name2);
+
+ if (nblabel1 >= nblabel2)
+ min_lum_label = nblabel2;
+ else
+ min_lum_label = nblabel1;
+
+
+ for (i=1 ; i < min_lum_label; i++) {
+ dns_name_getlabel(name1, nblabel1 -1 - i, &label1);
+ dns_name_getlabel(name2, nblabel2 -1 - i, &label2);
+ if ((ret = isc_region_compare(&label1, &label2)) != 0) {
+ if (ret < 0)
+ return (-1);
+ else if (ret > 0)
+ return (1);
+ }
+ }
+ if (nblabel1 == nblabel2)
+ return (0);
+
+ if (nblabel1 < nblabel2)
+ return (-1);
+ else
+ return (1);
+}
+
+/**
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_domain(dns_message_t *msg,
+ dns_name_t *name,
+ dns_name_t *rdata_name,
+ dns_rdataset_t **rdataset,
+ dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret = ISC_R_FAILURE;
+ isc_result_t result = ISC_R_NOTFOUND;
+ dns_rdataset_t *nsecset = NULL;
+ dns_rdataset_t *signsecset = NULL ;
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+ dns_name_t *nsecname;
+ dns_rdata_nsec_t nsecstruct;
+
+ if ((result = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+ != ISC_R_SUCCESS) {
+ printf(";; nothing in authority section : impossible to"
+ " validate the non-existence : FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ do {
+ nsecname = NULL;
+ dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &nsecname);
+ nsecset = search_type(nsecname, dns_rdatatype_nsec,
+ dns_rdatatype_any);
+ if (nsecset == NULL)
+ continue;
+
+ printf("There is a NSEC for this zone in the"
+ " AUTHORITY section:\n");
+ print_rdataset(nsecname, nsecset);
+
+ for (result = dns_rdataset_first(nsecset);
+ result == ISC_R_SUCCESS;
+ result = dns_rdataset_next(nsecset)) {
+ dns_rdataset_current(nsecset, &nsec);
+
+ signsecset
+ = chase_scanname_section(msg, nsecname,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec,
+ DNS_SECTION_AUTHORITY);
+ if (signsecset == NULL) {
+ printf(";; no RRSIG NSEC in authority section:"
+ " impossible to validate the "
+ "non-existence: FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ ret = dns_rdata_tostruct(&nsec, &nsecstruct, NULL);
+ check_result(ret,"dns_rdata_tostruct");
+
+ if ((inf_name(nsecname, &nsecstruct.next) == 1 &&
+ inf_name(name, &nsecstruct.next) == 1) ||
+ (inf_name(name, nsecname) == 1 &&
+ inf_name(&nsecstruct.next, name) == 1)) {
+ dns_rdata_freestruct(&nsecstruct);
+ *rdataset = nsecset;
+ *sigrdataset = signsecset;
+ dup_name(nsecname, rdata_name);
+
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_rdata_freestruct(&nsecstruct);
+ dns_rdata_reset(&nsec);
+ }
+ } while (dns_message_nextname(msg, DNS_SECTION_AUTHORITY)
+ == ISC_R_SUCCESS);
+
+ *rdataset = NULL;
+ *sigrdataset = NULL;
+ rdata_name = NULL;
+ return (ISC_R_FAILURE);
+}
+
+/**
+ *
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx_type(dns_message_t *msg, dns_name_t *name, dns_rdataset_t *nsecset,
+ dns_rdataclass_t rdclass, dns_rdatatype_t type,
+ dns_name_t *rdata_name, dns_rdataset_t **rdataset,
+ dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret;
+ dns_rdataset_t *signsecset;
+ dns_rdata_t nsec = DNS_RDATA_INIT;
+
+ UNUSED(rdclass);
+
+ ret = dns_rdataset_first(nsecset);
+ check_result(ret,"dns_rdataset_first");
+
+ dns_rdataset_current(nsecset, &nsec);
+
+ ret = dns_nsec_typepresent(&nsec, type);
+ if (ret == ISC_R_SUCCESS)
+ printf("OK the NSEC said that the type doesn't exist \n");
+
+ signsecset = chase_scanname_section(msg, name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_nsec,
+ DNS_SECTION_AUTHORITY);
+ if (signsecset == NULL) {
+ printf("There isn't RRSIG NSEC for the zone \n");
+ return (ISC_R_FAILURE);
+ }
+ dup_name(name, rdata_name);
+ *rdataset = nsecset;
+ *sigrdataset = signsecset;
+
+ return (ret);
+}
+
+/**
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t rdclass,
+ dns_rdatatype_t type, dns_name_t *rdata_name,
+ dns_rdataset_t **rdataset, dns_rdataset_t **sigrdataset)
+{
+ isc_result_t ret;
+ dns_rdataset_t *nsecset = NULL;
+
+ printf("We want to prove the non-existence of a type of rdata %d"
+ " or of the zone: \n", type);
+
+ if ((ret = dns_message_firstname(msg, DNS_SECTION_AUTHORITY))
+ != ISC_R_SUCCESS) {
+ printf(";; nothing in authority section : impossible to"
+ " validate the non-existence : FAILED\n");
+ return (ISC_R_FAILURE);
+ }
+
+ nsecset = chase_scanname_section(msg, name, dns_rdatatype_nsec,
+ dns_rdatatype_any,
+ DNS_SECTION_AUTHORITY);
+ if (nsecset != NULL) {
+ printf("We have a NSEC for this zone :OK\n");
+ ret = prove_nx_type(msg, name, nsecset, rdclass,
+ type, rdata_name, rdataset,
+ sigrdataset);
+ if (ret != ISC_R_SUCCESS) {
+ printf("prove_nx: ERROR type exist\n");
+ return (ret);
+ } else {
+ printf("prove_nx: OK type does not exist\n");
+ return (ISC_R_SUCCESS);
+ }
+ } else {
+ printf("there is no NSEC for this zone: validating "
+ "that the zone doesn't exist\n");
+ ret = prove_nx_domain(msg, name, rdata_name,
+ rdataset, sigrdataset);
+ return (ret);
+ }
+ /* Never get here */
+}
+#endif
diff --git a/bin/dig/host.1 b/bin/dig/host.1
new file mode 100644
index 0000000..3e75fb7
--- /dev/null
+++ b/bin/dig/host.1
@@ -0,0 +1,269 @@
+.\" Copyright (C) 2000-2002, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: host
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2009-01-20
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "HOST" "1" "2009\-01\-20" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+host \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP \w'\fBhost\fR\ 'u
+\fBhost\fR [\fB\-aCdlnrsTUwv\fR] [\fB\-c\ \fR\fB\fIclass\fR\fR] [\fB\-N\ \fR\fB\fIndots\fR\fR] [\fB\-R\ \fR\fB\fInumber\fR\fR] [\fB\-t\ \fR\fB\fItype\fR\fR] [\fB\-W\ \fR\fB\fIwait\fR\fR] [\fB\-m\ \fR\fB\fIflag\fR\fR] [[\fB\-4\fR] | [\fB\-6\fR]] [\fB\-v\fR] [\fB\-V\fR] {name} [server]
+.SH "DESCRIPTION"
+.PP
+\fBhost\fR
+is a simple utility for performing DNS lookups\&. It is normally used to convert names to IP addresses and vice versa\&. When no arguments or options are given,
+\fBhost\fR
+prints a short summary of its command line arguments and options\&.
+.PP
+\fIname\fR
+is the domain name that is to be looked up\&. It can also be a dotted\-decimal IPv4 address or a colon\-delimited IPv6 address, in which case
+\fBhost\fR
+will by default perform a reverse lookup for that address\&.
+\fIserver\fR
+is an optional argument which is either the name or IP address of the name server that
+\fBhost\fR
+should query instead of the server or servers listed in
+/etc/resolv\&.conf\&.
+.SH "OPTIONS"
+.PP
+\-4
+.RS 4
+Use IPv4 only for query transport\&. See also the
+\fB\-6\fR
+option\&.
+.RE
+.PP
+\-6
+.RS 4
+Use IPv6 only for query transport\&. See also the
+\fB\-4\fR
+option\&.
+.RE
+.PP
+\-a
+.RS 4
+"All"\&. The
+\fB\-a\fR
+option is normally equivalent to
+\fB\-v \-t \fR\fBANY\fR\&. It also affects the behaviour of the
+\fB\-l\fR
+list zone option\&.
+.RE
+.PP
+\-c \fIclass\fR
+.RS 4
+Query class: This can be used to lookup HS (Hesiod) or CH (Chaosnet) class resource records\&. The default class is IN (Internet)\&.
+.RE
+.PP
+\-C
+.RS 4
+Check consistency:
+\fBhost\fR
+will query the SOA records for zone
+\fIname\fR
+from all the listed authoritative name servers for that zone\&. The list of name servers is defined by the NS records that are found for the zone\&.
+.RE
+.PP
+\-d
+.RS 4
+Print debugging traces\&. Equivalent to the
+\fB\-v\fR
+verbose option\&.
+.RE
+.PP
+\-i
+.RS 4
+Obsolete\&. Use the IP6\&.INT domain for reverse lookups of IPv6 addresses as defined in RFC1886 and deprecated in RFC4159\&. The default is to use IP6\&.ARPA as specified in RFC3596\&.
+.RE
+.PP
+\-l
+.RS 4
+List zone: The
+\fBhost\fR
+command performs a zone transfer of zone
+\fIname\fR
+and prints out the NS, PTR and address records (A/AAAA)\&.
+.sp
+Together, the
+\fB\-l \-a\fR
+options print all records in the zone\&.
+.RE
+.PP
+\-N \fIndots\fR
+.RS 4
+The number of dots that have to be in
+\fIname\fR
+for it to be considered absolute\&. The default value is that defined using the ndots statement in
+/etc/resolv\&.conf, or 1 if no ndots statement is present\&. Names with fewer dots are interpreted as relative names and will be searched for in the domains listed in the
+\fBsearch\fR
+or
+\fBdomain\fR
+directive in
+/etc/resolv\&.conf\&.
+.RE
+.PP
+\-r
+.RS 4
+Non\-recursive query: Setting this option clears the RD (recursion desired) bit in the query\&. This should mean that the name server receiving the query will not attempt to resolve
+\fIname\fR\&. The
+\fB\-r\fR
+option enables
+\fBhost\fR
+to mimic the behavior of a name server by making non\-recursive queries and expecting to receive answers to those queries that can be referrals to other name servers\&.
+.RE
+.PP
+\-R \fInumber\fR
+.RS 4
+Number of retries for UDP queries: If
+\fInumber\fR
+is negative or zero, the number of retries will default to 1\&. The default value is 1, or the value of the
+\fIattempts\fR
+option in
+/etc/resolv\&.conf, if set\&.
+.RE
+.PP
+\-s
+.RS 4
+Do
+\fInot\fR
+send the query to the next nameserver if any server responds with a SERVFAIL response, which is the reverse of normal stub resolver behavior\&.
+.RE
+.PP
+\-t \fItype\fR
+.RS 4
+Query type: The
+\fItype\fR
+argument can be any recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc\&.
+.sp
+When no query type is specified,
+\fBhost\fR
+automatically selects an appropriate query type\&. By default, it looks for A, AAAA, and MX records\&. If the
+\fB\-C\fR
+option is given, queries will be made for SOA records\&. If
+\fIname\fR
+is a dotted\-decimal IPv4 address or colon\-delimited IPv6 address,
+\fBhost\fR
+will query for PTR records\&.
+.sp
+If a query type of IXFR is chosen the starting serial number can be specified by appending an equal followed by the starting serial number (like
+\fB\-t \fR\fBIXFR=12345678\fR)\&.
+.RE
+.PP
+\-T, \-U
+.RS 4
+TCP/UDP: By default,
+\fBhost\fR
+uses UDP when making queries\&. The
+\fB\-T\fR
+option makes it use a TCP connection when querying the name server\&. TCP will be automatically selected for queries that require it, such as zone transfer (AXFR) requests\&. Type ANY queries default to TCP but can be forced to UDP initially using
+\fB\-U\fR\&.
+.RE
+.PP
+\-m \fIflag\fR
+.RS 4
+Memory usage debugging: the flag can be
+\fIrecord\fR,
+\fIusage\fR, or
+\fItrace\fR\&. You can specify the
+\fB\-m\fR
+option more than once to set multiple flags\&.
+.RE
+.PP
+\-v
+.RS 4
+Verbose output\&. Equivalent to the
+\fB\-d\fR
+debug option\&. Verbose output can also be enabled by setting the
+\fIdebug\fR
+option in
+/etc/resolv\&.conf\&.
+.RE
+.PP
+\-V
+.RS 4
+Print the version number and exit\&.
+.RE
+.PP
+\-w
+.RS 4
+Wait forever: The query timeout is set to the maximum possible\&. See also the
+\fB\-W\fR
+option\&.
+.RE
+.PP
+\-W \fIwait\fR
+.RS 4
+Timeout: Wait for up to
+\fIwait\fR
+seconds for a reply\&. If
+\fIwait\fR
+is less than one, the wait interval is set to one second\&.
+.sp
+By default,
+\fBhost\fR
+will wait for 5 seconds for UDP responses and 10 seconds for TCP connections\&. These defaults can be overridden by the
+\fItimeout\fR
+option in
+/etc/resolv\&.conf\&.
+.sp
+See also the
+\fB\-w\fR
+option\&.
+.RE
+.SH "IDN SUPPORT"
+.PP
+If
+\fBhost\fR
+has been built with IDN (internationalized domain name) support, it can accept and display non\-ASCII domain names\&.
+\fBhost\fR
+appropriately converts character encoding of domain name before sending a request to DNS server or displaying a reply from the server\&. If you\*(Aqd like to turn off the IDN support for some reason, defines the
+\fBIDN_DISABLE\fR
+environment variable\&. The IDN support is disabled if the variable is set when
+\fBhost\fR
+runs\&.
+.SH "FILES"
+.PP
+/etc/resolv\&.conf
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBnamed\fR(8)\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2000-2002, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/host.c b/bin/dig/host.c
new file mode 100644
index 0000000..d342b1e
--- /dev/null
+++ b/bin/dig/host.c
@@ -0,0 +1,921 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*! \file */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDNKIT
+#include <idn/result.h>
+#include <idn/log.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#endif
+
+#include <isc/app.h>
+#include <isc/commandline.h>
+#include <isc/netaddr.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/task.h>
+#include <isc/stdlib.h>
+
+#include <dns/byaddr.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/rdatastruct.h>
+
+#include <dig/dig.h>
+
+static bool short_form = true, listed_server = false;
+static bool default_lookups = true;
+static int seen_error = -1;
+static bool list_addresses = true;
+static dns_rdatatype_t list_type = dns_rdatatype_a;
+static bool printed_server = false;
+static bool ipv4only = false, ipv6only = false;
+
+static const char *opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+static const char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+struct rtype {
+ unsigned int type;
+ const char *text;
+};
+
+struct rtype rtypes[] = {
+ { 1, "has address" },
+ { 2, "name server" },
+ { 5, "is an alias for" },
+ { 11, "has well known services" },
+ { 12, "domain name pointer" },
+ { 13, "host information" },
+ { 15, "mail is handled by" },
+ { 16, "descriptive text" },
+ { 19, "x25 address" },
+ { 20, "ISDN address" },
+ { 24, "has signature" },
+ { 25, "has key" },
+ { 28, "has IPv6 address" },
+ { 29, "location" },
+ { 0, NULL }
+};
+
+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;
+}
+
+ISC_PLATFORM_NORETURN_PRE static void
+show_usage(void) ISC_PLATFORM_NORETURN_POST;
+
+static void
+show_usage(void) {
+ fputs(
+"Usage: host [-aCdilrTvVw] [-c class] [-N ndots] [-t type] [-W time]\n"
+" [-R number] [-m flag] hostname [server]\n"
+" -a is equivalent to -v -t ANY\n"
+" -c specifies query class for non-IN data\n"
+" -C compares SOA records on authoritative nameservers\n"
+" -d is equivalent to -v\n"
+" -i IP6.INT reverse lookups\n"
+" -l lists all hosts in a domain, using AXFR\n"
+" -m set memory debugging flag (trace|record|usage)\n"
+" -N changes the number of dots allowed before root lookup is done\n"
+" -r disables recursive processing\n"
+" -R specifies number of retries for UDP packets\n"
+" -s a SERVFAIL response should stop query\n"
+" -t specifies the query type\n"
+" -T enables TCP/IP mode\n"
+" -v enables verbose output\n"
+" -V print version number and exit\n"
+" -w specifies to wait forever for a reply\n"
+" -W specifies how long to wait for a reply\n"
+" -4 use IPv4 query transport only\n"
+" -6 use IPv6 query transport only\n", stderr);
+ exit(1);
+}
+
+static void
+host_shutdown(void) {
+ (void) isc_app_shutdown();
+}
+
+static void
+received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ isc_time_t now;
+ int diff;
+
+ if (!short_form) {
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+ TIME_NOW(&now);
+ diff = (int) isc_time_microdiff(&now, &query->time_sent);
+ printf("Received %u bytes from %s in %d ms\n",
+ bytes, fromtext, diff/1000);
+ }
+}
+
+static void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(lookup);
+
+ if (!short_form)
+ printf("Trying \"%s\"\n", frm);
+}
+
+static void
+say_message(dns_name_t *name, const char *msg, dns_rdata_t *rdata,
+ dig_query_t *query)
+{
+ isc_buffer_t *b = NULL;
+ char namestr[DNS_NAME_FORMATSIZE];
+ isc_region_t r;
+ isc_result_t result;
+ unsigned int bufsize = BUFSIZ;
+
+ dns_name_format(name, namestr, sizeof(namestr));
+ retry:
+ result = isc_buffer_allocate(mctx, &b, bufsize);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_rdata_totext(rdata, NULL, b);
+ if (result == ISC_R_NOSPACE) {
+ isc_buffer_free(&b);
+ bufsize *= 2;
+ goto retry;
+ }
+ check_result(result, "dns_rdata_totext");
+ isc_buffer_usedregion(b, &r);
+ if (query->lookup->identify_previous_line) {
+ printf("Nameserver %s:\n\t",
+ query->servname);
+ }
+ printf("%s %s %.*s", namestr,
+ msg, (int)r.length, (char *)r.base);
+ if (query->lookup->identify) {
+ printf(" on server %s", query->servname);
+ }
+ printf("\n");
+ isc_buffer_free(&b);
+}
+#ifdef DIG_SIGCHASE
+/* Just for compatibility : not use in host program */
+static isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ UNUSED(owner_name);
+ UNUSED(rdataset);
+ UNUSED(target);
+ return(false);
+}
+#endif
+static isc_result_t
+printsection(dns_message_t *msg, dns_section_t sectionid,
+ const char *section_name, bool headers,
+ dig_query_t *query)
+{
+ dns_name_t *name, *print_name;
+ dns_rdataset_t *rdataset;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ isc_buffer_t target;
+ isc_result_t result, loopresult;
+ isc_region_t r;
+ dns_name_t empty_name;
+ char tbuf[4096];
+ bool first;
+ bool no_rdata;
+
+ if (sectionid == DNS_SECTION_QUESTION)
+ no_rdata = true;
+ else
+ no_rdata = false;
+
+ if (headers)
+ printf(";; %s SECTION:\n", section_name);
+
+ dns_name_init(&empty_name, NULL);
+
+ result = dns_message_firstname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, sectionid, &name);
+
+ isc_buffer_init(&target, tbuf, sizeof(tbuf));
+ first = true;
+ print_name = name;
+
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (query->lookup->rdtype == dns_rdatatype_axfr &&
+ !((!list_addresses &&
+ (list_type == dns_rdatatype_any ||
+ rdataset->type == list_type)) ||
+ (list_addresses &&
+ (rdataset->type == dns_rdatatype_a ||
+ rdataset->type == dns_rdatatype_aaaa ||
+ rdataset->type == dns_rdatatype_ns ||
+ rdataset->type == dns_rdatatype_ptr))))
+ continue;
+ if (!short_form) {
+ result = dns_rdataset_totext(rdataset,
+ print_name,
+ false,
+ no_rdata,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#ifdef USEINITALWS
+ if (first) {
+ print_name = &empty_name;
+ first = false;
+ }
+#else
+ UNUSED(first); /* Shut up compiler. */
+#endif
+ } else {
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ struct rtype *t;
+ const char *rtt;
+ char typebuf[DNS_RDATATYPE_FORMATSIZE];
+ char typebuf2[DNS_RDATATYPE_FORMATSIZE
+ + 20];
+ dns_rdataset_current(rdataset, &rdata);
+
+ for (t = rtypes; t->text != NULL; t++) {
+ if (t->type == rdata.type) {
+ rtt = t->text;
+ goto found;
+ }
+ }
+
+ dns_rdatatype_format(rdata.type,
+ typebuf,
+ sizeof(typebuf));
+ snprintf(typebuf2, sizeof(typebuf2),
+ "has %s record", typebuf);
+ rtt = typebuf2;
+ found:
+ say_message(print_name, rtt,
+ &rdata, query);
+ dns_rdata_reset(&rdata);
+ loopresult =
+ dns_rdataset_next(rdataset);
+ }
+ }
+ }
+ if (!short_form) {
+ isc_buffer_usedregion(&target, &r);
+ if (no_rdata)
+ printf(";%.*s", (int)r.length,
+ (char *)r.base);
+ else
+ printf("%.*s", (int)r.length, (char *)r.base);
+ }
+
+ result = dns_message_nextname(msg, sectionid);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+printrdata(dns_message_t *msg, dns_rdataset_t *rdataset, dns_name_t *owner,
+ const char *set_name, bool headers)
+{
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char tbuf[4096];
+
+ UNUSED(msg);
+ if (headers)
+ printf(";; %s SECTION:\n", set_name);
+
+ isc_buffer_init(&target, tbuf, sizeof(tbuf));
+
+ result = dns_rdataset_totext(rdataset, owner, false, false,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ isc_buffer_usedregion(&target, &r);
+ printf("%.*s", (int)r.length, (char *)r.base);
+
+ return (ISC_R_SUCCESS);
+}
+
+static void
+chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset;
+ dns_rdata_cname_t cname;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i = msg->counts[DNS_SECTION_ANSWER];
+
+ while (i-- > 0) {
+ rdataset = NULL;
+ result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+ dns_rdatatype_cname, 0, NULL,
+ &rdataset);
+ if (result != ISC_R_SUCCESS)
+ return;
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_copy(&cname.cname, qname, NULL);
+ dns_rdata_freestruct(&cname);
+ }
+}
+
+static isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, bool headers) {
+ bool did_flag = false;
+ dns_rdataset_t *opt, *tsig = NULL;
+ dns_name_t *tsigname;
+ isc_result_t result = ISC_R_SUCCESS;
+ int force_error;
+
+ UNUSED(headers);
+
+ /*
+ * We get called multiple times.
+ * Preserve any existing error status.
+ */
+ force_error = (seen_error == 1) ? 1 : 0;
+ seen_error = 1;
+ if (listed_server && !printed_server) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ printf("Using domain server:\n");
+ printf("Name: %s\n", query->userarg);
+ isc_sockaddr_format(&query->sockaddr, sockstr,
+ sizeof(sockstr));
+ printf("Address: %s\n", sockstr);
+ printf("Aliases: \n\n");
+ printed_server = true;
+ }
+
+ if (msg->rcode != 0) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(query->lookup->name, namestr, sizeof(namestr));
+
+ if (query->lookup->identify_previous_line)
+ printf("Nameserver %s:\n\t%s not found: %d(%s)\n",
+ query->servname,
+ (msg->rcode != dns_rcode_nxdomain) ? namestr :
+ query->lookup->textname, msg->rcode,
+ rcode_totext(msg->rcode));
+ else
+ printf("Host %s not found: %d(%s)\n",
+ (msg->rcode != dns_rcode_nxdomain) ? namestr :
+ query->lookup->textname, msg->rcode,
+ rcode_totext(msg->rcode));
+ return (ISC_R_SUCCESS);
+ }
+
+ if (default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dig_lookup_t *lookup;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ /* Add AAAA and MX lookups. */
+ name = dns_fixedname_initname(&fixed);
+ dns_name_copy(query->lookup->name, name, NULL);
+ chase_cnamechain(msg, name);
+ dns_name_format(name, namestr, sizeof(namestr));
+ lookup = clone_lookup(query->lookup, false);
+ if (lookup != NULL) {
+ strlcpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_aaaa;
+ lookup->rdtypeset = true;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ lookup = clone_lookup(query->lookup, false);
+ if (lookup != NULL) {
+ strlcpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_mx;
+ lookup->rdtypeset = true;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ }
+
+ if (!short_form) {
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, id: %u\n",
+ opcodetext[msg->opcode], rcode_totext(msg->rcode),
+ msg->id);
+ printf(";; flags: ");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf("qr");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf("%saa", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf("%stc", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf("%srd", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf("%sra", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf("%sad", did_flag ? " " : "");
+ did_flag = true;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf("%scd", did_flag ? " " : "");
+ did_flag = true;
+ POST(did_flag);
+ }
+ printf("; QUERY: %u, ANSWER: %u, "
+ "AUTHORITY: %u, ADDITIONAL: %u\n",
+ msg->counts[DNS_SECTION_QUESTION],
+ msg->counts[DNS_SECTION_ANSWER],
+ msg->counts[DNS_SECTION_AUTHORITY],
+ msg->counts[DNS_SECTION_ADDITIONAL]);
+ opt = dns_message_getopt(msg);
+ if (opt != NULL)
+ printf(";; EDNS: version: %u, udp=%u\n",
+ (unsigned int)((opt->ttl & 0x00ff0000) >> 16),
+ (unsigned int)opt->rdclass);
+ tsigname = NULL;
+ tsig = dns_message_gettsig(msg, &tsigname);
+ if (tsig != NULL)
+ printf(";; PSEUDOSECTIONS: TSIG\n");
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_QUESTION]) &&
+ !short_form) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_QUESTION, "QUESTION",
+ true, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
+ if (!short_form)
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ANSWER, "ANSWER",
+ !short_form, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_AUTHORITY]) &&
+ !short_form) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_AUTHORITY, "AUTHORITY",
+ true, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (! ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ADDITIONAL]) &&
+ !short_form) {
+ printf("\n");
+ result = printsection(msg, DNS_SECTION_ADDITIONAL,
+ "ADDITIONAL", true, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if ((tsig != NULL) && !short_form) {
+ printf("\n");
+ result = printrdata(msg, tsig, tsigname,
+ "PSEUDOSECTION TSIG", true);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if (!short_form)
+ printf("\n");
+
+ if (short_form && !default_lookups &&
+ ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ char typestr[DNS_RDATATYPE_FORMATSIZE];
+ dns_name_format(query->lookup->name, namestr, sizeof(namestr));
+ dns_rdatatype_format(query->lookup->rdtype, typestr,
+ sizeof(typestr));
+ printf("%s has no %s record\n", namestr, typestr);
+ }
+ seen_error = force_error;
+ return (result);
+}
+
+static const char * optstring = "46ac:dilnm:rst:vVwCDN:R:TUW:";
+
+/*% version */
+static void
+version(void) {
+ fputs("host " VERSION "\n", stderr);
+}
+
+static void
+pre_parse_args(int argc, char **argv) {
+ int c;
+
+ while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
+ switch (c) {
+ case 'm':
+ memdebugging = true;
+ if (strcasecmp("trace", isc_commandline_argument) == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGTRACE;
+ else if (strcasecmp("record",
+ isc_commandline_argument) == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGRECORD;
+ else if (strcasecmp("usage",
+ isc_commandline_argument) == 0)
+ isc_mem_debugging |= ISC_MEM_DEBUGUSAGE;
+ 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;
+ case 'a': break;
+ case 'c': break;
+ case 'd': break;
+ case 'i': break;
+ case 'l': break;
+ case 'n': break;
+ case 'r': break;
+ case 's': break;
+ case 't': break;
+ case 'v': break;
+ case 'V':
+ version();
+ exit(0);
+ break;
+ case 'w': break;
+ case 'C': break;
+ case 'D':
+ if (debugging)
+ debugtiming = true;
+ debugging = true;
+ break;
+ case 'N': break;
+ case 'R': break;
+ case 'T': break;
+ case 'W': break;
+ default:
+ show_usage();
+ }
+ }
+ isc_commandline_reset = true;
+ isc_commandline_index = 1;
+}
+
+static void
+parse_args(bool is_batchfile, int argc, char **argv) {
+ char hostname[MXNAME];
+ dig_lookup_t *lookup;
+ int c;
+ char store[MXNAME];
+ isc_textregion_t tr;
+ isc_result_t result = ISC_R_SUCCESS;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ uint32_t serial = 0;
+
+ UNUSED(is_batchfile);
+
+ lookup = make_empty_lookup();
+
+ lookup->servfail_stops = false;
+ lookup->comments = false;
+ short_form = !verbose;
+
+ while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
+ switch (c) {
+ case 'l':
+ lookup->tcp_mode = true;
+ lookup->rdtype = dns_rdatatype_axfr;
+ lookup->rdtypeset = true;
+ fatalexit = 3;
+ break;
+ case 'v':
+ case 'd':
+ short_form = false;
+ break;
+ case 'r':
+ lookup->recurse = false;
+ break;
+ case 't':
+ if (strncasecmp(isc_commandline_argument,
+ "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ /* XXXMPA add error checking */
+ serial = strtoul(isc_commandline_argument + 5,
+ NULL, 10);
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = isc_commandline_argument;
+ tr.length = strlen(isc_commandline_argument);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ }
+
+ if (result != ISC_R_SUCCESS) {
+ fatalexit = 2;
+ fatal("invalid type: %s\n",
+ isc_commandline_argument);
+ }
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = true;
+#ifdef WITH_IDNKIT
+ idnoptions = 0;
+#endif
+ if (rdtype == dns_rdatatype_axfr) {
+ /* -l -t any -v */
+ list_type = dns_rdatatype_any;
+ short_form = false;
+ lookup->tcp_mode = true;
+ } else if (rdtype == dns_rdatatype_ixfr) {
+ lookup->ixfr_serial = serial;
+ lookup->tcp_mode = true;
+ list_type = rdtype;
+ } else if (rdtype == dns_rdatatype_any) {
+ if (!lookup->tcp_mode_set)
+ lookup->tcp_mode = true;
+#ifdef WITH_IDNKIT
+ } else if (rdtype == dns_rdatatype_a ||
+ rdtype == dns_rdatatype_aaaa ||
+ rdtype == dns_rdatatype_mx) {
+ idnoptions = IDN_ASCCHECK;
+ list_type = rdtype;
+#endif
+ } else
+ list_type = rdtype;
+ list_addresses = false;
+ default_lookups = false;
+ break;
+ case 'c':
+ tr.base = isc_commandline_argument;
+ tr.length = strlen(isc_commandline_argument);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+
+ if (result != ISC_R_SUCCESS) {
+ fatalexit = 2;
+ fatal("invalid class: %s\n",
+ isc_commandline_argument);
+ } else {
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = true;
+ }
+ default_lookups = false;
+ break;
+ case 'a':
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ lookup->rdtype = dns_rdatatype_any;
+#ifdef WITH_IDNKIT
+ idnoptions = 0;
+#endif
+ list_type = dns_rdatatype_any;
+ list_addresses = false;
+ lookup->rdtypeset = true;
+ short_form = false;
+ default_lookups = false;
+ break;
+ case 'i':
+ lookup->ip6_int = true;
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'm':
+ /* Handled by pre_parse_args(). */
+ break;
+ case 'w':
+ /*
+ * The timer routines are coded such that
+ * timeout==MAXINT doesn't enable the timer
+ */
+ timeout = INT_MAX;
+ break;
+ case 'W':
+ timeout = atoi(isc_commandline_argument);
+ if (timeout < 1)
+ timeout = 1;
+ break;
+ case 'R':
+ tries = atoi(isc_commandline_argument) + 1;
+ if (tries < 2)
+ tries = 2;
+ break;
+ case 'T':
+ lookup->tcp_mode = true;
+ lookup->tcp_mode_set = true;
+ break;
+ case 'U':
+ lookup->tcp_mode = false;
+ lookup->tcp_mode_set = true;
+ break;
+ case 'C':
+ debug("showing all SOAs");
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = true;
+ lookup->rdclass = dns_rdataclass_in;
+ lookup->rdclassset = true;
+ lookup->ns_search_only = true;
+ lookup->trace_root = true;
+ lookup->identify_previous_line = true;
+ default_lookups = false;
+ break;
+ case 'N':
+ debug("setting NDOTS to %s",
+ isc_commandline_argument);
+ ndots = atoi(isc_commandline_argument);
+ break;
+ case 'D':
+ /* Handled by pre_parse_args(). */
+ break;
+ case '4':
+ /* Handled by pre_parse_args(). */
+ break;
+ case '6':
+ /* Handled by pre_parse_args(). */
+ break;
+ case 's':
+ lookup->servfail_stops = true;
+ break;
+ }
+ }
+
+ lookup->retries = tries;
+
+ if (isc_commandline_index >= argc)
+ show_usage();
+
+ strlcpy(hostname, argv[isc_commandline_index], sizeof(hostname));
+
+ if (argc > isc_commandline_index + 1) {
+ set_nameserver(argv[isc_commandline_index+1]);
+ debug("server is %s", argv[isc_commandline_index+1]);
+ listed_server = true;
+ } else
+ check_ra = true;
+
+ lookup->pending = false;
+ if (get_reverse(store, sizeof(store), hostname,
+ lookup->ip6_int, true) == ISC_R_SUCCESS) {
+ strlcpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = true;
+ default_lookups = false;
+ } else {
+ strlcpy(lookup->textname, hostname, sizeof(lookup->textname));
+ usesearch = true;
+ }
+ lookup->new_search = true;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ tries = 2;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ fatalexit = 1;
+#ifdef WITH_IDNKIT
+ idnoptions = IDN_ASCCHECK;
+#endif
+
+ /* setup dighost callbacks */
+#ifdef DIG_SIGCHASE
+ dighost_printrdataset = printrdataset;
+#endif
+ dighost_printmessage = printmessage;
+ dighost_received = received;
+ dighost_trying = trying;
+ dighost_shutdown = host_shutdown;
+
+ debug("main()");
+ progname = argv[0];
+ pre_parse_args(argc, argv);
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+ setup_libs();
+ setup_system(ipv4only, ipv6only);
+ parse_args(false, argc, argv);
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+ setup_text_key();
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ check_result(result, "isc_app_onrun");
+ isc_app_run();
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+ return ((seen_error == 0) ? 0 : 1);
+}
diff --git a/bin/dig/host.docbook b/bin/dig/host.docbook
new file mode 100644
index 0000000..da0f8fb
--- /dev/null
+++ b/bin/dig/host.docbook
@@ -0,0 +1,406 @@
+<!DOCTYPE book [
+<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.host">
+ <info>
+ <date>2009-01-20</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>host</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>host</refname>
+ <refpurpose>DNS lookup utility</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <year>2009</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>host</command>
+ <arg choice="opt" rep="norepeat"><option>-aCdlnrsTUwv</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-N <replaceable class="parameter">ndots</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-R <replaceable class="parameter">number</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-W <replaceable class="parameter">wait</replaceable></option></arg>
+ <arg choice="opt" rep="norepeat"><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <group choice="opt" rep="norepeat">
+ <arg choice="opt" rep="norepeat"><option>-4</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-6</option></arg>
+ </group>
+ <arg choice="opt" rep="norepeat"><option>-v</option></arg>
+ <arg choice="opt" rep="norepeat"><option>-V</option></arg>
+ <arg choice="req" rep="norepeat">name</arg>
+ <arg choice="opt" rep="norepeat">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+
+ <para><command>host</command>
+ is a simple utility for performing DNS lookups.
+ It is normally used to convert names to IP addresses and vice versa.
+ When no arguments or options are given,
+ <command>host</command>
+ prints a short summary of its command line arguments and options.
+ </para>
+
+ <para><parameter>name</parameter> is the domain name that is to be
+ looked
+ up. It can also be a dotted-decimal IPv4 address or a colon-delimited
+ IPv6 address, in which case <command>host</command> will by
+ default
+ perform a reverse lookup for that address.
+ <parameter>server</parameter> is an optional argument which
+ is either
+ the name or IP address of the name server that <command>host</command>
+ should query instead of the server or servers listed in
+ <filename>/etc/resolv.conf</filename>.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>OPTIONS</title></info>
+
+ <variablelist>
+
+ <varlistentry>
+ <term>-4</term>
+ <listitem>
+ <para>
+ Use IPv4 only for query transport.
+ See also the <option>-6</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-6</term>
+ <listitem>
+ <para>
+ Use IPv6 only for query transport.
+ See also the <option>-4</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-a</term>
+ <listitem>
+ <para>
+ "All". The <option>-a</option> option is normally equivalent
+ to <option>-v -t <literal>ANY</literal></option>.
+ It also affects the behaviour of the <option>-l</option>
+ list zone option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-c <replaceable class="parameter">class</replaceable></term>
+ <listitem>
+ <para>
+ Query class: This can be used to lookup HS (Hesiod) or CH
+ (Chaosnet) class resource records. The default class is IN
+ (Internet).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-C</term>
+ <listitem>
+ <para>
+ Check consistency: <command>host</command> will query the
+ SOA records for zone <parameter>name</parameter> from all
+ the listed authoritative name servers for that zone. The
+ list of name servers is defined by the NS records that are
+ found for the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-d</term>
+ <listitem>
+ <para>
+ Print debugging traces.
+ Equivalent to the <option>-v</option> verbose option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-i</term>
+ <listitem>
+ <para>
+ Obsolete.
+ Use the IP6.INT domain for reverse lookups of IPv6
+ addresses as defined in RFC1886 and deprecated in RFC4159.
+ The default is to use IP6.ARPA as specified in RFC3596.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-l</term>
+ <listitem>
+ <para>
+ List zone:
+ The <command>host</command> command performs a zone transfer of
+ zone <parameter>name</parameter> and prints out the NS,
+ PTR and address records (A/AAAA).
+ </para>
+ <para>
+ Together, the <option>-l -a</option>
+ options print all records in the zone.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-N <replaceable class="parameter">ndots</replaceable></term>
+ <listitem>
+ <para>
+ The number of dots that have to be
+ in <parameter>name</parameter> for it to be considered
+ absolute. The default value is that defined using the
+ ndots statement in <filename>/etc/resolv.conf</filename>,
+ or 1 if no ndots statement is present. Names with fewer
+ dots are interpreted as relative names and will be
+ searched for in the domains listed in
+ the <type>search</type> or <type>domain</type> directive
+ in <filename>/etc/resolv.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-r</term>
+ <listitem>
+ <para>
+ Non-recursive query:
+ Setting this option clears the RD (recursion desired) bit
+ in the query. This should mean that the name server
+ receiving the query will not attempt to
+ resolve <parameter>name</parameter>.
+ The <option>-r</option> option
+ enables <command>host</command> to mimic the behavior of a
+ name server by making non-recursive queries and expecting
+ to receive answers to those queries that can be
+ referrals to other name servers.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-R <replaceable class="parameter">number</replaceable></term>
+ <listitem>
+ <para>
+ Number of retries for UDP queries:
+ If <parameter>number</parameter> is negative or zero, the
+ number of retries will default to 1. The default value is
+ 1, or the value of the <parameter>attempts</parameter>
+ option in <filename>/etc/resolv.conf</filename>, if set.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-s</term>
+ <listitem>
+ <para>
+ Do <emphasis>not</emphasis> send the query to the next
+ nameserver if any server responds with a SERVFAIL
+ response, which is the reverse of normal stub resolver
+ behavior.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-t <replaceable class="parameter">type</replaceable></term>
+ <listitem>
+ <para>
+ Query type:
+ The <parameter>type</parameter> argument can be any
+ recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc.
+ </para>
+ <para>
+ When no query type is specified, <command>host</command>
+ automatically selects an appropriate query type. By default, it
+ looks for A, AAAA, and MX records.
+ If the <option>-C</option> option is given, queries will
+ be made for SOA records.
+ If <parameter>name</parameter> is a dotted-decimal IPv4
+ address or colon-delimited IPv6
+ address, <command>host</command> will query for PTR
+ records.
+ </para>
+ <para>
+ If a query type of IXFR is chosen the starting serial
+ number can be specified by appending an equal followed by
+ the starting serial number
+ (like <option>-t <literal>IXFR=12345678</literal></option>).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-T</term>
+ <term>-U</term>
+ <listitem>
+ <para>
+ TCP/UDP:
+ By default, <command>host</command> uses UDP when making
+ queries. The <option>-T</option> option makes it use a TCP
+ connection when querying the name server. TCP will be
+ automatically selected for queries that require it, such
+ as zone transfer (AXFR) requests. Type ANY queries default
+ to TCP but can be forced to UDP initially using <option>-U</option>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-m <replaceable class="parameter">flag</replaceable></term>
+ <listitem>
+ <para>
+ Memory usage debugging: the flag can
+ be <parameter>record</parameter>, <parameter>usage</parameter>,
+ or <parameter>trace</parameter>. You can specify
+ the <option>-m</option> option more than once to set
+ multiple flags.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-v</term>
+ <listitem>
+ <para>
+ Verbose output.
+ Equivalent to the <option>-d</option> debug option.
+ Verbose output can also be enabled by setting
+ the <parameter>debug</parameter> option
+ in <filename>/etc/resolv.conf</filename>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-V</term>
+ <listitem>
+ <para>
+ Print the version number and exit.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-w</term>
+ <listitem>
+ <para>
+ Wait forever: The query timeout is set to the maximum possible.
+ See also the <option>-W</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>-W <replaceable class="parameter">wait</replaceable></term>
+ <listitem>
+ <para>
+ Timeout: Wait for up to <parameter>wait</parameter>
+ seconds for a reply. If <parameter>wait</parameter> is
+ less than one, the wait interval is set to one second.
+ </para>
+ <para>
+ By default, <command>host</command> will wait for 5
+ seconds for UDP responses and 10 seconds for TCP
+ connections. These defaults can be overridden by
+ the <parameter>timeout</parameter> option
+ in <filename>/etc/resolv.conf</filename>.
+ </para>
+ <para>
+ See also the <option>-w</option> option.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+
+ </refsection>
+
+ <refsection><info><title>IDN SUPPORT</title></info>
+
+ <para>
+ If <command>host</command> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <command>host</command> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <envar>IDN_DISABLE</envar> environment variable.
+ The IDN support is disabled if the variable is set when
+ <command>host</command> runs.
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsection>
+
+</refentry>
diff --git a/bin/dig/host.html b/bin/dig/host.html
new file mode 100644
index 0000000..665a5e6
--- /dev/null
+++ b/bin/dig/host.html
@@ -0,0 +1,333 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2000-2002, 2004, 2005, 2007-2009, 2014-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>host</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.host"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ host
+ &#8212; DNS lookup utility
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">host</code>
+ [<code class="option">-aCdlnrsTUwv</code>]
+ [<code class="option">-c <em class="replaceable"><code>class</code></em></code>]
+ [<code class="option">-N <em class="replaceable"><code>ndots</code></em></code>]
+ [<code class="option">-R <em class="replaceable"><code>number</code></em></code>]
+ [<code class="option">-t <em class="replaceable"><code>type</code></em></code>]
+ [<code class="option">-W <em class="replaceable"><code>wait</code></em></code>]
+ [<code class="option">-m <em class="replaceable"><code>flag</code></em></code>]
+ [
+ [<code class="option">-4</code>]
+ | [<code class="option">-6</code>]
+ ]
+ [<code class="option">-v</code>]
+ [<code class="option">-V</code>]
+ {name}
+ [server]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+
+ <p><span class="command"><strong>host</strong></span>
+ is a simple utility for performing DNS lookups.
+ It is normally used to convert names to IP addresses and vice versa.
+ When no arguments or options are given,
+ <span class="command"><strong>host</strong></span>
+ prints a short summary of its command line arguments and options.
+ </p>
+
+ <p><em class="parameter"><code>name</code></em> is the domain name that is to be
+ looked
+ up. It can also be a dotted-decimal IPv4 address or a colon-delimited
+ IPv6 address, in which case <span class="command"><strong>host</strong></span> will by
+ default
+ perform a reverse lookup for that address.
+ <em class="parameter"><code>server</code></em> is an optional argument which
+ is either
+ the name or IP address of the name server that <span class="command"><strong>host</strong></span>
+ should query instead of the server or servers listed in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>OPTIONS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term">-4</span></dt>
+<dd>
+ <p>
+ Use IPv4 only for query transport.
+ See also the <code class="option">-6</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-6</span></dt>
+<dd>
+ <p>
+ Use IPv6 only for query transport.
+ See also the <code class="option">-4</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-a</span></dt>
+<dd>
+ <p>
+ "All". The <code class="option">-a</code> option is normally equivalent
+ to <code class="option">-v -t <code class="literal">ANY</code></code>.
+ It also affects the behaviour of the <code class="option">-l</code>
+ list zone option.
+ </p>
+ </dd>
+<dt><span class="term">-c <em class="replaceable"><code>class</code></em></span></dt>
+<dd>
+ <p>
+ Query class: This can be used to lookup HS (Hesiod) or CH
+ (Chaosnet) class resource records. The default class is IN
+ (Internet).
+ </p>
+ </dd>
+<dt><span class="term">-C</span></dt>
+<dd>
+ <p>
+ Check consistency: <span class="command"><strong>host</strong></span> will query the
+ SOA records for zone <em class="parameter"><code>name</code></em> from all
+ the listed authoritative name servers for that zone. The
+ list of name servers is defined by the NS records that are
+ found for the zone.
+ </p>
+ </dd>
+<dt><span class="term">-d</span></dt>
+<dd>
+ <p>
+ Print debugging traces.
+ Equivalent to the <code class="option">-v</code> verbose option.
+ </p>
+ </dd>
+<dt><span class="term">-i</span></dt>
+<dd>
+ <p>
+ Obsolete.
+ Use the IP6.INT domain for reverse lookups of IPv6
+ addresses as defined in RFC1886 and deprecated in RFC4159.
+ The default is to use IP6.ARPA as specified in RFC3596.
+ </p>
+ </dd>
+<dt><span class="term">-l</span></dt>
+<dd>
+ <p>
+ List zone:
+ The <span class="command"><strong>host</strong></span> command performs a zone transfer of
+ zone <em class="parameter"><code>name</code></em> and prints out the NS,
+ PTR and address records (A/AAAA).
+ </p>
+ <p>
+ Together, the <code class="option">-l -a</code>
+ options print all records in the zone.
+ </p>
+ </dd>
+<dt><span class="term">-N <em class="replaceable"><code>ndots</code></em></span></dt>
+<dd>
+ <p>
+ The number of dots that have to be
+ in <em class="parameter"><code>name</code></em> for it to be considered
+ absolute. The default value is that defined using the
+ ndots statement in <code class="filename">/etc/resolv.conf</code>,
+ or 1 if no ndots statement is present. Names with fewer
+ dots are interpreted as relative names and will be
+ searched for in the domains listed in
+ the <span class="type">search</span> or <span class="type">domain</span> directive
+ in <code class="filename">/etc/resolv.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-r</span></dt>
+<dd>
+ <p>
+ Non-recursive query:
+ Setting this option clears the RD (recursion desired) bit
+ in the query. This should mean that the name server
+ receiving the query will not attempt to
+ resolve <em class="parameter"><code>name</code></em>.
+ The <code class="option">-r</code> option
+ enables <span class="command"><strong>host</strong></span> to mimic the behavior of a
+ name server by making non-recursive queries and expecting
+ to receive answers to those queries that can be
+ referrals to other name servers.
+ </p>
+ </dd>
+<dt><span class="term">-R <em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Number of retries for UDP queries:
+ If <em class="parameter"><code>number</code></em> is negative or zero, the
+ number of retries will default to 1. The default value is
+ 1, or the value of the <em class="parameter"><code>attempts</code></em>
+ option in <code class="filename">/etc/resolv.conf</code>, if set.
+ </p>
+ </dd>
+<dt><span class="term">-s</span></dt>
+<dd>
+ <p>
+ Do <span class="emphasis"><em>not</em></span> send the query to the next
+ nameserver if any server responds with a SERVFAIL
+ response, which is the reverse of normal stub resolver
+ behavior.
+ </p>
+ </dd>
+<dt><span class="term">-t <em class="replaceable"><code>type</code></em></span></dt>
+<dd>
+ <p>
+ Query type:
+ The <em class="parameter"><code>type</code></em> argument can be any
+ recognized query type: CNAME, NS, SOA, TXT, DNSKEY, AXFR, etc.
+ </p>
+ <p>
+ When no query type is specified, <span class="command"><strong>host</strong></span>
+ automatically selects an appropriate query type. By default, it
+ looks for A, AAAA, and MX records.
+ If the <code class="option">-C</code> option is given, queries will
+ be made for SOA records.
+ If <em class="parameter"><code>name</code></em> is a dotted-decimal IPv4
+ address or colon-delimited IPv6
+ address, <span class="command"><strong>host</strong></span> will query for PTR
+ records.
+ </p>
+ <p>
+ If a query type of IXFR is chosen the starting serial
+ number can be specified by appending an equal followed by
+ the starting serial number
+ (like <code class="option">-t <code class="literal">IXFR=12345678</code></code>).
+ </p>
+ </dd>
+<dt>
+<span class="term">-T, </span><span class="term">-U</span>
+</dt>
+<dd>
+ <p>
+ TCP/UDP:
+ By default, <span class="command"><strong>host</strong></span> uses UDP when making
+ queries. The <code class="option">-T</code> option makes it use a TCP
+ connection when querying the name server. TCP will be
+ automatically selected for queries that require it, such
+ as zone transfer (AXFR) requests. Type ANY queries default
+ to TCP but can be forced to UDP initially using <code class="option">-U</code>.
+ </p>
+ </dd>
+<dt><span class="term">-m <em class="replaceable"><code>flag</code></em></span></dt>
+<dd>
+ <p>
+ Memory usage debugging: the flag can
+ be <em class="parameter"><code>record</code></em>, <em class="parameter"><code>usage</code></em>,
+ or <em class="parameter"><code>trace</code></em>. You can specify
+ the <code class="option">-m</code> option more than once to set
+ multiple flags.
+ </p>
+ </dd>
+<dt><span class="term">-v</span></dt>
+<dd>
+ <p>
+ Verbose output.
+ Equivalent to the <code class="option">-d</code> debug option.
+ Verbose output can also be enabled by setting
+ the <em class="parameter"><code>debug</code></em> option
+ in <code class="filename">/etc/resolv.conf</code>.
+ </p>
+ </dd>
+<dt><span class="term">-V</span></dt>
+<dd>
+ <p>
+ Print the version number and exit.
+ </p>
+ </dd>
+<dt><span class="term">-w</span></dt>
+<dd>
+ <p>
+ Wait forever: The query timeout is set to the maximum possible.
+ See also the <code class="option">-W</code> option.
+ </p>
+ </dd>
+<dt><span class="term">-W <em class="replaceable"><code>wait</code></em></span></dt>
+<dd>
+ <p>
+ Timeout: Wait for up to <em class="parameter"><code>wait</code></em>
+ seconds for a reply. If <em class="parameter"><code>wait</code></em> is
+ less than one, the wait interval is set to one second.
+ </p>
+ <p>
+ By default, <span class="command"><strong>host</strong></span> will wait for 5
+ seconds for UDP responses and 10 seconds for TCP
+ connections. These defaults can be overridden by
+ the <em class="parameter"><code>timeout</code></em> option
+ in <code class="filename">/etc/resolv.conf</code>.
+ </p>
+ <p>
+ See also the <code class="option">-w</code> option.
+ </p>
+ </dd>
+</dl></div>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>IDN SUPPORT</h2>
+
+ <p>
+ If <span class="command"><strong>host</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span class="command"><strong>host</strong></span> appropriately converts character encoding of
+ domain name before sending a request to DNS server or displaying a
+ reply from the server.
+ If you'd like to turn off the IDN support for some reason, defines
+ the <code class="envar">IDN_DISABLE</code> environment variable.
+ The IDN support is disabled if the variable is set when
+ <span class="command"><strong>host</strong></span> runs.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/resolv.conf</code>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dig</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>.
+ </p>
+ </div>
+
+</div></body>
+</html>
diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h
new file mode 100644
index 0000000..cc37c55
--- /dev/null
+++ b/bin/dig/include/dig/dig.h
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#ifndef DIG_H
+#define DIG_H
+
+/*! \file */
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <dns/rdatalist.h>
+
+#include <dst/dst.h>
+
+#include <isc/buffer.h>
+#include <isc/bufferlist.h>
+#include <isc/formatcheck.h>
+#include <isc/lang.h>
+#include <isc/list.h>
+#include <isc/mem.h>
+#include <isc/print.h>
+#include <isc/sockaddr.h>
+#include <isc/socket.h>
+
+#define MXSERV 20
+#define MXNAME (DNS_NAME_MAXTEXT+1)
+#define MXRD 32
+/*% Buffer Size */
+#define BUFSIZE 512
+#define COMMSIZE 0xffff
+#ifndef RESOLV_CONF
+/*% location of resolve.conf */
+#define RESOLV_CONF "/etc/resolv.conf"
+#endif
+/*% output buffer */
+#define OUTPUTBUF 32767
+/*% Max RR Limit */
+#define MAXRRLIMIT 0xffffffff
+#define MAXTIMEOUT 0xffff
+/*% Max number of tries */
+#define MAXTRIES 0xffffffff
+/*% Max number of dots */
+#define MAXNDOTS 0xffff
+/*% Max number of ports */
+#define MAXPORT 0xffff
+/*% Max serial number */
+#define MAXSERIAL 0xffffffff
+
+/*% Default TCP Timeout */
+#define TCP_TIMEOUT 10
+/*% Default UDP Timeout */
+#define UDP_TIMEOUT 5
+
+#define SERVER_TIMEOUT 1
+
+#define LOOKUP_LIMIT 64
+/*%
+ * Lookup_limit is just a limiter, keeping too many lookups from being
+ * created. It's job is mainly to prevent the program from running away
+ * in a tight loop of constant lookups. It's value is arbitrary.
+ */
+
+/*
+ * Defaults for the sigchase suboptions. Consolidated here because
+ * these control the layout of dig_lookup_t (among other things).
+ */
+#ifdef DIG_SIGCHASE
+#ifndef DIG_SIGCHASE_BU
+#define DIG_SIGCHASE_BU 1
+#endif
+#ifndef DIG_SIGCHASE_TD
+#define DIG_SIGCHASE_TD 1
+#endif
+#endif
+
+ISC_LANG_BEGINDECLS
+
+typedef struct dig_lookup dig_lookup_t;
+typedef struct dig_query dig_query_t;
+typedef struct dig_server dig_server_t;
+#ifdef DIG_SIGCHASE
+typedef struct dig_message dig_message_t;
+#endif
+typedef ISC_LIST(dig_server_t) dig_serverlist_t;
+typedef struct dig_searchlist dig_searchlist_t;
+
+/*% The dig_lookup structure */
+struct dig_lookup {
+ bool
+ pending, /*%< Pending a successful answer */
+ waiting_connect,
+ doing_xfr,
+ ns_search_only, /*%< dig +nssearch, host -C */
+ identify, /*%< Append an "on server <foo>" message */
+ identify_previous_line, /*% Prepend a "Nameserver <foo>:"
+ message, with newline and tab */
+ ignore,
+ recurse,
+ aaonly,
+ adflag,
+ cdflag,
+ zflag,
+ trace, /*% dig +trace */
+ trace_root, /*% initial query for either +trace or +nssearch */
+ tcp_mode,
+ tcp_mode_set,
+ ip6_int,
+ comments,
+ stats,
+ section_question,
+ section_answer,
+ section_authority,
+ section_additional,
+ servfail_stops,
+ new_search,
+ need_search,
+ done_as_is,
+ besteffort,
+ dnssec,
+ expire,
+ sendcookie,
+ seenbadcookie,
+ badcookie,
+ nsid, /*% Name Server ID (RFC 5001) */
+ header_only,
+ ednsneg,
+ mapped,
+ print_unknown_format,
+ idnin,
+ idnout;
+#ifdef DIG_SIGCHASE
+bool sigchase;
+#if DIG_SIGCHASE_TD
+ bool do_topdown,
+ trace_root_sigchase,
+ rdtype_sigchaseset,
+ rdclass_sigchaseset;
+ /* Name we are going to validate RRset */
+ char textnamesigchase[MXNAME];
+#endif
+#endif
+
+ char textname[MXNAME]; /*% Name we're going to be looking up */
+ char cmdline[MXNAME];
+ dns_rdatatype_t rdtype;
+ dns_rdatatype_t qrdtype;
+#if DIG_SIGCHASE_TD
+ dns_rdatatype_t rdtype_sigchase;
+ dns_rdatatype_t qrdtype_sigchase;
+ dns_rdataclass_t rdclass_sigchase;
+#endif
+ dns_rdataclass_t rdclass;
+ bool rdtypeset;
+ bool rdclassset;
+ char name_space[BUFSIZE];
+ char oname_space[BUFSIZE];
+ isc_buffer_t namebuf;
+ isc_buffer_t onamebuf;
+ isc_buffer_t renderbuf;
+ char *sendspace;
+ dns_name_t *name;
+ isc_interval_t interval;
+ dns_message_t *sendmsg;
+ dns_name_t *oname;
+ ISC_LINK(dig_lookup_t) link;
+ ISC_LIST(dig_query_t) q;
+ ISC_LIST(dig_query_t) connecting;
+ dig_query_t *current_query;
+ dig_serverlist_t my_server_list;
+ dig_searchlist_t *origin;
+ dig_query_t *xfr_q;
+ uint32_t retries;
+ int nsfound;
+ uint16_t udpsize;
+ int16_t edns;
+ uint32_t ixfr_serial;
+ isc_buffer_t rdatabuf;
+ char rdatastore[MXNAME];
+ dst_context_t *tsigctx;
+ isc_buffer_t *querysig;
+ uint32_t msgcounter;
+ dns_fixedname_t fdomain;
+ isc_sockaddr_t *ecs_addr;
+ char *cookie;
+ dns_ednsopt_t *ednsopts;
+ unsigned int ednsoptscnt;
+ isc_dscp_t dscp;
+ unsigned int ednsflags;
+ dns_opcode_t opcode;
+ unsigned int eoferr;
+};
+
+/*% The dig_query structure */
+struct dig_query {
+ dig_lookup_t *lookup;
+ bool waiting_connect,
+ pending_free,
+ waiting_senddone,
+ first_pass,
+ first_soa_rcvd,
+ second_rr_rcvd,
+ first_repeat_rcvd,
+ recv_made,
+ warn_id,
+ timedout;
+ uint32_t first_rr_serial;
+ uint32_t second_rr_serial;
+ uint32_t msg_count;
+ uint32_t rr_count;
+ bool ixfr_axfr;
+ char *servname;
+ char *userarg;
+ isc_bufferlist_t sendlist,
+ recvlist,
+ lengthlist;
+ isc_buffer_t recvbuf,
+ lengthbuf,
+ slbuf;
+ char *recvspace,
+ lengthspace[4],
+ slspace[4];
+ isc_socket_t *sock;
+ ISC_LINK(dig_query_t) link;
+ ISC_LINK(dig_query_t) clink;
+ isc_sockaddr_t sockaddr;
+ isc_time_t time_sent;
+ isc_time_t time_recv;
+ uint64_t byte_count;
+ isc_buffer_t sendbuf;
+ isc_timer_t *timer;
+};
+
+struct dig_server {
+ char servername[MXNAME];
+ char userarg[MXNAME];
+ ISC_LINK(dig_server_t) link;
+};
+
+struct dig_searchlist {
+ char origin[MXNAME];
+ ISC_LINK(dig_searchlist_t) link;
+};
+#ifdef DIG_SIGCHASE
+struct dig_message {
+ dns_message_t *msg;
+ ISC_LINK(dig_message_t) link;
+};
+#endif
+
+typedef ISC_LIST(dig_searchlist_t) dig_searchlistlist_t;
+typedef ISC_LIST(dig_lookup_t) dig_lookuplist_t;
+
+/*
+ * Externals from dighost.c
+ */
+
+extern dig_lookuplist_t lookup_list;
+extern dig_serverlist_t server_list;
+extern dig_searchlistlist_t search_list;
+extern unsigned int extrabytes;
+
+extern bool check_ra, have_ipv4, have_ipv6, specified_source,
+ usesearch, showsearch, qr;
+extern in_port_t port;
+extern unsigned int timeout;
+extern isc_mem_t *mctx;
+extern int sendcount;
+extern int ndots;
+extern int lookup_counter;
+extern int exitcode;
+extern isc_sockaddr_t bind_address;
+extern char keynametext[MXNAME];
+extern char keyfile[MXNAME];
+extern char keysecret[MXNAME];
+extern dns_name_t *hmacname;
+extern unsigned int digestbits;
+#ifdef DIG_SIGCHASE
+extern char trustedkey[MXNAME];
+#endif
+extern dns_tsigkey_t *tsigkey;
+extern bool validated;
+extern isc_taskmgr_t *taskmgr;
+extern isc_task_t *global_task;
+extern bool free_now;
+extern bool debugging, debugtiming, memdebugging;
+extern bool keep_open;
+
+extern char *progname;
+extern int tries;
+extern int fatalexit;
+extern bool verbose;
+#ifdef WITH_IDNKIT
+extern int idnoptions;
+#endif
+
+/*
+ * Routines in dighost.c.
+ */
+isc_result_t
+get_address(char *host, in_port_t myport, isc_sockaddr_t *sockaddr);
+
+int
+getaddresses(dig_lookup_t *lookup, const char *host, isc_result_t *resultp);
+
+isc_result_t
+get_reverse(char *reverse, size_t len, char *value, bool ip6_int,
+ bool strict);
+
+ISC_PLATFORM_NORETURN_PRE void
+fatal(const char *format, ...)
+ISC_FORMAT_PRINTF(1, 2) ISC_PLATFORM_NORETURN_POST;
+
+void
+debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+check_result(isc_result_t result, const char *msg);
+
+bool
+setup_lookup(dig_lookup_t *lookup);
+
+void
+destroy_lookup(dig_lookup_t *lookup);
+
+void
+do_lookup(dig_lookup_t *lookup);
+
+void
+start_lookup(void);
+
+void
+onrun_callback(isc_task_t *task, isc_event_t *event);
+
+int
+dhmain(int argc, char **argv);
+
+void
+setup_libs(void);
+
+void
+setup_system(bool ipv4only, bool ipv6only);
+
+isc_result_t
+parse_uint(uint32_t *uip, const char *value, uint32_t max,
+ const char *desc);
+
+isc_result_t
+parse_xint(uint32_t *uip, const char *value, uint32_t max,
+ const char *desc);
+
+isc_result_t
+parse_netprefix(isc_sockaddr_t **sap, const char *value);
+
+void
+parse_hmac(const char *hmacstr);
+
+dig_lookup_t *
+requeue_lookup(dig_lookup_t *lookold, bool servers);
+
+dig_lookup_t *
+make_empty_lookup(void);
+
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, bool servers);
+
+dig_server_t *
+make_server(const char *servname, const char *userarg);
+
+void
+flush_server_list(void);
+
+void
+set_nameserver(char *opt);
+
+void
+clone_server_list(dig_serverlist_t src,
+ dig_serverlist_t *dest);
+
+void
+cancel_all(void);
+
+void
+destroy_libs(void);
+
+void
+set_search_domain(char *domain);
+
+#ifdef DIG_SIGCHASE
+void
+clean_trustedkey(void);
+#endif
+
+char *
+next_token(char **stringp, const char *delim);
+
+/*
+ * Routines to be defined in dig.c, host.c, and nslookup.c. and
+ * then assigned to the appropriate function pointer
+ */
+#ifdef DIG_SIGCHASE
+extern isc_result_t
+(*dighost_printrdataset)(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target);
+#endif
+
+extern isc_result_t
+(*dighost_printmessage)(dig_query_t *query, dns_message_t *msg, bool headers);
+/*%<
+ * Print the final result of the lookup.
+ */
+
+extern void
+(*dighost_received)(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query);
+/*%<
+ * Print a message about where and when the response
+ * was received from, like the final comment in the
+ * output of "dig".
+ */
+
+extern void
+(*dighost_trying)(char *frm, dig_lookup_t *lookup);
+
+extern void
+(*dighost_shutdown)(void);
+
+#ifdef DIG_SIGCHASE
+/* Chasing functions */
+dns_rdataset_t *
+chase_scanname(dns_name_t *name, dns_rdatatype_t type, dns_rdatatype_t covers);
+void
+chase_sig(dns_message_t *msg);
+#endif
+
+void save_opt(dig_lookup_t *lookup, char *code, char *value);
+
+void setup_file_key(void);
+void setup_text_key(void);
+
+/*
+ * Routines exported from dig.c for use by dig for iOS
+ */
+
+/*%<
+ * Call once only to set up libraries, parse global
+ * parameters and initial command line query parameters
+ */
+void
+dig_setup(int argc, char **argv);
+
+/*%<
+ * Call to supply new parameters for the next lookup
+ */
+void
+dig_query_setup(bool, bool, int argc, char **argv);
+
+/*%<
+ * set the main application event cycle running
+ */
+void
+dig_startup(void);
+
+/*%<
+ * Initiates the next lookup cycle
+ */
+void
+dig_query_start(void);
+
+/*%<
+ * Cleans up the application
+ */
+void
+dig_shutdown(void);
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/bin/dig/nslookup.1 b/bin/dig/nslookup.1
new file mode 100644
index 0000000..761b0d4
--- /dev/null
+++ b/bin/dig/nslookup.1
@@ -0,0 +1,294 @@
+.\" Copyright (C) 2004-2007, 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" This Source Code Form is subject to the terms of the Mozilla Public
+.\" License, v. 2.0. If a copy of the MPL was not distributed with this
+.\" file, You can obtain one at http://mozilla.org/MPL/2.0/.
+.\"
+.hy 0
+.ad l
+'\" t
+.\" Title: nslookup
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
+.\" Date: 2014-01-24
+.\" Manual: BIND9
+.\" Source: ISC
+.\" Language: English
+.\"
+.TH "NSLOOKUP" "1" "2014\-01\-24" "ISC" "BIND9"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nslookup \- query Internet name servers interactively
+.SH "SYNOPSIS"
+.HP \w'\fBnslookup\fR\ 'u
+\fBnslookup\fR [\fB\-option\fR] [name\ |\ \-] [server]
+.SH "DESCRIPTION"
+.PP
+\fBNslookup\fR
+is a program to query Internet domain name servers\&.
+\fBNslookup\fR
+has two modes: interactive and non\-interactive\&. Interactive mode allows the user to query name servers for information about various hosts and domains or to print a list of hosts in a domain\&. Non\-interactive mode is used to print just the name and requested information for a host or domain\&.
+.SH "ARGUMENTS"
+.PP
+Interactive mode is entered in the following cases:
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 1.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 1." 4.2
+.\}
+when no arguments are given (the default name server will be used)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04' 2.\h'+01'\c
+.\}
+.el \{\
+.sp -1
+.IP " 2." 4.2
+.\}
+when the first argument is a hyphen (\-) and the second argument is the host name or Internet address of a name server\&.
+.RE
+.PP
+Non\-interactive mode is used when the name or Internet address of the host to be looked up is given as the first argument\&. The optional second argument specifies the host name or address of a name server\&.
+.PP
+Options can also be specified on the command line if they precede the arguments and are prefixed with a hyphen\&. For example, to change the default query type to host information, and the initial timeout to 10 seconds, type:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+nslookup \-query=hinfo \-timeout=10
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+The
+\fB\-version\fR
+option causes
+\fBnslookup\fR
+to print the version number and immediately exits\&.
+.SH "INTERACTIVE COMMANDS"
+.PP
+\fBhost\fR [server]
+.RS 4
+Look up information for host using the current default server or using server, if specified\&. If host is an Internet address and the query type is A or PTR, the name of the host is returned\&. If host is a name and does not have a trailing period, the search list is used to qualify the name\&.
+.sp
+To look up a host not in the current domain, append a period to the name\&.
+.RE
+.PP
+\fBserver\fR \fIdomain\fR
+.RS 4
+.RE
+.PP
+\fBlserver\fR \fIdomain\fR
+.RS 4
+Change the default server to
+\fIdomain\fR;
+\fBlserver\fR
+uses the initial server to look up information about
+\fIdomain\fR, while
+\fBserver\fR
+uses the current default server\&. If an authoritative answer can\*(Aqt be found, the names of servers that might have the answer are returned\&.
+.RE
+.PP
+\fBroot\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBfinger\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBls\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBview\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBhelp\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fB?\fR
+.RS 4
+not implemented
+.RE
+.PP
+\fBexit\fR
+.RS 4
+Exits the program\&.
+.RE
+.PP
+\fBset\fR \fIkeyword\fR\fI[=value]\fR
+.RS 4
+This command is used to change state information that affects the lookups\&. Valid keywords are:
+.PP
+\fBall\fR
+.RS 4
+Prints the current values of the frequently used options to
+\fBset\fR\&. Information about the current default server and host is also printed\&.
+.RE
+.PP
+\fBclass=\fR\fIvalue\fR
+.RS 4
+Change the query class to one of:
+.PP
+\fBIN\fR
+.RS 4
+the Internet class
+.RE
+.PP
+\fBCH\fR
+.RS 4
+the Chaos class
+.RE
+.PP
+\fBHS\fR
+.RS 4
+the Hesiod class
+.RE
+.PP
+\fBANY\fR
+.RS 4
+wildcard
+.RE
+.sp
+The class specifies the protocol group of the information\&.
+.sp
+(Default = IN; abbreviation = cl)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBdebug\fR
+.RS 4
+Turn on or off the display of the full response packet and any intermediate response packets when searching\&.
+.sp
+(Default = nodebug; abbreviation =
+[no]deb)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBd2\fR
+.RS 4
+Turn debugging mode on or off\&. This displays more about what nslookup is doing\&.
+.sp
+(Default = nod2)
+.RE
+.PP
+\fBdomain=\fR\fIname\fR
+.RS 4
+Sets the search list to
+\fIname\fR\&.
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBsearch\fR
+.RS 4
+If the lookup request contains at least one period but doesn\*(Aqt end with a trailing period, append the domain names in the domain search list to the request until an answer is received\&.
+.sp
+(Default = search)
+.RE
+.PP
+\fBport=\fR\fIvalue\fR
+.RS 4
+Change the default TCP/UDP name server port to
+\fIvalue\fR\&.
+.sp
+(Default = 53; abbreviation = po)
+.RE
+.PP
+\fBquerytype=\fR\fIvalue\fR
+.RS 4
+.RE
+.PP
+\fBtype=\fR\fIvalue\fR
+.RS 4
+Change the type of the information query\&.
+.sp
+(Default = A; abbreviations = q, ty)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBrecurse\fR
+.RS 4
+Tell the name server to query other servers if it does not have the information\&.
+.sp
+(Default = recurse; abbreviation = [no]rec)
+.RE
+.PP
+\fBndots=\fR\fInumber\fR
+.RS 4
+Set the number of dots (label separators) in a domain that will disable searching\&. Absolute names always stop searching\&.
+.RE
+.PP
+\fBretry=\fR\fInumber\fR
+.RS 4
+Set the number of retries to number\&.
+.RE
+.PP
+\fBtimeout=\fR\fInumber\fR
+.RS 4
+Change the initial timeout interval for waiting for a reply to number seconds\&.
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBvc\fR
+.RS 4
+Always use a virtual circuit when sending requests to the server\&.
+.sp
+(Default = novc)
+.RE
+.PP
+\fB\fI[no]\fR\fR\fBfail\fR
+.RS 4
+Try the next nameserver if a nameserver responds with SERVFAIL or a referral (nofail) or terminate query (fail) on such a response\&.
+.sp
+(Default = nofail)
+.RE
+.sp
+.RE
+.SH "RETURN VALUES"
+.PP
+\fBnslookup\fR
+returns with an exit status of 1 if any query failed, and 0 otherwise\&.
+.SH "FILES"
+.PP
+/etc/resolv\&.conf
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBhost\fR(1),
+\fBnamed\fR(8)\&.
+.SH "AUTHOR"
+.PP
+\fBInternet Systems Consortium, Inc\&.\fR
+.SH "COPYRIGHT"
+.br
+Copyright \(co 2004-2007, 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c
new file mode 100644
index 0000000..59bd01b
--- /dev/null
+++ b/bin/dig/nslookup.c
@@ -0,0 +1,1037 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+#include <config.h>
+
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/event.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/task.h>
+#include <isc/netaddr.h>
+
+#include <dns/message.h>
+#include <dns/name.h>
+#include <dns/fixedname.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rdataset.h>
+#include <dns/rdatastruct.h>
+#include <dns/rdatatype.h>
+#include <dns/byaddr.h>
+
+#include <dig/dig.h>
+
+#if defined(HAVE_READLINE)
+#if defined(HAVE_EDIT_READLINE_READLINE_H)
+#include <edit/readline/readline.h>
+#if defined(HAVE_EDIT_READLINE_HISTORY_H)
+#include <edit/readline/history.h>
+#endif
+#elif defined(HAVE_EDITLINE_READLINE_H)
+#include <editline/readline.h>
+#elif defined(HAVE_READLINE_READLINE_H)
+#include <readline/readline.h>
+#if defined (HAVE_READLINE_HISTORY_H)
+#include <readline/history.h>
+#endif
+#endif
+#endif
+
+static bool short_form = true,
+ tcpmode = false, tcpmode_set = false,
+ identify = false, stats = true,
+ comments = true, section_question = true,
+ section_answer = true, section_authority = true,
+ section_additional = true, recurse = true,
+ aaonly = false, nofail = true,
+ default_lookups = true, a_noanswer = false;
+
+static bool interactive;
+
+static bool in_use = false;
+static char defclass[MXRD] = "IN";
+static char deftype[MXRD] = "A";
+static isc_event_t *global_event = NULL;
+static int query_error = 1, print_error = 0;
+
+static char domainopt[DNS_NAME_MAXTEXT];
+
+static const char *rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+static const char *rtypetext[] = {
+ "rtype_0 = ", /* 0 */
+ "internet address = ", /* 1 */
+ "nameserver = ", /* 2 */
+ "md = ", /* 3 */
+ "mf = ", /* 4 */
+ "canonical name = ", /* 5 */
+ "soa = ", /* 6 */
+ "mb = ", /* 7 */
+ "mg = ", /* 8 */
+ "mr = ", /* 9 */
+ "rtype_10 = ", /* 10 */
+ "protocol = ", /* 11 */
+ "name = ", /* 12 */
+ "hinfo = ", /* 13 */
+ "minfo = ", /* 14 */
+ "mail exchanger = ", /* 15 */
+ "text = ", /* 16 */
+ "rp = ", /* 17 */
+ "afsdb = ", /* 18 */
+ "x25 address = ", /* 19 */
+ "isdn address = ", /* 20 */
+ "rt = ", /* 21 */
+ "nsap = ", /* 22 */
+ "nsap_ptr = ", /* 23 */
+ "signature = ", /* 24 */
+ "key = ", /* 25 */
+ "px = ", /* 26 */
+ "gpos = ", /* 27 */
+ "has AAAA address ", /* 28 */
+ "loc = ", /* 29 */
+ "next = ", /* 30 */
+ "rtype_31 = ", /* 31 */
+ "rtype_32 = ", /* 32 */
+ "service = ", /* 33 */
+ "rtype_34 = ", /* 34 */
+ "naptr = ", /* 35 */
+ "kx = ", /* 36 */
+ "cert = ", /* 37 */
+ "v6 address = ", /* 38 */
+ "dname = ", /* 39 */
+ "rtype_40 = ", /* 40 */
+ "optional = " /* 41 */
+};
+
+#define N_KNOWN_RRTYPES (sizeof(rtypetext) / sizeof(rtypetext[0]))
+
+static void flush_lookup_list(void);
+static void getinput(isc_task_t *task, isc_event_t *event);
+
+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;
+}
+
+static void
+query_finished(void) {
+ isc_event_t *event = global_event;
+
+ flush_lookup_list();
+ debug("dighost_shutdown()");
+
+ if (!in_use) {
+ isc_app_shutdown();
+ return;
+ }
+
+ isc_task_send(global_task, &event);
+}
+
+static void
+printsoa(dns_rdata_t *rdata) {
+ dns_rdata_soa_t soa;
+ isc_result_t result;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ result = dns_rdata_tostruct(rdata, &soa, NULL);
+ check_result(result, "dns_rdata_tostruct");
+
+ dns_name_format(&soa.origin, namebuf, sizeof(namebuf));
+ printf("\torigin = %s\n", namebuf);
+ dns_name_format(&soa.contact, namebuf, sizeof(namebuf));
+ printf("\tmail addr = %s\n", namebuf);
+ printf("\tserial = %u\n", soa.serial);
+ printf("\trefresh = %u\n", soa.refresh);
+ printf("\tretry = %u\n", soa.retry);
+ printf("\texpire = %u\n", soa.expire);
+ printf("\tminimum = %u\n", soa.minimum);
+ dns_rdata_freestruct(&soa);
+}
+
+static void
+printaddr(dns_rdata_t *rdata) {
+ isc_result_t result;
+ char text[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ isc_buffer_t b;
+
+ isc_buffer_init(&b, text, sizeof(text));
+ result = dns_rdata_totext(rdata, NULL, &b);
+ check_result(result, "dns_rdata_totext");
+ printf("Address: %.*s\n", (int)isc_buffer_usedlength(&b),
+ (char *)isc_buffer_base(&b));
+}
+
+#ifdef DIG_SIGCHASE
+/* Just for compatibility : not use in host program */
+static isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target)
+{
+ UNUSED(owner_name);
+ UNUSED(rdataset);
+ UNUSED(target);
+ return(false);
+}
+#endif
+static void
+printrdata(dns_rdata_t *rdata) {
+ isc_result_t result;
+ isc_buffer_t *b = NULL;
+ unsigned int size = 1024;
+ bool done = false;
+
+ if (rdata->type < N_KNOWN_RRTYPES)
+ printf("%s", rtypetext[rdata->type]);
+ else
+ printf("rdata_%d = ", rdata->type);
+
+ while (!done) {
+ result = isc_buffer_allocate(mctx, &b, size);
+ if (result != ISC_R_SUCCESS)
+ check_result(result, "isc_buffer_allocate");
+ result = dns_rdata_totext(rdata, NULL, b);
+ if (result == ISC_R_SUCCESS) {
+ printf("%.*s\n", (int)isc_buffer_usedlength(b),
+ (char *)isc_buffer_base(b));
+ done = true;
+ } else if (result != ISC_R_NOSPACE)
+ check_result(result, "dns_rdata_totext");
+ isc_buffer_free(&b);
+ size *= 2;
+ }
+}
+
+static isc_result_t
+printsection(dig_query_t *query, dns_message_t *msg, bool headers,
+ dns_section_t section) {
+ isc_result_t result, loopresult;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ UNUSED(query);
+ UNUSED(headers);
+
+ debug("printsection()");
+
+ result = dns_message_firstname(msg, section);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, section,
+ &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);
+ switch (rdata.type) {
+ case dns_rdatatype_a:
+ case dns_rdatatype_aaaa:
+ if (section != DNS_SECTION_ANSWER)
+ goto def_short_section;
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("Name:\t%s\n", namebuf);
+ printaddr(&rdata);
+ break;
+ case dns_rdatatype_soa:
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("%s\n", namebuf);
+ printsoa(&rdata);
+ break;
+ default:
+ def_short_section:
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("%s\t", namebuf);
+ printrdata(&rdata);
+ break;
+ }
+ dns_rdata_reset(&rdata);
+ loopresult = dns_rdataset_next(rdataset);
+ }
+ }
+ result = dns_message_nextname(msg, section);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+detailsection(dig_query_t *query, dns_message_t *msg, bool headers,
+ dns_section_t section) {
+ isc_result_t result, loopresult;
+ dns_name_t *name;
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ char namebuf[DNS_NAME_FORMATSIZE];
+
+ UNUSED(query);
+
+ debug("detailsection()");
+
+ if (headers) {
+ switch (section) {
+ case DNS_SECTION_QUESTION:
+ puts(" QUESTIONS:");
+ break;
+ case DNS_SECTION_ANSWER:
+ puts(" ANSWERS:");
+ break;
+ case DNS_SECTION_AUTHORITY:
+ puts(" AUTHORITY RECORDS:");
+ break;
+ case DNS_SECTION_ADDITIONAL:
+ puts(" ADDITIONAL RECORDS:");
+ break;
+ }
+ }
+
+ result = dns_message_firstname(msg, section);
+ if (result == ISC_R_NOMORE)
+ return (ISC_R_SUCCESS);
+ else if (result != ISC_R_SUCCESS)
+ return (result);
+ for (;;) {
+ name = NULL;
+ dns_message_currentname(msg, section,
+ &name);
+ for (rdataset = ISC_LIST_HEAD(name->list);
+ rdataset != NULL;
+ rdataset = ISC_LIST_NEXT(rdataset, link)) {
+ if (section == DNS_SECTION_QUESTION) {
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("\t%s, ", namebuf);
+ dns_rdatatype_format(rdataset->type,
+ namebuf,
+ sizeof(namebuf));
+ printf("type = %s, ", namebuf);
+ dns_rdataclass_format(rdataset->rdclass,
+ namebuf,
+ sizeof(namebuf));
+ printf("class = %s\n", namebuf);
+ }
+ loopresult = dns_rdataset_first(rdataset);
+ while (loopresult == ISC_R_SUCCESS) {
+ dns_rdataset_current(rdataset, &rdata);
+
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf(" -> %s\n", namebuf);
+
+ switch (rdata.type) {
+ case dns_rdatatype_soa:
+ printsoa(&rdata);
+ break;
+ default:
+ printf("\t");
+ printrdata(&rdata);
+ }
+ dns_rdata_reset(&rdata);
+ printf("\tttl = %u\n", rdataset->ttl);
+ loopresult = dns_rdataset_next(rdataset);
+ }
+ }
+ result = dns_message_nextname(msg, section);
+ if (result == ISC_R_NOMORE)
+ break;
+ else if (result != ISC_R_SUCCESS) {
+ return (result);
+ }
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+received(unsigned int bytes, isc_sockaddr_t *from, dig_query_t *query)
+{
+ UNUSED(bytes);
+ UNUSED(from);
+ UNUSED(query);
+}
+
+static void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(frm);
+ UNUSED(lookup);
+}
+
+static void
+chase_cnamechain(dns_message_t *msg, dns_name_t *qname) {
+ isc_result_t result;
+ dns_rdataset_t *rdataset;
+ dns_rdata_cname_t cname;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ unsigned int i = msg->counts[DNS_SECTION_ANSWER];
+
+ while (i-- > 0) {
+ rdataset = NULL;
+ result = dns_message_findname(msg, DNS_SECTION_ANSWER, qname,
+ dns_rdatatype_cname, 0, NULL, &rdataset);
+ if (result != ISC_R_SUCCESS)
+ return;
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "dns_rdataset_first");
+ dns_rdata_reset(&rdata);
+ dns_rdataset_current(rdataset, &rdata);
+ result = dns_rdata_tostruct(&rdata, &cname, NULL);
+ check_result(result, "dns_rdata_tostruct");
+ dns_name_copy(&cname.cname, qname, NULL);
+ dns_rdata_freestruct(&cname);
+ }
+}
+
+static isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, bool headers) {
+ char servtext[ISC_SOCKADDR_FORMATSIZE];
+
+ /* I've we've gotten this far, we've reached a server. */
+ query_error = 0;
+
+ debug("printmessage()");
+
+ if(!default_lookups || query->lookup->rdtype == dns_rdatatype_a) {
+ isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext));
+ printf("Server:\t\t%s\n", query->userarg);
+ printf("Address:\t%s\n", servtext);
+
+ puts("");
+ }
+
+ if (!short_form) {
+ puts("------------");
+ /* detailheader(query, msg);*/
+ detailsection(query, msg, true, DNS_SECTION_QUESTION);
+ detailsection(query, msg, true, DNS_SECTION_ANSWER);
+ detailsection(query, msg, true, DNS_SECTION_AUTHORITY);
+ detailsection(query, msg, true, DNS_SECTION_ADDITIONAL);
+ puts("------------");
+ }
+
+ if (msg->rcode != 0) {
+ char nametext[DNS_NAME_FORMATSIZE];
+ dns_name_format(query->lookup->name,
+ nametext, sizeof(nametext));
+ printf("** server can't find %s: %s\n",
+ nametext, rcode_totext(msg->rcode));
+ debug("returning with rcode == 0");
+
+ /* the lookup failed */
+ print_error |= 1;
+ return (ISC_R_SUCCESS);
+ }
+
+ if ( default_lookups && query->lookup->rdtype == dns_rdatatype_a) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dig_lookup_t *lookup;
+ dns_fixedname_t fixed;
+ dns_name_t *name;
+
+ /* Add AAAA lookup. */
+ name = dns_fixedname_initname(&fixed);
+ dns_name_copy(query->lookup->name, name, NULL);
+ chase_cnamechain(msg, name);
+ dns_name_format(name, namestr, sizeof(namestr));
+ lookup = clone_lookup(query->lookup, false);
+ if (lookup != NULL) {
+ strlcpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_aaaa;
+ lookup->rdtypeset = true;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ }
+
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0 &&
+ ( !default_lookups || query->lookup->rdtype == dns_rdatatype_a) )
+ puts("Non-authoritative answer:");
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
+ printsection(query, msg, headers, DNS_SECTION_ANSWER);
+ else {
+ if (default_lookups && query->lookup->rdtype == dns_rdatatype_a)
+ a_noanswer = true;
+
+ else if (!default_lookups ||
+ (query->lookup->rdtype == dns_rdatatype_aaaa &&
+ a_noanswer ) )
+ printf("*** Can't find %s: No answer\n",
+ query->lookup->textname);
+ }
+
+ if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
+ (query->lookup->rdtype != dns_rdatatype_a) &&
+ (query->lookup->rdtype != dns_rdatatype_aaaa) ) {
+ puts("\nAuthoritative answers can be found from:");
+ printsection(query, msg, headers,
+ DNS_SECTION_AUTHORITY);
+ printsection(query, msg, headers,
+ DNS_SECTION_ADDITIONAL);
+ }
+ return (ISC_R_SUCCESS);
+}
+
+static void
+show_settings(bool full, bool serv_only) {
+ dig_server_t *srv;
+ isc_sockaddr_t sockaddr;
+ dig_searchlist_t *listent;
+ isc_result_t result;
+
+ srv = ISC_LIST_HEAD(server_list);
+
+ while (srv != NULL) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ result = get_address(srv->servername, port, &sockaddr);
+ check_result(result, "get_address");
+
+ isc_sockaddr_format(&sockaddr, sockstr, sizeof(sockstr));
+ printf("Default server: %s\nAddress: %s\n",
+ srv->userarg, sockstr);
+ if (!full)
+ return;
+ srv = ISC_LIST_NEXT(srv, link);
+ }
+ if (serv_only)
+ return;
+ printf("\nSet options:\n");
+ printf(" %s\t\t\t%s\t\t%s\n",
+ tcpmode ? "vc" : "novc",
+ short_form ? "nodebug" : "debug",
+ debugging ? "d2" : "nod2");
+ printf(" %s\t\t%s\n",
+ usesearch ? "search" : "nosearch",
+ recurse ? "recurse" : "norecurse");
+ printf(" timeout = %u\t\tretry = %d\tport = %u\tndots = %d\n",
+ timeout, tries, port, ndots);
+ printf(" querytype = %-8s\tclass = %s\n", deftype, defclass);
+ printf(" srchlist = ");
+ for (listent = ISC_LIST_HEAD(search_list);
+ listent != NULL;
+ listent = ISC_LIST_NEXT(listent, link)) {
+ printf("%s", listent->origin);
+ if (ISC_LIST_NEXT(listent, link) != NULL)
+ printf("/");
+ }
+ printf("\n");
+}
+
+static bool
+testtype(char *typetext) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+
+ tr.base = typetext;
+ tr.length = strlen(typetext);
+ result = dns_rdatatype_fromtext(&rdtype, &tr);
+ if (result == ISC_R_SUCCESS)
+ return (true);
+ else {
+ printf("unknown query type: %s\n", typetext);
+ return (false);
+ }
+}
+
+static bool
+testclass(char *typetext) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdataclass_t rdclass;
+
+ tr.base = typetext;
+ tr.length = strlen(typetext);
+ result = dns_rdataclass_fromtext(&rdclass, &tr);
+ if (result == ISC_R_SUCCESS)
+ return (true);
+ else {
+ printf("unknown query class: %s\n", typetext);
+ return (false);
+ }
+}
+
+static void
+set_port(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, 65535, "port");
+ if (result == ISC_R_SUCCESS)
+ port = (uint16_t) n;
+}
+
+static void
+set_timeout(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, UINT_MAX, "timeout");
+ if (result == ISC_R_SUCCESS)
+ timeout = n;
+}
+
+static void
+set_tries(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
+ if (result == ISC_R_SUCCESS)
+ tries = n;
+}
+
+static void
+set_ndots(const char *value) {
+ uint32_t n;
+ isc_result_t result = parse_uint(&n, value, 128, "ndots");
+ if (result == ISC_R_SUCCESS)
+ ndots = n;
+}
+
+static void
+version(void) {
+ fputs("nslookup " VERSION "\n", stderr);
+}
+
+static void
+setoption(char *opt) {
+ size_t l = strlen(opt);
+
+#define CHECKOPT(A, N) \
+ ((l >= N) && (l < sizeof(A)) && (strncasecmp(opt, A, l) == 0))
+
+ if (CHECKOPT("all", 3)) {
+ show_settings(true, false);
+ } else if (strncasecmp(opt, "class=", 6) == 0) {
+ if (testclass(&opt[6]))
+ strlcpy(defclass, &opt[6], sizeof(defclass));
+ } else if (strncasecmp(opt, "cl=", 3) == 0) {
+ if (testclass(&opt[3]))
+ strlcpy(defclass, &opt[3], sizeof(defclass));
+ } else if (strncasecmp(opt, "type=", 5) == 0) {
+ if (testtype(&opt[5])) {
+ strlcpy(deftype, &opt[5], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "ty=", 3) == 0) {
+ if (testtype(&opt[3])) {
+ strlcpy(deftype, &opt[3], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "querytype=", 10) == 0) {
+ if (testtype(&opt[10])) {
+ strlcpy(deftype, &opt[10], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "query=", 6) == 0) {
+ if (testtype(&opt[6])) {
+ strlcpy(deftype, &opt[6], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "qu=", 3) == 0) {
+ if (testtype(&opt[3])) {
+ strlcpy(deftype, &opt[3], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "q=", 2) == 0) {
+ if (testtype(&opt[2])) {
+ strlcpy(deftype, &opt[2], sizeof(deftype));
+ default_lookups = false;
+ }
+ } else if (strncasecmp(opt, "domain=", 7) == 0) {
+ strlcpy(domainopt, &opt[7], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = true;
+ } else if (strncasecmp(opt, "do=", 3) == 0) {
+ strlcpy(domainopt, &opt[3], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = true;
+ } else if (strncasecmp(opt, "port=", 5) == 0) {
+ set_port(&opt[5]);
+ } else if (strncasecmp(opt, "po=", 3) == 0) {
+ set_port(&opt[3]);
+ } else if (strncasecmp(opt, "timeout=", 8) == 0) {
+ set_timeout(&opt[8]);
+ } else if (strncasecmp(opt, "t=", 2) == 0) {
+ set_timeout(&opt[2]);
+ } else if (CHECKOPT("recurse", 3)) {
+ recurse = true;
+ } else if (CHECKOPT("norecurse", 5)) {
+ recurse = false;
+ } else if (strncasecmp(opt, "retry=", 6) == 0) {
+ set_tries(&opt[6]);
+ } else if (strncasecmp(opt, "ret=", 4) == 0) {
+ set_tries(&opt[4]);
+ } else if (CHECKOPT("defname", 3)) {
+ usesearch = true;
+ } else if (CHECKOPT("nodefname", 5)) {
+ usesearch = false;
+ } else if (CHECKOPT("vc", 2)) {
+ tcpmode = true;
+ tcpmode_set = true;
+ } else if (CHECKOPT("novc", 4)) {
+ tcpmode = false;
+ tcpmode_set = true;
+ } else if (CHECKOPT("debug", 3)) {
+ short_form = false;
+ showsearch = true;
+ } else if (CHECKOPT("nodebug", 5)) {
+ short_form = true;
+ showsearch = false;
+ } else if (CHECKOPT("d2", 2)) {
+ debugging = true;
+ } else if (CHECKOPT("nod2", 4)) {
+ debugging = false;
+ } else if (CHECKOPT("search", 3)) {
+ usesearch = true;
+ } else if (CHECKOPT("nosearch", 5)) {
+ usesearch = false;
+ } else if (CHECKOPT("sil", 3)) {
+ /* deprecation_msg = false; */
+ } else if (CHECKOPT("fail", 3)) {
+ nofail=false;
+ } else if (CHECKOPT("nofail", 5)) {
+ nofail=true;
+ } else if (strncasecmp(opt, "ndots=", 6) == 0) {
+ set_ndots(&opt[6]);
+ } else {
+ printf("*** Invalid option: %s\n", opt);
+ }
+}
+
+static void
+addlookup(char *opt) {
+ dig_lookup_t *lookup;
+ isc_result_t result;
+ isc_textregion_t tr;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ char store[MXNAME];
+
+ debug("addlookup()");
+
+ a_noanswer = false;
+
+ tr.base = deftype;
+ tr.length = strlen(deftype);
+ result = dns_rdatatype_fromtext(&rdtype, &tr);
+ if (result != ISC_R_SUCCESS) {
+ printf("unknown query type: %s\n", deftype);
+ rdclass = dns_rdatatype_a;
+ }
+ tr.base = defclass;
+ tr.length = strlen(defclass);
+ result = dns_rdataclass_fromtext(&rdclass, &tr);
+ if (result != ISC_R_SUCCESS) {
+ printf("unknown query class: %s\n", defclass);
+ rdclass = dns_rdataclass_in;
+ }
+ lookup = make_empty_lookup();
+ if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, true)
+ == ISC_R_SUCCESS) {
+ strlcpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = true;
+ } else {
+ strlcpy(lookup->textname, opt, sizeof(lookup->textname));
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = true;
+ }
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = true;
+ lookup->trace = false;
+ lookup->trace_root = lookup->trace;
+ lookup->ns_search_only = false;
+ lookup->identify = identify;
+ lookup->recurse = recurse;
+ lookup->aaonly = aaonly;
+ lookup->retries = tries;
+ lookup->udpsize = 0;
+ lookup->comments = comments;
+ if (lookup->rdtype == dns_rdatatype_any && !tcpmode_set)
+ lookup->tcp_mode = true;
+ else
+ lookup->tcp_mode = tcpmode;
+ lookup->stats = stats;
+ lookup->section_question = section_question;
+ lookup->section_answer = section_answer;
+ lookup->section_authority = section_authority;
+ lookup->section_additional = section_additional;
+ lookup->new_search = true;
+ if (nofail)
+ lookup->servfail_stops = false;
+ ISC_LIST_INIT(lookup->q);
+ ISC_LINK_INIT(lookup, link);
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ lookup->origin = NULL;
+ ISC_LIST_INIT(lookup->my_server_list);
+ debug("looking up %s", lookup->textname);
+}
+
+static void
+do_next_command(char *input) {
+ char *ptr, *arg;
+
+ ptr = next_token(&input, " \t\r\n");
+ if (ptr == NULL)
+ return;
+ arg = next_token(&input, " \t\r\n");
+ if ((strcasecmp(ptr, "set") == 0) &&
+ (arg != NULL))
+ setoption(arg);
+ else if ((strcasecmp(ptr, "server") == 0) ||
+ (strcasecmp(ptr, "lserver") == 0)) {
+ isc_app_block();
+ set_nameserver(arg);
+ check_ra = false;
+ isc_app_unblock();
+ show_settings(true, true);
+ } else if (strcasecmp(ptr, "exit") == 0) {
+ in_use = false;
+ } else if (strcasecmp(ptr, "help") == 0 ||
+ strcasecmp(ptr, "?") == 0) {
+ printf("The '%s' command is not yet implemented.\n", ptr);
+ } else if (strcasecmp(ptr, "finger") == 0 ||
+ strcasecmp(ptr, "root") == 0 ||
+ strcasecmp(ptr, "ls") == 0 ||
+ strcasecmp(ptr, "view") == 0) {
+ printf("The '%s' command is not implemented.\n", ptr);
+ } else
+ addlookup(ptr);
+}
+
+static void
+get_next_command(void) {
+ char *buf;
+ char *ptr;
+
+ fflush(stdout);
+ buf = isc_mem_allocate(mctx, COMMSIZE);
+ if (buf == NULL)
+ fatal("memory allocation failure");
+ isc_app_block();
+ if (interactive) {
+#ifdef HAVE_READLINE
+ ptr = readline("> ");
+ if (ptr != NULL)
+ add_history(ptr);
+#else
+ fputs("> ", stderr);
+ fflush(stderr);
+ ptr = fgets(buf, COMMSIZE, stdin);
+#endif
+ } else
+ ptr = fgets(buf, COMMSIZE, stdin);
+ isc_app_unblock();
+ if (ptr == NULL) {
+ in_use = false;
+ } else
+ do_next_command(ptr);
+#ifdef HAVE_READLINE
+ if (interactive)
+ free(ptr);
+#endif
+ isc_mem_free(mctx, buf);
+}
+
+static void
+parse_args(int argc, char **argv) {
+ bool have_lookup = false;
+
+ usesearch = true;
+ for (argc--, argv++; argc > 0; argc--, argv++) {
+ debug("main parsing %s", argv[0]);
+ if (argv[0][0] == '-') {
+ if (strncasecmp(argv[0], "-ver", 4) == 0) {
+ version();
+ exit(0);
+ } else if (argv[0][1] != 0) {
+ setoption(&argv[0][1]);
+ } else
+ have_lookup = true;
+ } else {
+ if (!have_lookup) {
+ have_lookup = true;
+ in_use = true;
+ addlookup(argv[0]);
+ } else {
+ set_nameserver(argv[0]);
+ check_ra = false;
+ }
+ }
+ }
+}
+
+static void
+flush_lookup_list(void) {
+ dig_lookup_t *l, *lp;
+ dig_query_t *q, *qp;
+ dig_server_t *s, *sp;
+
+ lookup_counter = 0;
+ l = ISC_LIST_HEAD(lookup_list);
+ while (l != NULL) {
+ q = ISC_LIST_HEAD(l->q);
+ while (q != NULL) {
+ if (q->sock != NULL) {
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ isc_socket_detach(&q->sock);
+ }
+ if (ISC_LINK_LINKED(&q->recvbuf, link))
+ ISC_LIST_DEQUEUE(q->recvlist, &q->recvbuf,
+ link);
+ if (ISC_LINK_LINKED(&q->lengthbuf, link))
+ ISC_LIST_DEQUEUE(q->lengthlist, &q->lengthbuf,
+ link);
+ isc_buffer_invalidate(&q->recvbuf);
+ isc_buffer_invalidate(&q->lengthbuf);
+ qp = q;
+ q = ISC_LIST_NEXT(q, link);
+ ISC_LIST_DEQUEUE(l->q, qp, link);
+ isc_mem_free(mctx, qp);
+ }
+ s = ISC_LIST_HEAD(l->my_server_list);
+ while (s != NULL) {
+ sp = s;
+ s = ISC_LIST_NEXT(s, link);
+ ISC_LIST_DEQUEUE(l->my_server_list, sp, link);
+ isc_mem_free(mctx, sp);
+
+ }
+ if (l->sendmsg != NULL)
+ dns_message_destroy(&l->sendmsg);
+ lp = l;
+ l = ISC_LIST_NEXT(l, link);
+ ISC_LIST_DEQUEUE(lookup_list, lp, link);
+ isc_mem_free(mctx, lp);
+ }
+}
+
+static void
+getinput(isc_task_t *task, isc_event_t *event) {
+ UNUSED(task);
+ if (global_event == NULL)
+ global_event = event;
+ while (in_use) {
+ get_next_command();
+ if (ISC_LIST_HEAD(lookup_list) != NULL) {
+ start_lookup();
+ return;
+ }
+ }
+ isc_app_shutdown();
+}
+
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ interactive = isatty(0);
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ check_ra = true;
+
+ /* setup dighost callbacks */
+#ifdef DIG_SIGCHASE
+ dighost_printrdataset = printrdataset;
+#endif
+ dighost_printmessage = printmessage;
+ dighost_received = received;
+ dighost_trying = trying;
+ dighost_shutdown = query_finished;
+
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+
+ setup_libs();
+ progname = argv[0];
+
+ setup_system(false, false);
+ parse_args(argc, argv);
+ if (keyfile[0] != 0)
+ setup_file_key();
+ else if (keysecret[0] != 0)
+ setup_text_key();
+ if (domainopt[0] != '\0')
+ set_search_domain(domainopt);
+ if (in_use)
+ result = isc_app_onrun(mctx, global_task, onrun_callback,
+ NULL);
+ else
+ result = isc_app_onrun(mctx, global_task, getinput, NULL);
+ check_result(result, "isc_app_onrun");
+ in_use = !in_use;
+
+ (void)isc_app_run();
+
+ puts("");
+ debug("done, and starting to shut down");
+ if (global_event != NULL)
+ isc_event_free(&global_event);
+ cancel_all();
+ destroy_libs();
+ isc_app_finish();
+
+ return (query_error | print_error);
+}
diff --git a/bin/dig/nslookup.docbook b/bin/dig/nslookup.docbook
new file mode 100644
index 0000000..cc47aab
--- /dev/null
+++ b/bin/dig/nslookup.docbook
@@ -0,0 +1,501 @@
+<!--
+ - Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ -
+ - See the COPYRIGHT file distributed with this work for additional
+ - information regarding copyright ownership.
+-->
+
+<!--
+ - Copyright (c) 1985, 1989
+ - The Regents of the University of California. All rights reserved.
+ -
+ - Redistribution and use in source and binary forms, with or without
+ - modification, are permitted provided that the following conditions
+ - are met:
+ - 1. Redistributions of source code must retain the above copyright
+ - notice, this list of conditions and the following disclaimer.
+ - 2. Redistributions in binary form must reproduce the above copyright
+ - notice, this list of conditions and the following disclaimer in the
+ - documentation and/or other materials provided with the distribution.
+ - 3. Neither the name of the University nor the names of its contributors
+ - may be used to endorse or promote products derived from this software
+ - without specific prior written permission.
+ -
+ - THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ - ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ - SUCH DAMAGE.
+-->
+<!-- Converted by db4-upgrade version 1.0 -->
+<refentry xmlns:db="http://docbook.org/ns/docbook" version="5.0" xml:id="man.nslookup">
+ <info>
+ <date>2014-01-24</date>
+ </info>
+ <refentryinfo>
+ <corpname>ISC</corpname>
+ <corpauthor>Internet Systems Consortium, Inc.</corpauthor>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>nslookup</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo>BIND9</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>nslookup</refname>
+ <refpurpose>query Internet name servers interactively</refpurpose>
+ </refnamediv>
+
+ <docinfo>
+ <copyright>
+ <year>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2010</year>
+ <year>2013</year>
+ <year>2014</year>
+ <year>2015</year>
+ <year>2016</year>
+ <year>2017</year>
+ <year>2018</year>
+ <year>2019</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis sepchar=" ">
+ <command>nslookup</command>
+ <arg choice="opt" rep="norepeat"><option>-option</option></arg>
+ <arg choice="opt" rep="norepeat">name | -</arg>
+ <arg choice="opt" rep="norepeat">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsection><info><title>DESCRIPTION</title></info>
+
+ <para><command>Nslookup</command>
+ is a program to query Internet domain name servers. <command>Nslookup</command>
+ has two modes: interactive and non-interactive. Interactive mode allows
+ the user to query name servers for information about various hosts and
+ domains or to print a list of hosts in a domain. Non-interactive mode
+ is
+ used to print just the name and requested information for a host or
+ domain.
+ </para>
+ </refsection>
+
+ <refsection><info><title>ARGUMENTS</title></info>
+
+ <para>
+ Interactive mode is entered in the following cases:
+ <orderedlist numeration="loweralpha" inheritnum="ignore" continuation="restarts">
+ <listitem>
+ <para>
+ when no arguments are given (the default name server will be used)
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ when the first argument is a hyphen (-) and the second argument is
+ the host name or Internet address of a name server.
+ </para>
+ </listitem>
+ </orderedlist>
+ </para>
+
+ <para>
+ Non-interactive mode is used when the name or Internet address of the
+ host to be looked up is given as the first argument. The optional second
+ argument specifies the host name or address of a name server.
+ </para>
+
+ <para>
+ Options can also be specified on the command line if they precede the
+ arguments and are prefixed with a hyphen. For example, to
+ change the default query type to host information, and the initial
+ timeout to 10 seconds, type:
+ <!-- <informalexample> produces bad nroff. -->
+ <programlisting>
+nslookup -query=hinfo -timeout=10
+</programlisting>
+ <!-- </informalexample> -->
+ </para>
+ <para>
+ The <option>-version</option> option causes
+ <command>nslookup</command> to print the version
+ number and immediately exits.
+ </para>
+
+ </refsection>
+
+ <refsection><info><title>INTERACTIVE COMMANDS</title></info>
+
+ <variablelist>
+ <varlistentry>
+ <term><constant>host</constant> <optional>server</optional></term>
+ <listitem>
+ <para>
+ Look up information for host using the current default server or
+ using server, if specified. If host is an Internet address and
+ the query type is A or PTR, the name of the host is returned.
+ If host is a name and does not have a trailing period, the
+ search list is used to qualify the name.
+ </para>
+
+ <para>
+ To look up a host not in the current domain, append a period to
+ the name.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>server</constant> <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para/>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>lserver</constant> <replaceable class="parameter">domain</replaceable></term>
+ <listitem>
+ <para>
+ Change the default server to <replaceable>domain</replaceable>; <constant>lserver</constant> uses the initial
+ server to look up information about <replaceable>domain</replaceable>, while <constant>server</constant> uses
+ the current default server. If an authoritative answer can't be
+ found, the names of servers that might have the answer are
+ returned.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>root</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>finger</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ls</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>view</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>help</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>?</constant></term>
+ <listitem>
+ <para>
+ not implemented
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>exit</constant></term>
+ <listitem>
+ <para>
+ Exits the program.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>set</constant>
+ <replaceable>keyword<optional>=value</optional></replaceable></term>
+ <listitem>
+ <para>
+ This command is used to change state information that affects
+ the lookups. Valid keywords are:
+ <variablelist>
+ <varlistentry>
+ <term><constant>all</constant></term>
+ <listitem>
+ <para>
+ Prints the current values of the frequently used
+ options to <command>set</command>.
+ Information about the current default
+ server and host is also printed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>class=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the query class to one of:
+ <variablelist>
+ <varlistentry>
+ <term><constant>IN</constant></term>
+ <listitem>
+ <para>
+ the Internet class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>CH</constant></term>
+ <listitem>
+ <para>
+ the Chaos class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>HS</constant></term>
+ <listitem>
+ <para>
+ the Hesiod class
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><constant>ANY</constant></term>
+ <listitem>
+ <para>
+ wildcard
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ The class specifies the protocol group of the information.
+
+ </para>
+ <para>
+ (Default = IN; abbreviation = cl)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>debug</constant></term>
+ <listitem>
+ <para>
+ Turn on or off the display of the full response packet and
+ any intermediate response packets when searching.
+ </para>
+ <para>
+ (Default = nodebug; abbreviation = <optional>no</optional>deb)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>d2</constant></term>
+ <listitem>
+ <para>
+ Turn debugging mode on or off. This displays more about
+ what nslookup is doing.
+ </para>
+ <para>
+ (Default = nod2)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>domain=</constant><replaceable>name</replaceable></term>
+ <listitem>
+ <para>
+ Sets the search list to <replaceable>name</replaceable>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>search</constant></term>
+ <listitem>
+ <para>
+ If the lookup request contains at least one period but
+ doesn't end with a trailing period, append the domain
+ names in the domain search list to the request until an
+ answer is received.
+ </para>
+ <para>
+ (Default = search)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>port=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the default TCP/UDP name server port to <replaceable>value</replaceable>.
+ </para>
+ <para>
+ (Default = 53; abbreviation = po)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>querytype=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para/>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>type=</constant><replaceable>value</replaceable></term>
+ <listitem>
+ <para>
+ Change the type of the information query.
+ </para>
+ <para>
+ (Default = A; abbreviations = q, ty)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>recurse</constant></term>
+ <listitem>
+ <para>
+ Tell the name server to query other servers if it does not
+ have the
+ information.
+ </para>
+ <para>
+ (Default = recurse; abbreviation = [no]rec)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>ndots=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Set the number of dots (label separators) in a domain
+ that will disable searching. Absolute names always
+ stop searching.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>retry=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Set the number of retries to number.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant>timeout=</constant><replaceable>number</replaceable></term>
+ <listitem>
+ <para>
+ Change the initial timeout interval for waiting for a
+ reply to number seconds.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>vc</constant></term>
+ <listitem>
+ <para>
+ Always use a virtual circuit when sending requests to the
+ server.
+ </para>
+ <para>
+ (Default = novc)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><constant><replaceable><optional>no</optional></replaceable>fail</constant></term>
+ <listitem>
+ <para>
+ Try the next nameserver if a nameserver responds with
+ SERVFAIL or a referral (nofail) or terminate query
+ (fail) on such a response.
+ </para>
+ <para>
+ (Default = nofail)
+ </para>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+ </refsection>
+
+ <refsection><info><title>RETURN VALUES</title></info>
+ <para>
+ <command>nslookup</command> returns with an exit status of 1
+ if any query failed, and 0 otherwise.
+ </para>
+ </refsection>
+
+ <refsection><info><title>FILES</title></info>
+
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsection>
+
+ <refsection><info><title>SEE ALSO</title></info>
+
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>host</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+ </refsection>
+</refentry>
diff --git a/bin/dig/nslookup.html b/bin/dig/nslookup.html
new file mode 100644
index 0000000..d5b038b
--- /dev/null
+++ b/bin/dig/nslookup.html
@@ -0,0 +1,386 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+ - Copyright (C) 2004-2007, 2010, 2013-2019 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+<html lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nslookup</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry">
+<a name="man.nslookup"></a><div class="titlepage"></div>
+
+
+
+
+
+ <div class="refnamediv">
+<h2>Name</h2>
+<p>
+ nslookup
+ &#8212; query Internet name servers interactively
+ </p>
+</div>
+
+
+
+ <div class="refsynopsisdiv">
+<h2>Synopsis</h2>
+ <div class="cmdsynopsis"><p>
+ <code class="command">nslookup</code>
+ [<code class="option">-option</code>]
+ [name | -]
+ [server]
+ </p></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.7"></a><h2>DESCRIPTION</h2>
+
+ <p><span class="command"><strong>Nslookup</strong></span>
+ is a program to query Internet domain name servers. <span class="command"><strong>Nslookup</strong></span>
+ has two modes: interactive and non-interactive. Interactive mode allows
+ the user to query name servers for information about various hosts and
+ domains or to print a list of hosts in a domain. Non-interactive mode
+ is
+ used to print just the name and requested information for a host or
+ domain.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.8"></a><h2>ARGUMENTS</h2>
+
+ <p>
+ Interactive mode is entered in the following cases:
+ </p>
+<div class="orderedlist"><ol class="orderedlist" type="a">
+<li class="listitem">
+ <p>
+ when no arguments are given (the default name server will be used)
+ </p>
+ </li>
+<li class="listitem">
+ <p>
+ when the first argument is a hyphen (-) and the second argument is
+ the host name or Internet address of a name server.
+ </p>
+ </li>
+</ol></div>
+<p>
+ </p>
+
+ <p>
+ Non-interactive mode is used when the name or Internet address of the
+ host to be looked up is given as the first argument. The optional second
+ argument specifies the host name or address of a name server.
+ </p>
+
+ <p>
+ Options can also be specified on the command line if they precede the
+ arguments and are prefixed with a hyphen. For example, to
+ change the default query type to host information, and the initial
+ timeout to 10 seconds, type:
+
+ </p>
+<pre class="programlisting">
+nslookup -query=hinfo -timeout=10
+</pre>
+<p>
+
+ </p>
+ <p>
+ The <code class="option">-version</code> option causes
+ <span class="command"><strong>nslookup</strong></span> to print the version
+ number and immediately exits.
+ </p>
+
+ </div>
+
+ <div class="refsection">
+<a name="id-1.9"></a><h2>INTERACTIVE COMMANDS</h2>
+
+ <div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">host</code> [<span class="optional">server</span>]</span></dt>
+<dd>
+ <p>
+ Look up information for host using the current default server or
+ using server, if specified. If host is an Internet address and
+ the query type is A or PTR, the name of the host is returned.
+ If host is a name and does not have a trailing period, the
+ search list is used to qualify the name.
+ </p>
+
+ <p>
+ To look up a host not in the current domain, append a period to
+ the name.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">server</code> <em class="replaceable"><code>domain</code></em></span></dt>
+<dd>
+ <p></p>
+ </dd>
+<dt><span class="term"><code class="constant">lserver</code> <em class="replaceable"><code>domain</code></em></span></dt>
+<dd>
+ <p>
+ Change the default server to <em class="replaceable"><code>domain</code></em>; <code class="constant">lserver</code> uses the initial
+ server to look up information about <em class="replaceable"><code>domain</code></em>, while <code class="constant">server</code> uses
+ the current default server. If an authoritative answer can't be
+ found, the names of servers that might have the answer are
+ returned.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">root</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">finger</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">ls</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">view</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">help</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">?</code></span></dt>
+<dd>
+ <p>
+ not implemented
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">exit</code></span></dt>
+<dd>
+ <p>
+ Exits the program.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">set</code>
+ <em class="replaceable"><code>keyword[<span class="optional">=value</span>]</code></em></span></dt>
+<dd>
+ <p>
+ This command is used to change state information that affects
+ the lookups. Valid keywords are:
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">all</code></span></dt>
+<dd>
+ <p>
+ Prints the current values of the frequently used
+ options to <span class="command"><strong>set</strong></span>.
+ Information about the current default
+ server and host is also printed.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">class=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p>
+ Change the query class to one of:
+ </p>
+<div class="variablelist"><dl class="variablelist">
+<dt><span class="term"><code class="constant">IN</code></span></dt>
+<dd>
+ <p>
+ the Internet class
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">CH</code></span></dt>
+<dd>
+ <p>
+ the Chaos class
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">HS</code></span></dt>
+<dd>
+ <p>
+ the Hesiod class
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">ANY</code></span></dt>
+<dd>
+ <p>
+ wildcard
+ </p>
+ </dd>
+</dl></div>
+<p>
+ The class specifies the protocol group of the information.
+
+ </p>
+ <p>
+ (Default = IN; abbreviation = cl)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>debug</code></span></dt>
+<dd>
+ <p>
+ Turn on or off the display of the full response packet and
+ any intermediate response packets when searching.
+ </p>
+ <p>
+ (Default = nodebug; abbreviation = [<span class="optional">no</span>]deb)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>d2</code></span></dt>
+<dd>
+ <p>
+ Turn debugging mode on or off. This displays more about
+ what nslookup is doing.
+ </p>
+ <p>
+ (Default = nod2)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">domain=</code><em class="replaceable"><code>name</code></em></span></dt>
+<dd>
+ <p>
+ Sets the search list to <em class="replaceable"><code>name</code></em>.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>search</code></span></dt>
+<dd>
+ <p>
+ If the lookup request contains at least one period but
+ doesn't end with a trailing period, append the domain
+ names in the domain search list to the request until an
+ answer is received.
+ </p>
+ <p>
+ (Default = search)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">port=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p>
+ Change the default TCP/UDP name server port to <em class="replaceable"><code>value</code></em>.
+ </p>
+ <p>
+ (Default = 53; abbreviation = po)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">querytype=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p></p>
+ </dd>
+<dt><span class="term"><code class="constant">type=</code><em class="replaceable"><code>value</code></em></span></dt>
+<dd>
+ <p>
+ Change the type of the information query.
+ </p>
+ <p>
+ (Default = A; abbreviations = q, ty)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>recurse</code></span></dt>
+<dd>
+ <p>
+ Tell the name server to query other servers if it does not
+ have the
+ information.
+ </p>
+ <p>
+ (Default = recurse; abbreviation = [no]rec)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">ndots=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Set the number of dots (label separators) in a domain
+ that will disable searching. Absolute names always
+ stop searching.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">retry=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Set the number of retries to number.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant">timeout=</code><em class="replaceable"><code>number</code></em></span></dt>
+<dd>
+ <p>
+ Change the initial timeout interval for waiting for a
+ reply to number seconds.
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>vc</code></span></dt>
+<dd>
+ <p>
+ Always use a virtual circuit when sending requests to the
+ server.
+ </p>
+ <p>
+ (Default = novc)
+ </p>
+ </dd>
+<dt><span class="term"><code class="constant"><em class="replaceable"><code>[<span class="optional">no</span>]</code></em>fail</code></span></dt>
+<dd>
+ <p>
+ Try the next nameserver if a nameserver responds with
+ SERVFAIL or a referral (nofail) or terminate query
+ (fail) on such a response.
+ </p>
+ <p>
+ (Default = nofail)
+ </p>
+ </dd>
+</dl></div>
+<p>
+ </p>
+ </dd>
+</dl></div>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.10"></a><h2>RETURN VALUES</h2>
+ <p>
+ <span class="command"><strong>nslookup</strong></span> returns with an exit status of 1
+ if any query failed, and 0 otherwise.
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.11"></a><h2>FILES</h2>
+
+ <p><code class="filename">/etc/resolv.conf</code>
+ </p>
+ </div>
+
+ <div class="refsection">
+<a name="id-1.12"></a><h2>SEE ALSO</h2>
+
+ <p><span class="citerefentry">
+ <span class="refentrytitle">dig</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">host</span>(1)
+ </span>,
+ <span class="citerefentry">
+ <span class="refentrytitle">named</span>(8)
+ </span>.
+ </p>
+ </div>
+</div></body>
+</html>
diff --git a/bin/dig/win32/dig.dsp.in b/bin/dig/win32/dig.dsp.in
new file mode 100644
index 0000000..8e57707
--- /dev/null
+++ b/bin/dig/win32/dig.dsp.in
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="dig" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=dig - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak" CFG="dig - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "dig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/dig.exe"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/dig.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "dig - @PLATFORM@ Release"
+# Name "dig - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\dig.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=..\include\dig\dig.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/dig.dsw b/bin/dig/win32/dig.dsw
new file mode 100644
index 0000000..ae9c548
--- /dev/null
+++ b/bin/dig/win32/dig.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dig"=".\dig.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/dig.mak.in b/bin/dig/win32/dig.mak.in
new file mode 100644
index 0000000..10cdf75
--- /dev/null
+++ b/bin/dig/win32/dig.mak.in
@@ -0,0 +1,427 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on dig.dsp
+!IF "$(CFG)" == ""
+CFG=dig - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to dig - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "dig - @PLATFORM@ Release" && "$(CFG)" != "dig - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dig.mak" CFG="dig - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "dig - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\dig.exe"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\dig.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dig.obj"
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\dig.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dig.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dig.pdb" @MACHINE@ /out:"../../../Build/Release/dig.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dig.obj" \
+ "$(INTDIR)\dighost.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dig.obj"
+ -@erase "$(INTDIR)\dig.sbr"
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\dig.bsc"
+ -@erase "$(OUTDIR)\dig.pdb"
+ -@erase "..\..\..\Build\Debug\dig.exe"
+ -@erase "..\..\..\Build\Debug\dig.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\dig.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dig.sbr" \
+ "$(INTDIR)\dighost.sbr"
+
+"$(OUTDIR)\dig.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dig.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/dig.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dig.obj" \
+ "$(INTDIR)\dighost.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\dig.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("dig.dep")
+!INCLUDE "dig.dep"
+!ELSE
+!MESSAGE Warning: cannot find "dig.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release" || "$(CFG)" == "dig - @PLATFORM@ Debug"
+SOURCE=..\dig.c
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dig.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dig.obj" "$(INTDIR)\dig.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/dig.vcxproj.filters.in b/bin/dig/win32/dig.vcxproj.filters.in
new file mode 100644
index 0000000..1d92732
--- /dev/null
+++ b/bin/dig/win32/dig.vcxproj.filters.in
@@ -0,0 +1,27 @@
+<?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>
+ <ClInclude Include="..\include\dig\dig.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dig.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/dig.vcxproj.in b/bin/dig/win32/dig.vcxproj.in
new file mode 100644
index 0000000..2214a51
--- /dev/null
+++ b/bin/dig/win32/dig.vcxproj.in
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" 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>{F938F9B8-D395-4A40-BEC7-0122D289C692}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>dig</RootNamespace>
+ </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>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </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>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_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>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;@IDN_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@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>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\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>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;@IDN_LIB@ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\include\dig\dig.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dig.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/dig.vcxproj.user b/bin/dig/win32/dig.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/dig.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/dig/win32/dighost.dsp.in b/bin/dig/win32/dighost.dsp.in
new file mode 100644
index 0000000..33b7c8d
--- /dev/null
+++ b/bin/dig/win32/dighost.dsp.in
@@ -0,0 +1,113 @@
+# Microsoft Developer Studio Project File - Name="dighost" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Static-Link Library" 0x0104
+
+CFG=dighost - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "dighost.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "dighost.mak" CFG="dighost - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dighost - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE "dighost - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Static-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dighost - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "NDEBUG" @CRYPTO@ /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" @COPTY@ /FD /c /Fddighost
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /out:"Release/dighost.lib"
+
+!ELSEIF "$(CFG)" == "dighost - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" @CRYPTO@ /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR @COPTY@ /FD /GZ /c /Fddighost
+# SUBTRACT CPP /X
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32
+# ADD LINK32 /debug out:"Debug/dighost.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "dighost - @PLATFORM@ Release"
+# Name "dighost - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Group "Main Dns Lib"
+
+# PROP Default_Filter "c"
+# Begin Source File
+
+SOURCE=..\dighost.c
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/dighost.dsw b/bin/dig/win32/dighost.dsw
new file mode 100644
index 0000000..fdae6d4
--- /dev/null
+++ b/bin/dig/win32/dighost.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "dighost"=".\dighost.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/dighost.vcxproj.filters.in b/bin/dig/win32/dighost.vcxproj.filters.in
new file mode 100644
index 0000000..d108bfb
--- /dev/null
+++ b/bin/dig/win32/dighost.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="..\dighost.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/dighost.vcxproj.in b/bin/dig/win32/dighost.vcxproj.in
new file mode 100644
index 0000000..2380506
--- /dev/null
+++ b/bin/dig/win32/dighost.vcxproj.in
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" 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>{140DE800-E552-43CC-B0C7-A33A92E368CA}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>dighost</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </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>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>.\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_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>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\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>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@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>
+ <AdditionalIncludeDirectories>.\;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\include;..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\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>false</LinkTimeCodeGeneration>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dighost.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/dighost.vcxproj.user b/bin/dig/win32/dighost.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/dighost.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/dig/win32/host.dsp.in b/bin/dig/win32/host.dsp.in
new file mode 100644
index 0000000..adb48d5
--- /dev/null
+++ b/bin/dig/win32/host.dsp.in
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="host" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=host - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak" CFG="host - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "host - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/host.exe"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/host.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "host - @PLATFORM@ Release"
+# Name "host - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\host.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/host.dsw b/bin/dig/win32/host.dsw
new file mode 100644
index 0000000..e566e78
--- /dev/null
+++ b/bin/dig/win32/host.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "host"=".\host.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/host.mak.in b/bin/dig/win32/host.mak.in
new file mode 100644
index 0000000..2653ef0
--- /dev/null
+++ b/bin/dig/win32/host.mak.in
@@ -0,0 +1,427 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on host.dsp
+!IF "$(CFG)" == ""
+CFG=host - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to host - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "host - @PLATFORM@ Release" && "$(CFG)" != "host - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "host.mak" CFG="host - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "host - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\host.exe"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\host.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\host.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\host.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\host.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\host.pdb" @MACHINE@ /out:"../../../Build/Release/host.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\host.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\host.obj"
+ -@erase "$(INTDIR)\host.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\host.bsc"
+ -@erase "$(OUTDIR)\host.pdb"
+ -@erase "..\..\..\Build\Debug\host.exe"
+ -@erase "..\..\..\Build\Debug\host.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @IDN_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\host.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dighost.sbr" \
+ "$(INTDIR)\host.sbr"
+
+"$(OUTDIR)\host.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\host.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/host.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\host.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\host.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("host.dep")
+!INCLUDE "host.dep"
+!ELSE
+!MESSAGE Warning: cannot find "host.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release" || "$(CFG)" == "host - @PLATFORM@ Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\host.c
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+
+"$(INTDIR)\host.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\host.obj" "$(INTDIR)\host.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/host.vcxproj.filters.in b/bin/dig/win32/host.vcxproj.filters.in
new file mode 100644
index 0000000..56e7818
--- /dev/null
+++ b/bin/dig/win32/host.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="..\host.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/host.vcxproj.in b/bin/dig/win32/host.vcxproj.in
new file mode 100644
index 0000000..e909608
--- /dev/null
+++ b/bin/dig/win32/host.vcxproj.in
@@ -0,0 +1,110 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" 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>{BA1048A8-6961-4A20-BE12-08BE20611C9D}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>host</RootNamespace>
+ </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>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </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>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@_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>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <CompileAs>CompileAsC</CompileAs>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <OutputFile>..\..\..\Build\$(Configuration)\$(TargetName)$(TargetExt)</OutputFile>
+ <AdditionalLibraryDirectories>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@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>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@IDN_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\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>$(Configuration);..\..\..\lib\isc\win32\$(Configuration);..\..\..\lib\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>dighost.lib;@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\host.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/host.vcxproj.user b/bin/dig/win32/host.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/host.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/dig/win32/nslookup.dsp.in b/bin/dig/win32/nslookup.dsp.in
new file mode 100644
index 0000000..9c4800a
--- /dev/null
+++ b/bin/dig/win32/nslookup.dsp.in
@@ -0,0 +1,107 @@
+# Microsoft Developer Studio Project File - Name="nslookup" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "@PLATFORM@ (x86) Console Application" 0x0103
+
+CFG=nslookup - @PLATFORM@ Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nslookup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 @COPTX@ @COPTI@ /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD CPP /nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console @MACHINE@
+# ADD LINK32 @READLINE_LIB@ @IDN_LIB@ user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console @MACHINE@ /out:"../../../Build/Release/nslookup.exe"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" @COPTY@ /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u @COPTY@
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug @MACHINE@ /pdbtype:sept
+# ADD LINK32 @READLINE_LIBD@ @IDN_LIB@ user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug @MACHINE@ /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nslookup - @PLATFORM@ Release"
+# Name "nslookup - @PLATFORM@ Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=..\dighost.c
+# End Source File
+# Begin Source File
+
+SOURCE=..\nslookup.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/bin/dig/win32/nslookup.dsw b/bin/dig/win32/nslookup.dsw
new file mode 100644
index 0000000..0ff8c66
--- /dev/null
+++ b/bin/dig/win32/nslookup.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "nslookup"=".\nslookup.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/bin/dig/win32/nslookup.mak.in b/bin/dig/win32/nslookup.mak.in
new file mode 100644
index 0000000..233231e
--- /dev/null
+++ b/bin/dig/win32/nslookup.mak.in
@@ -0,0 +1,427 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on nslookup.dsp
+!IF "$(CFG)" == ""
+CFG=nslookup - @PLATFORM@ Debug
+!MESSAGE No configuration specified. Defaulting to nslookup - @PLATFORM@ Debug.
+!ENDIF
+
+!IF "$(CFG)" != "nslookup - @PLATFORM@ Release" && "$(CFG)" != "nslookup - @PLATFORM@ Debug"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "nslookup.mak" CFG="nslookup - @PLATFORM@ Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - @PLATFORM@ Release" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE "nslookup - @PLATFORM@ Debug" (based on "@PLATFORM@ (x86) Console Application")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+_VC_MANIFEST_INC=0
+_VC_MANIFEST_BASENAME=__VC80
+!ELSE
+_VC_MANIFEST_INC=1
+_VC_MANIFEST_BASENAME=__VC80.Debug
+!ENDIF
+
+####################################################
+# Specifying name of temporary resource file used only in incremental builds:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
+!else
+_VC_MANIFEST_AUTO_RES=
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_EXE - command to embed manifest in EXE:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
+
+!endif
+
+####################################################
+# _VC_MANIFEST_EMBED_DLL - command to embed manifest in DLL:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+#MT_SPECIAL_RETURN=1090650113
+#MT_SPECIAL_SWITCH=-notify_resource_update
+MT_SPECIAL_RETURN=0
+MT_SPECIAL_SWITCH=
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
+if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
+rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
+link $** /out:$@ $(LFLAGS)
+
+!else
+
+_VC_MANIFEST_EMBED_EXE= \
+if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
+
+!endif
+####################################################
+# _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily:
+
+!if "$(_VC_MANIFEST_INC)" == "1"
+
+_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
+ $(_VC_MANIFEST_BASENAME).auto.rc \
+ $(_VC_MANIFEST_BASENAME).auto.manifest
+
+!else
+
+_VC_MANIFEST_CLEAN=
+
+!endif
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\nslookup.exe"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Release" "libbind9 - @PLATFORM@ Release" "libisc - @PLATFORM@ Release" "libdns - @PLATFORM@ Release" "..\..\..\Build\Release\nslookup.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ ReleaseCLEAN" "libisc - @PLATFORM@ ReleaseCLEAN" "libbind9 - @PLATFORM@ ReleaseCLEAN" "liblwres - @PLATFORM@ ReleaseCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\nslookup.obj"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "..\..\..\Build\Release\nslookup.exe"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MD /W3 @COPTX@ @COPTI@ /O2 /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nslookup.pch" @COPTY@ /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/isccfg/win32/Release/libisccfg.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib @READLINE_LIB@ @IDN_LIB@ /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nslookup.pdb" @MACHINE@ /out:"../../../Build/Release/nslookup.exe"
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\nslookup.obj" \
+ "..\..\..\lib\dns\win32\Release\libdns.lib" \
+ "..\..\..\lib\isc\win32\Release\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Release\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Release\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Release\liblwres.lib"
+
+"..\..\..\Build\Release\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+OUTDIR=.\Debug
+INTDIR=.\Debug
+# Begin Custom Macros
+OutDir=.\Debug
+# End Custom Macros
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc"
+
+!ELSE
+
+ALL : "liblwres - @PLATFORM@ Debug" "libbind9 - @PLATFORM@ Debug" "libisc - @PLATFORM@ Debug" "libdns - @PLATFORM@ Debug" "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - @PLATFORM@ DebugCLEAN" "libisc - @PLATFORM@ DebugCLEAN" "libbind9 - @PLATFORM@ DebugCLEAN" "liblwres - @PLATFORM@ DebugCLEAN"
+!ELSE
+CLEAN :
+!ENDIF
+ -@erase "$(INTDIR)\dighost.obj"
+ -@erase "$(INTDIR)\dighost.sbr"
+ -@erase "$(INTDIR)\nslookup.obj"
+ -@erase "$(INTDIR)\nslookup.sbr"
+ -@erase "$(INTDIR)\vc60.idb"
+ -@erase "$(INTDIR)\vc60.pdb"
+ -@erase "$(OUTDIR)\nslookup.bsc"
+ -@erase "$(OUTDIR)\nslookup.pdb"
+ -@erase "..\..\..\Build\Debug\nslookup.exe"
+ -@erase "..\..\..\Build\Debug\nslookup.ilk"
+ -@$(_VC_MANIFEST_CLEAN)
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP_PROJ=/nologo /MDd /W3 /Gm @COPTX@ @COPTI@ /ZI /Od /I "./" /I "../include" /I "../../../" @LIBXML2_INC@ @OPENSSL_INC@ @READLINE_INC@ /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isccfg/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" @CRYPTO@ /D "WIN32" /D "USE_READLINE_STATIC" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR"$(INTDIR)\\" /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c
+BSC32=bscmake.exe
+BSC32_FLAGS=/nologo /o"$(OUTDIR)\nslookup.bsc"
+BSC32_SBRS= \
+ "$(INTDIR)\dighost.sbr" \
+ "$(INTDIR)\nslookup.sbr"
+
+"$(OUTDIR)\nslookup.bsc" : "$(OUTDIR)" $(BSC32_SBRS)
+ $(BSC32) @<<
+ $(BSC32_FLAGS) $(BSC32_SBRS)
+<<
+
+LINK32=link.exe
+LINK32_FLAGS=user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/isccfg/win32/Debug/libisccfg.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib @READLINE_LIBD@ @IDN_LIB@ /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nslookup.pdb" /debug @MACHINE@ /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept
+LINK32_OBJS= \
+ "$(INTDIR)\dighost.obj" \
+ "$(INTDIR)\nslookup.obj" \
+ "..\..\..\lib\dns\win32\Debug\libdns.lib" \
+ "..\..\..\lib\isc\win32\Debug\libisc.lib" \
+ "..\..\..\lib\isccfg\win32\Debug\libisccfg.lib" \
+ "..\..\..\lib\bind9\win32\Debug\libbind9.lib" \
+ "..\..\..\lib\lwres\win32\Debug\liblwres.lib"
+
+"..\..\..\Build\Debug\nslookup.exe" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+ $(_VC_MANIFEST_EMBED_EXE)
+
+!ENDIF
+
+.c{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.obj::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.c{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cpp{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+.cxx{$(INTDIR)}.sbr::
+ $(CPP) @<<
+ $(CPP_PROJ) $<
+<<
+
+
+!IF "$(NO_EXTERNAL_DEPS)" != "1"
+!IF EXISTS("nslookup.dep")
+!INCLUDE "nslookup.dep"
+!ELSE
+!MESSAGE Warning: cannot find "nslookup.dep"
+!ENDIF
+!ENDIF
+
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release" || "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nslookup.c
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+
+"$(INTDIR)\nslookup.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+
+"$(INTDIR)\nslookup.obj" "$(INTDIR)\nslookup.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"libdns - @PLATFORM@ Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"libdns - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"libisc - @PLATFORM@ Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"libisc - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"libbind9 - @PLATFORM@ Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"libbind9 - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - @PLATFORM@ Release"
+
+"liblwres - @PLATFORM@ Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - @PLATFORM@ Debug"
+
+"liblwres - @PLATFORM@ Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - @PLATFORM@ DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - @PLATFORM@ Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+
+!ENDIF
+
+####################################################
+# Commands to generate initial empty manifest file and the RC file
+# that references it, and for generating the .res file:
+
+$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
+
+$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
+ type <<$@
+#include <winuser.h>
+1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
+<< KEEP
+
+$(_VC_MANIFEST_BASENAME).auto.manifest :
+ type <<$@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
+</assembly>
+<< KEEP
diff --git a/bin/dig/win32/nslookup.vcxproj.filters.in b/bin/dig/win32/nslookup.vcxproj.filters.in
new file mode 100644
index 0000000..7f4756e
--- /dev/null
+++ b/bin/dig/win32/nslookup.vcxproj.filters.in
@@ -0,0 +1,21 @@
+<?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="..\dighost.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\nslookup.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/bin/dig/win32/nslookup.vcxproj.in b/bin/dig/win32/nslookup.vcxproj.in
new file mode 100644
index 0000000..5c338ae
--- /dev/null
+++ b/bin/dig/win32/nslookup.vcxproj.in
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" 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>{C15A6E1A-94CE-4686-99F9-6BC5FD623EB5}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>nslookup</RootNamespace>
+ </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>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </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>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <LinkIncremental>false</LinkIncremental>
+ <OutDir>..\..\..\Build\$(Configuration)\</OutDir>
+ <IntDir>.\$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|@PLATFORM@'">
+ <ClCompile>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@USE_READLINE_STATIC;_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>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\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\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@READLINE_LIBD@@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|@PLATFORM@'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>@INTRINSIC@</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;@CRYPTO@USE_READLINE_STATIC;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>
+ <AdditionalIncludeDirectories>.\;..\include;..\..\..\;@LIBXML2_INC@@OPENSSL_INC@@READLINE_INC@..\..\..\lib\isc\win32;..\..\..\lib\isc\win32\include;..\..\..\lib\isc\include;..\..\..\lib\isccfg\include;..\..\..\lib\dns\include;..\..\..\lib\bind9\include;..\..\..\lib\lwres\win32\include;..\..\..\lib\lwres\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\isccfg\win32\$(Configuration);..\..\..\lib\dns\win32\$(Configuration);..\..\..\lib\bind9\win32\$(Configuration);..\..\..\lib\lwres\win32\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
+ <AdditionalDependencies>@READLINE_LIB@@IDN_LIB@libisc.lib;libisccfg.lib;libdns.lib;libbind9.lib;liblwres.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\dighost.c" />
+ <ClCompile Include="..\nslookup.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/bin/dig/win32/nslookup.vcxproj.user b/bin/dig/win32/nslookup.vcxproj.user
new file mode 100644
index 0000000..695b5c7
--- /dev/null
+++ b/bin/dig/win32/nslookup.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