{-|
Module      : Net.DNSBase.Lookup
Description : Per-RRtype lookup functions over a 'Resolver'
Copyright   : (c) IIJ Innovation Institute Inc., 2009
              (c) Viktor Dukhovni, 2020-2026
License     : BSD-3-Clause
Maintainer  : ietf-dane@dukhovni.org
Stability   : unstable
-}
{-# LANGUAGE RecordWildCards #-}
module Net.DNSBase.Lookup
    ( Lookup
    , extractAnswers
    , lookupRawCtl
    , lookupRaw
    , lookupAnswers
    , lookupM
    , lookupM_
    , lookupX
    , lookupA
    , lookupAAAA
    , lookupAFSDB
    , lookupCAA
    , lookupCDNSKEY
    , lookupCDS
    , lookupCNAME
    , lookupDNAME
    , lookupDNSKEY
    , lookupDS
    , lookupHINFO
    , lookupHTTPS
    , lookupMX
    , lookupNS
    , lookupNSEC
    , lookupNSEC3PARAM
    , lookupNULL
    , lookupPTR
    , lookupRP
    , lookupSOA
    , lookupSRV
    , lookupSSHFP
    , lookupSVCB
    , lookupTLSA
    , lookupTXT
    , lookupZONEMD
    ) where
import qualified Data.Map.Strict as M
import Data.Foldable (foldlM)
import Data.Map.Strict (Map)
import Data.Maybe (mapMaybe)

import Net.DNSBase.Internal.Bytes
import Net.DNSBase.Internal.Domain
import Net.DNSBase.Internal.Error
import Net.DNSBase.Internal.Message
import Net.DNSBase.Internal.RCODE
import Net.DNSBase.Internal.RData
import Net.DNSBase.Internal.RR
import Net.DNSBase.Internal.Transport
import Net.DNSBase.Internal.Util
import Net.DNSBase.Resolver.Internal.Types

import Net.DNSBase.RData.A
import Net.DNSBase.RData.CAA
import Net.DNSBase.RData.Dnssec
import Net.DNSBase.RData.SOA
import Net.DNSBase.RData.SRV
import Net.DNSBase.RData.SVCB
import Net.DNSBase.RData.TLSA
import Net.DNSBase.RData.TXT
import Net.DNSBase.RData.XNAME
import Net.DNSBase.RRCLASS
import Net.DNSBase.RRSet
import Net.DNSBase.RRTYPE

-- | Shape of a typed lookup: a 'Resolver' and a query 'Domain' produce
-- either a list of answers, or a 'DNSError'.  An empty list means that
-- either the name exists and has no records of the queried type
-- (@NODATA@), or the name does not exist (@NXDOMAIN@). Both are
-- non-error outcomes.
--
type Lookup a = Resolver -> Domain -> IO (Either DNSError [a])

-- | Generic answer-RData lookup, applying a function to each
-- result.  If the the function's first argument is polymorphic, a
-- type application at the call site may be needed to make it
-- possible to determine the type of its argument.
--
lookupX :: KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX :: forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
typ a -> b
f Resolver
rslv Domain
dom =
    (Either DNSError [RR] -> Either DNSError [b])
-> IO (Either DNSError [RR]) -> IO (Either DNSError [b])
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([RR] -> [b]) -> Either DNSError [RR] -> Either DNSError [b]
forall a b. (a -> b) -> Either DNSError a -> Either DNSError b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [RR] -> [b]
getOnly) (Resolver
-> QueryControls
-> RRCLASS
-> RRTYPE
-> Domain
-> IO (Either DNSError [RR])
lookupAnswers Resolver
rslv QueryControls
forall a. Monoid a => a
mempty RRCLASS
IN RRTYPE
typ Domain
dom)
  where
    getOnly :: [RR] -> [b]
