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


-- | Asynchronous DNS Resolver
--   
--   This library provides an asynchronous DNS resolver on top of GNU ADNS
--   <a>http://www.chiark.greenend.org.uk/~ian/adns/</a>. Not all options
--   are supported, but A, MX, and PTR lookups work nicely. There is also
--   support for retrieving generic RR types, CNAMEs, and for NSEC zone
--   walking. The library can be expected to work with fine ADNS 1.4 or
--   later. It might also work with version ADNS 1.3, but that hasn't been
--   tested.
--   
--   The example program adns-reverse-lookup.hs demonstrates how the
--   resolver is used. Given a list of host names on the command line, it
--   performs an A/PTR double-lookup and checks whether the records are
--   consistent. The output is printed in the order in which the DNS
--   responses arrive:
--   
--   <pre>
--   $ ./adns-reverse-lookup cryp.to localhost www.example.com
--   OK: localhost &lt;-&gt; 127.0.0.1
--   FAIL: cryp.to -&gt; 217.19.183.102 -&gt; ["zuse.cryp.to"]
--   OK: www.example.com &lt;-&gt; 192.0.32.10
--   </pre>
@package hsdns
@version 1.7.1


-- | This module provides bindings to GNU ADNS, a domain name resolver
--   library written in C. ADNS is available from
--   <a>http://www.gnu.org/software/adns/</a>.
--   
--   You will most likely not need this module directly: <a>ADNS</a>
--   provides a simpler API for the Haskell world; this module contains
--   mostly marshaling code.
module ADNS.Base
data OpaqueState
type AdnsState = Ptr OpaqueState
data OpaqueQuery
type Query = Ptr OpaqueQuery
data InitFlag

-- | do not look at environment
NoEnv :: InitFlag

-- | never print output to stderr (<a>Debug</a> overrides)
NoErrPrint :: InitFlag

-- | do not warn to stderr about duff nameservers etc
NoServerWarn :: InitFlag

-- | enable all output to stderr plus <a>Debug</a> msgs
Debug :: InitFlag

-- | include process id in diagnostic output
LogPid :: InitFlag

-- | do not make syscalls at every opportunity
NoAutoSys :: InitFlag

-- | allow <a>adnsSynch</a> to return <a>eINTR</a>
Eintr :: InitFlag

-- | application has SIGPIPE set to SIG_IGN, do not protect
NoSigPipe :: InitFlag

-- | do consistency checks on entry/exit to adns functions
CheckC_EntEx :: InitFlag

-- | do consistency checks very frequently (slow!)
CheckC_Freq :: InitFlag
data QueryFlag

-- | use the searchlist
Search :: QueryFlag

-- | use a virtual circuit (TCP connection)
UseVC :: QueryFlag

-- | fill in the owner field in the answer
Owner :: QueryFlag

-- | allow special chars in query domain
QuoteOk_Query :: QueryFlag

-- | allow special chars in CNAME we go via (default)
QuoteOk_CName :: QueryFlag

-- | allow special chars in things supposed to be hostnames
QuoteOk_AnsHost :: QueryFlag

-- | refuse if quote-req chars in CNAME we go via
QuoteFail_CName :: QueryFlag

-- | allow refs to CNAMEs - without, get _s_cname
CName_Loose :: QueryFlag

-- | don't follow CNAMEs, instead give _s_cname
CName_Forbid :: QueryFlag

-- | The record types we support.
data RRType
A :: RRType
CNAME :: RRType
MX :: RRType
NS :: RRType
PTR :: RRType
NSEC :: RRType
SRV :: RRType
RRType :: Int -> RRType

-- | The status codes recognized by ADNS vary in different versions of the
--   library. So instead of providing an <a>Enum</a>, the <a>Status</a>
--   type contains the numeric value as returned by ADNS itself. For common
--   status codes, helper functions like <a>sOK</a> or <a>sNXDOMAIN</a> are
--   provided. The functions <a>adnsErrTypeAbbrev</a>,
--   <a>adnsErrAbbrev</a>, and <a>adnsStrerror</a> can also be used to map
--   these codes into human readable strings.
newtype Status
StatusCode :: Int -> Status
sOK :: Status
sNOMEMORY :: Status
sUNKNOWNRRTYPE :: Status
sSYSTEMFAIL :: Status
sMAX_LOCALFAIL :: Status
sTIMEOUT :: Status
sALLSERVFAIL :: Status
sNORECURSE :: Status
sINVALIDRESPONSE :: Status
sUNKNOWNFORMAT :: Status
sMAX_REMOTEFAIL :: Status
sRCODESERVFAIL :: Status
sRCODEFORMATERROR :: Status
sRCODENOTIMPLEMENTED :: Status
sRCODEREFUSED :: Status
sRCODEUNKNOWN :: Status

