-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | A thread-safe DNS library for both clients and servers written in pure
--   Haskell.
@package dns
@version 4.2.0


-- | DNS message decoders.
--   
--   When in doubt, use the <a>decodeAt</a> or <a>decodeManyAt</a>
--   functions, which correctly handle <i>circle-arithmetic</i> DNS
--   timestamps, e.g., in <tt>RRSIG</tt> resource records. The
--   <a>decode</a>, and <a>decodeMany</a> functions are only appropriate in
--   pure contexts when the current time is not available, and
--   <tt>RRSIG</tt> records are not expected or desired.
--   
--   The <a>decodeMany</a> and <a>decodeManyAt</a> functions decode a
--   buffer holding one or more messages, each preceded by 16-bit length in
--   network byte order. This encoding is generally only appropriate for
--   DNS TCP, and because TCP does not preserve message boundaries, the
--   decode is prepared to return a trailing message fragment to be
--   completed and retried when more input arrives from network.
module Network.DNS.Decode

-- | Decode an input buffer containing a single encoded DNS message. If the
--   input buffer has excess content beyond the end of the message an error
--   is returned. DNS <i>circle-arithmetic</i> timestamps (e.g. in RRSIG
--   records) are interpreted at the supplied epoch time.
decodeAt :: Int64 -> ByteString -> Either DNSError DNSMessage

-- | Decode an input buffer containing a single encoded DNS message. If the
--   input buffer has excess content beyond the end of the message an error
--   is returned. DNS <i>circle-arithmetic</i> timestamps (e.g. in RRSIG
--   records) are interpreted based on a nominal time in the year 2073
--   chosen to maximize the time range for which this gives correct
--   translations of 32-bit epoch times to absolute 64-bit epoch times.
--   This will yield incorrect results starting circa 2141.
decode :: ByteString -> Either DNSError DNSMessage

-- | Decode a buffer containing multiple encoded DNS messages each preceded
--   by a 16-bit length in network byte order. Any left-over bytes of a
--   partial message after the last complete message are returned as the
--   second element of the result tuple. DNS <i>circle-arithmetic</i>
--   timestamps (e.g. in RRSIG records) are interpreted at the supplied
--   epoch time.
decodeManyAt :: Int64 -> ByteString -> Either DNSError ([DNSMessage], ByteString)

-- | Decode a buffer containing multiple encoded DNS messages each preceded
--   by a 16-bit length in network byte order. Any left-over bytes of a
--   partial message after the last complete message are returned as the
--   second element of the result tuple. DNS <i>circle-arithmetic</i>
--   timestamps (e.g. in RRSIG records) are interpreted based on a nominal
--   time in the year 2078 chosen to give correct dates for DNS timestamps
--   over a 136 year time range from the date the root zone was signed on
--   the 15th of July 2010 until the 21st of August in 2146. Outside this
--   date range the output is off by some non-zero multiple 2^32 seconds.
decodeMany :: ByteString -> Either DNSError ([DNSMessage], ByteString)


-- | DNS message encoder.
--   
--   Note: <a>DNS</a> is a client library, and its focus is on
--   <i>sending</i> <i>queries</i>, and <i>receiving</i> <i>replies</i>.
--   Thefore, while this module is reasonably adept at query generation,
--   building a DNS server with this module requires additional work to
--   handle message size limits, correct UDP truncation, proper EDNS
--   negotiation, and so on. Support for server-side DNS is at best
--   rudimentary.
--   
--   For sending queries, in most cases you should be using one of the
--   functions from <a>Lookup</a> and <a>LookupRaw</a>, or lastly, if you
--   want to handle the network reads and writes for yourself (with your
--   own code for UDP retries, TCP fallback, EDNS fallback, ...), then
--   perhaps <a>encodeQuestion</a> (letting <a>DNS</a> do the lookups for
--   you in an <tt>async</tt> thread is likely much simpler).
module Network.DNS.Encode

-- | Encode a <a>DNSMessage</a> for transmission over UDP. For transmission
--   over TCP encapsulate the result via <a>encodeVC</a>, or use
--   <a>sendVC</a>, which handles this internally. If any
--   <a>ResourceRecord</a> in the message contains incorrectly encoded
--   <a>Domain</a> name ByteStrings, this function may raise a
--   <a>DecodeError</a>.
encode :: DNSMessage -> ByteString

module Network.DNS.IO

-- | Receive and decode a single <a>DNSMessage</a> from a UDP
--   <a>Socket</a>, throwing away the client address. Messages longer than
--   <a>maxUdpSize</a> are silently truncated, but this should not occur in
--   practice, since we cap the advertised EDNS UDP buffer size limit at
--   the same value. A <a>DNSError</a> is raised if I/O or message decoding
--   fails.
receive :: Socket -> IO DNSMessage

-- | Receive and decode a single <a>DNSMessage</a> from a UDP
--   <a>Socket</a>. Messages longer than <a>maxUdpSize</a> are silently
--   truncated, but this should not occur in practice, since we cap the
--   advertised EDNS UDP buffer size limit at the same value. A
--   <a>DNSError</a> is raised if I/O or message decoding fails.
receiveFrom :: Socket -> IO (DNSMessage, SockAddr)

-- | Receive and decode a single <tt>DNSMesage</tt> from a virtual-circuit
--   (TCP). It is up to the caller to implement any desired timeout. An
--   <a>DNSError</a> is raised if I/O or message decoding fails.
receiveVC :: Socket -> IO DNSMessage