getOnly = (RR -> Maybe b) -> [RR] -> [b]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (a -> b
f (a -> b) -> (RR -> Maybe a) -> RR -> Maybe b
forall (m :: * -> *) b c a.
Functor m =>
(b -> c) -> (a -> m b) -> a -> m c
<.> RR -> Maybe a
forall a. KnownRData a => RR -> Maybe a
rrDataCast)

-- | Apply an IO action to each lookup value and collect the
-- results. If the the action's first argument is polymorphic,
-- a type application at the call site may be needed to make it
-- possible to determine the type of its argument.
--
lookupM :: forall a b. KnownRData a => (a -> IO b) -> Lookup b
lookupM :: forall a b. KnownRData a => (a -> IO b) -> Lookup b
lookupM a -> IO b
f Resolver
rslv = Resolver
-> QueryControls
-> RRCLASS
-> RRTYPE
-> Domain
-> IO (Either DNSError [RR])
lookupAnswers Resolver
rslv QueryControls
forall a. Monoid a => a
mempty RRCLASS
IN (rdType a) (Domain -> IO (Either DNSError [RR]))
-> (Either DNSError [RR] -> IO (Either DNSError [b]))
-> Domain
-> IO (Either DNSError [b])
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> \ case
   Left DNSError
why -> Either DNSError [b] -> IO (Either DNSError [b])
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either DNSError [b] -> IO (Either DNSError [b]))
-> Either DNSError [b] -> IO (Either DNSError [b])
forall a b. (a -> b) -> a -> b
$ DNSError -> Either DNSError [b]
forall a b. a -> Either a b
Left DNSError
why
   Right [RR]
rrs -> [b] -> Either DNSError [b]
forall a b. b -> Either a b
Right ([b] -> Either DNSError [b]) -> IO [b] -> IO (Either DNSError [b])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ([b] -> RR -> IO [b]) -> [b] -> [RR] -> IO [b]
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldlM [b] -> RR -> IO [b]
go [] [RR]
rrs
 where
    go :: [b] -> RR -> IO [b]
go [b]
acc RR
rr = case RR -> Maybe a
forall a. KnownRData a => RR -> Maybe a
rrDataCast RR
rr of
        Just a
rd -> do
            !b <- a -> IO b
f a
rd
            pure $ b : acc
        Maybe a
Nothing -> [b] -> IO [b]
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [b]
acc

-- | Apply an IO action to each lookup value and discard the
-- results. If the the action's first argument is polymorphic, a
-- type application at the call site may be needed to make it
-- possible to determine the type of its argument.
--
lookupM_ :: forall a b. KnownRData a
         => (a -> IO b) -> Resolver -> Domain -> IO (Either DNSError ())
lookupM_ :: forall a b.
KnownRData a =>
(a -> IO b) -> Resolver -> Domain -> IO (Either DNSError ())
lookupM_ a -> IO b
f Resolver
rslv = Resolver
-> QueryControls
-> RRCLASS
-> RRTYPE
-> Domain
-> IO (Either DNSError [RR])
lookupAnswers Resolver
rslv QueryControls
forall a. Monoid a => a
mempty RRCLASS
IN (rdType a) (Domain -> IO (Either DNSError [RR]))
-> (Either DNSError [RR] -> IO (Either DNSError ()))
-> Domain
-> IO (Either DNSError ())
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> \ case
   Left DNSError
why -> Either DNSError () -> IO (Either DNSError ())
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either DNSError () -> IO (Either DNSError ()))
-> Either DNSError () -> IO (Either DNSError ())
forall a b. (a -> b) -> a -> b
$ DNSError -> Either DNSError ()
forall a b. a -> Either a b
Left DNSError
why
   Right [RR]