-- | Original definition:
--   
--   <pre>
--   typedef struct {
--     int len;
--     union {
--       struct sockaddr sa;
--       struct sockaddr_in inet;
--     } addr;
--   } adns_rr_addr;
--   </pre>
--   
--   <i>Note</i>: Anything but <tt>sockaddr_in</tt> will cause <a>peek</a>
--   to call <a>fail</a>, when marshaling this structure. <a>poke</a> is
--   not defined.
sMAX_TEMPFAIL :: Status
sINCONSISTENT :: Status
sPROHIBITEDCNAME :: Status
sANSWERDOMAININVALID :: Status
sANSWERDOMAINTOOLONG :: Status
sINVALIDDATA :: Status
sMAX_MISCONFIG :: Status
newtype RRAddr
RRAddr :: HostAddress -> RRAddr
sQUERYDOMAINWRONG :: Status
sQUERYDOMAININVALID :: Status
sQUERYDOMAINTOOLONG :: Status
sMAX_MISQUERY :: Status
sNXDOMAIN :: Status
sNODATA :: Status
sMAX_PERMFAIL :: Status

-- | Original definition:
--   
--   <pre>
--   typedef struct {
--     char *host;
--     adns_status astatus;
--     int naddrs; /* temp fail =&gt; -1, perm fail =&gt; 0, s_ok =&gt; &gt;0
--     adns_rr_addr *addrs;
--   } adns_rr_hostaddr;
--   </pre>
--   
--   The <tt>naddrs</tt> field is not available in <tt>RRHostAddr</tt>
--   because I couldn't see how that information wouldn't be available in
--   the <tt>astatus</tt> field too. If I missed anything, please let me
--   know.
--   
--   <i>Note</i>: The data type should probably contain <a>HostAddress</a>
--   rather than <a>RRAddr</a>. I'm using the former only because it has
--   nicer output with <a>show</a>. <a>poke</a> is not defined.
data RRHostAddr
RRHostAddr :: HostName -> Status -> [RRAddr] -> RRHostAddr

-- | Original definition:
--   
--   <pre>
--   typedef struct {
--     int i;
--     adns_rr_hostaddr ha;
--   } adns_rr_inthostaddr;
--   </pre>
data RRIntHostAddr
RRIntHostAddr :: Int -> RRHostAddr -> RRIntHostAddr

-- | Original definition:
--   
--   <pre>
--   typedef struct {
--     int len;
--     unsigned char *data;
--   } adns_rr_byteblock;
--   </pre>
data RRByteblock
RRByteblock :: Int -> (Ptr CChar) -> RRByteblock

-- | Original definition:
--   
--   <pre>
--   typedef struct {
--     int priority, weight, port;
--     char *host;
--   } adns_rr_srvraw;
--   </pre>
data RRSrvRaw
RRSrvRaw :: Int -> Int -> Int -> (Ptr CChar) -> RRSrvRaw
data Answer
Answer :: Status -> Maybe String -> Maybe String -> CTime -> [Response] -> Answer

-- | Status code for this query.
[status] :: Answer -> Status

-- | Always <a>Nothing</a> for <tt>CNAME</tt> queries
[cname] :: Answer -> Maybe String

-- | Only set if <a>Owner</a> was requested for query.
[owner] :: Answer -> Maybe String

-- | Only defined if status is <a>sOK</a>, <a>sNXDOMAIN</a>, or
--   <a>sNODATA</a>.
[expires] :: Answer -> CTime

-- | The list will be empty if an error occured.
[rrs] :: Answer -> [Response]
data Response
RRA :: RRAddr -> Response
RRCNAME :: String -> Response
RRMX :: Int -> RRHostAddr -> Response
RRNS :: RRHostAddr -> Response
RRPTR :: String -> Response
RRNSEC :: String -> Response
RRUNKNOWN :: String -> Response
RRSRV :: Int -> Int -> Int -> String -> Response

-- | This function parses the <a>Response</a> union found in <a>Answer</a>.
--   It cannot be defined via <a>Storable</a> because it needs to know the
--   type of the record to expect. This is, by the way, the function to
--   look at, if you want to add support for additional <a>RRType</a>
--   records.
peekResp :: RRType -> Ptr b -> Int -> Int -> IO [Response]

-- | This function parses a FQDN in uncompressed wire format and advances
--   the pointer to the next byte after the parsed name.
peekFQDNAndAdvance :: Ptr a -> Int -> IO (String, Ptr a)

-- | Run the given <a>IO</a> computation with an initialized resolver. As
--   of now, the diagnose stream is always set to <a>stderr</a>. Initialize
--   the library with <a>NoErrPrint</a> if you don't wont to see any error
--   output. All resources are freed when <tt>adnsInit</tt> returns.
adnsInit :: [InitFlag] -> (AdnsState -> IO a) -> IO a

-- | Similar to <a>adnsInit</a>, but reads the resolver configuration from
--   a string rather than from <tt>/etc/resolv.conf</tt>. Supported are the
--   usual commands: <tt>nameserver</tt>, <tt>search</tt>, <tt>domain</tt>,
--   <tt>sortlist</tt>, and <tt>options</tt>.
--   
--   Additionally, these non-standard commands may be used:
--   
--   <ul>
--   <li><tt>clearnameservers</tt>: Clears the list of nameservers.</li>
--   <li><tt>include filename</tt>: The specified file will be read.</li>
--   </ul>
adnsInitCfg :: [InitFlag] -> String -> (AdnsState -> IO a) -> IO a

-- | Perform a synchronous query for a record. In case of an I/O error, an
--   <a>IOException</a> is thrown. If the query fails for other reasons,
--   the <a>Status</a> code in the <a>Answer</a> will signify that.
adnsSynch :: AdnsState -> String -> RRType -> [QueryFlag] -> IO Answer

-- | Submit an asynchronous query. The returned <a>Query</a> can be tested
--   for completion with <a>adnsCheck</a>.
adnsSubmit :: AdnsState -> String -> RRType -> [QueryFlag] -> IO Query

-- | Check the status of an asynchronous query. If the query is complete,
--   the <a>Answer</a> will be returned. The <a>Query</a> becomes invalid
--   after that.
adnsCheck :: AdnsState -> Query -> IO (Maybe Answer)

-- | Wait for a response to arrive. The returned <a>Query</a> is invalid
--   and must not be passed to ADNS again. If <a>Nothing</a> is returned,
--   the resolver is empty.
adnsWait :: AdnsState -> IO (Maybe (Query, Answer))

-- | Cancel an open <a>Query</a>.
adnsCancel :: Query -> IO ()

-- | Wait for the next <a>Query</a> to become available.
adns_wait :: AdnsState -> Ptr Query -> Ptr (Ptr Answer) -> Ptr (Ptr a) -> IO CInt

-- | Return the list of all currently open queries.
adnsQueries :: AdnsState -> IO [Query]

-- | Map a <a>Status</a> code to a human-readable error description. For
--   example:
--   
--   <pre>
--   *ADNS&gt; adnsStrerror sNXDOMAIN &gt;&gt;= print
--   "No such domain"
--   </pre>
--   
--   Use this function with great care: It will crash the process when
--   called with a status code that ADNS doesn't know about. So use it only
--   to print values you got from the resolver!
adnsStrerror :: Status -> IO String

-- | Map a <a>Status</a> code to a short error name. Don't use this
--   function to print a status code unless you've obtained it from the
--   resolver!
adnsErrAbbrev :: Status -> IO String

-- | Map a <a>Status</a> code to a short description of the type of error.
--   Don't use this function to print a status code unless you've obtained
--   it from the resolver!
adnsErrTypeAbbrev :: Status -> IO String
adns_init :: Ptr AdnsState -> CInt -> Ptr CFile -> IO CInt
adns_init_strcfg :: Ptr AdnsState -> CInt -> Ptr CFile -> CString -> IO CInt
adns_finish :: AdnsState -> IO ()
adns_submit :: AdnsState -> CString -> CInt -> CInt -> Ptr a -> Ptr Query -> IO CInt
adns_check :: AdnsState -> Ptr Query -> Ptr (Ptr Answer) -> Ptr (Ptr a) -> IO CInt
adns_synchronous :: AdnsState -> CString -> CInt -> CInt -> Ptr (Ptr Answer) -> IO CInt
adns_forallqueries_begin :: AdnsState -> IO ()
adns_forallqueries_next :: AdnsState -> Ptr (Ptr a) -> IO Query
adns_strerror :: CInt -> IO CString
adns_errabbrev :: CInt -> IO CString
adns_errtypeabbrev :: CInt -> IO CString

-- | Internel helper function to handle result passing from ADNS via
--   <tt>Ptr (Ptr a)</tt>, and to generate human-readable IO exceptions in
--   case of an error.
wrapAdns :: (Ptr (Ptr b) -> IO CInt) -> (Ptr (Ptr b) -> IO a) -> IO a

-- | Map a list of flags (<a>Enum</a> types) into a <a>CInt</a> suitable
--   for adns calls.
mkFlags :: Enum a => [a] -> CInt
instance GHC.Show.Show ADNS.Base.Answer
instance GHC.Show.Show ADNS.Base.Response
instance GHC.Show.Show ADNS.Base.RRIntHostAddr
instance GHC.Show.Show ADNS.Base.RRHostAddr
instance GHC.Classes.Eq ADNS.Base.RRAddr
instance GHC.Show.Show ADNS.Base.Status
instance GHC.Classes.Eq ADNS.Base.Status
instance GHC.Read.Read ADNS.Base.RRType
instance GHC.Show.Show ADNS.Base.QueryFlag
instance GHC.Enum.Bounded ADNS.Base.QueryFlag
instance GHC.Classes.Eq ADNS.Base.QueryFlag
instance GHC.Show.Show ADNS.Base.InitFlag
instance GHC.Enum.Bounded ADNS.Base.InitFlag
instance GHC.Classes.Eq ADNS.Base.InitFlag
instance Foreign.Storable.Storable ADNS.Base.Answer
instance Foreign.Storable.Storable ADNS.Base.RRSrvRaw
instance Foreign.Storable.Storable ADNS.Base.RRByteblock
instance Foreign.Storable.Storable ADNS.Base.RRIntHostAddr
instance Foreign.Storable.Storable ADNS.Base.RRHostAddr
instance GHC.Show.Show ADNS.Base.RRAddr
instance Foreign.Storable.Storable ADNS.Base.RRAddr
instance GHC.Classes.Eq ADNS.Base.RRType
instance GHC.Show.Show ADNS.Base.RRType
instance GHC.Enum.Enum ADNS.Base.RRType
instance Foreign.Storable.Storable ADNS.Base.RRType
instance GHC.Enum.Enum ADNS.Base.QueryFlag
instance GHC.Enum.Enum ADNS.Base.InitFlag


-- | This module implements a Haskell DNS Resolver on top of the ADNS
--   library. GHC users should compile their code using the
--   <tt>-threaded</tt> runtime system.
module ADNS.Resolver

-- | A <a>Resolver</a> is an <a>IO</a> computation which -- given the name
--   and type of the record to query -- returns an <a>MVar</a> that will
--   eventually contain the <a>Answer</a> from the Domain Name System.
type Resolver = String -> RRType -> [QueryFlag] -> IO (MVar Answer)

-- | Run the given <a>IO</a> computation with an Initialized
--   <a>Resolver</a>. Note that resolver functions can be shared, and
--   <i>should</i> be shared between any number of <a>IO</a> threads. You
--   may use multiple resolvers, of course, but doing so defeats the
--   purpose of an asynchronous resolver.
initResolver :: [InitFlag] -> (Resolver -> IO a) -> IO a

-- | Print an IP host address as a string suitable for <a>PTR</a> lookups.
toPTR :: HostAddress -> String

-- | Resolve a hostname's <a>A</a> records.
resolveA :: Resolver -> HostName -> IO (Either Status [HostAddress])

-- | Get the <a>PTR</a> records assigned to a host address. Note that
--   although the API allows for a record to have more than one <a>PTR</a>
--   entry, this will actually not happen because the GNU adns library
--   can't handle this case and will return <a>sINCONSISTENT</a>.
resolvePTR :: Resolver -> HostAddress -> IO (Either Status [HostName])

-- | Resolve the mail exchangers for a hostname. The returned list may
--   contain more than one entry per hostname, in case the host has several
--   <a>A</a> records. The records are returned in the order you should try
--   to contact them as determined by the priority in the <a>RRMX</a>
--   response.
resolveMX :: Resolver -> HostName -> IO (Either Status [(HostName, HostAddress)])

-- | Resolve a hostname's <a>SRV</a> records.
resolveSRV :: Resolver -> HostName -> IO (Either Status [(HostName, PortID)])

-- | Convenience wrapper that will modify any of the <tt>revolveXXX</tt>
--   functions above to return <a>Maybe</a> rather than <a>Either</a>. The
--   idea is that <tt>Nothing</tt> signifies any sort of failure: <tt>Just
--   []</tt> signifies <a>sNXDOMAIN</a> or <a>sNODATA</a>, and everything
--   else signifies <a>sOK</a>.
--   
--   So if you aren't interested in getting accurate <a>Status</a> codes in
--   case of failures. Wrap your DNS queries as follows:
--   
--   <pre>
--   queryA :: Resolver -&gt; HostName -&gt; IO (Maybe [HostAddress])
--   queryA = query resolveA
--   </pre>
query :: (Resolver -> a -> IO (Either Status [b])) -> Resolver -> a -> IO (Maybe [b])

-- | Use this function to disable DNS resolving. It will always return
--   <tt>(<a>Answer</a> <a>sSYSTEMFAIL</a> Nothing (Just host) (-1)
--   [])</tt>.
dummyDNS :: Resolver


-- | An asynchronous DNS resolver based on GNU ADNS
--   <a>http://www.gnu.org/software/adns/</a>. You should link your program
--   with the <i>threaded</i> runtime-system when using this module. In
--   GHC, this is accomplished by specifying <tt>-threaded</tt> on the
--   command-line.
module ADNS

-- | Either a host name e.g., <tt>"haskell.org"</tt> or a numeric host
--   address string consisting of a dotted decimal IPv4 address or an IPv6
--   address e.g., <tt>"192.168.0.1"</tt>.
type HostName = String

-- | The raw network byte order number is read using host byte order.
--   Therefore on little-endian architectures the byte order is swapped.
--   For example <tt>127.0.0.1</tt> is represented as <tt>0x0100007f</tt>
--   on little-endian hosts and as <tt>0x7f000001</tt> on big-endian hosts.
--   
--   For direct manipulation prefer <a>hostAddressToTuple</a> and
--   <a>tupleToHostAddress</a>.
type HostAddress = Word32

-- | A <a>Resolver</a> is an <a>IO</a> computation which -- given the name
--   and type of the record to query -- returns an <a>MVar</a> that will
--   eventually contain the <a>Answer</a> from the Domain Name System.
type Resolver = String -> RRType -> [QueryFlag] -> IO (MVar Answer)

-- | Run the given <a>IO</a> computation with an Initialized
--   <a>Resolver</a>. Note that resolver functions can be shared, and
--   <i>should</i> be shared between any number of <a>IO</a> threads. You
--   may use multiple resolvers, of course, but doing so defeats the
--   purpose of an asynchronous resolver.
initResolver :: [InitFlag] -> (Resolver -> IO a) -> IO a
data InitFlag

-- | do not look at environment
NoEnv :: InitFlag

-- | never print output to stderr (<a>Debug</a> overrides)
NoErrPrint :: InitFlag

-- | do not warn to stderr about duff nameservers etc
NoServerWarn :: InitFlag

-- | enable all output to stderr plus <a>Debug</a> msgs
Debug :: InitFlag

-- | include process id in diagnostic output
LogPid :: InitFlag

-- | do not make syscalls at every opportunity
NoAutoSys :: InitFlag

-- | allow <a>adnsSynch</a> to return <a>eINTR</a>
Eintr :: InitFlag

-- | application has SIGPIPE set to SIG_IGN, do not protect
NoSigPipe :: InitFlag

-- | do consistency checks on entry/exit to adns functions
CheckC_EntEx :: InitFlag

-- | do consistency checks very frequently (slow!)
CheckC_Freq :: InitFlag
queryA :: Resolver -> HostName -> IO (Maybe [HostAddress])
queryPTR :: Resolver -> HostAddress -> IO (Maybe [HostName])
queryMX :: Resolver -> HostName -> IO (Maybe [(HostName, HostAddress)])

-- | For quering SRV records. Result is the list of tuples (host, port).
querySRV :: Resolver -> HostName -> IO (Maybe [(HostName, PortID)])

-- | Use this function to disable DNS resolving. It will always return
--   <tt>(<a>Answer</a> <a>sSYSTEMFAIL</a> Nothing (Just host) (-1)
--   [])</tt>.
dummyDNS :: Resolver
