-- 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 4.0.1 -- | DNS message decoders. -- -- When in doubt, use the decodeAt or decodeManyAt -- functions, which correctly handle circle-arithmetic DNS -- timestamps, e.g., in RRSIG resource records. The -- decode, and decodeMany functions are only appropriate in -- pure contexts when the current time is not available, and -- RRSIG records are not expected or desired. -- -- The decodeMany and decodeManyAt 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 circle-arithmetic 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 circle-arithmetic 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 circle-arithmetic -- 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 circle-arithmetic -- 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: DNS is a client library, and its focus is on -- sending queries, and receiving replies. -- 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 Lookup and LookupRaw, 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 encodeQuestion (letting DNS do the lookups for -- you in an async thread is likely much simpler). module Network.DNS.Encode -- | Encode a DNSMessage for transmission over UDP. For transmission -- over TCP encapsulate the result via encodeVC, or use -- sendVC, which handles this internally. If any -- ResourceRecord in the message contains incorrectly encoded -- Domain name ByteStrings, this function may raise a -- DecodeError. encode :: DNSMessage -> ByteString module Network.DNS.IO -- | Receive and decode a single DNSMessage from a UDP -- Socket. Messages longer than maxUdpSize 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 -- DNSError is raised if I/O or message decoding fails. receive :: Socket -> IO DNSMessage -- | Receive and decode a single DNSMesage from a virtual-circuit -- (TCP). It is up to the caller to implement any desired timeout. An -- DNSError is raised if I/O or message decoding fails. receiveVC :: Socket -> IO DNSMessage -- | Send an encoded DNSMessage datagram over UDP. The message -- length is implicit in the size of the UDP datagram. With TCP you must -- use sendVC, 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 a single encoded DNSMessage 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 -- encodeVC to prefix each message with a length, and then use -- sendAll to send a concatenated batch of the resulting -- encapsulated messages. sendVC :: Socket -> ByteString -> IO () -- | Send one or more encoded DNSMessage buffers over TCP, each -- allready encapsulated with an explicit length prefix (perhaps via -- encodeVC) and then concatenated into a single buffer. DO NOT -- use sendAll with UDP. sendAll :: Socket -> ByteString -> IO () -- | The encoded DNSMessage 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 QueryControls parameter. -- -- The caller is responsible for generating the ID via a securely seeded -- CSPRNG. encodeQuestion :: Identifier -> Question -> QueryControls -> ByteString -- | Encapsulate an encoded DNSMessage 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 FormatErr 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 FormatErr 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 -- | Type for resolver configuration. Use defaultResolvConf to -- create a new value. -- -- An example to use Google's public DNS cache instead of resolv.conf: -- --
--   >>> let conf = defaultResolvConf { resolvInfo = RCHostName "8.8.8.8" }
--   
-- -- An example to use multiple Google's public DNS cache concurrently: -- --
--   >>> let conf = defaultResolvConf { resolvInfo = RCHostNames ["8.8.8.8","8.8.4.4"], resolvConcurrent = True }
--   
-- -- An example to disable EDNS: -- --
--   >>> let conf = defaultResolvConf { resolvQueryControls = ednsEnabled FlagClear }
--   
-- -- An example to enable query result caching: -- --
--   >>> let conf = defaultResolvConf { resolvCache = Just defaultCacheConf }
--   
-- -- An example to disable requesting recursive service. -- --
--   >>> let conf = defaultResolvConf { resolvQueryControls = rdFlag FlagClear }
--   
-- -- An example to set the AD bit in all queries by default. -- --
--   >>> let conf = defaultResolvConf { resolvQueryControls = adFlag FlagSet }
--   
-- -- An example to set the both the AD and CD bits in all queries by -- default. -- --
--   >>> let conf = defaultResolvConf { resolvQueryControls = adFlag FlagSet <> cdFlag FlagSet }
--   
-- -- An example with an EDNS buffer size of 1216 bytes, which is more -- robust with IPv6, and the DO bit set to request DNSSEC responses. -- --
--   >>> let conf = defaultResolvConf { resolvQueryControls = ednsSetUdpSize (Just 1216) <> doFlag FlagSet }
--   
data ResolvConf -- | Return a default ResolvConf: -- -- defaultResolvConf :: ResolvConf -- | Server information. resolvInfo :: ResolvConf -> FileOrNumericHost -- | Timeout in micro seconds. resolvTimeout :: ResolvConf -> Int -- | The number of retries including the first try. resolvRetry :: ResolvConf -> Int -- | Concurrent queries if multiple DNS servers are specified. resolvConcurrent :: ResolvConf -> Bool -- | Cache configuration. resolvCache :: ResolvConf -> Maybe CacheConf -- | Overrides for the default flags used for queries via resolvers that -- use this configuration. resolvQueryControls :: ResolvConf -> QueryControls -- | The type to specify a cache server. data FileOrNumericHost -- | A path for "resolv.conf" where one or more IP addresses of DNS servers -- should be found on Unix. Default DNS servers are automatically -- detected on Windows regardless of the value of the file name. RCFilePath :: FilePath -> FileOrNumericHost -- | A numeric IP address. Warning: host names are invalid. RCHostName :: HostName -> FileOrNumericHost -- | Numeric IP addresses. Warning: host names are invalid. RCHostNames :: [HostName] -> FileOrNumericHost -- | A numeric IP address and port number. Warning: host names are -- invalid. RCHostPort :: HostName -> PortNumber -> FileOrNumericHost -- | Cache configuration for responses. data CacheConf -- | Default cache configuration. -- --
--   >>> defaultCacheConf
--   CacheConf {maximumTTL = 300, pruningDelay = 10}
--   
defaultCacheConf :: CacheConf -- | If RR's TTL is higher than this value, this value is used instead. maximumTTL :: CacheConf -> TTL -- | Cache pruning interval in seconds. pruningDelay :: CacheConf -> Int -- | Intermediate abstract data type for resolvers. IP address information -- of DNS servers is generated according to resolvInfo internally. -- This value can be safely reused for withResolver. -- -- The naming is confusing for historical reasons. data ResolvSeed -- | Make a ResolvSeed from a ResolvConf. -- -- Examples: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
makeResolvSeed :: ResolvConf -> IO ResolvSeed -- | Abstract data type of DNS Resolver. This includes newly seeded -- identifier generators for all specified DNS servers and a cache -- database. data Resolver -- | Giving a thread-safe Resolver to the function of the second -- argument. withResolver :: ResolvSeed -> (Resolver -> IO a) -> IO a -- | Giving thread-safe Resolvers to the function of the second -- argument. For each Resolver, multiple lookups must be done -- sequentially. Resolvers can be used concurrently. -- | Deprecated: Use withResolver with resolvConcurrent set to True 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 lookupRaw to understand the concrete behavior. -- Cache is used if resolvCache is Just. -- -- Example: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookup resolver "www.example.com" A
--   Right [93.184.216.34]
--   
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 lookupRaw to understand the concrete behavior. -- Cache is used even if resolvCache is Just. 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: -- -- -- -- If multiple DNS servers are specified ResolvConf ('RCHostNames -- ') or found (RCFilePath), either sequential lookup or -- concurrent lookup is carried out: -- -- -- -- Cache is not used even if resolvCache is Just. -- -- The example code: -- --
--   rs <- makeResolvSeed defaultResolvConf
--   withResolver rs $ \resolver -> lookupRaw resolver "www.example.com" A
--   
--   
-- -- And the (formatted) expected output: -- --
--   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 = []})
--   
--   
-- -- AXFR requests cannot be performed with this interface. -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupRaw resolver "mew.org" AXFR
--   Left InvalidAXFRLookup
--   
lookupRaw :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSMessage) -- | Similar to lookupRaw, but the default values of the RD, AD, CD -- and DO flag bits, as well as various EDNS features, can be adjusted -- via the QueryControls parameter. lookupRawCtl :: Resolver -> Domain -> TYPE -> QueryControls -> IO (Either DNSError DNSMessage) -- | Messages with a non-error RCODE are passed to the supplied function -- for processing. Other messages are translated to DNSError -- instances. -- -- Note that NameError is not a lookup error. The lookup is -- successful, bearing the sad news that the requested domain does not -- exist. NameError 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 NameError (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 lookupA function, if successful, will -- return a list of IPv4. The lookupMX function will -- instead return a list of (Domain,Int) 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 sort to the returned -- list. -- -- The errors that can occur are the same for all lookups. Namely: -- -- -- -- If an error occurs, you should be able to pattern match on the -- DNSError constructor to determine which of these is the case. -- -- Note: 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 Right []. -- -- We perform a successful lookup of "www.example.com": -- --
--   >>> let hostname = Data.ByteString.Char8.pack "www.example.com"
--   
--   >>> 
--   
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupA resolver hostname
--   Right [93.184.216.34]
--   
-- -- The only error that we can easily cause is a timeout. We do this by -- creating and utilizing a ResolvConf which has a timeout of one -- millisecond and a very limited number of retries: -- --
--   >>> let hostname = Data.ByteString.Char8.pack "www.example.com"
--   
--   >>> let badrc = defaultResolvConf { resolvTimeout = 0, resolvRetry = 1 }
--   
--   >>> 
--   
--   >>> rs <- makeResolvSeed badrc
--   
--   >>> withResolver rs $ \resolver -> lookupA resolver hostname
--   Left RetryLimitExceeded
--   
-- -- As is the convention, successful results will always be wrapped in a -- Right while errors will be wrapped in a Left. -- -- For convenience, you may wish to enable GHC's OverloadedStrings -- extension. This will allow you to avoid calling pack on each -- domain name. See -- https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#overloaded-string-literals -- for more information. In the following examples, we assuem this -- extension is enabled. -- -- All lookup functions eventually call lookupRaw. 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: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupA resolver "192.0.2.1.nip.io"
--   Right [192.0.2.1]
--   
-- -- This function will also follow a CNAME and resolve its target if one -- exists for the queried hostname: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupA resolver "www.kame.net"
--   Right [203.178.141.194]
--   
lookupA :: Resolver -> Domain -> IO (Either DNSError [IPv4]) -- | Look up all (IPv6) 'AAAA' records for the given hostname. -- -- Examples: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupAAAA resolver "www.wide.ad.jp"
--   Right [2001:200:dff:fff1:216:3eff:fe4b:651c]
--   
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 (Domain, Int). -- -- 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). -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupMX resolver "example.com"
--   Right [(".",0)]
--   
-- -- The domain "mew.org" does however have a single MX: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupMX resolver "mew.org"
--   Right [("mail.mew.org.",10)]
--   
-- -- 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. -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupMX resolver "mail.mew.org"
--   Right []
--   
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 lookupA. The -- priorities are not retained. -- -- Examples: -- --
--   >>> import Data.List (sort)
--   
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> ips <- withResolver rs $ \resolver -> lookupAviaMX resolver "wide.ad.jp"
--   
--   >>> fmap sort ips
--   Right [133.138.10.39,203.178.136.30]
--   
-- -- 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 lookupAAAA. 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. http://www.zytrax.com/books/dns/ch15/. -- -- 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: -- --
--   >>> import Data.List (sort)
--   
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> ns <- withResolver rs $ \resolver -> lookupNS resolver "mew.org"
--   
--   >>> fmap sort ns
--   Right ["ns1.mew.org.","ns2.mew.org."]
--   
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 lookupNS for that). For details, see e.g. -- http://www.zytrax.com/books/dns/ch15/. -- -- 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: -- --
--   >>> import Data.List (sort)
--   
--   >>> let ri = RCHostName "192.5.6.30" -- a.gtld-servers.net
--   
--   >>> let rc = defaultResolvConf { resolvInfo = ri }
--   
--   >>> rs <- makeResolvSeed rc
--   
--   >>> ns <- withResolver rs $ \resolver -> lookupNSAuth resolver "example.com"
--   
--   >>> fmap sort ns
--   Right ["a.iana-servers.net.","b.iana-servers.net."]
--   
lookupNSAuth :: Resolver -> Domain -> IO (Either DNSError [Domain]) -- | Look up all 'TXT' records for the given hostname. The results are -- free-form ByteStrings. -- -- Two common uses for 'TXT' records are -- http://en.wikipedia.org/wiki/Sender_Policy_Framework and -- http://en.wikipedia.org/wiki/DomainKeys_Identified_Mail. As an -- example, we find the SPF record for "mew.org": -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupTXT resolver "mew.org"
--   Right ["v=spf1 +mx -all"]
--   
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. -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> soa <- withResolver rs $ \resolver -> lookupSOA resolver "mew.org"
--   
--   >>> map (\ (mn, rn, _, _, _, _, _) -> (mn, rn)) <$> soa
--   Right [("ns1.mew.org.","kazu@mew.org.")]
--   
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: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupPTR resolver "164.2.232.202.in-addr.arpa"
--   Right ["www.iij.ad.jp."]
--   
-- -- The lookupRDNS function is more suited to this particular task. lookupPTR :: Resolver -> Domain -> IO (Either DNSError [Domain]) -- | Convenient wrapper around lookupPTR to perform a reverse lookup -- on a single IP address. -- -- We repeat the example from lookupPTR, except now we pass the IP -- address directly: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupRDNS resolver "202.232.2.164"
--   Right ["www.iij.ad.jp."]
--   
lookupRDNS :: Resolver -> Domain -> IO (Either DNSError [Domain]) -- | Look up all 'SRV' records for the given hostname. SRV records consist -- (see https://tools.ietf.org/html/rfc2782) of the following four -- fields: -- -- -- -- The first three are integral, and the target is another DNS hostname. -- We therefore return a four-tuple (Int,Int,Int,Domain). -- -- Examples: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupSRV resolver "_xmpp-server._tcp.jabber.ietf.org"
--   Right [(5,0,5269,"jabber.ietf.org.")]
--   
lookupSRV :: Resolver -> Domain -> IO (Either DNSError [(Word16, Word16, Word16, Domain)]) -- | Data types for DNS Query and Response. For more information, see -- http://www.ietf.org/rfc/rfc1035. module Network.DNS.Types -- | Raw data format for resource records. data ResourceRecord ResourceRecord :: !Domain -> !TYPE -> !CLASS -> !TTL -> !RData -> ResourceRecord -- | Name [rrname] :: ResourceRecord -> !Domain -- | Resource record type [rrtype] :: ResourceRecord -> !TYPE -- | Resource record class [rrclass] :: ResourceRecord -> !CLASS -- | Time to live [rrttl] :: ResourceRecord -> !TTL -- | Resource data [rdata] :: ResourceRecord -> !RData -- | Type alias for resource records in the answer section. type Answers = [ResourceRecord] -- | Type alias for resource records in the answer section. type AuthorityRecords = [ResourceRecord] -- | Type for resource records in the additional section. type AdditionalRecords = [ResourceRecord] -- | This type holds the presentation form of fully-qualified DNS -- domain names encoded as ASCII A-labels, with '.' separators between -- labels. Non-printing characters are escaped as \DDD (a -- backslash, followed by three decimal digits). The special characters: -- ", $, (, ), ;, @, and \ are escaped by prepending a -- backslash. The trailing '.' is optional on input, but is recommended, -- and is always added when decoding from wire form. -- -- The encoding of domain names to wire form, e.g. for -- transmission in a query, requires the input encodings to be valid, -- otherwise a DecodeError may be thrown. Domain names received in -- wire form in DNS messages are escaped to this presentation form as -- part of decoding the DNSMessage. -- -- This form is ASCII-only. Any conversion between A-label -- ByteStrings, and U-label Text happens at whatever -- layer maps user input to DNS names, or presents friendly DNS -- names to the user. Not all users can read all scripts, and -- applications that default to U-label form should ideally give the user -- a choice to see the A-label form. Examples: -- --
--   www.example.org.           -- Ordinary DNS name.
--   _25._tcp.mx1.example.net.  -- TLSA RR initial labels have _ prefixes.
--   \001.exotic.example.       -- First label is Ctrl-A!
--   just\.one\.label.example.  -- First label is "just.one.label"
--   
type Domain = ByteString -- | Resource record class. type CLASS = Word16 -- | Resource record class for the Internet. classIN :: CLASS -- | Time to live in second. type TTL = Word32 -- | Types for resource records. data TYPE -- | IPv4 address pattern A :: () => () => TYPE -- | An authoritative name serve pattern NS :: () => () => TYPE -- | The canonical name for an alias pattern CNAME :: () => () => TYPE -- | Marks the start of a zone of authority pattern SOA :: () => () => TYPE -- | A null RR (EXPERIMENTAL) pattern NULL :: () => () => TYPE -- | A domain name pointer pattern PTR :: () => () => TYPE -- | Mail exchange pattern MX :: () => () => TYPE -- | Text strings pattern TXT :: () => () => TYPE -- | IPv6 Address pattern AAAA :: () => () => TYPE -- | Server Selection (RFC2782) pattern SRV :: () => () => TYPE -- | DNAME (RFC6672) pattern DNAME :: () => () => TYPE -- | OPT (RFC6891) pattern OPT :: () => () => TYPE -- | Delegation Signer (RFC4034) pattern DS :: () => () => TYPE -- | RRSIG (RFC4034) pattern RRSIG :: () => () => TYPE -- | NSEC (RFC4034) pattern NSEC :: () => () => TYPE -- | DNSKEY (RFC4034) pattern DNSKEY :: () => () => TYPE -- | NSEC3 (RFC5155) pattern NSEC3 :: () => () => TYPE -- | NSEC3PARAM (RFC5155) pattern NSEC3PARAM :: () => () => TYPE -- | TLSA (RFC6698) pattern TLSA :: () => () => TYPE -- | Child DS (RFC7344) pattern CDS :: () => () => TYPE -- | DNSKEY(s) the Child wants reflected in DS (RFC7344) pattern CDNSKEY :: () => () => TYPE -- | Child-To-Parent Synchronization (RFC7477) pattern CSYNC :: () => () => TYPE -- | Zone transfer (RFC5936) pattern AXFR :: () => () => TYPE -- | A request for all records the server/cache has available pattern ANY :: () => () => TYPE -- | Certification Authority Authorization (RFC6844) pattern CAA :: () => () => TYPE -- | From type to number. fromTYPE :: TYPE -> Word16 -- | From number to type. toTYPE :: Word16 -> TYPE -- | Raw data format for each type. data RData -- | IPv4 address RD_A :: IPv4 -> RData -- | An authoritative name serve RD_NS :: Domain -> RData -- | The canonical name for an alias RD_CNAME :: Domain -> RData -- | Marks the start of a zone of authority RD_SOA :: Domain -> Mailbox -> Word32 -> Word32 -> Word32 -> Word32 -> Word32 -> RData -- | NULL RR (EXPERIMENTAL, RFC1035). RD_NULL :: ByteString -> RData -- | A domain name pointer RD_PTR :: Domain -> RData -- | Mail exchange RD_MX :: Word16 -> Domain -> RData -- | Text strings RD_TXT :: ByteString -> RData -- | IPv6 Address RD_AAAA :: IPv6 -> RData -- | Server Selection (RFC2782) RD_SRV :: Word16 -> Word16 -> Word16 -> Domain -> RData -- | DNAME (RFC6672) RD_DNAME :: Domain -> RData -- | OPT (RFC6891) RD_OPT :: [OData] -> RData -- | Delegation Signer (RFC4034) RD_DS :: Word16 -> Word8 -> Word8 -> ByteString -> RData -- | DNSSEC signature RD_RRSIG :: RD_RRSIG -> RData -- | DNSSEC denial of existence NSEC record RD_NSEC :: Domain -> [TYPE] -> RData -- | DNSKEY (RFC4034) RD_DNSKEY :: Word16 -> Word8 -> Word8 -> ByteString -> RData -- | DNSSEC hashed denial of existence (RFC5155) RD_NSEC3 :: Word8 -> Word8 -> Word16 -> ByteString -> ByteString -> [TYPE] -> RData -- | NSEC3 zone parameters (RFC5155) RD_NSEC3PARAM :: Word8 -> Word8 -> Word16 -> ByteString -> RData -- | TLSA (RFC6698) RD_TLSA :: Word8 -> Word8 -> Word8 -> ByteString -> RData -- | Child DS (RFC7344) RD_CDS :: Word16 -> Word8 -> Word8 -> ByteString -> RData -- | Child DNSKEY (RFC7344) RD_CSYNC RD_CDNSKEY :: Word16 -> Word8 -> Word8 -> ByteString -> RData -- | Unknown resource data UnknownRData :: ByteString -> RData -- | RRSIG representation. -- -- As noted in Section 3.1.5 of RFC 4034 the RRsig inception and -- expiration times use serial number arithmetic. As a result these -- timestamps are not pure values, their meaning is -- time-dependent! They depend on the present time and are both at most -- approximately +/-68 years from the present. This ambiguity is not a -- problem because cached RRSIG records should only persist a few days, -- signature lifetimes should be *much* shorter than 68 years, and key -- rotation should result any misconstrued 136-year-old signatures fail -- to validate. This also means that the interpretation of a time that is -- exactly half-way around the clock at now +/-0x80000000 is not -- important, the signature should never be valid. -- -- The upshot for us is that we need to convert these *impure* relative -- values to pure absolute values at the moment they are received from -- from the network (or read from files, ... in some impure I/O context), -- and convert them back to 32-bit values when encoding. Therefore, the -- constructor takes absolute 64-bit representations of the inception and -- expiration times. -- -- The dnsTime function performs the requisite conversion. data RD_RRSIG RDREP_RRSIG :: !TYPE -> !Word8 -> !Word8 -> !Word32 -> !Int64 -> !Int64 -> !Word16 -> !Domain -> !ByteString -> RD_RRSIG -- | RRtype of RRset signed [rrsigType] :: RD_RRSIG -> !TYPE -- | DNSKEY algorithm [rrsigKeyAlg] :: RD_RRSIG -> !Word8 -- | Number of labels signed [rrsigNumLabels] :: RD_RRSIG -> !Word8 -- | Maximum origin TTL [rrsigTTL] :: RD_RRSIG -> !Word32 -- | Time last valid [rrsigExpiration] :: RD_RRSIG -> !Int64 -- | Time first valid [rrsigInception] :: RD_RRSIG -> !Int64 -- | Signing key tag [rrsigKeyTag] :: RD_RRSIG -> !Word16 -- | Signing domain [rrsigZone] :: RD_RRSIG -> !Domain -- | Opaque signature [rrsigValue] :: RD_RRSIG -> !ByteString -- | Given a 32-bit circle-arithmetic DNS time, and the current absolute -- epoch time, return the epoch time corresponding to the DNS timestamp. dnsTime :: Word32 -> Int64 -> Int64 -- | DNS message format for queries and replies. data DNSMessage DNSMessage :: !DNSHeader -> EDNSheader -> [Question] -> Answers -> AuthorityRecords -> AdditionalRecords -> DNSMessage -- | Header with extended RCODE [header] :: DNSMessage -> !DNSHeader -- | EDNS pseudo-header [ednsHeader] :: DNSMessage -> EDNSheader -- | The question for the name server [question] :: DNSMessage -> [Question] -- | RRs answering the question [answer] :: DNSMessage -> Answers -- | RRs pointing toward an authority [authority] :: DNSMessage -> AuthorityRecords -- | RRs holding additional information [additional] :: DNSMessage -> AdditionalRecords -- | Construct a complete query DNSMessage, by combining the -- defaultQuery template with the specified Identifier, and -- Question. The QueryControls can be mempty to -- leave all header and EDNS settings at their default values, or some -- combination of overrides. A default set of overrides can be enabled -- via the resolvQueryControls field of ResolvConf. -- Per-query overrides are possible by using loookupRawCtl. makeQuery :: Identifier -> Question -> QueryControls -> DNSMessage -- | A query template with QueryControls overrides applied, with -- just the Question and query Identifier remaining to be -- filled in. makeEmptyQuery :: QueryControls -> DNSMessage -- | A DNSMessage template for queries with default settings for the -- message DNSHeader and EDNSheader. This is the initial -- query message state, before customization via QueryControls. defaultQuery :: DNSMessage -- | Query controls form a Monoid, as with function composition, the -- left-most value has the last say. The Monoid is generated by -- two sets of combinators, one that controls query-related DNS header -- flags, and another that controls EDNS features. -- -- The header flag controls are: rdFlag, adFlag and -- cdFlag. -- -- The EDNS feature controls are: doFlag, ednsEnabled, -- ednsSetVersion, ednsSetUdpSize and -- ednsSetOptions. When EDNS is disabled, all the other -- EDNS-related controls have no effect. -- -- Example: Disable DNSSEC checking on the server, and request -- signatures and NSEC records, perhaps for your own independent -- validation. The UDP buffer size is set large, for use with a local -- loopback nameserver on the same host. -- --
--   >>> :{
--   mconcat [ adFlag FlagClear
--           , cdFlag FlagSet
--           , doFlag FlagSet
--           , ednsSetUdpSize (Just 8192) -- IPv4 loopback server?
--           ]
--   :}
--   ad:0,cd:1,edns.udpsize:8192,edns.dobit:1
--   
-- -- Example: Use EDNS version 1 (yet to be specified), request -- nameserver ids from the server, and indicate a client subnet of -- "192.0.2.1/24". -- --
--   >>> :set -XOverloadedStrings
--   
--   >>> let emptyNSID = ""
--   
--   >>> let mask = 24
--   
--   >>> let ipaddr = read "192.0.2.1"
--   
--   >>> :{
--   mconcat [ ednsSetVersion (Just 1)
--           , ednsSetOptions (ODataAdd [OD_NSID emptyNSID])
--           , ednsSetOptions (ODataAdd [OD_ClientSubnet mask 0 ipaddr])
--           ]
--   :}
--   edns.version:1,edns.options:[NSID,ClientSubnet]
--   
data QueryControls -- | Generator of QueryControls that adjusts the RD bit. -- --
--   >>> rdFlag FlagClear
--   rd:0
--   
rdFlag :: FlagOp -> QueryControls -- | Generator of QueryControls that adjusts the AD bit. -- --
--   >>> adFlag FlagSet
--   ad:1
--   
adFlag :: FlagOp -> QueryControls -- | Generator of QueryControls that adjusts the CD bit. -- --
--   >>> cdFlag FlagSet
--   cd:1
--   
cdFlag :: FlagOp -> QueryControls -- | Generator of QueryControls that adjusts the EDNS -- DnssecOk (DO) bit. -- --
--   >>> doFlag FlagSet
--   edns.dobit:1
--   
doFlag :: FlagOp -> QueryControls -- | Generator of QueryControls that enables or disables EDNS -- support. When EDNS is disabled, the rest of the EDNS controls -- are ignored. -- --
--   >>> ednsHeader $ makeEmptyQuery $ ednsEnabled FlagClear <> doFlag FlagSet
--   NoEDNS
--   
ednsEnabled :: FlagOp -> QueryControls -- | Generator of QueryControls that adjusts the EDNS -- version. A value of Nothing makes no changes, while Just -- v sets the EDNS version to v. -- --
--   >>> ednsSetVersion (Just 1)
--   edns.version:1
--   
ednsSetVersion :: Maybe Word8 -> QueryControls -- | Generator of QueryControls that adjusts the EDNS UDP -- buffer size. A value of Nothing makes no changes, while -- Just n sets the EDNS UDP buffer size to n. -- --
--   >>> ednsSetUdpSize (Just 2048)
--   edns.udpsize:2048
--   
ednsSetUdpSize :: Maybe Word16 -> QueryControls -- | Generator of QueryControls that adjusts the list of EDNS -- options. -- --
--   >>> :set -XOverloadedStrings
--   
--   >>> ednsSetOptions (ODataAdd [OD_NSID ""])
--   edns.options:[NSID]
--   
ednsSetOptions :: ODataOp -> QueryControls -- | Boolean flag operations. These form a Monoid. When combined via -- mappend, as with function composition, the left-most value has -- the last say. -- --
--   >>> mempty :: FlagOp
--   FlagKeep
--   
--   >>> FlagSet <> mempty
--   FlagSet
--   
--   >>> FlagClear <> FlagSet <> mempty
--   FlagClear
--   
--   >>> FlagReset <> FlagClear <> FlagSet <> mempty
--   FlagReset
--   
data FlagOp -- | Set the flag to 1 FlagSet :: FlagOp -- | Clear the flag to 0 FlagClear :: FlagOp -- | Reset the flag to its default value FlagReset :: FlagOp -- | Leave the flag unchanged FlagKeep :: FlagOp -- | The default EDNS Option list is empty. We define two operations, one -- to prepend a list of options, and another to set a specific list of -- options. data ODataOp -- | Add the specified options to the list. ODataAdd :: [OData] -> ODataOp -- | Set the option list as specified. ODataSet :: [OData] -> ODataOp -- | Default response. When responding to EDNS queries, the response must -- either be an EDNS response, or else FormatErr must be returned. The -- default response message has EDNS disabled (ednsHeader set to -- NoEDNS), it should be updated as appropriate. -- -- Do not explicitly add OPT RRs to the additional section, instead let -- the encoder compute and add the OPT record based on the EDNS -- pseudo-header. -- -- The RCODE in the DNSHeader should be set to the -- appropriate 12-bit extended value, which will be split between the -- primary header and EDNS OPT record during message encoding (low 4 bits -- in DNS header, high 8 bits in EDNS OPT record). See EDNSheader -- for more details. defaultResponse :: DNSMessage -- | Construct a query response DNSMessage. makeResponse :: Identifier -> Question -> Answers -> DNSMessage -- | Raw data format for the header of DNS Query and Response. data DNSHeader DNSHeader :: !Identifier -> !DNSFlags -> DNSHeader -- | Query or reply identifier. [identifier] :: DNSHeader -> !Identifier -- | Flags, OPCODE, and RCODE [flags] :: DNSHeader -> !DNSFlags -- | An identifier assigned by the program that generates any kind of -- query. type Identifier = Word16 -- | Raw data format for the flags of DNS Query and Response. data DNSFlags DNSFlags :: !QorR -> !OPCODE -> !Bool -> !Bool -> !Bool -> !Bool -> !RCODE -> !Bool -> !Bool -> DNSFlags -- | Query or response. [qOrR] :: DNSFlags -> !QorR -- | Kind of query. [opcode] :: DNSFlags -> !OPCODE -- | AA (Authoritative Answer) bit - this bit is valid in responses, and -- specifies that the responding name server is an authority for the -- domain name in question section. [authAnswer] :: DNSFlags -> !Bool -- | TC (Truncated Response) bit - specifies that this message was -- truncated due to length greater than that permitted on the -- transmission channel. [trunCation] :: DNSFlags -> !Bool -- | RD (Recursion Desired) bit - this bit may be set in a query and is -- copied into the response. If RD is set, it directs the name server to -- pursue the query recursively. Recursive query support is optional. [recDesired] :: DNSFlags -> !Bool -- | RA (Recursion Available) bit - this be is set or cleared in a -- response, and denotes whether recursive query support is available in -- the name server. [recAvailable] :: DNSFlags -> !Bool -- | The full 12-bit extended RCODE when EDNS is in use. Should always be -- zero in well-formed requests. When decoding replies, the high eight -- bits from any EDNS response are combined with the 4-bit RCODE from the -- DNS header. When encoding replies, if no EDNS OPT record is provided, -- RCODE values > 15 are mapped to FormatErr. [rcode] :: DNSFlags -> !RCODE -- | AD (Authenticated Data) bit - (RFC4035, Section 3.2.3). [authenData] :: DNSFlags -> !Bool -- | CD (Checking Disabled) bit - (RFC4035, Section 3.2.2). [chkDisable] :: DNSFlags -> !Bool -- | Query or response. data QorR -- | Query. QR_Query :: QorR -- | Response. QR_Response :: QorR -- | Default DNSFlags record suitable for making recursive queries. -- By default the RD bit is set, and the AD and CD bits are cleared. defaultDNSFlags :: DNSFlags -- | Kind of query. data OPCODE -- | A standard query. OP_STD :: OPCODE -- | An inverse query (inverse queries are deprecated). OP_INV :: OPCODE -- | A server status request. OP_SSR :: OPCODE -- | A zone change notification (RFC1996) OP_NOTIFY :: OPCODE -- | An update request (RFC2136) OP_UPDATE :: OPCODE -- | Convert the internal representation of a DNS OPCODE to its 16-bit -- numeric value. fromOPCODE :: OPCODE -> Word16 -- | Convert a 16-bit DNS OPCODE number to its internal representation toOPCODE :: Word16 -> Maybe OPCODE -- | EDNS extended 12-bit response code. Non-EDNS messages use only the low -- 4 bits. With EDNS this stores the combined error code from the DNS -- header and and the EDNS psuedo-header. See EDNSheader for more -- detail. data RCODE -- | No error condition. pattern NoErr :: () => () => RCODE -- | Format error - The name server was unable to interpret the query. pattern FormatErr :: () => () => RCODE -- | Server failure - The name server was unable to process this query due -- to a problem with the name server. pattern ServFail :: () => () => RCODE -- | Name Error - Meaningful only for responses from an authoritative name -- server, this code signifies that the domain name referenced in the -- query does not exist. pattern NameErr :: () => () => RCODE -- | Not Implemented - The name server does not support the requested kind -- of query. pattern NotImpl :: () => () => RCODE -- | Refused - 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. pattern Refused :: () => () => RCODE -- | YXDomain - Dynamic update response, a pre-requisite domain that should -- not exist, does exist. pattern YXDomain :: () => () => RCODE -- | YXRRSet - Dynamic update response, a pre-requisite RRSet that should -- not exist, does exist. pattern YXRRSet :: () => () => RCODE -- | NXRRSet - Dynamic update response, a pre-requisite RRSet that should -- exist, does not exist. pattern NXRRSet :: () => () => RCODE -- | NotAuth - Dynamic update response, the server is not authoritative for -- the zone named in the Zone Section. pattern NotAuth :: () => () => RCODE -- | NotZone - Dynamic update response, a name used in the Prerequisite or -- Update Section is not within the zone denoted by the Zone Section. pattern NotZone :: () => () => RCODE -- | Bad OPT Version (BADVERS, RFC 6891). pattern BadVers :: () => () => RCODE -- | Key not recognized [RFC2845] pattern BadKey :: () => () => RCODE -- | Signature out of time window [RFC2845] pattern BadTime :: () => () => RCODE -- | Bad TKEY Mode [RFC2930] pattern BadMode :: () => () => RCODE -- | Duplicate key name [RFC2930] pattern BadName :: () => () => RCODE -- | Algorithm not supported [RFC2930] pattern BadAlg :: () => () => RCODE -- | Bad Truncation [RFC4635] pattern BadTrunc :: () => () => RCODE -- | Bad/missing Server Cookie [RFC7873] pattern BadCookie :: () => () => RCODE -- | Malformed (peer) EDNS message, no RCODE available. This is not an -- RCODE that can be sent by a peer. It lies outside the 12-bit range -- expressible via EDNS. The low 12-bits are chosen to coincide with -- FormatErr. When an EDNS message is malformed, and we're unable -- to extract the extended RCODE, the header rcode is set to -- BadRCODE. pattern BadRCODE :: () => () => RCODE -- | Convert an RCODE to its numeric value. fromRCODE :: RCODE -> Word16 -- | Convert a numeric value to a corresponding RCODE. The behaviour -- is undefined for values outside the range [0 .. 0xFFF] since -- the EDNS extended RCODE is a 12-bit value. Values in the range -- [0xF01 .. 0xFFF] are reserved for private use. toRCODE :: Word16 -> RCODE -- | Data type representing the optional EDNS pseudo-header of a -- DNSMessage When a single well-formed OPT -- ResourceRecord was present in the message's additional section, -- it is decoded to an EDNS record and and stored in the message -- ednsHeader field. The corresponding OPT RR is then -- removed from the additional section. -- -- When the constructor is NoEDNS, no EDNS OPT record was -- present in the message additional section. When InvalidEDNS, -- the message holds either a malformed OPT record or more than one OPT -- record, which can still be found in (have not been removed from) the -- message additional section. -- -- The EDNS OPT record augments the message error status with an 8-bit -- field that forms 12-bit extended RCODE when combined with the 4-bit -- RCODE from the unextended DNS header. In EDNS messages it is essential -- to not use just the bare 4-bit RCODE from the original DNS -- header. Therefore, in order to avoid potential misinterpretation of -- the response RCODE, when the OPT record is decoded, the upper -- eight bits of the error status are automatically combined with the -- rcode of the message header, so that there is only one place in -- which to find the full 12-bit result. Therefore, the decoded -- EDNS pseudo-header, does not hold any error status bits. -- -- The reverse process occurs when encoding messages. The low four bits -- of the message header rcode are encoded into the wire-form DNS -- header, while the upper eight bits are encoded as part of the OPT -- record. In DNS responses with an rcode larger than 15, EDNS -- extensions SHOULD be enabled by providing a value for -- ednsHeader with a constructor of EDNSheader. If EDNS is -- not enabled in such a message, in order to avoid truncation of -- RCODE values that don't fit in the non-extended DNS header, the -- encoded wire-form RCODE is set to FormatErr. -- -- When encoding messages for transmission, the ednsHeader is used -- to generate the additional OPT record. Do not add explicit -- OPT records to the aditional section, configure EDNS via the -- EDNSheader instead. -- --
--   >>> let getopts eh = mapEDNS eh ednsOptions []
--   
--   >>> let optsin     = [OD_ClientSubnet 24 0 $ read "192.0.2.1"]
--   
--   >>> let masked     = [OD_ClientSubnet 24 0 $ read "192.0.2.0"]
--   
--   >>> let message    = makeEmptyQuery $ ednsSetOptions $ ODataSet optsin
--   
--   >>> let optsout    = getopts. ednsHeader <$> (decode $ encode message)
--   
--   >>> optsout       == Right masked
--   True
--   
data EDNSheader -- | A valid EDNS message EDNSheader :: EDNS -> EDNSheader -- | A valid non-EDNS message NoEDNS :: EDNSheader -- | Multiple or bad additional OPT RRs InvalidEDNS :: EDNSheader -- | Return the second argument for EDNS messages, otherwise the third. ifEDNS :: () => EDNSheader -> a -> a -> a -- | Return the output of a function applied to the EDNS pseudo-header if -- EDNS is enabled, otherwise return a default value. mapEDNS :: () => EDNSheader -> (EDNS -> a) -> a -> a -- | EDNS information defined in RFC 6891. data EDNS EDNS :: !Word8 -> !Word16 -> !Bool -> ![OData] -> EDNS -- | EDNS version, presently only version 0 is defined. [ednsVersion] :: EDNS -> !Word8 -- | Supported UDP payload size. [ednsUdpSize] :: EDNS -> !Word16 -- | Request DNSSEC replies (with RRSIG and NSEC records as as appropriate) -- from the server. Generally, not needed (except for diagnostic -- purposes) unless the signatures will be validated. Just setting the -- AD bit in the query and checking it in the response is -- sufficient (but often subject to man-in-the-middle forgery) if all -- that's wanted is whether the server validated the response. [ednsDnssecOk] :: EDNS -> !Bool -- | EDNS options (e.g. OD_NSID, OD_ClientSubnet, ...) [ednsOptions] :: EDNS -> ![OData] -- | The default EDNS pseudo-header for queries. The UDP buffer size is set -- to 1216 bytes, which should result in replies that fit into the 1280 -- byte IPv6 minimum MTU. Since IPv6 only supports fragmentation at the -- source, and even then not all gateways forward IPv6 pre-fragmented -- IPv6 packets, it is best to keep DNS packet sizes below this limit -- when using IPv6 nameservers. A larger value may be practical when -- using IPv4 exclusively. -- --
--   defaultEDNS = EDNS
--       { ednsVersion = 0      -- The default EDNS version is 0
--       , ednsUdpSize = 1232   -- IPv6-safe UDP MTU (RIPE recommendation)
--       , ednsDnssecOk = False -- We don't do DNSSEC validation
--       , ednsOptions = []     -- No EDNS options by default
--       }
--   
defaultEDNS :: EDNS -- | Maximum UDP size that can be advertised. If the ednsUdpSize of -- EDNS is larger, then this value is sent instead. This value is -- likely to work only for local nameservers on the loopback network. -- Servers may enforce a smaller limit. -- --
--   >>> maxUdpSize
--   16384
--   
maxUdpSize :: Word16 -- | Minimum UDP size to advertise. If ednsUdpSize of EDNS is -- smaller, then this value is sent instead. -- --
--   >>> minUdpSize
--   512
--   
minUdpSize :: Word16 -- | RData formats for a few EDNS options, and an opaque catchall data OData -- | Name Server Identifier (RFC5001). Bidirectional, empty from client. -- (opaque octet-string). May contain binary data, which MUST be empty in -- queries. OD_NSID :: ByteString -> OData -- | DNSSEC Algorithm Understood (RFC6975). Client to server. (array of -- 8-bit numbers). Lists supported DNSKEY algorithms. OD_DAU :: [Word8] -> OData -- | DS Hash Understood (RFC6975). Client to server. (array of 8-bit -- numbers). Lists supported DS hash algorithms. OD_DHU :: [Word8] -> OData -- | NSEC3 Hash Understood (RFC6975). Client to server. (array of 8-bit -- numbers). Lists supported NSEC3 hash algorithms. OD_N3U :: [Word8] -> OData -- | Client subnet (RFC7871). Bidirectional. (source bits, scope bits, -- address). The address is masked and truncated when encoding queries. -- The address is zero-padded when decoding. Invalid input encodings -- result in an OD_ECSgeneric value instead. OD_ClientSubnet :: Word8 -> Word8 -> IP -> OData -- | Unsupported or malformed IP client subnet option. Bidirectional. -- (address family, source bits, scope bits, opaque address). OD_ECSgeneric :: Word16 -> Word8 -> Word8 -> ByteString -> OData -- | Generic EDNS option. (numeric OptCode, opaque content) UnknownOData :: Word16 -> ByteString -> OData -- | EDNS Option Code (RFC 6891). data OptCode -- | Client subnet (RFC7871) pattern ClientSubnet :: () => () => OptCode -- | DNSSEC algorithm support (RFC6974, section 3) pattern DAU :: () => () => OptCode pattern DHU :: () => () => OptCode pattern N3U :: () => () => OptCode -- | NSID (RFC5001, section 2.3) pattern NSID :: () => () => OptCode -- | From option code to number. fromOptCode :: OptCode -> Word16 -- | From number to option code. toOptCode :: Word16 -> OptCode -- | Raw data format for DNS questions. data Question Question :: Domain -> TYPE -> Question -- | A domain name [qname] :: Question -> Domain -- | The type of the query [qtype] :: Question -> TYPE -- | 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 question section of the response doesn't match our query. This -- could indicate foul play. QuestionMismatch :: DNSError -- | A zone tranfer, i.e., a request of type AXFR, was attempted with the -- "lookup" interface. Zone transfer is different enough from "normal" -- requests that it requires a different interface. InvalidAXFRLookup :: DNSError -- | The number of retries for the request was exceeded. RetryLimitExceeded :: DNSError -- | TCP fallback request 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 -- | 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 does not support the OPT RR version or content BadOptRecord :: DNSError -- | Configuration is wrong. BadConfiguration :: DNSError -- | Network failure. NetworkFailure :: IOException -> DNSError -- | Error is unknown DecodeError :: String -> DNSError UnknownDNSError :: DNSError -- | Type for a mailbox encoded on the wire as a DNS name, but the first -- label is conceptually the local part of an email address, and may -- contain internal periods that are not label separators. Therefore, in -- mailboxes @ is used as the separator between the first and second -- labels, and any '.' characters in the first label are not escaped. The -- encoding is otherwise the same as Domain above. This is most -- commonly seen in the mrname of SOA records. On input, -- if there is no unescaped @ character in the Mailbox, it is -- reparsed with '.' as the first label separator. Thus the traditional -- format with all labels separated by dots is also accepted, but -- decoding from wire form always uses @ between the first label and the -- domain-part of the address. Examples: -- --
--   hostmaster@example.org.  -- First label is simply hostmaster
--   john.smith@examle.com.   -- First label is john.smith
--   
type Mailbox = ByteString -- | Miscellaneous utility functions for processing DNS data. module Network.DNS.Utils -- | Perform both normalizeCase and normalizeRoot on the -- given Domain. When comparing DNS names taken from user input, -- this is often necessary to avoid unexpected results. -- -- Examples: -- --
--   >>> let domain1 = BS.pack "ExAmPlE.COM"
--   
--   >>> let domain2 = BS.pack "example.com."
--   
--   >>> domain1 == domain2
--   False
--   
--   >>> normalize domain1 == normalize domain2
--   True
--   
-- -- The normalize function should be idempotent: -- --
--   >>> normalize (normalize domain1) == normalize domain1
--   True
--   
-- -- Ensure that we don't crash on the empty Domain: -- --
--   >>> import qualified Data.ByteString.Char8 as BS
--   
--   >>> normalize BS.empty
--   "."
--   
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. -- -- Examples: -- --
--   >>> let domain1 = BS.pack "ExAmPlE.COM"
--   
--   >>> let domain2 = BS.pack "exAMPle.com"
--   
--   >>> domain1 == domain2
--   False
--   
--   >>> normalizeCase domain1 == normalizeCase domain2
--   True
--   
-- -- The normalizeCase function should be idempotent: -- --
--   >>> normalizeCase (normalizeCase domain2) == normalizeCase domain2
--   True
--   
-- -- Ensure that we don't crash on the empty Domain: -- --
--   >>> import qualified Data.ByteString.Char8 as BS
--   
--   >>> normalizeCase BS.empty
--   ""
--   
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: -- -- -- -- 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." -- -- Examples: -- --
--   >>> let domain1 = BS.pack "example.com"
--   
--   >>> let domain2 = BS.pack "example.com."
--   
--   >>> domain1 == domain2
--   False
--   
--   >>> normalizeRoot domain1 == normalizeRoot domain2
--   True
--   
-- -- The normalizeRoot function should be idempotent: -- --
--   >>> normalizeRoot (normalizeRoot domain1) == normalizeRoot domain1
--   True
--   
-- -- Ensure that we don't crash on the empty Domain: -- --
--   >>> import qualified Data.ByteString.Char8 as BS
--   
--   >>> normalizeRoot BS.empty
--   "."
--   
normalizeRoot :: Domain -> 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: -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupA resolver "192.0.2.1.nip.io"
--   Right [192.0.2.1]
--   
module Network.DNS