-- | Send an encoded <a>DNSMessage</a> datagram over UDP. The message
--   length is implicit in the size of the UDP datagram. With TCP you must
--   use <a>sendVC</a>, because TCP does not have message boundaries, and
--   each message needs to be prepended with an explicit length. The socket
--   must be explicitly connected to the destination nameserver.
send :: Socket -> ByteString -> IO ()

-- | Send an encoded <a>DNSMessage</a> datagram over UDP to a given
--   address. The message length is implicit in the size of the UDP
--   datagram. With TCP you must use <a>sendVC</a>, because TCP does not
--   have message boundaries, and each message needs to be prepended with
--   an explicit length.
sendTo :: Socket -> ByteString -> SockAddr -> IO ()

-- | Send a single encoded <a>DNSMessage</a> over TCP. An explicit length
--   is prepended to the encoded buffer before transmission. If you want to
--   send a batch of multiple encoded messages back-to-back over a single
--   TCP connection, and then loop to collect the results, use
--   <a>encodeVC</a> to prefix each message with a length, and then use
--   <a>sendAll</a> to send a concatenated batch of the resulting
--   encapsulated messages.
sendVC :: Socket -> ByteString -> IO ()

-- | Send one or more encoded <a>DNSMessage</a> buffers over TCP, each
--   allready encapsulated with an explicit length prefix (perhaps via
--   <a>encodeVC</a>) and then concatenated into a single buffer. DO NOT
--   use <a>sendAll</a> with UDP.
sendAll :: Socket -> ByteString -> IO ()

-- | The encoded <a>DNSMessage</a> has the specified request ID. The
--   default values of the RD, AD, CD and DO flag bits, as well as various
--   EDNS features, can be adjusted via the <a>QueryControls</a> parameter.
--   
--   The caller is responsible for generating the ID via a securely seeded
--   CSPRNG.
encodeQuestion :: Identifier -> Question -> QueryControls -> ByteString

-- | Encapsulate an encoded <a>DNSMessage</a> buffer for transmission over
--   a TCP virtual circuit. With TCP the buffer needs to start with an
--   explicit length (the length is implicit with UDP).
encodeVC :: ByteString -> ByteString

-- | Compose a response with a single IPv4 RRset. If the query had an EDNS
--   pseudo-header, a suitable EDNS pseudo-header must be added to the
--   response message, or else a <a>FormatErr</a> response must be sent.
--   The response TTL defaults to 300 seconds, and should be updated (to
--   the same value across all the RRs) if some other TTL value is more
--   appropriate.
responseA :: Identifier -> Question -> [IPv4] -> DNSMessage

-- | Compose a response with a single IPv6 RRset. If the query had an EDNS
--   pseudo-header, a suitable EDNS pseudo-header must be added to the
--   response message, or else a <a>FormatErr</a> response must be sent.
--   The response TTL defaults to 300 seconds, and should be updated (to
--   the same value across all the RRs) if some other TTL value is more
--   appropriate.
responseAAAA :: Identifier -> Question -> [IPv6] -> DNSMessage


-- | Resolver related data types.
module Network.DNS.Resolver
data ResolvConf
defaultResolvConf :: ResolvConf
resolvInfo :: ResolvConf -> FileOrNumericHost
resolvTimeout :: ResolvConf -> Int
resolvRetry :: ResolvConf -> Int
resolvConcurrent :: ResolvConf -> Bool
resolvCache :: ResolvConf -> Maybe CacheConf
resolvQueryControls :: ResolvConf -> QueryControls
data FileOrNumericHost
RCFilePath :: FilePath -> FileOrNumericHost
RCHostName :: HostName -> FileOrNumericHost
RCHostNames :: [HostName] -> FileOrNumericHost
RCHostPort :: HostName -> PortNumber -> FileOrNumericHost
data CacheConf
defaultCacheConf :: CacheConf
maximumTTL :: CacheConf -> TTL
pruningDelay :: CacheConf -> Int
data ResolvSeed

-- | Make a <a>ResolvSeed</a> from a <a>ResolvConf</a>.
--   
--   Examples:
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   </pre>
makeResolvSeed :: ResolvConf -> IO ResolvSeed
data Resolver

-- | Giving a thread-safe <a>Resolver</a> to the function of the second
--   argument.
withResolver :: ResolvSeed -> (Resolver -> IO a) -> IO a

-- | Giving thread-safe <a>Resolver</a>s to the function of the second
--   argument. For each <a>Resolver</a>, multiple lookups must be done
--   sequentially. <a>Resolver</a>s can be used concurrently.

-- | <i>Deprecated: Use withResolver with resolvConcurrent set to True</i>
withResolvers :: [ResolvSeed] -> ([Resolver] -> IO a) -> IO a

module Network.DNS.LookupRaw

-- | Look up resource records of a specified type for a domain, collecting
--   the results from the ANSWER section of the response. See the
--   documentation of <a>lookupRaw</a> to understand the concrete behavior.
--   Cache is used if <a>resolvCache</a> is <a>Just</a>.
--   
--   Example:
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookup resolver "www.example.com" A
--   Right [93.184.216.34]
--   </pre>
lookup :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RData])

-- | Look up resource records of a specified type for a domain, collecting
--   the results from the AUTHORITY section of the response. See the
--   documentation of <a>lookupRaw</a> to understand the concrete behavior.
--   Cache is used even if <a>resolvCache</a> is <a>Just</a>.
lookupAuth :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RData])

