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


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


-- | Data types for DNS Query and Response. For more information, see
--   <a>http://www.ietf.org/rfc/rfc1035</a>.
module Network.DNS.Types

-- | Type for domain.
type Domain = ByteString

-- | Raw data format for resource records.
data ResourceRecord
ResourceRecord :: Domain -> TYPE -> Int -> RData -> ResourceRecord
[rrname] :: ResourceRecord -> Domain
[rrtype] :: ResourceRecord -> TYPE
[rrttl] :: ResourceRecord -> Int
[rdata] :: ResourceRecord -> RData
OptRecord :: Int -> Bool -> Int -> RData -> ResourceRecord
[orudpsize] :: ResourceRecord -> Int
[ordnssecok] :: ResourceRecord -> Bool
[orversion] :: ResourceRecord -> Int
[rdata] :: ResourceRecord -> RData

-- | Raw data format for each type.
data RData
RD_NS :: Domain -> RData
RD_CNAME :: Domain -> RData
RD_DNAME :: Domain -> RData
RD_MX :: Int -> Domain -> RData
RD_PTR :: Domain -> RData
RD_SOA :: Domain -> Domain -> Int -> Int -> Int -> Int -> Int -> RData
RD_A :: IPv4 -> RData
RD_AAAA :: IPv6 -> RData
RD_TXT :: ByteString -> RData
RD_SRV :: Int -> Int -> Int -> Domain -> RData
RD_OPT :: [OData] -> RData
RD_OTH :: ByteString -> RData
data OData
OD_ClientSubnet :: Int -> Int -> IP -> OData
OD_Unknown :: Int -> ByteString -> OData

-- | Types for resource records.
data TYPE
A :: TYPE
AAAA :: TYPE
NS :: TYPE
TXT :: TYPE
MX :: TYPE
CNAME :: TYPE
SOA :: TYPE
PTR :: TYPE
SRV :: TYPE
DNAME :: TYPE
OPT :: TYPE
UNKNOWN :: Int -> TYPE
intToType :: Int -> TYPE
typeToInt :: TYPE -> Int
data OPTTYPE
ClientSubnet :: OPTTYPE
OUNKNOWN :: Int -> OPTTYPE
intToOptType :: Int -> OPTTYPE
optTypeToInt :: OPTTYPE -> Int

-- | An enumeration of all possible DNS errors that can occur.
data DNSError

-- | The sequence number of the answer doesn't match our query. This could
--   indicate foul play.
SequenceNumberMismatch :: DNSError

-- | The request simply timed out.
TimeoutExpired :: DNSError

-- | The answer has the correct sequence number, but returned an unexpected
--   RDATA format.
UnexpectedRDATA :: DNSError

-- | The domain for query is illegal.
IllegalDomain :: DNSError

-- | The name server was unable to interpret the query.
FormatError :: DNSError

-- | The name server was unable to process this query due to a problem with
--   the name server.
ServerFailure :: DNSError

-- | Meaningful only for responses from an authoritative name server, this
--   code signifies that the domain name referenced in the query does not
--   exist.
NameError :: DNSError

-- | The name server does not support the requested kind of query.
NotImplemented :: DNSError

-- | The name server refuses to perform the specified operation for policy
--   reasons. For example, a name server may not wish to provide the
--   information to the particular requester, or a name server may not wish
--   to perform a particular operation (e.g., zone transfer) for particular
--   data.
OperationRefused :: DNSError

-- | The server detected a malformed OPT RR.
BadOptRecord :: DNSError

-- | Raw data format for DNS Query and Response.
data DNSMessage
DNSMessage :: DNSHeader -> [Question] -> [ResourceRecord] -> [ResourceRecord] -> [ResourceRecord] -> DNSMessage
[header] :: DNSMessage -> DNSHeader
[question] :: DNSMessage -> [Question]
[answer] :: DNSMessage -> [ResourceRecord]
[authority] :: DNSMessage -> [ResourceRecord]
[additional] :: DNSMessage -> [ResourceRecord]

-- | For backward compatibility.
type DNSFormat = DNSMessage

-- | Raw data format for the header of DNS Query and Response.
data DNSHeader
DNSHeader :: Int -> DNSFlags -> DNSHeader
[identifier] :: DNSHeader -> Int
[flags] :: DNSHeader -> DNSFlags

-- | Raw data format for the flags of DNS Query and Response.
data DNSFlags
DNSFlags :: QorR -> OPCODE -> Bool -> Bool -> Bool -> Bool -> RCODE -> DNSFlags
[qOrR] :: DNSFlags -> QorR
[opcode] :: DNSFlags -> OPCODE
[authAnswer] :: DNSFlags -> Bool
[trunCation] :: DNSFlags -> Bool
[recDesired] :: DNSFlags -> Bool
[recAvailable] :: DNSFlags -> Bool
[rcode] :: DNSFlags -> RCODE
data QorR
QR_Query :: QorR
QR_Response :: QorR
data OPCODE
OP_STD :: OPCODE
OP_INV :: OPCODE
OP_SSR :: OPCODE
data RCODE
NoErr :: RCODE
FormatErr :: RCODE
ServFail :: RCODE
NameErr :: RCODE
NotImpl :: RCODE
Refused :: RCODE
BadOpt :: RCODE

