diff --git a/lib/dnsbox-base/src/common_types/binary.rs b/lib/dnsbox-base/src/common_types/binary.rs index 0d2f61a..84a62e3 100644 --- a/lib/dnsbox-base/src/common_types/binary.rs +++ b/lib/dnsbox-base/src/common_types/binary.rs @@ -186,3 +186,43 @@ impl DnsTextData for HexRemainingBlob { write!(f, "{}", HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.0)) } } + +/// No length byte (or restriction), just all data to end of record. uses +/// hex encoding for text representation, whitespace allowed. +/// +/// No following field allowed, i.e. last field in the record. +/// +/// Must contain at least one byte +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct HexRemainingBlobNotEmpty(Bytes); + +impl DnsPacketData for HexRemainingBlobNotEmpty { + fn deserialize(data: &mut Cursor) -> Result { + let data = remaining_bytes(data); + failure::ensure!(!data.is_empty(), "must not be empty"); + Ok(HexRemainingBlobNotEmpty(data)) + } + + fn serialize(&self, _context: &mut DnsPacketWriteContext, packet: &mut Vec) -> Result<()> { + failure::ensure!(!self.0.is_empty(), "must not be empty"); + packet.reserve(self.0.len()); + packet.put_slice(&self.0); + Ok(()) + } +} + +impl DnsTextData for HexRemainingBlobNotEmpty { + fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> crate::errors::Result { + skip_whitespace(data); + let result = HEXLOWER_PERMISSIVE_ALLOW_WS.decode(data.as_bytes()) + .with_context(|e| e.context(format!("invalid hex: {:?}", data)))?; + *data = ""; + failure::ensure!(!result.is_empty(), "must not be empty"); + Ok(HexRemainingBlobNotEmpty(result.into())) + } + + fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { + if self.0.is_empty() { return Err(fmt::Error); } + write!(f, "{}", HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.0)) + } +} diff --git a/lib/dnsbox-base/src/common_types/mod.rs b/lib/dnsbox-base/src/common_types/mod.rs index 8aef4f4..d83aa5a 100644 --- a/lib/dnsbox-base/src/common_types/mod.rs +++ b/lib/dnsbox-base/src/common_types/mod.rs @@ -10,7 +10,7 @@ mod sig; mod time; mod uri; -pub use self::binary::{HexShortBlob, Base64LongBlob, Base64RemainingBlob, HexRemainingBlob}; +pub use self::binary::{HexShortBlob, Base64LongBlob, Base64RemainingBlob, HexRemainingBlob, HexRemainingBlobNotEmpty}; pub use self::classes::Class; pub use self::eui::{EUI48Addr, EUI64Addr}; pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName}; diff --git a/lib/dnsbox-base/src/common_types/types.rs b/lib/dnsbox-base/src/common_types/types.rs index 005fe75..b15eb47 100644 --- a/lib/dnsbox-base/src/common_types/types.rs +++ b/lib/dnsbox-base/src/common_types/types.rs @@ -131,6 +131,8 @@ pub const CDNSKEY : Type = Type(KnownType::CDNSKEY as u16); pub const OPENPGPKEY : Type = Type(KnownType::OPENPGPKEY as u16); /// Child-To-Parent Synchronization pub const CSYNC : Type = Type(KnownType::CSYNC as u16); +/// message digest for DNS zone +pub const ZONEMD : Type = Type(KnownType::ZONEMD as u16); /// SPF pub const SPF : Type = Type(KnownType::SPF as u16); /// UINFO @@ -175,6 +177,8 @@ pub const CAA : Type = Type(KnownType::CAA as u16); pub const AVC : Type = Type(KnownType::AVC as u16); /// Digital Object Architecture pub const DOA : Type = Type(KnownType::DOA as u16); +/// Automatic Multicast Tunneling Relay +pub const AMTRELAY : Type = Type(KnownType::AMTRELAY as u16); /// DNSSEC Trust Authorities pub const TA : Type = Type(KnownType::TA as u16); /// DNSSEC Lookaside Validation @@ -309,6 +313,11 @@ pub enum KnownType { OPENPGPKEY = 0x003d, // RFC 7929 /// Child-To-Parent Synchronization CSYNC = 0x003e, // RFC 7477 + /// message digest for DNS zone + ZONEMD = 0x003f, // https://tools.ietf.org/html/draft-ietf-dnsop-dns-zone-digest-00 + + // Unassigned: 0x0040..0x0062 + /// SPF SPF = 0x0063, // RFC 7208 /// UINFO @@ -331,7 +340,11 @@ pub enum KnownType { EUI48 = 0x006c, // RFC 7043 /// an EUI-64 address EUI64 = 0x006d, // RFC 7043 + + // unassigned: 0x006e..0x007f + // 0x0080..0x00ff: meta and qtypes + /// URI URI = 0x0100, // RFC 7553 /// Certification Authority Restriction @@ -340,12 +353,23 @@ pub enum KnownType { AVC = 0x0102, // Wolfgang Riedel /// Digital Object Architecture DOA = 0x0103, // http://www.iana.org/go/draft-durand-doa-over-dns + /// Automatic Multicast Tunneling Relay + AMTRELAY = 0x0104, // http://www.iana.org/go/draft-ietf-mboned-driad-amt-discovery + + // Unassigned: 0x0105..0x7fff + /// DNSSEC Trust Authorities TA = 0x8000, // /// DNSSEC Lookaside Validation DLV = 0x8001, // RFC 4431 - /// powerdns feature: authoritate should resolve to A and AAAA + + // Unassigned: 0x8002..0xfeff + // Private use: 0xff00..0xfffe + + /// powerdns feature: authoritative should resolve to A and AAAA ALIAS = 0xff79, // powerdns + + // Reserved: 0xffff } /// known QTYPEs @@ -353,6 +377,10 @@ pub enum KnownType { #[repr(u16)] #[allow(non_camel_case_types)] pub enum KnownQType { + // Unassigned 0x0080..0x00f8 + + // 0x00f9..0x00fa: meta type + /// incremental transfer IXFR = 0x00fb, // RFC 1995 /// transfer of an entire zone @@ -372,10 +400,15 @@ pub enum KnownQType { pub enum KnownMetaType { /// OPT OPT = 0x0029, // RFC 6891 + + // Unassigned 0x0080..0x00f8 + /// Transaction Key TKEY = 0x00f9, // RFC 2930 /// Transaction Signature TSIG = 0x00fa, // RFC 2845 + + // 0x00fb..0x00ff: qtype } /// DNS (RR)TYPE @@ -679,6 +712,8 @@ fn check_types() { check_type!(CDNSKEY , 60); check_type!(OPENPGPKEY, 61); check_type!(CSYNC , 62); + check_type!(ZONEMD , 63); + // Unassigned: 64-98 check_type!(SPF , 99); check_type!(UINFO , 100); check_type!(UID , 101); @@ -690,6 +725,7 @@ fn check_types() { check_type!(LP , 107); check_type!(EUI48 , 108); check_type!(EUI64 , 109); + // Unassigned: 110-248 check_type!(TKEY , 249); check_type!(TSIG , 250); check_type!(IXFR , 251); @@ -701,7 +737,12 @@ fn check_types() { check_type!(CAA , 257); check_type!(AVC , 258); check_type!(DOA , 259); + check_type!(AMTRELAY , 260); + // Unassigned: 261-32767 check_type!(TA , 32768); check_type!(DLV , 32769); + // Unassigned: 32770-65279 + // Private use: 65280-65534 check_type!(ALIAS , 65401); + // Reserved: 65535 } diff --git a/lib/dnsbox-base/src/records/registry.rs b/lib/dnsbox-base/src/records/registry.rs index 2515e94..8898ed5 100644 --- a/lib/dnsbox-base/src/records/registry.rs +++ b/lib/dnsbox-base/src/records/registry.rs @@ -174,6 +174,7 @@ impl Registry { r.register_known::(); r.register_known::(); r.register_unknown("CSYNC" , types::CSYNC); + r.register_unknown("ZONEMD" , types::ZONEMD); r.register_known::(); r.register_unknown("UINFO" , types::UINFO); r.register_unknown("UID" , types::UID); @@ -196,6 +197,7 @@ impl Registry { r.register_known::(); r.register_unknown("AVC" , types::AVC); r.register_unknown("DOA" , types::DOA); + r.register_unknown("AMTRELAY" , types::AMTRELAY); r.register_unknown("TA" , types::TA); r.register_known::(); r.register_known::(); diff --git a/lib/dnsbox-base/src/records/structs.rs b/lib/dnsbox-base/src/records/structs.rs index c9372bb..5147cea 100644 --- a/lib/dnsbox-base/src/records/structs.rs +++ b/lib/dnsbox-base/src/records/structs.rs @@ -449,6 +449,15 @@ pub struct OPENPGPKEY { // #[RRClass(?)] // pub struct CSYNC; +// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)] +// #[RRClass(ANY)] +// pub struct ZONEMD { +// pub serial: u32, +// pub digest_type: u8, +// pub reserved: u8, +// pub digest: HexRemainingBlobNotEmpty, +// } + #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)] // #[RRClass(?)] pub struct SPF { @@ -543,6 +552,8 @@ pub struct CAA { // pub struct AVC; // pub struct DOA; +// pub struct AMTRELAY; +// pub struct TA; #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)] #[RRClass(ANY)]