-- | Look up a name and return the entire DNS Response.
--   
--   For a given DNS server, the queries are done:
--   
--   <ul>
--   <li>A new UDP socket bound to a new local port is created and a new
--   identifier is created atomically from the cryptographically secure
--   pseudo random number generator for the target DNS server. Then UDP
--   queries are tried with the limitation of <a>resolvRetry</a> (use EDNS
--   if specifiecd). If it appears that the target DNS server does not
--   support EDNS, it falls back to traditional queries.</li>
--   <li>If the response is truncated, a new TCP socket bound to a new
--   local port is created. Then exactly one TCP query is retried.</li>
--   </ul>
--   
--   If multiple DNS servers are specified <a>ResolvConf</a> ('RCHostNames
--   ') or found (<a>RCFilePath</a>), either sequential lookup or
--   concurrent lookup is carried out:
--   
--   <ul>
--   <li>In sequential lookup (<a>resolvConcurrent</a> is False), the query
--   procedure above is processed in the order of the DNS servers
--   sequentially until a successful response is received.</li>
--   <li>In concurrent lookup (<a>resolvConcurrent</a> is True), the query
--   procedure above is processed for each DNS server concurrently. The
--   first received response is accepted even if it is an error.</li>
--   </ul>
--   
--   Cache is not used even if <a>resolvCache</a> is <a>Just</a>.
--   
--   The example code:
--   
--   <pre>
--   rs &lt;- makeResolvSeed defaultResolvConf
--   withResolver rs $ \resolver -&gt; lookupRaw resolver "www.example.com" A
--   
--   </pre>
--   
--   And the (formatted) expected output:
--   
--   <pre>
--   Right (DNSMessage
--           { header = DNSHeader
--                        { identifier = 1,
--                          flags = DNSFlags
--                                    { qOrR = QR_Response,
--                                      opcode = OP_STD,
--                                      authAnswer = False,
--                                      trunCation = False,
--                                      recDesired = True,
--                                      recAvailable = True,
--                                      rcode = NoErr,
--                                      authenData = False
--                                    },
--                        },
--             question = [Question { qname = "www.example.com.",
--                                    qtype = A}],
--             answer = [ResourceRecord {rrname = "www.example.com.",
--                                       rrtype = A,
--                                       rrttl = 800,
--                                       rdlen = 4,
--                                       rdata = 93.184.216.119}],
--             authority = [],
--             additional = []})
--   
--   </pre>
--   
--   AXFR requests cannot be performed with this interface.
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupRaw resolver "mew.org" AXFR
--   Left InvalidAXFRLookup
--   </pre>
lookupRaw :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSMessage)

-- | Similar to <a>lookupRaw</a>, but the default values of the RD, AD, CD
--   and DO flag bits, as well as various EDNS features, can be adjusted
--   via the <a>QueryControls</a> parameter.
lookupRawCtl :: Resolver -> Domain -> TYPE -> QueryControls -> IO (Either DNSError DNSMessage)

-- | Similar to <a>lookupRawCtl</a>, but the recv action can be replaced
--   with something other than <a>receive</a>. For example, in an
--   environment where frequent retrieval of the current time is a
--   performance issue, you can pass the time from outside instead of
--   having <a>receive</a> retrieve the current time.
lookupRawCtlRecv :: Resolver -> Domain -> TYPE -> QueryControls -> (Socket -> IO DNSMessage) -> IO (Either DNSError DNSMessage)

-- | Messages with a non-error RCODE are passed to the supplied function
--   for processing. Other messages are translated to <a>DNSError</a>
--   instances.
--   
--   Note that <a>NameError</a> is not a lookup error. The lookup is
--   successful, bearing the sad news that the requested domain does not
--   exist. <a>NameError</a> responses may return a meaningful AD bit, may
--   contain useful data in the authority section, and even initial CNAME
--   records that lead to the ultimately non-existent domain. Applications
--   that wish to process the content of <a>NameError</a> (NXDomain)
--   messages will need to implement their own RCODE handling.
fromDNSMessage :: DNSMessage -> (DNSMessage -> a) -> Either DNSError a


-- | Simple, high-level DNS lookup functions for clients.
--   
--   All of the lookup functions necessary run in IO since they interact
--   with the network. The return types are similar, but differ in what can
--   be returned from a successful lookup.
--   
--   We can think of the return type as either "what I asked for" or "an
--   error". For example, the <a>lookupA</a> function, if successful, will
--   return a list of <a>IPv4</a>. The <a>lookupMX</a> function will
--   instead return a list of <tt>(<a>Domain</a>,<a>Int</a>)</tt> pairs,
--   where each pair represents a hostname and its associated priority.
--   
--   The order of multiple results may not be consistent between lookups.
--   If you require consistent results, apply <a>sort</a> to the returned
--   list.
--   
--   The errors that can occur are the same for all lookups. Namely:
--   
--   <ul>
--   <li>Timeout</li>
--   <li>Wrong sequence number (foul play?)</li>
--   <li>Unexpected data in the response</li>
--   </ul>
--   
--   If an error occurs, you should be able to pattern match on the
--   <a>DNSError</a> constructor to determine which of these is the case.
--   
--   <i>Note</i>: A result of "no records" is not considered an error. If
--   you perform, say, an 'AAAA' lookup for a domain with no such records,
--   the "success" result would be <tt>Right []</tt>.
--   
--   We perform a successful lookup of "www.example.com":
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "www.example.com"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupA resolver hostname
--   Right [93.184.216.34]
--   </pre>
--   
--   The only error that we can easily cause is a timeout. We do this by
--   creating and utilizing a <a>ResolvConf</a> which has a timeout of one
--   millisecond and a very limited number of retries:
--   
--   <pre>
--   &gt;&gt;&gt; let hostname2 = Data.ByteString.Char8.pack "www.example.com"
--   
--   &gt;&gt;&gt; let badrc = defaultResolvConf { resolvTimeout = 0, resolvRetry = 1 }
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs2 &lt;- makeResolvSeed badrc
--   
--   &gt;&gt;&gt; withResolver rs2 $ \resolver -&gt; lookupA resolver hostname2
--   Left RetryLimitExceeded
--   </pre>
--   
--   As is the convention, successful results will always be wrapped in a
--   <a>Right</a> while errors will be wrapped in a <a>Left</a>.
--   
--   For convenience, you may wish to enable GHC's OverloadedStrings
--   extension. This will allow you to avoid calling <a>pack</a> on each
--   domain name. See
--   <a>https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#overloaded-string-literals</a>
--   for more information. In the following examples, we assuem this
--   extension is enabled.
--   
--   All lookup functions eventually call <a>lookupRaw</a>. See its
--   documentation to understand the concrete lookup behavior.
module Network.DNS.Lookup

