From f10f5d339affa5fb2a1772efc66ecfda87629fc0 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Wed, 9 Sep 2020 13:10:04 +0200 Subject: [PATCH 1/5] Introduce OctetsFrom and OctetsInto. --- src/base/charstr.rs | 18 +++++++- src/base/message.rs | 16 ++++++- src/base/name/dname.rs | 16 ++++++- src/base/name/relative.rs | 19 +++++++- src/base/octets.rs | 91 +++++++++++++++++++++++++++++++++----- src/base/opt/mod.rs | 29 +++++++++++- src/base/question.rs | 18 +++++++- src/base/rdata.rs | 19 +++++++- src/base/record.rs | 24 +++++++++- src/rdata/macros.rs | 90 ++++++++++++++++++++++++++++++++++++++ src/rdata/rfc1035.rs | 92 ++++++++++++++++++++++++++++++++++++++- src/rdata/rfc2782.rs | 15 ++++++- src/rdata/rfc2845.rs | 23 +++++++++- src/rdata/rfc3596.rs | 11 ++++- src/rdata/rfc4034.rs | 92 ++++++++++++++++++++++++++++++++++++++- src/rdata/rfc5155.rs | 32 +++++++++++++- src/rdata/rfc6672.rs | 5 ++- src/rdata/rfc7344.rs | 29 +++++++++++- src/resolv/stub/mod.rs | 2 +- 19 files changed, 608 insertions(+), 33 deletions(-) diff --git a/src/base/charstr.rs b/src/base/charstr.rs index 8ee83e010..0fefeaf9b 100644 --- a/src/base/charstr.rs +++ b/src/base/charstr.rs @@ -33,8 +33,8 @@ use core::{cmp, fmt, hash, ops, str}; }; use super::cmp::CanonicalOrd; use super::octets::{ - Compose, EmptyBuilder, FromBuilder, IntoBuilder, OctetsBuilder, OctetsRef, - Parse, ParseError, Parser, ShortBuf + Compose, EmptyBuilder, FromBuilder, IntoBuilder, OctetsBuilder, OctetsFrom, + OctetsRef, Parse, ParseError, Parser, ShortBuf }; use super::str::{BadSymbol, Symbol, SymbolError}; @@ -163,6 +163,20 @@ impl CharStr<[u8]> { } +//--- OctetsFrom + +impl OctetsFrom> for CharStr +where Octets: OctetsFrom { + fn octets_from(source: CharStr) -> Result { + Octets::octets_from(source.0).map(|octets| { + unsafe { + Self::from_octets_unchecked(octets) + } + }) + } +} + + //--- FromStr impl str::FromStr for CharStr diff --git a/src/base/message.rs b/src/base/message.rs index 121bea7e1..dbb5e1252 100644 --- a/src/base/message.rs +++ b/src/base/message.rs @@ -17,7 +17,7 @@ use super::iana::{Class, Rcode, Rtype}; use super::message_builder::{AdditionalBuilder, AnswerBuilder}; use super::name::ParsedDname; use super::octets::{ - OctetsBuilder, OctetsRef, Parse, ParseError, Parser, ShortBuf + OctetsBuilder, OctetsFrom, OctetsRef, Parse, ParseError, Parser, ShortBuf }; use super::opt::{Opt, OptRecord}; use super::question::Question; @@ -597,6 +597,20 @@ impl> AsRef<[u8]> for Message { } +//--- OctetsFrom + +impl OctetsFrom> for Message +where Octets: OctetsFrom { + fn octets_from(source: Message) -> Result { + Octets::octets_from(source.octets).map(|octets| { + unsafe { + Self::from_octets_unchecked(octets) + } + }) + } +} + + //--- IntoIterator impl<'a, Octets> IntoIterator for &'a Message diff --git a/src/base/name/dname.rs b/src/base/name/dname.rs index a682153b4..eb3c09ffc 100644 --- a/src/base/name/dname.rs +++ b/src/base/name/dname.rs @@ -12,7 +12,7 @@ use core::str::FromStr; use super::super::cmp::CanonicalOrd; use super::super::octets::{ Compose, EmptyBuilder, FormError, FromBuilder, OctetsBuilder, OctetsExt, - OctetsRef, Parse, Parser, ParseError, ShortBuf + OctetsFrom, OctetsRef, Parse, Parser, ParseError, ShortBuf }; use super::builder::{DnameBuilder, FromStrError}; use super::label::{Label, LabelTypeError, SplitLabelError}; @@ -588,6 +588,20 @@ impl + ?Sized, T: ?Sized> AsRef for Dname { } +//--- OctetsFrom + +impl OctetsFrom> for Dname +where Octets: OctetsFrom { + fn octets_from(source: Dname) -> Result { + Octets::octets_from(source.0).map(|octets| { + unsafe { + Self::from_octets_unchecked(octets) + } + }) + } +} + + //--- FromStr impl FromStr for Dname diff --git a/src/base/name/relative.rs b/src/base/name/relative.rs index d3ad65a94..5f6f29d30 100644 --- a/src/base/name/relative.rs +++ b/src/base/name/relative.rs @@ -7,8 +7,8 @@ use core::cmp::Ordering; #[cfg(feature = "std")] use std::vec::Vec; #[cfg(feature = "bytes")] use bytes::Bytes; use super::super::octets::{ - Compose, IntoBuilder, OctetsBuilder, OctetsExt, OctetsRef, ParseError, - ShortBuf + Compose, IntoBuilder, OctetsBuilder, OctetsExt, OctetsFrom, OctetsRef, + ParseError, ShortBuf }; use super::builder::{DnameBuilder, PushError}; use super::chain::{Chain, LongChainError}; @@ -569,6 +569,21 @@ impl + ?Sized, T: ?Sized> AsRef for RelativeDname { } +//--- OctetsFrom + +impl +OctetsFrom> for RelativeDname +where Octets: OctetsFrom { + fn octets_from(source: RelativeDname) -> Result { + Octets::octets_from(source.0).map(|octets| { + unsafe { + Self::from_octets_unchecked(octets) + } + }) + } +} + + //--- ToLabelIter and ToRelativeDname impl<'a, Octets> ToLabelIter<'a> for RelativeDname diff --git a/src/base/octets.rs b/src/base/octets.rs index b73c24fbb..bd7add2ec 100644 --- a/src/base/octets.rs +++ b/src/base/octets.rs @@ -313,6 +313,86 @@ impl<'a, A: Array> OctetsRef for &'a SmallVec { } +//------------ OctetsFrom ---------------------------------------------------- + +/// Convert a type from one octets type to another. +/// +/// This trait allows creating a value of a type that is generic over an +/// octets sequence from an identical value using a different type of octets +/// sequence. +/// +/// This is different from just `From` in that the conversion may fail if the +/// source sequence is longer than the space available for the target type. +pub trait OctetsFrom: Sized { + /// Performs the conversion. + fn octets_from(source: Source) -> Result; +} + + +impl<'a, Source: AsRef<[u8]> + 'a> OctetsFrom<&'a Source> for &'a [u8] { + fn octets_from(source: &'a Source) -> Result { + Ok(source.as_ref()) + } +} + +#[cfg(feature = "std")] +impl OctetsFrom for Vec +where Self: From { + fn octets_from(source: Source) -> Result { + Ok(From::from(source)) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for Bytes +where Self: From { + fn octets_from(source: Source) -> Result { + Ok(From::from(source)) + } +} + +#[cfg(feature = "bytes")] +impl OctetsFrom for BytesMut +where Self: From { + fn octets_from(source: Source) -> Result { + Ok(From::from(source)) + } +} + +#[cfg(features = "smallvec")] +impl OctetsFrom for SmallVec +where Source: AsRef, A: Array { + fn octets_from(source: Source) -> Result { + Ok(smallvec::ToSmallVec::to_smallvec(source.as_ref())) + } +} + + +//------------ OctetsInto ---------------------------------------------------- + +/// Convert a type from one octets type to another. +/// +/// This trait allows trading in a value of a type that is generic over an +/// octets sequence for an identical value using a different type of octets +/// sequence. +/// +/// This is different from just `Into` in that the conversion may fail if the +/// source sequence is longer than the space available for the target type. +/// +/// This trait has a blanket implementation for all pairs of types where +/// `OctetsFrom` has been implemented. +pub trait OctetsInto { + /// Performs the conversion. + fn octets_into(self) -> Result; +} + +impl> OctetsInto for Source { + fn octets_into(self) -> Result { + Target::octets_from(self) + } +} + + //------------ OctetsBuilder ------------------------------------------------- /// A buffer to construct an octet sequence. @@ -557,11 +637,6 @@ impl> EmptyBuilder for SmallVec { /// An octets type that can be converted into an octets builder. pub trait IntoBuilder { /// The type of octets builder this octets type can be converted into. - /// - /// If `Builder` implements [`IntoOctets`], the `Octets` associated - /// type of that trait must be `Self`. - /// - /// [`IntoOctets`]: trait.IntoOctets.html type Builder: OctetsBuilder; /// Converts an octets value into an octets builder. @@ -620,12 +695,6 @@ impl> IntoBuilder for SmallVec { //------------ FromBuilder --------------------------------------------------- /// An octets type that can be created from an octets builder. -/// -/// This trait is a mirror of [`IntoOctets`] and only exists because otherwise -/// trait bounds become ridiculously complex. The implementations of the two -/// traits must behave identically. -/// -/// [`IntoOctets`]: trait.IntoOctets.html pub trait FromBuilder: AsRef<[u8]> + Sized { /// The type of builder this octets type can be created from. type Builder: OctetsBuilder; diff --git a/src/base/opt/mod.rs b/src/base/opt/mod.rs index 9bc39f7cf..25818a251 100644 --- a/src/base/opt/mod.rs +++ b/src/base/opt/mod.rs @@ -47,7 +47,8 @@ use super::iana::{OptionCode, OptRcode, Rtype}; use super::header::Header; use super::name::ToDname; use super::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, ParseError, Parser, ShortBuf + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, ParseError, Parser, + ShortBuf }; use super::rdata::RtypeRecordData; use super::record::Record; @@ -104,6 +105,16 @@ impl> Opt { } +//--- OctetsFrom + +impl OctetsFrom> for Opt +where Octets: OctetsFrom { + fn octets_from(source: Opt) -> Result { + Octets::octets_from(source.octets).map(|octets| Opt { octets }) + } +} + + //--- PartialEq and Eq impl PartialEq> for Opt @@ -410,6 +421,22 @@ impl From>> for OptRecord { } +//--- OctetsFrom + +impl OctetsFrom> for OptRecord +where Octets: OctetsFrom { + fn octets_from(source: OptRecord) -> Result { + Ok(OptRecord { + udp_payload_size: source.udp_payload_size, + ext_rcode: source.ext_rcode, + version: source.version, + flags: source.flags, + data: Opt::octets_from(source.data)?, + }) + } +} + + //--- Deref and AsRef impl ops::Deref for OptRecord { diff --git a/src/base/question.rs b/src/base/question.rs index 102b663ab..3c4f9b517 100644 --- a/src/base/question.rs +++ b/src/base/question.rs @@ -10,7 +10,8 @@ use super::cmp::CanonicalOrd; use super::iana::{Class, Rtype}; use super::name::{ParsedDname, ToDname}; use super::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, Parser, ParseError, ShortBuf + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, Parser, ParseError, + ShortBuf }; @@ -42,7 +43,7 @@ pub struct Question { /// # Creation and Conversion /// -impl Question { +impl Question { /// Creates a new question from its three componets. pub fn new(qname: N, qtype: Rtype, qclass: Class) -> Self { Question { qname, qtype, qclass } @@ -95,6 +96,19 @@ impl From<(N, Rtype)> for Question { } +//--- OctetsFrom + +impl OctetsFrom> for Question +where Name: OctetsFrom { + fn octets_from(source: Question) -> Result { + Ok(Question::new( + Name::octets_from(source.qname)?, + source.qtype, source.qclass + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Question diff --git a/src/base/rdata.rs b/src/base/rdata.rs index f7eeb422f..35ab0b7a2 100644 --- a/src/base/rdata.rs +++ b/src/base/rdata.rs @@ -31,7 +31,8 @@ use core::cmp::Ordering; use super::cmp::CanonicalOrd; use super::iana::Rtype; use super::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, ParseError, Parser, ShortBuf + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, ParseError, Parser, + ShortBuf }; @@ -220,6 +221,22 @@ impl UnknownRecordData { } +//--- OctetsFrom + +impl +OctetsFrom> for UnknownRecordData +where Octets: OctetsFrom { + fn octets_from( + source: UnknownRecordData + ) -> Result { + Ok(UnknownRecordData { + rtype: source.rtype, + data: Octets::octets_from(source.data)? + }) + } +} + + //--- PartialEq and Eq impl PartialEq> diff --git a/src/base/record.rs b/src/base/record.rs index 47b7c846d..a97740e17 100644 --- a/src/base/record.rs +++ b/src/base/record.rs @@ -21,7 +21,8 @@ use super::cmp::CanonicalOrd; use super::iana::{Class, Rtype}; use super::name::{ParsedDname, ToDname}; use super::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, Parser, ParseError, ShortBuf + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, Parser, ParseError, + ShortBuf }; use super::rdata::{RecordData, ParseRecordData}; @@ -182,6 +183,27 @@ impl From<(N, u32, D)> for Record { } +//--- OctetsFrom +// +// XXX We don’t have blanket FromOctets for a type T into itself, so this may +// not always work as expected. Not sure what we can do about it? + +impl +OctetsFrom> for Record +where Name: OctetsFrom, Data: OctetsFrom { + fn octets_from( + source: Record + ) -> Result { + Ok(Record { + owner: Name::octets_from(source.owner)?, + class: source.class, + ttl: source.ttl, + data: Data::octets_from(source.data)? + }) + } +} + + //--- PartialEq and Eq impl PartialEq> for Record diff --git a/src/rdata/macros.rs b/src/rdata/macros.rs index b711bacb3..a8ca7b69d 100644 --- a/src/rdata/macros.rs +++ b/src/rdata/macros.rs @@ -60,6 +60,39 @@ macro_rules! rdata_types { } + //--- OctetsFrom + + impl + $crate::base::octets::OctetsFrom< + MasterRecordData + > + for MasterRecordData + where + Octets: $crate::base::octets::OctetsFrom, + Name: $crate::base::octets::OctetsFrom + { + fn octets_from( + source: MasterRecordData + ) -> Result { + match source { + $( $( $( + MasterRecordData::$mtype(inner) => { + $mtype::octets_from(inner).map( + MasterRecordData::$mtype + ) + } + )* )* )* + MasterRecordData::Other(inner) => { + $crate::base::rdata:: + UnknownRecordData::octets_from(inner).map( + MasterRecordData::Other + ) + } + } + } + } + + //--- From $( $( $( @@ -449,6 +482,51 @@ macro_rules! rdata_types { } + //--- OctetsFrom + + impl + $crate::base::octets::OctetsFrom< + AllRecordData + > + for AllRecordData + where + Octets: $crate::base::octets::OctetsFrom, + Name: $crate::base::octets::OctetsFrom + { + fn octets_from( + source: AllRecordData + ) -> Result { + match source { + $( $( $( + AllRecordData::$mtype(inner) => { + $mtype::octets_from(inner).map( + AllRecordData::$mtype + ) + } + )* )* )* + $( $( $( + AllRecordData::$ptype(inner) => { + $ptype::octets_from(inner).map( + AllRecordData::$ptype + ) + } + )* )* )* + AllRecordData::Opt(inner) => { + $crate::base::opt::Opt::octets_from(inner).map( + AllRecordData::Opt + ) + } + AllRecordData::Other(inner) => { + $crate::base::rdata:: + UnknownRecordData::octets_from(inner).map( + AllRecordData::Other + ) + } + } + } + } + + //--- PartialEq and Eq impl PartialEq> @@ -745,6 +823,18 @@ macro_rules! dname_type { } + //--- OctetsFrom + + impl OctetsFrom<$target> for $target + where Name: OctetsFrom { + fn octets_from(source: $target) -> Result { + Name::octets_from(source.$field).map(|name| { + Self::new(name) + }) + } + } + + //--- PartialEq and Eq impl PartialEq<$target> for $target diff --git a/src/rdata/rfc1035.rs b/src/rdata/rfc1035.rs index 810409d59..a5767521e 100644 --- a/src/rdata/rfc1035.rs +++ b/src/rdata/rfc1035.rs @@ -16,8 +16,8 @@ use crate::base::str::Symbol; use crate::base::name::{ParsedDname, ToDname}; use crate::base::net::Ipv4Addr; use crate::base::octets::{ - Compose, EmptyBuilder, FromBuilder, OctetsBuilder, OctetsRef, Parse, - ParseError, Parser, ShortBuf + Compose, EmptyBuilder, FromBuilder, OctetsBuilder, OctetsFrom, OctetsRef, + Parse, ParseError, Parser, ShortBuf }; use crate::base::rdata::RtypeRecordData; use crate::base::serial::Serial; @@ -55,6 +55,15 @@ impl A { } +//--- OctetsFrom + +impl OctetsFrom for A { + fn octets_from(source: A) -> Result { + Ok(source) + } +} + + //--- From and FromStr impl From for A { @@ -211,6 +220,19 @@ impl Hinfo { } +//--- OctetsFrom + +impl OctetsFrom> for Hinfo +where Octets: OctetsFrom { + fn octets_from(source: Hinfo) -> Result { + Ok(Hinfo::new( + CharStr::octets_from(source.cpu)?, + CharStr::octets_from(source.os)? + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Hinfo @@ -434,6 +456,19 @@ impl Minfo { } +//--- OctetsFrom + +impl OctetsFrom> for Minfo +where Name: OctetsFrom { + fn octets_from(source: Minfo) -> Result { + Ok(Minfo::new( + Name::octets_from(source.rmailbx)?, + Name::octets_from(source.emailbx)? + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Minfo @@ -595,6 +630,19 @@ impl Mx { } +//--- OctetsFrom + +impl OctetsFrom> for Mx +where Name: OctetsFrom { + fn octets_from(source: Mx) -> Result { + Ok(Mx::new( + source.preference, + Name::octets_from(source.exchange)? + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Mx @@ -759,6 +807,18 @@ impl From for Null { } +//--- OctetsFrom + +impl OctetsFrom> for Null +where Octets: OctetsFrom { + fn octets_from(source: Null) -> Result { + Octets::octets_from(source.data).map(|octets| { + Self::new(octets) + }) + } +} + + //--- PartialEq and Eq impl PartialEq> for Null @@ -957,6 +1017,24 @@ impl Soa { } +//--- OctetsFrom + +impl OctetsFrom> for Soa +where Name: OctetsFrom { + fn octets_from(source: Soa) -> Result { + Ok(Soa::new( + Name::octets_from(source.mname)?, + Name::octets_from(source.rname)?, + source.serial, + source.refresh, + source.retry, + source.expire, + source.minimum + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Soa @@ -1223,6 +1301,16 @@ impl> Txt { } +//--- OctetsFrom + +impl OctetsFrom> for Txt +where Octets: OctetsFrom { + fn octets_from(source: Txt) -> Result { + Octets::octets_from(source.0).map(Self) + } +} + + //--- IntoIterator impl<'a, Octets: AsRef<[u8]>> IntoIterator for &'a Txt { diff --git a/src/rdata/rfc2782.rs b/src/rdata/rfc2782.rs index 30163b165..6784f4b7b 100644 --- a/src/rdata/rfc2782.rs +++ b/src/rdata/rfc2782.rs @@ -10,7 +10,7 @@ use crate::base::cmp::CanonicalOrd; use crate::base::iana::Rtype; use crate::base::name::{ParsedDname, ToDname}; use crate::base::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, Parser, ParseError, + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, Parser, ParseError, ShortBuf }; use crate::base::rdata::RtypeRecordData; @@ -58,6 +58,19 @@ impl Srv { } +//--- OctetsFrom + +impl OctetsFrom> for Srv +where Name: OctetsFrom { + fn octets_from(source: Srv) -> Result { + Ok(Srv::new( + source.priority, source.weight, source.port, + Name::octets_from(source.target)? + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Srv diff --git a/src/rdata/rfc2845.rs b/src/rdata/rfc2845.rs index 16acf0af9..5088fa8a2 100644 --- a/src/rdata/rfc2845.rs +++ b/src/rdata/rfc2845.rs @@ -11,7 +11,7 @@ use crate::base::cmp::CanonicalOrd; use crate::base::iana::{Rtype, TsigRcode}; use crate::base::name::{ParsedDname, ToDname}; use crate::base::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, ParseError, Parser, + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, ParseError, Parser, ShortBuf }; use crate::base::rdata::RtypeRecordData; @@ -165,6 +165,27 @@ impl Tsig { } } + +//--- OctetsFrom + +impl + OctetsFrom> for Tsig +where Octets: OctetsFrom, Name: OctetsFrom { + fn octets_from( + source: Tsig + ) -> Result { + Ok(Tsig::new( + Name::octets_from(source.algorithm)?, + source.time_signed, + source.fudge, + Octets::octets_from(source.mac)?, + source.original_id, + source.error, + Octets::octets_from(source.other)?, + )) + } +} + //--- PartialEq and Eq impl PartialEq> for Tsig diff --git a/src/rdata/rfc3596.rs b/src/rdata/rfc3596.rs index 088355042..57d23fce2 100644 --- a/src/rdata/rfc3596.rs +++ b/src/rdata/rfc3596.rs @@ -10,7 +10,7 @@ use crate::base::cmp::CanonicalOrd; use crate::base::iana::Rtype; use crate::base::net::Ipv6Addr; use crate::base::octets::{ - Compose, OctetsBuilder, Parse, ParseError, Parser, ShortBuf + Compose, OctetsBuilder, OctetsFrom, Parse, ParseError, Parser, ShortBuf }; use crate::base::rdata::RtypeRecordData; #[cfg(feature="master")] use crate::master::scan::{ @@ -59,6 +59,15 @@ impl core::str::FromStr for Aaaa { } +//--- OctetsFrom + +impl OctetsFrom for Aaaa { + fn octets_from(source: Aaaa) -> Result { + Ok(source) + } +} + + //--- CanonicalOrd impl CanonicalOrd for Aaaa { diff --git a/src/rdata/rfc4034.rs b/src/rdata/rfc4034.rs index 38c9d6c4a..1728e61a4 100644 --- a/src/rdata/rfc4034.rs +++ b/src/rdata/rfc4034.rs @@ -13,8 +13,8 @@ use crate::base::cmp::CanonicalOrd; use crate::base::iana::{DigestAlg, Rtype, SecAlg}; use crate::base::name::{ParsedDname, ToDname}; use crate::base::octets::{ - Compose, EmptyBuilder, FormError, FromBuilder, OctetsBuilder, OctetsRef, - Parse, ParseError, Parser, ShortBuf + Compose, EmptyBuilder, FormError, FromBuilder, OctetsBuilder, OctetsFrom, + OctetsRef, Parse, ParseError, Parser, ShortBuf }; use crate::base::rdata::{RtypeRecordData}; use crate::base::serial::Serial; @@ -157,6 +157,19 @@ impl Dnskey { } +//--- OctetsFrom + +impl OctetsFrom> for Dnskey +where Octets: OctetsFrom { + fn octets_from(source: Dnskey) -> Result { + Ok(Dnskey::new( + source.flags, source.protocol, source.algorithm, + Octets::octets_from(source.public_key)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Dnskey @@ -355,6 +368,22 @@ impl ProtoRrsig { } } + +//--- OctetsFrom + +impl OctetsFrom> for ProtoRrsig +where Name: OctetsFrom { + fn octets_from(source: ProtoRrsig) -> Result { + Ok(ProtoRrsig::new( + source.type_covered, source.algorithm, source.labels, + source.original_ttl, source.expiration, source.inception, + source.key_tag, + Name::octets_from(source.signer_name)? + )) + } +} + + //--- Compose impl Compose for ProtoRrsig { @@ -476,6 +505,25 @@ impl Rrsig { } +//--- OctetsFrom + +impl + OctetsFrom> for Rrsig +where Octets: OctetsFrom, Name: OctetsFrom { + fn octets_from( + source: Rrsig + ) -> Result { + Ok(Rrsig::new( + source.type_covered, source.algorithm, source.labels, + source.original_ttl, source.expiration, source.inception, + source.key_tag, + Name::octets_from(source.signer_name)?, + Octets::octets_from(source.signature)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Rrsig @@ -759,6 +807,22 @@ impl Nsec { } +//--- OctetsFrom + +impl + OctetsFrom> for Nsec +where Octets: OctetsFrom, Name: OctetsFrom { + fn octets_from( + source: Nsec + ) -> Result { + Ok(Nsec::new( + Name::octets_from(source.next_name)?, + RtypeBitmap::octets_from(source.types)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Nsec @@ -943,6 +1007,19 @@ impl Ds { } +//--- OctetsFrom + +impl OctetsFrom> for Ds +where Octets: OctetsFrom { + fn octets_from(source: Ds) -> Result { + Ok(Ds::new( + source.key_tag, source.algorithm, source.digest_type, + Octets::octets_from(source.digest)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Ds @@ -1188,6 +1265,17 @@ impl> AsRef for RtypeBitmap { } +//--- OctetsFrom + +impl + OctetsFrom> for RtypeBitmap +where Octets: OctetsFrom { + fn octets_from(source: RtypeBitmap) -> Result { + Octets::octets_from(source.0).map(RtypeBitmap) + } +} + + //--- PartialEq and Eq impl PartialEq> for RtypeBitmap diff --git a/src/rdata/rfc5155.rs b/src/rdata/rfc5155.rs index 1d98402d3..74bbbeb95 100644 --- a/src/rdata/rfc5155.rs +++ b/src/rdata/rfc5155.rs @@ -11,7 +11,8 @@ use crate::base::charstr::CharStr; use crate::base::cmp::CanonicalOrd; use crate::base::iana::{Nsec3HashAlg, Rtype}; use crate::base::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, ParseError, Parser, ShortBuf + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, ParseError, Parser, + ShortBuf }; use crate::base::rdata::RtypeRecordData; #[cfg(feature="master")] use crate::master::scan::{ @@ -75,6 +76,21 @@ impl Nsec3 { } +//--- OctetsFrom + +impl OctetsFrom> for Nsec3 +where Octets: OctetsFrom { + fn octets_from(source: Nsec3) -> Result { + Ok(Nsec3::new( + source.hash_algorithm, source.flags, source.iterations, + CharStr::octets_from(source.salt)?, + CharStr::octets_from(source.next_owner)?, + RtypeBitmap::octets_from(source.types)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Nsec3 @@ -321,6 +337,20 @@ impl Nsec3param { } +//--- OctetsFrom + +impl + OctetsFrom> for Nsec3param +where Octets: OctetsFrom { + fn octets_from(source: Nsec3param) -> Result { + Ok(Nsec3param::new( + source.hash_algorithm, source.flags, source.iterations, + CharStr::octets_from(source.salt)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Nsec3param diff --git a/src/rdata/rfc6672.rs b/src/rdata/rfc6672.rs index 75bfe697f..962e751d7 100644 --- a/src/rdata/rfc6672.rs +++ b/src/rdata/rfc6672.rs @@ -1,7 +1,10 @@ use crate::base::cmp::CanonicalOrd; use crate::base::iana::Rtype; use crate::base::name::{ParsedDname, ToDname}; -use crate::base::octets::{Compose, OctetsBuilder, OctetsRef, Parse, ParseError, Parser, ShortBuf}; +use crate::base::octets::{ + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, ParseError, Parser, + ShortBuf +}; use crate::base::rdata::RtypeRecordData; #[cfg(feature = "master")] use crate::master::scan::{CharSource, Scan, ScanError, Scanner}; diff --git a/src/rdata/rfc7344.rs b/src/rdata/rfc7344.rs index 4cbb44771..8f295142e 100644 --- a/src/rdata/rfc7344.rs +++ b/src/rdata/rfc7344.rs @@ -7,7 +7,8 @@ use core::cmp::Ordering; use crate::base::cmp::CanonicalOrd; use crate::base::iana::{DigestAlg, Rtype, SecAlg}; use crate::base::octets::{ - Compose, OctetsBuilder, OctetsRef, Parse, ParseError, Parser, ShortBuf + Compose, OctetsBuilder, OctetsFrom, OctetsRef, Parse, ParseError, Parser, + ShortBuf }; use crate::base::rdata::RtypeRecordData; #[cfg(feature="master")] use crate::master::scan::{ @@ -59,6 +60,19 @@ impl Cdnskey { } +//--- OctetsFrom + +impl OctetsFrom> for Cdnskey +where Octets: OctetsFrom { + fn octets_from(source: Cdnskey) -> Result { + Ok(Cdnskey::new( + source.flags, source.protocol, source.algorithm, + Octets::octets_from(source.public_key)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Cdnskey @@ -248,6 +262,19 @@ impl Cds { } +//--- OctetsFrom + +impl OctetsFrom> for Cds +where Octets: OctetsFrom { + fn octets_from(source: Cds) -> Result { + Ok(Cds::new( + source.key_tag, source.algorithm, source.digest_type, + Octets::octets_from(source.digest)?, + )) + } +} + + //--- PartialEq and Eq impl PartialEq> for Cds diff --git a/src/resolv/stub/mod.rs b/src/resolv/stub/mod.rs index 390bbe363..9ec5437d3 100644 --- a/src/resolv/stub/mod.rs +++ b/src/resolv/stub/mod.rs @@ -56,7 +56,7 @@ const RETRY_RANDOM_PORT: usize = 10; /// A DNS stub resolver. /// /// This type collects all information making it possible to start DNS -/// queries. You can create a new resoler using the system’s configuration +/// queries. You can create a new resolver using the system’s configuration /// using the [`new()`] associate function or using your own configuration /// with [`from_conf()`]. /// From 186996b0978525039821d2f69aa77519ae1cb2e2 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Thu, 10 Sep 2020 17:08:09 +0200 Subject: [PATCH 2/5] Add a few tests. --- src/base/record.rs | 25 +++++++++++++++++++++++++ src/rdata/rfc1035.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/src/base/record.rs b/src/base/record.rs index a97740e17..05c83fbdf 100644 --- a/src/base/record.rs +++ b/src/base/record.rs @@ -905,3 +905,28 @@ impl From for RecordParseError { } } + +//============ Testing ====================================================== + +#[cfg(test)] +mod test { + + #[test] + #[cfg(features = "bytes")] + fn ds_octets_into() { + use crate::name::Dname; + use crate::octets::OctetsInto; + use crate::base::iana::{DigestAlg, Rtype, SecAlg}; + use crate::rdata::Ds; + + let ds: Record, Ds<&[u8]>> = Record::new( + "a.example".parse().unwrap(), Class::In, 86400, + Ds::new(12, SecAlg::RsaSha256, b"something") + ); + let ds_bytes: Record, Ds> + = ds.octets_into().unwrap(); + assert_eq!(ds.owner(), ds_bytes.owner()); + asswer_eq!(ds.data().digest(), ds_bytes.data().digest()); + } +} + diff --git a/src/rdata/rfc1035.rs b/src/rdata/rfc1035.rs index a5767521e..60f0f76fe 100644 --- a/src/rdata/rfc1035.rs +++ b/src/rdata/rfc1035.rs @@ -1552,6 +1552,7 @@ impl Default for TxtBuilder { } } + //============ Testing ====================================================== #[cfg(test)] @@ -1560,6 +1561,36 @@ mod test { use std::vec::Vec; use super::*; + #[test] + #[cfg(features = "bytes")] + fn hinfo_octets_into() { + use crate::octets::OctetsInto; + + let hinfo: Hinfo> = Hinfo::new( + "1234".parse().unwrap(), + "abcd".parse().unwrap() + ); + let hinfo_bytes: Hinfo = hinfo.octets_into().unwrap(); + assert_eq!(hinfo.cpu(), hinfo_bytes.cpu()); + assert_eq!(hinfo.os(), hinfo_bytes.os()); + } + + #[test] + #[cfg(features = "bytes")] + fn minfo_octets_into() { + use crate::base::Dname; + use crate::octets::OctetsInto; + + let minfo: Minfo>> = Minfo::new( + "a.example".parse().unwrap(), + "b.example".parse().unwrap() + ); + let minfo_bytes: Minfo> = + minfo.octets_into().unwrap(); + assert_eq!(minfo.rmailbx(), minfo_bytes.rmailbx()); + assert_eq!(minfo.emailbx(), minfo_bytes.emailbx()); + } + #[test] fn txt_from_slice() { let short = b"01234"; From 7a1db17ab1cd5bcee4617587adb2317d6ba7cf6a Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Tue, 10 Nov 2020 14:16:35 +0100 Subject: [PATCH 3/5] Update changelog. --- Changelog.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Changelog.md b/Changelog.md index 11193fb66..4de6de7b5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -23,12 +23,17 @@ Bug Fixes New +* Supprt for extended errors defined in [RFC 8914]. ([#79] by [@xofyarg]). + Other Changes [#74]: https://github.com/NLnetLabs/domain/pull/74 [#75]: https://github.com/NLnetLabs/domain/pull/75 [#76]: https://github.com/NLnetLabs/domain/pull/76 +[#79]: https://github.com/NLnetLabs/domain/pull/79 [@vavrusa]: https://github.com/vavrusa +[@xofyarg]: https://github.com/xofyarg +[RFC 8914]: https://tools.ietf.org/html/rfc8914 ## 0.5.3 From a02449e7beaef03adf5733a013c713fdb3e557b7 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Wed, 11 Nov 2020 12:20:42 +0100 Subject: [PATCH 4/5] Update changelog. --- Changelog.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 4de6de7b5..8c397eb8c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -20,10 +20,11 @@ Bug Fixes by [@vavrusa]) * Fix canonical comparison of TXT RDATA by taking the length labels into account. ([#76] by [@vavrusa]) +* Fix parsed not rejecting of malformed TXT RDATA. ([#80] by [@vavrusa]) New -* Supprt for extended errors defined in [RFC 8914]. ([#79] by [@xofyarg]). +* Supprt for extended errors defined in [RFC 8914]. ([#79] by [@xofyarg]) Other Changes @@ -31,6 +32,7 @@ Other Changes [#75]: https://github.com/NLnetLabs/domain/pull/75 [#76]: https://github.com/NLnetLabs/domain/pull/76 [#79]: https://github.com/NLnetLabs/domain/pull/79 +[#80]: https://github.com/NLnetLabs/domain/pull/80 [@vavrusa]: https://github.com/vavrusa [@xofyarg]: https://github.com/xofyarg [RFC 8914]: https://tools.ietf.org/html/rfc8914 From 66086ced0c724d2bf2682935e7e1051ae6edddf7 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Thu, 12 Nov 2020 12:23:08 +0100 Subject: [PATCH 5/5] Update changelog. --- Changelog.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 8c397eb8c..19971702a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,11 @@ Breaking `domain::base::octets::OctetsBuilder`. It’s method `into_octets` is now available as `freeze` on `OctetsBuilder. ([#75]) +* Supprt for extended errors defined in [RFC 8914]. ([#79] by [@xofyarg]) +* New traits `domain::base::octets::OctetsFrom` and `OctetsInto` to + convert types that are generic over octets sequences between different + octets sequences. ([#77]) + Bug Fixes * Fix domain name compressors when giving a root label only. ([#76] @@ -24,13 +29,13 @@ Bug Fixes New -* Supprt for extended errors defined in [RFC 8914]. ([#79] by [@xofyarg]) Other Changes [#74]: https://github.com/NLnetLabs/domain/pull/74 [#75]: https://github.com/NLnetLabs/domain/pull/75 [#76]: https://github.com/NLnetLabs/domain/pull/76 +[#77]: https://github.com/NLnetLabs/domain/pull/77 [#79]: https://github.com/NLnetLabs/domain/pull/79 [#80]: https://github.com/NLnetLabs/domain/pull/80 [@vavrusa]: https://github.com/vavrusa