rrs -> () -> Either DNSError ()
forall a b. b -> Either a b
Right (() -> Either DNSError ()) -> IO () -> IO (Either DNSError ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [RR] -> IO ()
go [RR]
rrs
 where
    go :: [RR] -> IO ()
go (RR
rr : [RR]
rest) = case RR -> Maybe a
forall a. KnownRData a => RR -> Maybe a
rrDataCast RR
rr of
        Just a
rd -> a -> IO b
f a
rd IO b -> IO () -> IO ()
forall a b. IO a -> IO b -> IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [RR] -> IO ()
go [RR]
rest
        Maybe a
Nothing -> [RR] -> IO ()
go [RR]
rest
    go [] = () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

-- | Perform a raw lookup returning the full 'DNSMessage' or a
-- 'DNSError'.  See 'lookupRawCtl' for the variant that takes
-- per-call query controls.
--
lookupRaw :: Resolver -> Domain -> RRCLASS -> RRTYPE
          -> IO (Either DNSError DNSMessage)
lookupRaw :: Resolver
-> Domain -> RRCLASS -> RRTYPE -> IO (Either DNSError DNSMessage)
lookupRaw Resolver
rslv = Resolver
-> QueryControls
-> Domain
-> RRCLASS
-> RRTYPE
-> IO (Either DNSError DNSMessage)
lookupRawCtl Resolver
rslv QueryControls
forall a. Monoid a => a
mempty

-- | Perform a raw lookup with per-call 'QueryControls' overrides,
-- returning the full 'DNSMessage' or a 'DNSError'.  The supplied
-- controls are merged into the resolver's ambient query controls:
-- only the flag and EDNS bits specified in the controls affect the
-- outgoing query, the rest are inherited from the resolver
-- configuration.  Use 'lookupAnswers' (or the per-RRtype 'Lookup'
-- functions) when you want only the answer RRs for the requested
-- name and type, rather than the entire response 'DNSMessage'.
--
lookupRawCtl :: Resolver -> QueryControls -> Domain -> RRCLASS
             -> RRTYPE -> IO (Either DNSError DNSMessage)
lookupRawCtl :: Resolver
-> QueryControls
-> Domain
-> RRCLASS
-> RRTYPE
-> IO (Either DNSError DNSMessage)
lookupRawCtl Resolver
rslv QueryControls
ctls Domain
dom RRCLASS
qclass RRTYPE
qtype =
    DNSIO DNSMessage -> IO (Either DNSError DNSMessage)
forall a. DNSIO a -> IO (Either DNSError a)
runDNSIO (Resolver
-> QueryControls -> Domain -> RRCLASS -> RRTYPE -> DNSIO DNSMessage
lookupRawCtl_ Resolver
rslv QueryControls
ctls Domain
dom RRCLASS
qclass RRTYPE
qtype)

-- | Find the RRs that answer the query, following any CNAMEs
-- found when there's no exact match for the qname and qtype.
-- Also returns any associated covering DNSSEC RRSIGs.
filterRelevant :: [RR] -> RRCLASS -> RRTYPE -> Domain -> [RR]
filterRelevant :: [RR] -> RRCLASS -> RRTYPE -> Domain -> [RR]
filterRelevant [RR]
rrs RRCLASS
qclass RRTYPE
qtype =
    [ RR
rr | RR
rr <- [RR]
rrs
    , RR -> RRCLASS
rrClass RR
rr RRCLASS -> RRCLASS -> Bool
forall a. Eq a => a -> a -> Bool
== RRCLASS
qclass
    , RR -> RRTYPE
rrType RR
rr RRTYPE -> RRTYPE -> Bool
forall a. Eq a => a -> a -> Bool
== RRTYPE
qtype Bool -> Bool -> Bool
|| RR -> RRTYPE
rrType RR
rr RRTYPE -> RRTYPE -> Bool
forall a. Eq a => a -> a -> Bool
== RRTYPE
CNAME ]
    [RR] -> ([RR] -> [RRSet]) -> [RRSet]
forall a b. a -> (a -> b) -> b
& [RR] -> [RRSet]
rrSetsFromList
    [RRSet]
-> ([RRSet] -> [((RRTYPE, Domain), [RR])])
-> [((RRTYPE, Domain), [RR])]
forall a b. a -> (a -> b) -> b
& (RRSet -> ((RRTYPE, Domain), [RR]))
-> [RRSet] -> [((RRTYPE, Domain), [RR])]
forall a b. (a -> b) -> [a] -> [b]
map (\RRSet
s -> ((RRSet -> RRTYPE
rrSetType RRSet
s, RRSet -> Domain
rrSetOwner RRSet
s), RRSet -> [RR]
rrSetRecs RRSet
s))
    [((RRTYPE, Domain), [RR])]
-> ([((RRTYPE, Domain), [RR])] -> Map (RRTYPE, Domain) [RR])
-> Map (RRTYPE, Domain) [RR]
forall a b. a -> (a -> b) -> b
& [((RRTYPE, Domain), [RR])] -> Map (RRTYPE, Domain) [RR]
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
    Map (RRTYPE, Domain) [RR]
-> (Map (RRTYPE, Domain) [RR] -> Domain -> [RR]) -> Domain -> [RR]
forall a b. a -> (a -> b) -> b
& Map (RRTYPE, Domain) [RR] -> Domain -> [RR]
loop
  where
    -- Cycles are avoided by deleting traversed CNAMEs.
    loop :: Map (RRTYPE, Domain) [RR] -> Domain -> [RR]
    loop :: Map (RRTYPE, Domain) [RR] -> Domain -> [RR]
loop Map (RRTYPE, Domain) [RR]
sm (Domain -> Domain
canonicalise -> Domain
qname)
          | Just [RR]
found <- (RRTYPE, Domain) -> Map (RRTYPE, Domain) [RR] -> Maybe [RR]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup (RRTYPE
qtype, Domain
qname) Map (RRTYPE, Domain) [RR]
sm = [RR]
found
          | (Just [RR]
found, Map (RRTYPE, Domain) [RR]
sm') <- (Maybe [RR] -> (Maybe [RR], Maybe [RR]))
-> (RRTYPE, Domain)
-> Map (RRTYPE, Domain) [RR]
-> (Maybe [RR], Map (RRTYPE, Domain) [RR])
forall (f :: * -> *) k a.
(Functor f, Ord k) =>
(Maybe a -> f (Maybe a)) -> k -> Map k a -> f (Map k a)
M.alterF (, [RR] -> Maybe [RR]
forall a. a -> Maybe a
Just []) (RRTYPE
CNAME, Domain
qname) Map (RRTYPE, Domain) [RR]
sm
          , [Domain
t] <- [Domain
t | T_CNAME Domain
t <- [RData] -> [T_cname]
forall a (t :: * -> *).
(KnownRData a, Foldable t) =>
t RData -> [a]
monoRData ([RData] -> [T_cname]) -> [RData] -> [T_cname]
forall a b. (a -> b) -> a -> b
$ (RR -> RData) -> [RR] -> [RData]
forall a b. (a -> b) -> [a] -> [b]
map RR -> RData
rrData [RR]
found] = Map (RRTYPE, Domain) [RR] -> Domain -> [RR]
loop Map (RRTYPE, Domain) [RR]
sm' Domain
t
          | Bool
otherwise = []

-------

-- | Perform the requested query and return the answer RRs from the
-- response, or a 'DNSError' carrying the RCODE for error responses.
-- The 'QueryControls' argument carries per-call tweaks; it is
-- merged onto the resolver's ambient query controls, so callers only
-- need to specify the flag and EDNS bits they want to change, the
-- rest are inherited from the resolver configuration.
--
-- Note that @NXDOMAIN@ is /not/ a lookup error.  An empty list of
-- RRs is returned for both @NODATA@ and @NXDOMAIN@.
--
-- If the nameserver's response does not include any RRs matching
-- query name and type, but does include a @CNAME@ record for the
-- requested name, the response is (recursively) rescanned for
-- records matching that name and type instead.  Note, no
-- additional queries are issued if the final CNAME found does
-- not lead to any record of the desired record type.
--
-- The returned RRs may include covering @DNSSEC@ signatures when the
-- 'Net.DNSBase.Flags.DOflag' is set as part of the 'QueryControls', and
-- the response was signed.
--
-- The presence of @RRSIG@ records does not however imply that the
-- response was /validated/ by the resolver.  For that one would
-- typically use a trusted DNSSEC-validating local (loopback)
-- resolver, to which the network path is immune to potential
-- active attacks, and inspect the 'Net.DNSBase.Flags.ADflag' in
-- the response message.
--
-- The full response 'DNSMessage' can be obtained via 'lookupRawCtl'.
--
lookupAnswers :: Resolver -> QueryControls -> RRCLASS -> RRTYPE -> Domain
              -> IO (Either DNSError [RR])
lookupAnswers :: Resolver
-> QueryControls
-> RRCLASS
-> RRTYPE
-> Domain
-> IO (Either DNSError [RR])
lookupAnswers Resolver
rslv QueryControls
ctls RRCLASS
cls RRTYPE
typ Domain
dom = DNSIO [RR] -> IO (Either DNSError [RR])
forall a. DNSIO a -> IO (Either DNSError a)
runDNSIO do
    msg <- Resolver
-> QueryControls -> Domain -> RRCLASS -> RRTYPE -> DNSIO DNSMessage
lookupRawCtl_ Resolver
rslv QueryControls
ctls Domain
dom RRCLASS
cls RRTYPE
typ
    extractAnswers_ msg

-- | Given a 'DNSMessage' return answer RRs that match its question,
-- possibly after /chasing/ @CNAME@ aliases within the answer
-- section of the message.
extractAnswers :: DNSMessage -> IO (Either DNSError [RR])
extractAnswers :: DNSMessage -> IO (Either DNSError [RR])
extractAnswers DNSMessage
msg = DNSIO [RR] -> IO (Either DNSError [RR])
forall a. DNSIO a -> IO (Either DNSError a)
runDNSIO (DNSMessage -> DNSIO [RR]
forall (m :: * -> *).
Monad m =>
DNSMessage -> ExceptT DNSError m [RR]
extractAnswers_ DNSMessage
msg)

-- | Extract the answer RRs matching the question from a 'DNSMessage'
-- when the RCODE is non-error.
extractAnswers_ :: Monad m => DNSMessage -> ExceptT DNSError m [RR]
extractAnswers_ :: forall (m :: * -> *).
Monad m =>
DNSMessage -> ExceptT DNSError m [RR]
extractAnswers_ m :: DNSMessage
m@(DNSMessage -> [DnsTriple]
dnsMsgQu -> [DnsTriple
q])
    | RCODE
NOERROR  <- DNSMessage -> RCODE
dnsMsgRC DNSMessage
m = [RR] -> ExceptT DNSError m [RR]
forall a. a -> ExceptT DNSError m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([RR] -> ExceptT DNSError m [RR])
-> [RR] -> ExceptT DNSError m [RR]
forall a b. (a -> b) -> a -> b
$ [RR] -> RRCLASS -> RRTYPE -> Domain -> [RR]
filterRelevant (DNSMessage -> [RR]
dnsMsgAn DNSMessage
m) RRCLASS
cls RRTYPE
typ Domain
dom
    | RCODE
NXDOMAIN <- DNSMessage -> RCODE
dnsMsgRC DNSMessage
m = [RR] -> ExceptT DNSError m [RR]
forall a. a -> ExceptT DNSError m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
    | RCODE
YXDOMAIN <- DNSMessage -> RCODE
dnsMsgRC DNSMessage
m = [RR] -> ExceptT DNSError m [RR]
forall a. a -> ExceptT DNSError m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure []
    | Bool
otherwise              = DNSError -> ExceptT DNSError m [RR]
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE (DNSError -> ExceptT DNSError m [RR])
-> DNSError -> ExceptT DNSError m [RR]
forall a b. (a -> b) -> a -> b
$ RCODE -> DNSError
ResponseError (RCODE -> DNSError) -> RCODE -> DNSError
forall a b. (a -> b) -> a -> b
$ DNSMessage -> RCODE
dnsMsgRC DNSMessage
m
  where
    dom :: Domain
dom = DnsTriple -> Domain
dnsTripleName DnsTriple
q
    cls :: RRCLASS
cls = DnsTriple -> RRCLASS
dnsTripleClass DnsTriple
q
    typ :: RRTYPE
typ = DnsTriple -> RRTYPE
dnsTripleType DnsTriple
q
extractAnswers_ DNSMessage
m =
    DNSError -> ExceptT DNSError m [RR]
forall (m :: * -> *) e a. Monad m => e -> ExceptT e m a
throwE (DNSError -> ExceptT DNSError m [RR])
-> DNSError -> ExceptT DNSError m [RR]
forall a b. (a -> b) -> a -> b
$ UserContext -> DNSError
UserError (UserContext -> DNSError) -> UserContext -> DNSError
forall a b. (a -> b) -> a -> b
$ Int -> UserContext
BadResponseQuestionCount (Int -> UserContext) -> Int -> UserContext
forall a b. (a -> b) -> a -> b
$ [DnsTriple] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([DnsTriple] -> Int) -> [DnsTriple] -> Int
forall a b. (a -> b) -> a -> b
$ DNSMessage -> [DnsTriple]
dnsMsgQu DNSMessage
m


-- | @IPv4@ addresses of query domain.
lookupA     :: Lookup IPv4
lookupA :: Lookup IPv4
lookupA = RRTYPE -> (T_a -> IPv4) -> Lookup IPv4
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
A ((T_a -> IPv4) -> Lookup IPv4) -> (T_a -> IPv4) -> Lookup IPv4
forall a b. (a -> b) -> a -> b
$ \(T_A IPv4
ip) -> IPv4
ip

-- | @IPv6@ addresses of query domain.
lookupAAAA  :: Lookup IPv6
lookupAAAA :: Lookup IPv6
lookupAAAA = RRTYPE -> (T_aaaa -> IPv6) -> Lookup IPv6
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
AAAA ((T_aaaa -> IPv6) -> Lookup IPv6)
-> (T_aaaa -> IPv6) -> Lookup IPv6
forall a b. (a -> b) -> a -> b
$ \(T_AAAA IPv6
ip) -> IPv6
ip

-- | @CNAME@s of query domain (should be at most one).
lookupCNAME :: Lookup Domain
lookupCNAME :: Lookup Domain
lookupCNAME = RRTYPE -> (T_cname -> Domain) -> Lookup Domain
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
CNAME ((T_cname -> Domain) -> Lookup Domain)
-> (T_cname -> Domain) -> Lookup Domain
forall a b. (a -> b) -> a -> b
$ \(T_CNAME Domain
dom) -> Domain
dom

-- | @CAA@s @RData@ of query domain
lookupCAA :: Lookup T_caa
lookupCAA :: Lookup T_caa
lookupCAA = RRTYPE -> (T_caa -> T_caa) -> Lookup T_caa
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
CAA T_caa -> T_caa
forall a. a -> a
id

-- | @DNAME@s of query domain (should be at most one).
lookupDNAME :: Lookup Domain
lookupDNAME :: Lookup Domain
lookupDNAME = RRTYPE -> (T_dname -> Domain) -> Lookup Domain
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
DNAME ((T_dname -> Domain) -> Lookup Domain)
-> (T_dname -> Domain) -> Lookup Domain
forall a b. (a -> b) -> a -> b
$ \(T_DNAME Domain
dom) -> Domain
dom

-- | @PTR@ names of query domain.
lookupPTR   :: Lookup Domain
lookupPTR :: Lookup Domain
lookupPTR = RRTYPE -> (T_ptr -> Domain) -> Lookup Domain
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
PTR ((T_ptr -> Domain) -> Lookup Domain)
-> (T_ptr -> Domain) -> Lookup Domain
forall a b. (a -> b) -> a -> b
$ \(T_PTR Domain
dom) -> Domain
dom

-- | Nameservers of query domain.
lookupNS :: Lookup Domain
lookupNS :: Lookup Domain
lookupNS = RRTYPE -> (T_ns -> Domain) -> Lookup Domain
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
NS ((T_ns -> Domain) -> Lookup Domain)
-> (T_ns -> Domain) -> Lookup Domain
forall a b. (a -> b) -> a -> b
$ \(T_NS Domain
dom) -> Domain
dom

-- | @NULL@ RR payload of query domain.
lookupNULL  :: Lookup ShortByteString
lookupNULL :: Lookup ShortByteString
lookupNULL = RRTYPE -> (T_null -> ShortByteString) -> Lookup ShortByteString
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
NULL ((T_null -> ShortByteString) -> Lookup ShortByteString)
-> (T_null -> ShortByteString) -> Lookup ShortByteString
forall a b. (a -> b) -> a -> b
$ \ (T_NULL Bytes16
b16) -> Bytes16 -> ShortByteString
getShort16 Bytes16
b16

-- | @AFSDB@ RData of query domain.
lookupAFSDB  :: Lookup T_afsdb
lookupAFSDB :: Lookup T_afsdb
lookupAFSDB = RRTYPE -> (T_afsdb -> T_afsdb) -> Lookup T_afsdb
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
AFSDB T_afsdb -> T_afsdb
forall a. a -> a
id

-- | @CDNSKEY@ RData of query domain.
lookupCDNSKEY  :: Lookup T_cdnskey
lookupCDNSKEY :: Lookup T_cdnskey
lookupCDNSKEY = RRTYPE -> (T_cdnskey -> T_cdnskey) -> Lookup T_cdnskey
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
CDNSKEY T_cdnskey -> T_cdnskey
forall a. a -> a
id

-- | @CDS@ RData of query domain.
lookupCDS  :: Lookup T_cds
lookupCDS :: Lookup T_cds
lookupCDS = RRTYPE -> (T_cds -> T_cds) -> Lookup T_cds
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
CDS T_cds -> T_cds
forall a. a -> a
id

-- | @DNSKEY@ RData of query domain.
lookupDNSKEY  :: Lookup T_dnskey
lookupDNSKEY :: Lookup T_dnskey
lookupDNSKEY = RRTYPE -> (T_dnskey -> T_dnskey) -> Lookup T_dnskey
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
DNSKEY T_dnskey -> T_dnskey
forall a. a -> a
id

-- | @DS@ RData of query domain.
lookupDS  :: Lookup T_ds
lookupDS :: Lookup T_ds
lookupDS = RRTYPE -> (T_ds -> T_ds) -> Lookup T_ds
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
DS T_ds -> T_ds
forall a. a -> a
id

-- | @HINFO@ RData of query domain.
lookupHINFO  :: Lookup T_hinfo
lookupHINFO :: Lookup T_hinfo
lookupHINFO = RRTYPE -> (T_hinfo -> T_hinfo) -> Lookup T_hinfo
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
HINFO T_hinfo -> T_hinfo
forall a. a -> a
id

-- | @HTTPS@ RData of query domain.
lookupHTTPS  :: Lookup T_https
lookupHTTPS :: Lookup T_https
lookupHTTPS = RRTYPE -> (T_https -> T_https) -> Lookup T_https
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
HTTPS T_https -> T_https
forall a. a -> a
id

-- | @MX@ RData of query domain.
lookupMX  :: Lookup T_mx
lookupMX :: Lookup T_mx
lookupMX = RRTYPE -> (T_mx -> T_mx) -> Lookup T_mx
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
MX T_mx -> T_mx
forall a. a -> a
id

-- | @NSEC@ RData of query domain.
lookupNSEC  :: Lookup T_nsec
lookupNSEC :: Lookup T_nsec
lookupNSEC = RRTYPE -> (T_nsec -> T_nsec) -> Lookup T_nsec
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
NSEC T_nsec -> T_nsec
forall a. a -> a
id

-- | @NSEC3PARAM@ RData of query domain.
lookupNSEC3PARAM  :: Lookup T_nsec3param
lookupNSEC3PARAM :: Lookup T_nsec3param
lookupNSEC3PARAM = RRTYPE -> (T_nsec3param -> T_nsec3param) -> Lookup T_nsec3param
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
NSEC3PARAM T_nsec3param -> T_nsec3param
forall a. a -> a
id

-- | @SOA@ RData of query domain.
lookupSOA  :: Lookup T_soa
lookupSOA :: Lookup T_soa
lookupSOA = RRTYPE -> (T_soa -> T_soa) -> Lookup T_soa
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
SOA T_soa -> T_soa
forall a. a -> a
id

-- | @RP@ RData of query domain.
lookupRP :: Lookup T_rp
lookupRP :: Lookup T_rp
lookupRP = RRTYPE -> (T_rp -> T_rp) -> Lookup T_rp
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
RP T_rp -> T_rp
forall a. a -> a
id

-- | @SRV@ RData of query domain.
lookupSRV  :: Lookup T_srv
lookupSRV :: Lookup T_srv
lookupSRV = RRTYPE -> (T_srv -> T_srv) -> Lookup T_srv
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
SRV T_srv -> T_srv
forall a. a -> a
id

-- | @SSHFP@ RData of query domain.
lookupSSHFP  :: Lookup T_sshfp
lookupSSHFP :: Lookup T_sshfp
lookupSSHFP = RRTYPE -> (T_sshfp -> T_sshfp) -> Lookup T_sshfp
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
SSHFP T_sshfp -> T_sshfp
forall a. a -> a
id

-- | @SVCB@ RData of query domain.
lookupSVCB  :: Lookup T_svcb
lookupSVCB :: Lookup T_svcb
lookupSVCB = RRTYPE -> (T_svcb -> T_svcb) -> Lookup T_svcb
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
SVCB T_svcb -> T_svcb
forall a. a -> a
id

-- | @TLSA@ RData of query domain.
lookupTLSA  :: Lookup T_tlsa
lookupTLSA :: Lookup T_tlsa
lookupTLSA = RRTYPE -> (T_tlsa -> T_tlsa) -> Lookup T_tlsa
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
TLSA T_tlsa -> T_tlsa
forall a. a -> a
id

-- | @TXT@ RData of query domain.  Applications typically concatenate each list
-- of character strings into a single combined value.
lookupTXT  :: Lookup (NonEmpty ShortByteString)
lookupTXT :: Lookup (NonEmpty ShortByteString)
lookupTXT = RRTYPE
-> (T_txt -> NonEmpty ShortByteString)
-> Lookup (NonEmpty ShortByteString)
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
TXT \(T_TXT NonEmpty ShortByteString
chunks) -> NonEmpty ShortByteString
chunks

-- | @ZONEMD@ RData of query domain.
lookupZONEMD  :: Lookup T_zonemd
lookupZONEMD :: Lookup T_zonemd
lookupZONEMD = RRTYPE -> (T_zonemd -> T_zonemd) -> Lookup T_zonemd
forall a b. KnownRData a => RRTYPE -> (a -> b) -> Lookup b
lookupX RRTYPE
ZONEMD T_zonemd -> T_zonemd
forall a. a -> a
id