-- | Look up all 'A' records for the given hostname.
--   
--   A straightforward example:
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupA resolver "192.0.2.1.nip.io"
--   Right [192.0.2.1]
--   </pre>
--   
--   This function will also follow a CNAME and resolve its target if one
--   exists for the queried hostname:
--   
--   <pre>
--   &gt;&gt;&gt; rs2 &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs2 $ \resolver -&gt; lookupA resolver "www.kame.net"
--   Right [210.155.141.200]
--   </pre>
lookupA :: Resolver -> Domain -> IO (Either DNSError [IPv4])

-- | Look up all (IPv6) 'AAAA' records for the given hostname.
--   
--   Examples:
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupAAAA resolver "www.wide.ad.jp"
--   Right [2001:200:0:180c:20c:29ff:fec9:9d61]
--   </pre>
lookupAAAA :: Resolver -> Domain -> IO (Either DNSError [IPv6])

-- | Look up all 'MX' records for the given hostname. Two parts constitute
--   an MX record: a hostname , and an integer priority. We therefore
--   return each record as a <tt>(<a>Domain</a>, Int)</tt>.
--   
--   In this first example, we look up the MX for the domain "example.com".
--   It has an RFC7505 NULL MX (to prevent a deluge of spam from examples
--   posted on the internet).
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupMX resolver "example.com"
--   Right [(".",0)]
--   </pre>
--   
--   The domain "mew.org" does however have a single MX:
--   
--   <pre>
--   &gt;&gt;&gt; rs2 &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs2 $ \resolver -&gt; lookupMX resolver "mew.org"
--   Right [("mail.mew.org.",10)]
--   </pre>
--   
--   Also note that all hostnames are returned with a trailing dot to
--   indicate the DNS root.
--   
--   However the MX host itself has no need for an MX record, so its MX
--   RRset is empty. But, "no results" is still a successful result.
--   
--   <pre>
--   &gt;&gt;&gt; rs3 &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs3 $ \resolver -&gt; lookupMX resolver "mail.mew.org"
--   Right []
--   </pre>
lookupMX :: Resolver -> Domain -> IO (Either DNSError [(Domain, Int)])

-- | Look up all 'MX' records for the given hostname, and then resolve
--   their hostnames to IPv4 addresses by calling <a>lookupA</a>. The
--   priorities are not retained.
--   
--   Examples:
--   
--   <pre>
--   &gt;&gt;&gt; import Data.List (sort)
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; ips &lt;- withResolver rs $ \resolver -&gt; lookupAviaMX resolver "wide.ad.jp"
--   
--   &gt;&gt;&gt; fmap sort ips
--   Right [203.178.136.30]
--   </pre>
--   
--   Since there is more than one result, it is necessary to sort the list
--   in order to check for equality.
lookupAviaMX :: Resolver -> Domain -> IO (Either DNSError [IPv4])

-- | Look up all 'MX' records for the given hostname, and then resolve
--   their hostnames to IPv6 addresses by calling <a>lookupAAAA</a>. The
--   priorities are not retained.
lookupAAAAviaMX :: Resolver -> Domain -> IO (Either DNSError [IPv6])

-- | Look up all 'NS' records for the given hostname. The results are taken
--   from the ANSWER section of the response (as opposed to AUTHORITY). For
--   details, see e.g. <a>http://www.zytrax.com/books/dns/ch15/</a>.
--   
--   There will typically be more than one name server for a domain. It is
--   therefore extra important to sort the results if you prefer them to be
--   at all deterministic.
--   
--   Examples:
--   
--   <pre>
--   &gt;&gt;&gt; import Data.List (sort)
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; ns &lt;- withResolver rs $ \resolver -&gt; lookupNS resolver "mew.org"
--   
--   &gt;&gt;&gt; fmap sort ns
--   Right ["ns1.mew.org.","ns2.mew.org."]
--   </pre>
lookupNS :: Resolver -> Domain -> IO (Either DNSError [Domain])

