From 19fcfe393cc0d82e228fdc24efe593932a2b1348 Mon Sep 17 00:00:00 2001 From: Marek Vavrusa Date: Wed, 15 Apr 2020 18:39:21 -0700 Subject: [PATCH] rdata/rfc6672: added Dname type support --- domain/src/rdata/macros.rs | 149 +++++++++++++++++++++++++++++++++++ domain/src/rdata/mod.rs | 12 ++- domain/src/rdata/rfc1035.rs | 151 ------------------------------------ domain/src/rdata/rfc6672.rs | 37 +++++++++ 4 files changed, 195 insertions(+), 154 deletions(-) create mode 100644 domain/src/rdata/rfc6672.rs diff --git a/domain/src/rdata/macros.rs b/domain/src/rdata/macros.rs index 7f1795dc5..97eef9011 100644 --- a/domain/src/rdata/macros.rs +++ b/domain/src/rdata/macros.rs @@ -703,3 +703,152 @@ macro_rules! rdata_types { } } + +//------------ dname_type! -------------------------------------------------- + +/// A macro for implementing a record data type with a single domain name. +/// +/// Implements some basic methods plus the `RecordData`, `FlatRecordData`, +/// and `Display` traits. +macro_rules! dname_type { + ($(#[$attr:meta])* ( $target:ident, $rtype:ident, $field:ident ) ) => { + $(#[$attr])* + #[derive(Clone, Debug)] + pub struct $target { + $field: N + } + + impl $target { + pub fn new($field: N) -> Self { + $target { $field: $field } + } + + pub fn $field(&self) -> &N { + &self.$field + } + } + + //--- From and FromStr + + impl From for $target { + fn from(name: N) -> Self { + Self::new(name) + } + } + + impl FromStr for $target { + type Err = N::Err; + + fn from_str(s: &str) -> Result { + N::from_str(s).map(Self::new) + } + } + + + //--- PartialEq and Eq + + impl PartialEq<$target> for $target + where N: ToDname, NN: ToDname { + fn eq(&self, other: &$target) -> bool { + self.$field.name_eq(&other.$field) + } + } + + impl Eq for $target { } + + + //--- PartialOrd, Ord, and CanonicalOrd + + impl PartialOrd<$target> for $target + where N: ToDname, NN: ToDname { + fn partial_cmp(&self, other: &$target) -> Option { + Some(self.$field.name_cmp(&other.$field)) + } + } + + impl Ord for $target { + fn cmp(&self, other: &Self) -> Ordering { + self.$field.name_cmp(&other.$field) + } + } + + impl CanonicalOrd<$target> for $target { + fn canonical_cmp(&self, other: &$target) -> Ordering { + self.$field.lowercase_composed_cmp(&other.$field) + } + } + + + //--- Hash + + impl hash::Hash for $target { + fn hash(&self, state: &mut H) { + self.$field.hash(state) + } + } + + + //--- Parse and Compose + + impl Parse for $target> { + fn parse(parser: &mut Parser) -> Result { + ParsedDname::parse(parser).map(Self::new) + } + + fn skip(parser: &mut Parser) -> Result<(), ParseError> { + ParsedDname::skip(parser).map_err(Into::into) + } + } + + impl Compose for $target { + fn compose( + &self, + target: &mut T + ) -> Result<(), ShortBuf> { + target.append_compressed_dname(&self.$field) + } + + fn compose_canonical( + &self, + target: &mut T + ) -> Result<(), ShortBuf> { + self.$field.compose_canonical(target) + } + } + + + //--- Scan and Display + + #[cfg(feature="master")] + impl Scan for $target { + fn scan(scanner: &mut Scanner) + -> Result { + N::scan(scanner).map(Self::new) + } + } + + impl fmt::Display for $target { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}.", self.$field) + } + } + + + //--- RtypeRecordData + + impl RtypeRecordData for $target { + const RTYPE: Rtype = Rtype::$rtype; + } + + + //--- Deref + + impl ops::Deref for $target { + type Target = N; + + fn deref(&self) -> &Self::Target { + &self.$field + } + } + } +} diff --git a/domain/src/rdata/mod.rs b/domain/src/rdata/mod.rs index 06efe9468..55c9932cf 100644 --- a/domain/src/rdata/mod.rs +++ b/domain/src/rdata/mod.rs @@ -24,17 +24,18 @@ //! [`MasterRecordData`]: enum.MasterRecordData.html //! [`base::iana::Rtype`]: ../base/iana/enum.Rtype.html +#[macro_use] +mod macros; + pub mod rfc1035; pub mod rfc2782; pub mod rfc2845; pub mod rfc3596; pub mod rfc4034; +pub mod rfc6672; pub mod rfc5155; pub mod rfc7344; -#[macro_use] -mod macros; - // The rdata_types! macro (defined in self::macros) reexports the record data // types here and creates the MasterRecordData and AllRecordData enums // containing all record types that can appear in master files or all record @@ -95,6 +96,11 @@ rdata_types! { Ds, } } + rfc6672::{ + master { + Dname, + } + } rfc5155::{ master { Nsec3, diff --git a/domain/src/rdata/rfc1035.rs b/domain/src/rdata/rfc1035.rs index fd4925656..b3ec8c6fa 100644 --- a/domain/src/rdata/rfc1035.rs +++ b/domain/src/rdata/rfc1035.rs @@ -25,157 +25,6 @@ use crate::base::serial::Serial; CharSource, ScanError, Scan, Scanner, SyntaxError }; - -//------------ dname_type! -------------------------------------------------- - -/// A macro for implementing a record data type with a single domain name. -/// -/// Implements some basic methods plus the `RecordData`, `FlatRecordData`, -/// and `Display` traits. -macro_rules! dname_type { - ($(#[$attr:meta])* ( $target:ident, $rtype:ident, $field:ident ) ) => { - $(#[$attr])* - #[derive(Clone, Debug)] - pub struct $target { - $field: N - } - - impl $target { - pub fn new($field: N) -> Self { - $target { $field: $field } - } - - pub fn $field(&self) -> &N { - &self.$field - } - } - - //--- From and FromStr - - impl From for $target { - fn from(name: N) -> Self { - Self::new(name) - } - } - - impl FromStr for $target { - type Err = N::Err; - - fn from_str(s: &str) -> Result { - N::from_str(s).map(Self::new) - } - } - - - //--- PartialEq and Eq - - impl PartialEq<$target> for $target - where N: ToDname, NN: ToDname { - fn eq(&self, other: &$target) -> bool { - self.$field.name_eq(&other.$field) - } - } - - impl Eq for $target { } - - - //--- PartialOrd, Ord, and CanonicalOrd - - impl PartialOrd<$target> for $target - where N: ToDname, NN: ToDname { - fn partial_cmp(&self, other: &$target) -> Option { - Some(self.$field.name_cmp(&other.$field)) - } - } - - impl Ord for $target { - fn cmp(&self, other: &Self) -> Ordering { - self.$field.name_cmp(&other.$field) - } - } - - impl CanonicalOrd<$target> for $target { - fn canonical_cmp(&self, other: &$target) -> Ordering { - self.$field.lowercase_composed_cmp(&other.$field) - } - } - - - //--- Hash - - impl hash::Hash for $target { - fn hash(&self, state: &mut H) { - self.$field.hash(state) - } - } - - - //--- Parse and Compose - - impl Parse for $target> { - fn parse(parser: &mut Parser) -> Result { - ParsedDname::parse(parser).map(Self::new) - } - - fn skip(parser: &mut Parser) -> Result<(), ParseError> { - ParsedDname::skip(parser).map_err(Into::into) - } - } - - impl Compose for $target { - fn compose( - &self, - target: &mut T - ) -> Result<(), ShortBuf> { - target.append_compressed_dname(&self.$field) - } - - fn compose_canonical( - &self, - target: &mut T - ) -> Result<(), ShortBuf> { - self.$field.compose_canonical(target) - } - } - - - //--- Scan and Display - - #[cfg(feature="master")] - impl Scan for $target { - fn scan(scanner: &mut Scanner) - -> Result { - N::scan(scanner).map(Self::new) - } - } - - impl fmt::Display for $target { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}.", self.$field) - } - } - - - //--- RtypeRecordData - - impl RtypeRecordData for $target { - const RTYPE: Rtype = Rtype::$rtype; - } - - - //--- Deref - - impl ops::Deref for $target { - type Target = N; - - fn deref(&self) -> &Self::Target { - &self.$field - } - } - } -} - - //------------ A ------------------------------------------------------------ /// A record data. diff --git a/domain/src/rdata/rfc6672.rs b/domain/src/rdata/rfc6672.rs new file mode 100644 index 000000000..fdb357970 --- /dev/null +++ b/domain/src/rdata/rfc6672.rs @@ -0,0 +1,37 @@ +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::rdata::RtypeRecordData; +#[cfg(feature = "master")] +use crate::master::scan::{CharSource, Scan, ScanError, Scanner}; +use core::cmp::Ordering; +use core::str::FromStr; +use core::{fmt, hash, ops}; + +//------------ Dname -------------------------------------------------------- + +dname_type! { + /// DNAME record data. + /// + /// The DNAME record provides redirection for a subtree of the domain + /// name tree in the DNS. + /// + /// The DNAME type is defined in RFC 6672. + (Dname, Dname, dname) +} + +#[cfg(test)] +mod test { + use crate::base::name::Dname; + use crate::rdata::rfc6672; + use core::str::FromStr; + use std::vec::Vec; + + #[test] + fn create_dname() { + let name = Dname::>::from_str("bar.example.com").unwrap(); + let rdata = rfc6672::Dname::new(name.clone()); + assert_eq!(rdata.dname(), &name); + } +}