record is changed.
.P
Haeredes can alert administrators when NS/MX records are changed.
+.SH NORMALIZATION
+.P
+By default, domain/hostnames given will be normalized in two ways:
+.IP \[bu] 2
+All names will be lowercased.
+
+.IP \[bu]
+All names will have a trailing dot (the DNS root) appended if one is
+not present. This can be controlled with the
+\fB\-\-no\-append\-root\fR flag.
+.SH QUERY RESULTS
+.P
+When Haeredes makes a query for an MX record, the result is parsed
+from the \(dqanswer\(dq section of the response. This is
+straightforward.
+.P
+For NS records, however, there are two sections that may contain
+results. If you query the authoritative nameservers for example.com,
+they will return the response in the \(dqanswer\(dq section, as with
+MX records:
+
+.nf
+.I $ dig +short @a.iana-servers.net example.com NS
+b.iana-servers.net.
+a.iana-servers.net.
+.fi
+.P
+However, if you ask a root server, they will return the response in
+another section, called \(dqauthority\(dq. The \(dqanswer\(dq section
+is empty:
+
+.nf
+.I $ dig +short @a.gtld-servers.net example.com NS
+.fi
+.P
+We have to request the \(dqauthority\(dq section explicitly:
+
+.nf
+.I $ dig +noall +authority @a.gtld-servers.net example.com NS
+example.com. 172800 IN NS a.iana-servers.net.
+example.com. 172800 IN NS b.iana-servers.net.
+.fi
+.P
+Given Haeredes' use case, it is useful to combine the two. You can
+query a root server to check the registrar data, or a recursive
+resolver to check the data on the authoritative nameservers.
+.P
+So that's what we do. In NS mode, Haeredes will check both the
+\(dqanswer\(dq and \(dqauthority\(dq sections for results.
+.SH PARALLEL QUERIES
+.P
+Haeredes can use multiple threads to perform its queries. It will use
+a number of threads equal to the number of processors available to the
+GHC runtime. This can be changed with the \fI+RTS \-N\fR flag. For
+example, to use 10 threads,
+
+.nf
+$ haeredes [OPTIONS] [DELEGATES] \fI+RTS -N10\fR
+.fi
+.SH DNS ERRORS
+.P
+There are three types of DNS errors that can occur:
+.nr step 1 1
+.IP \n[step] 2
+Timeouts. If the query times out, we don't get an answer back. The
+timeout can be adjusted with the \fB\-\-timeout\fR flag.
+.IP \n+[step]
+Sequence number mismatches. Every DNS query is sent with a sequence
+number; if the response has a different sequence number than the one
+we sent, something is wrong (foul play, or a bug somewhere in the
+stack).
+.IP \n+[step]
+Unexpected RDATA. If we ask for an \fIA\fR record, we expect to get a
+response for an \fIA\fR record. If we get something else -- well,
+something went wrong.
+.P
+Haeredes is designed to ignore these errors. A timeout or bad response
+to a query is not an indication that something is wrong with the DNS
+for the supplied domains. There might be something else wrong with
+your (caching/recursive) DNS infrastructure, but it isn't one of the
+problems that Haeredes is designed to detect.
.SH OPTIONS
+.IP \fB\-\-no\-append\-root\fR,\ \fB-n\fR
+Don't append a trailing dot to any DNS names. If you know what you're
+doing, this can be used to check relative results. Otherwise, it will
+probably just lead to false positives.
.IP \fB\-\-server\fR,\ \fB-s\fR
Use the given DNS server rather than the resolvers listed in
-/etc/resolv.conf.
+/etc/resolv.conf. Either an IP address or a hostname will work.
+.IP \fB\-\-timeout\fR,\ \fB-t\fR
+The number of seconds to wait for an answer from DNS (default: 15).
.SH EXAMPLES
.IP \[bu] 2
[ab].iana-servers.net:
.nf
-.I $ haeredes a.iana-servers.net b.iana-servers.net <<< \(dqexample.com\(dq
+.I $ echo \(dqexample.com\(dq | haeredes a.iana-servers.net b.iana-servers.net
+.fi
+
+.IP \[bu] 2
+If you use \-\-no\-append\-root and your nameservers are rooted, you
+must remember to supply the trailing dot yourself. Otherwise, you'll
+get false positives.
+
+.nf
+.I $ echo \(dqexample.com\(dq | \\\\
+.I " haeredes \-\-no\-append\-root a.iana-servers.net b.iana-servers.net"
+Domain \(dqexample.com\(dq delegates somewhere else:
+\(dqa.iana-servers.net.\(dq \(dqb.iana-servers.net.\(dq
.fi
.IP \[bu]
Check orlitzky.com against the expected name servers, using
-d.gtld-servers.net:
+a root nameserver (this checks the registrar configuration):
.nf
-.I $ haeredes --server 199.7.91.13 dns1.viabit.com dns2.viabit.com \\\\
-.I " <<< \(dqorlitzky.com\(dq"
+.I $ echo \(dqorlitzky.com\(dq | \\\\
+.I " haeredes --server d.gtld-servers.net" \\\\
+.I " dns1.viabit.com dns2.viabit.com"
.fi
.IP \[bu]
Check orlitzky.com against only one of the expected two nameservers:
.nf
-.I $ haeredes dns1.viabit.com <<< \(dqorlitzky.com\(dq
+.I $ echo \(dqorlitzky.com\(dq | haeredes dns1.viabit.com
Domain \(dqorlitzky.com.\(dq delegates somewhere else: \
\(dqdns2.viabit.com.\(dq
.fi
.IP \[bu]
Check a nonexistent domain (we provide no delegates, since we
-know .invalid will not be delegated):
+know .doesnt-exist will not be delegated):
+
+.nf
+.I $ echo \(dqfoo.doesnt-exist\(dq | haeredes
+Domain \(dqfoo.doesnt-exist.\(dq not delegated.
+.fi
+.IP \[bu]
+Set the timeout to one second, and query a nonexistent
+nameserver. This should result in a timeout, which will be ignored per
+the discussion in \fBDNS ERRORS\fR:
.nf
-.I $ haeredes <<< \(dqexample.invalid\(dq
-Domain \(dqexample.invalid.\(dq not delegated.
+.I $ echo \(dqexample.com\(dq | \\\\
+.I " haeredes --timeout=1 --server 10.1.46.12 ns1.example.com"
.fi
.SH BUGS
.P