-- | Look up all 'NS' records for the given hostname. The results are taken
--   from the AUTHORITY section of the response and not the usual ANSWER
--   (use <a>lookupNS</a> for that). For details, see e.g.
--   <a>http://www.zytrax.com/books/dns/ch15/</a>.
--   
--   There will typically be more than one name server for a domain. It is
--   therefore extra important to sort the results if you prefer them to be
--   at all deterministic.
--   
--   For an example, we can look up the nameservers for "example.com" from
--   one of the root servers, a.gtld-servers.net, the IP address of which
--   was found beforehand:
--   
--   <pre>
--   &gt;&gt;&gt; import Data.List (sort)
--   
--   &gt;&gt;&gt; let ri = RCHostName "192.5.6.30" -- a.gtld-servers.net
--   
--   &gt;&gt;&gt; let rc = defaultResolvConf { resolvInfo = ri }
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed rc
--   
--   &gt;&gt;&gt; ns &lt;- withResolver rs $ \resolver -&gt; lookupNSAuth resolver "example.com"
--   
--   &gt;&gt;&gt; fmap sort ns
--   Right ["a.iana-servers.net.","b.iana-servers.net."]
--   </pre>
lookupNSAuth :: Resolver -> Domain -> IO (Either DNSError [Domain])

-- | Look up all 'TXT' records for the given hostname. The results are
--   free-form <a>ByteString</a>s.
--   
--   Two common uses for 'TXT' records are
--   <a>http://en.wikipedia.org/wiki/Sender_Policy_Framework</a> and
--   <a>http://en.wikipedia.org/wiki/DomainKeys_Identified_Mail</a>. As an
--   example, we find the SPF record for "mew.org":
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupTXT resolver "mew.org"
--   Right ["v=spf1 +mx -all"]
--   </pre>
lookupTXT :: Resolver -> Domain -> IO (Either DNSError [ByteString])

-- | Look up the 'SOA' record for the given domain. The result 7-tuple
--   consists of the 'mname', 'rname', 'serial', 'refresh', 'retry',
--   'expire' and 'minimum' fields of the SOA record.
--   
--   An @ separator is used between the first and second labels of the
--   'rname' field. Since 'rname' is an email address, it often contains
--   periods within its first label. Presently, the trailing period is not
--   removed from the domain part of the 'rname', but this may change in
--   the future. Users should be prepared to remove any trailing period
--   before using the 'rname` as a contact email address.
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; soa &lt;- withResolver rs $ \resolver -&gt; lookupSOA resolver "mew.org"
--   
--   &gt;&gt;&gt; map (\ (mn, rn, _, _, _, _, _) -&gt; (mn, rn)) &lt;$&gt; soa
--   Right [("ns1.mew.org.","kazu@mew.org.")]
--   </pre>
lookupSOA :: Resolver -> Domain -> IO (Either DNSError [(Domain, Mailbox, Word32, Word32, Word32, Word32, Word32)])

-- | Look up all 'PTR' records for the given hostname. To perform a reverse
--   lookup on an IP address, you must first reverse its octets and then
--   append the suffix ".in-addr.arpa."
--   
--   We look up the PTR associated with the IP address 210.130.137.80,
--   i.e., 80.137.130.210.in-addr.arpa:
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupPTR resolver "180.2.232.202.in-addr.arpa"
--   Right ["www.iij.ad.jp."]
--   </pre>
--   
--   The <a>lookupRDNS</a> function is more suited to this particular task.
lookupPTR :: Resolver -> Domain -> IO (Either DNSError [Domain])

-- | Convenient wrapper around <a>lookupPTR</a> to perform a reverse lookup
--   on a single IP address.
--   
--   We repeat the example from <a>lookupPTR</a>, except now we pass the IP
--   address directly:
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupRDNS resolver "202.232.2.180"
--   Right ["www.iij.ad.jp."]
--   </pre>
lookupRDNS :: Resolver -> Domain -> IO (Either DNSError [Domain])