-- | Raw data format for DNS questions.
data Question
Question :: Domain -> TYPE -> Question
[qname] :: Question -> Domain
[qtype] :: Question -> TYPE
responseA :: Int -> Question -> [IPv4] -> DNSMessage
responseAAAA :: Int -> Question -> [IPv6] -> DNSMessage

module Network.DNS.Decode

-- | Parsing DNS data.
decode :: ByteString -> Either String DNSMessage

-- | Receiving DNS data from <a>Socket</a> and parse it.
receive :: Socket -> IO DNSMessage
instance GHC.Show.Show Network.DNS.Decode.RDATAParseError
instance GHC.Exception.Exception Network.DNS.Decode.RDATAParseError

module Network.DNS.Encode

-- | Composing DNS data.
encode :: DNSMessage -> ByteString

-- | Composing query. First argument is a number to identify response.
composeQuery :: Int -> [Question] -> 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 ( empty )
--   
--   &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 ( empty )
--   
--   &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 ( empty )
--   
--   &gt;&gt;&gt; normalizeRoot BS.empty
--   "."
--   </pre>
normalizeRoot :: Domain -> Domain


-- | DNS Resolver and generic (lower-level) lookup functions.
module Network.DNS.Resolver

-- | Union type for <a>FilePath</a> and <a>HostName</a>. Specify
--   <a>FilePath</a> to "resolv.conf" or numeric IP address in
--   <a>String</a> form.
--   
--   <i>Warning</i>: Only numeric IP addresses are valid
--   <tt>RCHostName</tt>s.
--   
--   Example (using Google's public DNS cache):
--   
--   <pre>
--   &gt;&gt;&gt; let cache = RCHostName "8.8.8.8"
--   </pre>
data FileOrNumericHost

-- | A path for "resolv.conf"
RCFilePath :: FilePath -> FileOrNumericHost

-- | A numeric IP address
RCHostName :: HostName -> FileOrNumericHost

-- | A numeric IP address and port number
RCHostPort :: HostName -> PortNumber -> FileOrNumericHost

-- | Type for resolver configuration. The easiest way to construct a
--   <tt>ResolvConf</tt> object is to modify the <a>defaultResolvConf</a>.
data ResolvConf
ResolvConf :: FileOrNumericHost -> Int -> Int -> Integer -> ResolvConf
[resolvInfo] :: ResolvConf -> FileOrNumericHost

-- | Timeout in micro seconds.
[resolvTimeout] :: ResolvConf -> Int

-- | The number of retries including the first try.
[resolvRetry] :: ResolvConf -> Int

-- | This field was obsoleted.
[resolvBufsize] :: ResolvConf -> Integer

-- | Return a default <a>ResolvConf</a>:
--   
--   <ul>
--   <li><a>resolvInfo</a> is <a>RCFilePath</a> "/etc/resolv.conf".</li>
--   <li><a>resolvTimeout</a> is 3,000,000 micro seconds.</li>
--   <li><a>resolvRetry</a> is 3.</li>
--   <li><a>resolvBufsize</a> is 512. (obsoleted)</li>
--   </ul>
--   
--   Example (use Google's public DNS cache instead of resolv.conf):
--   
--   <pre>
--   &gt;&gt;&gt; let cache = RCHostName "8.8.8.8"
--   
--   &gt;&gt;&gt; let rc = defaultResolvConf { resolvInfo = cache }
--   </pre>
defaultResolvConf :: ResolvConf

-- | Abstract data type of DNS Resolver seed. When implementing a DNS
--   cache, this should be re-used.
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

-- | Abstract data type of DNS Resolver When implementing a DNS cache, this
--   MUST NOT be re-used.
data Resolver
Resolver :: IO Int -> Socket -> Int -> Int -> Integer -> Resolver
[genId] :: Resolver -> IO Int
[dnsSock] :: Resolver -> Socket
[dnsTimeout] :: Resolver -> Int
[dnsRetry] :: Resolver -> Int
[dnsBufsize] :: Resolver -> Integer

-- | Giving a thread-safe <a>Resolver</a> to the function of the second
--   argument. A socket for UDP is opened inside and is surely closed.
--   Multiple <a>withResolver</a>s can be used concurrently. Multiple
--   lookups must be done sequentially with a given <a>Resolver</a>. If
--   multiple <a>Resolver</a>s are necessary for concurrent purpose, use
--   <a>withResolvers</a>.
withResolver :: ResolvSeed -> (Resolver -> IO a) -> IO a

-- | Giving thread-safe <a>Resolver</a>s to the function of the second
--   argument. Sockets for UDP are opened inside and are surely closed. For
--   each <a>Resolver</a>, multiple lookups must be done sequentially.
--   <a>Resolver</a>s can be used concurrently.
withResolvers :: [ResolvSeed] -> ([Resolver] -> IO a) -> IO a

-- | Look up resource records for a domain, collecting the results from the
--   ANSWER section of the response.
--   
--   We repeat an example from <a>Network.DNS.Lookup</a>:
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "www.example.com"
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookup resolver hostname A
--   Right [93.184.216.34]
--   </pre>
lookup :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RData])

