Copyright | © 2017 Herbert Valerio Riedel |
---|---|
License | GPL-2.0-or-later |
Safe Haskell | Trustworthy |
Language | Haskell2010 |
This module implements an API for accessing
the Domain Name Service (DNS)
resolver service via the standard libresolv
system library
on Unix systems.
Synopsis
- queryA :: Name -> IO [(TTL, IPv4)]
- queryAAAA :: Name -> IO [(TTL, IPv6)]
- queryCNAME :: Name -> IO [(TTL, Name)]
- queryPTR :: Name -> IO [(TTL, Name)]
- querySRV :: Name -> IO [(TTL, SRV Name)]
- queryTXT :: Name -> IO [(TTL, [CharStr])]
- query :: IsLabels n => Class -> n -> TypeSym -> IO (Msg n)
- data DnsException
- resIsReentrant :: Bool
- queryRaw :: Class -> Name -> Type -> IO ByteString
- sendRaw :: ByteString -> IO ByteString
- mkQueryRaw :: Class -> Name -> Type -> IO ByteString
- decodeMessage :: IsLabels n => ByteString -> Maybe (Msg n)
- encodeMessage :: IsLabels n => Msg n -> Maybe ByteString
- mkQueryMsg :: IsLabels n => Class -> n -> Type -> Msg n
- type Label = ByteString
- data Labels
- class IsLabels s where
- toLabels :: s -> Maybe Labels
- fromLabels :: Labels -> s
- newtype Name = Name ByteString
- caseFoldName :: Name -> Name
- newtype CharStr = CharStr ByteString
- data IPv4 = IPv4 !Word32
- arpaIPv4 :: IPv4 -> Name
- data IPv6 = IPv6 !Word64 !Word64
- arpaIPv6 :: IPv6 -> Name
- newtype TTL = TTL Int32
- newtype Class = Class Word16
- classIN :: Class
- newtype Type = Type Word16
- data TypeSym
- typeFromSym :: TypeSym -> Type
- typeToSym :: Type -> Maybe TypeSym
- data Msg l = Msg {}
- data MsgHeader = MsgHeader {}
- data MsgHeaderFlags = MsgHeaderFlags {}
- data QR
- data MsgQuestion l = MsgQuestion !l !Type !Class
- data MsgRR l = MsgRR {}
- data RData l
- = RDataA !IPv4
- | RDataAAAA !IPv6
- | RDataCNAME !l
- | RDataPTR !l
- | RDataHINFO !CharStr !CharStr
- | RDataNS !l
- | RDataMX !Word16 !l
- | RDataTXT ![CharStr]
- | RDataSPF ![CharStr]
- | RDataSOA !l !l !Word32 !Word32 !Word32 !Word32 !Word32
- | RDataSRV !(SRV l)
- | RDataAFSDB !Word16 !l
- | RDataNAPTR !Word16 !Word16 !CharStr !CharStr !CharStr !l
- | RDataURI !Word16 !Word16 !ByteString
- | RDataRRSIG !Word16 !Word8 !Word8 !Word32 !Word32 !Word32 !Word16 !l !ByteString
- | RDataDNSKEY !Word16 !Word8 !Word8 !ByteString
- | RDataDS !Word16 !Word8 !Word8 !ByteString
- | RDataNSEC !l !(Set Type)
- | RDataSSHFP !Word8 !Word8 !ByteString
- | RDataNSEC3PARAM !Word8 !Word8 !Word16 !CharStr
- | RDataNSEC3 !Word8 !Word8 !Word16 !CharStr !CharStr !(Set Type)
- | RDataCAA !Word8 !CharStr !ByteString
- | RDataOPT !ByteString
- | RData !Type !ByteString
- rdType :: RData l -> Either Type TypeSym
- data SRV l = SRV {}
High level API
queryA :: Name -> IO [(TTL, IPv4)] Source #
Query A
record (see RFC 1035, section 3.4.1).
This query returns only exact matches (modulo foldCaseName
).
E.g. in case of CNAME
responses even if the
answer section would contain A
records for the hostnames pointed
to by the CNAME
. You can use query
if you need more control.
>>>
queryA (Name "www.google.com")
[(TTL 72,IPv4 0xd83acde4)]
queryAAAA :: Name -> IO [(TTL, IPv6)] Source #
Query AAAA
records (see RFC 3596).
This query returns only exact matches (modulo foldCaseName
).
E.g. in case of CNAME
responses even if the answer section would
contain A
records for the hostnames pointed to by the
CNAME
. You can use query
if you need more control.
>>>
queryAAAA (Name "www.google.com")
[(TTL 299,IPv6 0x2a0014504001081e 0x2004)]
queryCNAME :: Name -> IO [(TTL, Name)] Source #
Query CNAME
records (see RFC 1035, section 3.3.1).
>>>
queryCNAME (Name "hackage.haskell.org")
[(TTL 299,Name "j.global-ssl.fastly.net.")]
queryPTR :: Name -> IO [(TTL, Name)] Source #
Query PTR
records (see RFC 1035, section 3.3.12).
>>>
queryPTR (Name "4.4.8.8.in-addr.arpa.")
[(TTL 14390,Name "dns.google.")]
See also arpaIPv6
and arpaIPv4
for converting IPv6
and IPv4
values to the respective .arpa."
domain name for reverse lookups.
Since: 0.1.2.0
querySRV :: Name -> IO [(TTL, SRV Name)] Source #
Query SRV
records (see RFC 2782).
>>>
querySRV (Name "_imap._tcp.gmail.com")
[(TTL 21599,SRV {srvPriority = 0, srvWeight = 0, srvPort = 0, srvTarget = Name "."})]
queryTXT :: Name -> IO [(TTL, [CharStr])] Source #
Query TXT
records (see RFC 1035, section 3.3.14).
>>>
queryTXT (Name "_mirrors.hackage.haskell.org")
[(TTL 299,["0.urlbase=http://hackage.fpcomplete.com/", "1.urlbase=http://objects-us-west-1.dream.io/hackage-mirror/"])]
Mid-level API
query :: IsLabels n => Class -> n -> TypeSym -> IO (Msg n) Source #
Send a query via res_query(3)
and decode its response into a Msg
Throws DnsException
in case of resolving or encoding/decoding errors. May throw other IO exceptions in case of network errors.
Example
>>>
query classIN (Name "_mirrors.hackage.haskell.org") TypeTXT
Just (Msg{msgHeader = MsgHeader{mhId = 56694, mhFlags = MsgHeaderFlags{mhQR = IsResponse, mhOpcode = 0, mhAA = False, mhTC = False, mhRD = True, mhRA = True, mhZ = False, mhAD = False, mhCD = False, mhRCode = 0}, mhQDCount = 1, mhANCount = 1, mhNSCount = 0, mhARCount = 1}, msgQD = [MsgQuestion (Name "_mirrors.hackage.haskell.org.") (Type 16) (Class 1)], msgAN = [MsgRR{rrName = Name "_mirrors.hackage.haskell.org.", rrClass = Class 1, rrTTL = TTL 299, rrData = RDataTXT ["0.urlbase=http://hackage.fpcomplete.com/", "1.urlbase=http://objects-us-west-1.dream.io/hackage-mirror/"]}], msgNS = [], msgAR = [MsgRR{rrName = Name ".", rrClass = Class 512, rrTTL = TTL 32768, rrData = RDataOPT ""}] })
data DnsException Source #
Exception thrown in case of errors while resolving or encoding/decoding into a Msg
.
Since: 0.1.1.0
DnsEncodeException | |
DnsDecodeException | |
DnsHostNotFound | No such domain (authoritative) Since: 0.2.0.0 |
DnsNoData | No record for requested type Since: 0.2.0.0 |
DnsNoRecovery | Non recoverable errors, REFUSED, NOTIMP Since: 0.2.0.0 |
DnsTryAgain | No such domain (non-authoritative) or SERVERFAIL Since: 0.2.0.0 |
Instances
Exception DnsException Source # | |
Defined in Network.DNS | |
Show DnsException Source # | |
Defined in Network.DNS showsPrec :: Int -> DnsException -> ShowS # show :: DnsException -> String # showList :: [DnsException] -> ShowS # |
Low-level API
resIsReentrant :: Bool Source #
Whether the reentrant DNS resolver C API (e.g. res_nquery(3)
, res_nsend(3)
) is being used.
If this this False
, then as a fall-back
res_query(3)
/res_send(3)
are used, protected by a global mutex.
Since: 0.1.1.0
queryRaw :: Class -> Name -> Type -> IO ByteString Source #
Send a query via res_query(3)
, the return value is the raw binary response message.
You can use decodeMessage
to decode the response message.
sendRaw :: ByteString -> IO ByteString Source #
Send a raw preformatted query via res_send(3)
.
mkQueryRaw :: Class -> Name -> Type -> IO ByteString Source #
Use res_mkquery(3)
to construct a DNS query message.
decodeMessage :: IsLabels n => ByteString -> Maybe (Msg n) Source #
Decode a raw DNS message (query or response)
Returns Nothing
on decoding failures.
encodeMessage :: IsLabels n => Msg n -> Maybe ByteString Source #
Construct a raw DNS message (query or response)
May return Nothing
in input parameters are detected to be invalid.
mkQueryMsg :: IsLabels n => Class -> n -> Type -> Msg n Source #
Construct a DNS query Msg
in the style of mkQueryRaw
Types
Basic types
Names/Labels
type Label = ByteString Source #
A DNS Label
Must be non-empty and at most 63 octets.
A domain-name
as per RFC 1035, section 3.3 expressed as list of Label
s.
See also Name
class IsLabels s where Source #
Types that represent domain-name
as per RFC 1035, section 3.3 and can be converted to and from Labels
.
<domain-name>
as per RFC 1035, section 3.3.
A domain-name represented as a series of labels separated by dots.
See also Labels
for list-based representation.
NOTE: The Labels
type is able to properly represent domain
names whose components contain dots which the Name
representation
cannot.
caseFoldName :: Name -> Name Source #
Normalise Name
This function case folds Name
s as described in
in RFC 4343, section 3
by subtracting 0x20
from all octets in the inclusive range
[0x61..0x7A]
(i.e. mapping [
to a
..z
][
).A
..Z
]
This operation is idempotent.
Character strings
<character-string>
as per RFC 1035, section 3.3.
A sequence of up to 255 octets
The limit of 255 octets is caused by the encoding which uses by a prefixed octet denoting the length.
IP addresses
An IPv4 address
The IP address is represented in network order, i.e. 127.0.0.1
is
represented as (IPv4 0x7f000001)
.
arpaIPv4 :: IPv4 -> Name Source #
Convert IPv4
address to in-addr.arpa.
Name
(see RFC 1035, section 3.5).
>>>
arpaIPv4 (IPv4 0x8080404)
Name "4.4.8.8.in-addr.arpa."
Since: 0.1.2.0
An IPv6 address
The IP address is represented in network order,
i.e. 2606:2800:220:1:248:1893:25c8:1946
is
represented as (IPv6 0x2606280002200001 0x248189325c81946)
.
arpaIPv6 :: IPv6 -> Name Source #
Convert IPv4
address to ip6.arpa.
Name
(see RFC 3596, section 2.5).
>>>
arpaIPv6 (IPv6 0x2001486048600000 0x8844)
Name "4.4.8.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.8.4.0.6.8.4.1.0.0.2.ip6.arpa."
Since: 0.1.2.0
RR TTL & Class
Cache time-to-live expressed in seconds
DNS CLASS
code as per RFC 1035, section 3.2.4
The most commonly used value is classIN
.
Message types
Raw DNS record type code
See also TypeSym
Symbolic DNS record type
Instances
Bounded TypeSym Source # | |
Enum TypeSym Source # | |
Read TypeSym Source # | |
Show TypeSym Source # | |
Eq TypeSym Source # | |
Ord TypeSym Source # | |
Messages
Represents a DNS message as per RFC 1035
Instances
Foldable Msg Source # | |
Defined in Network.DNS.Message fold :: Monoid m => Msg m -> m # foldMap :: Monoid m => (a -> m) -> Msg a -> m # foldMap' :: Monoid m => (a -> m) -> Msg a -> m # foldr :: (a -> b -> b) -> b -> Msg a -> b # foldr' :: (a -> b -> b) -> b -> Msg a -> b # foldl :: (b -> a -> b) -> b -> Msg a -> b # foldl' :: (b -> a -> b) -> b -> Msg a -> b # foldr1 :: (a -> a -> a) -> Msg a -> a # foldl1 :: (a -> a -> a) -> Msg a -> a # elem :: Eq a => a -> Msg a -> Bool # maximum :: Ord a => Msg a -> a # | |
Traversable Msg Source # | |
Functor Msg Source # | |
Read l => Read (Msg l) Source # | |
Show l => Show (Msg l) Source # | |
Binary l => Binary (Msg l) Source # | |
DNS message header section as per RFC 1035, section 4.1.1
data MsgHeaderFlags Source #
DNS message header flags as per RFC 1035, section 4.1.1
Instances
Read MsgHeaderFlags Source # | |
Defined in Network.DNS.Message readsPrec :: Int -> ReadS MsgHeaderFlags # readList :: ReadS [MsgHeaderFlags] # | |
Show MsgHeaderFlags Source # | |
Defined in Network.DNS.Message showsPrec :: Int -> MsgHeaderFlags -> ShowS # show :: MsgHeaderFlags -> String # showList :: [MsgHeaderFlags] -> ShowS # | |
Binary MsgHeaderFlags Source # | |
Defined in Network.DNS.Message |
Encodes whether message is a query or a response
Since: 0.1.1.0
data MsgQuestion l Source #
DNS message header section as per RFC 1035, section 4.1.2
MsgQuestion !l !Type !Class |
Instances
DNS resource record section as per RFC 1035, section 4.1.3
Instances
Foldable MsgRR Source # | |
Defined in Network.DNS.Message fold :: Monoid m => MsgRR m -> m # foldMap :: Monoid m => (a -> m) -> MsgRR a -> m # foldMap' :: Monoid m => (a -> m) -> MsgRR a -> m # foldr :: (a -> b -> b) -> b -> MsgRR a -> b # foldr' :: (a -> b -> b) -> b -> MsgRR a -> b # foldl :: (b -> a -> b) -> b -> MsgRR a -> b # foldl' :: (b -> a -> b) -> b -> MsgRR a -> b # foldr1 :: (a -> a -> a) -> MsgRR a -> a # foldl1 :: (a -> a -> a) -> MsgRR a -> a # elem :: Eq a => a -> MsgRR a -> Bool # maximum :: Ord a => MsgRR a -> a # minimum :: Ord a => MsgRR a -> a # | |
Traversable MsgRR Source # | |
Functor MsgRR Source # | |
Read l => Read (MsgRR l) Source # | |
Show l => Show (MsgRR l) Source # | |
Binary l => Binary (MsgRR l) Source # | |
Eq l => Eq (MsgRR l) Source # | |
RDataA !IPv4 | |
RDataAAAA !IPv6 | |
RDataCNAME !l | |
RDataPTR !l | |
RDataHINFO !CharStr !CharStr | |
RDataNS !l | |
RDataMX !Word16 !l | |
RDataTXT ![CharStr] | |
RDataSPF ![CharStr] | |
RDataSOA !l !l !Word32 !Word32 !Word32 !Word32 !Word32 | |
RDataSRV !(SRV l) | |
RDataAFSDB !Word16 !l | |
RDataNAPTR !Word16 !Word16 !CharStr !CharStr !CharStr !l | |
RDataURI !Word16 !Word16 !ByteString | |
RDataRRSIG !Word16 !Word8 !Word8 !Word32 !Word32 !Word32 !Word16 !l !ByteString | |
RDataDNSKEY !Word16 !Word8 !Word8 !ByteString | |
RDataDS !Word16 !Word8 !Word8 !ByteString | |
RDataNSEC !l !(Set Type) | |
RDataSSHFP !Word8 !Word8 !ByteString | |
RDataNSEC3PARAM !Word8 !Word8 !Word16 !CharStr | |
RDataNSEC3 !Word8 !Word8 !Word16 !CharStr !CharStr !(Set Type) | |
RDataCAA !Word8 !CharStr !ByteString | |
RDataOPT !ByteString | |
RData !Type !ByteString | Unknown/undecoded resource record type |
Instances
Foldable RData Source # | |
Defined in Network.DNS.Message fold :: Monoid m => RData m -> m # foldMap :: Monoid m => (a -> m) -> RData a -> m # foldMap' :: Monoid m => (a -> m) -> RData a -> m # foldr :: (a -> b -> b) -> b -> RData a -> b # foldr' :: (a -> b -> b) -> b -> RData a -> b # foldl :: (b -> a -> b) -> b -> RData a -> b # foldl' :: (b -> a -> b) -> b -> RData a -> b # foldr1 :: (a -> a -> a) -> RData a -> a # foldl1 :: (a -> a -> a) -> RData a -> a # elem :: Eq a => a -> RData a -> Bool # maximum :: Ord a => RData a -> a # minimum :: Ord a => RData a -> a # | |
Traversable RData Source # | |
Functor RData Source # | |
Read l => Read (RData l) Source # | |
Show l => Show (RData l) Source # | |
Eq l => Eq (RData l) Source # | |
SRV
Record data as per RFC 2782
Instances
Foldable SRV Source # | |
Defined in Network.DNS.Message fold :: Monoid m => SRV m -> m # foldMap :: Monoid m => (a -> m) -> SRV a -> m # foldMap' :: Monoid m => (a -> m) -> SRV a -> m # foldr :: (a -> b -> b) -> b -> SRV a -> b # foldr' :: (a -> b -> b) -> b -> SRV a -> b # foldl :: (b -> a -> b) -> b -> SRV a -> b # foldl' :: (b -> a -> b) -> b -> SRV a -> b # foldr1 :: (a -> a -> a) -> SRV a -> a # foldl1 :: (a -> a -> a) -> SRV a -> a # elem :: Eq a => a -> SRV a -> Bool # maximum :: Ord a => SRV a -> a # | |
Traversable SRV Source # | |
Functor SRV Source # | |
Read l => Read (SRV l) Source # | |
Show l => Show (SRV l) Source # | |
Binary l => Binary (SRV l) Source # | |
Eq l => Eq (SRV l) Source # | |