-- 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 1.2.2 -- | Data types for DNS Query and Response. For more information, see -- http://www.ietf.org/rfc/rfc1035. module Network.DNS.Types -- | Type for domain. type Domain = ByteString -- | Types for resource records. data TYPE A :: TYPE AAAA :: TYPE NS :: TYPE TXT :: TYPE MX :: TYPE CNAME :: TYPE SOA :: TYPE PTR :: TYPE SRV :: TYPE UNKNOWN :: Int -> TYPE intToType :: Int -> TYPE typeToInt :: TYPE -> Int toType :: String -> 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 request simply timed out. TimeoutExpired :: DNSError -- | The answer has the correct sequence number, but returned an unexpected -- RDATA format. UnexpectedRDATA :: DNSError -- | The domain for query is illegal. IllegalDomain :: DNSError -- | The name server was unable to interpret the query. FormatError :: DNSError -- | The name server was unable to process this query due to a problem with -- the name server. ServerFailure :: DNSError -- | Meaningful only for responses from an authoritative name server, this -- code signifies that the domain name referenced in the query does not -- exist. NameError :: DNSError -- | The name server does not support the requested kind of query. NotImplemented :: DNSError -- | The name server refuses to perform the specified operation for policy -- reasons. For example, a name server may not wish to provide the -- information to the particular requester, or a name server may not wish -- to perform a particular operation (e.g., zone transfer) for particular -- data. OperationRefused :: DNSError -- | Raw data format for DNS Query and Response. data DNSFormat DNSFormat :: DNSHeader -> [Question] -> [ResourceRecord] -> [ResourceRecord] -> [ResourceRecord] -> DNSFormat header :: DNSFormat -> DNSHeader question :: DNSFormat -> [Question] answer :: DNSFormat -> [ResourceRecord] authority :: DNSFormat -> [ResourceRecord] additional :: DNSFormat -> [ResourceRecord] -- | Raw data format for the header of DNS Query and Response. data DNSHeader DNSHeader :: Int -> DNSFlags -> Int -> Int -> Int -> Int -> DNSHeader identifier :: DNSHeader -> Int flags :: DNSHeader -> DNSFlags qdCount :: DNSHeader -> Int anCount :: DNSHeader -> Int nsCount :: DNSHeader -> Int arCount :: DNSHeader -> Int -- | Raw data format for the flags of DNS Query and Response. data DNSFlags DNSFlags :: QorR -> OPCODE -> Bool -> Bool -> Bool -> Bool -> RCODE -> DNSFlags qOrR :: DNSFlags -> QorR opcode :: DNSFlags -> OPCODE authAnswer :: DNSFlags -> Bool trunCation :: DNSFlags -> Bool recDesired :: DNSFlags -> Bool recAvailable :: DNSFlags -> Bool rcode :: DNSFlags -> RCODE data QorR QR_Query :: QorR QR_Response :: QorR data OPCODE OP_STD :: OPCODE OP_INV :: OPCODE OP_SSR :: OPCODE data RCODE NoErr :: RCODE FormatErr :: RCODE ServFail :: RCODE NameErr :: RCODE NotImpl :: RCODE Refused :: RCODE -- | Raw data format for resource records. data ResourceRecord ResourceRecord :: Domain -> TYPE -> Int -> Int -> RDATA -> ResourceRecord rrname :: ResourceRecord -> Domain rrtype :: ResourceRecord -> TYPE rrttl :: ResourceRecord -> Int rdlen :: ResourceRecord -> Int rdata :: ResourceRecord -> RDATA -- | Raw data format for DNS questions. data Question Question :: Domain -> TYPE -> Question qname :: Question -> Domain qtype :: Question -> TYPE -- | Raw data format for each type. data RDATA RD_NS :: Domain -> RDATA RD_CNAME :: Domain -> RDATA RD_MX :: Int -> Domain -> RDATA RD_PTR :: Domain -> RDATA RD_SOA :: Domain -> Domain -> Int -> Int -> Int -> Int -> Int -> RDATA RD_A :: IPv4 -> RDATA RD_AAAA :: IPv6 -> RDATA RD_TXT :: ByteString -> RDATA RD_SRV :: Int -> Int -> Int -> Domain -> RDATA RD_OTH :: [Int] -> RDATA responseA :: Int -> Question -> IPv4 -> DNSFormat responseAAAA :: Int -> Question -> IPv6 -> DNSFormat module Network.DNS.Decode -- | Parsing DNS data. decode :: ByteString -> Either String DNSFormat -- | Receiving DNS data from Socket and parse it. receive :: Socket -> IO DNSFormat module Network.DNS.Encode -- | Composing DNS data. encode :: DNSFormat -> ByteString -- | Composing query. First argument is a number to identify response. composeQuery :: Int -> [Question] -> ByteString -- | DNS Resolver and generic (lower-level) lookup functions. module Network.DNS.Resolver -- | Union type for FilePath and HostName. Specify -- FilePath to "resolv.conf" or numeric IP address in -- String form. -- -- Warning: Only numeric IP addresses are valid -- RCHostNames. -- -- Example (using Google's public DNS cache): -- --
-- >>> let cache = RCHostName "8.8.8.8" --data FileOrNumericHost -- | A path for "resolv.conf" RCFilePath :: FilePath -> FileOrNumericHost -- | A numeric IP address RCHostName :: HostName -> FileOrNumericHost -- | Type for resolver configuration. The easiest way to construct a -- ResolvConf object is to modify the defaultResolvConf. data ResolvConf ResolvConf :: FileOrNumericHost -> Int -> Int -> Integer -> ResolvConf resolvInfo :: ResolvConf -> FileOrNumericHost -- | Timeout in micro seconds. resolvTimeout :: ResolvConf -> Int -- | The number of retries including the first try. resolvRetry :: ResolvConf -> Int -- | This field was obsoleted. resolvBufsize :: ResolvConf -> Integer -- | Return a default ResolvConf: -- --
-- >>> let cache = RCHostName "8.8.8.8"
--
-- >>> let rc = defaultResolvConf { resolvInfo = cache }
--
defaultResolvConf :: ResolvConf
-- | Abstract data type of DNS Resolver seed. When implementing a DNS
-- cache, this should be re-used.
data ResolvSeed
-- | Make a ResolvSeed from a ResolvConf.
--
-- Examples:
--
-- -- >>> rs <- makeResolvSeed defaultResolvConf --makeResolvSeed :: ResolvConf -> IO ResolvSeed -- | Abstract data type of DNS Resolver When implementing a DNS cache, this -- MUST NOT be re-used. data Resolver Resolver :: IO Int -> Socket -> Int -> Int -> Integer -> Resolver genId :: Resolver -> IO Int dnsSock :: Resolver -> Socket dnsTimeout :: Resolver -> Int dnsRetry :: Resolver -> Int dnsBufsize :: Resolver -> Integer -- | Giving a thread-safe Resolver to the function of the second -- argument. A socket for UDP is opened inside and is surely closed. withResolver :: ResolvSeed -> (Resolver -> IO a) -> IO a -- | Giving thread-safe Resolvers to the function of the second -- argument. Sockets for UDP are opened inside and are surely closed. withResolvers :: [ResolvSeed] -> ([Resolver] -> IO a) -> IO a -- | Look up resource records for a domain, collecting the results from the -- ANSWER section of the response. -- -- We repeat an example from Network.DNS.Lookup: -- --
-- >>> let hostname = Data.ByteString.Char8.pack "www.example.com" -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookup resolver hostname A -- Right [93.184.216.119] --lookup :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RDATA]) -- | Look up resource records for a domain, collecting the results from the -- AUTHORITY section of the response. lookupAuth :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RDATA]) -- | Look up a name and return the entire DNS Response. Sample output is -- included below, however it is not tested -- the sequence number -- is unpredictable (it has to be!). -- -- The example code: -- --
-- let hostname = Data.ByteString.Char8.pack "www.example.com" -- rs <- makeResolvSeed defaultResolvConf -- withResolver rs $ resolver -> lookupRaw resolver hostname A ---- -- And the (formatted) expected output: -- --
-- Right (DNSFormat
-- { header = DNSHeader
-- { identifier = 1,
-- flags = DNSFlags
-- { qOrR = QR_Response,
-- opcode = OP_STD,
-- authAnswer = False,
-- trunCation = False,
-- recDesired = True,
-- recAvailable = True,
-- rcode = NoErr },
-- qdCount = 1,
-- anCount = 1,
-- nsCount = 0,
-- arCount = 0},
-- 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 = []})
--
lookupRaw :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSFormat)
-- | Extract necessary information from DNSFormat
fromDNSFormat :: DNSFormat -> (DNSFormat -> a) -> Either DNSError a
-- | Simple, high-level DNS lookup functions.
--
-- All of the lookup functions necessary run in IO, since they interact
-- with the network. The return types are similar, but differ in what can
-- be returned from a successful lookup.
--
-- We can think of the return type as "either what I asked for, or an
-- error". For example, the 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:
--
-- -- >>> let hostname = Data.ByteString.Char8.pack "www.example.com" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupA resolver hostname -- Right [93.184.216.119] ---- -- 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: -- --
-- >>> let hostname = Data.ByteString.Char8.pack "www.example.com"
--
-- >>> let badrc = defaultResolvConf { resolvTimeout = 1 }
--
-- >>>
--
-- >>> rs <- makeResolvSeed badrc
--
-- >>> withResolver rs $ \resolver -> lookupA resolver hostname
-- Left TimeoutExpired
--
--
-- 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
-- http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/type-class-extensions.html#overloaded-strings
-- for more information.
module Network.DNS.Lookup
-- | Look up all 'A' records for the given hostname.
--
-- A straightforward example:
--
-- -- >>> let hostname = Data.ByteString.Char8.pack "www.mew.org" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupA resolver hostname -- Right [202.232.15.101] ---- -- This function will also follow a CNAME and resolve its target if one -- exists for the queries hostname: -- --
-- >>> let hostname = Data.ByteString.Char8.pack "www.kame.net" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupA resolver hostname -- Right [203.178.141.194] --lookupA :: Resolver -> Domain -> IO (Either DNSError [IPv4]) -- | Look up all (IPv6) 'AAAA' records for the given hostname. -- -- Examples: -- --
-- >>> let hostname = Data.ByteString.Char8.pack "www.mew.org" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupAAAA resolver hostname -- Right [2001:240:11e:c00:00:00:00:101] --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. -- --
-- >>> let hostname = Data.ByteString.Char8.pack "example.com" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupMX resolver hostname -- Right [] ---- -- The domain "mew.org" does however have a single MX: -- --
-- >>> let hostname = Data.ByteString.Char8.pack "mew.org"
--
-- >>>
--
-- >>> rs <- makeResolvSeed defaultResolvConf
--
-- >>> withResolver rs $ \resolver -> lookupMX resolver hostname
-- 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) -- -- >>> let hostname = Data.ByteString.Char8.pack "mixi.jp" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> ips <- withResolver rs $ \resolver -> lookupAviaMX resolver hostname -- -- >>> fmap sort ips -- Right [202.32.29.4,202.32.29.5] ---- -- 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) -- -- >>> let hostname = Data.ByteString.Char8.pack "mew.org" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> ns <- withResolver rs $ \resolver -> lookupNS resolver hostname -- -- >>> 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 hostname = Data.ByteString.Char8.pack "example.com"
--
-- >>>
--
-- >>> 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 hostname
--
-- >>> 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":
--
-- -- >>> let hostname = Data.ByteString.Char8.pack "mew.org" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupTXT resolver hostname -- Right ["v=spf1 +mx -all"] --lookupTXT :: Resolver -> Domain -> IO (Either DNSError [ByteString]) -- | Look up all 'PTR' records for the given hostname. To perform a reverse -- lookup on an IP address, you must first reverse its octets and then -- append the suffix ".in-addr.arpa." -- -- We look up the PTR associated with the IP address 210.130.137.80, -- i.e., 80.137.130.210.in-addr.arpa: -- --
-- >>> let hostname = Data.ByteString.Char8.pack "80.137.130.210.in-addr.arpa" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupPTR resolver hostname -- Right ["www-v4.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: -- --
-- >>> let hostname = Data.ByteString.Char8.pack "210.130.137.80" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupRDNS resolver hostname -- Right ["www-v4.iij.ad.jp."] --lookupRDNS :: Resolver -> Domain -> IO (Either DNSError [Domain]) -- | Look up all 'SRV' records for the given hostname. A SRV record -- comprises four fields, -- --
-- >>> let hostname = Data.ByteString.Char8.pack "_sip._tcp.cisco.com" -- -- >>> -- -- >>> rs <- makeResolvSeed defaultResolvConf -- -- >>> withResolver rs $ \resolver -> lookupSRV resolver hostname -- Right [(1,0,5060,"vcsgw.cisco.com.")] --lookupSRV :: Resolver -> Domain -> IO (Either DNSError [(Int, Int, Int, Domain)]) -- | A thread-safe DNS library for both clients and servers written in pure -- Haskell. The Network.DNS module re-exports all other exposed modules -- for convenience. Applications will most likely use the high-level -- interface, while library/daemon authors may need to use the -- lower-level one. EDNS0 and TCP fallback are not supported yet. module Network.DNS