-- | Look up resource records for a domain, collecting the results from the
--   AUTHORITY section of the response.
lookupAuth :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RData])

-- | Look up a name and return the entire DNS Response. Sample output is
--   included below, however it is <i>not</i> tested -- the sequence number
--   is unpredictable (it has to be!).
--   
--   The example code:
--   
--   <pre>
--   let hostname = Data.ByteString.Char8.pack "www.example.com"
--   rs &lt;- makeResolvSeed defaultResolvConf
--   withResolver rs $ resolver -&gt; lookupRaw resolver hostname 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 },
--                        },
--             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>
lookupRaw :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSMessage)

-- | Extract necessary information from <a>DNSMessage</a>
fromDNSMessage :: DNSMessage -> (DNSMessage -> a) -> Either DNSError a

-- | For backward compatibility.
fromDNSFormat :: DNSMessage -> (DNSMessage -> a) -> Either DNSError a


-- | Simple, high-level DNS lookup functions.
--   
--   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>,Int)</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:
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "www.example.com"
--   
--   &gt;&gt;&gt; let badrc = defaultResolvConf { resolvTimeout = 1 }
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed badrc
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupA resolver hostname
--   Left TimeoutExpired
--   </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>http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/type-class-extensions.html#overloaded-strings</a>
--   for more information.
module Network.DNS.Lookup

-- | Look up all 'A' records for the given hostname.
--   
--   A straightforward example:
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "www.mew.org"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupA resolver hostname
--   Right [210.130.207.72]
--   </pre>
--   
--   This function will also follow a CNAME and resolve its target if one
--   exists for the queries hostname:
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "www.kame.net"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupA resolver hostname
--   Right [203.178.141.194]
--   </pre>
lookupA :: Resolver -> Domain -> IO (Either DNSError [IPv4])

-- | Look up all (IPv6) 'AAAA' records for the given hostname.
--   
--   Examples:
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "www.wide.ad.jp"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupAAAA resolver hostname
--   Right [2001:200:dff:fff1:216:3eff:fe4b:651c]
--   </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 no MX (to prevent a deluge of spam from examples posted on the
--   internet). But remember, "no results" is still a successful result.
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "example.com"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupMX resolver hostname
--   Right []
--   </pre>
--   
--   The domain "mew.org" does however have a single MX:
--   
--   <pre>
--   &gt;&gt;&gt; let hostname = Data.ByteString.Char8.pack "mew.org"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupMX resolver hostname
--   Right [("mail.mew.org.",10)]
--   </pre>
--   
--   Also note that all hostnames are returned with a trailing dot to
--   indicate the DNS root.
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; let hostname = Data.ByteString.Char8.pack "wide.ad.jp"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; ips &lt;- withResolver rs $ \resolver -&gt; lookupAviaMX resolver hostname
--   
--   &gt;&gt;&gt; fmap sort ips
--   Right [133.138.10.34,203.178.136.49]
--   </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; let hostname = Data.ByteString.Char8.pack "mew.org"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; ns &lt;- withResolver rs $ \resolver -&gt; lookupNS resolver hostname
--   
--   &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 hostname = Data.ByteString.Char8.pack "example.com"
--   
--   &gt;&gt;&gt; 
--   
--   &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 hostname
--   
--   &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; let hostname = Data.ByteString.Char8.pack "mew.org"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupTXT resolver hostname
--   Right ["v=spf1 +mx -all"]
--   </pre>
lookupTXT :: Resolver -> Domain -> IO (Either DNSError [ByteString])

-- | 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; let hostname = Data.ByteString.Char8.pack "164.2.232.202.in-addr.arpa"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupPTR resolver hostname
--   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; let hostname = Data.ByteString.Char8.pack "202.232.2.164"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupRDNS resolver hostname
--   Right ["www.iij.ad.jp."]
--   </pre>
lookupRDNS :: Resolver -> Domain -> IO (Either DNSError [Domain])

-- | Look up all 'SRV' records for the given hostname. A SRV record
--   comprises 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; let hostname = Data.ByteString.Char8.pack "_sip._tcp.cisco.com"
--   
--   &gt;&gt;&gt; 
--   
--   &gt;&gt;&gt; rs &lt;- makeResolvSeed defaultResolvConf
--   
--   &gt;&gt;&gt; withResolver rs $ \resolver -&gt; lookupSRV resolver hostname
--   Right [(1,0,5060,"vcsgw.cisco.com.")]
--   </pre>
lookupSRV :: Resolver -> Domain -> IO (Either DNSError [(Int, Int, Int, 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. EDNS0 and TCP fallback are not supported yet.
module Network.DNS
