step
This commit is contained in:
parent
2e380af9bb
commit
e0f597ba9c
@ -21,6 +21,7 @@ pub const ANY : Class = Class(KnownQClass::ANY as u16);
|
|||||||
pub enum KnownClass {
|
pub enum KnownClass {
|
||||||
// try to list "original" rfc
|
// try to list "original" rfc
|
||||||
IN = 0x0001, // RFC 1035
|
IN = 0x0001, // RFC 1035
|
||||||
|
// CS = 0x0002, // "CSNET"
|
||||||
CH = 0x0003, // "Chaos"
|
CH = 0x0003, // "Chaos"
|
||||||
HS = 0x0004, // "Hesiod"
|
HS = 0x0004, // "Hesiod"
|
||||||
}
|
}
|
||||||
@ -110,6 +111,18 @@ impl Class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<KnownClass> for Class {
|
||||||
|
fn from(value: KnownClass) -> Self {
|
||||||
|
Class(value as u16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<KnownQClass> for Class {
|
||||||
|
fn from(value: KnownQClass) -> Self {
|
||||||
|
Class(value as u16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Display for Class {
|
impl fmt::Display for Class {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let n = match *self {
|
let n = match *self {
|
||||||
|
@ -5,14 +5,13 @@ pub mod classes;
|
|||||||
pub mod types;
|
pub mod types;
|
||||||
mod nsec;
|
mod nsec;
|
||||||
mod nxt;
|
mod nxt;
|
||||||
mod rr_type;
|
|
||||||
mod time;
|
mod time;
|
||||||
mod uri;
|
mod uri;
|
||||||
|
|
||||||
pub use self::binary::{HexShortBlob, Base64RemainingBlob, HexRemainingBlob};
|
pub use self::binary::{HexShortBlob, Base64RemainingBlob, HexRemainingBlob};
|
||||||
pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName};
|
pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName};
|
||||||
pub use self::nsec::{NsecTypeBitmap, NextHashedOwnerName};
|
pub use self::nsec::{NsecTypeBitmap, NextHashedOwnerName};
|
||||||
pub use self::rr_type::Type;
|
pub use self::types::Type;
|
||||||
pub use self::classes::Class;
|
pub use self::classes::Class;
|
||||||
pub use self::text::{ShortText, LongText, UnquotedShortText, RemainingText};
|
pub use self::text::{ShortText, LongText, UnquotedShortText, RemainingText};
|
||||||
pub use self::uri::UriText;
|
pub use self::uri::UriText;
|
||||||
|
@ -1,99 +0,0 @@
|
|||||||
use bytes::Bytes;
|
|
||||||
use errors::*;
|
|
||||||
use ser::DnsPacketData;
|
|
||||||
use ser::text::{DnsTextData, DnsTextFormatter, next_field};
|
|
||||||
use std::fmt;
|
|
||||||
use std::io::Cursor;
|
|
||||||
use records::registry::{name_to_type, type_name};
|
|
||||||
use common_types::types;
|
|
||||||
use std::borrow::Cow;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
|
||||||
pub struct Type(pub u16);
|
|
||||||
|
|
||||||
impl Type {
|
|
||||||
pub fn name(self) -> Cow<'static, str> {
|
|
||||||
if let Some(name) = type_name(self) {
|
|
||||||
Cow::Borrowed(name)
|
|
||||||
} else {
|
|
||||||
Cow::Owned(format!("TYPE{}", self.0))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// defined in RFC 1035
|
|
||||||
pub fn well_known(self) -> bool {
|
|
||||||
// 0x0001 (A) ... 0x0010 (TXT) are defined in RFC 1035
|
|
||||||
self.0 >= 0x0001 && self.0 <= 0x0010
|
|
||||||
}
|
|
||||||
|
|
||||||
/// require converting to canonical form for DNSSEC (i.e. names
|
|
||||||
/// must be converted to (ASCII) lower case, no compression)
|
|
||||||
///
|
|
||||||
/// See https://tools.ietf.org/html/rfc4034#section-6.2 (updates RFC 3597).
|
|
||||||
pub fn canonical(self) -> bool {
|
|
||||||
match self {
|
|
||||||
types::NS => true,
|
|
||||||
types::MD => true,
|
|
||||||
types::MF => true,
|
|
||||||
types::CNAME => true,
|
|
||||||
types::SOA => true,
|
|
||||||
types::MB => true,
|
|
||||||
types::MG => true,
|
|
||||||
types::MR => true,
|
|
||||||
types::PTR => true,
|
|
||||||
// types::HINFO => true, // doesn't have a name in data
|
|
||||||
types::MINFO => true,
|
|
||||||
types::MX => true,
|
|
||||||
// types::HINFO => true, // see above, also duplicate in the RFCs
|
|
||||||
types::RP => true,
|
|
||||||
types::AFSDB => true,
|
|
||||||
types::RT => true,
|
|
||||||
types::NSAP_PTR => true, // not listed in the RFCs, but probably should be.
|
|
||||||
types::SIG => true,
|
|
||||||
types::PX => true,
|
|
||||||
types::NXT => true,
|
|
||||||
types::SRV => true, // moved up to match numeric order
|
|
||||||
types::NAPTR => true,
|
|
||||||
types::KX => true,
|
|
||||||
// types::SRV => true, // moved up to match numeric order
|
|
||||||
types::A6 => true, // moved up to match numeric order
|
|
||||||
types::DNAME => true,
|
|
||||||
// types::A6 => true, // moved up to match numeric order
|
|
||||||
types::RRSIG => true,
|
|
||||||
types::NSEC => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Type {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
if let Some(name) = type_name(*self) {
|
|
||||||
write!(f, "{}", name)
|
|
||||||
} else {
|
|
||||||
write!(f, "TYPE{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DnsPacketData for Type {
|
|
||||||
fn deserialize(data: &mut Cursor<Bytes>) -> Result<Self> {
|
|
||||||
Ok(Type(DnsPacketData::deserialize(data)?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DnsTextData for Type {
|
|
||||||
fn dns_parse(data: &mut &str) -> Result<Self> {
|
|
||||||
let field = next_field(data)?;
|
|
||||||
if field.starts_with("TYPE") || field.starts_with("type") {
|
|
||||||
if let Ok(t) = field[4..].parse::<u16>() {
|
|
||||||
return Ok(Type(t));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
name_to_type(field).ok_or_else(|| format_err!("unknown type {:?}", field))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result {
|
|
||||||
write!(f, "{}", self)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,14 @@
|
|||||||
use common_types::Type;
|
use bytes::Bytes;
|
||||||
|
use errors::*;
|
||||||
|
use records::registry::{lookup_type_to_name, lookup_type_name};
|
||||||
|
use ser::DnsPacketData;
|
||||||
|
use ser::text::{DnsTextData, DnsTextFormatter, next_field};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::fmt;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
pub struct Type(pub u16);
|
||||||
|
|
||||||
pub const A : Type = Type(KnownType::A as u16);
|
pub const A : Type = Type(KnownType::A as u16);
|
||||||
pub const NS : Type = Type(KnownType::NS as u16);
|
pub const NS : Type = Type(KnownType::NS as u16);
|
||||||
@ -40,7 +50,7 @@ pub const CERT : Type = Type(KnownType::CERT as u16);
|
|||||||
pub const A6 : Type = Type(KnownType::A6 as u16);
|
pub const A6 : Type = Type(KnownType::A6 as u16);
|
||||||
pub const DNAME : Type = Type(KnownType::DNAME as u16);
|
pub const DNAME : Type = Type(KnownType::DNAME as u16);
|
||||||
pub const SINK : Type = Type(KnownType::SINK as u16);
|
pub const SINK : Type = Type(KnownType::SINK as u16);
|
||||||
pub const OPT : Type = Type(KnownType::OPT as u16);
|
pub const OPT : Type = Type(KnownMetaType::OPT as u16);
|
||||||
pub const APL : Type = Type(KnownType::APL as u16);
|
pub const APL : Type = Type(KnownType::APL as u16);
|
||||||
pub const DS : Type = Type(KnownType::DS as u16);
|
pub const DS : Type = Type(KnownType::DS as u16);
|
||||||
pub const SSHFP : Type = Type(KnownType::SSHFP as u16);
|
pub const SSHFP : Type = Type(KnownType::SSHFP as u16);
|
||||||
@ -72,19 +82,19 @@ pub const L64 : Type = Type(KnownType::L64 as u16);
|
|||||||
pub const LP : Type = Type(KnownType::LP as u16);
|
pub const LP : Type = Type(KnownType::LP as u16);
|
||||||
pub const EUI48 : Type = Type(KnownType::EUI48 as u16);
|
pub const EUI48 : Type = Type(KnownType::EUI48 as u16);
|
||||||
pub const EUI64 : Type = Type(KnownType::EUI64 as u16);
|
pub const EUI64 : Type = Type(KnownType::EUI64 as u16);
|
||||||
pub const TKEY : Type = Type(KnownType::TKEY as u16);
|
pub const TKEY : Type = Type(KnownMetaType::TKEY as u16);
|
||||||
pub const TSIG : Type = Type(KnownType::TSIG as u16);
|
pub const TSIG : Type = Type(KnownMetaType::TSIG as u16);
|
||||||
pub const IXFR : Type = Type(KnownType::IXFR as u16);
|
pub const IXFR : Type = Type(KnownQType::IXFR as u16);
|
||||||
pub const AXFR : Type = Type(KnownType::AXFR as u16);
|
pub const AXFR : Type = Type(KnownQType::AXFR as u16);
|
||||||
pub const MAILB : Type = Type(KnownType::MAILB as u16);
|
pub const MAILB : Type = Type(KnownQType::MAILB as u16);
|
||||||
pub const MAILA : Type = Type(KnownType::MAILA as u16);
|
pub const MAILA : Type = Type(KnownQType::MAILA as u16);
|
||||||
pub const ANY : Type = Type(KnownType::ANY as u16);
|
pub const ANY : Type = Type(KnownQType::ANY as u16);
|
||||||
pub const URI : Type = Type(KnownType::URI as u16);
|
pub const URI : Type = Type(KnownType::URI as u16);
|
||||||
pub const CAA : Type = Type(KnownType::CAA as u16);
|
pub const CAA : Type = Type(KnownType::CAA as u16);
|
||||||
pub const AVC : Type = Type(KnownType::AVC as u16);
|
pub const AVC : Type = Type(KnownType::AVC as u16);
|
||||||
pub const DOA : Type = Type(KnownType::DOA as u16);
|
pub const DOA : Type = Type(KnownType::DOA as u16);
|
||||||
|
pub const TA : Type = Type(KnownType::TA as u16);
|
||||||
pub const DLV : Type = Type(KnownType::DLV as u16);
|
pub const DLV : Type = Type(KnownType::DLV as u16);
|
||||||
pub const ADDR : Type = Type(KnownType::ADDR as u16);
|
|
||||||
pub const ALIAS : Type = Type(KnownType::ALIAS as u16);
|
pub const ALIAS : Type = Type(KnownType::ALIAS as u16);
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
@ -132,7 +142,7 @@ pub enum KnownType {
|
|||||||
A6 = 0x0026, // RFC 2874
|
A6 = 0x0026, // RFC 2874
|
||||||
DNAME = 0x0027, // RFC 6672
|
DNAME = 0x0027, // RFC 6672
|
||||||
SINK = 0x0028, // Donald E Eastlake: http://tools.ietf.org/html/draft-eastlake-kitchen-sink
|
SINK = 0x0028, // Donald E Eastlake: http://tools.ietf.org/html/draft-eastlake-kitchen-sink
|
||||||
OPT = 0x0029, // RFC 6891
|
// OPT (0x0029) is a meta type
|
||||||
APL = 0x002a, // RFC 3123
|
APL = 0x002a, // RFC 3123
|
||||||
DS = 0x002b, // RFC 3658
|
DS = 0x002b, // RFC 3658
|
||||||
SSHFP = 0x002c, // RFC 4255
|
SSHFP = 0x002c, // RFC 4255
|
||||||
@ -164,22 +174,219 @@ pub enum KnownType {
|
|||||||
LP = 0x006b, // RFC 6742
|
LP = 0x006b, // RFC 6742
|
||||||
EUI48 = 0x006c, // RFC 7043
|
EUI48 = 0x006c, // RFC 7043
|
||||||
EUI64 = 0x006d, // RFC 7043
|
EUI64 = 0x006d, // RFC 7043
|
||||||
|
// 0x0080..0x00ff: meta and qtypes
|
||||||
|
URI = 0x0100, // RFC 7553
|
||||||
|
CAA = 0x0101, // RFC 6844
|
||||||
|
AVC = 0x0102, // Wolfgang Riedel
|
||||||
|
DOA = 0x0103, // http://www.iana.org/go/draft-durand-doa-over-dns
|
||||||
|
TA = 0x8000, //
|
||||||
|
DLV = 0x8001, // RFC 4431
|
||||||
|
ALIAS = 0xff79, // powerdns
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[repr(u16)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum KnownMetaType {
|
||||||
|
OPT = 0x0029, // RFC 6891
|
||||||
TKEY = 0x00f9, // RFC 2930
|
TKEY = 0x00f9, // RFC 2930
|
||||||
TSIG = 0x00fa, // RFC 2845
|
TSIG = 0x00fa, // RFC 2845
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[repr(u16)]
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
pub enum KnownQType {
|
||||||
IXFR = 0x00fb, // RFC 1995
|
IXFR = 0x00fb, // RFC 1995
|
||||||
AXFR = 0x00fc, // RFC 1035
|
AXFR = 0x00fc, // RFC 1035
|
||||||
MAILB = 0x00fd, // RFC 1035
|
MAILB = 0x00fd, // RFC 1035
|
||||||
MAILA = 0x00fe, // RFC 1035
|
MAILA = 0x00fe, // RFC 1035
|
||||||
ANY = 0x00ff, // RFC 1035, "*"
|
ANY = 0x00ff, // RFC 1035, "*"
|
||||||
URI = 0x0100, // RFC 7553
|
|
||||||
CAA = 0x0101, // RFC 6844
|
|
||||||
AVC = 0x0102, // Wolfgang Riedel
|
|
||||||
DOA = 0x0103, // http://www.iana.org/go/draft-durand-doa-over-dns
|
|
||||||
DLV = 0x8001, // RFC 4431
|
|
||||||
ADDR = 0xff78, // powerdns?
|
|
||||||
ALIAS = 0xff79, // powerdns?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Type {
|
||||||
|
pub fn name(self) -> Cow<'static, str> {
|
||||||
|
if let Some(name) = lookup_type_to_name(self) {
|
||||||
|
Cow::Borrowed(name)
|
||||||
|
} else {
|
||||||
|
Cow::Owned(self.generic_name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0x0080-0x00FF is reserved for QTYPEs and Meta TYPEs.
|
||||||
|
// OPT is a special meta type
|
||||||
|
pub fn is_q_or_meta_type(self) -> bool {
|
||||||
|
self == OPT || (self.0 >= 128 && self.0 < 256)
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks for known qtypes
|
||||||
|
pub fn is_known_qtype(self) -> bool {
|
||||||
|
match self {
|
||||||
|
IXFR => true,
|
||||||
|
AXFR => true,
|
||||||
|
MAILB => true,
|
||||||
|
MAILA => true,
|
||||||
|
ANY => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// checks for known meta types
|
||||||
|
pub fn is_known_meta_type(self) -> bool {
|
||||||
|
match self {
|
||||||
|
OPT => true,
|
||||||
|
TKEY => true,
|
||||||
|
TSIG => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// uses generic name for QTYPEs/Meta TYPEs (`is_q_or_meta_type`)
|
||||||
|
pub fn type_name(self) -> Cow<'static, str> {
|
||||||
|
if self.is_q_or_meta_type() {
|
||||||
|
Cow::Owned(self.generic_name())
|
||||||
|
} else {
|
||||||
|
self.name()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generic_name(self) -> String {
|
||||||
|
format!("TYPE{}", self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_name(name: &str) -> Option<Self> {
|
||||||
|
use std::ascii::AsciiExt;
|
||||||
|
if let Some(t) = lookup_type_name(name) { return Some(t); }
|
||||||
|
if name.as_bytes()[0..4].eq_ignore_ascii_case(b"TYPE") {
|
||||||
|
if let Ok(t) = name[4..].parse::<u16>() {
|
||||||
|
return Some(Type(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// similar to `from_name`, but doesn't accept QTYPE/Meta TYPE names (it
|
||||||
|
/// always accepts "TYPE..." names though, even if they are known to
|
||||||
|
/// be QTYPE/Meta TYPE)
|
||||||
|
pub fn type_from_name(name: &str) -> Option<Self> {
|
||||||
|
use std::ascii::AsciiExt;
|
||||||
|
if let Some(t) = lookup_type_name(name) {
|
||||||
|
if t.is_q_or_meta_type() { return None; }
|
||||||
|
return Some(t);
|
||||||
|
}
|
||||||
|
if name.as_bytes()[0..4].eq_ignore_ascii_case(b"TYPE") {
|
||||||
|
if let Ok(t) = name[4..].parse::<u16>() {
|
||||||
|
return Some(Type(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_type_name(self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
if self.is_q_or_meta_type() {
|
||||||
|
self.write_generic_name(f)
|
||||||
|
} else {
|
||||||
|
write!(f, "{}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_generic_name(self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "TYPE{}", self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// defined in RFC 1035
|
||||||
|
pub fn well_known(self) -> bool {
|
||||||
|
// 0x0001 (A) ... 0x0010 (TXT) are defined in RFC 1035
|
||||||
|
self.0 >= 0x0001 && self.0 <= 0x0010
|
||||||
|
}
|
||||||
|
|
||||||
|
/// require converting to canonical form for DNSSEC (i.e. names
|
||||||
|
/// must be converted to (ASCII) lower case, no compression)
|
||||||
|
///
|
||||||
|
/// See https://tools.ietf.org/html/rfc4034#section-6.2 (updates RFC 3597).
|
||||||
|
/// Also updated by https://tools.ietf.org/html/rfc6840#section-5.1
|
||||||
|
pub fn canonical(self) -> bool {
|
||||||
|
match self {
|
||||||
|
NS => true,
|
||||||
|
MD => true,
|
||||||
|
MF => true,
|
||||||
|
CNAME => true,
|
||||||
|
SOA => true,
|
||||||
|
MB => true,
|
||||||
|
MG => true,
|
||||||
|
MR => true,
|
||||||
|
PTR => true,
|
||||||
|
// HINFO => true, // removed by RFC 6840: doesn't have a name in data
|
||||||
|
MINFO => true,
|
||||||
|
MX => true,
|
||||||
|
// HINFO => true, // removed by RFC 6840: see above, also duplicate
|
||||||
|
RP => true,
|
||||||
|
AFSDB => true,
|
||||||
|
RT => true,
|
||||||
|
NSAP_PTR => true, // not listed in the RFCs, but probably should be.
|
||||||
|
SIG => true,
|
||||||
|
PX => true,
|
||||||
|
NXT => true,
|
||||||
|
SRV => true, // moved up to match numeric order
|
||||||
|
NAPTR => true,
|
||||||
|
KX => true,
|
||||||
|
// SRV => true, // moved up to match numeric order
|
||||||
|
A6 => true, // moved up to match numeric order
|
||||||
|
DNAME => true,
|
||||||
|
// A6 => true, // moved up to match numeric order
|
||||||
|
RRSIG => true,
|
||||||
|
// NSEC => true, // removed by RFC 6840
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<KnownType> for Type {
|
||||||
|
fn from(value: KnownType) -> Self {
|
||||||
|
Type(value as u16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<KnownMetaType> for Type {
|
||||||
|
fn from(value: KnownMetaType) -> Self {
|
||||||
|
Type(value as u16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<KnownQType> for Type {
|
||||||
|
fn from(value: KnownQType) -> Self {
|
||||||
|
Type(value as u16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Type {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
if let Some(name) = lookup_type_to_name(*self) {
|
||||||
|
write!(f, "{}", name)
|
||||||
|
} else {
|
||||||
|
self.write_generic_name(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DnsPacketData for Type {
|
||||||
|
fn deserialize(data: &mut Cursor<Bytes>) -> Result<Self> {
|
||||||
|
Ok(Type(DnsPacketData::deserialize(data)?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DnsTextData for Type {
|
||||||
|
fn dns_parse(data: &mut &str) -> Result<Self> {
|
||||||
|
let field = next_field(data)?;
|
||||||
|
Type::from_name(field).ok_or_else(|| format_err!("unknown type {:?}", field))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result {
|
||||||
|
write!(f, "{}", self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
macro_rules! check_type {
|
macro_rules! check_type {
|
||||||
($t:ident, $dec:expr) => {
|
($t:ident, $dec:expr) => {
|
||||||
@ -188,7 +395,7 @@ macro_rules! check_type {
|
|||||||
// compare decimal value
|
// compare decimal value
|
||||||
assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t));
|
assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t));
|
||||||
// make sure it's registered
|
// make sure it's registered
|
||||||
assert_eq!(registry::name_to_type(stringify!($t)), Some($t), "{} not registered", stringify!($t));
|
assert_eq!(registry::lookup_type_name(stringify!($t)), Some($t), "{} not registered", stringify!($t));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($t:ident, $dec:expr, $name:expr) => {
|
($t:ident, $dec:expr, $name:expr) => {
|
||||||
@ -197,7 +404,7 @@ macro_rules! check_type {
|
|||||||
// compare decimal value
|
// compare decimal value
|
||||||
assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t));
|
assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t));
|
||||||
// make sure it's registered
|
// make sure it's registered
|
||||||
assert_eq!(registry::name_to_type($name), Some($t), "{} not registered as {:?}", stringify!($t), $name);
|
assert_eq!(registry::lookup_type_name($name), Some($t), "{} not registered as {:?}", stringify!($t), $name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -288,7 +495,7 @@ fn check_types() {
|
|||||||
check_type!(CAA , 257);
|
check_type!(CAA , 257);
|
||||||
check_type!(AVC , 258);
|
check_type!(AVC , 258);
|
||||||
check_type!(DOA , 259);
|
check_type!(DOA , 259);
|
||||||
|
check_type!(TA , 32768);
|
||||||
check_type!(DLV , 32769);
|
check_type!(DLV , 32769);
|
||||||
check_type!(ADDR , 65400);
|
|
||||||
check_type!(ALIAS , 65401);
|
check_type!(ALIAS , 65401);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
use std::collections::HashMap;
|
use bytes::Bytes;
|
||||||
|
use std::any::TypeId;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::io::Cursor;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use common_types::{Class, Type, types};
|
||||||
|
use errors::*;
|
||||||
use records::structs;
|
use records::structs;
|
||||||
use common_types::types;
|
|
||||||
use common_types::Type;
|
|
||||||
use ser::{RRData, StaticRRData};
|
use ser::{RRData, StaticRRData};
|
||||||
|
|
||||||
|
// this should be enough for registered names
|
||||||
|
const TYPE_NAME_MAX_LEN: usize = 16;
|
||||||
|
|
||||||
lazy_static!{
|
lazy_static!{
|
||||||
static ref REGISTRY: Registry = Registry::init();
|
static ref REGISTRY: Registry = Registry::init();
|
||||||
}
|
}
|
||||||
@ -15,31 +21,59 @@ fn registry() -> &'static Registry {
|
|||||||
&*REGISTRY
|
&*REGISTRY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn lookup_type_name(name: &str) -> Option<Type> {
|
||||||
|
if name.len() >= TYPE_NAME_MAX_LEN { return None; }
|
||||||
|
let mut name_buf_storage = [0u8; TYPE_NAME_MAX_LEN];
|
||||||
|
let name_buf = &mut name_buf_storage[..name.len()];
|
||||||
|
name_buf.copy_from_slice(name.as_bytes());
|
||||||
|
|
||||||
|
name_buf.make_ascii_uppercase();
|
||||||
|
|
||||||
|
let registry = registry();
|
||||||
|
let &t = registry.names_to_type.get(name_buf)?;
|
||||||
|
Some(t)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn known_name_to_type(name: &str) -> Option<Type> {
|
pub fn known_name_to_type(name: &str) -> Option<Type> {
|
||||||
let registry = registry();
|
let registry = registry();
|
||||||
let t = name_to_type(name)?;
|
let t = lookup_type_name(name)?;
|
||||||
registry.type_parser.get(&t)?;
|
registry.type_parser.get(&t)?;
|
||||||
|
|
||||||
Some(t)
|
Some(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name_to_type(name: &str) -> Option<Type> {
|
pub(crate) fn lookup_type_to_name(rrtype: Type) -> Option<&'static str> {
|
||||||
let registry = registry();
|
|
||||||
let &t = registry.names_to_type.get(name)?;
|
|
||||||
Some(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn type_name(rrtype: Type) -> Option<&'static str> {
|
|
||||||
let registry = registry();
|
let registry = registry();
|
||||||
registry.type_names.get(&rrtype).map(|s| s as _)
|
registry.type_names.get(&rrtype).map(|s| s as _)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub fn check_registration<T: StaticRRData + Sync + 'static>() {
|
||||||
|
registry().check_registration::<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
struct TagRRDataType<T: RRData>(PhantomData<T>);
|
struct TagRRDataType<T: RRData>(PhantomData<T>);
|
||||||
|
|
||||||
|
trait RRDataTypeParse: 'static {
|
||||||
|
fn type_id(&self) -> TypeId {
|
||||||
|
TypeId::of::<Self>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_rr_data(&self, ttl: u32, rr_class: Class, rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Box<RRData>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RRData + 'static> RRDataTypeParse for TagRRDataType<T> {
|
||||||
|
fn deserialize_rr_data(&self, ttl: u32, rr_class: Class, rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Box<RRData>> {
|
||||||
|
T::deserialize_rr_data(ttl, rr_class, rr_type, data).map(|d| Box::new(d) as _)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Registry {
|
struct Registry {
|
||||||
names_to_type: HashMap<String, Type>,
|
// store (ascii) upper-case names.
|
||||||
|
names_to_type: HashMap<Vec<u8>, Type>,
|
||||||
type_names: HashMap<Type, String>,
|
type_names: HashMap<Type, String>,
|
||||||
type_parser: HashMap<Type, ()>,
|
type_parser: HashMap<Type, Box<RRDataTypeParse + Sync>>,
|
||||||
// make sure registrations are in order
|
// make sure registrations are in order
|
||||||
prev_type: Option<Type>,
|
prev_type: Option<Type>,
|
||||||
}
|
}
|
||||||
@ -79,7 +113,7 @@ impl Registry {
|
|||||||
r.register_known::<structs::SIG>();
|
r.register_known::<structs::SIG>();
|
||||||
r.register_known::<structs::KEY>();
|
r.register_known::<structs::KEY>();
|
||||||
r.register_known::<structs::PX>();
|
r.register_known::<structs::PX>();
|
||||||
r.register_unknown("GPOS" , types::GPOS);
|
r.register_known::<structs::GPOS>();
|
||||||
r.register_known::<structs::AAAA>();
|
r.register_known::<structs::AAAA>();
|
||||||
r.register_known::<structs::LOC>();
|
r.register_known::<structs::LOC>();
|
||||||
r.register_known::<structs::NXT>();
|
r.register_known::<structs::NXT>();
|
||||||
@ -136,9 +170,12 @@ impl Registry {
|
|||||||
r.register_known::<structs::CAA>();
|
r.register_known::<structs::CAA>();
|
||||||
r.register_unknown("AVC" , types::AVC);
|
r.register_unknown("AVC" , types::AVC);
|
||||||
r.register_unknown("DOA" , types::DOA);
|
r.register_unknown("DOA" , types::DOA);
|
||||||
|
r.register_unknown("TA" , types::TA);
|
||||||
r.register_unknown("DLV" , types::DLV);
|
r.register_unknown("DLV" , types::DLV);
|
||||||
r.register_unknown("ADDR" , types::ADDR);
|
r.register_known::<structs::ALIAS>();
|
||||||
r.register_unknown("ALIAS" , types::ALIAS);
|
|
||||||
|
// "ALL" could be an alias for the ANY type?
|
||||||
|
// assert!(r.names_to_type.insert("ALL".into(), types::ANY).is_none());
|
||||||
|
|
||||||
r
|
r
|
||||||
}
|
}
|
||||||
@ -148,7 +185,9 @@ impl Registry {
|
|||||||
self.prev_type = Some(rrtype);
|
self.prev_type = Some(rrtype);
|
||||||
let mut name: String = name.into();
|
let mut name: String = name.into();
|
||||||
name.make_ascii_uppercase();
|
name.make_ascii_uppercase();
|
||||||
assert!(self.names_to_type.insert(name.clone(), rrtype).is_none());
|
assert!(!name.starts_with("TYPE"), "must not register generic name: {}", name);
|
||||||
|
assert!(name.len() <= TYPE_NAME_MAX_LEN, "name too long: {} - maybe you need to increase TYPE_NAME_MAX_LEN", name);
|
||||||
|
assert!(self.names_to_type.insert(name.clone().into_bytes(), rrtype).is_none());
|
||||||
self.type_names.insert(rrtype, name);
|
self.type_names.insert(rrtype, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,10 +195,17 @@ impl Registry {
|
|||||||
self.register_name(name, rrtype);
|
self.register_name(name, rrtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_known<T: StaticRRData>(&mut self) {
|
fn register_known<T: StaticRRData + Sync + 'static>(&mut self) {
|
||||||
let rrtype = T::TYPE;
|
let rrtype = T::TYPE;
|
||||||
let name = T::NAME;
|
let name = T::NAME;
|
||||||
self.register_name(name, rrtype);
|
self.register_name(name, rrtype);
|
||||||
self.type_parser.insert(rrtype, ());
|
self.type_parser.insert(rrtype, Box::new(TagRRDataType::<T>(PhantomData)));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_registration<T: StaticRRData + Sync + 'static>(&self) {
|
||||||
|
assert_eq!(self.names_to_type.get(T::NAME.as_bytes()), Some(&T::TYPE));
|
||||||
|
let p: &RRDataTypeParse = &**self.type_parser.get(&T::TYPE).expect("no parser registered");
|
||||||
|
let tid = TypeId::of::<TagRRDataType<T>>();
|
||||||
|
assert_eq!(p.type_id(), tid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,38 +7,38 @@ use std::net::{Ipv4Addr, Ipv6Addr};
|
|||||||
// registered; there must be a records::types::$name `Type` constant
|
// registered; there must be a records::types::$name `Type` constant
|
||||||
// with the same name as the struct.
|
// with the same name as the struct.
|
||||||
|
|
||||||
// class IN
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(IN)]
|
||||||
pub struct A {
|
pub struct A {
|
||||||
addr: Ipv4Addr,
|
addr: Ipv4Addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct NS {
|
pub struct NS {
|
||||||
nsdname: DnsCompressedName,
|
nsdname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct MD {
|
pub struct MD {
|
||||||
madname: DnsCompressedName,
|
madname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct MF {
|
pub struct MF {
|
||||||
madname: DnsCompressedName,
|
madname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct CNAME {
|
pub struct CNAME {
|
||||||
cname: DnsCompressedName,
|
cname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct SOA {
|
pub struct SOA {
|
||||||
mname: DnsCompressedName,
|
mname: DnsCompressedName,
|
||||||
rname: DnsCompressedName,
|
rname: DnsCompressedName,
|
||||||
@ -49,84 +49,86 @@ pub struct SOA {
|
|||||||
minimum: u32,
|
minimum: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct MB {
|
pub struct MB {
|
||||||
madname: DnsCompressedName,
|
madname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct MG {
|
pub struct MG {
|
||||||
mgmname: DnsCompressedName,
|
mgmname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct MR {
|
pub struct MR {
|
||||||
newname: DnsCompressedName,
|
newname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// not allowed in zone files anyway, i.e. no text representation.
|
// not allowed in zone files anyway, i.e. no text representation.
|
||||||
// content not restricted either, just some bytes. no need to parse it.
|
// content not restricted either, just some bytes. no need to parse it,
|
||||||
|
// generic representation should be just fine.
|
||||||
//
|
//
|
||||||
// class independent pub struct NULL;
|
// #[RRClass(ANY)]
|
||||||
|
// pub struct NULL;
|
||||||
|
|
||||||
// text representation like: `WKS 127.0.0.1 TCP smtp http 110`. would
|
// text representation like: `WKS 127.0.0.1 TCP smtp http 110`. would
|
||||||
// have to parse protocol and service names.
|
// have to parse protocol and service names.
|
||||||
//
|
//
|
||||||
// class IN
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(IN)]
|
||||||
// pub struct WKS {
|
// pub struct WKS {
|
||||||
// address: Ipv4Addr,
|
// address: Ipv4Addr,
|
||||||
// protocol: u8,
|
// protocol: u8,
|
||||||
// bitmap: ..., // remaining bytes
|
// bitmap: ..., // remaining bytes
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct PTR {
|
pub struct PTR {
|
||||||
ptrdname: DnsCompressedName,
|
ptrdname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct HINFO {
|
pub struct HINFO {
|
||||||
cpu: ShortText,
|
cpu: ShortText,
|
||||||
os: ShortText,
|
os: ShortText,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct MINFO {
|
pub struct MINFO {
|
||||||
rmailbx: DnsCompressedName,
|
rmailbx: DnsCompressedName,
|
||||||
emailbx: DnsCompressedName,
|
emailbx: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct MX {
|
pub struct MX {
|
||||||
preference: u16,
|
preference: u16,
|
||||||
mxname: DnsCompressedName,
|
mxname: DnsCompressedName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct TXT {
|
pub struct TXT {
|
||||||
text: LongText,
|
text: LongText,
|
||||||
}
|
}
|
||||||
|
|
||||||
// end of RFC 1035: no DnsCompressedName below!
|
// end of RFC 1035: no DnsCompressedName below!
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct RP {
|
pub struct RP {
|
||||||
mbox: DnsCanonicalName,
|
mbox: DnsCanonicalName,
|
||||||
txt: DnsCanonicalName,
|
txt: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct AFSDB {
|
pub struct AFSDB {
|
||||||
subtype: u16,
|
subtype: u16,
|
||||||
hostname: DnsCanonicalName,
|
hostname: DnsCanonicalName,
|
||||||
@ -142,35 +144,37 @@ pub struct AFSDB {
|
|||||||
// least 4 bytes in the field: probably due to "beginning with the 4
|
// least 4 bytes in the field: probably due to "beginning with the 4
|
||||||
// digit DNIC").
|
// digit DNIC").
|
||||||
//
|
//
|
||||||
// class independent
|
// #[RRClass(ANY)]
|
||||||
// pub struct X25 {
|
// pub struct X25 {
|
||||||
// psdn_address: ShortText,
|
// psdn_address: ShortText,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// class independent
|
// #[RRClass(ANY)]
|
||||||
// pub struct ISDN {
|
// pub struct ISDN {
|
||||||
// isdn_address: ShortText,
|
// isdn_address: ShortText,
|
||||||
// subaddress: Option<ShortText>,
|
// subaddress: Option<ShortText>,
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct RT {
|
pub struct RT {
|
||||||
preference: u16,
|
preference: u16,
|
||||||
intermediate: DnsCanonicalName,
|
intermediate: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[RRClass(ANY)]
|
||||||
// pub struct NSAP;
|
// pub struct NSAP;
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
#[RRTypeName = "NSAP-PTR"]
|
#[RRTypeName = "NSAP-PTR"]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct NSAP_PTR {
|
pub struct NSAP_PTR {
|
||||||
owner: DnsCanonicalName,
|
owner: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct SIG {
|
pub struct SIG {
|
||||||
rr_type: Type,
|
rr_type: Type,
|
||||||
algorithm: u8,
|
algorithm: u8,
|
||||||
@ -186,8 +190,8 @@ pub struct SIG {
|
|||||||
signature: Base64RemainingBlob,
|
signature: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct KEY {
|
pub struct KEY {
|
||||||
flags: u16,
|
flags: u16,
|
||||||
protocol: u8,
|
protocol: u8,
|
||||||
@ -195,18 +199,24 @@ pub struct KEY {
|
|||||||
public_key: Base64RemainingBlob,
|
public_key: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class IN
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(IN)]
|
||||||
pub struct PX {
|
pub struct PX {
|
||||||
preference: u16,
|
preference: u16,
|
||||||
map822: DnsCanonicalName,
|
map822: DnsCanonicalName,
|
||||||
mapx400: DnsCanonicalName,
|
mapx400: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub struct GPOS;
|
|
||||||
|
|
||||||
// class IN
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)] // not restricted in rfc 1712
|
||||||
|
pub struct GPOS {
|
||||||
|
longitude: ShortText,
|
||||||
|
latitude: ShortText,
|
||||||
|
altitude: ShortText,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(IN)]
|
||||||
pub struct AAAA {
|
pub struct AAAA {
|
||||||
addr: Ipv6Addr,
|
addr: Ipv6Addr,
|
||||||
}
|
}
|
||||||
@ -214,16 +224,22 @@ pub struct AAAA {
|
|||||||
pub use super::weird_structs::LOC;
|
pub use super::weird_structs::LOC;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct NXT {
|
pub struct NXT {
|
||||||
next: DnsCanonicalName,
|
next: DnsCanonicalName,
|
||||||
types: NxtTypeBitmap,
|
types: NxtTypeBitmap,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct EID;
|
// pub struct EID;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct NIMLOC;
|
// pub struct NIMLOC;
|
||||||
|
|
||||||
// class IN
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(IN)]
|
||||||
pub struct SRV {
|
pub struct SRV {
|
||||||
preference: u16,
|
preference: u16,
|
||||||
weight: u16,
|
weight: u16,
|
||||||
@ -231,10 +247,12 @@ pub struct SRV {
|
|||||||
target: DnsCanonicalName,
|
target: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct ATMA;
|
// pub struct ATMA;
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct NAPTR {
|
pub struct NAPTR {
|
||||||
order: u16,
|
order: u16,
|
||||||
preference: u16,
|
preference: u16,
|
||||||
@ -244,15 +262,15 @@ pub struct NAPTR {
|
|||||||
replacement: DnsCanonicalName,
|
replacement: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class IN
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(IN)]
|
||||||
pub struct KX {
|
pub struct KX {
|
||||||
preference: u16,
|
preference: u16,
|
||||||
exchanger: DnsCanonicalName,
|
exchanger: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class ??
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
pub struct CERT {
|
pub struct CERT {
|
||||||
cert_type: u16,
|
cert_type: u16,
|
||||||
key_tag: u16,
|
key_tag: u16,
|
||||||
@ -262,21 +280,26 @@ pub struct CERT {
|
|||||||
|
|
||||||
pub use super::weird_structs::A6;
|
pub use super::weird_structs::A6;
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct DNAME {
|
pub struct DNAME {
|
||||||
target: DnsCanonicalName,
|
target: DnsCanonicalName,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct SINK;
|
// pub struct SINK;
|
||||||
|
|
||||||
// OPT should be decoded at "transport level", abuses ttl and class
|
// OPT should be decoded at "transport level", abuses ttl and class
|
||||||
// fields too.
|
// fields too.
|
||||||
// pub struct OPT;
|
// pub struct OPT;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct APL;
|
// pub struct APL;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct DS {
|
pub struct DS {
|
||||||
key_tag: u16,
|
key_tag: u16,
|
||||||
algorithm: u8,
|
algorithm: u8,
|
||||||
@ -285,6 +308,7 @@ pub struct DS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
pub struct SSHFP {
|
pub struct SSHFP {
|
||||||
algorithm: u8,
|
algorithm: u8,
|
||||||
fingerprint_type: u8,
|
fingerprint_type: u8,
|
||||||
@ -294,10 +318,11 @@ pub struct SSHFP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct IPSECKEY;
|
// pub struct IPSECKEY;
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct RRSIG {
|
pub struct RRSIG {
|
||||||
rr_type: Type,
|
rr_type: Type,
|
||||||
algorithm: u8,
|
algorithm: u8,
|
||||||
@ -310,15 +335,15 @@ pub struct RRSIG {
|
|||||||
signature: Base64RemainingBlob,
|
signature: Base64RemainingBlob,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct NSEC {
|
pub struct NSEC {
|
||||||
next: DnsCanonicalName,
|
next: DnsName, // RFC 6840 says not canonic (updates RFC 4034)
|
||||||
types: NsecTypeBitmap,
|
types: NsecTypeBitmap,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct DNSKEY {
|
pub struct DNSKEY {
|
||||||
flags: u16,
|
flags: u16,
|
||||||
protocol: u8,
|
protocol: u8,
|
||||||
@ -327,10 +352,11 @@ pub struct DNSKEY {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct DHCID;
|
// pub struct DHCID;
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct NSEC3 {
|
pub struct NSEC3 {
|
||||||
hash_algorithm: u8,
|
hash_algorithm: u8,
|
||||||
flags: u8,
|
flags: u8,
|
||||||
@ -340,8 +366,8 @@ pub struct NSEC3 {
|
|||||||
types: NsecTypeBitmap,
|
types: NsecTypeBitmap,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct NSEC3PARAM {
|
pub struct NSEC3PARAM {
|
||||||
hash_algorithm: u8,
|
hash_algorithm: u8,
|
||||||
flags: u8,
|
flags: u8,
|
||||||
@ -350,63 +376,103 @@ pub struct NSEC3PARAM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct TLSA;
|
// pub struct TLSA;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct SMIMEA;
|
// pub struct SMIMEA;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct HIP;
|
// pub struct HIP;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct NINFO;
|
// pub struct NINFO;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct RKEY;
|
// pub struct RKEY;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct TALINK;
|
// pub struct TALINK;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct CDS;
|
// pub struct CDS;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct CDNSKEY;
|
// pub struct CDNSKEY;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct OPENPGPKEY;
|
// pub struct OPENPGPKEY;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct CSYNC;
|
// pub struct CSYNC;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
pub struct SPF {
|
pub struct SPF {
|
||||||
text: LongText,
|
text: LongText,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct UINFO;
|
// pub struct UINFO;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct UID;
|
// pub struct UID;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct GID;
|
// pub struct GID;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct UNSPEC;
|
// pub struct UNSPEC;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct NID;
|
// pub struct NID;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct L32;
|
// pub struct L32;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct L64;
|
// pub struct L64;
|
||||||
|
|
||||||
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct LP;
|
// pub struct LP;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct EUI48;
|
// pub struct EUI48;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct EUI64;
|
// pub struct EUI64;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct TKEY;
|
// pub struct TKEY;
|
||||||
|
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
// pub struct TSIG;
|
// pub struct TSIG;
|
||||||
|
|
||||||
// pub struct IXFR; // qtype only?
|
// QTYPEs: IXFR, AXFR, MAILB, MAILA, ANY
|
||||||
// pub struct AXFR; // qtype only?
|
|
||||||
// pub struct MAILB; // qtype only?
|
|
||||||
// pub struct MAILA; // qtype only?
|
|
||||||
// pub struct ANY; // qtype only?
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub struct URI {
|
pub struct URI {
|
||||||
priority: u16,
|
priority: u16,
|
||||||
weight: u16,
|
weight: u16,
|
||||||
@ -414,6 +480,7 @@ pub struct URI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
|
// #[RRClass(?)]
|
||||||
pub struct CAA {
|
pub struct CAA {
|
||||||
flags: u8,
|
flags: u8,
|
||||||
tag: UnquotedShortText,
|
tag: UnquotedShortText,
|
||||||
@ -426,7 +493,9 @@ pub struct CAA {
|
|||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
// pub struct DLV;
|
// pub struct DLV;
|
||||||
|
|
||||||
// pub struct ADDR;
|
// powerdns
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
#[RRClass(IN)] // used to lookup A and AAAA - only useful in IN
|
||||||
// pub struct ALIAS;
|
pub struct ALIAS {
|
||||||
|
content: DnsName,
|
||||||
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use bytes::{Bytes, Buf};
|
use bytes::{Bytes, Buf};
|
||||||
|
use common_types::classes;
|
||||||
use failure::ResultExt;
|
use failure::ResultExt;
|
||||||
use records::structs;
|
use records::structs;
|
||||||
use ser::{packet, text, StaticRRData};
|
use ser::{packet, text, StaticRRData};
|
||||||
@ -10,7 +11,7 @@ where
|
|||||||
T: StaticRRData
|
T: StaticRRData
|
||||||
{
|
{
|
||||||
let mut data = Cursor::new(Bytes::from_static(data));
|
let mut data = Cursor::new(Bytes::from_static(data));
|
||||||
let result = T::deserialize_rr_data(3600, 0x0001, T::TYPE, &mut data)?;
|
let result = T::deserialize_rr_data(3600, classes::IN, T::TYPE, &mut data)?;
|
||||||
ensure!(!data.has_remaining(), "rrdata not read completely");
|
ensure!(!data.has_remaining(), "rrdata not read completely");
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use common_types::*;
|
use common_types::*;
|
||||||
use failure::{ResultExt, Fail};
|
|
||||||
use ser::text::{DnsTextFormatter, next_field};
|
|
||||||
use ser::packet::remaining_bytes;
|
|
||||||
use common_types::binary::HEXLOWER_PERMISSIVE_ALLOW_WS;
|
use common_types::binary::HEXLOWER_PERMISSIVE_ALLOW_WS;
|
||||||
use std::fmt;
|
|
||||||
use errors::*;
|
use errors::*;
|
||||||
|
use failure::{ResultExt, Fail};
|
||||||
|
use ser::packet::remaining_bytes;
|
||||||
|
use ser::RRDataPacket;
|
||||||
|
use ser::text::{DnsTextFormatter, next_field};
|
||||||
|
use std::fmt;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
pub struct UnknownRecord {
|
pub struct UnknownRecord {
|
||||||
@ -45,3 +47,9 @@ impl UnknownRecord {
|
|||||||
write!(f, "TYPE{} \\# {} {}", self.rr_type.0, self.raw.len(), HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.raw))
|
write!(f, "TYPE{} \\# {} {}", self.rr_type.0, self.raw.len(), HEXLOWER_PERMISSIVE_ALLOW_WS.encode(&self.raw))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl RRDataPacket for UnknownRecord {
|
||||||
|
fn deserialize_rr_data(_ttl: u32, _rr_class: Class, rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self> {
|
||||||
|
UnknownRecord::deserialize(rr_type, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,8 +11,8 @@ use std::net::Ipv6Addr;
|
|||||||
// registered; there must be a records::types::$name `Type` constant
|
// registered; there must be a records::types::$name `Type` constant
|
||||||
// with the same name as the struct.
|
// with the same name as the struct.
|
||||||
|
|
||||||
// class independent
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
|
||||||
|
#[RRClass(ANY)]
|
||||||
pub enum LOC {
|
pub enum LOC {
|
||||||
Version0(LOC0),
|
Version0(LOC0),
|
||||||
UnknownVersion{
|
UnknownVersion{
|
||||||
@ -56,8 +56,8 @@ pub struct LOC0 {
|
|||||||
altitude: u32,
|
altitude: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// class IN
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
|
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
|
||||||
|
#[RRClass(IN)]
|
||||||
pub struct A6 {
|
pub struct A6 {
|
||||||
prefix: u8, // [0...128]
|
prefix: u8, // [0...128]
|
||||||
// might include non-zero padding
|
// might include non-zero padding
|
||||||
|
@ -1,24 +1,54 @@
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use common_types::Type;
|
use common_types::{Class, Type};
|
||||||
|
use common_types::classes;
|
||||||
use errors::*;
|
use errors::*;
|
||||||
use std::io::Cursor;
|
|
||||||
use ser::DnsPacketData;
|
use ser::DnsPacketData;
|
||||||
|
use ser::text::{DnsTextData, DnsTextFormatter};
|
||||||
|
use std::fmt;
|
||||||
|
use std::io::Cursor;
|
||||||
|
|
||||||
pub trait RRDataPacket: Sized {
|
pub trait RRDataPacket {
|
||||||
fn deserialize_rr_data(ttl: u32, rr_class: u16, rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self>;
|
fn deserialize_rr_data(ttl: u32, rr_class: Class, rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: DnsPacketData> RRDataPacket for T {
|
impl<T: DnsPacketData + StaticRRData> RRDataPacket for T {
|
||||||
fn deserialize_rr_data(_ttl: u32, _rr_class: u16, _rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self> {
|
fn deserialize_rr_data(_ttl: u32, rr_class: Class, rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self> {
|
||||||
|
ensure!(rr_type == T::TYPE, "type mismatch");
|
||||||
|
if T::CLASS != classes::ANY {
|
||||||
|
ensure!(rr_class == T::CLASS, "class mismatch");
|
||||||
|
}
|
||||||
T::deserialize(data)
|
T::deserialize(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RRData: RRDataPacket + super::DnsTextData {
|
pub trait RRDataText: Sized {
|
||||||
|
fn dns_parse_rr_data(ttl: u32, rr_class: Class, rr_type: Type, data: &mut &str) -> Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
;
|
||||||
|
|
||||||
|
// format might fail if there is no (known) text representation.
|
||||||
|
fn dns_format_rr_data(&self, f: &mut DnsTextFormatter) -> fmt::Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl<T: DnsTextData> RRDataText for T {
|
||||||
|
fn deserialize_rr_data(_ttl: u32, _rr_class: Class, _rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self> {
|
||||||
|
T::deserialize(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub trait RRData: RRDataPacket + DnsTextData {
|
||||||
fn rr_type(&self) -> Type;
|
fn rr_type(&self) -> Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait StaticRRData: RRData {
|
pub trait StaticRRData: RRData {
|
||||||
const TYPE: Type;
|
const TYPE: Type;
|
||||||
const NAME: &'static str;
|
const NAME: &'static str;
|
||||||
|
// classes::ANY marks class independent types
|
||||||
|
const CLASS: Class;
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,11 @@ impl<'a> DnsTextFormatter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DnsTextData: Sized {
|
pub trait DnsTextData {
|
||||||
fn dns_parse(data: &mut &str) -> ::errors::Result<Self>;
|
fn dns_parse(data: &mut &str) -> ::errors::Result<Self>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
;
|
||||||
// format might fail if there is no (known) text representation.
|
// format might fail if there is no (known) text representation.
|
||||||
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result;
|
fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ pub fn derive_dns_text_data(input: TokenStream) -> TokenStream {
|
|||||||
gen.parse().unwrap()
|
gen.parse().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(RRData, attributes(RRTypeName))]
|
#[proc_macro_derive(RRData, attributes(RRTypeName, RRClass))]
|
||||||
pub fn derive_rr_data(input: TokenStream) -> TokenStream {
|
pub fn derive_rr_data(input: TokenStream) -> TokenStream {
|
||||||
let s = input.to_string();
|
let s = input.to_string();
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ use super::{attr_get_single_list_arg};
|
|||||||
#[derive(Clone,Debug)]
|
#[derive(Clone,Debug)]
|
||||||
enum StructAttribute {
|
enum StructAttribute {
|
||||||
RRTypeName(quote::Tokens),
|
RRTypeName(quote::Tokens),
|
||||||
|
RRClass(quote::Tokens),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct StructAttributeParser<'a>(pub &'a [syn::Attribute]);
|
struct StructAttributeParser<'a>(pub &'a [syn::Attribute]);
|
||||||
@ -21,6 +22,9 @@ impl<'a> Iterator for StructAttributeParser<'a> {
|
|||||||
"RRTypeName" => {
|
"RRTypeName" => {
|
||||||
return Some(StructAttribute::RRTypeName(attr_get_single_list_arg(a)));
|
return Some(StructAttribute::RRTypeName(attr_get_single_list_arg(a)));
|
||||||
},
|
},
|
||||||
|
"RRClass" => {
|
||||||
|
return Some(StructAttribute::RRClass(attr_get_single_list_arg(a)));
|
||||||
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,19 +46,29 @@ pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let name = &ast.ident;
|
let name = &ast.ident;
|
||||||
let mut name_str = {
|
|
||||||
let name_str: &str = name.as_ref();
|
let mut name_str = None;
|
||||||
quote!{#name_str}
|
let mut rr_class = None;
|
||||||
};
|
|
||||||
|
|
||||||
for attr in StructAttributeParser(&ast.attrs) {
|
for attr in StructAttributeParser(&ast.attrs) {
|
||||||
match attr {
|
match attr {
|
||||||
StructAttribute::RRTypeName(name) => {
|
StructAttribute::RRTypeName(name) => {
|
||||||
name_str = name;
|
assert_eq!(name_str, None, "only one RRTypeName attribute allowed");
|
||||||
|
name_str = Some(name);
|
||||||
|
},
|
||||||
|
StructAttribute::RRClass(c) => {
|
||||||
|
assert_eq!(rr_class, None, "only one RRTypeName attribute allowed");
|
||||||
|
rr_class = Some(c);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let name_str = name_str.unwrap_or_else(|| {
|
||||||
|
let name_str: &str = name.as_ref();
|
||||||
|
quote!{#name_str}
|
||||||
|
});
|
||||||
|
let rr_class = rr_class.unwrap_or_else(|| quote!{ANY});
|
||||||
|
|
||||||
let test_mod_name = syn::Ident::from(format!("test_rr_{}", name));
|
let test_mod_name = syn::Ident::from(format!("test_rr_{}", name));
|
||||||
|
|
||||||
quote!{
|
quote!{
|
||||||
@ -67,6 +81,7 @@ pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
|||||||
impl ::dnsbox_base::ser::StaticRRData for #name {
|
impl ::dnsbox_base::ser::StaticRRData for #name {
|
||||||
const TYPE: ::dnsbox_base::common_types::Type = ::dnsbox_base::common_types::types::#name;
|
const TYPE: ::dnsbox_base::common_types::Type = ::dnsbox_base::common_types::types::#name;
|
||||||
const NAME: &'static str = #name_str;
|
const NAME: &'static str = #name_str;
|
||||||
|
const CLASS: ::dnsbox_base::common_types::Class = ::dnsbox_base::common_types::classes::#rr_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[cfg(test)]
|
// #[cfg(test)]
|
||||||
@ -78,10 +93,7 @@ pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_registry() {
|
fn test_registry() {
|
||||||
assert_eq!(
|
registry::check_registration::<#name>();
|
||||||
registry::known_name_to_type(#name::NAME),
|
|
||||||
Some(types::#name)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user