-- 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.0 -- | 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_CDS RD_CDNSKEY RD_CSYNC RD_TLSA :: Word8 -> 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 = 1216   -- IPv6-safe UDP MTU
--       , 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 catcall 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 instance GHC.Classes.Eq Network.DNS.Types.QueryControls instance GHC.Classes.Eq Network.DNS.Types.EdnsControls instance GHC.Classes.Eq Network.DNS.Types.ODataOp instance GHC.Show.Show Network.DNS.Types.DNSMessage instance GHC.Classes.Eq Network.DNS.Types.DNSMessage instance GHC.Show.Show Network.DNS.Types.ResourceRecord instance GHC.Classes.Eq Network.DNS.Types.ResourceRecord instance GHC.Classes.Ord Network.DNS.Types.RData instance GHC.Classes.Eq Network.DNS.Types.RData instance GHC.Show.Show Network.DNS.Types.EDNSheader instance GHC.Classes.Eq Network.DNS.Types.EDNSheader instance GHC.Show.Show Network.DNS.Types.EDNS instance GHC.Classes.Eq Network.DNS.Types.EDNS instance GHC.Classes.Ord Network.DNS.Types.OData instance GHC.Classes.Eq Network.DNS.Types.OData instance GHC.Classes.Ord Network.DNS.Types.OptCode instance GHC.Classes.Eq Network.DNS.Types.OptCode instance GHC.Classes.Ord Network.DNS.Types.RD_RRSIG instance GHC.Classes.Eq Network.DNS.Types.RD_RRSIG instance GHC.Show.Show Network.DNS.Types.Question instance GHC.Classes.Eq Network.DNS.Types.Question instance GHC.Show.Show Network.DNS.Types.DNSHeader instance GHC.Classes.Eq Network.DNS.Types.DNSHeader instance GHC.Show.Show Network.DNS.Types.DNSFlags instance GHC.Classes.Eq Network.DNS.Types.DNSFlags instance GHC.Classes.Eq Network.DNS.Types.RCODE instance GHC.Enum.Bounded Network.DNS.Types.OPCODE instance GHC.Enum.Enum Network.DNS.Types.OPCODE instance GHC.Show.Show Network.DNS.Types.OPCODE instance GHC.Classes.Eq Network.DNS.Types.OPCODE instance GHC.Enum.Bounded Network.DNS.Types.QorR instance GHC.Enum.Enum Network.DNS.Types.QorR instance GHC.Show.Show Network.DNS.Types.QorR instance GHC.Classes.Eq Network.DNS.Types.QorR instance GHC.Classes.Eq Network.DNS.Types.HeaderControls instance GHC.Show.Show Network.DNS.Types.FlagOp instance GHC.Classes.Eq Network.DNS.Types.FlagOp instance GHC.Show.Show Network.DNS.Types.DNSError instance GHC.Classes.Eq Network.DNS.Types.DNSError instance GHC.Classes.Ord Network.DNS.Types.TYPE instance GHC.Classes.Eq Network.DNS.Types.TYPE instance GHC.Base.Semigroup Network.DNS.Types.QueryControls instance GHC.Base.Monoid Network.DNS.Types.QueryControls instance GHC.Show.Show Network.DNS.Types.QueryControls instance GHC.Base.Semigroup Network.DNS.Types.EdnsControls instance GHC.Base.Monoid Network.DNS.Types.EdnsControls instance GHC.Show.Show Network.DNS.Types.EdnsControls instance GHC.Base.Semigroup Network.DNS.Types.ODataOp instance GHC.Base.Monoid Network.DNS.Types.ODataOp instance GHC.Show.Show Network.DNS.Types.RData instance GHC.Show.Show Network.DNS.Types.OData instance GHC.Show.Show Network.DNS.Types.OptCode instance GHC.Show.Show Network.DNS.Types.RD_RRSIG instance GHC.Enum.Enum Network.DNS.Types.RCODE instance GHC.Show.Show Network.DNS.Types.RCODE instance GHC.Base.Semigroup Network.DNS.Types.HeaderControls instance GHC.Base.Monoid Network.DNS.Types.HeaderControls instance GHC.Show.Show Network.DNS.Types.HeaderControls instance GHC.Base.Semigroup Network.DNS.Types.FlagOp instance GHC.Base.Monoid Network.DNS.Types.FlagOp instance GHC.Exception.Type.Exception Network.DNS.Types.DNSError instance GHC.Show.Show Network.DNS.Types.TYPE -- | 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 -- | 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) 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 "www.mew.org"
--   Right [210.130.207.72]
--   
-- -- This function will also follow a CNAME and resolve its target if one -- exists for the queries 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 no MX (to prevent a deluge of spam from examples posted on the -- internet). But remember, "no results" is still a successful result. -- --
--   >>> rs <- makeResolvSeed defaultResolvConf
--   
--   >>> withResolver rs $ \resolver -> lookupMX resolver "example.com"
--   Right []
--   
-- -- 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. 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
--   
--   >>> withResolver rs $ \resolver -> lookupSOA resolver "mew.org"
--   Right [("ns1.mew.org.","kazu@mew.org.",201406240,3600,300,3600000,3600)]
--   
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)]) -- | 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 "www.mew.org"
--   Right [210.130.207.72]
--   
module Network.DNS