summaryrefslogtreecommitdiffstats
path: root/bin/dig
diff options
context:
space:
mode:
authorMartin Nagy <mnagy@redhat.com>2009-02-11 20:37:59 +0100
committerMartin Nagy <mnagy@redhat.com>2009-02-11 20:37:59 +0100
commitf50ae72ec3417cae55dd4e085991c01af9fdc5f1 (patch)
tree0e36c9a3320f6d068df93d3ff6d84b821d23db40 /bin/dig
downloadbind_dynamic-f50ae72ec3417cae55dd4e085991c01af9fdc5f1.tar.gz
bind_dynamic-f50ae72ec3417cae55dd4e085991c01af9fdc5f1.tar.xz
bind_dynamic-f50ae72ec3417cae55dd4e085991c01af9fdc5f1.zip
Initial commitstart
Diffstat (limited to 'bin/dig')
-rw-r--r--bin/dig/Makefile.in101
-rw-r--r--bin/dig/dig.1568
-rw-r--r--bin/dig/dig.c1813
-rw-r--r--bin/dig/dig.docbook952
-rw-r--r--bin/dig/dig.html637
-rw-r--r--bin/dig/dighost.c5420
-rw-r--r--bin/dig/host.1219
-rw-r--r--bin/dig/host.c862
-rw-r--r--bin/dig/host.docbook278
-rw-r--r--bin/dig/host.html212
-rw-r--r--bin/dig/include/dig/dig.h406
-rw-r--r--bin/dig/nslookup.1252
-rw-r--r--bin/dig/nslookup.c891
-rw-r--r--bin/dig/nslookup.docbook496
-rw-r--r--bin/dig/nslookup.html307
-rw-r--r--bin/dig/win32/dig.dsp107
-rw-r--r--bin/dig/win32/dig.dsw29
-rw-r--r--bin/dig/win32/dig.mak425
-rw-r--r--bin/dig/win32/dighost.dsp113
-rw-r--r--bin/dig/win32/dighost.dsw29
-rw-r--r--bin/dig/win32/host.dsp103
-rw-r--r--bin/dig/win32/host.dsw29
-rw-r--r--bin/dig/win32/host.mak425
-rw-r--r--bin/dig/win32/nslookup.dsp107
-rw-r--r--bin/dig/win32/nslookup.dsw29
-rw-r--r--bin/dig/win32/nslookup.mak425
26 files changed, 15235 insertions, 0 deletions
diff --git a/bin/dig/Makefile.in b/bin/dig/Makefile.in
new file mode 100644
index 0000000..bc9d34f
--- /dev/null
+++ b/bin/dig/Makefile.in
@@ -0,0 +1,101 @@
+# Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC")
+# Copyright (C) 2000-2002 Internet Software Consortium.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+# PERFORMANCE OF THIS SOFTWARE.
+
+# $Id: Makefile.in,v 1.41 2007/06/19 23:46:59 tbox Exp $
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+top_srcdir = @top_srcdir@
+
+@BIND9_VERSION@
+
+@BIND9_MAKE_INCLUDES@
+
+CINCLUDES = -I${srcdir}/include ${DNS_INCLUDES} ${BIND9_INCLUDES} \
+ ${ISC_INCLUDES} ${LWRES_INCLUDES}
+
+CDEFINES = -DVERSION=\"${VERSION}\"
+CWARNINGS =
+
+ISCCFGLIBS = ../../lib/isccfg/libisccfg.@A@
+DNSLIBS = ../../lib/dns/libdns.@A@ @DNS_CRYPTO_LIBS@
+BIND9LIBS = ../../lib/bind9/libbind9.@A@
+ISCLIBS = ../../lib/isc/libisc.@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} ${DNSLIBS} ${BIND9LIBS} ${ISCLIBS} \
+ ${ISCCFGLIBS} @IDNLIBS@ @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}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ dig.@O@ dighost.@O@ ${UOBJS} ${LIBS}
+
+host@EXEEXT@: host.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ host.@O@ dighost.@O@ ${UOBJS} ${LIBS}
+
+nslookup@EXEEXT@: nslookup.@O@ dighost.@O@ ${UOBJS} ${DEPLIBS}
+ ${LIBTOOL_MODE_LINK} ${PURIFY} ${CC} ${CFLAGS} ${LDFLAGS} -o $@ \
+ nslookup.@O@ dighost.@O@ ${UOBJS} ${LIBS}
+
+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; \
+ done
diff --git a/bin/dig/dig.1 b/bin/dig/dig.1
new file mode 100644
index 0000000..436740b
--- /dev/null
+++ b/bin/dig/dig.1
@@ -0,0 +1,568 @@
+.\" Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2003 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: dig.1,v 1.50 2008/10/14 01:11:35 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: dig
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "DIG" "1" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+dig \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP 4
+\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\-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 4
+\fBdig\fR [\fB\-h\fR]
+.HP 4
+\fBdig\fR [global\-queryopt...] [query...]
+.SH "DESCRIPTION"
+.PP
+\fBdig\fR
+(domain information groper) 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
+\fI/etc/resolv.conf\fR.
+.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
+\fI${HOME}/.digrc\fR. 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 domains 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
+.RS 4
+.nf
+ dig @server name type
+.fi
+.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. If no
+\fIserver\fR
+argument is provided,
+\fBdig\fR
+consults
+\fI/etc/resolv.conf\fR
+and queries the name servers listed there. 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
+The
+\fB\-b\fR
+option sets the source IP address of the query to
+\fIaddress\fR. This must be a valid address on one of the host's network interfaces or "0.0.0.0" or "::". An optional port may be specified by appending "#<port>"
+.PP
+The default query class (IN for internet) is overridden by the
+\fB\-c\fR
+option.
+\fIclass\fR
+is any valid class, such as HS for Hesiod records or CH for Chaosnet records.
+.PP
+The
+\fB\-f\fR
+option makes
+\fBdig \fR
+operate in batch mode by reading a list of lookup requests to process from the file
+\fIfilename\fR. The file contains a number of queries, one per line. Each entry in the file should be organized in the same way they would be presented as queries to
+\fBdig\fR
+using the command\-line interface.
+.PP
+The
+\fB\-m\fR
+option enables memory usage debugging.
+.PP
+If a non\-standard port number is to be queried, the
+\fB\-p\fR
+option is used.
+\fIport#\fR
+is the port number that
+\fBdig\fR
+will send its queries instead of the standard DNS port number 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.
+.PP
+The
+\fB\-4\fR
+option forces
+\fBdig\fR
+to only use IPv4 query transport. The
+\fB\-6\fR
+option forces
+\fBdig\fR
+to only use IPv6 query transport.
+.PP
+The
+\fB\-t\fR
+option sets the query type to
+\fItype\fR. It can be any valid query type which is supported in BIND 9. 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,
+\fItype\fR
+is set to
+ixfr=N. The incremental zone transfer will contain the changes made to the zone since the serial number in the zone's SOA record was
+\fIN\fR.
+.PP
+The
+\fB\-q\fR
+option sets the query name to
+\fIname\fR. This useful do distinguish the
+\fIname\fR
+from other arguments.
+.PP
+Reverse lookups \(em mapping addresses to names \(em are simplified by the
+\fB\-x\fR
+option.
+\fIaddr\fR
+is an IPv4 address in dotted\-decimal notation, or a colon\-delimited IPv6 address. When this option 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
+11.12.13.10.in\-addr.arpa
+and sets the query type and class to PTR and IN respectively. By default, IPv6 addresses are looked up using nibble format under the IP6.ARPA domain. To use the older RFC1886 method using the IP6.INT domain specify the
+\fB\-i\fR
+option. Bit string labels (RFC2874) are now experimental and are not attempted.
+.PP
+To sign the DNS queries sent by
+\fBdig\fR
+and their responses using transaction signatures (TSIG), specify a TSIG key file using the
+\fB\-k\fR
+option. You can also specify the TSIG key itself on the command line using the
+\fB\-y\fR
+option;
+\fIhmac\fR
+is the type of the TSIG, default HMAC\-MD5,
+\fIname\fR
+is the name of the TSIG key and
+\fIkey\fR
+is the actual key. The key is a base\-64 encoded string, typically generated by
+\fBdnssec\-keygen\fR(8). Caution should be taken when using the
+\fB\-y\fR
+option on multi\-user systems as the key can be visible in the output from
+\fBps\fR(1)
+or in the shell's history file. 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
+\fInamed.conf\fR.
+.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. The query options are:
+.PP
+\fB+[no]tcp\fR
+.RS 4
+Use [do not use] TCP when querying name servers. The default behavior is to use UDP unless an AXFR or IXFR query is requested, in which case a TCP connection is used.
+.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]ignore\fR
+.RS 4
+Ignore truncation in UDP responses instead of retrying with TCP. By default, TCP retries are performed.
+.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
+\fI/etc/resolv.conf\fR, and enable search list processing as if the
+\fI+search\fR
+option were given.
+.RE
+.PP
+\fB+[no]search\fR
+.RS 4
+Use [do not use] the search list defined by the searchlist or domain directive in
+\fIresolv.conf\fR
+(if any). The search list is not used by default.
+.RE
+.PP
+\fB+[no]showsearch\fR
+.RS 4
+Perform [do not perform] a search showing intermediate results.
+.RE
+.PP
+\fB+[no]defname\fR
+.RS 4
+Deprecated, treated as a synonym for
+\fI+[no]search\fR
+.RE
+.PP
+\fB+[no]aaonly\fR
+.RS 4
+Sets the "aa" flag in the query.
+.RE
+.PP
+\fB+[no]aaflag\fR
+.RS 4
+A synonym for
+\fI+[no]aaonly\fR.
+.RE
+.PP
+\fB+[no]adflag\fR
+.RS 4
+Set [do not set] the AD (authentic data) bit in the query. The AD bit currently has a standard meaning only in responses, not in queries, but the ability to set the bit in the query is provided for completeness.
+.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]cl\fR
+.RS 4
+Display [do not display] the CLASS when printing the record.
+.RE
+.PP
+\fB+[no]ttlid\fR
+.RS 4
+Display [do not display] the TTL when printing the record.
+.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+[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]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.
+.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]short\fR
+.RS 4
+Provide a terse answer. The default is to print the answer in a verbose form.
+.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]comments\fR
+.RS 4
+Toggle the display of comment lines in the output. The default is to print comments.
+.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]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]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]additional\fR
+.RS 4
+Display [do not display] the additional section of a reply. The default is to display it.
+.RE
+.PP
+\fB+[no]all\fR
+.RS 4
+Set or clear all display flags.
+.RE
+.PP
+\fB+time=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+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+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+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
+\fI/etc/resolv.conf\fR, 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
+\fI/etc/resolv.conf\fR.
+.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+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.
+.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+[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]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+[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+[no]sigchase\fR
+.RS 4
+Chase DNSSEC signature chains. Requires dig be compiled with \-DDIG_SIGCHASE.
+.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
+\fI/etc/trusted\-key.key\fR
+then
+\fItrusted\-key.key\fR
+in the current directory.
+.sp
+Requires dig be compiled with \-DDIG_SIGCHASE.
+.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.
+.RE
+.PP
+\fB+[no]nsid\fR
+.RS 4
+Include an EDNS name server ID request when sending a query.
+.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
+.RS 4
+.nf
+dig +qr www.isc.org any \-x 127.0.0.1 isc.org ns +noqr
+.fi
+.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'd 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
+\fBdig\fR
+runs.
+.SH "FILES"
+.PP
+\fI/etc/resolv.conf\fR
+.PP
+\fI${HOME}/.digrc\fR
+.SH "SEE ALSO"
+.PP
+\fBhost\fR(1),
+\fBnamed\fR(8),
+\fBdnssec\-keygen\fR(8),
+RFC1035.
+.SH "BUGS"
+.PP
+There are probably too many query options.
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2003 Internet Software Consortium.
+.br
diff --git a/bin/dig/dig.c b/bin/dig/dig.c
new file mode 100644
index 0000000..7f9377d
--- /dev/null
+++ b/bin/dig/dig.c
@@ -0,0 +1,1813 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dig.c,v 1.225 2008/10/28 23:47:06 tbox Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+
+#include <isc/app.h>
+#include <isc/netaddr.h>
+#include <isc/parseint.h>
+#include <isc/print.h>
+#include <isc/string.h>
+#include <isc/util.h>
+#include <isc/task.h>
+
+#include <dns/byaddr.h>
+#include <dns/fixedname.h>
+#include <dns/masterdump.h>
+#include <dns/message.h>
+#include <dns/name.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 <bind9/getaddresses.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 isc_boolean_t short_form = ISC_FALSE, printcmd = ISC_TRUE,
+ ip6_int = ISC_FALSE, plusquest = ISC_FALSE, pluscomm = ISC_FALSE,
+ multiline = ISC_FALSE, nottl = ISC_FALSE, noclass = ISC_FALSE;
+
+/*% opcode text */
+static const char * const opcodetext[] = {
+ "QUERY",
+ "IQUERY",
+ "STATUS",
+ "RESERVED3",
+ "NOTIFY",
+ "UPDATE",
+ "RESERVED6",
+ "RESERVED7",
+ "RESERVED8",
+ "RESERVED9",
+ "RESERVED10",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15"
+};
+
+/*% return code text */
+static const char * const rcodetext[] = {
+ "NOERROR",
+ "FORMERR",
+ "SERVFAIL",
+ "NXDOMAIN",
+ "NOTIMP",
+ "REFUSED",
+ "YXDOMAIN",
+ "YXRRSET",
+ "NXRRSET",
+ "NOTAUTH",
+ "NOTZONE",
+ "RESERVED11",
+ "RESERVED12",
+ "RESERVED13",
+ "RESERVED14",
+ "RESERVED15",
+ "BADVERS"
+};
+
+/*% 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);
+}
+
+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"
+" -x dot-notation (shortcut for reverse lookups)\n"
+" -i (use IP6.INT for IPv6 reverse lookups)\n"
+" -f filename (batch mode)\n"
+" -b address[#port] (bind to source address/port)\n"
+" -p port (specify port number)\n"
+" -q name (specify query name)\n"
+" -t type (specify query type)\n"
+" -c class (specify query class)\n"
+" -k keyfile (specify tsig key file)\n"
+" -y [hmac:]name:key (specify named base64 tsig key)\n"
+" -4 (use IPv4 query transport only)\n"
+" -6 (use IPv6 query transport only)\n"
+" -m (enable memory usage debugging)\n"
+" d-opt is of the form +keyword[=value], where keyword is:\n"
+" +[no]vc (TCP mode)\n"
+" +[no]tcp (TCP mode, alternate syntax)\n"
+" +time=### (Set query timeout) [5]\n"
+" +tries=### (Set number of UDP attempts) [3]\n"
+" +retry=### (Set number of UDP retries) [2]\n"
+" +domain=### (Set default domainname)\n"
+" +bufsize=### (Set EDNS0 Max UDP packet size)\n"
+" +ndots=### (Set NDOTS value)\n"
+" +edns=### (Set EDNS version)\n"
+" +[no]search (Set whether to use searchlist)\n"
+" +[no]showsearch (Search with intermediate results)\n"
+" +[no]defname (Ditto)\n"
+" +[no]recurse (Recursive mode)\n"
+" +[no]ignore (Don't revert to TCP for TC responses.)"
+"\n"
+" +[no]fail (Don't try next server on SERVFAIL)\n"
+" +[no]besteffort (Try to parse even illegal messages)\n"
+" +[no]aaonly (Set AA flag in query (+[no]aaflag))\n"
+" +[no]adflag (Set AD flag in query)\n"
+" +[no]cdflag (Set CD flag in query)\n"
+" +[no]cl (Control display of class in records)\n"
+" +[no]cmd (Control display of command line)\n"
+" +[no]comments (Control display of comment lines)\n"
+" +[no]question (Control display of question)\n"
+" +[no]answer (Control display of answer)\n"
+" +[no]authority (Control display of authority)\n"
+" +[no]additional (Control display of additional)\n"
+" +[no]stats (Control display of statistics)\n"
+" +[no]short (Disable everything except short\n"
+" form of answer)\n"
+" +[no]ttlid (Control display of ttls in records)\n"
+" +[no]all (Set or clear all display flags)\n"
+" +[no]qr (Print question before sending)\n"
+" +[no]nssearch (Search all authoritative nameservers)\n"
+" +[no]identify (ID responders in short answers)\n"
+" +[no]trace (Trace delegation down from root)\n"
+" +[no]dnssec (Request DNSSEC records)\n"
+" +[no]nsid (Request Name Server ID)\n"
+#ifdef DIG_SIGCHASE
+" +[no]sigchase (Chase DNSSEC signatures)\n"
+" +trusted-key=#### (Trusted Key when chasing DNSSEC sigs)\n"
+#if DIG_SIGCHASE_TD
+" +[no]topdown (Do DNSSEC validation top down mode)\n"
+#endif
+#endif
+" +[no]multiline (Print records in an expanded format)\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.
+ */
+void
+received(int bytes, isc_sockaddr_t *from, dig_query_t *query) {
+ isc_uint64_t diff;
+ isc_time_t now;
+ time_t tnow;
+ char fromtext[ISC_SOCKADDR_FORMATSIZE];
+
+ isc_sockaddr_format(from, fromtext, sizeof(fromtext));
+
+ TIME_NOW(&now);
+
+ if (query->lookup->stats && !short_form) {
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ printf(";; Query time: %ld msec\n", (long int)diff/1000);
+ printf(";; SERVER: %s(%s)\n", fromtext, query->servname);
+ time(&tnow);
+ printf(";; WHEN: %s", ctime(&tnow));
+ if (query->lookup->doing_xfr) {
+ printf(";; XFR size: %u records (messages %u, "
+ "bytes %" ISC_PRINT_QUADFORMAT "u)\n",
+ query->rr_count, query->msg_count,
+ query->byte_count);
+ } else {
+ printf(";; MSG SIZE rcvd: %u\n", bytes);
+
+ }
+ if (key != NULL) {
+ if (!validated)
+ puts(";; WARNING -- Some TSIG could not "
+ "be validated");
+ }
+ if ((key == NULL) && (keysecret[0] != 0)) {
+ puts(";; WARNING -- TSIG key was not used.");
+ }
+ puts("");
+ } else if (query->lookup->identify && !short_form) {
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ printf(";; Received %" ISC_PRINT_QUADFORMAT "u bytes "
+ "from %s(%s) in %d ms\n\n",
+ query->lookup->doing_xfr ?
+ query->byte_count : (isc_uint64_t)bytes,
+ fromtext, query->servname,
+ (int)diff/1000);
+ }
+}
+
+/*
+ * Callback from dighost.c to print that it is trying a server.
+ * Not used in dig.
+ * XXX print_trying
+ */
+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;
+ isc_uint64_t diff;
+ isc_time_t now;
+ char store[sizeof("12345678901234567890")];
+
+ 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, " ");
+ }
+ result = dns_rdata_totext(rdata, NULL, buf);
+ check_result(result, "dns_rdata_totext");
+ if (query->lookup->identify) {
+ TIME_NOW(&now);
+ diff = isc_time_microdiff(&now, &query->time_sent);
+ ADD_STRING(buf, " from server ");
+ ADD_STRING(buf, query->servname);
+ snprintf(store, 19, " in %d ms.", (int)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_buffer_t target;
+ isc_result_t result, loopresult;
+ dns_name_t empty_name;
+ char t[4096];
+ 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);
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ 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);
+ 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
+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(ISC_FALSE);
+
+ styleflags |= DNS_STYLEFLAG_REL_OWNER;
+ if (nottl)
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ if (noclass)
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ 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;
+ }
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 24, 32, 80, 8, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 32, 40, 80, 8, mctx);
+ else
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 32, 40, 48, 80, 8, 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
+
+/*
+ * Callback from dighost.c to print the reply from a server
+ */
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t 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 (nottl)
+ styleflags |= DNS_STYLEFLAG_NO_TTL;
+ if (noclass)
+ styleflags |= DNS_STYLEFLAG_NO_CLASS;
+ 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;
+ }
+ if (multiline || (nottl && noclass))
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 24, 32, 80, 8, mctx);
+ else if (nottl || noclass)
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 24, 32, 40, 80, 8, mctx);
+ else
+ result = dns_master_stylecreate(&style, styleflags,
+ 24, 32, 40, 48, 80, 8, 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 (!query->lookup->comments)
+ flags |= DNS_MESSAGETEXTFLAG_NOCOMMENTS;
+
+ result = ISC_R_SUCCESS;
+
+ 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) {
+ printf(";; ->>HEADER<<- opcode: %s, status: %s, "
+ "id: %u\n",
+ opcodetext[msg->opcode], rcodetext[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");
+
+ 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 && extrabytes != 0U)
+ printf(";; WARNING: Messages 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;
+ int remaining;
+ static isc_boolean_t first = ISC_TRUE;
+ char append[MXNAME];
+
+ if (printcmd) {
+ lookup->cmdline[sizeof(lookup->cmdline) - 1] = 0;
+ snprintf(lookup->cmdline, sizeof(lookup->cmdline),
+ "%s; <<>> DiG " VERSION " <<>>",
+ first?"\n":"");
+ i = 1;
+ while (i < argc) {
+ snprintf(append, sizeof(append), " %s", argv[i++]);
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, append, remaining);
+ }
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, "\n", remaining);
+ if (first && addresscount != 0) {
+ snprintf(append, sizeof(append),
+ "; (%d server%s found)\n",
+ addresscount,
+ addresscount > 1 ? "s" : "");
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, append, remaining);
+ }
+ if (first) {
+ snprintf(append, sizeof(append),
+ ";; global options:%s%s\n",
+ short_form ? " +short" : "",
+ printcmd ? " +cmd" : "");
+ first = ISC_FALSE;
+ remaining = sizeof(lookup->cmdline) -
+ strlen(lookup->cmdline) - 1;
+ strncat(lookup->cmdline, append, remaining);
+ }
+ }
+}
+
+static isc_uint32_t
+parse_uint(char *arg, const char *desc, isc_uint32_t max) {
+ isc_result_t result;
+ isc_uint32_t tmp;
+
+ result = isc_parse_uint32(&tmp, arg, 10);
+ if (result == ISC_R_SUCCESS && tmp > max)
+ result = ISC_R_RANGE;
+ if (result != ISC_R_SUCCESS)
+ fatal("%s '%s': %s", desc, arg, isc_result_totext(result));
+ return (tmp);
+}
+
+/*%
+ * 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(char *option, isc_boolean_t is_batchfile,
+ dig_lookup_t *lookup)
+{
+ char option_store[256];
+ char *cmd, *value, *ptr;
+ isc_boolean_t state = ISC_TRUE;
+#ifdef DIG_SIGCHASE
+ size_t n;
+#endif
+
+ strncpy(option_store, option, sizeof(option_store));
+ option_store[sizeof(option_store)-1]=0;
+ 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 = ISC_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 */
+ 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 'e':/* besteffort */
+ FULLCHECK("besteffort");
+ lookup->besteffort = state;
+ break;
+ case 'u':/* bufsize */
+ FULLCHECK("bufsize");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ lookup->udpsize = (isc_uint16_t) parse_uint(value,
+ "buffer size", COMMSIZE);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'c':
+ switch (cmd[1]) {
+ case 'd':/* cdflag */
+ FULLCHECK("cdflag");
+ lookup->cdflag = state;
+ break;
+ case 'l': /* cl */
+ FULLCHECK("cl");
+ noclass = ISC_TF(!state);
+ break;
+ case 'm': /* cmd */
+ FULLCHECK("cmd");
+ printcmd = state;
+ break;
+ case 'o': /* comments */
+ FULLCHECK("comments");
+ lookup->comments = state;
+ if (lookup == default_lookup)
+ pluscomm = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'd':
+ switch (cmd[1]) {
+ case 'e': /* defname */
+ FULLCHECK("defname");
+ 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;
+ strncpy(domainopt, value, sizeof(domainopt));
+ domainopt[sizeof(domainopt)-1] = '\0';
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'e':
+ FULLCHECK("edns");
+ if (!state) {
+ lookup->edns = -1;
+ break;
+ }
+ if (value == NULL)
+ goto need_value;
+ lookup->edns = (isc_int16_t) parse_uint(value, "edns", 255);
+ break;
+ case 'f': /* fail */
+ FULLCHECK("fail");
+ lookup->servfail_stops = state;
+ break;
+ case 'i':
+ switch (cmd[1]) {
+ case 'd': /* identify */
+ FULLCHECK("identify");
+ lookup->identify = state;
+ break;
+ case 'g': /* ignore */
+ default: /* Inherets default for compatibility */
+ FULLCHECK("ignore");
+ lookup->ignore = ISC_TRUE;
+ }
+ break;
+ case 'm': /* multiline */
+ FULLCHECK("multiline");
+ multiline = state;
+ break;
+ case 'n':
+ switch (cmd[1]) {
+ case 'd': /* ndots */
+ FULLCHECK("ndots");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ ndots = parse_uint(value, "ndots", MAXNDOTS);
+ 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 = ISC_TRUE;
+ lookup->recurse = ISC_TRUE;
+ lookup->identify = ISC_TRUE;
+ lookup->stats = ISC_FALSE;
+ lookup->comments = ISC_FALSE;
+ lookup->section_additional = ISC_FALSE;
+ lookup->section_authority = ISC_FALSE;
+ lookup->section_question = ISC_FALSE;
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = ISC_TRUE;
+ short_form = ISC_TRUE;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ 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 '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;
+ lookup->retries = parse_uint(value, "retries",
+ MAXTRIES - 1);
+ lookup->retries++;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 's':
+ switch (cmd[1]) {
+ case 'e': /* search */
+ FULLCHECK("search");
+ 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 = ISC_FALSE;
+ lookup->section_additional = ISC_FALSE;
+ lookup->section_answer = ISC_TRUE;
+ lookup->section_authority = ISC_FALSE;
+ lookup->section_question = ISC_FALSE;
+ lookup->comments = ISC_FALSE;
+ lookup->stats = ISC_FALSE;
+ }
+ break;
+ case 'w': /* showsearch */
+ FULLCHECK("showsearch");
+ 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 = ISC_TRUE;
+ break;
+#endif
+ case 't': /* stats */
+ FULLCHECK("stats");
+ lookup->stats = state;
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 't':
+ switch (cmd[1]) {
+ case 'c': /* tcp */
+ FULLCHECK("tcp");
+ if (!is_batchfile)
+ lookup->tcp_mode = state;
+ break;
+ case 'i': /* timeout */
+ FULLCHECK("timeout");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ timeout = parse_uint(value, "timeout", MAXTIMEOUT);
+ 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 = ISC_FALSE;
+ lookup->identify = ISC_TRUE;
+ lookup->comments = ISC_FALSE;
+ lookup->stats = ISC_FALSE;
+ lookup->section_additional = ISC_FALSE;
+ lookup->section_authority = ISC_TRUE;
+ lookup->section_question = ISC_FALSE;
+ }
+ break;
+ case 'i': /* tries */
+ FULLCHECK("tries");
+ if (value == NULL)
+ goto need_value;
+ if (!state)
+ goto invalid_option;
+ lookup->retries = parse_uint(value, "tries",
+ MAXTRIES);
+ 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': /* ttlid */
+ FULLCHECK("ttlid");
+ nottl = ISC_TF(!state);
+ break;
+ default:
+ goto invalid_option;
+ }
+ break;
+ case 'v':
+ FULLCHECK("vc");
+ if (!is_batchfile)
+ lookup->tcp_mode = state;
+ break;
+ default:
+ invalid_option:
+ need_value:
+ fprintf(stderr, "Invalid option: +%s\n",
+ option);
+ usage();
+ }
+ return;
+}
+
+/*%
+ * #ISC_TRUE returned if value was used
+ */
+static const char *single_dash_opts = "46dhimnv";
+static const char *dash_opts = "46bcdfhikmnptvyx";
+static isc_boolean_t
+dash_option(char *option, char *next, dig_lookup_t **lookup,
+ isc_boolean_t *open_type_class, isc_boolean_t *need_clone,
+ isc_boolean_t config_only, int argc, char **argv,
+ isc_boolean_t *firstarg)
+{
+ char opt, *value, *ptr, *ptr2, *ptr3;
+ isc_result_t result;
+ isc_boolean_t 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;
+
+ while (strpbrk(option, single_dash_opts) == &option[0]) {
+ /*
+ * Since the -[46dhimnv] 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 = ISC_FALSE;
+ } else {
+ fatal("can't find IPv4 networking");
+ return (ISC_FALSE);
+ }
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = ISC_FALSE;
+ } else {
+ fatal("can't find IPv6 networking");
+ return (ISC_FALSE);
+ }
+ break;
+ case 'd':
+ ptr = strpbrk(&option[1], dash_opts);
+ if (ptr != &option[1]) {
+ cmd = option;
+ FULLCHECK("debug");
+ debugging = ISC_TRUE;
+ return (ISC_FALSE);
+ } else
+ debugging = ISC_TRUE;
+ break;
+ case 'h':
+ help();
+ exit(0);
+ break;
+ case 'i':
+ ip6_int = ISC_TRUE;
+ break;
+ case 'm': /* memdebug */
+ /* memdebug is handled in preparse_args() */
+ break;
+ case 'n':
+ /* deprecated */
+ break;
+ case 'v':
+ version();
+ exit(0);
+ break;
+ }
+ if (strlen(option) > 1U)
+ option = &option[1];
+ else
+ return (ISC_FALSE);
+ }
+ opt = option[0];
+ if (strlen(option) > 1U) {
+ value_from_next = ISC_FALSE;
+ value = &option[1];
+ } else {
+ value_from_next = ISC_TRUE;
+ value = next;
+ }
+ if (value == NULL)
+ goto invalid_option;
+ switch (opt) {
+ case 'b':
+ hash = strchr(value, '#');
+ if (hash != NULL) {
+ srcport = (in_port_t)
+ parse_uint(hash + 1,
+ "port number", MAXPORT);
+ *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 = ISC_TRUE;
+ return (value_from_next);
+ case 'c':
+ if ((*lookup)->rdclassset) {
+ fprintf(stderr, ";; Warning, extra class option\n");
+ }
+ *open_type_class = ISC_FALSE;
+ tr.base = value;
+ tr.length = strlen(value);
+ result = dns_rdataclass_fromtext(&rdclass,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS) {
+ (*lookup)->rdclass = rdclass;
+ (*lookup)->rdclassset = ISC_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':
+ strncpy(keyfile, value, sizeof(keyfile));
+ keyfile[sizeof(keyfile)-1]=0;
+ return (value_from_next);
+ case 'p':
+ port = (in_port_t) parse_uint(value, "port number", MAXPORT);
+ return (value_from_next);
+ case 'q':
+ if (!config_only) {
+ if (*need_clone)
+ (*lookup) = clone_lookup(default_lookup,
+ ISC_TRUE);
+ *need_clone = ISC_TRUE;
+ strncpy((*lookup)->textname, value,
+ sizeof((*lookup)->textname));
+ (*lookup)->textname[sizeof((*lookup)->textname)-1]=0;
+ (*lookup)->trace_root = ISC_TF((*lookup)->trace ||
+ (*lookup)->ns_search_only);
+ (*lookup)->new_search = ISC_TRUE;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = ISC_FALSE;
+ }
+ ISC_LIST_APPEND(lookup_list, (*lookup), link);
+ debug("looking up %s", (*lookup)->textname);
+ }
+ return (value_from_next);
+ case 't':
+ *open_type_class = ISC_FALSE;
+ if (strncasecmp(value, "ixfr=", 5) == 0) {
+ rdtype = dns_rdatatype_ixfr;
+ result = ISC_R_SUCCESS;
+ } else {
+ tr.base = value;
+ tr.length = 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) {
+ (*lookup)->rdtype = dns_rdatatype_ixfr;
+ (*lookup)->rdtypeset = ISC_TRUE;
+ (*lookup)->ixfr_serial =
+ parse_uint(&value[5], "serial number",
+ MAXSERIAL);
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ (*lookup)->tcp_mode = ISC_TRUE;
+ } else {
+ (*lookup)->rdtype = rdtype;
+ (*lookup)->rdtypeset = ISC_TRUE;
+ if (rdtype == dns_rdatatype_axfr) {
+ (*lookup)->section_question = plusquest;
+ (*lookup)->comments = pluscomm;
+ }
+ (*lookup)->ixfr_serial = ISC_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) {
+ if (strcasecmp(ptr, "hmac-md5") == 0) {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(ptr, "hmac-md5-", 9) == 0) {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ digestbits = parse_uint(&ptr[9],
+ "digest-bits [0..128]",
+ 128);
+ digestbits = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(ptr, "hmac-sha1") == 0) {
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(ptr, "hmac-sha1-", 10) == 0) {
+ hmacname = DNS_TSIG_HMACSHA1_NAME;
+ digestbits = parse_uint(&ptr[10],
+ "digest-bits [0..160]",
+ 160);
+ digestbits = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(ptr, "hmac-sha224") == 0) {
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(ptr, "hmac-sha224-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA224_NAME;
+ digestbits = parse_uint(&ptr[12],
+ "digest-bits [0..224]",
+ 224);
+ digestbits = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(ptr, "hmac-sha256") == 0) {
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(ptr, "hmac-sha256-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA256_NAME;
+ digestbits = parse_uint(&ptr[12],
+ "digest-bits [0..256]",
+ 256);
+ digestbits = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(ptr, "hmac-sha384") == 0) {
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(ptr, "hmac-sha384-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA384_NAME;
+ digestbits = parse_uint(&ptr[12],
+ "digest-bits [0..384]",
+ 384);
+ digestbits = (digestbits + 7) & ~0x7U;
+ } else if (strcasecmp(ptr, "hmac-sha512") == 0) {
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ digestbits = 0;
+ } else if (strncasecmp(ptr, "hmac-sha512-", 12) == 0) {
+ hmacname = DNS_TSIG_HMACSHA512_NAME;
+ digestbits = parse_uint(&ptr[12],
+ "digest-bits [0..512]",
+ 512);
+ digestbits = (digestbits + 7) & ~0x7U;
+ } else {
+ fprintf(stderr, ";; Warning, ignoring "
+ "invalid TSIG algorithm %s\n", ptr);
+ return (value_from_next);
+ }
+ ptr = ptr2;
+ ptr2 = ptr3;
+ } else {
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ digestbits = 0;
+ }
+ strncpy(keynametext, ptr, sizeof(keynametext));
+ keynametext[sizeof(keynametext)-1]=0;
+ strncpy(keysecret, ptr2, sizeof(keysecret));
+ keysecret[sizeof(keysecret)-1]=0;
+ return (value_from_next);
+ case 'x':
+ if (*need_clone)
+ *lookup = clone_lookup(default_lookup, ISC_TRUE);
+ *need_clone = ISC_TRUE;
+ if (get_reverse(textname, sizeof(textname), value,
+ ip6_int, ISC_FALSE) == ISC_R_SUCCESS) {
+ strncpy((*lookup)->textname, textname,
+ sizeof((*lookup)->textname));
+ debug("looking up %s", (*lookup)->textname);
+ (*lookup)->trace_root = ISC_TF((*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 = ISC_TRUE;
+ if (*firstarg) {
+ printgreeting(argc, argv, *lookup);
+ *firstarg = ISC_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();
+ }
+ return (ISC_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]) {
+ if (option[0] == 'm') {
+ memdebugging = ISC_TRUE;
+ isc_mem_debugging = ISC_MEM_DEBUGTRACE |
+ ISC_MEM_DEBUGRECORD;
+ return;
+ }
+ option = &option[1];
+ }
+ }
+}
+
+static void
+getaddresses(dig_lookup_t *lookup, const char *host) {
+ 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 (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ host, isc_result_totext(result));
+
+ 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);
+ }
+ addresscount = count;
+}
+
+static void
+parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only,
+ int argc, char **argv) {
+ isc_result_t result;
+ isc_textregion_t tr;
+ isc_boolean_t firstarg = ISC_TRUE;
+ dig_lookup_t *lookup = NULL;
+ dns_rdatatype_t rdtype;
+ dns_rdataclass_t rdclass;
+ isc_boolean_t open_type_class = ISC_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;
+ isc_boolean_t need_clone = ISC_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();
+
+#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 ((bargv[bargc] != NULL) &&
+ (bargc < 62)) {
+ 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(ISC_TRUE, ISC_TRUE, bargc,
+ (char **)bargv);
+ }
+ fclose(batchfp);
+ }
+#endif
+ }
+
+ if (is_batchfile && !config_only) {
+ /* Processing '-f batchfile'. */
+ lookup = clone_lookup(default_lookup, ISC_TRUE);
+ need_clone = ISC_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 (strncmp(rv[0], "@", 1) == 0) {
+ getaddresses(lookup, &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 = strlen(rv[0]);
+ result = dns_rdatatype_fromtext(&rdtype,
+ (isc_textregion_t *)&tr);
+ if (result == ISC_R_SUCCESS &&
+ rdtype == dns_rdatatype_ixfr) {
+ result = DNS_R_UNKNOWN;
+ 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) {
+ lookup->rdtype =
+ dns_rdatatype_ixfr;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->ixfr_serial =
+ parse_uint(&rv[0][5],
+ "serial number",
+ MAXSERIAL);
+ lookup->section_question =
+ plusquest;
+ lookup->comments = pluscomm;
+ lookup->tcp_mode = ISC_TRUE;
+ } else {
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = ISC_TRUE;
+ if (rdtype ==
+ dns_rdatatype_axfr) {
+ lookup->section_question =
+ plusquest;
+ lookup->comments = pluscomm;
+ }
+ lookup->ixfr_serial = ISC_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 = ISC_TRUE;
+ continue;
+ }
+ }
+
+ if (!config_only) {
+ if (need_clone)
+ lookup = clone_lookup(default_lookup,
+ ISC_TRUE);
+ need_clone = ISC_TRUE;
+ strncpy(lookup->textname, rv[0],
+ sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1]=0;
+ lookup->trace_root = ISC_TF(lookup->trace ||
+ lookup->ns_search_only);
+ lookup->new_search = ISC_TRUE;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = ISC_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 ((bargv[bargc] != NULL) && (bargc < 14)) {
+ 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(ISC_TRUE, ISC_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, ISC_TRUE);
+ need_clone = ISC_TRUE;
+ lookup->trace_root = ISC_TF(lookup->trace ||
+ lookup->ns_search_only);
+ lookup->new_search = ISC_TRUE;
+ strcpy(lookup->textname, ".");
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = ISC_TRUE;
+ if (firstarg) {
+ printgreeting(argc, argv, lookup);
+ firstarg = ISC_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.
+ */
+void
+dighost_shutdown(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 ((bargv[bargc] != NULL) && (bargc < 14)) {
+ 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(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv);
+ start_lookup();
+ } else {
+ batchname = NULL;
+ if (batchfp != stdin)
+ fclose(batchfp);
+ isc_app_shutdown();
+ return;
+ }
+}
+
+/*% Main processing routine for dig */
+int
+main(int argc, char **argv) {
+ isc_result_t result;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ debug("main()");
+ preparse_args(argc, argv);
+ progname = argv[0];
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+ setup_libs();
+ parse_args(ISC_FALSE, ISC_FALSE, argc, argv);
+ setup_system();
+ if (domainopt[0] != '\0') {
+ set_search_domain(domainopt);
+ usesearch = ISC_TRUE;
+ }
+ result = isc_app_onrun(mctx, global_task, onrun_callback, NULL);
+ check_result(result, "isc_app_onrun");
+ isc_app_run();
+ 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();
+ return (exitcode);
+}
diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook
new file mode 100644
index 0000000..af26d70
--- /dev/null
+++ b/bin/dig/dig.docbook
@@ -0,0 +1,952 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: dig.docbook,v 1.42 2008/10/13 21:18:56 jreed Exp $ -->
+<refentry id="man.dig">
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </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>2004</year>
+ <year>2005</year>
+ <year>2006</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <year>2003</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>dig</command>
+ <arg choice="opt">@server</arg>
+ <arg><option>-b <replaceable class="parameter">address</replaceable></option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-f <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg><option>-k <replaceable class="parameter">filename</replaceable></option></arg>
+ <arg><option>-m</option></arg>
+ <arg><option>-p <replaceable class="parameter">port#</replaceable></option></arg>
+ <arg><option>-q <replaceable class="parameter">name</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-x <replaceable class="parameter">addr</replaceable></option></arg>
+ <arg><option>-y <replaceable class="parameter"><optional>hmac:</optional>name:key</replaceable></option></arg>
+ <arg><option>-4</option></arg>
+ <arg><option>-6</option></arg>
+ <arg choice="opt">name</arg>
+ <arg choice="opt">type</arg>
+ <arg choice="opt">class</arg>
+ <arg choice="opt" rep="repeat">queryopt</arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>dig</command>
+ <arg><option>-h</option></arg>
+ </cmdsynopsis>
+
+ <cmdsynopsis>
+ <command>dig</command>
+ <arg choice="opt" rep="repeat">global-queryopt</arg>
+ <arg choice="opt" rep="repeat">query</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <para><command>dig</command>
+ (domain information groper) 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>.
+ </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
+ domains 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>
+
+ </refsect1>
+
+ <refsect1>
+ <title>SIMPLE USAGE</title>
+
+ <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. If no <parameter>server</parameter>
+ argument is provided,
+ <command>dig</command> consults <filename>/etc/resolv.conf</filename>
+ and queries the name servers listed there. 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>
+
+ </refsect1>
+
+ <refsect1>
+ <title>OPTIONS</title>
+
+ <para>
+ The <option>-b</option> option sets the source IP address of the query
+ to <parameter>address</parameter>. This must be a valid
+ address on
+ one of the host's network interfaces or "0.0.0.0" or "::". An optional
+ port
+ may be specified by appending "#&lt;port&gt;"
+ </para>
+
+ <para>
+ The default query class (IN for internet) is overridden by the
+ <option>-c</option> option. <parameter>class</parameter> is
+ any valid
+ class, such as HS for Hesiod records or CH for Chaosnet records.
+ </para>
+
+ <para>
+ The <option>-f</option> option makes <command>dig </command>
+ operate
+ in batch mode by reading a list of lookup requests to process from the
+ file <parameter>filename</parameter>. The file contains a
+ number of
+ queries, one per line. Each entry in the file should be organized in
+ the same way they would be presented as queries to
+ <command>dig</command> using the command-line interface.
+ </para>
+
+ <para>
+ The <option>-m</option> option enables memory usage debugging.
+ <!-- It enables ISC_MEM_DEBUGTRACE and ISC_MEM_DEBUGRECORD
+ documented in include/isc/mem.h -->
+ </para>
+
+ <para>
+ If a non-standard port number is to be queried, the
+ <option>-p</option> option is used. <parameter>port#</parameter> is
+ the port number that <command>dig</command> will send its
+ queries
+ instead of the standard DNS port number 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>
+
+ <para>
+ The <option>-4</option> option forces <command>dig</command>
+ to only
+ use IPv4 query transport. The <option>-6</option> option forces
+ <command>dig</command> to only use IPv6 query transport.
+ </para>
+
+ <para>
+ The <option>-t</option> option sets the query type to
+ <parameter>type</parameter>. It can be any valid query type
+ which is
+ supported in BIND 9. 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,
+ <parameter>type</parameter> is set 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>
+ The <option>-q</option> option sets the query name to
+ <parameter>name</parameter>. This useful do distinguish the
+ <parameter>name</parameter> from other arguments.
+ </para>
+
+ <para>
+ Reverse lookups &mdash; mapping addresses to names &mdash; are simplified by the
+ <option>-x</option> option. <parameter>addr</parameter> is
+ an IPv4
+ address in dotted-decimal notation, or a colon-delimited IPv6 address.
+ When this 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>11.12.13.10.in-addr.arpa</literal> and sets the
+ query type and
+ class to PTR and IN respectively. By default, IPv6 addresses are
+ looked up using nibble format under the IP6.ARPA domain.
+ To use the older RFC1886 method using the IP6.INT domain
+ specify the <option>-i</option> option. Bit string labels (RFC2874)
+ are now experimental and are not attempted.
+ </para>
+
+ <para>
+ To sign the DNS queries sent by <command>dig</command> and
+ their
+ responses using transaction signatures (TSIG), specify a TSIG key file
+ using the <option>-k</option> option. You can also specify the TSIG
+ key itself on the command line using the <option>-y</option> option;
+ <parameter>hmac</parameter> is the type of the TSIG, default HMAC-MD5,
+ <parameter>name</parameter> is the name of the TSIG key and
+ <parameter>key</parameter> is the actual key. The key is a
+ base-64
+ encoded string, typically generated by
+ <citerefentry>
+ <refentrytitle>dnssec-keygen</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+
+ Caution should be taken when using the <option>-y</option> option on
+ multi-user systems as the key can be visible in the output from
+ <citerefentry>
+ <refentrytitle>ps</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>
+ or in the shell's history file. 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>
+
+ </refsect1>
+
+ <refsect1>
+ <title>QUERY OPTIONS</title>
+
+ <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>.
+ The query options are:
+
+ <variablelist>
+
+ <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 an AXFR or IXFR query is
+ requested, in
+ which case a TCP connection is used.
+ </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]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>+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>+[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>
+ </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]defname</option></term>
+ <listitem>
+ <para>
+ Deprecated, treated as a synonym for <parameter>+[no]search</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]aaflag</option></term>
+ <listitem>
+ <para>
+ A synonym for <parameter>+[no]aaonly</parameter>.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+[no]adflag</option></term>
+ <listitem>
+ <para>
+ Set [do not set] the AD (authentic data) bit in the query. The
+ AD bit
+ currently has a standard meaning only in responses, not in
+ queries,
+ but the ability to set the bit in the query is provided for
+ completeness.
+ </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]cl</option></term>
+ <listitem>
+ <para>
+ Display [do not display] the CLASS when printing the record.
+ </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]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>+[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]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>
+ </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]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]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]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]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]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]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]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]all</option></term>
+ <listitem>
+ <para>
+ Set or clear all display flags.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>+time=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>+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>+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>+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>.
+ </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>+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.
+ </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>+[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]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>+[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>+[no]sigchase</option></term>
+ <listitem>
+ <para>
+ Chase DNSSEC signature chains. Requires dig be compiled with
+ -DDIG_SIGCHASE.
+ </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.
+ </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.
+ </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>
+
+
+ </variablelist>
+
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>MULTIPLE QUERIES</title>
+
+ <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>
+
+ </refsect1>
+
+ <refsect1>
+ <title>IDN SUPPORT</title>
+ <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, defines
+ the <envar>IDN_DISABLE</envar> environment variable.
+ The IDN support is disabled if the variable is set when
+ <command>dig</command> runs.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ <para><filename>${HOME}/.digrc</filename>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><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>RFC1035</citetitle>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>BUGS</title>
+ <para>
+ There are probably too many query options.
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dig/dig.html b/bin/dig/dig.html
new file mode 100644
index 0000000..7c79c6e
--- /dev/null
+++ b/bin/dig/dig.html
@@ -0,0 +1,637 @@
+<!--
+ - Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2003 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: dig.html,v 1.45 2008/10/14 01:11:35 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>dig</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<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">-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="refsect1" lang="en">
+<a name="id2543515"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">dig</strong></span>
+ (domain information groper) 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><strong class="command">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><strong class="command">dig</strong></span>.
+ </p>
+<p>
+ Although <span><strong class="command">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><strong class="command">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><strong class="command">dig</strong></span> will try each of the servers listed
+ in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ When no command line arguments or options are given,
+ <span><strong class="command">dig</strong></span> will perform an NS query for "." (the root).
+ </p>
+<p>
+ It is possible to set per-user defaults for <span><strong class="command">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
+ domains 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="refsect1" lang="en">
+<a name="id2543589"></a><h2>SIMPLE USAGE</h2>
+<p>
+ A typical invocation of <span><strong class="command">dig</strong></span> looks like:
+ </p>
+<pre class="programlisting"> dig @server name type </pre>
+<p>
+ where:
+
+ </p>
+<div class="variablelist"><dl>
+<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><strong class="command">dig</strong></span> resolves that name before
+ querying that name
+ server. If no <em class="parameter"><code>server</code></em>
+ argument is provided,
+ <span><strong class="command">dig</strong></span> consults <code class="filename">/etc/resolv.conf</code>
+ and queries the name servers listed there. 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><strong class="command">dig</strong></span> will perform a lookup for an
+ A record.
+ </p></dd>
+</dl></div>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543680"></a><h2>OPTIONS</h2>
+<p>
+ The <code class="option">-b</code> option sets the source IP address of the query
+ to <em class="parameter"><code>address</code></em>. This must be a valid
+ address on
+ one of the host's network interfaces or "0.0.0.0" or "::". An optional
+ port
+ may be specified by appending "#&lt;port&gt;"
+ </p>
+<p>
+ The default query class (IN for internet) is overridden by the
+ <code class="option">-c</code> option. <em class="parameter"><code>class</code></em> is
+ any valid
+ class, such as HS for Hesiod records or CH for Chaosnet records.
+ </p>
+<p>
+ The <code class="option">-f</code> option makes <span><strong class="command">dig </strong></span>
+ operate
+ in batch mode by reading a list of lookup requests to process from the
+ file <em class="parameter"><code>filename</code></em>. The file contains a
+ number of
+ queries, one per line. Each entry in the file should be organized in
+ the same way they would be presented as queries to
+ <span><strong class="command">dig</strong></span> using the command-line interface.
+ </p>
+<p>
+ The <code class="option">-m</code> option enables memory usage debugging.
+
+ </p>
+<p>
+ If a non-standard port number is to be queried, the
+ <code class="option">-p</code> option is used. <em class="parameter"><code>port#</code></em> is
+ the port number that <span><strong class="command">dig</strong></span> will send its
+ queries
+ instead of the standard DNS port number 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>
+<p>
+ The <code class="option">-4</code> option forces <span><strong class="command">dig</strong></span>
+ to only
+ use IPv4 query transport. The <code class="option">-6</code> option forces
+ <span><strong class="command">dig</strong></span> to only use IPv6 query transport.
+ </p>
+<p>
+ The <code class="option">-t</code> option sets the query type to
+ <em class="parameter"><code>type</code></em>. It can be any valid query type
+ which is
+ supported in BIND 9. 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,
+ <em class="parameter"><code>type</code></em> is set 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>
+ The <code class="option">-q</code> option sets the query name to
+ <em class="parameter"><code>name</code></em>. This useful do distinguish the
+ <em class="parameter"><code>name</code></em> from other arguments.
+ </p>
+<p>
+ Reverse lookups &#8212; mapping addresses to names &#8212; are simplified by the
+ <code class="option">-x</code> option. <em class="parameter"><code>addr</code></em> is
+ an IPv4
+ address in dotted-decimal notation, or a colon-delimited IPv6 address.
+ When this option 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><strong class="command">dig</strong></span>
+ automatically performs a lookup for a name like
+ <code class="literal">11.12.13.10.in-addr.arpa</code> and sets the
+ query type and
+ class to PTR and IN respectively. By default, IPv6 addresses are
+ looked up using nibble format under the IP6.ARPA domain.
+ To use the older RFC1886 method using the IP6.INT domain
+ specify the <code class="option">-i</code> option. Bit string labels (RFC2874)
+ are now experimental and are not attempted.
+ </p>
+<p>
+ To sign the DNS queries sent by <span><strong class="command">dig</strong></span> and
+ their
+ responses using transaction signatures (TSIG), specify a TSIG key file
+ using the <code class="option">-k</code> option. You can also specify the TSIG
+ key itself on the command line using the <code class="option">-y</code> option;
+ <em class="parameter"><code>hmac</code></em> is the type of the TSIG, default HMAC-MD5,
+ <em class="parameter"><code>name</code></em> is the name of the TSIG key and
+ <em class="parameter"><code>key</code></em> is the actual key. The key is a
+ base-64
+ encoded string, typically generated by
+ <span class="citerefentry"><span class="refentrytitle">dnssec-keygen</span>(8)</span>.
+
+ Caution should be taken when using the <code class="option">-y</code> option on
+ multi-user systems as the key can be visible in the output from
+ <span class="citerefentry"><span class="refentrytitle">ps</span>(1)</span>
+ or in the shell's history file. When
+ using TSIG authentication with <span><strong class="command">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><strong class="command">key</strong></span> and <span><strong class="command">server</strong></span> statements in
+ <code class="filename">named.conf</code>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2544028"></a><h2>QUERY OPTIONS</h2>
+<p><span><strong class="command">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>.
+ The query options are:
+
+ </p>
+<div class="variablelist"><dl>
+<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 an AXFR or IXFR query is
+ requested, in
+ which case a TCP connection is used.
+ </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]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">+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><strong class="command">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">+[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></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]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]aaonly</code></span></dt>
+<dd><p>
+ Sets the "aa" flag in the query.
+ </p></dd>
+<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]adflag</code></span></dt>
+<dd><p>
+ Set [do not set] the AD (authentic data) bit in the query. The
+ AD bit
+ currently has a standard meaning only in responses, not in
+ queries,
+ but the ability to set the bit in the query is provided for
+ completeness.
+ </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]cl</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]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]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><strong class="command">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">+[no]nssearch</code></span></dt>
+<dd><p>
+ When this option is set, <span><strong class="command">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]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><strong class="command">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></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><strong class="command">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]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]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]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]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]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]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]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]all</code></span></dt>
+<dd><p>
+ Set or clear all display flags.
+ </p></dd>
+<dt><span class="term"><code class="option">+time=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">+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">+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">+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>.
+ </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">+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.
+ </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><strong class="command">dig</strong></span> output.
+ </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]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">+[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">+[no]sigchase</code></span></dt>
+<dd><p>
+ Chase DNSSEC signature chains. Requires dig be compiled with
+ -DDIG_SIGCHASE.
+ </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><strong class="command">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.
+ </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.
+ </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>
+</dl></div>
+<p>
+
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545163"></a><h2>MULTIPLE QUERIES</h2>
+<p>
+ The BIND 9 implementation of <span><strong class="command">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><strong class="command">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><strong class="command">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><strong class="command">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="refsect1" lang="en">
+<a name="id2545225"></a><h2>IDN SUPPORT</h2>
+<p>
+ If <span><strong class="command">dig</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span><strong class="command">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, defines
+ the <code class="envar">IDN_DISABLE</code> environment variable.
+ The IDN support is disabled if the variable is set when
+ <span><strong class="command">dig</strong></span> runs.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545248"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+<p><code class="filename">${HOME}/.digrc</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545333"></a><h2>SEE ALSO</h2>
+<p><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">RFC1035</em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2545370"></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..51c24ea
--- /dev/null
+++ b/bin/dig/dighost.c
@@ -0,0 +1,5420 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dighost.c,v 1.311.70.1 2008/12/10 22:41:07 marka Exp $ */
+
+/*! \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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDN
+#include <idn/result.h>
+#include <idn/log.h>
+#include <idn/resconf.h>
+#include <idn/api.h>
+#endif
+
+#include <dns/byaddr.h>
+#ifdef DIG_SIGCHASE
+#include <dns/dnssec.h>
+#include <dns/ds.h>
+#include <dns/nsec.h>
+#include <isc/random.h>
+#include <ctype.h>
+#endif
+#include <dns/fixedname.h>
+#include <dns/message.h>
+#include <dns/name.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 <isc/app.h>
+#include <isc/base64.h>
+#include <isc/entropy.h>
+#include <isc/file.h>
+#include <isc/lang.h>
+#include <isc/netaddr.h>
+#ifdef DIG_SIGCHASE
+#include <isc/netdb.h>
+#endif
+#include <isc/print.h>
+#include <isc/random.h>
+#include <isc/result.h>
+#include <isc/string.h>
+#include <isc/task.h>
+#include <isc/timer.h>
+#include <isc/types.h>
+#include <isc/util.h>
+
+#include <lwres/lwres.h>
+#include <lwres/net.h>
+
+#include <bind9/getaddresses.h>
+
+#include <dig/dig.h>
+
+#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;
+
+isc_boolean_t
+ check_ra = ISC_FALSE,
+ have_ipv4 = ISC_FALSE,
+ have_ipv6 = ISC_FALSE,
+ specified_source = ISC_FALSE,
+ free_now = ISC_FALSE,
+ cancel_now = ISC_FALSE,
+ usesearch = ISC_FALSE,
+ showsearch = ISC_FALSE,
+ qr = ISC_FALSE,
+ is_dst_up = ISC_FALSE;
+in_port_t port = 53;
+unsigned int timeout = 0;
+unsigned int extrabytes;
+isc_mem_t *mctx = 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;
+
+#ifdef WITH_IDN
+static void initialize_idn(void);
+static isc_result_t output_filter(isc_buffer_t *buffer,
+ unsigned int used_org,
+ isc_boolean_t absolute);
+static idn_result_t append_textname(char *name, const char *origin,
+ size_t namesize);
+static void idn_check_result(idn_result_t r, const char *msg);
+
+#define MAXDLEN 256
+int idnoptions = 0;
+#endif
+
+/*%
+ * 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] = "";
+dns_name_t *hmacname = NULL;
+unsigned int digestbits = 0;
+isc_buffer_t *namebuf = NULL;
+dns_tsigkey_t *key = NULL;
+isc_boolean_t validated = ISC_TRUE;
+isc_entropy_t *entp = NULL;
+isc_mempool_t *commctx = NULL;
+isc_boolean_t debugging = ISC_FALSE;
+isc_boolean_t memdebugging = ISC_FALSE;
+char *progname = NULL;
+isc_mutex_t lookup_lock;
+dig_lookup_t *current_lookup = NULL;
+
+#ifdef DIG_SIGCHASE
+
+isc_result_t get_trusted_key(isc_mem_t *mctx);
+dns_rdataset_t * sigchase_scanname(dns_rdatatype_t type,
+ dns_rdatatype_t covers,
+ isc_boolean_t *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,
+ isc_boolean_t *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_mem_t *mctx);
+isc_result_t sigchase_verify_sig(dns_name_t *name,
+ dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx);
+isc_result_t sigchase_verify_ds(dns_name_t *name,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset,
+ isc_mem_t *mctx);
+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, isc_mem_t *mctx);
+void dup_name(dns_name_t *source, dns_name_t* target,
+ isc_mem_t *mctx);
+void free_name(dns_name_t *name, isc_mem_t *mctx);
+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,
+ isc_mem_t *mctx);
+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 class,
+ 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 class,
+ 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 opentmpkey(isc_mem_t *mctx, const char *file,
+ char **tempp, FILE **fp);
+isc_result_t removetmpkey(isc_mem_t *mctx, const char *file);
+void clean_trustedkey(void);
+void insert_trustedkey(dst_key_t * key);
+#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
+
+
+isc_boolean_t chase_siglookedup = ISC_FALSE;
+isc_boolean_t chase_keylookedup = ISC_FALSE;
+isc_boolean_t chase_sigkeylookedup = ISC_FALSE;
+isc_boolean_t chase_dslookedup = ISC_FALSE;
+isc_boolean_t chase_sigdslookedup = ISC_FALSE;
+#if DIG_SIGCHASE_TD
+isc_boolean_t chase_nslookedup = ISC_FALSE;
+isc_boolean_t chase_lookedup = ISC_FALSE;
+
+
+isc_boolean_t delegation_follow = ISC_FALSE;
+isc_boolean_t grandfather_pb = ISC_FALSE;
+isc_boolean_t have_response = ISC_FALSE;
+isc_boolean_t have_delegation_ns = ISC_FALSE;
+dns_message_t * error_message = NULL;
+#endif
+
+isc_boolean_t dsvalidating = ISC_FALSE;
+isc_boolean_t chase_name_dup = ISC_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");\
+}
+
+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, isc_boolean_t include_question);
+
+
+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;
+ isc_region_t r;
+
+ isc_buffer_usedregion(b, &r);
+
+ printf("%d bytes\n", r.length);
+ for (len = 0; len < r.length; len++) {
+ printf("%02x ", r.base[len]);
+ if (len % 16 == 15)
+ printf("\n");
+ }
+ if (len % 16 != 0)
+ 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, int len, char **p, char *end) {
+ if (len > end - *p)
+ return (ISC_R_NOSPACE);
+ memcpy(*p, text, len);
+ *p += len;
+ return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+reverse_octets(const char *in, char **p, char *end) {
+ char *dot = strchr(in, '.');
+ int 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 = dot - in;
+ } else {
+ len = strlen(in);
+ }
+ return (append(in, len, p, end));
+}
+
+isc_result_t
+get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
+ isc_boolean_t 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;
+ dns_fixedname_init(&fname);
+ name = dns_fixedname_name(&fname);
+ result = dns_byaddr_createptrname2(&addr, options, name);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ dns_name_format(name, reverse, 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;
+
+ if (debugging) {
+ fflush(stdout);
+ 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__);
+ strncpy(srv->servername, servname, MXNAME);
+ strncpy(srv->userarg, userarg, MXNAME);
+ srv->servername[MXNAME-1] = 0;
+ srv->userarg[MXNAME-1] = 0;
+ 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")];
+ int af;
+ int i;
+
+ debug("copy_server_list()");
+ for (i = 0; i < confdata->nsnext; i++) {
+ af = addr2af(confdata->nameservers[i].family);
+
+ lwres_net_ntop(af, confdata->nameservers[i].address,
+ tmp, 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 = ISC_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 = ISC_FALSE;
+ looknew->rdclassset = ISC_FALSE;
+ looknew->sendspace = NULL;
+ looknew->sendmsg = NULL;
+ looknew->name = NULL;
+ looknew->oname = NULL;
+ looknew->timer = NULL;
+ looknew->xfr_q = NULL;
+ looknew->current_query = NULL;
+ looknew->doing_xfr = ISC_FALSE;
+ looknew->ixfr_serial = ISC_FALSE;
+ looknew->trace = ISC_FALSE;
+ looknew->trace_root = ISC_FALSE;
+ looknew->identify = ISC_FALSE;
+ looknew->identify_previous_line = ISC_FALSE;
+ looknew->ignore = ISC_FALSE;
+ looknew->servfail_stops = ISC_TRUE;
+ looknew->besteffort = ISC_TRUE;
+ looknew->dnssec = ISC_FALSE;
+ looknew->nsid = ISC_FALSE;
+#ifdef DIG_SIGCHASE
+ looknew->sigchase = ISC_FALSE;
+#if DIG_SIGCHASE_TD
+ looknew->do_topdown = ISC_FALSE;
+ looknew->trace_root_sigchase = ISC_FALSE;
+ looknew->rdtype_sigchaseset = ISC_FALSE;
+ looknew->rdtype_sigchase = dns_rdatatype_any;
+ looknew->qrdtype_sigchase = dns_rdatatype_any;
+ looknew->rdclass_sigchase = dns_rdataclass_in;
+ looknew->rdclass_sigchaseset = ISC_FALSE;
+#endif
+#endif
+ looknew->udpsize = 0;
+ looknew->edns = -1;
+ looknew->recurse = ISC_TRUE;
+ looknew->aaonly = ISC_FALSE;
+ looknew->adflag = ISC_FALSE;
+ looknew->cdflag = ISC_FALSE;
+ looknew->ns_search_only = ISC_FALSE;
+ looknew->origin = NULL;
+ looknew->tsigctx = NULL;
+ looknew->querysig = NULL;
+ looknew->retries = tries;
+ looknew->nsfound = 0;
+ looknew->tcp_mode = ISC_FALSE;
+ looknew->ip6_int = ISC_FALSE;
+ looknew->comments = ISC_TRUE;
+ looknew->stats = ISC_TRUE;
+ looknew->section_question = ISC_TRUE;
+ looknew->section_answer = ISC_TRUE;
+ looknew->section_authority = ISC_TRUE;
+ looknew->section_additional = ISC_TRUE;
+ looknew->new_search = ISC_FALSE;
+ looknew->done_as_is = ISC_FALSE;
+ looknew->need_search = ISC_FALSE;
+ ISC_LINK_INIT(looknew, link);
+ ISC_LIST_INIT(looknew->q);
+ ISC_LIST_INIT(looknew->my_server_list);
+ return (looknew);
+}
+
+/*%
+ * 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 seperately from somewhere else, or construct it by hand.
+ */
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) {
+ dig_lookup_t *looknew;
+
+ debug("clone_lookup()");
+
+ INSIST(!free_now);
+
+ looknew = make_empty_lookup();
+ INSIST(looknew != NULL);
+ strncpy(looknew->textname, lookold->textname, MXNAME);
+#if DIG_SIGCHASE_TD
+ strncpy(looknew->textnamesigchase, lookold->textnamesigchase, MXNAME);
+#endif
+ strncpy(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->nsid = lookold->nsid;
+#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->ns_search_only = lookold->ns_search_only;
+ looknew->tcp_mode = lookold->tcp_mode;
+ 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->retries = lookold->retries;
+ looknew->tsigctx = NULL;
+ looknew->need_search = lookold->need_search;
+ looknew->done_as_is = lookold->done_as_is;
+
+ 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, isc_boolean_t 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);
+}
+
+
+static void
+setup_text_key(void) {
+ isc_result_t result;
+ dns_name_t keyname;
+ isc_buffer_t secretbuf;
+ 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 = 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);
+
+ result = dns_name_fromtext(&keyname, namebuf,
+ dns_rootname, ISC_FALSE,
+ namebuf);
+ if (result != ISC_R_SUCCESS)
+ goto failure;
+
+ result = dns_tsigkey_create(&keyname, hmacname, secretstore,
+ secretsize, ISC_FALSE, NULL, 0, 0, mctx,
+ NULL, &key);
+ failure:
+ if (result != ISC_R_SUCCESS)
+ printf(";; Couldn't create key %s: %s\n",
+ keynametext, isc_result_totext(result));
+ else
+ dst_key_setbits(key->key, digestbits);
+
+ isc_mem_free(mctx, secretstore);
+ dns_name_invalidate(&keyname);
+ isc_buffer_free(&namebuf);
+}
+
+static void
+setup_file_key(void) {
+ isc_result_t result;
+ dst_key_t *dstkey = NULL;
+
+ debug("setup_file_key()");
+ result = dst_key_fromnamedfile(keyfile, DST_TYPE_PRIVATE | DST_TYPE_KEY,
+ mctx, &dstkey);
+ 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)) {
+ case DST_ALG_HMACMD5:
+ hmacname = DNS_TSIG_HMACMD5_NAME;
+ break;
+ 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, ISC_FALSE, NULL, 0, 0,
+ mctx, NULL, &key);
+ if (result != ISC_R_SUCCESS) {
+ printf(";; Couldn't create key %s: %s\n",
+ keynametext, isc_result_totext(result));
+ goto failure;
+ }
+ dstkey = NULL;
+ 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__);
+ strncpy(search->origin, domain, MXNAME);
+ search->origin[MXNAME-1] = 0;
+ ISC_LINK_INIT(search, link);
+ return (search);
+}
+
+static void
+create_search_list(lwres_conf_t *confdata) {
+ int i;
+ dig_searchlist_t *search;
+
+ debug("create_search_list()");
+ ISC_LIST_INIT(search_list);
+
+ 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(void) {
+ dig_searchlist_t *domain = NULL;
+ lwres_result_t lwresult;
+
+ debug("setup_system()");
+
+ lwresult = lwres_context_create(&lwctx, mctx, mem_alloc, mem_free, 1);
+ 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_INITANDAPPEND(search_list, domain, link);
+ domain = NULL;
+ }
+ }
+
+ if (ndots == -1) {
+ ndots = lwconf->ndots;
+ debug("ndots is %d.", ndots);
+ }
+
+ /* If we don't find a nameserver fall back to localhost */
+ if (lwconf->nsnext == 0) {
+ 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");
+ }
+ }
+
+ if (ISC_LIST_EMPTY(server_list))
+ copy_server_list(lwconf, &server_list);
+
+#ifdef WITH_IDN
+ initialize_idn();
+#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
+
+}
+
+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);
+ }
+}
+
+/*%
+ * 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;
+
+ debug("setup_libs()");
+
+ result = isc_net_probeipv4();
+ if (result == ISC_R_SUCCESS)
+ have_ipv4 = ISC_TRUE;
+
+ result = isc_net_probeipv6();
+ if (result == ISC_R_SUCCESS)
+ have_ipv6 = ISC_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");
+
+ 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");
+
+ 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 = ISC_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");
+
+ dns_result_register();
+}
+
+/*%
+ * Add EDNS0 option record to a message. Currently, the only supported
+ * options are UDP buffer size, the DO bit, and NSID request.
+ */
+static void
+add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns,
+ isc_boolean_t dnssec, isc_boolean_t nsid)
+{
+ dns_rdataset_t *rdataset = NULL;
+ dns_rdatalist_t *rdatalist = NULL;
+ dns_rdata_t *rdata = NULL;
+ isc_result_t result;
+
+ debug("add_opt()");
+ result = dns_message_gettemprdataset(msg, &rdataset);
+ check_result(result, "dns_message_gettemprdataset");
+ dns_rdataset_init(rdataset);
+ result = dns_message_gettemprdatalist(msg, &rdatalist);
+ check_result(result, "dns_message_gettemprdatalist");
+ result = dns_message_gettemprdata(msg, &rdata);
+ check_result(result, "dns_message_gettemprdata");
+
+ debug("setting udp size of %d", udpsize);
+ rdatalist->type = dns_rdatatype_opt;
+ rdatalist->covers = 0;
+ rdatalist->rdclass = udpsize;
+ rdatalist->ttl = edns << 16;
+ if (dnssec)
+ rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO;
+ if (nsid) {
+ unsigned char data[4];
+ isc_buffer_t buf;
+
+ isc_buffer_init(&buf, data, sizeof(data));
+ isc_buffer_putuint16(&buf, DNS_OPT_NSID);
+ isc_buffer_putuint16(&buf, 0);
+ rdata->data = data;
+ rdata->length = sizeof(data);
+ } else {
+ rdata->data = NULL;
+ rdata->length = 0;
+ }
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+ dns_rdatalist_tordataset(rdatalist, rdataset);
+ 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_init(rdataset);
+ 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);
+
+ lookup = query->lookup;
+
+ if (lookup->current_query == query)
+ lookup->current_query = NULL;
+
+ ISC_LIST_UNLINK(lookup->q, query, link);
+ 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 = ISC_TRUE;
+ else
+ isc_mem_free(mctx, query);
+}
+
+/*%
+ * Try and clear out a lookup if we're done with it. Return ISC_TRUE if
+ * the lookup was successfully cleared. If ISC_TRUE is returned, the
+ * lookup pointer has been invalidated.
+ */
+static isc_boolean_t
+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) {
+ 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);
+ }
+ }
+ return (ISC_FALSE);
+ }
+
+ /*
+ * At this point, we know there are no queries on the lookup,
+ * so can make it go away also.
+ */
+ destroy_lookup(lookup);
+ return (ISC_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->timer != NULL)
+ isc_timer_detach(&lookup->timer);
+ if (lookup->sendspace != NULL)
+ isc_mempool_put(commctx, lookup->sendspace);
+
+ if (lookup->tsigctx != NULL)
+ dst_context_destroy(&lookup->tsigctx);
+
+ 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 *trustedkey = 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(mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No trusted key, "
+ "+sigchase option is disabled\n");
+ current_lookup->sigchase = ISC_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) == ISC_TRUE)
+ trustedkey = tk_list.key[i];
+ /*
+ * Verifier que la temp est bien la plus basse
+ * WARNING
+ */
+ }
+ if (trustedkey == 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 = ISC_FALSE;
+ free_name(&query_name, mctx);
+ goto novalidation;
+ }
+ free_name(&query_name, mctx);
+
+ 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;
+
+ strncpy(current_lookup->textnamesigchase,
+ current_lookup->textname, MXNAME);
+
+ current_lookup->trace_root_sigchase = ISC_TRUE;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(dst_key_name(trustedkey),
+ ISC_FALSE, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strncpy(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
+ setup_lookup(current_lookup);
+ do_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;
+ isc_boolean_t success = ISC_FALSE;
+ int numLookups = 0;
+ dns_name_t *domain;
+ isc_boolean_t horizontal = ISC_FALSE, bad = ISC_FALSE;
+
+ INSIST(!free_now);
+
+ debug("following up %s", query->lookup->textname);
+
+ 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 = ISC_TRUE;
+ } else if (namereln != dns_namereln_subdomain) {
+ if (!bad)
+ printf(";; BAD REFERRAL\n");
+ bad = ISC_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 %d %s", numLookups, namestr);
+ numLookups++;
+ if (!success) {
+ success = ISC_TRUE;
+ lookup_counter++;
+ lookup = requeue_lookup(query->lookup,
+ ISC_FALSE);
+ cancel_lookup(query->lookup);
+ lookup->doing_xfr = ISC_FALSE;
+ if (!lookup->trace_root &&
+ section == DNS_SECTION_ANSWER)
+ lookup->trace = ISC_FALSE;
+ else
+ lookup->trace = query->lookup->trace;
+ lookup->ns_search_only =
+ query->lookup->ns_search_only;
+ lookup->trace_root = ISC_FALSE;
+ if (lookup->ns_search_only)
+ lookup->recurse = ISC_FALSE;
+ dns_fixedname_init(&lookup->fdomain);
+ domain = dns_fixedname_name(&lookup->fdomain);
+ dns_name_copy(name, domain, NULL);
+ }
+ srv = make_server(namestr, namestr);
+ debug("adding server %s", srv->servername);
+ ISC_LIST_APPEND(lookup->my_server_list, srv, link);
+ dns_rdata_reset(&rdata);
+ }
+ }
+
+ 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) {
+ isc_uint32_t i, j;
+ dig_serverlist_t my_server_list;
+
+ ISC_LIST_INIT(my_server_list);
+
+ for (i = numLookups; i > 0; i--) {
+ isc_random_get(&j);
+ j %= i;
+ srv = ISC_LIST_HEAD(lookup->my_server_list);
+ while (j-- > 0)
+ srv = ISC_LIST_NEXT(srv, link);
+ ISC_LIST_DEQUEUE(lookup->my_server_list, srv, link);
+ ISC_LIST_APPEND(my_server_list, srv, link);
+ }
+ 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 ISC_TRUE iff there was another searchlist entry.
+ */
+static isc_boolean_t
+next_origin(dns_message_t *msg, dig_query_t *query) {
+ dig_lookup_t *lookup;
+ dig_searchlist_t *search;
+
+ UNUSED(msg);
+
+ INSIST(!free_now);
+
+ debug("next_origin()");
+ debug("following up %s", query->lookup->textname);
+
+ if (!usesearch)
+ /*
+ * We're not using a search list, so don't even think
+ * about finding the next entry.
+ */
+ return (ISC_FALSE);
+ if (query->lookup->origin == NULL && !query->lookup->need_search)
+ /*
+ * Then we just did rootorg; there's nothing left.
+ */
+ return (ISC_FALSE);
+ if (query->lookup->origin == NULL && query->lookup->need_search) {
+ lookup = requeue_lookup(query->lookup, ISC_TRUE);
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = ISC_FALSE;
+ } else {
+ search = ISC_LIST_NEXT(query->lookup->origin, link);
+ if (search == NULL && query->lookup->done_as_is)
+ return (ISC_FALSE);
+ lookup = requeue_lookup(query->lookup, ISC_TRUE);
+ lookup->origin = search;
+ }
+ cancel_lookup(query->lookup);
+ return (ISC_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;
+ rdatalist->covers = 0;
+ rdatalist->ttl = 0;
+ ISC_LIST_INIT(rdatalist->rdata);
+ ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
+
+ dns_rdataset_init(rdataset);
+ 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);
+}
+
+/*%
+ * 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.
+ */
+void
+setup_lookup(dig_lookup_t *lookup) {
+ isc_result_t result;
+ isc_uint32_t id;
+ int len;
+ dig_server_t *serv;
+ dig_query_t *query;
+ isc_buffer_t b;
+ dns_compress_t cctx;
+ char store[MXNAME];
+#ifdef WITH_IDN
+ idn_result_t mr;
+ char utf8_textname[MXNAME], utf8_origin[MXNAME], idn_textname[MXNAME];
+#endif
+
+#ifdef WITH_IDN
+ result = dns_name_settotextfilter(output_filter);
+ 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->namespace,
+ sizeof(lookup->namespace));
+ isc_buffer_init(&lookup->onamebuf, lookup->onamespace,
+ sizeof(lookup->onamespace));
+
+#ifdef WITH_IDN
+ /*
+ * We cannot convert `textname' and `origin' separately.
+ * `textname' doesn't contain TLD, but local mapping needs
+ * TLD.
+ */
+ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP, lookup->textname,
+ utf8_textname, sizeof(utf8_textname));
+ idn_check_result(mr, "convert textname to UTF-8");
+#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) {
+#ifdef WITH_IDN
+ if ((count_dots(utf8_textname) >= ndots) || !usesearch) {
+ lookup->origin = NULL; /* Force abs lookup */
+ lookup->done_as_is = ISC_TRUE;
+ lookup->need_search = usesearch;
+ } else if (lookup->origin == NULL && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = ISC_FALSE;
+ }
+#else
+ if ((count_dots(lookup->textname) >= ndots) || !usesearch) {
+ lookup->origin = NULL; /* Force abs lookup */
+ lookup->done_as_is = ISC_TRUE;
+ lookup->need_search = usesearch;
+ } else if (lookup->origin == NULL && usesearch) {
+ lookup->origin = ISC_LIST_HEAD(search_list);
+ lookup->need_search = ISC_FALSE;
+ }
+#endif
+ }
+
+#ifdef WITH_IDN
+ if (lookup->origin != NULL) {
+ mr = idn_encodename(IDN_LOCALCONV | IDN_DELIMMAP,
+ lookup->origin->origin, utf8_origin,
+ sizeof(utf8_origin));
+ idn_check_result(mr, "convert origin to UTF-8");
+ mr = append_textname(utf8_textname, utf8_origin,
+ sizeof(utf8_textname));
+ idn_check_result(mr, "append origin to textname");
+ }
+ mr = idn_encodename(idnoptions | IDN_LOCALMAP | IDN_NAMEPREP |
+ IDN_IDNCONV | IDN_LENCHECK, utf8_textname,
+ idn_textname, sizeof(idn_textname));
+ idn_check_result(mr, "convert UTF-8 textname to IDN encoding");
+#else
+ 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? */
+ len = strlen(lookup->origin->origin);
+ isc_buffer_init(&b, lookup->origin->origin, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->oname, &b, dns_rootname,
+ ISC_FALSE, &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)",
+ lookup->origin->origin,
+ isc_result_totext(result));
+ }
+ if (lookup->trace && lookup->trace_root) {
+ dns_name_clone(dns_rootname, lookup->name);
+ } else {
+ len = strlen(lookup->textname);
+ isc_buffer_init(&b, lookup->textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
+ lookup->oname, ISC_FALSE,
+ &lookup->namebuf);
+ }
+ 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)",
+ lookup->textname, isc_result_totext(result));
+ }
+ dns_message_puttempname(lookup->sendmsg, &lookup->oname);
+ } else
+#endif
+ {
+ debug("using root origin");
+ if (lookup->trace && lookup->trace_root)
+ dns_name_clone(dns_rootname, lookup->name);
+ else {
+#ifdef WITH_IDN
+ len = strlen(idn_textname);
+ isc_buffer_init(&b, idn_textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
+ dns_rootname,
+ ISC_FALSE,
+ &lookup->namebuf);
+#else
+ len = strlen(lookup->textname);
+ isc_buffer_init(&b, lookup->textname, len);
+ isc_buffer_add(&b, len);
+ result = dns_name_fromtext(lookup->name, &b,
+ dns_rootname,
+ ISC_FALSE,
+ &lookup->namebuf);
+#endif
+ }
+ if (result != ISC_R_SUCCESS) {
+ dns_message_puttempname(lookup->sendmsg,
+ &lookup->name);
+ isc_buffer_init(&b, store, MXNAME);
+ fatal("'%s' is not a legal name "
+ "(%s)", lookup->textname,
+ isc_result_totext(result));
+ }
+ }
+ dns_name_format(lookup->name, store, sizeof(store));
+ trying(store, lookup);
+ INSIST(dns_name_isabsolute(lookup->name));
+
+ isc_random_get(&id);
+ lookup->sendmsg->id = (unsigned short)id & 0xFFFF;
+ lookup->sendmsg->opcode = dns_opcode_query;
+ 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 = ISC_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;
+ }
+
+ 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 = ISC_TRUE;
+ lookup->tcp_mode = ISC_TRUE;
+ } else if (lookup->tcp_mode) {
+ lookup->doing_xfr = ISC_TRUE;
+ }
+ }
+
+ 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 (key != NULL) {
+ debug("initializing keys");
+ result = dns_message_settsigkey(lookup->sendmsg, key);
+ 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) {
+ if (lookup->udpsize == 0)
+ lookup->udpsize = 4096;
+ if (lookup->edns < 0)
+ lookup->edns = 0;
+ add_opt(lookup->sendmsg, lookup->udpsize,
+ lookup->edns, lookup->dnssec, lookup->nsid);
+ }
+
+ 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 = ISC_TRUE;
+
+ lookup->pending = ISC_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->waiting_connect = ISC_FALSE;
+ query->waiting_senddone = ISC_FALSE;
+ query->pending_free = ISC_FALSE;
+ query->recv_made = ISC_FALSE;
+ query->first_pass = ISC_TRUE;
+ query->first_soa_rcvd = ISC_FALSE;
+ query->second_rr_rcvd = ISC_FALSE;
+ query->first_repeat_rcvd = ISC_FALSE;
+ query->warn_id = ISC_TRUE;
+ 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;
+ ISC_LINK_INIT(query, link);
+ 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, link);
+ ISC_LIST_ENQUEUE(lookup->q, query, link);
+ }
+ /* XXX qrflag, print_query, etc... */
+ if (!ISC_LIST_EMPTY(lookup->q) && qr) {
+ extrabytes = 0;
+ printmessage(ISC_LIST_HEAD(lookup->q), lookup->sendmsg,
+ ISC_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);
+
+ query = event->ev_arg;
+ query->waiting_senddone = ISC_FALSE;
+ l = query->lookup;
+
+ if (l->ns_search_only && !l->trace_root) {
+ 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;
+ }
+ if (lookup->timer != NULL)
+ isc_timer_detach(&lookup->timer);
+ lookup->pending = ISC_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_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 (l->timer != NULL)
+ isc_timer_detach(&l->timer);
+ result = isc_timer_create(timermgr, isc_timertype_once, NULL,
+ &l->interval, global_task, connect_timeout,
+ l, &l->timer);
+ check_result(result, "isc_timer_create");
+}
+
+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 = ISC_TRUE;
+ query->lookup->current_query = query;
+ get_address(query->servname, port, &query->sockaddr);
+
+ 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 = ISC_FALSE;
+ next = ISC_LIST_NEXT(query, link);
+ 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);
+ 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 (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");
+ /*
+ * 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");
+ next = ISC_LIST_NEXT(query, link);
+ if (next != NULL)
+ send_tcp_connect(next);
+ }
+}
+
+/*%
+ * 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;
+
+ 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 = ISC_FALSE;
+ get_address(query->servname, port, &query->sockaddr);
+
+ 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 (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 = ISC_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);
+ ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, link);
+ debug("sending a request");
+ TIME_NOW(&query->time_sent);
+ INSIST(query->sock != NULL);
+ query->waiting_senddone = ISC_TRUE;
+ result = isc_socket_sendtov(query->sock, &query->sendlist,
+ global_task, send_done, query,
+ &query->sockaddr, NULL);
+ 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;
+ l = event->ev_arg;
+ query = l->current_query;
+ isc_event_free(&event);
+
+ INSIST(!free_now);
+
+ if ((query != NULL) && (query->lookup->current_query != NULL) &&
+ (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
+ send_tcp_connect(ISC_LIST_NEXT(cq, link));
+ UNLOCK_LOOKUP;
+ return;
+ }
+
+ 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, ISC_TRUE);
+ cancel_lookup(l);
+ check_next_lookup(l);
+ }
+ } else {
+ 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;
+ isc_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));
+ l = query->lookup;
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ length = isc_buffer_getuint16(b);
+ if (length == 0) {
+ isc_event_free(&event);
+ launch_next_query(query, ISC_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, isc_boolean_t include_question) {
+ isc_result_t result;
+ dig_lookup_t *l;
+
+ 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 = ISC_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, (isc_uint16_t) query->sendbuf.used);
+ ISC_LIST_INIT(query->sendlist);
+ ISC_LINK_INIT(&query->slbuf, link);
+ ISC_LIST_ENQUEUE(query->sendlist, &query->slbuf, link);
+ if (include_question)
+ ISC_LIST_ENQUEUE(query->sendlist, &query->sendbuf, 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 = ISC_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 = ISC_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) {
+ 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 = ISC_FALSE;
+
+ if (sevent->result == ISC_R_CANCELED) {
+ debug("in cancel handler");
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ INSIST(sockcount >= 0);
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = ISC_FALSE;
+ 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];
+
+ 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);
+ sockcount--;
+ INSIST(sockcount >= 0);
+ /* XXX Clean up exitcodes */
+ if (exitcode < 9)
+ exitcode = 9;
+ debug("sockcount=%d", sockcount);
+ query->waiting_connect = ISC_FALSE;
+ isc_event_free(&event);
+ l = query->lookup;
+ if (l->current_query != NULL)
+ 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;
+ }
+ launch_next_query(query, ISC_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.
+ * ISC_FALSE means more data is on the way, and the recv has been issued.
+ */
+static isc_boolean_t
+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;
+ isc_uint32_t serial;
+ isc_result_t result;
+
+ 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 (ISC_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 (ISC_TRUE);
+ }
+ if ((!query->second_rr_rcvd) &&
+ (rdata.type != dns_rdatatype_soa)) {
+ query->second_rr_rcvd = ISC_TRUE;
+ query->second_rr_serial = 0;
+ debug("got the second rr as nonsoa");
+ 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 = ISC_TRUE;
+ query->first_rr_serial = serial;
+ debug("this is the first %d",
+ query->lookup->ixfr_serial);
+ if (query->lookup->ixfr_serial >=
+ serial)
+ goto doexit;
+ goto next_rdata;
+ }
+ if (query->lookup->rdtype ==
+ dns_rdatatype_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 %d",
+ query->lookup->ixfr_serial);
+ query->second_rr_rcvd = ISC_TRUE;
+ query->second_rr_serial = serial;
+ goto next_rdata;
+ }
+ if (query->second_rr_serial == 0) {
+ /*
+ * If the second RR was a non-SOA
+ * record, and we're getting any
+ * other SOA, then this is an
+ * AXFR, and we're done.
+ */
+ debug("done, since axfr");
+ goto doexit;
+ }
+ /*
+ * 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 =
+ ISC_TRUE;
+ goto next_rdata;
+ }
+ debug("done with ixfr");
+ goto doexit;
+ }
+ debug("meaningless soa %d", 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, ISC_FALSE);
+ return (ISC_FALSE);
+ doexit:
+ received(sevent->n, &sevent->address, query);
+ return (ISC_TRUE);
+}
+
+/*%
+ * 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;
+ isc_boolean_t docancel = ISC_FALSE;
+ isc_boolean_t match = ISC_TRUE;
+ unsigned int parseflags;
+ dns_messageid_t id;
+ unsigned int msgflags;
+#ifdef DIG_SIGCHASE
+ isc_result_t do_sigchase = ISC_FALSE;
+
+ dns_message_t *msg_temp = NULL;
+ isc_region_t r;
+ isc_buffer_t *buf = NULL;
+#endif
+
+ UNUSED(task);
+ INSIST(!free_now);
+
+ debug("recv_done()");
+
+ LOCK_LOOKUP;
+ recvcount--;
+ debug("recvcount=%d", recvcount);
+ INSIST(recvcount >= 0);
+
+ query = event->ev_arg;
+ 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) && (l->timer != NULL))
+ isc_timer_touch(l->timer);
+ if ((!l->pending && !l->ns_search_only) || cancel_now) {
+ debug("no longer pending. Got %s",
+ isc_result_totext(sevent->result));
+ query->waiting_connect = ISC_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 = ISC_FALSE;
+ } else {
+ printf(";; communications error: %s\n",
+ isc_result_totext(sevent->result));
+ isc_socket_detach(&query->sock);
+ sockcount--;
+ debug("sockcount=%d", sockcount);
+ INSIST(sockcount >= 0);
+ }
+ isc_event_free(&event);
+ clear_query(query);
+ 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 = ISC_FALSE;
+ }
+ }
+
+ result = dns_message_peekheader(b, &id, &msgflags);
+ if (result != ISC_R_SUCCESS || l->sendmsg->id != id) {
+ match = ISC_FALSE;
+ if (l->tcp_mode) {
+ isc_boolean_t fail = ISC_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 = ISC_FALSE;
+ query->warn_id = ISC_FALSE;
+ } else
+ printf(";; ERROR: short "
+ "(< header size) message\n");
+ if (fail) {
+ isc_event_free(&event);
+ clear_query(query);
+ check_next_lookup(l);
+ UNLOCK_LOOKUP;
+ return;
+ }
+ match = ISC_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) {
+ 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;
+ }
+
+ result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &msg);
+ check_result(result, "dns_message_create");
+
+ if (key != 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, key);
+ 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 = ISC_FALSE;
+ } else {
+ parseflags = 0;
+ do_sigchase = ISC_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 = ISC_FALSE;
+ 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) {
+ printf(";; Truncated, retrying in TCP mode.\n");
+ n = requeue_lookup(l, ISC_TRUE);
+ n->tcp_mode = ISC_TRUE;
+ n->origin = query->lookup->origin;
+ 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 == ISC_TRUE )
+ 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 (key != 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 = ISC_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 && l->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(l->timer,
+ isc_timertype_once,
+ NULL,
+ &l->interval,
+ ISC_FALSE);
+ check_result(result, "isc_timer_reset");
+ }
+ }
+
+ if (!l->doing_xfr || l->xfr_q == query) {
+ if (msg->rcode != dns_rcode_noerror &&
+ (l->origin != NULL || l->need_search)) {
+ if (!next_origin(msg, query) || showsearch) {
+ printmessage(query, msg, ISC_TRUE);
+ received(b->used, &sevent->address, query);
+ }
+ } else if (!l->trace && !l->ns_search_only) {
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ printmessage(query, msg, ISC_TRUE);
+ } else if (l->trace) {
+ int n = 0;
+ int count = msg->counts[DNS_SECTION_ANSWER];
+
+ debug("in TRACE code");
+ if (!l->ns_search_only)
+ printmessage(query, msg, ISC_TRUE);
+
+ l->rdtype = l->qrdtype;
+ if (l->trace_root || (l->ns_search_only && count > 0)) {
+ if (!l->trace_root)
+ l->rdtype = dns_rdatatype_soa;
+ n = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ l->trace_root = ISC_FALSE;
+ } else if (count == 0)
+ n = followup_lookup(msg, query,
+ DNS_SECTION_AUTHORITY);
+ if (n == 0)
+ docancel = ISC_TRUE;
+ } else {
+ debug("in NSSEARCH code");
+
+ if (l->trace_root) {
+ /*
+ * This is the initial NS query.
+ */
+ int n;
+
+ l->rdtype = dns_rdatatype_soa;
+ n = followup_lookup(msg, query,
+ DNS_SECTION_ANSWER);
+ if (n == 0)
+ docancel = ISC_TRUE;
+ l->trace_root = ISC_FALSE;
+ } else
+#ifdef DIG_SIGCHASE
+ if (!do_sigchase)
+#endif
+ printmessage(query, msg, ISC_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 = ISC_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
+ received(b->used, &sevent->address, query);
+ }
+
+ if (!query->lookup->ns_search_only)
+ query->lookup->pending = ISC_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;
+}
+
+/*%
+ * 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.
+ */
+void
+get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr) {
+ int count;
+ isc_result_t result;
+
+ isc_app_block();
+ result = bind9_getaddresses(host, port, sockaddr, 1, &count);
+ isc_app_unblock();
+ if (result != ISC_R_SUCCESS)
+ fatal("couldn't get address for '%s': %s",
+ host, isc_result_totext(result));
+ INSIST(count == 1);
+}
+
+/*%
+ * Initiate either a TCP or UDP lookup
+ */
+void
+do_lookup(dig_lookup_t *lookup) {
+
+ REQUIRE(lookup != NULL);
+
+ debug("do_lookup()");
+ lookup->pending = ISC_TRUE;
+ if (lookup->tcp_mode)
+ send_tcp_connect(ISC_LIST_HEAD(lookup->q));
+ else
+ send_udp(ISC_LIST_HEAD(lookup->q));
+}
+
+/*%
+ * 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 = ISC_TRUE;
+ if (current_lookup != NULL) {
+ if (current_lookup->timer != NULL)
+ isc_timer_detach(&current_lookup->timer);
+ q = ISC_LIST_HEAD(current_lookup->q);
+ while (q != NULL) {
+ debug("cancelling query %p, belonging to %p",
+ q, current_lookup);
+ nq = ISC_LIST_NEXT(q, link);
+ if (q->sock != NULL) {
+ isc_socket_cancel(q->sock, NULL,
+ ISC_SOCKCANCEL_ALL);
+ } else {
+ clear_query(q);
+ }
+ q = nq;
+ }
+ }
+ 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
+ isc_result_t result;
+#endif
+
+ 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 = ISC_TRUE;
+
+ lwres_conf_clear(lwctx);
+ lwres_context_destroy(&lwctx);
+
+ flush_server_list();
+
+ clear_searchlist();
+
+#ifdef WITH_IDN
+ 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 (key != NULL) {
+ debug("freeing key %p", key);
+ dns_tsigkey_detach(&key);
+ }
+ if (namebuf != NULL)
+ isc_buffer_free(&namebuf);
+
+ if (is_dst_up) {
+ debug("destroy DST lib");
+ dst_lib_destroy();
+ is_dst_up = ISC_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, mctx);
+#if DIG_SIGCHASE_TD
+ if (dns_name_dynamic(&chase_current_name))
+ free_name(&chase_current_name, mctx);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name, mctx);
+#endif
+#if DIG_SIGCHASE_BU
+ if (dns_name_dynamic(&chase_signame))
+ free_name(&chase_signame, mctx);
+#endif
+
+ debug("Destroy memory");
+
+#endif
+ if (memdebugging != 0)
+ isc_mem_stats(mctx, stderr);
+ if (mctx != NULL)
+ isc_mem_destroy(&mctx);
+}
+
+#ifdef WITH_IDN
+static void
+initialize_idn(void) {
+ idn_result_t r;
+ isc_result_t result;
+
+#ifdef HAVE_SETLOCALE
+ /* Set locale */
+ (void)setlocale(LC_ALL, "");
+#endif
+ /* Create configuration context. */
+ r = idn_nameinit(1);
+ if (r != idn_success)
+ fatal("idn api initialization failed: %s",
+ idn_result_tostring(r));
+
+ /* Set domain name -> text post-conversion filter. */
+ result = dns_name_settotextfilter(output_filter);
+ check_result(result, "dns_name_settotextfilter");
+}
+
+static isc_result_t
+output_filter(isc_buffer_t *buffer, unsigned int used_org,
+ isc_boolean_t absolute)
+{
+ char tmp1[MAXDLEN], tmp2[MAXDLEN];
+ size_t fromlen, tolen;
+ isc_boolean_t end_with_dot;
+
+ /*
+ * 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);
+ memcpy(tmp1, (char *)isc_buffer_base(buffer) + used_org, fromlen);
+ end_with_dot = (tmp1[fromlen - 1] == '.') ? ISC_TRUE : ISC_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.
+ */
+ if (idn_decodename(IDN_DECODE_APP, tmp1, tmp2, MAXDLEN) != idn_success)
+ return (ISC_R_SUCCESS);
+ strcpy(tmp1, tmp2);
+
+ /*
+ * Copy the converted contents in 'tmp1' back to 'buffer'.
+ * If we have appended trailing dot, remove it.
+ */
+ tolen = strlen(tmp1);
+ if (absolute && !end_with_dot && tmp1[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);
+ memcpy(isc_buffer_used(buffer), tmp1, tolen);
+ isc_buffer_add(buffer, tolen);
+
+ return (ISC_R_SUCCESS);
+}
+
+static idn_result_t
+append_textname(char *name, const char *origin, size_t namesize) {
+ size_t namelen = strlen(name);
+ size_t originlen = strlen(origin);
+
+ /* Already absolute? */
+ if (namelen > 0 && name[namelen - 1] == '.')
+ return idn_success;
+
+ /* Append dot and origin */
+
+ if (namelen + 1 + originlen >= namesize)
+ return idn_buffer_overflow;
+
+ name[namelen++] = '.';
+ (void)strcpy(name + namelen, origin);
+ return idn_success;
+}
+
+static void
+idn_check_result(idn_result_t r, const char *msg) {
+ if (r != idn_success) {
+ exitcode = 1;
+ fatal("%s: %s", msg, idn_result_tostring(r));
+ }
+}
+#endif /* WITH_IDN */
+
+#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, mctx);
+ 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;
+
+ 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,
+ isc_boolean_t * 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 == ISC_TRUE)
+ return (NULL);
+
+ lookup = clone_lookup(current_lookup, ISC_TRUE);
+ lookup->trace_root = ISC_FALSE;
+ lookup->new_search = ISC_TRUE;
+
+ result = isc_buffer_allocate(mctx, &b, BUFSIZE);
+ check_result(result, "isc_buffer_allocate");
+ result = dns_name_totext(rdata_name, ISC_FALSE, b);
+ check_result(result, "dns_name_totext");
+ isc_buffer_usedregion(b, &r);
+ r.base[r.length] = '\0';
+ strcpy(lookup->textname, (char*)r.base);
+ 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 = ISC_TRUE;
+ lookup->qrdtype = querytype;
+ *lookedup = ISC_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);
+}
+
+void
+insert_trustedkey(dst_key_t * key)
+{
+ if (key == NULL)
+ return;
+ if (tk_list.nb_tk >= MAX_TRUSTED_KEY)
+ return;
+
+ tk_list.key[tk_list.nb_tk++] = key;
+ return;
+}
+
+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(isc_mem_t *mctx, 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
+opentmpkey(isc_mem_t *mctx, const char *file, char **tempp, FILE **fp) {
+ FILE *f = NULL;
+ isc_result_t result;
+ char *tempname = NULL;
+ char *tempnamekey = NULL;
+ int tempnamelen;
+ int tempnamekeylen;
+ char *x;
+ char *cp;
+ isc_uint32_t which;
+
+ while (1) {
+ tempnamelen = strlen(file) + 20;
+ tempname = isc_mem_allocate(mctx, tempnamelen);
+ if (tempname == NULL)
+ return (ISC_R_NOMEMORY);
+ memset(tempname, 0, tempnamelen);
+
+ result = isc_file_mktemplate(file, tempname, tempnamelen);
+ if (result != ISC_R_SUCCESS)
+ goto cleanup;
+
+ cp = tempname;
+ while (*cp != '\0')
+ cp++;
+ if (cp == tempname) {
+ isc_mem_free(mctx, tempname);
+ return (ISC_R_FAILURE);
+ }
+
+ x = cp--;
+ while (cp >= tempname && *cp == 'X') {
+ isc_random_get(&which);
+ *cp = alphnum[which % (sizeof(alphnum) - 1)];
+ x = cp--;
+ }
+
+ tempnamekeylen = tempnamelen+5;
+ tempnamekey = isc_mem_allocate(mctx, tempnamekeylen);
+ if (tempnamekey == NULL)
+ return (ISC_R_NOMEMORY);
+
+ memset(tempnamekey, 0, tempnamekeylen);
+ strncpy(tempnamekey, tempname, tempnamelen);
+ strcat(tempnamekey ,".key");
+
+
+ if (isc_file_exists(tempnamekey)) {
+ isc_mem_free(mctx, tempnamekey);
+ isc_mem_free(mctx, tempname);
+ continue;
+ }
+
+ if ((f = fopen(tempnamekey, "w")) == NULL) {
+ printf("get_trusted_key(): trusted key not found %s\n",
+ tempnamekey);
+ return (ISC_R_FAILURE);
+ }
+ break;
+ }
+ isc_mem_free(mctx, tempnamekey);
+ *tempp = tempname;
+ *fp = f;
+ return (ISC_R_SUCCESS);
+
+ cleanup:
+ isc_mem_free(mctx, tempname);
+
+ return (result);
+}
+
+
+isc_result_t
+get_trusted_key(isc_mem_t *mctx)
+{
+ isc_result_t result;
+ const char *filename = NULL;
+ char *filetemp = NULL;
+ char buf[1500];
+ FILE *fp, *fptemp;
+ dst_key_t *key = NULL;
+
+ result = isc_file_exists(trustedkey);
+ if (result != ISC_TRUE) {
+ result = isc_file_exists("/etc/trusted-key.key");
+ if (result != ISC_TRUE) {
+ result = isc_file_exists("./trusted-key.key");
+ if (result != ISC_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);
+ }
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ printf("get_trusted_key(): trusted key not found %s\n",
+ filename);
+ return (ISC_R_FAILURE);
+ }
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ result = opentmpkey(mctx,"tmp_file", &filetemp, &fptemp);
+ if (result != ISC_R_SUCCESS) {
+ fclose(fp);
+ return (ISC_R_FAILURE);
+ }
+ if (fputs(buf, fptemp) < 0) {
+ fclose(fp);
+ fclose(fptemp);
+ return (ISC_R_FAILURE);
+ }
+ fclose(fptemp);
+ result = dst_key_fromnamedfile(filetemp, DST_TYPE_PUBLIC,
+ mctx, &key);
+ removetmpkey(mctx, filetemp);
+ isc_mem_free(mctx, filetemp);
+ if (result != ISC_R_SUCCESS) {
+ fclose(fp);
+ return (ISC_R_FAILURE);
+ }
+ insert_trustedkey(key);
+#if 0
+ dst_key_tofile(key, DST_TYPE_PUBLIC,"/tmp");
+#endif
+ key = NULL;
+ }
+ return (ISC_R_SUCCESS);
+}
+
+
+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_init(&buffer, str, len);
+ isc_buffer_add(&buffer, len);
+
+ dns_fixedname_init(&fixedname);
+ result = dns_name_fromtext(dns_fixedname_name(&fixedname), &buffer,
+ dns_rootname, ISC_TRUE, NULL);
+ check_result(result, "nameFromString");
+
+ if (dns_name_dynamic(p_ret))
+ free_name(p_ret, mctx);
+
+ 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, ISC_TRUE);
+ lookup->trace_root = ISC_FALSE;
+ lookup->new_search = ISC_TRUE;
+ lookup->trace_root_sigchase = ISC_FALSE;
+
+ strncpy(lookup->textname, lookup->textnamesigchase, MXNAME);
+
+ lookup->rdtype = lookup->rdtype_sigchase;
+ lookup->rdtypeset = ISC_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_result_t result;
+ isc_region_t r;
+ dns_rdataset_t *rdataset = NULL;
+ isc_boolean_t true = ISC_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, &true);
+ 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';
+ strncpy(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, &true);
+ 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';
+ strncpy(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, mctx);
+ 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)
+{
+ isc_result_t result;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_sig_t siginfo;
+
+ result = dns_rdataset_first(sigrdataset);
+ check_result(result, "empty RRSIG dataset");
+ dns_rdata_init(&sigrdata);
+
+ do {
+ dns_rdataset_current(sigrdataset, &sigrdata);
+
+ result = dns_rdata_tostruct(&sigrdata, &siginfo, NULL);
+ check_result(result, "sigrdata tostruct siginfo");
+
+ if (dns_name_compare(&siginfo.signer, zone_name) == 0) {
+ dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
+ return (ISC_R_SUCCESS);
+ }
+
+ dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
+
+ } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&sigrdata);
+
+ return (ISC_R_FAILURE);
+}
+
+
+isc_result_t
+initialization(dns_name_t *name)
+{
+ isc_result_t result;
+ isc_boolean_t true = ISC_TRUE;
+
+ chase_nsrdataset = NULL;
+ result = advanced_rrsearch(&chase_nsrdataset, name, dns_rdatatype_ns,
+ dns_rdatatype_any, &true);
+ 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, mctx);
+
+ return (ISC_R_SUCCESS);
+}
+#endif
+
+void
+print_rdataset(dns_name_t *name, dns_rdataset_t *rdataset, isc_mem_t *mctx)
+{
+ 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");
+
+ 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_mem_t *mctx) {
+ isc_result_t result;
+
+ if (dns_name_dynamic(target))
+ free_name(target, mctx);
+ result = dns_name_dup(source, mctx, target);
+ check_result(result, "dns_name_dup");
+}
+
+void
+free_name(dns_name_t *name, isc_mem_t *mctx) {
+ 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,
+ isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t rdata = DNS_RDATA_INIT;
+ dst_key_t *trustedKey = NULL;
+ dst_key_t *dnsseckey = NULL;
+ int i;
+
+ if (name == NULL || rdataset == NULL)
+ return (ISC_R_FAILURE);
+
+ result = dns_rdataset_first(rdataset);
+ check_result(result, "empty rdataset");
+
+ do {
+ dns_rdataset_current(rdataset, &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)
+ == ISC_TRUE) {
+ dns_rdata_reset(&rdata);
+
+ printf(";; Ok, find a Trusted Key in the "
+ "DNSKEY RRset: %d\n",
+ dst_key_id(dnsseckey));
+ if (sigchase_verify_sig_key(name, rdataset,
+ dnsseckey,
+ sigrdataset,
+ mctx)
+ == ISC_R_SUCCESS) {
+ dst_key_free(&dnsseckey);
+ dnsseckey = NULL;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ }
+
+ dns_rdata_reset(&rdata);
+ if (dnsseckey != NULL)
+ dst_key_free(&dnsseckey);
+ } while (dns_rdataset_next(rdataset) == ISC_R_SUCCESS);
+
+ if (trustedKey != NULL)
+ dst_key_free(&trustedKey);
+ trustedKey = NULL;
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+sigchase_verify_sig(dns_name_t *name, dns_rdataset_t *rdataset,
+ dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+ dst_key_t *dnsseckey = NULL;
+
+ result = dns_rdataset_first(keyrdataset);
+ check_result(result, "empty DNSKEY dataset");
+ dns_rdata_init(&keyrdata);
+
+ do {
+ dns_rdataset_current(keyrdataset, &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, mctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&keyrdata);
+ dst_key_free(&dnsseckey);
+ return (ISC_R_SUCCESS);
+ }
+ dst_key_free(&dnsseckey);
+ dns_rdata_reset(&keyrdata);
+ } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&keyrdata);
+
+ return (ISC_R_NOTFOUND);
+}
+
+isc_result_t
+sigchase_verify_sig_key(dns_name_t *name, dns_rdataset_t *rdataset,
+ dst_key_t *dnsseckey, dns_rdataset_t *sigrdataset,
+ isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t sigrdata = DNS_RDATA_INIT;
+ dns_rdata_sig_t siginfo;
+
+ result = dns_rdataset_first(sigrdataset);
+ check_result(result, "empty RRSIG dataset");
+ dns_rdata_init(&sigrdata);
+
+ do {
+ dns_rdataset_current(sigrdataset, &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(rdataset);
+ check_result(result, "empty DS dataset");
+
+ result = dns_dnssec_verify(name, rdataset, dnsseckey,
+ ISC_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) {
+ dns_rdata_reset(&sigrdata);
+ return (result);
+ }
+ }
+ dns_rdata_freestruct(&siginfo);
+ dns_rdata_reset(&sigrdata);
+
+ } while (dns_rdataset_next(chase_sigkeyrdataset) == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&sigrdata);
+
+ return (ISC_R_NOTFOUND);
+}
+
+
+isc_result_t
+sigchase_verify_ds(dns_name_t *name, dns_rdataset_t *keyrdataset,
+ dns_rdataset_t *dsrdataset, isc_mem_t *mctx)
+{
+ isc_result_t result;
+ dns_rdata_t keyrdata = DNS_RDATA_INIT;
+ dns_rdata_t newdsrdata = DNS_RDATA_INIT;
+ dns_rdata_t dsrdata = DNS_RDATA_INIT;
+ dns_rdata_ds_t dsinfo;
+ dst_key_t *dnsseckey = NULL;
+ unsigned char dsbuf[DNS_DS_BUFFERSIZE];
+
+ result = dns_rdataset_first(dsrdataset);
+ check_result(result, "empty DSset dataset");
+ do {
+ dns_rdataset_current(dsrdataset, &dsrdata);
+
+ result = dns_rdata_tostruct(&dsrdata, &dsinfo, NULL);
+ check_result(result, "dns_rdata_tostruct for DS");
+
+ result = dns_rdataset_first(keyrdataset);
+ check_result(result, "empty KEY dataset");
+
+ do {
+ dns_rdataset_current(keyrdataset, &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)) {
+
+ result = dns_ds_buildrdata(name, &keyrdata,
+ dsinfo.digest_type,
+ dsbuf, &newdsrdata);
+ dns_rdata_freestruct(&dsinfo);
+
+ if (result != ISC_R_SUCCESS) {
+ dns_rdata_reset(&keyrdata);
+ dns_rdata_reset(&newdsrdata);
+ dns_rdata_reset(&dsrdata);
+ dst_key_free(&dnsseckey);
+ dns_rdata_freestruct(&dsinfo);
+ printf("Oops: impossible to build"
+ " new DS rdata\n");
+ return (result);
+ }
+
+
+ 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,
+ mctx);
+ if (result == ISC_R_SUCCESS) {
+ dns_rdata_reset(&keyrdata);
+ dns_rdata_reset(&newdsrdata);
+ dns_rdata_reset(&dsrdata);
+ dst_key_free(&dnsseckey);
+
+ return (result);
+ }
+ } else {
+ printf(";; This DS is NOT the DS for"
+ " the chasing KEY: FAILED\n");
+ }
+
+ dns_rdata_reset(&newdsrdata);
+ }
+ dst_key_free(&dnsseckey);
+ dns_rdata_reset(&keyrdata);
+ dnsseckey = NULL;
+ } while (dns_rdataset_next(chase_keyrdataset) == ISC_R_SUCCESS);
+ dns_rdata_reset(&dsrdata);
+
+ } while (dns_rdataset_next(chase_dsrdataset) == ISC_R_SUCCESS);
+
+ dns_rdata_reset(&keyrdata);
+ dns_rdata_reset(&newdsrdata);
+ dns_rdata_reset(&dsrdata);
+
+ return (ISC_R_NOTFOUND);
+}
+
+/*
+ *
+ * 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,
+ isc_boolean_t *lookedup)
+{
+ isc_boolean_t 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 = ISC_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;
+ isc_boolean_t have_answer = ISC_FALSE;
+ isc_boolean_t true = ISC_TRUE;
+
+ 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)
+ 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, mctx);
+ if (chase_nsrdataset != NULL) {
+ have_delegation_ns = ISC_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, mctx);
+ 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 = ISC_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, mctx);
+
+
+ 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, mctx);
+
+
+ if (!chase_dslookedup && !chase_nslookedup) {
+ if (!delegation_follow) {
+ result = contains_trusted_key(&chase_current_name,
+ chase_keyrdataset,
+ chase_sigkeyrdataset,
+ mctx);
+ } else {
+ INSIST(chase_dsrdataset != NULL);
+ INSIST(chase_sigdsrdataset != NULL);
+ result = sigchase_verify_ds(&chase_current_name,
+ chase_keyrdataset,
+ chase_dsrdataset,
+ mctx);
+ }
+
+ 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,
+ &true);
+ 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,
+ &true);
+ 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 3568\n");
+ chase_rdataset = NULL;
+ chase_sigrdataset = NULL;
+ have_response = ISC_FALSE;
+ have_delegation_ns = ISC_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, mctx);
+ dup_name(&tmp_name, &chase_authority_name, mctx);
+ 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 = ISC_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, mctx);
+
+ result = advanced_rrsearch(&chase_sigdsrdataset,
+ &chase_authority_name,
+ dns_rdatatype_rrsig,
+ dns_rdatatype_ds,
+ &true);
+ 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, mctx);
+ INSIST(chase_sigdsrdataset != NULL);
+
+ result = sigchase_verify_sig(&chase_authority_name,
+ chase_dsrdataset,
+ chase_keyrdataset,
+ chase_sigdsrdataset, mctx);
+ 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 = ISC_FALSE;
+ have_delegation_ns = ISC_FALSE;
+ delegation_follow = ISC_TRUE;
+ error_message = NULL;
+ dup_name(&chase_authority_name, &chase_current_name, mctx);
+ free_name(&chase_authority_name, mctx);
+ 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, mctx);
+ if (ret != ISC_R_SUCCESS) {
+ free_name(&rdata_name, mctx);
+ printf("\n;; Impossible to verify the NSEC RR to prove"
+ " the non-existence : FAILED\n\n");
+ goto cleanandgo;
+ }
+ free_name(&rdata_name, mctx);
+ 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, mctx);
+ if (dns_name_dynamic(&chase_authority_name))
+ free_name(&chase_authority_name, mctx);
+ clean_trustedkey();
+ return;
+
+ finalstep :
+ result = advanced_rrsearch(&chase_rdataset, &chase_name,
+ current_lookup->rdtype_sigchase,
+ dns_rdatatype_any ,
+ &true);
+ 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, mctx);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; Impossible to verify the RRset : FAILED\n\n");
+ /*
+ printf("RRset:\n");
+ print_rdataset(&chase_name , chase_rdataset, mctx);
+ printf("DNSKEYset:\n");
+ print_rdataset(&chase_name , chase_keyrdataset, mctx);
+ printf("RRSIG of RRset:\n");
+ print_rdataset(&chase_name , chase_sigrdataset, mctx);
+ printf("\n");
+ */
+ goto cleanandgo;
+ } else {
+ printf("\n;; The Answer:\n");
+ print_rdataset(&chase_name , chase_rdataset, mctx);
+
+ 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;
+ isc_boolean_t true = ISC_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, &true);
+ if (result != ISC_R_SUCCESS) {
+ printf("\n;; No Answers: Validation FAILED\n\n");
+ return (ISC_R_NOTFOUND);
+ }
+ dup_name(name, &chase_name, mctx);
+ printf(";; RRset to chase:\n");
+ print_rdataset(&chase_name, chase_rdataset, mctx);
+ }
+ 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, mctx);
+ 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, mctx);
+ }
+ 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, mctx);
+ 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, mctx);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; DNSKEYset that signs the RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_keyrdataset, mctx);
+ }
+ 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, mctx);
+ if (dns_name_dynamic(&chase_name))
+ free_name(&chase_name, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ if (result == ISC_R_NOTFOUND) {
+ free_name(&chase_signame, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ printf("\n;; RRSIG of the DNSKEYset that signs the "
+ "RRset to chase:\n");
+ print_rdataset(&chase_signame, chase_sigkeyrdataset, mctx);
+ }
+ 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, mctx);
+ return (ISC_R_NOTFOUND);
+ }
+ if (chase_dsrdataset != NULL) {
+ printf("\n;; DSset of the DNSKEYset\n");
+ print_rdataset(&chase_signame, chase_dsrdataset, mctx);
+ }
+ }
+
+ 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, &true);
+ 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,
+ mctx);
+ }
+ }
+ 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(mctx);
+ 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, mctx);
+ 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, mctx);
+ free_name(&rdata_name, mctx);
+ chase_rdataset = rdataset;
+ chase_sigrdataset = sigrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = ISC_FALSE;
+ chase_keylookedup = ISC_FALSE;
+ chase_dslookedup = ISC_FALSE;
+ chase_sigdslookedup = ISC_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, mctx);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_name, mctx);
+ free_name(&chase_signame, mctx);
+ 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, mctx);
+ if (result == ISC_R_SUCCESS) {
+ free_name(&chase_name, mctx);
+ free_name(&chase_signame, mctx);
+ 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, mctx);
+ free_name(&chase_signame, mctx);
+ 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, mctx);
+ if (result != ISC_R_SUCCESS) {
+ free_name(&chase_signame, mctx);
+ free_name(&chase_name, mctx);
+ 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, mctx);
+ free_name(&chase_signame, mctx);
+ chase_rdataset = chase_dsrdataset;
+ chase_sigrdataset = chase_sigdsrdataset;
+ chase_keyrdataset = NULL;
+ chase_sigkeyrdataset = NULL;
+ chase_dsrdataset = NULL;
+ chase_sigdsrdataset = NULL;
+ chase_siglookedup = chase_keylookedup = ISC_FALSE;
+ chase_dslookedup = chase_sigdslookedup = ISC_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, mctx);
+
+ 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, mctx);
+
+ 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 class, 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(class);
+
+ 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, mctx);
+ *rdataset = nsecset;
+ *sigrdataset = signsecset;
+
+ return (ret);
+}
+
+/**
+ *
+ *
+ *
+ *
+ */
+isc_result_t
+prove_nx(dns_message_t *msg, dns_name_t *name, dns_rdataclass_t class,
+ 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-existance 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, class,
+ 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..2ec7d17
--- /dev/null
+++ b/bin/dig/host.1
@@ -0,0 +1,219 @@
+.\" Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000-2002 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: host.1,v 1.29 2008/04/05 01:09:34 tbox Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: host
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "HOST" "1" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+host \- DNS lookup utility
+.SH "SYNOPSIS"
+.HP 5
+\fBhost\fR [\fB\-aCdlnrsTwv\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] {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
+\fI/etc/resolv.conf\fR.
+.PP
+The
+\fB\-a\fR
+(all) option is equivalent to setting the
+\fB\-v\fR
+option and asking
+\fBhost\fR
+to make a query of type ANY.
+.PP
+When the
+\fB\-C\fR
+option is used,
+\fBhost\fR
+will attempt to display 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.
+.PP
+The
+\fB\-c\fR
+option instructs to make a DNS query of class
+\fIclass\fR. This can be used to lookup Hesiod or Chaosnet class resource records. The default class is IN (Internet).
+.PP
+Verbose output is generated by
+\fBhost\fR
+when the
+\fB\-d\fR
+or
+\fB\-v\fR
+option is used. The two options are equivalent. They have been provided for backwards compatibility. In previous versions, the
+\fB\-d\fR
+option switched on debugging traces and
+\fB\-v\fR
+enabled verbose output.
+.PP
+List mode is selected by the
+\fB\-l\fR
+option. This makes
+\fBhost\fR
+perform a zone transfer for zone
+\fIname\fR. Transfer the zone printing out the NS, PTR and address records (A/AAAA). If combined with
+\fB\-a\fR
+all records will be printed.
+.PP
+The
+\fB\-i\fR
+option specifies that reverse lookups of IPv6 addresses should use the IP6.INT domain as defined in RFC1886. The default is to use IP6.ARPA.
+.PP
+The
+\fB\-N\fR
+option sets 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
+\fI/etc/resolv.conf\fR, 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
+\fI/etc/resolv.conf\fR.
+.PP
+The number of UDP retries for a lookup can be changed with the
+\fB\-R\fR
+option.
+\fInumber\fR
+indicates how many times
+\fBhost\fR
+will repeat a query that does not get answered. The default number of retries is 1. If
+\fInumber\fR
+is negative or zero, the number of retries will default to 1.
+.PP
+Non\-recursive queries can be made via the
+\fB\-r\fR
+option. Setting this option clears the
+\fBRD\fR
+\(em recursion desired \(em bit in the query which
+\fBhost\fR
+makes. 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 are usually referrals to other name servers.
+.PP
+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.
+.PP
+The
+\fB\-4\fR
+option forces
+\fBhost\fR
+to only use IPv4 query transport. The
+\fB\-6\fR
+option forces
+\fBhost\fR
+to only use IPv6 query transport.
+.PP
+The
+\fB\-t\fR
+option is used to select the query type.
+\fItype\fR
+can be any recognized query type: CNAME, NS, SOA, SIG, KEY, AXFR, etc. When no query type is specified,
+\fBhost\fR
+automatically selects an appropriate query type. By default it looks for A, AAAA, and MX records, but if the
+\fB\-C\fR
+option was given, queries will be made for SOA records, and if
+\fIname\fR
+is a dotted\-decimal IPv4 address or colon\-delimited IPv6 address,
+\fBhost\fR
+will query for PTR records. 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 (e.g. \-t IXFR=12345678).
+.PP
+The time to wait for a reply can be controlled through the
+\fB\-W\fR
+and
+\fB\-w\fR
+options. The
+\fB\-W\fR
+option makes
+\fBhost\fR
+wait for
+\fIwait\fR
+seconds. If
+\fIwait\fR
+is less than one, the wait interval is set to one second. When the
+\fB\-w\fR
+option is used,
+\fBhost\fR
+will effectively wait forever for a reply. The time to wait for a response will be set to the number of seconds given by the hardware's maximum value for an integer quantity.
+.PP
+The
+\fB\-s\fR
+option tells
+\fBhost\fR
+\fInot\fR
+to send the query to the next nameserver if any server responds with a SERVFAIL response, which is the reverse of normal stub resolver behavior.
+.PP
+The
+\fB\-m\fR
+can be used to set the memory usage debugging flags
+\fIrecord\fR,
+\fIusage\fR
+and
+\fItrace\fR.
+.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'd 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
+\fI/etc/resolv.conf\fR
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBnamed\fR(8).
+.SH "COPYRIGHT"
+Copyright \(co 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+.br
+Copyright \(co 2000\-2002 Internet Software Consortium.
+.br
diff --git a/bin/dig/host.c b/bin/dig/host.c
new file mode 100644
index 0000000..ac29ae6
--- /dev/null
+++ b/bin/dig/host.c
@@ -0,0 +1,862 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: host.c,v 1.116 2007/12/03 00:21:48 marka Exp $ */
+
+/*! \file */
+
+#include <config.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef WITH_IDN
+#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 isc_boolean_t short_form = ISC_TRUE, listed_server = ISC_FALSE;
+static isc_boolean_t default_lookups = ISC_TRUE;
+static int seen_error = -1;
+static isc_boolean_t list_addresses = ISC_TRUE;
+static dns_rdatatype_t list_type = dns_rdatatype_a;
+static isc_boolean_t printed_server = ISC_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 void
+show_usage(void) {
+ fputs(
+"Usage: host [-aCdlriTwv] [-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"
+" -l lists all hosts in a domain, using AXFR\n"
+" -i IP6.INT reverse lookups\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"
+" -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"
+" -m set memory debugging flag (trace|record|usage)\n", stderr);
+ exit(1);
+}
+
+void
+dighost_shutdown(void) {
+ isc_app_shutdown();
+}
+
+void
+received(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);
+ }
+}
+
+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 */
+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(ISC_FALSE);
+}
+#endif
+static isc_result_t
+printsection(dns_message_t *msg, dns_section_t sectionid,
+ const char *section_name, isc_boolean_t 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 t[4096];
+ isc_boolean_t first;
+ isc_boolean_t no_rdata;
+
+ if (sectionid == DNS_SECTION_QUESTION)
+ no_rdata = ISC_TRUE;
+ else
+ no_rdata = ISC_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, t, sizeof(t));
+ first = ISC_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,
+ ISC_FALSE,
+ no_rdata,
+ &target);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+#ifdef USEINITALWS
+ if (first) {
+ print_name = &empty_name;
+ first = ISC_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, isc_boolean_t headers)
+{
+ isc_buffer_t target;
+ isc_result_t result;
+ isc_region_t r;
+ char t[4096];
+
+ UNUSED(msg);
+ if (headers)
+ printf(";; %s SECTION:\n", set_name);
+
+ isc_buffer_init(&target, t, sizeof(t));
+
+ result = dns_rdataset_totext(rdataset, owner, ISC_FALSE, ISC_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);
+ }
+}
+
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
+ isc_boolean_t did_flag = ISC_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 = ISC_TRUE;
+ }
+
+ if (msg->rcode != 0) {
+ char namestr[DNS_NAME_FORMATSIZE];
+ dns_name_format(query->lookup->name, namestr, sizeof(namestr));
+ printf("Host %s not found: %d(%s)\n",
+ (msg->rcode != dns_rcode_nxdomain) ? namestr :
+ query->lookup->textname, msg->rcode,
+ rcodetext[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. */
+ dns_fixedname_init(&fixed);
+ name = dns_fixedname_name(&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, ISC_FALSE);
+ if (lookup != NULL) {
+ strncpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1] = 0;
+ lookup->rdtype = dns_rdatatype_aaaa;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->origin = NULL;
+ lookup->retries = tries;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+ }
+ lookup = clone_lookup(query->lookup, ISC_FALSE);
+ if (lookup != NULL) {
+ strncpy(lookup->textname, namestr,
+ sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1] = 0;
+ lookup->rdtype = dns_rdatatype_mx;
+ lookup->rdtypeset = ISC_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], rcodetext[msg->rcode],
+ msg->id);
+ printf(";; flags: ");
+ if ((msg->flags & DNS_MESSAGEFLAG_QR) != 0) {
+ printf("qr");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) != 0) {
+ printf("%saa", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
+ printf("%stc", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RD) != 0) {
+ printf("%srd", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_RA) != 0) {
+ printf("%sra", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_AD) != 0) {
+ printf("%sad", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ if ((msg->flags & DNS_MESSAGEFLAG_CD) != 0) {
+ printf("%scd", did_flag ? " " : "");
+ did_flag = ISC_TRUE;
+ }
+ 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",
+ ISC_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",
+ ISC_TF(!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",
+ ISC_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", ISC_TRUE, query);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
+ if ((tsig != NULL) && !short_form) {
+ printf("\n");
+ result = printrdata(msg, tsig, tsigname,
+ "PSEUDOSECTION TSIG", ISC_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:vwCDN:R:TW:";
+
+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 = ISC_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': break;
+ case '6': 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 'w': break;
+ case 'C': break;
+ case 'D': break;
+ case 'N': break;
+ case 'R': break;
+ case 'T': break;
+ case 'W': break;
+ default:
+ show_usage();
+ }
+ }
+ isc_commandline_reset = ISC_TRUE;
+ isc_commandline_index = 1;
+}
+
+static void
+parse_args(isc_boolean_t 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;
+ isc_uint32_t serial = 0;
+
+ UNUSED(is_batchfile);
+
+ lookup = make_empty_lookup();
+
+ lookup->servfail_stops = ISC_FALSE;
+ lookup->comments = ISC_FALSE;
+
+ while ((c = isc_commandline_parse(argc, argv, optstring)) != -1) {
+ switch (c) {
+ case 'l':
+ lookup->tcp_mode = ISC_TRUE;
+ lookup->rdtype = dns_rdatatype_axfr;
+ lookup->rdtypeset = ISC_TRUE;
+ fatalexit = 3;
+ break;
+ case 'v':
+ case 'd':
+ short_form = ISC_FALSE;
+ break;
+ case 'r':
+ lookup->recurse = ISC_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 = ISC_TRUE;
+#ifdef WITH_IDN
+ idnoptions = 0;
+#endif
+ if (rdtype == dns_rdatatype_axfr) {
+ /* -l -t any -v */
+ list_type = dns_rdatatype_any;
+ short_form = ISC_FALSE;
+ lookup->tcp_mode = ISC_TRUE;
+ } else if (rdtype == dns_rdatatype_ixfr) {
+ lookup->ixfr_serial = serial;
+ lookup->tcp_mode = ISC_TRUE;
+ list_type = rdtype;
+#ifdef WITH_IDN
+ } 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 = ISC_FALSE;
+ default_lookups = ISC_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 = ISC_TRUE;
+ }
+ default_lookups = ISC_FALSE;
+ break;
+ case 'a':
+ if (!lookup->rdtypeset ||
+ lookup->rdtype != dns_rdatatype_axfr)
+ lookup->rdtype = dns_rdatatype_any;
+ list_type = dns_rdatatype_any;
+ list_addresses = ISC_FALSE;
+ lookup->rdtypeset = ISC_TRUE;
+ short_form = ISC_FALSE;
+ default_lookups = ISC_FALSE;
+ break;
+ case 'i':
+ lookup->ip6_int = ISC_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 = ISC_TRUE;
+ break;
+ case 'C':
+ debug("showing all SOAs");
+ lookup->rdtype = dns_rdatatype_ns;
+ lookup->rdtypeset = ISC_TRUE;
+ lookup->rdclass = dns_rdataclass_in;
+ lookup->rdclassset = ISC_TRUE;
+ lookup->ns_search_only = ISC_TRUE;
+ lookup->trace_root = ISC_TRUE;
+ lookup->identify_previous_line = ISC_TRUE;
+ default_lookups = ISC_FALSE;
+ break;
+ case 'N':
+ debug("setting NDOTS to %s",
+ isc_commandline_argument);
+ ndots = atoi(isc_commandline_argument);
+ break;
+ case 'D':
+ debugging = ISC_TRUE;
+ break;
+ case '4':
+ if (have_ipv4) {
+ isc_net_disableipv6();
+ have_ipv6 = ISC_FALSE;
+ } else
+ fatal("can't find IPv4 networking");
+ break;
+ case '6':
+ if (have_ipv6) {
+ isc_net_disableipv4();
+ have_ipv4 = ISC_FALSE;
+ } else
+ fatal("can't find IPv6 networking");
+ break;
+ case 's':
+ lookup->servfail_stops = ISC_TRUE;
+ break;
+ }
+ }
+
+ lookup->retries = tries;
+
+ if (isc_commandline_index >= argc)
+ show_usage();
+
+ strncpy(hostname, argv[isc_commandline_index], sizeof(hostname));
+ hostname[sizeof(hostname)-1]=0;
+ if (argc > isc_commandline_index + 1) {
+ set_nameserver(argv[isc_commandline_index+1]);
+ debug("server is %s", argv[isc_commandline_index+1]);
+ listed_server = ISC_TRUE;
+ } else
+ check_ra = ISC_TRUE;
+
+ lookup->pending = ISC_FALSE;
+ if (get_reverse(store, sizeof(store), hostname,
+ lookup->ip6_int, ISC_TRUE) == ISC_R_SUCCESS) {
+ strncpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1] = 0;
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = ISC_TRUE;
+ default_lookups = ISC_FALSE;
+ } else {
+ strncpy(lookup->textname, hostname, sizeof(lookup->textname));
+ lookup->textname[sizeof(lookup->textname)-1]=0;
+ }
+ lookup->new_search = ISC_TRUE;
+ ISC_LIST_APPEND(lookup_list, lookup, link);
+
+ usesearch = ISC_TRUE;
+}
+
+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_IDN
+ idnoptions = IDN_ASCCHECK;
+#endif
+
+ debug("main()");
+ progname = argv[0];
+ pre_parse_args(argc, argv);
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+ setup_libs();
+ parse_args(ISC_FALSE, argc, argv);
+ setup_system();
+ 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..bbd8d72
--- /dev/null
+++ b/bin/dig/host.docbook
@@ -0,0 +1,278 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: host.docbook,v 1.18 2008/04/04 23:47:01 tbox Exp $ -->
+<refentry id="man.host">
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </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>2004</year>
+ <year>2005</year>
+ <year>2007</year>
+ <year>2008</year>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ <copyright>
+ <year>2000</year>
+ <year>2001</year>
+ <year>2002</year>
+ <holder>Internet Software Consortium.</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>host</command>
+ <arg><option>-aCdlnrsTwv</option></arg>
+ <arg><option>-c <replaceable class="parameter">class</replaceable></option></arg>
+ <arg><option>-N <replaceable class="parameter">ndots</replaceable></option></arg>
+ <arg><option>-R <replaceable class="parameter">number</replaceable></option></arg>
+ <arg><option>-t <replaceable class="parameter">type</replaceable></option></arg>
+ <arg><option>-W <replaceable class="parameter">wait</replaceable></option></arg>
+ <arg><option>-m <replaceable class="parameter">flag</replaceable></option></arg>
+ <arg><option>-4</option></arg>
+ <arg><option>-6</option></arg>
+ <arg choice="req">name</arg>
+ <arg choice="opt">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+
+ <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>
+
+ <para>
+ The <option>-a</option> (all) option is equivalent to setting the
+ <option>-v</option> option and asking <command>host</command> to make
+ a query of type ANY.
+ </para>
+
+ <para>
+ When the <option>-C</option> option is used, <command>host</command>
+ will attempt to display 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>
+
+ <para>
+ The <option>-c</option> option instructs to make a DNS query of class
+ <parameter>class</parameter>. This can be used to lookup
+ Hesiod or
+ Chaosnet class resource records. The default class is IN (Internet).
+ </para>
+
+ <para>
+ Verbose output is generated by <command>host</command> when
+ the
+ <option>-d</option> or <option>-v</option> option is used. The two
+ options are equivalent. They have been provided for backwards
+ compatibility. In previous versions, the <option>-d</option> option
+ switched on debugging traces and <option>-v</option> enabled verbose
+ output.
+ </para>
+
+ <para>
+ List mode is selected by the <option>-l</option> option. This makes
+ <command>host</command> perform a zone transfer for zone
+ <parameter>name</parameter>. Transfer the zone printing out
+ the NS, PTR
+ and address records (A/AAAA). If combined with <option>-a</option>
+ all records will be printed.
+ </para>
+
+ <para>
+ The <option>-i</option>
+ option specifies that reverse lookups of IPv6 addresses should
+ use the IP6.INT domain as defined in RFC1886.
+ The default is to use IP6.ARPA.
+ </para>
+
+ <para>
+ The <option>-N</option> option sets 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>
+
+ <para>
+ The number of UDP retries for a lookup can be changed with the
+ <option>-R</option> option. <parameter>number</parameter>
+ indicates
+ how many times <command>host</command> will repeat a query
+ that does
+ not get answered. The default number of retries is 1. If
+ <parameter>number</parameter> is negative or zero, the
+ number of
+ retries will default to 1.
+ </para>
+
+ <para>
+ Non-recursive queries can be made via the <option>-r</option> option.
+ Setting this option clears the <type>RD</type> &mdash; recursion
+ desired &mdash; bit in the query which <command>host</command> makes.
+ 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 are usually
+ referrals to other name servers.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ The <option>-4</option> option forces <command>host</command> to only
+ use IPv4 query transport. The <option>-6</option> option forces
+ <command>host</command> to only use IPv6 query transport.
+ </para>
+
+ <para>
+ The <option>-t</option> option is used to select the query type.
+ <parameter>type</parameter> can be any recognized query
+ type: CNAME,
+ NS, SOA, SIG, KEY, AXFR, etc. 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, but if the
+ <option>-C</option> option was given, queries will be made for SOA
+ records, and if <parameter>name</parameter> is a
+ dotted-decimal IPv4
+ address or colon-delimited IPv6 address, <command>host</command> will
+ query for PTR records. 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 (e.g. -t IXFR=12345678).
+ </para>
+
+ <para>
+ The time to wait for a reply can be controlled through the
+ <option>-W</option> and <option>-w</option> options. The
+ <option>-W</option> option makes <command>host</command>
+ wait for
+ <parameter>wait</parameter> seconds. If <parameter>wait</parameter>
+ is less than one, the wait interval is set to one second. When the
+ <option>-w</option> option is used, <command>host</command>
+ will
+ effectively wait forever for a reply. The time to wait for a response
+ will be set to the number of seconds given by the hardware's maximum
+ value for an integer quantity.
+ </para>
+
+ <para>
+ The <option>-s</option> option tells <command>host</command>
+ <emphasis>not</emphasis> to 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>
+
+ <para>
+ The <option>-m</option> can be used to set the memory usage debugging
+ flags
+ <parameter>record</parameter>, <parameter>usage</parameter> and
+ <parameter>trace</parameter>.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>IDN SUPPORT</title>
+ <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>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <para><citerefentry>
+ <refentrytitle>dig</refentrytitle><manvolnum>1</manvolnum>
+ </citerefentry>,
+ <citerefentry>
+ <refentrytitle>named</refentrytitle><manvolnum>8</manvolnum>
+ </citerefentry>.
+ </para>
+
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dig/host.html b/bin/dig/host.html
new file mode 100644
index 0000000..6d14ef5
--- /dev/null
+++ b/bin/dig/host.html
@@ -0,0 +1,212 @@
+<!--
+ - Copyright (C) 2004, 2005, 2007, 2008 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2000-2002 Internet Software Consortium.
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: host.html,v 1.28 2008/04/05 01:09:34 tbox Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>host</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<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">-aCdlnrsTwv</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>] {name} [server]</p></div>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543431"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">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><strong class="command">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><strong class="command">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><strong class="command">host</strong></span>
+ should query instead of the server or servers listed in
+ <code class="filename">/etc/resolv.conf</code>.
+ </p>
+<p>
+ The <code class="option">-a</code> (all) option is equivalent to setting the
+ <code class="option">-v</code> option and asking <span><strong class="command">host</strong></span> to make
+ a query of type ANY.
+ </p>
+<p>
+ When the <code class="option">-C</code> option is used, <span><strong class="command">host</strong></span>
+ will attempt to display 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>
+<p>
+ The <code class="option">-c</code> option instructs to make a DNS query of class
+ <em class="parameter"><code>class</code></em>. This can be used to lookup
+ Hesiod or
+ Chaosnet class resource records. The default class is IN (Internet).
+ </p>
+<p>
+ Verbose output is generated by <span><strong class="command">host</strong></span> when
+ the
+ <code class="option">-d</code> or <code class="option">-v</code> option is used. The two
+ options are equivalent. They have been provided for backwards
+ compatibility. In previous versions, the <code class="option">-d</code> option
+ switched on debugging traces and <code class="option">-v</code> enabled verbose
+ output.
+ </p>
+<p>
+ List mode is selected by the <code class="option">-l</code> option. This makes
+ <span><strong class="command">host</strong></span> perform a zone transfer for zone
+ <em class="parameter"><code>name</code></em>. Transfer the zone printing out
+ the NS, PTR
+ and address records (A/AAAA). If combined with <code class="option">-a</code>
+ all records will be printed.
+ </p>
+<p>
+ The <code class="option">-i</code>
+ option specifies that reverse lookups of IPv6 addresses should
+ use the IP6.INT domain as defined in RFC1886.
+ The default is to use IP6.ARPA.
+ </p>
+<p>
+ The <code class="option">-N</code> option sets 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>
+<p>
+ The number of UDP retries for a lookup can be changed with the
+ <code class="option">-R</code> option. <em class="parameter"><code>number</code></em>
+ indicates
+ how many times <span><strong class="command">host</strong></span> will repeat a query
+ that does
+ not get answered. The default number of retries is 1. If
+ <em class="parameter"><code>number</code></em> is negative or zero, the
+ number of
+ retries will default to 1.
+ </p>
+<p>
+ Non-recursive queries can be made via the <code class="option">-r</code> option.
+ Setting this option clears the <span class="type">RD</span> &#8212; recursion
+ desired &#8212; bit in the query which <span><strong class="command">host</strong></span> makes.
+ 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><strong class="command">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 are usually
+ referrals to other name servers.
+ </p>
+<p>
+ By default <span><strong class="command">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.
+ </p>
+<p>
+ The <code class="option">-4</code> option forces <span><strong class="command">host</strong></span> to only
+ use IPv4 query transport. The <code class="option">-6</code> option forces
+ <span><strong class="command">host</strong></span> to only use IPv6 query transport.
+ </p>
+<p>
+ The <code class="option">-t</code> option is used to select the query type.
+ <em class="parameter"><code>type</code></em> can be any recognized query
+ type: CNAME,
+ NS, SOA, SIG, KEY, AXFR, etc. When no query type is specified,
+ <span><strong class="command">host</strong></span> automatically selects an appropriate
+ query
+ type. By default it looks for A, AAAA, and MX records, but if the
+ <code class="option">-C</code> option was given, queries will be made for SOA
+ records, and if <em class="parameter"><code>name</code></em> is a
+ dotted-decimal IPv4
+ address or colon-delimited IPv6 address, <span><strong class="command">host</strong></span> will
+ query for PTR records. 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 (e.g. -t IXFR=12345678).
+ </p>
+<p>
+ The time to wait for a reply can be controlled through the
+ <code class="option">-W</code> and <code class="option">-w</code> options. The
+ <code class="option">-W</code> option makes <span><strong class="command">host</strong></span>
+ wait for
+ <em class="parameter"><code>wait</code></em> seconds. If <em class="parameter"><code>wait</code></em>
+ is less than one, the wait interval is set to one second. When the
+ <code class="option">-w</code> option is used, <span><strong class="command">host</strong></span>
+ will
+ effectively wait forever for a reply. The time to wait for a response
+ will be set to the number of seconds given by the hardware's maximum
+ value for an integer quantity.
+ </p>
+<p>
+ The <code class="option">-s</code> option tells <span><strong class="command">host</strong></span>
+ <span class="emphasis"><em>not</em></span> to 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>
+<p>
+ The <code class="option">-m</code> can be used to set the memory usage debugging
+ flags
+ <em class="parameter"><code>record</code></em>, <em class="parameter"><code>usage</code></em> and
+ <em class="parameter"><code>trace</code></em>.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543797"></a><h2>IDN SUPPORT</h2>
+<p>
+ If <span><strong class="command">host</strong></span> has been built with IDN (internationalized
+ domain name) support, it can accept and display non-ASCII domain names.
+ <span><strong class="command">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><strong class="command">host</strong></span> runs.
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543819"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543831"></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..ccf9bf1
--- /dev/null
+++ b/bin/dig/include/dig/dig.h
@@ -0,0 +1,406 @@
+/*
+ * Copyright (C) 2004-2008 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: dig.h,v 1.107 2008/04/03 06:09:04 tbox Exp $ */
+
+#ifndef DIG_H
+#define DIG_H
+
+/*! \file */
+
+#include <dns/rdatalist.h>
+
+#include <dst/dst.h>
+
+#include <isc/boolean.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 {
+ isc_boolean_t
+ 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,
+ trace, /*% dig +trace */
+ trace_root, /*% initial query for either +trace or +nssearch */
+ tcp_mode,
+ ip6_int,
+ comments,
+ stats,
+ section_question,
+ section_answer,
+ section_authority,
+ section_additional,
+ servfail_stops,
+ new_search,
+ need_search,
+ done_as_is,
+ besteffort,
+ dnssec,
+ nsid; /*% Name Server ID (RFC 5001) */
+#ifdef DIG_SIGCHASE
+isc_boolean_t sigchase;
+#if DIG_SIGCHASE_TD
+ isc_boolean_t 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;
+ isc_boolean_t rdtypeset;
+ isc_boolean_t rdclassset;
+ char namespace[BUFSIZE];
+ char onamespace[BUFSIZE];
+ isc_buffer_t namebuf;
+ isc_buffer_t onamebuf;
+ isc_buffer_t renderbuf;
+ char *sendspace;
+ dns_name_t *name;
+ isc_timer_t *timer;
+ isc_interval_t interval;
+ dns_message_t *sendmsg;
+ dns_name_t *oname;
+ ISC_LINK(dig_lookup_t) link;
+ ISC_LIST(dig_query_t) q;
+ dig_query_t *current_query;
+ dig_serverlist_t my_server_list;
+ dig_searchlist_t *origin;
+ dig_query_t *xfr_q;
+ isc_uint32_t retries;
+ int nsfound;
+ isc_uint16_t udpsize;
+ isc_int16_t edns;
+ isc_uint32_t ixfr_serial;
+ isc_buffer_t rdatabuf;
+ char rdatastore[MXNAME];
+ dst_context_t *tsigctx;
+ isc_buffer_t *querysig;
+ isc_uint32_t msgcounter;
+ dns_fixedname_t fdomain;
+};
+
+/*% The dig_query structure */
+struct dig_query {
+ dig_lookup_t *lookup;
+ isc_boolean_t waiting_connect,
+ pending_free,
+ waiting_senddone,
+ first_pass,
+ first_soa_rcvd,
+ second_rr_rcvd,
+ first_repeat_rcvd,
+ recv_made,
+ warn_id;
+ isc_uint32_t first_rr_serial;
+ isc_uint32_t second_rr_serial;
+ isc_uint32_t msg_count;
+ isc_uint32_t rr_count;
+ 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_sockaddr_t sockaddr;
+ isc_time_t time_sent;
+ isc_uint64_t byte_count;
+ isc_buffer_t sendbuf;
+};
+
+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 isc_boolean_t 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 dns_messageid_t id;
+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 *key;
+extern isc_boolean_t validated;
+extern isc_taskmgr_t *taskmgr;
+extern isc_task_t *global_task;
+extern isc_boolean_t free_now;
+extern isc_boolean_t debugging, memdebugging;
+
+extern char *progname;
+extern int tries;
+extern int fatalexit;
+#ifdef WITH_IDN
+extern int idnoptions;
+#endif
+
+/*
+ * Routines in dighost.c.
+ */
+void
+get_address(char *host, in_port_t port, isc_sockaddr_t *sockaddr);
+
+isc_result_t
+get_reverse(char *reverse, size_t len, char *value, isc_boolean_t ip6_int,
+ isc_boolean_t strict);
+
+void
+fatal(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+debug(const char *format, ...) ISC_FORMAT_PRINTF(1, 2);
+
+void
+check_result(isc_result_t result, const char *msg);
+
+void
+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(void);
+
+dig_lookup_t *
+requeue_lookup(dig_lookup_t *lookold, isc_boolean_t servers);
+
+dig_lookup_t *
+make_empty_lookup(void);
+
+dig_lookup_t *
+clone_lookup(dig_lookup_t *lookold, isc_boolean_t 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
+
+/*
+ * Routines to be defined in dig.c, host.c, and nslookup.c.
+ */
+#ifdef DIG_SIGCHASE
+isc_result_t
+printrdataset(dns_name_t *owner_name, dns_rdataset_t *rdataset,
+ isc_buffer_t *target);
+#endif
+
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers);
+/*%<
+ * Print the final result of the lookup.
+ */
+
+void
+received(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".
+ */
+
+void
+trying(char *frm, dig_lookup_t *lookup);
+
+void
+dighost_shutdown(void);
+
+char *
+next_token(char **stringp, const char *delim);
+
+#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
+
+ISC_LANG_ENDDECLS
+
+#endif
diff --git a/bin/dig/nslookup.1 b/bin/dig/nslookup.1
new file mode 100644
index 0000000..2d19534
--- /dev/null
+++ b/bin/dig/nslookup.1
@@ -0,0 +1,252 @@
+.\" Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $Id: nslookup.1,v 1.14 2007/05/16 06:12:01 marka Exp $
+.\"
+.hy 0
+.ad l
+.\" Title: nslookup
+.\" Author:
+.\" Generator: DocBook XSL Stylesheets v1.71.1 <http://docbook.sf.net/>
+.\" Date: Jun 30, 2000
+.\" Manual: BIND9
+.\" Source: BIND9
+.\"
+.TH "NSLOOKUP" "1" "Jun 30, 2000" "BIND9" "BIND9"
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.SH "NAME"
+nslookup \- query Internet name servers interactively
+.SH "SYNOPSIS"
+.HP 9
+\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:
+.TP 4
+1.
+when no arguments are given (the default name server will be used)
+.TP 4
+2.
+when the first argument is a hyphen (\-) and the second argument is the host name or Internet address of a name server.
+.sp
+.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 .RS 4 .nf nslookup \-query=hinfo \-timeout=10 .fi .RE
+.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't 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:
+.RS 4
+.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:
+.RS 4
+.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
+.RE
+.IP "" 4
+The class specifies the protocol group of the information.
+.sp
+(Default = IN; abbreviation = cl)
+.RE
+.PP
+\fB \fR\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 \fR\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 \fR\fB\fI[no]\fR\fR\fBsearch\fR
+.RS 4
+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.
+.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 \fR\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
+\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 \fR\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 \fR\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
+.RE
+.IP "" 4
+.RE
+.SH "FILES"
+.PP
+\fI/etc/resolv.conf\fR
+.SH "SEE ALSO"
+.PP
+\fBdig\fR(1),
+\fBhost\fR(1),
+\fBnamed\fR(8).
+.SH "AUTHOR"
+.PP
+Andrew Cherenson
+.SH "COPYRIGHT"
+Copyright \(co 2004\-2007 Internet Systems Consortium, Inc. ("ISC")
+.br
diff --git a/bin/dig/nslookup.c b/bin/dig/nslookup.c
new file mode 100644
index 0000000..31be018
--- /dev/null
+++ b/bin/dig/nslookup.c
@@ -0,0 +1,891 @@
+/*
+ * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2000-2003 Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: nslookup.c,v 1.117 2007/06/18 23:47:17 tbox Exp $ */
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <isc/app.h>
+#include <isc/buffer.h>
+#include <isc/commandline.h>
+#include <isc/event.h>
+#include <isc/parseint.h>
+#include <isc/string.h>
+#include <isc/timer.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>
+
+static isc_boolean_t short_form = ISC_TRUE,
+ tcpmode = ISC_FALSE,
+ identify = ISC_FALSE, stats = ISC_TRUE,
+ comments = ISC_TRUE, section_question = ISC_TRUE,
+ section_answer = ISC_TRUE, section_authority = ISC_TRUE,
+ section_additional = ISC_TRUE, recurse = ISC_TRUE,
+ aaonly = ISC_FALSE, nofail = ISC_TRUE;
+
+static isc_boolean_t in_use = ISC_FALSE;
+static char defclass[MXRD] = "IN";
+static char deftype[MXRD] = "A";
+static isc_event_t *global_event = NULL;
+
+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);
+
+void
+dighost_shutdown(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
+printa(dns_rdata_t *rdata) {
+ isc_result_t result;
+ char text[sizeof("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 */
+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(ISC_FALSE);
+}
+#endif
+static void
+printrdata(dns_rdata_t *rdata) {
+ isc_result_t result;
+ isc_buffer_t *b = NULL;
+ unsigned int size = 1024;
+ isc_boolean_t done = ISC_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 = ISC_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, isc_boolean_t 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:
+ if (section != DNS_SECTION_ANSWER)
+ goto def_short_section;
+ dns_name_format(name, namebuf,
+ sizeof(namebuf));
+ printf("Name:\t%s\n", namebuf);
+ printa(&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, isc_boolean_t 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);
+ 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);
+}
+
+void
+received(int bytes, isc_sockaddr_t *from, dig_query_t *query)
+{
+ UNUSED(bytes);
+ UNUSED(from);
+ UNUSED(query);
+}
+
+void
+trying(char *frm, dig_lookup_t *lookup) {
+ UNUSED(frm);
+ UNUSED(lookup);
+
+}
+
+isc_result_t
+printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) {
+ char servtext[ISC_SOCKADDR_FORMATSIZE];
+
+ debug("printmessage()");
+
+ 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) {
+ isc_boolean_t headers = ISC_TRUE;
+ puts("------------");
+ /* detailheader(query, msg);*/
+ detailsection(query, msg, headers, DNS_SECTION_QUESTION);
+ detailsection(query, msg, headers, DNS_SECTION_ANSWER);
+ detailsection(query, msg, headers, DNS_SECTION_AUTHORITY);
+ detailsection(query, msg, headers, 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",
+ (msg->rcode != dns_rcode_nxdomain) ? nametext :
+ query->lookup->textname, rcodetext[msg->rcode]);
+ debug("returning with rcode == 0");
+ return (ISC_R_SUCCESS);
+ }
+
+ if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0)
+ puts("Non-authoritative answer:");
+ if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER]))
+ printsection(query, msg, headers, DNS_SECTION_ANSWER);
+ else
+ printf("*** Can't find %s: No answer\n",
+ query->lookup->textname);
+
+ if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) &&
+ (query->lookup->rdtype != dns_rdatatype_a)) {
+ 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(isc_boolean_t full, isc_boolean_t serv_only) {
+ dig_server_t *srv;
+ isc_sockaddr_t sockaddr;
+ dig_searchlist_t *listent;
+
+ srv = ISC_LIST_HEAD(server_list);
+
+ while (srv != NULL) {
+ char sockstr[ISC_SOCKADDR_FORMATSIZE];
+
+ get_address(srv->servername, port, &sockaddr);
+ 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 = %d\t\tretry = %d\tport = %d\n",
+ timeout, tries, port);
+ 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 isc_boolean_t
+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 (ISC_TRUE);
+ else {
+ printf("unknown query type: %s\n", typetext);
+ return (ISC_FALSE);
+ }
+}
+
+static isc_boolean_t
+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 (ISC_TRUE);
+ else {
+ printf("unknown query class: %s\n", typetext);
+ return (ISC_FALSE);
+ }
+}
+
+static void
+safecpy(char *dest, char *src, int size) {
+ strncpy(dest, src, size);
+ dest[size-1] = 0;
+}
+
+static isc_result_t
+parse_uint(isc_uint32_t *uip, const char *value, isc_uint32_t max,
+ const char *desc) {
+ isc_uint32_t n;
+ isc_result_t result = isc_parse_uint32(&n, value, 10);
+ if (result == ISC_R_SUCCESS && n > max)
+ result = ISC_R_RANGE;
+ if (result != ISC_R_SUCCESS) {
+ printf("invalid %s '%s': %s\n", desc,
+ value, isc_result_totext(result));
+ return result;
+ }
+ *uip = n;
+ return (ISC_R_SUCCESS);
+}
+
+static void
+set_port(const char *value) {
+ isc_uint32_t n;
+ isc_result_t result = parse_uint(&n, value, 65535, "port");
+ if (result == ISC_R_SUCCESS)
+ port = (isc_uint16_t) n;
+}
+
+static void
+set_timeout(const char *value) {
+ isc_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) {
+ isc_uint32_t n;
+ isc_result_t result = parse_uint(&n, value, INT_MAX, "tries");
+ if (result == ISC_R_SUCCESS)
+ tries = n;
+}
+
+static void
+setoption(char *opt) {
+ if (strncasecmp(opt, "all", 4) == 0) {
+ show_settings(ISC_TRUE, ISC_FALSE);
+ } else if (strncasecmp(opt, "class=", 6) == 0) {
+ if (testclass(&opt[6]))
+ safecpy(defclass, &opt[6], sizeof(defclass));
+ } else if (strncasecmp(opt, "cl=", 3) == 0) {
+ if (testclass(&opt[3]))
+ safecpy(defclass, &opt[3], sizeof(defclass));
+ } else if (strncasecmp(opt, "type=", 5) == 0) {
+ if (testtype(&opt[5]))
+ safecpy(deftype, &opt[5], sizeof(deftype));
+ } else if (strncasecmp(opt, "ty=", 3) == 0) {
+ if (testtype(&opt[3]))
+ safecpy(deftype, &opt[3], sizeof(deftype));
+ } else if (strncasecmp(opt, "querytype=", 10) == 0) {
+ if (testtype(&opt[10]))
+ safecpy(deftype, &opt[10], sizeof(deftype));
+ } else if (strncasecmp(opt, "query=", 6) == 0) {
+ if (testtype(&opt[6]))
+ safecpy(deftype, &opt[6], sizeof(deftype));
+ } else if (strncasecmp(opt, "qu=", 3) == 0) {
+ if (testtype(&opt[3]))
+ safecpy(deftype, &opt[3], sizeof(deftype));
+ } else if (strncasecmp(opt, "q=", 2) == 0) {
+ if (testtype(&opt[2]))
+ safecpy(deftype, &opt[2], sizeof(deftype));
+ } else if (strncasecmp(opt, "domain=", 7) == 0) {
+ safecpy(domainopt, &opt[7], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "do=", 3) == 0) {
+ safecpy(domainopt, &opt[3], sizeof(domainopt));
+ set_search_domain(domainopt);
+ usesearch = ISC_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 (strncasecmp(opt, "rec", 3) == 0) {
+ recurse = ISC_TRUE;
+ } else if (strncasecmp(opt, "norec", 5) == 0) {
+ recurse = ISC_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 (strncasecmp(opt, "def", 3) == 0) {
+ usesearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "nodef", 5) == 0) {
+ usesearch = ISC_FALSE;
+ } else if (strncasecmp(opt, "vc", 3) == 0) {
+ tcpmode = ISC_TRUE;
+ } else if (strncasecmp(opt, "novc", 5) == 0) {
+ tcpmode = ISC_FALSE;
+ } else if (strncasecmp(opt, "deb", 3) == 0) {
+ short_form = ISC_FALSE;
+ showsearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "nodeb", 5) == 0) {
+ short_form = ISC_TRUE;
+ showsearch = ISC_FALSE;
+ } else if (strncasecmp(opt, "d2", 2) == 0) {
+ debugging = ISC_TRUE;
+ } else if (strncasecmp(opt, "nod2", 4) == 0) {
+ debugging = ISC_FALSE;
+ } else if (strncasecmp(opt, "search", 3) == 0) {
+ usesearch = ISC_TRUE;
+ } else if (strncasecmp(opt, "nosearch", 5) == 0) {
+ usesearch = ISC_FALSE;
+ } else if (strncasecmp(opt, "sil", 3) == 0) {
+ /* deprecation_msg = ISC_FALSE; */
+ } else if (strncasecmp(opt, "fail", 3) == 0) {
+ nofail=ISC_FALSE;
+ } else if (strncasecmp(opt, "nofail", 3) == 0) {
+ nofail=ISC_TRUE;
+ } 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()");
+ 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, ISC_TRUE)
+ == ISC_R_SUCCESS) {
+ safecpy(lookup->textname, store, sizeof(lookup->textname));
+ lookup->rdtype = dns_rdatatype_ptr;
+ lookup->rdtypeset = ISC_TRUE;
+ } else {
+ safecpy(lookup->textname, opt, sizeof(lookup->textname));
+ lookup->rdtype = rdtype;
+ lookup->rdtypeset = ISC_TRUE;
+ }
+ lookup->rdclass = rdclass;
+ lookup->rdclassset = ISC_TRUE;
+ lookup->trace = ISC_FALSE;
+ lookup->trace_root = lookup->trace;
+ lookup->ns_search_only = ISC_FALSE;
+ lookup->identify = identify;
+ lookup->recurse = recurse;
+ lookup->aaonly = aaonly;
+ lookup->retries = tries;
+ lookup->udpsize = 0;
+ lookup->comments = comments;
+ 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 = ISC_TRUE;
+ if (nofail)
+ lookup->servfail_stops = ISC_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
+get_next_command(void) {
+ char *buf;
+ char *ptr, *arg;
+ char *input;
+
+ fflush(stdout);
+ buf = isc_mem_allocate(mctx, COMMSIZE);
+ if (buf == NULL)
+ fatal("memory allocation failure");
+ fputs("> ", stderr);
+ fflush(stderr);
+ isc_app_block();
+ ptr = fgets(buf, COMMSIZE, stdin);
+ isc_app_unblock();
+ if (ptr == NULL) {
+ in_use = ISC_FALSE;
+ goto cleanup;
+ }
+ input = buf;
+ ptr = next_token(&input, " \t\r\n");
+ if (ptr == NULL)
+ goto cleanup;
+ 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 = ISC_FALSE;
+ isc_app_unblock();
+ show_settings(ISC_TRUE, ISC_TRUE);
+ } else if (strcasecmp(ptr, "exit") == 0) {
+ in_use = ISC_FALSE;
+ goto cleanup;
+ } else if (strcasecmp(ptr, "help") == 0 ||
+ strcasecmp(ptr, "?") == 0) {
+ printf("The '%s' command is not yet implemented.\n", ptr);
+ goto cleanup;
+ } 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);
+ goto cleanup;
+ } else
+ addlookup(ptr);
+ cleanup:
+ isc_mem_free(mctx, buf);
+}
+
+static void
+parse_args(int argc, char **argv) {
+ isc_boolean_t have_lookup = ISC_FALSE;
+
+ usesearch = ISC_TRUE;
+ for (argc--, argv++; argc > 0; argc--, argv++) {
+ debug("main parsing %s", argv[0]);
+ if (argv[0][0] == '-') {
+ if (argv[0][1] != 0)
+ setoption(&argv[0][1]);
+ else
+ have_lookup = ISC_TRUE;
+ } else {
+ if (!have_lookup) {
+ have_lookup = ISC_TRUE;
+ in_use = ISC_TRUE;
+ addlookup(argv[0]);
+ } else {
+ set_nameserver(argv[0]);
+ check_ra = ISC_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);
+ if (l->timer != NULL)
+ isc_timer_detach(&l->timer);
+ 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;
+
+ ISC_LIST_INIT(lookup_list);
+ ISC_LIST_INIT(server_list);
+ ISC_LIST_INIT(search_list);
+
+ check_ra = ISC_TRUE;
+
+ result = isc_app_start();
+ check_result(result, "isc_app_start");
+
+ setup_libs();
+ progname = argv[0];
+
+ parse_args(argc, argv);
+
+ setup_system();
+ 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 = ISC_TF(!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 (0);
+}
diff --git a/bin/dig/nslookup.docbook b/bin/dig/nslookup.docbook
new file mode 100644
index 0000000..6c94809
--- /dev/null
+++ b/bin/dig/nslookup.docbook
@@ -0,0 +1,496 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
+ [<!ENTITY mdash "&#8212;">]>
+<!--
+ - Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and/or distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+
+<!-- $Id: nslookup.docbook,v 1.16 2007/06/18 23:47:17 tbox Exp $ -->
+<!--
+ - 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. All advertising materials mentioning features or use of this software
+ - must display the following acknowledgement:
+ - This product includes software developed by the University of
+ - California, Berkeley and its contributors.
+ - 4. 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.
+-->
+<refentry>
+
+ <refentryinfo>
+ <date>Jun 30, 2000</date>
+ </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>
+ <holder>Internet Systems Consortium, Inc. ("ISC")</holder>
+ </copyright>
+ </docinfo>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>nslookup</command>
+ <arg><option>-option</option></arg>
+ <arg choice="opt">name | -</arg>
+ <arg choice="opt">server</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>DESCRIPTION</title>
+ <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>
+ </refsect1>
+
+ <refsect1>
+ <title>ARGUMENTS</title>
+ <para>
+ Interactive mode is entered in the following cases:
+ <orderedlist numeration="loweralpha">
+ <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>
+ <programlisting>
+nslookup -query=hinfo -timeout=10
+</programlisting>
+ </informalexample>
+ </para>
+
+ </refsect1>
+
+ <refsect1>
+ <title>INTERACTIVE COMMANDS</title>
+ <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>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>
+ </refsect1>
+
+ <refsect1>
+ <title>FILES</title>
+ <para><filename>/etc/resolv.conf</filename>
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>SEE ALSO</title>
+ <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>
+ </refsect1>
+
+ <refsect1>
+ <title>Author</title>
+ <para>
+ Andrew Cherenson
+ </para>
+ </refsect1>
+</refentry><!--
+ - Local variables:
+ - mode: sgml
+ - End:
+-->
diff --git a/bin/dig/nslookup.html b/bin/dig/nslookup.html
new file mode 100644
index 0000000..0f38176
--- /dev/null
+++ b/bin/dig/nslookup.html
@@ -0,0 +1,307 @@
+<!--
+ - Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
+ -
+ - Permission to use, copy, modify, and distribute this software for any
+ - purpose with or without fee is hereby granted, provided that the above
+ - copyright notice and this permission notice appear in all copies.
+ -
+ - THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ - AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ - OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ - PERFORMANCE OF THIS SOFTWARE.
+-->
+<!-- $Id: nslookup.html,v 1.21 2007/05/16 06:12:01 marka Exp $ -->
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>nslookup</title>
+<meta name="generator" content="DocBook XSL Stylesheets V1.71.1">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="refentry" lang="en">
+<a name="id2476276"></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="refsect1" lang="en">
+<a name="id2543355"></a><h2>DESCRIPTION</h2>
+<p><span><strong class="command">Nslookup</strong></span>
+ is a program to query Internet domain name servers. <span><strong class="command">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="refsect1" lang="en">
+<a name="id2543371"></a><h2>ARGUMENTS</h2>
+<p>
+ Interactive mode is entered in the following cases:
+ </p>
+<div class="orderedlist"><ol type="a">
+<li><p>
+ when no arguments are given (the default name server will be used)
+ </p></li>
+<li><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>
+<div class="informalexample"><pre class="programlisting">
+nslookup -query=hinfo -timeout=10
+</pre></div>
+<p>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2543413"></a><h2>INTERACTIVE COMMANDS</h2>
+<div class="variablelist"><dl>
+<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>
+<dt><span class="term"><code class="constant">all</code></span></dt>
+<dd><p>
+ Prints the current values of the frequently used
+ options to <span><strong class="command">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>
+<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">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="refsect1" lang="en">
+<a name="id2546279"></a><h2>FILES</h2>
+<p><code class="filename">/etc/resolv.conf</code>
+ </p>
+</div>
+<div class="refsect1" lang="en">
+<a name="id2546291"></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 class="refsect1" lang="en">
+<a name="id2546325"></a><h2>Author</h2>
+<p>
+ Andrew Cherenson
+ </p>
+</div>
+</div></body>
+</html>
diff --git a/bin/dig/win32/dig.dsp b/bin/dig/win32/dig.dsp
new file mode 100644
index 0000000..4051643
--- /dev/null
+++ b/bin/dig/win32/dig.dsp
@@ -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 "Win32 (x86) Console Application" 0x0103
+
+CFG=dig - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "dig - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "dig - Win32 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 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/dig.exe"
+
+!ELSEIF "$(CFG)" == "dig - Win32 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 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# 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:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/dig.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "dig - Win32 Release"
+# Name "dig - Win32 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 b/bin/dig/win32/dig.mak
new file mode 100644
index 0000000..e6eb21c
--- /dev/null
+++ b/bin/dig/win32/dig.mak
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on dig.dsp
+!IF "$(CFG)" == ""
+CFG=dig - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to dig - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "dig - Win32 Release" && "$(CFG)" != "dig - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dig - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "dig - Win32 Debug" (based on "Win32 (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 - Win32 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 - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\dig.exe"
+
+!ELSE
+
+ALL : "liblwres - Win32 Release" "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\dig.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN" "liblwres - Win32 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 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\dig.pch" /YX /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/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\dig.pdb" /machine:I386 /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\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 - Win32 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 - Win32 Debug" "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\dig.exe" "$(OUTDIR)\dig.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN" "liblwres - Win32 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 /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /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/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\dig.pdb" /debug /machine:I386 /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\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 - Win32 Release" || "$(CFG)" == "dig - Win32 Debug"
+SOURCE=..\dig.c
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+
+"$(INTDIR)\dig.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+
+"$(INTDIR)\dig.obj" "$(INTDIR)\dig.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "dig - Win32 Release"
+
+"liblwres - Win32 Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "dig - Win32 Debug"
+
+"liblwres - Win32 Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 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/dighost.dsp b/bin/dig/win32/dighost.dsp
new file mode 100644
index 0000000..e37031b
--- /dev/null
+++ b/bin/dig/win32/dighost.dsp
@@ -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 "Win32 (x86) Static-Link Library" 0x0104
+
+CFG=dighost - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "dighost - Win32 Release" (based on "Win32 (x86) Static-Link Library")
+!MESSAGE "dighost - Win32 Debug" (based on "Win32 (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 - Win32 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 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /YX /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 - Win32 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 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../../../" /I "../include" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "__STDC__" /D "_MBCS" /FR /YX /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 - Win32 Release"
+# Name "dighost - Win32 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/host.dsp b/bin/dig/win32/host.dsp
new file mode 100644
index 0000000..4dc4312
--- /dev/null
+++ b/bin/dig/win32/host.dsp
@@ -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 "Win32 (x86) Console Application" 0x0103
+
+CFG=host - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "host - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "host - Win32 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 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Release/dighost.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/host.exe"
+
+!ELSEIF "$(CFG)" == "host - Win32 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 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# 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:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib Debug/dighost.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/host.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "host - Win32 Release"
+# Name "host - Win32 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 b/bin/dig/win32/host.mak
new file mode 100644
index 0000000..4a72609
--- /dev/null
+++ b/bin/dig/win32/host.mak
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on host.dsp
+!IF "$(CFG)" == ""
+CFG=host - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to host - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "host - Win32 Release" && "$(CFG)" != "host - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "host - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "host - Win32 Debug" (based on "Win32 (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 - Win32 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 - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\host.exe"
+
+!ELSE
+
+ALL : "liblwres - Win32 Release" "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\host.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN" "liblwres - Win32 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 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\host.pch" /YX /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/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\host.pdb" /machine:I386 /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\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 - Win32 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 - Win32 Debug" "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\host.exe" "$(OUTDIR)\host.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN" "liblwres - Win32 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 /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /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/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\host.pdb" /debug /machine:I386 /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\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 - Win32 Release" || "$(CFG)" == "host - Win32 Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\host.c
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+
+"$(INTDIR)\host.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+
+"$(INTDIR)\host.obj" "$(INTDIR)\host.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "host - Win32 Release"
+
+"liblwres - Win32 Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "host - Win32 Debug"
+
+"liblwres - Win32 Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 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.dsp b/bin/dig/win32/nslookup.dsp
new file mode 100644
index 0000000..cc0f4ab
--- /dev/null
+++ b/bin/dig/win32/nslookup.dsp
@@ -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 "Win32 (x86) Console Application" 0x0103
+
+CFG=nslookup - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nslookup - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "nslookup - Win32 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 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /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:I386
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Release/libisc.lib ../../../lib/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /machine:I386 /out:"../../../Build/Release/nslookup.exe"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 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 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
+# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FR /FD /GZ /c
+# SUBTRACT CPP /X /u /YX
+# 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:I386 /pdbtype:sept
+# ADD LINK32 user32.lib advapi32.lib ws2_32.lib ../../../lib/isc/win32/Debug/libisc.lib ../../../lib/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /debug /machine:I386 /out:"../../../Build/Debug/nslookup.exe" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "nslookup - Win32 Release"
+# Name "nslookup - Win32 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 b/bin/dig/win32/nslookup.mak
new file mode 100644
index 0000000..6fcbf13
--- /dev/null
+++ b/bin/dig/win32/nslookup.mak
@@ -0,0 +1,425 @@
+# Microsoft Developer Studio Generated NMAKE File, Based on nslookup.dsp
+!IF "$(CFG)" == ""
+CFG=nslookup - Win32 Debug
+!MESSAGE No configuration specified. Defaulting to nslookup - Win32 Debug.
+!ENDIF
+
+!IF "$(CFG)" != "nslookup - Win32 Release" && "$(CFG)" != "nslookup - Win32 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 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "nslookup - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "nslookup - Win32 Debug" (based on "Win32 (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 - Win32 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 - Win32 Release"
+
+OUTDIR=.\Release
+INTDIR=.\Release
+
+!IF "$(RECURSE)" == "0"
+
+ALL : "..\..\..\Build\Release\nslookup.exe"
+
+!ELSE
+
+ALL : "liblwres - Win32 Release" "libbind9 - Win32 Release" "libisc - Win32 Release" "libdns - Win32 Release" "..\..\..\Build\Release\nslookup.exe"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 ReleaseCLEAN" "libisc - Win32 ReleaseCLEAN" "libbind9 - Win32 ReleaseCLEAN" "liblwres - Win32 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 /GX /O2 /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /D "WIN32" /D "__STDC__" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fp"$(INTDIR)\nslookup.pch" /YX /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/dns/win32/Release/libdns.lib ../../../lib/bind9/win32/Release/libbind9.lib ../../../lib/lwres/win32/Release/liblwres.lib /nologo /subsystem:console /incremental:no /pdb:"$(OUTDIR)\nslookup.pdb" /machine:I386 /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\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 - Win32 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 - Win32 Debug" "libbind9 - Win32 Debug" "libisc - Win32 Debug" "libdns - Win32 Debug" "..\..\..\Build\Debug\nslookup.exe" "$(OUTDIR)\nslookup.bsc"
+
+!ENDIF
+
+!IF "$(RECURSE)" == "1"
+CLEAN :"libdns - Win32 DebugCLEAN" "libisc - Win32 DebugCLEAN" "libbind9 - Win32 DebugCLEAN" "liblwres - Win32 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 /GX /ZI /Od /I "./" /I "../include" /I "../../../" /I "../../../lib/isc/win32" /I "../../../lib/isc/win32/include" /I "../../../lib/isc/include" /I "../../../lib/isc/noatomic/include" /I "../../../lib/dns/include" /I "../../../lib/bind9/include" /I "../../../lib/lwres/win32/include" /I "../../../lib/lwres/include" /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)\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/dns/win32/Debug/libdns.lib ../../../lib/bind9/win32/Debug/libbind9.lib ../../../lib/lwres/win32/Debug/liblwres.lib /nologo /subsystem:console /incremental:yes /pdb:"$(OUTDIR)\nslookup.pdb" /debug /machine:I386 /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\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 - Win32 Release" || "$(CFG)" == "nslookup - Win32 Debug"
+SOURCE=..\dighost.c
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+
+"$(INTDIR)\dighost.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+
+"$(INTDIR)\dighost.obj" "$(INTDIR)\dighost.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+SOURCE=..\nslookup.c
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+
+"$(INTDIR)\nslookup.obj" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+
+"$(INTDIR)\nslookup.obj" "$(INTDIR)\nslookup.sbr" : $(SOURCE) "$(INTDIR)"
+ $(CPP) $(CPP_PROJ) $(SOURCE)
+
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"libdns - Win32 Release" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"libdns - Win32 Debug" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libdns - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\dns\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libdns.mak" CFG="libdns - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"libisc - Win32 Release" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"libisc - Win32 Debug" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libisc - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\isc\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libisc.mak" CFG="libisc - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"libbind9 - Win32 Release" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"libbind9 - Win32 Debug" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"libbind9 - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\bind9\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\libbind9.mak" CFG="libbind9 - Win32 Debug" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ENDIF
+
+!IF "$(CFG)" == "nslookup - Win32 Release"
+
+"liblwres - Win32 Release" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 ReleaseCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Release" RECURSE=1 CLEAN
+ cd "..\..\..\bin\dig\win32"
+
+!ELSEIF "$(CFG)" == "nslookup - Win32 Debug"
+
+"liblwres - Win32 Debug" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 Debug"
+ cd "..\..\..\bin\dig\win32"
+
+"liblwres - Win32 DebugCLEAN" :
+ cd "..\..\..\lib\lwres\win32"
+ $(MAKE) /$(MAKEFLAGS) /F ".\liblwres.mak" CFG="liblwres - Win32 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