dnsbase 1.0.1.0 → 1.0.2.0
raw patch · 9 files changed
+559/−331 lines, 9 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Net.DNSBase.RData.Dnssec: [_dsHalg] :: X_ds (n :: Nat) -> DSHashAlg
- Net.DNSBase.RData.Dnssec: [_dsHval] :: X_ds (n :: Nat) -> ShortByteString
- Net.DNSBase.RData.Dnssec: [_dsKalg] :: X_ds (n :: Nat) -> DNSKEYAlg
- Net.DNSBase.RData.Dnssec: [_dsKtag] :: X_ds (n :: Nat) -> Word16
- Net.DNSBase.RData.Dnssec: [_keyAlgor] :: X_key (n :: Nat) -> DNSKEYAlg
- Net.DNSBase.RData.Dnssec: [_keyFlags] :: X_key (n :: Nat) -> Word16
- Net.DNSBase.RData.Dnssec: [_keyProto] :: X_key (n :: Nat) -> Word8
- Net.DNSBase.RData.Dnssec: [_keyValue] :: X_key (n :: Nat) -> ShortByteString
- Net.DNSBase.RData.Dnssec: [_sigExpiration] :: X_sig (n :: Nat) -> Int64
- Net.DNSBase.RData.Dnssec: [_sigInception] :: X_sig (n :: Nat) -> Int64
- Net.DNSBase.RData.Dnssec: [_sigKeyAlg] :: X_sig (n :: Nat) -> DNSKEYAlg
- Net.DNSBase.RData.Dnssec: [_sigKeyTag] :: X_sig (n :: Nat) -> Word16
- Net.DNSBase.RData.Dnssec: [_sigNumLabels] :: X_sig (n :: Nat) -> Word8
- Net.DNSBase.RData.Dnssec: [_sigTTL] :: X_sig (n :: Nat) -> Word32
- Net.DNSBase.RData.Dnssec: [_sigType] :: X_sig (n :: Nat) -> RRTYPE
- Net.DNSBase.RData.Dnssec: [_sigValue] :: X_sig (n :: Nat) -> ShortByteString
- Net.DNSBase.RData.Dnssec: [_sigZone] :: X_sig (n :: Nat) -> Domain
- Net.DNSBase.RData.SRV: [_nidAddr] :: X_nid (n :: Nat) -> Word64
- Net.DNSBase.RData.SRV: [_nidPref] :: X_nid (n :: Nat) -> Word16
- Net.DNSBase.RData.SVCB: [_svcParamValues] :: X_svcb (n :: Nat) -> SPVSet
- Net.DNSBase.RData.SVCB: [_svcPriority] :: X_svcb (n :: Nat) -> Word16
- Net.DNSBase.RData.SVCB: [_svcTarget] :: X_svcb (n :: Nat) -> Domain
- Net.DNSBase.RData.TLSA: [_tlsaAssocData] :: X_tlsa (n :: Nat) -> ShortByteString
- Net.DNSBase.RData.TLSA: [_tlsaMtype] :: X_tlsa (n :: Nat) -> Word8
- Net.DNSBase.RData.TLSA: [_tlsaSelector] :: X_tlsa (n :: Nat) -> Word8
- Net.DNSBase.RData.TLSA: [_tlsaUsage] :: X_tlsa (n :: Nat) -> Word8
+ Net.DNSBase.RData.Dnssec: [x_dsHalg] :: X_ds (n :: Nat) -> DSHashAlg
+ Net.DNSBase.RData.Dnssec: [x_dsHval] :: X_ds (n :: Nat) -> ShortByteString
+ Net.DNSBase.RData.Dnssec: [x_dsKalg] :: X_ds (n :: Nat) -> DNSKEYAlg
+ Net.DNSBase.RData.Dnssec: [x_dsKtag] :: X_ds (n :: Nat) -> Word16
+ Net.DNSBase.RData.Dnssec: [x_keyAlgor] :: X_key (n :: Nat) -> DNSKEYAlg
+ Net.DNSBase.RData.Dnssec: [x_keyFlags] :: X_key (n :: Nat) -> Word16
+ Net.DNSBase.RData.Dnssec: [x_keyProto] :: X_key (n :: Nat) -> Word8
+ Net.DNSBase.RData.Dnssec: [x_keyValue] :: X_key (n :: Nat) -> ShortByteString
+ Net.DNSBase.RData.Dnssec: [x_sigExpiration] :: X_sig (n :: Nat) -> Int64
+ Net.DNSBase.RData.Dnssec: [x_sigInception] :: X_sig (n :: Nat) -> Int64
+ Net.DNSBase.RData.Dnssec: [x_sigKeyAlg] :: X_sig (n :: Nat) -> DNSKEYAlg
+ Net.DNSBase.RData.Dnssec: [x_sigKeyTag] :: X_sig (n :: Nat) -> Word16
+ Net.DNSBase.RData.Dnssec: [x_sigNumLabels] :: X_sig (n :: Nat) -> Word8
+ Net.DNSBase.RData.Dnssec: [x_sigTTL] :: X_sig (n :: Nat) -> Word32
+ Net.DNSBase.RData.Dnssec: [x_sigType] :: X_sig (n :: Nat) -> RRTYPE
+ Net.DNSBase.RData.Dnssec: [x_sigValue] :: X_sig (n :: Nat) -> ShortByteString
+ Net.DNSBase.RData.Dnssec: [x_sigZone] :: X_sig (n :: Nat) -> Domain
+ Net.DNSBase.RData.SRV: [x_nidAddr] :: X_nid (n :: Nat) -> Word64
+ Net.DNSBase.RData.SRV: [x_nidPref] :: X_nid (n :: Nat) -> Word16
+ Net.DNSBase.RData.SVCB: [x_svcParamValues] :: X_svcb (n :: Nat) -> SPVSet
+ Net.DNSBase.RData.SVCB: [x_svcPriority] :: X_svcb (n :: Nat) -> Word16
+ Net.DNSBase.RData.SVCB: [x_svcTarget] :: X_svcb (n :: Nat) -> Domain
+ Net.DNSBase.RData.TLSA: [x_tlsaAssocData] :: X_tlsa (n :: Nat) -> ShortByteString
+ Net.DNSBase.RData.TLSA: [x_tlsaMtype] :: X_tlsa (n :: Nat) -> Word8
+ Net.DNSBase.RData.TLSA: [x_tlsaSelector] :: X_tlsa (n :: Nat) -> Word8
+ Net.DNSBase.RData.TLSA: [x_tlsaUsage] :: X_tlsa (n :: Nat) -> Word8
Files
- CHANGELOG.md +11/−0
- dnsbase.cabal +1/−1
- internal/Net/DNSBase/RData/Internal/XNAME.hs +2/−1
- src/Net/DNSBase/RData/Dnssec.hs +323/−204
- src/Net/DNSBase/RData/SRV.hs +63/−30
- src/Net/DNSBase/RData/SVCB.hs +72/−46
- src/Net/DNSBase/RData/SVCB/SVCParamValue.hs +17/−8
- src/Net/DNSBase/RData/TLSA.hs +68/−39
- tests/extensibility.hs +2/−2
CHANGELOG.md view
@@ -1,5 +1,16 @@ # Changelog +## 1.0.2.0++* Bundled record pattern field selectors with the X_<general>+ type, for easier import. Users may need to import both+ X_name(..), and the T_specific type synonym. Made sure+ this is reflected clearly in the documentation.++## 1.0.1.0++* Exported SVCB modules that should have been public+ ## 1.0.0.0 First public release on Hackage. See [`README.md`](README.md) for
dnsbase.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.12 name: dnsbase-version: 1.0.1.0+version: 1.0.2.0 build-type: Simple synopsis: Stub DNS resolver with a typed RData model and value-based extension API
internal/Net/DNSBase/RData/Internal/XNAME.hs view
@@ -26,7 +26,8 @@ ( -- * Domain-name-valued RR types. -- ** Well-known (from RFC1035) X_domain(T_NS, T_CNAME, T_PTR, T_MB, T_MD, T_MF, T_MG, T_MR)- , type XdomainConName, T_ns, T_cname, T_ptr, T_mb, T_md, T_mf, T_mg, T_mr+ , T_ns, T_cname, T_ptr, T_mb, T_md, T_mf, T_mg, T_mr+ , type XdomainConName -- ** @DNAME@ , T_dname(..) ) where
src/Net/DNSBase/RData/Dnssec.hs view
@@ -26,37 +26,55 @@ too, alongside the re-export of "Net.DNSBase.RData.NSEC" for the denial-of-existence records. -}+{-# OPTIONS_GHC -Wno-duplicate-exports #-} {-# LANGUAGE MagicHash , RecordWildCards , UndecidableInstances #-} module Net.DNSBase.RData.Dnssec- ( -- * DS and DNSKEY+ ( -- * DS, DNSKEY and RRSIG -- ** DS resource records- X_ds(.., T_DS, T_CDS)- , type XdsConName, T_ds, T_cds- -- *** DS fields+ X_ds(.., T_DS, T_CDS+ , dsKtag, dsKalg, dsHalg, dsHval+ , cdsKtag, cdsKalg, cdsHalg, cdsHval)+ , type XdsConName+ -- **** @T_DS@ record pattern synonym fields+ , T_ds , dsKtag, dsKalg, dsHalg, dsHval- -- *** CDS fields+ -- **** @T_CDS@ record pattern synonym fields+ , T_cds , cdsKtag, cdsKalg, cdsHalg, cdsHval -- ** DNSKEY resource records- , X_key(.., T_KEY, T_DNSKEY, T_CDNSKEY)- , type XkeyConName, T_key, T_dnskey, T_cdnskey- -- *** KEY fields- , keyFlags, keyProto, keyAlgor, keyValue- -- *** DNSKEY fields+ , X_key(.., T_DNSKEY, T_CDNSKEY, T_KEY+ , dnskeyFlags, dnskeyProto, dnskeyAlgor, dnskeyValue+ , cdnskeyFlags, cdnskeyProto, cdnskeyAlgor, cdnskeyValue+ , keyFlags, keyProto, keyAlgor, keyValue)+ , type XkeyConName+ -- *** @DNSKEY@ record pattern synonym fields+ , T_dnskey , dnskeyFlags, dnskeyProto, dnskeyAlgor, dnskeyValue- -- *** CDNSKEY fields- , cdnskeyFlags, cdnskeyProto, cdnskeyAlgor, cdnskeyValue+ -- **** Compute a DNSKey tag , keytag- -- * RRSIGs- , X_sig(.., T_SIG, T_RRSIG)- , type XsigConName, T_rrsig, T_sig- -- ** RRSIG fields+ -- *** @CDNSKEY@ record pattern synonym fields+ , T_cdnskey+ , cdnskeyFlags, cdnskeyProto, cdnskeyAlgor, cdnskeyValue+ -- *** @KEY@ record pattern synonym fields+ , T_key+ , keyFlags, keyProto, keyAlgor, keyValue+ -- ** RRSIG resource records+ , X_sig(.., T_RRSIG, T_SIG+ , rrsigType, rrsigKeyAlg, rrsigNumLabels, rrsigTTL+ , rrsigExpiration, rrsigInception, rrsigKeyTag, rrsigZone, rrsigValue+ , sigType, sigKeyAlg, sigNumLabels, sigTTL+ , sigExpiration, sigInception, sigKeyTag, sigZone, sigValue)+ , type XsigConName+ -- *** @RRSIG@ record pattern synonym fields+ , T_rrsig , rrsigType, rrsigKeyAlg, rrsigNumLabels, rrsigTTL , rrsigExpiration, rrsigInception, rrsigKeyTag, rrsigZone, rrsigValue- -- ** SIG fields+ -- *** @SIG@ record pattern synonym fields+ , T_sig , sigType, sigKeyAlg, sigNumLabels, sigTTL , sigExpiration, sigInception, sigKeyTag, sigZone, sigValue -- * IPSECKEY resource records@@ -113,8 +131,27 @@ :<>: TL.Text " is not a SIG or RRSIG RRTYPE" ) -- | X_ds specialised to @DS@ records.+--+-- Note that @T_ds@ is just a type alias! The 'T_DS' record pattern+-- synonym and its fields are bundled with the underlying 'X_ds'+-- data type. In many cases it is sufficient to import just+-- @X_ds(..)@, but if you also need the type alias, it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_ds(..), T_ds)+-- type T_ds = X_ds N_ds+ -- | X_ds specialised to @CDS@ records.+--+-- Note that @T_cds@ is just a type alias! The 'T_CDS' record pattern+-- synonym and its fields are bundled with the underlying 'X_ds'+-- data type. In many cases it is sufficient to import just+-- @X_ds(..)@, but if you also need the type alias it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_ds(..), T_cds)+-- type T_cds = X_ds N_cds -- | Record pattern synonym viewing the shared 'X_ds' record as a@@ -141,26 +178,41 @@ = (X_DS cdsKtag cdsKalg cdsHalg cdsHval :: T_cds) {-# COMPLETE T_CDS #-} --- | X_key specialised to @KEY@ records.-type T_key = X_key N_key -- | X_key specialised to @DNSKEY@ records.+--+-- Note that @T_dnskey@ is just a type alias! The 'T_DNSKEY'+-- record pattern synonym and its fields are bundled with the+-- underlying 'X_key' data type. In many cases it is sufficient+-- to import just @X_key(..)@, but if you also need the type+-- alias, it needs to be imported separately:+--+-- > import Net.DNSBase (X_key(..), T_dnskey)+-- type T_dnskey = X_key N_dnskey+ -- | X_key specialised to @CDNSKEY@ records.+--+-- Note that @T_cdnskey@ is just a type alias! The 'T_CDNSKEY'+-- record pattern synonym and its fields are bundled with the+-- underlying 'X_key' data type. In many cases it is sufficient+-- to import just @X_key(..)@, but if you also need the type+-- alias, it needs to be imported separately:+--+-- > import Net.DNSBase (X_key(..), T_cdnskey)+-- type T_cdnskey = X_key N_cdnskey --- | Record pattern synonym viewing the shared 'X_key' record as a--- legacy @KEY@ record (RFC 2535, section 3), still used by SIG(0)--- transaction authentication. Fields: 'keyFlags', 'keyProto',--- 'keyAlgor', 'keyValue'. Coercible to/from 'T_dnskey' and--- 'T_cdnskey'.-pattern T_KEY :: Word16 -- ^ Flags- -> Word8 -- ^ Protocol selector; for DNSKEY the only valid value is 3 (RFC 4034 section 2.1.2), other values appear in legacy KEY records- -> DNSKEYAlg -- ^ Algorithm- -> ShortByteString -- ^ Public Key- -> T_key-pattern T_KEY { keyFlags, keyProto, keyAlgor, keyValue }- = (X_KEY keyFlags keyProto keyAlgor keyValue :: T_key)-{-# COMPLETE T_KEY #-}+-- | X_key specialised to @KEY@ records.+--+-- Note that @T_key@ is just a type alias! The 'T_KEY' record+-- pattern synonym and its fields are bundled with the underlying+-- 'X_key' data type. In many cases it is sufficient to import+-- just @X_key(..)@, but if you also need the type alias, it needs+-- to be imported separately:+--+-- > import Net.DNSBase (X_key(..), T_key)+--+type T_key = X_key N_key -- | Record pattern synonym viewing the shared 'X_key' record as a -- DNSSEC @DNSKEY@ (RFC 4034, section 2). Fields: 'dnskeyFlags',@@ -189,36 +241,46 @@ = (X_KEY cdnskeyFlags cdnskeyProto cdnskeyAlgor cdnskeyValue :: T_cdnskey) {-# COMPLETE T_CDNSKEY #-} --- | X_sig specialised to @SIG@ / @SIG(0)@ records.-type T_sig = X_sig N_sig+-- | Record pattern synonym viewing the shared 'X_key' record as a+-- legacy @KEY@ record (RFC 2535, section 3), still used by SIG(0)+-- transaction authentication. Fields: 'keyFlags', 'keyProto',+-- 'keyAlgor', 'keyValue'. Coercible to/from 'T_dnskey' and+-- 'T_cdnskey'.+pattern T_KEY :: Word16 -- ^ Flags+ -> Word8 -- ^ Protocol selector;+ -- for DNSKEY the only valid value is 3+ -- (RFC 4034 section 2.1.2), other values+ -- appear in legacy KEY records+ -> DNSKEYAlg -- ^ Algorithm+ -> ShortByteString -- ^ Public Key+ -> T_key+pattern T_KEY { keyFlags, keyProto, keyAlgor, keyValue }+ = (X_KEY keyFlags keyProto keyAlgor keyValue :: T_key)+{-# COMPLETE T_KEY #-}+ -- | X_sig specialised to @RRSIG@ records.+--+-- Note that @T_rrsig@ is just a type alias! The 'T_RRSIG' record+-- pattern synonym and its fields are bundled with the underlying+-- 'X_sig' data type. In many cases it is sufficient to import+-- just @X_sig(..)@, but if you also need the type alias, it needs+-- to be imported separately:+--+-- > import Net.DNSBase (X_sig(..), T_rrsig)+-- type T_rrsig = X_sig N_rrsig --- | Record pattern synonym viewing the shared 'X_sig' record as a--- legacy @SIG@ record (RFC 2535, section 4.1) or @SIG(0)@--- transaction authenticator (RFC 2931). Fields: 'sigType',--- 'sigKeyAlg', 'sigNumLabels', 'sigTTL', 'sigExpiration',--- 'sigInception', 'sigKeyTag', 'sigZone', 'sigValue'. 'Eq' and--- 'Ord' compare the signer name in canonical wire form--- (via 'equalWireHost' / 'compareWireHost'); see 'X_sig' for why--- 'T_sig' and 'T_rrsig' are not coercible.-pattern T_SIG :: RRTYPE -- ^ Type Covered- -> DNSKEYAlg -- ^ Algorithm- -> Word8 -- ^ Number of labels in the signed owner name, excluding any leading wildcard ('*') and the trailing root (RFC 4034 section 3.1.3)- -> Word32 -- ^ Original TTL- -> Int64 -- ^ Signature expiration as absolute 'Int64' time; 32-bit serial-number arithmetic on the wire (see 'X_sig' for the conversion)- -> Int64 -- ^ Signature inception as absolute 'Int64' time; same serial-number caveat as 'sigExpiration'- -> Word16 -- ^ Key Tag- -> Domain -- ^ Signer's Name- -> ShortByteString -- ^ Signature- -> T_sig-pattern T_SIG- { sigType, sigKeyAlg, sigNumLabels, sigTTL- , sigExpiration, sigInception, sigKeyTag, sigZone, sigValue- } = ( X_SIG sigType sigKeyAlg sigNumLabels sigTTL- sigExpiration sigInception sigKeyTag sigZone sigValue- :: T_sig )-{-# COMPLETE T_SIG #-}+-- | X_sig specialised to @SIG@ / @SIG(0)@ records.+--+-- Note that @T_sig@ is just a type alias! The 'T_SIG' record+-- pattern synonym and its fields are bundled with the underlying+-- 'X_sig' data type. In many cases it is sufficient to import+-- just @X_sig(..)@, but if you also need the type alias, it needs+-- to be imported separately:+--+-- > import Net.DNSBase (X_sig(..), T_sig)+--+type T_sig = X_sig N_sig -- | Record pattern synonym viewing the shared 'X_sig' record as a -- DNSSEC @RRSIG@ (RFC 4034, section 3). Fields: 'rrsigType',@@ -245,6 +307,32 @@ :: T_rrsig ) {-# COMPLETE T_RRSIG #-} +-- | Record pattern synonym viewing the shared 'X_sig' record as a+-- legacy @SIG@ record (RFC 2535, section 4.1) or @SIG(0)@+-- transaction authenticator (RFC 2931). Fields: 'sigType',+-- 'sigKeyAlg', 'sigNumLabels', 'sigTTL', 'sigExpiration',+-- 'sigInception', 'sigKeyTag', 'sigZone', 'sigValue'. 'Eq' and+-- 'Ord' compare the signer name in canonical wire form+-- (via 'equalWireHost' / 'compareWireHost'); see 'X_sig' for why+-- 'T_sig' and 'T_rrsig' are not coercible.+pattern T_SIG :: RRTYPE -- ^ Type Covered+ -> DNSKEYAlg -- ^ Algorithm+ -> Word8 -- ^ Number of labels in the signed owner name, excluding any leading wildcard ('*') and the trailing root (RFC 4034 section 3.1.3)+ -> Word32 -- ^ Original TTL+ -> Int64 -- ^ Signature expiration as absolute 'Int64' time; 32-bit serial-number arithmetic on the wire (see 'X_sig' for the conversion)+ -> Int64 -- ^ Signature inception as absolute 'Int64' time; same serial-number caveat as 'sigExpiration'+ -> Word16 -- ^ Key Tag+ -> Domain -- ^ Signer's Name+ -> ShortByteString -- ^ Signature+ -> T_sig+pattern T_SIG+ { sigType, sigKeyAlg, sigNumLabels, sigTTL+ , sigExpiration, sigInception, sigKeyTag, sigZone, sigValue+ } = ( X_SIG sigType sigKeyAlg sigNumLabels sigTTL+ sigExpiration sigInception sigKeyTag sigZone sigValue+ :: T_sig )+{-# COMPLETE T_SIG #-}+ ------------------- -- RData structure Definitions @@ -253,14 +341,6 @@ -- ([RFC 4034 section 5.1](https://datatracker.ietf.org/doc/html/rfc4034#section-5.1)) -- and the child-side @CDS@ announcement -- ([RFC 7344 section 3.1](https://www.rfc-editor.org/rfc/rfc7344.html#section-3.1)).--- The type parameter @n@ (either 'N_ds' or 'N_cds') determines--- the RR type. Each has its own type synonym ('T_ds', 'T_cds')--- and matching record pattern synonym ('T_DS', 'T_CDS') with the--- corresponding field-name prefix (@ds@, @cds@). The wire format--- is identical and the type role of @n@ is @phantom@, so 'T_ds'--- and 'T_cds' are mutually coercible — useful for promoting a--- child-side CDS announcement into a parent-side DS without--- rebuilding the value. -- -- > 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 -- > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1@@ -272,6 +352,24 @@ -- > / / -- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ --+-- The type parameter @n@ (either 'N_ds' or 'N_cds') determines+-- the RR type. Each has its own type synonym ('T_ds', 'T_cds')+-- and matching record pattern synonym ('T_DS', 'T_CDS') with the+-- corresponding field-name prefix (@ds@, @cds@).+--+-- The wire format is identical and the type role of @n@ is+-- @phantom@, so 'T_ds' and 'T_cds' are mutually coercible —+-- useful for promoting a child-side CDS announcement into a+-- parent-side DS without rebuilding the value.+--+-- Note that @T_ds@ and @T_cds@ are just type aliases! The 'T_DS'+-- and 'T_CDS' record pattern synonyms and their fields are+-- bundled with the underlying 'X_ds' data type. In many cases it+-- is sufficient to import just @X_ds(..)@, but if you also need+-- the type aliases, they need to be imported separately:+--+-- > import Net.DNSBase (X_ds(..), T_ds, T_cds)+-- -- No embedded domain field, so derived 'Ord' agrees with the -- canonical wire-form octet ordering -- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).@@ -295,13 +393,14 @@ -- underscore-prefixed selectors on the shared 'X_ds' record: -- -- > hashTypeVal :: forall n. X_ds n -> (Word8, ShortByteString)--- > hashTypeVal = (,) <$> _dsHalg <*> _dsHval+-- > hashTypeVal = (,) <$> x_dsHalg <*> x_dsHval+-- type X_ds :: Nat -> Type data X_ds n = X_DS- { _dsKtag :: Word16 -- ^ Key Tag- , _dsKalg :: DNSKEYAlg -- ^ Algorithm- , _dsHalg :: DSHashAlg -- ^ Digest Type- , _dsHval :: ShortByteString -- ^ Digest+ { x_dsKtag :: Word16 -- ^ Key Tag+ , x_dsKalg :: DNSKEYAlg -- ^ Algorithm+ , x_dsHalg :: DSHashAlg -- ^ Digest Type+ , x_dsHval :: ShortByteString -- ^ Digest } deriving instance (KnownSymbol (XdsConName n)) => Eq (X_ds n) deriving instance (KnownSymbol (XdsConName n)) => Ord (X_ds n)@@ -309,19 +408,19 @@ instance (Nat16 n, KnownSymbol (XdsConName n)) => Show (X_ds n) where showsPrec p X_DS{..} = showsP p $ showString (symbolVal' (proxy# @(XdsConName n))) . showChar ' '- . shows' _dsKtag . showChar ' '- . shows' _dsKalg . showChar ' '- . shows' _dsHalg . showChar ' '- . showHv _dsHval+ . shows' x_dsKtag . showChar ' '+ . shows' x_dsKalg . showChar ' '+ . shows' x_dsHalg . showChar ' '+ . showHv x_dsHval where showHv = shows @Bytes16 . coerce instance (KnownSymbol (XdsConName n)) => Presentable (X_ds n) where present X_DS{..} =- present _dsKtag- . presentSp _dsKalg- . presentSp _dsHalg- . presentHv _dsHval+ present x_dsKtag+ . presentSp x_dsKalg+ . presentSp x_dsHalg+ . presentHv x_dsHval where presentHv = presentSp @Bytes16 . coerce @@ -329,15 +428,15 @@ rdType _ = RRTYPE $ natToWord16 n {-# INLINE rdType #-} rdEncode X_DS{..} = putSizedBuilder $!- mbWord16 _dsKtag- <> coerce mbWord8 _dsKalg- <> coerce mbWord8 _dsHalg- <> mbShortByteString _dsHval+ mbWord16 x_dsKtag+ <> coerce mbWord8 x_dsKalg+ <> coerce mbWord8 x_dsHalg+ <> mbShortByteString x_dsHval rdDecode _ _ = const do- _dsKtag <- get16- _dsKalg <- DNSKEYAlg <$> get8- _dsHalg <- DSHashAlg <$> get8- _dsHval <- getShortByteString+ x_dsKtag <- get16+ x_dsKalg <- DNSKEYAlg <$> get8+ x_dsHalg <- DSHashAlg <$> get8+ x_dsHval <- getShortByteString pure $ RData (X_DS{..} :: X_ds n) -- | Shared wire-format representation for DNSSEC signing-key@@ -350,15 +449,7 @@ -- @KEY@ record -- ([RFC 2535 section 3.1](https://datatracker.ietf.org/doc/html/rfc2535#section-3.1)) -- still used by SIG(0) transaction authentication and otherwise--- effectively unused in modern deployments. The type parameter--- @n@ (one of 'N_key', 'N_dnskey', 'N_cdnskey') determines the--- RR type. Each has its own type synonym ('T_key', 'T_dnskey',--- 'T_cdnskey') and matching record pattern synonym ('T_KEY',--- 'T_DNSKEY', 'T_CDNSKEY') with the corresponding field-name--- prefix (@key@, @dnskey@, @cdnskey@). The wire format is--- identical across all three and the type role of @n@ is--- @phantom@, so the types are mutually coercible; the practical--- pairing is DNSKEY \<-\> CDNSKEY (mirroring DS \<-\> CDS).+-- effectively unused in modern deployments. -- -- > 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 -- > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1@@ -370,6 +461,25 @@ -- > / / -- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ --+-- The type parameter @n@ (one of 'N_dnskey', 'N_cdnskey',+-- 'N_key') determines the RR type. Each has its own type synonym+-- ('T_dnskey', 'T_cdnskey', 'T_key') and matching record pattern+-- synonym ('T_DNSKEY', 'T_CDNSKEY', 'T_KEY') with the+-- corresponding field-name prefix (@dnskey@, @cdnskey@, @key@).+-- The wire format is identical across all three and the type role+-- of @n@ is @phantom@, so the types are mutually coercible; the+-- practical pairing is DNSKEY \<-\> CDNSKEY (mirroring DS \<-\>+-- CDS).+--+-- Note that @T_dnskey@, @T_cdnskey@ and @T_key@ are just type+-- aliases! The 'T_DNSKEY', 'T_CDNSKEY' and 'T_KEY' record+-- pattern synonyms and their fields are bundled with the+-- underlying 'X_key' data type. In many cases it is sufficient+-- to import just @X_key(..)@, but if you also need the type+-- aliases, they need to be imported separately:+--+-- > import Net.DNSBase (X_key(..), T_dnskey, T_cdnskey, T_key)+-- -- No embedded domain field, so derived 'Ord' agrees with the -- canonical wire-form octet ordering -- ([RFC 4034 section 6.2](https://datatracker.ietf.org/doc/html/rfc4034#section-6.2)).@@ -392,14 +502,14 @@ -- underscore-prefixed selectors on the shared 'X_key' record: -- -- > keyAlgVal :: forall n. X_key n -> (DNSKEYAlg, ShortByteString)--- > keyAlgVal = (,) <$> _keyAlgor <*> _keyValue+-- > keyAlgVal = (,) <$> x_keyAlgor <*> x_keyValue type role X_key phantom type X_key :: Nat -> Type data X_key n = X_KEY- { _keyFlags :: Word16 -- ^ Flags- , _keyProto :: Word8 -- ^ Protocol- , _keyAlgor :: DNSKEYAlg -- ^ Algorithm- , _keyValue :: ShortByteString -- ^ Public Key+ { x_keyFlags :: Word16 -- ^ Flags+ , x_keyProto :: Word8 -- ^ Protocol+ , x_keyAlgor :: DNSKEYAlg -- ^ Algorithm+ , x_keyValue :: ShortByteString -- ^ Public Key } deriving instance (KnownSymbol (XkeyConName n)) => Eq (X_key n) deriving instance (KnownSymbol (XkeyConName n)) => Ord (X_key n)@@ -407,19 +517,19 @@ instance (Nat16 n, KnownSymbol (XkeyConName n)) => Show (X_key n) where showsPrec p X_KEY{..} = showsP p $ showString (symbolVal' (proxy# @(XkeyConName n))) . showChar ' '- . shows' _keyFlags . showChar ' '- . shows' _keyProto . showChar ' '- . shows' _keyAlgor . showChar ' '- . showKv _keyValue+ . shows' x_keyFlags . showChar ' '+ . shows' x_keyProto . showChar ' '+ . shows' x_keyAlgor . showChar ' '+ . showKv x_keyValue where showKv = shows @Bytes64 . coerce instance (KnownSymbol (XkeyConName n)) => Presentable (X_key n) where present X_KEY{..} =- present _keyFlags- . presentSp _keyProto- . presentSp _keyAlgor- . presentKv _keyValue+ present x_keyFlags+ . presentSp x_keyProto+ . presentSp x_keyAlgor+ . presentKv x_keyValue where presentKv = presentSp @Bytes64 . coerce @@ -427,15 +537,15 @@ rdType _ = RRTYPE $ natToWord16 n {-# INLINE rdType #-} rdEncode X_KEY{..} = putSizedBuilder $!- mbWord16 _keyFlags- <> mbWord8 _keyProto- <> coerce mbWord8 _keyAlgor- <> mbShortByteString _keyValue+ mbWord16 x_keyFlags+ <> mbWord8 x_keyProto+ <> coerce mbWord8 x_keyAlgor+ <> mbShortByteString x_keyValue rdDecode _ _ = const do- _keyFlags <- get16- _keyProto <- get8- _keyAlgor <- DNSKEYAlg <$> get8- _keyValue <- getShortByteString+ x_keyFlags <- get16+ x_keyProto <- get8+ x_keyAlgor <- DNSKEYAlg <$> get8+ x_keyValue <- getShortByteString pure $ RData (X_KEY{..} :: X_key n) -- | Shared wire-format representation for DNSSEC signature@@ -445,15 +555,6 @@ -- ([RFC 2535 section 4.1](https://datatracker.ietf.org/doc/html/rfc2535#section-4.1)) -- and its @SIG(0)@ transaction-authentication use -- ([RFC 2931 section 3](https://datatracker.ietf.org/doc/html/rfc2931#section-3)).--- The type parameter @n@ (either 'N_sig' or 'N_rrsig') determines--- the RR type. Each has its own type synonym ('T_sig', 'T_rrsig')--- and matching record pattern synonym ('T_SIG', 'T_RRSIG') with--- the corresponding field-name prefix (@sig@, @rrsig@). The--- wire format is shared, but the type role of @n@ is @nominal@:--- a 'T_sig' value cannot be used where a 'T_rrsig' is expected.--- This is deliberate — SIG(0) signs a single transaction while--- RRSIG signs an RRSet, and conflating them at the type level--- would be unsafe. -- -- > 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 -- > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1@@ -475,6 +576,24 @@ -- > / / -- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ --+-- The type parameter @n@ (either 'N_rrsig' or 'N_sig') determines+-- the RR type. Each has its own type synonym ('T_rrsig', 'T_sig')+-- and matching record pattern synonym ('T_RRSIG', 'T_SIG') with+-- the corresponding field-name prefix (@rrsig@, @sig@). The+-- wire format is shared, but the type role of @n@ is @nominal@:+-- a 'T_sig' value cannot be used where a 'T_rrsig' is expected.+-- This is deliberate — SIG(0) signs a single transaction while+-- RRSIG signs an RRSet, and conflating them at the type level+-- would be unsafe.+--+-- Note that @T_rrsig@ and @T_sig@ are just type aliases! The 'T_RRSIG' and+-- 'T_SIG' record pattern synonyms and their fields are bundled+-- with the underlying 'X_sig' data type. In many cases it is+-- sufficient to import just @X_sig(..)@, but if you also need the+-- type aliases, they need to be imported separately:+--+-- > import Net.DNSBase (X_sig(..), T_rrsig, T_sig)+-- -- As noted in -- [Section 3.1.5 of RFC 4034](https://tools.ietf.org/html/rfc4034#section-3.1.5) -- the RRsig inception and expiration times use serial number arithmetic. As a@@ -511,67 +630,67 @@ type role X_sig nominal type X_sig :: Nat -> Type data X_sig n = X_SIG- { _sigType :: RRTYPE -- ^ Type Covered- , _sigKeyAlg :: DNSKEYAlg -- ^ Algorithm- , _sigNumLabels :: Word8 -- ^ Labels- , _sigTTL :: Word32 -- ^ Original TTL- , _sigExpiration :: Int64 -- ^ Signature Expiration- , _sigInception :: Int64 -- ^ Signature Inception- , _sigKeyTag :: Word16 -- ^ Key Tag- , _sigZone :: Domain -- ^ Signer's Name- , _sigValue :: ShortByteString -- ^ Signature+ { x_sigType :: RRTYPE -- ^ Type Covered+ , x_sigKeyAlg :: DNSKEYAlg -- ^ Algorithm+ , x_sigNumLabels :: Word8 -- ^ Labels+ , x_sigTTL :: Word32 -- ^ Original TTL+ , x_sigExpiration :: Int64 -- ^ Signature Expiration+ , x_sigInception :: Int64 -- ^ Signature Inception+ , x_sigKeyTag :: Word16 -- ^ Key Tag+ , x_sigZone :: Domain -- ^ Signer's Name+ , x_sigValue :: ShortByteString -- ^ Signature } instance (Nat16 n, KnownSymbol (XsigConName n)) => Show (X_sig n) where showsPrec p X_SIG{..} = showsP p $ showString (symbolVal' (proxy# @(XsigConName n))) . showChar ' '- . shows' _sigType . showChar ' '- . shows' _sigKeyAlg . showChar ' '- . shows' _sigNumLabels . showChar ' '- . shows' _sigTTL . showChar ' '- . shows' _sigExpiration . showChar ' '- . shows' _sigInception . showChar ' '- . shows' _sigKeyTag . showChar ' '- . shows' _sigZone . showChar ' '- . showSv _sigValue+ . shows' x_sigType . showChar ' '+ . shows' x_sigKeyAlg . showChar ' '+ . shows' x_sigNumLabels . showChar ' '+ . shows' x_sigTTL . showChar ' '+ . shows' x_sigExpiration . showChar ' '+ . shows' x_sigInception . showChar ' '+ . shows' x_sigKeyTag . showChar ' '+ . shows' x_sigZone . showChar ' '+ . showSv x_sigValue where showSv = shows @Bytes64 . coerce -- | Equality of signer names is case-insensitive. instance (KnownSymbol (XsigConName n)) => Eq (X_sig n) where- a == b = (_sigType a) == (_sigType b)- && (_sigKeyAlg a) == (_sigKeyAlg b)- && (_sigNumLabels a) == (_sigNumLabels b)- && (_sigTTL a) == (_sigTTL b)- && (_sigExpiration a) == (_sigExpiration b)- && (_sigInception a) == (_sigInception b)- && (_sigKeyTag a) == (_sigKeyTag b)- && (_sigZone a) `equalWireHost` (_sigZone b)- && (_sigValue a) == (_sigValue b)+ a == b = (x_sigType a) == (x_sigType b)+ && (x_sigKeyAlg a) == (x_sigKeyAlg b)+ && (x_sigNumLabels a) == (x_sigNumLabels b)+ && (x_sigTTL a) == (x_sigTTL b)+ && (x_sigExpiration a) == (x_sigExpiration b)+ && (x_sigInception a) == (x_sigInception b)+ && (x_sigKeyTag a) == (x_sigKeyTag b)+ && (x_sigZone a) `equalWireHost` (x_sigZone b)+ && (x_sigValue a) == (x_sigValue b) -- | Comparison of signer names is case-insensitive. instance (KnownSymbol (XsigConName n)) => Ord (X_sig n) where- a `compare` b = (_sigType a) `compare` (_sigType b)- <> (_sigKeyAlg a) `compare` (_sigKeyAlg b)- <> (_sigNumLabels a) `compare` (_sigNumLabels b)- <> (_sigTTL a) `compare` (_sigTTL b)- <> (_sigExpiration a) `compare` (_sigExpiration b)- <> (_sigInception a) `compare` (_sigInception b)- <> (_sigKeyTag a) `compare` (_sigKeyTag b)- <> (_sigZone a) `compareWireHost` (_sigZone b)- <> (_sigValue a) `compare` (_sigValue b)+ a `compare` b = (x_sigType a) `compare` (x_sigType b)+ <> (x_sigKeyAlg a) `compare` (x_sigKeyAlg b)+ <> (x_sigNumLabels a) `compare` (x_sigNumLabels b)+ <> (x_sigTTL a) `compare` (x_sigTTL b)+ <> (x_sigExpiration a) `compare` (x_sigExpiration b)+ <> (x_sigInception a) `compare` (x_sigInception b)+ <> (x_sigKeyTag a) `compare` (x_sigKeyTag b)+ <> (x_sigZone a) `compareWireHost` (x_sigZone b)+ <> (x_sigValue a) `compare` (x_sigValue b) instance (KnownSymbol (XsigConName n)) => Presentable (X_sig n) where present X_SIG{..} =- present _sigType- . presentSp _sigKeyAlg- . presentSp _sigNumLabels- . presentSp _sigTTL- . presentEp _sigExpiration- . presentEp _sigInception- . presentSp _sigKeyTag- . presentSp _sigZone- . presentSv _sigValue+ present x_sigType+ . presentSp x_sigKeyAlg+ . presentSp x_sigNumLabels+ . presentSp x_sigTTL+ . presentEp x_sigExpiration+ . presentEp x_sigInception+ . presentSp x_sigKeyTag+ . presentSp x_sigZone+ . presentSv x_sigValue where presentEp = presentSp @Epoch64 . coerce presentSv = presentSp @Bytes64 . coerce@@ -580,41 +699,41 @@ rdType _ = RRTYPE $ natToWord16 n {-# INLINE rdType #-} rdEncode X_SIG{..} = putSizedBuilder $- coerce mbWord16 _sigType- <> coerce mbWord8 _sigKeyAlg- <> mbWord8 _sigNumLabels- <> mbWord32 _sigTTL- <> coerce clock _sigExpiration- <> coerce clock _sigInception- <> mbWord16 _sigKeyTag- <> mbWireForm _sigZone- <> mbShortByteString _sigValue+ coerce mbWord16 x_sigType+ <> coerce mbWord8 x_sigKeyAlg+ <> mbWord8 x_sigNumLabels+ <> mbWord32 x_sigTTL+ <> coerce clock x_sigExpiration+ <> coerce clock x_sigInception+ <> mbWord16 x_sigKeyTag+ <> mbWireForm x_sigZone+ <> mbShortByteString x_sigValue where clock :: Int64 -> SizedBuilder clock = mbWord32 . fromIntegral cnEncode X_SIG{..} = putSizedBuilder $- coerce mbWord16 _sigType- <> coerce mbWord8 _sigKeyAlg- <> mbWord8 _sigNumLabels- <> mbWord32 _sigTTL- <> coerce clock _sigExpiration- <> coerce clock _sigInception- <> mbWord16 _sigKeyTag- <> mbWireForm (canonicalise _sigZone)+ coerce mbWord16 x_sigType+ <> coerce mbWord8 x_sigKeyAlg+ <> mbWord8 x_sigNumLabels+ <> mbWord32 x_sigTTL+ <> coerce clock x_sigExpiration+ <> coerce clock x_sigInception+ <> mbWord16 x_sigKeyTag+ <> mbWireForm (canonicalise x_sigZone) -- | Canonical encoding of the RRSIG omits the signature value. where clock :: Int64 -> SizedBuilder clock = mbWord32 . fromIntegral rdDecode _ _ = const do- _sigType <- RRTYPE <$> get16- _sigKeyAlg <- DNSKEYAlg <$> get8- _sigNumLabels <- get8- _sigTTL <- get32- _sigExpiration <- getDnsTime- _sigInception <- getDnsTime- _sigKeyTag <- get16- _sigZone <- getDomainNC- _sigValue <- getShortByteString+ x_sigType <- RRTYPE <$> get16+ x_sigKeyAlg <- DNSKEYAlg <$> get8+ x_sigNumLabels <- get8+ x_sigTTL <- get32+ x_sigExpiration <- getDnsTime+ x_sigInception <- getDnsTime+ x_sigKeyTag <- get16+ x_sigZone <- getDomainNC+ x_sigValue <- getShortByteString pure $ RData (X_SIG{..} :: X_sig n) -- | The @ZONEMD@ resource record@@ -848,17 +967,17 @@ go :: X_key n -> Word32 go X_KEY{..} | alg /= 1 = tag where- (DNSKEYAlg alg) = _keyAlgor- !z = lo _keyFlags + hi _keyProto + lo alg- ws32 = zipWith ($) (cycle [hi, lo]) $ SB.unpack _keyValue+ (DNSKEYAlg alg) = x_keyAlgor+ !z = lo x_keyFlags + hi x_keyProto + lo alg+ ws32 = zipWith ($) (cycle [hi, lo]) $ SB.unpack x_keyValue !raw = foldl' (+) z ws32 !tag = (raw + (raw `shiftR` 16)) .&. 0xffff go X_KEY{..} | Just !tag <- c32 = tag | otherwise = 0 where- len = SB.length _keyValue- c32 = (+) <$> (hi <$.> SB.indexMaybe _keyValue (len - 3))- <*> (lo <$.> SB.indexMaybe _keyValue (len - 2))+ len = SB.length x_keyValue+ c32 = (+) <$> (hi <$.> SB.indexMaybe x_keyValue (len - 3))+ <*> (lo <$.> SB.indexMaybe x_keyValue (len - 2)) hi, lo :: Integral a => a -> Word32 lo = fromIntegral
src/Net/DNSBase/RData/SRV.hs view
@@ -16,6 +16,7 @@ domain field treat it case-sensitively in canonical form per RFC 6840 section 5.1. -}+{-# OPTIONS_GHC -Wno-duplicate-exports #-} {-# LANGUAGE MagicHash , RecordWildCards@@ -23,19 +24,22 @@ #-} module Net.DNSBase.RData.SRV- ( T_mx(..)+ ( -- * MX, SRV, AFSDB and NAPTR+ T_mx(..) , T_srv(..) , T_afsdb(..) , T_naptr(..) -- * NID and L64- , X_nid(.., T_NID, T_L64)- , type XnidConName, T_nid, T_l64- -- *** 'T_NID' fields- , nidPref- , nidAddr- -- *** 'T_L64' fields- , l64Pref- , l64Addr+ , X_nid(.., T_NID, T_L64+ , nidPref, nidAddr+ , l64Pref, l64Addr)+ , type XnidConName+ -- *** @T_NID@ record pattern synonym fields+ , T_nid+ , nidPref, nidAddr+ -- *** @T_L64@ record pattern synonym fields+ , T_l64+ , l64Pref, l64Addr -- * L32 , T_l32(..) -- * LP@@ -74,8 +78,27 @@ :<>: TL.Text " is not a NID or L64 RRTYPE" ) -- | X_nid specialised to @NID@ records.+--+-- Note that @T_nid@ is just a type alias! The 'T_NID' record pattern+-- synonym and its fields are bundled with the underlying 'X_nid'+-- data type. In many cases it is sufficient to import just+-- @X_nid(..)@, but if you also need the type alias, it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_nid(..), T_nid)+-- type T_nid = X_nid N_nid+ -- | X_nid specialised to @L64@ records.+--+-- Note that @T_l64@ is just a type alias! The 'T_L64' record pattern+-- synonym and its fields are bundled with the underlying 'X_nid'+-- data type. In many cases it is sufficient to import just+-- @X_nid(..)@, but if you also need the type alias, it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_nid(..), T_l64)+-- type T_l64 = X_nid N_l64 -- | Record pattern synonym viewing the shared 'X_nid' record as an@@ -363,17 +386,7 @@ -- ([RFC 6742 section 2.1.1](https://www.rfc-editor.org/rfc/rfc6742.html#section-2.1.1)) -- carries a 64-bit Node-ID, and @L64@ -- ([RFC 6742 section 2.3.1](https://www.rfc-editor.org/rfc/rfc6742.html#section-2.3.1))--- carries a 64-bit IPv6 locator prefix. The type parameter @n@--- (either 'N_nid' or 'N_l64') determines the RR type. Each has--- its own type synonym ('T_nid', 'T_l64') and matching record--- pattern synonym ('T_NID', 'T_L64') with the corresponding--- field-name prefix (@nid@, @l64@). The role of 'X_nid' is--- /nominal/: the 64-bit payload means different things in each,--- so 'T_nid' and 'T_l64' are not coercible.------ Derived 'Ord' is canonical: no embedded domain, fields compared--- in wire-encoding order. See 'T_l32' and 'T_lp' for the rest--- of the ILNP record family.+-- carries a 64-bit IPv6 locator prefix. -- -- > 0 1 2 3 -- > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1@@ -385,11 +398,31 @@ -- > | | -- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ --+-- The type parameter @n@ (either 'N_nid' or 'N_l64') determines+-- the RR type. Each has its own type synonym ('T_nid', 'T_l64')+-- and matching record pattern synonym ('T_NID', 'T_L64') with the+-- corresponding field-name prefix (@nid@, @l64@). The role of+-- 'X_nid' is /nominal/: the 64-bit payload means different things+-- in each, so 'T_nid' and 'T_l64' are not coercible.+--+-- Note that @T_nid@ and @T_l64@ are just type aliases! The+-- 'T_NID' and 'T_L64' record pattern synonyms and their fields+-- are bundled with the underlying 'X_nid' data type. In many+-- cases it is sufficient to import just @X_nid(..)@, but if you+-- also need the type aliases, they need to be imported+-- separately:+--+-- > import Net.DNSBase (X_nid(..), T_nid, T_l64)+--+-- Derived 'Ord' is canonical: no embedded domain, fields compared+-- in wire-encoding order. See 'T_l32' and 'T_lp' for the rest+-- of the ILNP record family.+-- type X_nid :: Nat -> Type type role X_nid nominal data X_nid n = X_NID- { _nidPref :: Word16 -- ^ Preference- , _nidAddr :: Word64 -- ^ Node ID or 64-bit IPv6 prefix+ { x_nidPref :: Word16 -- ^ Preference+ , x_nidAddr :: Word64 -- ^ Node ID or 64-bit IPv6 prefix } deriving instance (KnownSymbol (XnidConName n)) => Eq (X_nid n) deriving instance (KnownSymbol (XnidConName n)) => Ord (X_nid n)@@ -397,27 +430,27 @@ instance (Nat16 n, KnownSymbol (XnidConName n)) => Show (X_nid n) where showsPrec p X_NID{..} = showsP p $ showString (symbolVal' (proxy# @(XnidConName n)))- . showChar ' ' . shows' _nidPref- . showChar ' ' . shows' _nidAddr+ . showChar ' ' . shows' x_nidPref+ . showChar ' ' . shows' x_nidAddr instance (KnownSymbol (XnidConName n)) => Presentable (X_nid n) where present X_NID{..} =- present _nidPref+ present x_nidPref . \k -> bld ' ' 48 <> bld ':' 32 <> bld ':' 16 <> bld ':' 0 <> k where bld :: Char -> Int -> Builder bld sep shft = char8 sep <>- (word16HexFixed $ fromIntegral $ _nidAddr `shiftR` shft)+ (word16HexFixed $ fromIntegral $ x_nidAddr `shiftR` shft) instance (Nat16 n, KnownSymbol (XnidConName n)) => KnownRData (X_nid n) where rdType _ = RRTYPE $ natToWord16 n {-# INLINE rdType #-} rdEncode X_NID{..} = putSizedBuilder $- mbWord16 _nidPref- <> mbWord64 _nidAddr+ mbWord16 x_nidPref+ <> mbWord64 x_nidAddr rdDecode _ _ = const do- _nidPref <- get16- _nidAddr <- get64+ x_nidPref <- get16+ x_nidAddr <- get64 pure $ RData (X_NID{..} :: X_nid n) -- | The @L32@ resource record
src/Net/DNSBase/RData/SVCB.hs view
@@ -43,19 +43,17 @@ module Net.DNSBase.RData.SVCB ( -- * SVCB and HTTPS- X_svcb(.., T_SVCB, T_HTTPS)+ X_svcb(.., T_SVCB, T_HTTPS+ , httpsPriority, httpsTarget, httpsParamValues+ , svcPriority, svcTarget, svcParamValues) , type XsvcbConName- , T_svcb+ -- *** @T_HTTPS@ pattern record synonym fields , T_https- -- *** 'T_SVCB' fields- , svcPriority- , svcTarget- , svcParamValues- -- *** 'T_HTTPS' fields- , httpsPriority- , httpsTarget- , httpsParamValues- -- * Service parameter values+ , httpsPriority, httpsTarget, httpsParamValues+ -- *** @T_SVCB@ pattern record synonym fields+ , T_svcb+ , svcPriority, svcTarget, svcParamValues+ -- ** Service parameter values , KnownSVCParamValue(..) , SPVSet(..) , spvLookup@@ -102,22 +100,29 @@ -- type SPVDecoderMap = IntMap (Int -> SGet SVCParamValue) --- | X_svcb specialised to @SVCB@ records.-type T_svcb = X_svcb N_svcb -- | X_svcb specialised to @HTTPS@ records.+--+-- Note that @T_https@ is just a type alias! The 'T_HTTPS' record pattern+-- synonym and its fields are bundled with the underlying 'X_svcb'+-- data type. In many cases it is sufficient to import just+-- @X_svcb(..)@, but if you also need the type alias, it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_svcb(..), T_https)+-- type T_https = X_svcb N_https --- | Record pattern synonym viewing the shared 'X_svcb' record as a--- generic SVCB service-binding record (RFC 9460). Fields:--- 'svcPriority', 'svcTarget', 'svcParamValues'. See 'X_svcb' for--- why 'T_svcb' and 'T_https' are not coercible.-pattern T_SVCB :: Word16 -- ^ SvcPriority- -> Domain -- ^ TargetName- -> SPVSet -- ^ SvcParams- -> T_svcb-pattern T_SVCB { svcPriority, svcTarget, svcParamValues }- = (X_SVCB svcPriority svcTarget svcParamValues :: T_svcb)-{-# COMPLETE T_SVCB #-}+-- | X_svcb specialised to @SVCB@ records.+--+-- Note that @T_svcb@ is just a type alias! The 'T_SCVB' record pattern+-- synonym and its fields are bundled with the underlying 'X_svcb'+-- data type. In many cases it is sufficient to import just+-- @X_svcb(..)@, but if you also need the type alias, it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_svcb(..), T_svcb)+--+type T_svcb = X_svcb N_svcb -- | Record pattern synonym viewing the shared 'X_svcb' record as -- an HTTPS service-binding record (RFC 9460). Fields:@@ -130,20 +135,23 @@ = (X_SVCB httpsPriority httpsTarget httpsParamValues :: T_https) {-# COMPLETE T_HTTPS #-} +-- | Record pattern synonym viewing the shared 'X_svcb' record as a+-- generic SVCB service-binding record (RFC 9460). Fields:+-- 'svcPriority', 'svcTarget', 'svcParamValues'. See 'X_svcb' for+-- why 'T_svcb' and 'T_https' are not coercible.+pattern T_SVCB :: Word16 -- ^ SvcPriority+ -> Domain -- ^ TargetName+ -> SPVSet -- ^ SvcParams+ -> T_svcb+pattern T_SVCB { svcPriority, svcTarget, svcParamValues }+ = (X_SVCB svcPriority svcTarget svcParamValues :: T_svcb)+{-# COMPLETE T_SVCB #-}+ -- | Shared wire-format representation for the @SVCB@ service -- binding record -- ([RFC 9460 section 2](https://datatracker.ietf.org/doc/html/rfc9460#section-2)) -- and its HTTPS-specific variant -- ([RFC 9460 section 9](https://datatracker.ietf.org/doc/html/rfc9460#section-9)).--- The type parameter @n@ (either 'N_svcb' or 'N_https') determines--- the RR type. Each has its own type synonym ('T_svcb',--- 'T_https') and matching record pattern synonym ('T_SVCB',--- 'T_HTTPS') with the corresponding field-name prefix (@svc@,--- @https@). The wire format is shared, but the type role of--- @n@ is @nominal@: a 'T_svcb' value cannot be used where a--- 'T_https' is expected. This is deliberate — the two RR types--- serve different transports, and future SvcParamKeys may apply--- to only one of them. -- -- > 1 1 1 1 1 1 -- > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5@@ -157,6 +165,24 @@ -- > / / -- > +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ --+-- The type parameter @n@ (either 'N_https' or 'N_svcb')+-- determines the RR type. Each has its own type synonym+-- ('T_https', 'T_svcb') and matching record pattern synonym+-- ('T_HTTPS', 'T_SVCB') with the corresponding field-name prefix+-- (@https@, @svcb@). The wire format is shared, but the type+-- role of @n@ is @nominal@: a 'T_svcb' value cannot be used where+-- a 'T_https' is expected. This is deliberate — the two RR types+-- serve different transports, and future SvcParamKeys may apply+-- to only one of them.+--+-- Note that @T_https@ and @T_svcb@ are just type aliases! The 'T_HTTPS'+-- and 'T_SVCB' record pattern synonyms and their fields are+-- bundled with the underlying 'X_svcb' data type. In many cases it+-- is sufficient to import just @X_svcb(..)@, but if you also need+-- the type aliases, they need to be imported separately:+--+-- > import Net.DNSBase (X_svcb(..), T_https, T_svcb)+-- -- The target field is not subject to wire-form name compression -- ([RFC 3597 section 4](https://datatracker.ietf.org/doc/html/rfc3597#section-4)) -- and is /not/ in the@@ -204,14 +230,14 @@ -- underscore-prefixed selectors on the shared 'X_svcb' record: -- -- > aliasDomain :: forall n. X_svcb n -> Maybe Domain--- > aliasDomain r | _svcPriority r == 0 = Just $ _svcTarget r+-- > aliasDomain r | x_svcPriority r == 0 = Just $ x_svcTarget r -- > | otherwise = Nothing type X_svcb :: Nat -> Type type role X_svcb nominal data X_svcb n = X_SVCB- { _svcPriority :: Word16 -- ^ SvcPriority- , _svcTarget :: Domain -- ^ TargetName- , _svcParamValues :: SPVSet -- ^ SvcParams+ { x_svcPriority :: Word16 -- ^ SvcPriority+ , x_svcTarget :: Domain -- ^ TargetName+ , x_svcParamValues :: SPVSet -- ^ SvcParams } deriving instance Eq (X_svcb n)@@ -219,16 +245,16 @@ instance (KnownSymbol (XsvcbConName n)) => Show (X_svcb n) where showsPrec p X_SVCB{..} = showsP p $ showString (symbolVal' (proxy# @(XsvcbConName n))) . showChar ' '- . shows' _svcPriority . showChar ' '- . shows' _svcTarget . showChar ' '- . shows' _svcParamValues+ . shows' x_svcPriority . showChar ' '+ . shows' x_svcTarget . showChar ' '+ . shows' x_svcParamValues instance Ord (X_svcb n) where- a `compare` b = (_svcPriority a) `compare` (_svcPriority b)- <> (_svcTarget a) `compare` (_svcTarget b)+ a `compare` b = (x_svcPriority a) `compare` (x_svcPriority b)+ <> (x_svcTarget a) `compare` (x_svcTarget b) <> (spvs a) `compare` (spvs b) where- spvs = toList . _svcParamValues+ spvs = toList . x_svcParamValues instance Presentable (X_svcb n) where present (X_SVCB p d vs) =@@ -251,11 +277,11 @@ -- and can be extended at runtime as part of resolver configuration. rdDecode _ sdm len = do pos0 <- getPosition- _svcPriority <- get16- _svcTarget <- getDomainNC+ x_svcPriority <- get16+ x_svcTarget <- getDomainNC pos1 <- getPosition vals <- decodeSVCFieldValues (len - (pos1 - pos0))- let _svcParamValues = spvSetFromMonoList $ reverse vals+ let x_svcParamValues = spvSetFromMonoList $ reverse vals pure $ RData $ (X_SVCB{..} :: X_svcb n) where decodeSVCFieldValues :: Int -> SGet [SVCParamValue]
src/Net/DNSBase/RData/SVCB/SVCParamValue.hs view
@@ -46,12 +46,7 @@ -- | The class of types representing the value side of a service -- parameter inside an @SVCB@ or @HTTPS@ record. Each instance -- corresponds to a specific 'SVCParamKey'; the 'encodeSPV' and--- 'decodeSPV' methods handle only the value bytes. The--- surrounding @(key, length)@ frame is owned by the SVCB-record--- encoder: 'encodeSPV' writes just the payload, and the framework--- wraps the result in the 2-byte length prefix.--- For value-less parameters this means 'encodeSPV' is just--- @pure ()@.+-- 'decodeSPV' methods handle only the value bytes. -- -- The 'Presentable' instance builds the RFC 9460 zone-file -- presentation form: the key name followed (where the value is@@ -63,9 +58,23 @@ spvKey :: forall b -> b ~ a => SVCParamKey -- | CPS presentation form builder for the key spvKeyPres :: forall b -> b ~ a => Builder -> Builder- -- | Encode value to wire form++ -- | Encode value to wire form.+ -- The surrounding @(key, length)@ frame is owned by the+ -- SVCB-record encoder: 'encodeSPV' writes just the payload,+ -- and the framework wraps the result in the 2-byte length+ -- prefix. For valueless parameters this means 'encodeSPV'+ -- is just @pure ()@.+ -- encodeSPV :: forall r s. ErrorContext r => a -> SPut s r- -- | Decode value from wire form++ -- | Decode value from wire form.+ -- The overall SVCB RData decoder gives each parameter decoder+ -- a view into a buffer of exactly the indicated length, and+ -- makes sure exactly that many bytes are consumed. The+ -- length argument is only needed in decoders that read+ -- variable-length fields that run to the end of the record.+ -- decodeSPV :: forall b -> b ~ a => Int -> SGet SVCParamValue -- | Override to get user-friendly output for runtime-added types.
src/Net/DNSBase/RData/TLSA.hs view
@@ -14,6 +14,7 @@ fingerprints. 'T_openpgpkey' (RFC 7929) carries an OpenPGP transferable public key. -}+{-# OPTIONS_GHC -Wno-duplicate-exports #-} {-# LANGUAGE MagicHash , RecordWildCards@@ -22,18 +23,16 @@ module Net.DNSBase.RData.TLSA ( -- * TLSA and SMIMEA- X_tlsa(.., T_TLSA, T_SMIMEA)- , type XtlsaConName, T_tlsa, T_smimea- -- *** 'T_TLSA' fields- , tlsaUsage- , tlsaSelector- , tlsaMtype- , tlsaAssocData- -- *** 'T_SMIMEA' fields- , smimeaUsage- , smimeaSelector- , smimeaMtype- , smimeaAssocData+ X_tlsa(.., T_TLSA, T_SMIMEA+ , tlsaUsage, tlsaSelector, tlsaMtype, tlsaAssocData+ , smimeaUsage, smimeaSelector, smimeaMtype, smimeaAssocData)+ , type XtlsaConName+ -- *** @T_TLSA@ record pattern synonym fields+ , T_tlsa+ , tlsaUsage, tlsaSelector, tlsaMtype, tlsaAssocData+ -- *** @T_SMIMEA@ record pattern synonym fields+ , T_smimea+ , smimeaUsage, smimeaSelector, smimeaMtype, smimeaAssocData -- * SSHFP , T_sshfp(..) -- * OPENPGPKEY@@ -64,8 +63,27 @@ :<>: TL.Text " is not a TLSA or SMIMEA RRTYPE" ) -- | X_tlsa specialised to @TLSA@ records.+--+-- Note that @T_tlsa@ is just a type alias! The 'T_TLSA' record pattern+-- synonym and its fields are bundled with the underlying 'X_tlsa'+-- data type. In many cases it is sufficient to import just+-- @X_tlsa(..)@, but if you also need the type alias, it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_tlsa(..), T_tlsa)+-- type T_tlsa = X_tlsa N_tlsa+ -- | X_tlsa specialised to @SMIMEA@ records.+--+-- Note that @T_smimea@ is just a type alias! The 'T_SMIMEA' record pattern+-- synonym and its fields are bundled with the underlying 'X_tlsa'+-- data type. In many cases it is sufficient to import just+-- @X_tlsa(..)@, but if you also need the type alias, it needs to be+-- imported separately:+--+-- > import Net.DNSBase (X_tlsa(..), T_smimea)+-- type T_smimea = X_tlsa N_smimea -- | Record pattern synonym viewing the shared 'X_tlsa' record as a@@ -101,13 +119,7 @@ -- ([RFC 6698 section 2.1](https://tools.ietf.org/html/rfc6698#section-2.1), -- DANE for TLS) and the @SMIMEA@ record -- ([RFC 8162 section 2](https://tools.ietf.org/html/rfc8162#section-2),--- DANE for S/MIME). The type parameter @n@ (either 'N_tlsa' or--- 'N_smimea') determines the RR type. Each has its own type synonym--- ('T_tlsa', 'T_smimea') and matching record pattern synonym--- ('T_TLSA', 'T_SMIMEA') with the corresponding field-name prefix--- (@tlsa@, @smimea@). The role of 'X_tlsa' is /nominal/: the wire--- format is shared but the two RR types bind to different protocols,--- so 'T_tlsa' and 'T_smimea' are not coercible.+-- DANE for S/MIME). -- -- > 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 -- > 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1@@ -119,6 +131,23 @@ -- > / / -- > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ --+-- The type parameter @n@ (either 'N_tlsa' or 'N_smimea')+-- determines the RR type. Each has its own type synonym+-- ('T_tlsa', 'T_smimea') and matching record pattern synonym+-- ('T_TLSA', 'T_SMIMEA') with the corresponding field-name prefix+-- (@tlsa@, @smimea@). The role of 'X_tlsa' is /nominal/: the+-- wire format is shared but the two RR types bind to different+-- protocols, so 'T_tlsa' and 'T_smimea' are not coercible.+--+-- Note that @T_tlsa@ and @T_smime@ are just type aliases! The+-- 'T_TLSA' and 'T_SMIMEA' record pattern synonyms and their+-- fields are bundled with the underlying 'X_tlsa' data type. In+-- many cases it is sufficient to import just @X_tlsa(..)@, but if+-- you also need the type aliases, they need to be imported+-- separately:+--+-- > import Net.DNSBase (X_tlsa(..), T_tlsa, T_smimea)+-- -- If a received message carries a payload shorter than 3 bytes the -- record is returned as an opaque RData of the corresponding -- RRTYPE with the truncated bytes as its value; DANE validators@@ -133,10 +162,10 @@ type X_tlsa :: Nat -> Type type role X_tlsa nominal data X_tlsa n = X_TLSA- { _tlsaUsage :: Word8 -- ^ Certificate Usage- , _tlsaSelector :: Word8 -- ^ Selector- , _tlsaMtype :: Word8 -- ^ Matching Type- , _tlsaAssocData :: ShortByteString -- ^ Certificate Association Data+ { x_tlsaUsage :: Word8 -- ^ Certificate Usage+ , x_tlsaSelector :: Word8 -- ^ Selector+ , x_tlsaMtype :: Word8 -- ^ Matching Type+ , x_tlsaAssocData :: ShortByteString -- ^ Certificate Association Data } deriving instance (KnownSymbol (XtlsaConName n)) => Eq (X_tlsa n) deriving instance (KnownSymbol (XtlsaConName n)) => Ord (X_tlsa n)@@ -144,19 +173,19 @@ instance (Nat16 n, KnownSymbol (XtlsaConName n)) => Show (X_tlsa n) where showsPrec p X_TLSA{..} = showsP p $ showString (symbolVal' (proxy# @(XtlsaConName n))) . showChar ' '- . shows' _tlsaUsage . showChar ' '- . shows' _tlsaSelector . showChar ' '- . shows' _tlsaMtype . showChar ' '- . showAd _tlsaAssocData+ . shows' x_tlsaUsage . showChar ' '+ . shows' x_tlsaSelector . showChar ' '+ . shows' x_tlsaMtype . showChar ' '+ . showAd x_tlsaAssocData where showAd = shows @Bytes16 . coerce instance (KnownSymbol (XtlsaConName n)) => Presentable (X_tlsa n) where present X_TLSA{..} =- present _tlsaUsage- . presentSp _tlsaSelector- . presentSp _tlsaMtype- . presentAd _tlsaAssocData+ present x_tlsaUsage+ . presentSp x_tlsaSelector+ . presentSp x_tlsaMtype+ . presentAd x_tlsaAssocData where presentAd = presentSp @Bytes16 . coerce @@ -164,15 +193,15 @@ rdType _ = RRTYPE $ natToWord16 n {-# INLINE rdType #-} rdEncode X_TLSA{..} = putSizedBuilder $- mbWord8 _tlsaUsage- <> mbWord8 _tlsaSelector- <> mbWord8 _tlsaMtype- <> mbShortByteString _tlsaAssocData+ mbWord8 x_tlsaUsage+ <> mbWord8 x_tlsaSelector+ <> mbWord8 x_tlsaMtype+ <> mbShortByteString x_tlsaAssocData rdDecode _ _ = const do- _tlsaUsage <- get8- _tlsaSelector <- get8- _tlsaMtype <- get8- _tlsaAssocData <- getShortByteString+ x_tlsaUsage <- get8+ x_tlsaSelector <- get8+ x_tlsaMtype <- get8+ x_tlsaAssocData <- getShortByteString pure $ RData (X_TLSA{..} :: X_tlsa n) -- | The @SSHFP@ resource record
tests/extensibility.hs view
@@ -91,13 +91,13 @@ Nothing -> assertFailure $ "expected T_svcb, got " ++ presentString rd mempty Just X_SVCB{..} ->- case spvLookup @SPV_EXT_port _svcParamValues of+ case spvLookup @SPV_EXT_port x_svcParamValues of Just (SPV_EXT_PORT 80) -> pure () Just (SPV_EXT_PORT p) -> assertFailure $ "expected port 80, got " ++ show p Nothing -> assertFailure $ "no SPV_EXT_port in "- ++ presentString _svcParamValues mempty+ ++ presentString x_svcParamValues mempty where -- | Wire form for a minimal SVCB record: priority 1, root target, -- one SvcParam (port = 80).