-- | Look up all 'SRV' records for the given hostname. SRV records consist
--   (see <a>https://tools.ietf.org/html/rfc2782</a>) of the following four
--   fields:
--   
--   <ul>
--   <li>Priority (lower is more-preferred)</li>
--   <li>Weight (relative frequency with which to use this record amongst
--   all results with the same priority)</li>
--   <li>Port (the port on which the service is offered)</li>
--   <li>Target (the hostname on which the service is offered)</li>
--   </ul>
--   
--   The first three are integral, and the target is another DNS hostname.
--   We therefore return a four-tuple <tt>(Int,Int,Int,<a>Domain</a>)</tt>.
--   
--   Examples:
--   
--   <pre>
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupSRV resolver "_xmpp-server._tcp.jabber.ietf.org"
--   Right [(5,0,5269,"_dc-srv.6661af51975d._xmpp-server._tcp.jabber.ietf.org.")]
--   </pre>
lookupSRV :: Resolver -> Domain -> IO (Either DNSError [(Word16, Word16, Word16, Domain)])


-- | Data types for DNS Query and Response. For more information, see
--   <a>http://www.ietf.org/rfc/rfc1035</a>.
module Network.DNS.Types
data ResourceRecord
ResourceRecord :: !Domain -> !TYPE -> !CLASS -> !TTL -> !RData -> ResourceRecord
[rrname] :: ResourceRecord -> !Domain
[rrtype] :: ResourceRecord -> !TYPE
[rrclass] :: ResourceRecord -> !CLASS
[rrttl] :: ResourceRecord -> !TTL
[rdata] :: ResourceRecord -> !RData
type Answers = [ResourceRecord]
type AuthorityRecords = [ResourceRecord]
type AdditionalRecords = [ResourceRecord]
type Domain = ByteString
type CLASS = Word16
classIN :: CLASS
type TTL = Word32
data TYPE
pattern A :: TYPE
pattern NS :: TYPE
pattern CNAME :: TYPE
pattern SOA :: TYPE
pattern NULL :: TYPE
pattern PTR :: TYPE
pattern MX :: TYPE
pattern TXT :: TYPE
pattern AAAA :: TYPE
pattern SRV :: TYPE
pattern DNAME :: TYPE
pattern OPT :: TYPE
pattern DS :: TYPE
pattern RRSIG :: TYPE
pattern NSEC :: TYPE
pattern DNSKEY :: TYPE
pattern NSEC3 :: TYPE
pattern NSEC3PARAM :: TYPE
pattern TLSA :: TYPE
pattern CDS :: TYPE
pattern CDNSKEY :: TYPE
pattern CSYNC :: TYPE
pattern AXFR :: TYPE
pattern ANY :: TYPE
pattern CAA :: TYPE
fromTYPE :: TYPE -> Word16
toTYPE :: Word16 -> TYPE
data RData
RD_A :: IPv4 -> RData
RD_NS :: Domain -> RData
RD_CNAME :: Domain -> RData
RD_SOA :: Domain -> Mailbox -> Word32 -> Word32 -> Word32 -> Word32 -> Word32 -> RData
RD_NULL :: ByteString -> RData
RD_PTR :: Domain -> RData
RD_MX :: Word16 -> Domain -> RData
RD_TXT :: ByteString -> RData
RD_RP :: Mailbox -> Domain -> RData
RD_AAAA :: IPv6 -> RData
RD_SRV :: Word16 -> Word16 -> Word16 -> Domain -> RData
RD_DNAME :: Domain -> RData
RD_OPT :: [OData] -> RData
RD_DS :: Word16 -> Word8 -> Word8 -> ByteString -> RData
RD_RRSIG :: RD_RRSIG -> RData
RD_NSEC :: Domain -> [TYPE] -> RData
RD_DNSKEY :: Word16 -> Word8 -> Word8 -> ByteString -> RData
RD_NSEC3 :: Word8 -> Word8 -> Word16 -> ByteString -> ByteString -> [TYPE] -> RData
RD_NSEC3PARAM :: Word8 -> Word8 -> Word16 -> ByteString -> RData
RD_TLSA :: Word8 -> Word8 -> Word8 -> ByteString -> RData
RD_CDS :: Word16 -> Word8 -> Word8 -> ByteString -> RData
RD_CDNSKEY :: Word16 -> Word8 -> Word8 -> ByteString -> RData
RD_CAA :: Word8 -> CI ByteString -> ByteString -> RData
UnknownRData :: ByteString -> RData
data RD_RRSIG
RDREP_RRSIG :: !TYPE -> !Word8 -> !Word8 -> !Word32 -> !Int64 -> !Int64 -> !Word16 -> !Domain -> !ByteString -> RD_RRSIG
[rrsigType] :: RD_RRSIG -> !TYPE
[rrsigKeyAlg] :: RD_RRSIG -> !Word8
[rrsigNumLabels] :: RD_RRSIG -> !Word8
[rrsigTTL] :: RD_RRSIG -> !Word32
[rrsigExpiration] :: RD_RRSIG -> !Int64
[rrsigInception] :: RD_RRSIG -> !Int64
[rrsigKeyTag] :: RD_RRSIG -> !Word16
[rrsigZone] :: RD_RRSIG -> !Domain
[rrsigValue] :: RD_RRSIG -> !ByteString
dnsTime :: Word32 -> Int64 -> Int64
data DNSMessage
DNSMessage :: !DNSHeader -> EDNSheader -> [Question] -> Answers -> AuthorityRecords -> AdditionalRecords -> DNSMessage
[header] :: DNSMessage -> !DNSHeader
[ednsHeader] :: DNSMessage -> EDNSheader
[question] :: DNSMessage -> [Question]
[answer] :: DNSMessage -> Answers
[authority] :: DNSMessage -> AuthorityRecords
[additional] :: DNSMessage -> AdditionalRecords
makeQuery :: Identifier -> Question -> QueryControls -> DNSMessage
makeEmptyQuery :: QueryControls -> DNSMessage
defaultQuery :: DNSMessage
data QueryControls
rdFlag :: FlagOp -> QueryControls
adFlag :: FlagOp -> QueryControls
cdFlag :: FlagOp -> QueryControls
doFlag :: FlagOp -> QueryControls
ednsEnabled :: FlagOp -> QueryControls
ednsSetVersion :: Maybe Word8 -> QueryControls
ednsSetUdpSize :: Maybe Word16 -> QueryControls
ednsSetOptions :: ODataOp -> QueryControls
data FlagOp
FlagSet :: FlagOp
FlagClear :: FlagOp
FlagReset :: FlagOp
FlagKeep :: FlagOp
data ODataOp
ODataAdd :: [OData] -> ODataOp
ODataSet :: [OData] -> ODataOp
defaultResponse :: DNSMessage
makeResponse :: Identifier -> Question -> Answers -> DNSMessage
data DNSHeader
DNSHeader :: !Identifier -> !DNSFlags -> DNSHeader
[identifier] :: DNSHeader -> !Identifier
[flags] :: DNSHeader -> !DNSFlags
type Identifier = Word16
data DNSFlags
DNSFlags :: !QorR -> !OPCODE -> !Bool -> !Bool -> !Bool -> !Bool -> !RCODE -> !Bool -> !Bool -> DNSFlags
[qOrR] :: DNSFlags -> !QorR
[opcode] :: DNSFlags -> !OPCODE
[authAnswer] :: DNSFlags -> !Bool
[trunCation] :: DNSFlags -> !Bool
[recDesired] :: DNSFlags -> !Bool
[recAvailable] :: DNSFlags -> !Bool
[rcode] :: DNSFlags -> !RCODE
[authenData] :: DNSFlags -> !Bool
[chkDisable] :: DNSFlags -> !Bool
data QorR
QR_Query :: QorR
QR_Response :: QorR
defaultDNSFlags :: DNSFlags
data OPCODE
OP_STD :: OPCODE
OP_INV :: OPCODE
OP_SSR :: OPCODE
OP_NOTIFY :: OPCODE
OP_UPDATE :: OPCODE
fromOPCODE :: OPCODE -> Word16
toOPCODE :: Word16 -> Maybe OPCODE
data RCODE
pattern NoErr :: RCODE
pattern FormatErr :: RCODE
pattern ServFail :: RCODE
pattern NameErr :: RCODE
pattern NotImpl :: RCODE
pattern Refused :: RCODE
pattern YXDomain :: RCODE
pattern YXRRSet :: RCODE
pattern NXRRSet :: RCODE
pattern NotAuth :: RCODE
pattern NotZone :: RCODE
pattern BadVers :: RCODE
pattern BadKey :: RCODE
pattern BadTime :: RCODE
pattern BadMode :: RCODE
pattern BadName :: RCODE
pattern BadAlg :: RCODE
pattern BadTrunc :: RCODE
pattern BadCookie :: RCODE
pattern BadRCODE :: RCODE
fromRCODE :: RCODE -> Word16
toRCODE :: Word16 -> RCODE
data EDNSheader
EDNSheader :: EDNS -> EDNSheader
NoEDNS :: EDNSheader
InvalidEDNS :: EDNSheader
ifEDNS :: EDNSheader -> a -> a -> a
mapEDNS :: EDNSheader -> (EDNS -> a) -> a -> a
data EDNS
EDNS :: !Word8 -> !Word16 -> !Bool -> ![OData] -> EDNS
[ednsVersion] :: EDNS -> !Word8
[ednsUdpSize] :: EDNS -> !Word16
[ednsDnssecOk] :: EDNS -> !Bool
[ednsOptions] :: EDNS -> ![OData]
defaultEDNS :: EDNS
maxUdpSize :: Word16
minUdpSize :: Word16
data OData
OD_NSID :: ByteString -> OData
OD_DAU :: [Word8] -> OData
OD_DHU :: [Word8] -> OData
OD_N3U :: [Word8] -> OData
OD_ClientSubnet :: Word8 -> Word8 -> IP -> OData
OD_ECSgeneric :: Word16 -> Word8 -> Word8 -> ByteString -> OData
UnknownOData :: Word16 -> ByteString -> OData
data OptCode
pattern ClientSubnet :: OptCode
pattern DAU :: OptCode
pattern DHU :: OptCode
pattern N3U :: OptCode
pattern NSID :: OptCode
fromOptCode :: OptCode -> Word16
toOptCode :: Word16 -> OptCode
data Question
Question :: Domain -> TYPE -> Question
[qname] :: Question -> Domain
[qtype] :: Question -> TYPE
data DNSError
SequenceNumberMismatch :: DNSError
QuestionMismatch :: DNSError
InvalidAXFRLookup :: DNSError
RetryLimitExceeded :: DNSError
TimeoutExpired :: DNSError
UnexpectedRDATA :: DNSError
IllegalDomain :: DNSError
FormatError :: DNSError
ServerFailure :: DNSError
NameError :: DNSError
NotImplemented :: DNSError
OperationRefused :: DNSError
BadOptRecord :: DNSError
BadConfiguration :: DNSError
NetworkFailure :: IOException -> DNSError
DecodeError :: String -> DNSError
UnknownDNSError :: DNSError
type Mailbox = ByteString


-- | Miscellaneous utility functions for processing DNS data.
module Network.DNS.Utils

-- | Perform both <a>normalizeCase</a> and <a>normalizeRoot</a> on the
--   given <a>Domain</a>. When comparing DNS names taken from user input,
--   this is often necessary to avoid unexpected results.
--   
--   <i>Examples</i>:
--   
--   <pre>
--   &gt;&gt;&gt; let domain1 = BS.pack "ExAmPlE.COM"
--   
--   &gt;&gt;&gt; let domain2 = BS.pack "example.com."
--   
--   &gt;&gt;&gt; domain1 == domain2
--   False
--   
--   &gt;&gt;&gt; normalize domain1 == normalize domain2
--   True
--   </pre>
--   
--   The <a>normalize</a> function should be idempotent:
--   
--   <pre>
--   &gt;&gt;&gt; normalize (normalize domain1) == normalize domain1
--   True
--   </pre>
--   
--   Ensure that we don't crash on the empty <a>Domain</a>:
--   
--   <pre>
--   &gt;&gt;&gt; import qualified Data.ByteString.Char8 as BS
--   
--   &gt;&gt;&gt; normalize BS.empty
--   "."
--   </pre>
normalize :: Domain -> Domain

-- | Normalize the case of the given DNS name for comparisons.
--   
--   According to RFC #1035, "For all parts of the DNS that are part of the
--   official protocol, all comparisons between character strings (e.g.,
--   labels, domain names, etc.) are done in a case-insensitive manner."
--   This function chooses to lowercase its argument, but that should be
--   treated as an implementation detail if at all possible.
--   
--   <i>Examples</i>:
--   
--   <pre>
--   &gt;&gt;&gt; let domain1 = BS.pack "ExAmPlE.COM"
--   
--   &gt;&gt;&gt; let domain2 = BS.pack "exAMPle.com"
--   
--   &gt;&gt;&gt; domain1 == domain2
--   False
--   
--   &gt;&gt;&gt; normalizeCase domain1 == normalizeCase domain2
--   True
--   </pre>
--   
--   The <a>normalizeCase</a> function should be idempotent:
--   
--   <pre>
--   &gt;&gt;&gt; normalizeCase (normalizeCase domain2) == normalizeCase domain2
--   True
--   </pre>
--   
--   Ensure that we don't crash on the empty <a>Domain</a>:
--   
--   <pre>
--   &gt;&gt;&gt; import qualified Data.ByteString.Char8 as BS
--   
--   &gt;&gt;&gt; normalizeCase BS.empty
--   ""
--   </pre>
normalizeCase :: Domain -> Domain

-- | Normalize the given name by appending a trailing dot (the DNS root) if
--   one does not already exist.
--   
--   Warning: this does not produce an equivalent DNS name! However, users
--   are often unaware of the effect that the absence of the root will
--   have. In user interface design, it may therefore be wise to act as if
--   the user supplied the trailing dot during comparisons.
--   
--   Per RFC #1034,
--   
--   "Since a complete domain name ends with the root label, this leads to
--   a printed form which ends in a dot. We use this property to
--   distinguish between:
--   
--   <ul>
--   <li>a character string which represents a complete domain name (often
--   called 'absolute'). For example, 'poneria.ISI.EDU.'</li>
--   <li>a character string that represents the starting labels of a domain
--   name which is incomplete, and should be completed by local software
--   using knowledge of the local domain (often called 'relative'). For
--   example, 'poneria' used in the ISI.EDU domain.</li>
--   </ul>
--   
--   Relative names are either taken relative to a well known origin, or to
--   a list of domains used as a search list. Relative names appear mostly
--   at the user interface, where their interpretation varies from
--   implementation to implementation, and in master files, where they are
--   relative to a single origin domain name."
--   
--   <i>Examples</i>:
--   
--   <pre>
--   &gt;&gt;&gt; let domain1 = BS.pack "example.com"
--   
--   &gt;&gt;&gt; let domain2 = BS.pack "example.com."
--   
--   &gt;&gt;&gt; domain1 == domain2
--   False
--   
--   &gt;&gt;&gt; normalizeRoot domain1 == normalizeRoot domain2
--   True
--   </pre>
--   
--   The <a>normalizeRoot</a> function should be idempotent:
--   
--   <pre>
--   &gt;&gt;&gt; normalizeRoot (normalizeRoot domain1) == normalizeRoot domain1
--   True
--   </pre>
--   
--   Ensure that we don't crash on the empty <a>Domain</a>:
--   
--   <pre>
--   &gt;&gt;&gt; import qualified Data.ByteString.Char8 as BS
--   
--   &gt;&gt;&gt; normalizeRoot BS.empty
--   "."
--   </pre>
normalizeRoot :: Domain -> Domain

-- | Split a domain name in A-label form into its initial label and the
--   rest of the domain. Returns an error if the initial label is
--   malformed. When no more labels remain, the initial label will satisfy
--   <a>null</a>.
--   
--   This also decodes any escaped characters in the initial label, which
--   may therefore contain whitespace, binary data, or unescaped internal
--   dots. To reconstruct the original domain, the initial label may
--   sometimes require correct escaping of special characters.
--   
--   <h4><b>Examples</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; import Data.ByteString.Char8 as BS
--   
--   &gt;&gt;&gt; splitDomain $ BS.pack "abc\\.def.xyz"
--   Right ("abc.def","xyz")
--   </pre>
--   
--   <pre>
--   &gt;&gt;&gt; splitDomain $ BS.pack ".abc.def.xyz"
--   Left (DecodeError "invalid domain: .abc.def.xyz")
--   </pre>
splitDomain :: Domain -> Either DNSError (ByteString, Domain)

-- | Split a <a>Mailbox</a> in A-label form into its initial label
--   <a>ByteString</a> (the <i>localpart</i> of the email address) and the
--   remaining <a>Domain</a> (the <i>domainpart</i> of the email address,
--   with a possible trailing <tt><a>.</a></tt>). Returns an error if the
--   initial label is malformed. When no more labels remain, the initial
--   label will satisfy <a>null</a>. The remaining labels can be obtained
--   by applying <a>splitDomain</a> the returned domain part.
--   
--   This also decodes any escaped characters in the initial label, which
--   may therefore contain whitespace, binary data, or unescaped internal
--   dots. To reconstruct the original mailbox, the initial label may
--   sometimes require correct escaping of special characters.
--   
--   <h4><b>Example</b></h4>
--   
--   <pre>
--   &gt;&gt;&gt; import Data.ByteString.Char8 as BS
--   
--   &gt;&gt;&gt; splitMailbox $ BS.pack "Joe.Admin@example.com."
--   Right ("Joe.Admin","example.com.")
--   </pre>
splitMailbox :: Mailbox -> Either DNSError (ByteString, Domain)


-- | A thread-safe DNS library for both clients and servers written in pure
--   Haskell. The Network.DNS module re-exports all other exposed modules
--   for convenience. Applications will most likely use the high-level
--   interface, while library/daemon authors may need to use the
--   lower-level one. EDNS and TCP fallback are supported.
--   
--   Examples:
--   
--   <pre>
--   &gt;&gt;&gt; :set -XOverloadedStrings
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupA resolver "192.0.2.1.nip.io"
--   Right [192.0.2.1]
--   </pre>
module Network.DNS
