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 {
|
||||
// try to list "original" rfc
|
||||
IN = 0x0001, // RFC 1035
|
||||
// CS = 0x0002, // "CSNET"
|
||||
CH = 0x0003, // "Chaos"
|
||||
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 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let n = match *self {
|
||||
|
@ -5,14 +5,13 @@ pub mod classes;
|
||||
pub mod types;
|
||||
mod nsec;
|
||||
mod nxt;
|
||||
mod rr_type;
|
||||
mod time;
|
||||
mod uri;
|
||||
|
||||
pub use self::binary::{HexShortBlob, Base64RemainingBlob, HexRemainingBlob};
|
||||
pub use self::name::{DnsName, DnsCanonicalName, DnsCompressedName};
|
||||
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::text::{ShortText, LongText, UnquotedShortText, RemainingText};
|
||||
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 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 DNAME : Type = Type(KnownType::DNAME 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 DS : Type = Type(KnownType::DS 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 EUI48 : Type = Type(KnownType::EUI48 as u16);
|
||||
pub const EUI64 : Type = Type(KnownType::EUI64 as u16);
|
||||
pub const TKEY : Type = Type(KnownType::TKEY as u16);
|
||||
pub const TSIG : Type = Type(KnownType::TSIG as u16);
|
||||
pub const IXFR : Type = Type(KnownType::IXFR as u16);
|
||||
pub const AXFR : Type = Type(KnownType::AXFR as u16);
|
||||
pub const MAILB : Type = Type(KnownType::MAILB as u16);
|
||||
pub const MAILA : Type = Type(KnownType::MAILA as u16);
|
||||
pub const ANY : Type = Type(KnownType::ANY as u16);
|
||||
pub const TKEY : Type = Type(KnownMetaType::TKEY as u16);
|
||||
pub const TSIG : Type = Type(KnownMetaType::TSIG as u16);
|
||||
pub const IXFR : Type = Type(KnownQType::IXFR as u16);
|
||||
pub const AXFR : Type = Type(KnownQType::AXFR as u16);
|
||||
pub const MAILB : Type = Type(KnownQType::MAILB as u16);
|
||||
pub const MAILA : Type = Type(KnownQType::MAILA as u16);
|
||||
pub const ANY : Type = Type(KnownQType::ANY as u16);
|
||||
pub const URI : Type = Type(KnownType::URI as u16);
|
||||
pub const CAA : Type = Type(KnownType::CAA as u16);
|
||||
pub const AVC : Type = Type(KnownType::AVC 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 ADDR : Type = Type(KnownType::ADDR as u16);
|
||||
pub const ALIAS : Type = Type(KnownType::ALIAS as u16);
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
@ -132,7 +142,7 @@ pub enum KnownType {
|
||||
A6 = 0x0026, // RFC 2874
|
||||
DNAME = 0x0027, // RFC 6672
|
||||
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
|
||||
DS = 0x002b, // RFC 3658
|
||||
SSHFP = 0x002c, // RFC 4255
|
||||
@ -164,22 +174,219 @@ pub enum KnownType {
|
||||
LP = 0x006b, // RFC 6742
|
||||
EUI48 = 0x006c, // 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
|
||||
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
|
||||
AXFR = 0x00fc, // RFC 1035
|
||||
MAILB = 0x00fd, // RFC 1035
|
||||
MAILA = 0x00fe, // 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)]
|
||||
macro_rules! check_type {
|
||||
($t:ident, $dec:expr) => {
|
||||
@ -188,7 +395,7 @@ macro_rules! check_type {
|
||||
// compare decimal value
|
||||
assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t));
|
||||
// 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) => {
|
||||
@ -197,7 +404,7 @@ macro_rules! check_type {
|
||||
// compare decimal value
|
||||
assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t));
|
||||
// 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!(AVC , 258);
|
||||
check_type!(DOA , 259);
|
||||
check_type!(TA , 32768);
|
||||
check_type!(DLV , 32769);
|
||||
check_type!(ADDR , 65400);
|
||||
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::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use common_types::{Class, Type, types};
|
||||
use errors::*;
|
||||
use records::structs;
|
||||
use common_types::types;
|
||||
use common_types::Type;
|
||||
use ser::{RRData, StaticRRData};
|
||||
|
||||
// this should be enough for registered names
|
||||
const TYPE_NAME_MAX_LEN: usize = 16;
|
||||
|
||||
lazy_static!{
|
||||
static ref REGISTRY: Registry = Registry::init();
|
||||
}
|
||||
@ -15,31 +21,59 @@ fn registry() -> &'static 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> {
|
||||
let registry = registry();
|
||||
let t = name_to_type(name)?;
|
||||
let t = lookup_type_name(name)?;
|
||||
registry.type_parser.get(&t)?;
|
||||
|
||||
Some(t)
|
||||
}
|
||||
|
||||
pub fn name_to_type(name: &str) -> Option<Type> {
|
||||
let registry = registry();
|
||||
let &t = registry.names_to_type.get(name)?;
|
||||
Some(t)
|
||||
}
|
||||
|
||||
pub(crate) fn type_name(rrtype: Type) -> Option<&'static str> {
|
||||
pub(crate) fn lookup_type_to_name(rrtype: Type) -> Option<&'static str> {
|
||||
let registry = registry();
|
||||
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>);
|
||||
|
||||
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 {
|
||||
names_to_type: HashMap<String, Type>,
|
||||
// store (ascii) upper-case names.
|
||||
names_to_type: HashMap<Vec<u8>, Type>,
|
||||
type_names: HashMap<Type, String>,
|
||||
type_parser: HashMap<Type, ()>,
|
||||
type_parser: HashMap<Type, Box<RRDataTypeParse + Sync>>,
|
||||
// make sure registrations are in order
|
||||
prev_type: Option<Type>,
|
||||
}
|
||||
@ -79,7 +113,7 @@ impl Registry {
|
||||
r.register_known::<structs::SIG>();
|
||||
r.register_known::<structs::KEY>();
|
||||
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::LOC>();
|
||||
r.register_known::<structs::NXT>();
|
||||
@ -136,9 +170,12 @@ impl Registry {
|
||||
r.register_known::<structs::CAA>();
|
||||
r.register_unknown("AVC" , types::AVC);
|
||||
r.register_unknown("DOA" , types::DOA);
|
||||
r.register_unknown("TA" , types::TA);
|
||||
r.register_unknown("DLV" , types::DLV);
|
||||
r.register_unknown("ADDR" , types::ADDR);
|
||||
r.register_unknown("ALIAS" , types::ALIAS);
|
||||
r.register_known::<structs::ALIAS>();
|
||||
|
||||
// "ALL" could be an alias for the ANY type?
|
||||
// assert!(r.names_to_type.insert("ALL".into(), types::ANY).is_none());
|
||||
|
||||
r
|
||||
}
|
||||
@ -148,7 +185,9 @@ impl Registry {
|
||||
self.prev_type = Some(rrtype);
|
||||
let mut name: String = name.into();
|
||||
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);
|
||||
}
|
||||
|
||||
@ -156,10 +195,17 @@ impl Registry {
|
||||
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 name = T::NAME;
|
||||
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
|
||||
// with the same name as the struct.
|
||||
|
||||
// class IN
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(IN)]
|
||||
pub struct A {
|
||||
addr: Ipv4Addr,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct NS {
|
||||
nsdname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct MD {
|
||||
madname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct MF {
|
||||
madname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct CNAME {
|
||||
cname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct SOA {
|
||||
mname: DnsCompressedName,
|
||||
rname: DnsCompressedName,
|
||||
@ -49,84 +49,86 @@ pub struct SOA {
|
||||
minimum: u32,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct MB {
|
||||
madname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct MG {
|
||||
mgmname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct MR {
|
||||
newname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// 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
|
||||
// have to parse protocol and service names.
|
||||
//
|
||||
// class IN
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(IN)]
|
||||
// pub struct WKS {
|
||||
// address: Ipv4Addr,
|
||||
// protocol: u8,
|
||||
// bitmap: ..., // remaining bytes
|
||||
// }
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct PTR {
|
||||
ptrdname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct HINFO {
|
||||
cpu: ShortText,
|
||||
os: ShortText,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct MINFO {
|
||||
rmailbx: DnsCompressedName,
|
||||
emailbx: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct MX {
|
||||
preference: u16,
|
||||
mxname: DnsCompressedName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct TXT {
|
||||
text: LongText,
|
||||
}
|
||||
|
||||
// end of RFC 1035: no DnsCompressedName below!
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct RP {
|
||||
mbox: DnsCanonicalName,
|
||||
txt: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct AFSDB {
|
||||
subtype: u16,
|
||||
hostname: DnsCanonicalName,
|
||||
@ -142,35 +144,37 @@ pub struct AFSDB {
|
||||
// least 4 bytes in the field: probably due to "beginning with the 4
|
||||
// digit DNIC").
|
||||
//
|
||||
// class independent
|
||||
// #[RRClass(ANY)]
|
||||
// pub struct X25 {
|
||||
// psdn_address: ShortText,
|
||||
// }
|
||||
|
||||
// class independent
|
||||
// #[RRClass(ANY)]
|
||||
// pub struct ISDN {
|
||||
// isdn_address: ShortText,
|
||||
// subaddress: Option<ShortText>,
|
||||
// }
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct RT {
|
||||
preference: u16,
|
||||
intermediate: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// #[RRClass(ANY)]
|
||||
// pub struct NSAP;
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRTypeName = "NSAP-PTR"]
|
||||
#[RRClass(ANY)]
|
||||
pub struct NSAP_PTR {
|
||||
owner: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct SIG {
|
||||
rr_type: Type,
|
||||
algorithm: u8,
|
||||
@ -186,8 +190,8 @@ pub struct SIG {
|
||||
signature: Base64RemainingBlob,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct KEY {
|
||||
flags: u16,
|
||||
protocol: u8,
|
||||
@ -195,18 +199,24 @@ pub struct KEY {
|
||||
public_key: Base64RemainingBlob,
|
||||
}
|
||||
|
||||
// class IN
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(IN)]
|
||||
pub struct PX {
|
||||
preference: u16,
|
||||
map822: DnsCanonicalName,
|
||||
mapx400: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// pub struct GPOS;
|
||||
|
||||
// class IN
|
||||
#[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 {
|
||||
addr: Ipv6Addr,
|
||||
}
|
||||
@ -214,16 +224,22 @@ pub struct AAAA {
|
||||
pub use super::weird_structs::LOC;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct NXT {
|
||||
next: DnsCanonicalName,
|
||||
types: NxtTypeBitmap,
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct EID;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct NIMLOC;
|
||||
|
||||
// class IN
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(IN)]
|
||||
pub struct SRV {
|
||||
preference: u16,
|
||||
weight: u16,
|
||||
@ -231,10 +247,12 @@ pub struct SRV {
|
||||
target: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct ATMA;
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct NAPTR {
|
||||
order: u16,
|
||||
preference: u16,
|
||||
@ -244,15 +262,15 @@ pub struct NAPTR {
|
||||
replacement: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// class IN
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(IN)]
|
||||
pub struct KX {
|
||||
preference: u16,
|
||||
exchanger: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// class ??
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
pub struct CERT {
|
||||
cert_type: u16,
|
||||
key_tag: u16,
|
||||
@ -262,21 +280,26 @@ pub struct CERT {
|
||||
|
||||
pub use super::weird_structs::A6;
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct DNAME {
|
||||
target: DnsCanonicalName,
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct SINK;
|
||||
|
||||
// OPT should be decoded at "transport level", abuses ttl and class
|
||||
// fields too.
|
||||
// pub struct OPT;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct APL;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct DS {
|
||||
key_tag: u16,
|
||||
algorithm: u8,
|
||||
@ -285,6 +308,7 @@ pub struct DS {
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
pub struct SSHFP {
|
||||
algorithm: u8,
|
||||
fingerprint_type: u8,
|
||||
@ -294,10 +318,11 @@ pub struct SSHFP {
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct IPSECKEY;
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct RRSIG {
|
||||
rr_type: Type,
|
||||
algorithm: u8,
|
||||
@ -310,15 +335,15 @@ pub struct RRSIG {
|
||||
signature: Base64RemainingBlob,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct NSEC {
|
||||
next: DnsCanonicalName,
|
||||
next: DnsName, // RFC 6840 says not canonic (updates RFC 4034)
|
||||
types: NsecTypeBitmap,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct DNSKEY {
|
||||
flags: u16,
|
||||
protocol: u8,
|
||||
@ -327,10 +352,11 @@ pub struct DNSKEY {
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct DHCID;
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct NSEC3 {
|
||||
hash_algorithm: u8,
|
||||
flags: u8,
|
||||
@ -340,8 +366,8 @@ pub struct NSEC3 {
|
||||
types: NsecTypeBitmap,
|
||||
}
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct NSEC3PARAM {
|
||||
hash_algorithm: u8,
|
||||
flags: u8,
|
||||
@ -350,63 +376,103 @@ pub struct NSEC3PARAM {
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct TLSA;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct SMIMEA;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct HIP;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct NINFO;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct RKEY;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct TALINK;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct CDS;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct CDNSKEY;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct OPENPGPKEY;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct CSYNC;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
pub struct SPF {
|
||||
text: LongText,
|
||||
}
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct UINFO;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct UID;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct GID;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct UNSPEC;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct NID;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct L32;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct L64;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct LP;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct EUI48;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct EUI64;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct TKEY;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
// pub struct TSIG;
|
||||
|
||||
// pub struct IXFR; // qtype only?
|
||||
// pub struct AXFR; // qtype only?
|
||||
// pub struct MAILB; // qtype only?
|
||||
// pub struct MAILA; // qtype only?
|
||||
// pub struct ANY; // qtype only?
|
||||
// QTYPEs: IXFR, AXFR, MAILB, MAILA, ANY
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub struct URI {
|
||||
priority: u16,
|
||||
weight: u16,
|
||||
@ -414,6 +480,7 @@ pub struct URI {
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// #[RRClass(?)]
|
||||
pub struct CAA {
|
||||
flags: u8,
|
||||
tag: UnquotedShortText,
|
||||
@ -426,7 +493,9 @@ pub struct CAA {
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// pub struct DLV;
|
||||
|
||||
// pub struct ADDR;
|
||||
|
||||
// #[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
// pub struct ALIAS;
|
||||
// powerdns
|
||||
#[derive(Clone, PartialEq, Eq, Debug, DnsPacketData, DnsTextData, RRData)]
|
||||
#[RRClass(IN)] // used to lookup A and AAAA - only useful in IN
|
||||
pub struct ALIAS {
|
||||
content: DnsName,
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
use bytes::{Bytes, Buf};
|
||||
use common_types::classes;
|
||||
use failure::ResultExt;
|
||||
use records::structs;
|
||||
use ser::{packet, text, StaticRRData};
|
||||
@ -10,7 +11,7 @@ where
|
||||
T: StaticRRData
|
||||
{
|
||||
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");
|
||||
Ok(result)
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
use bytes::Bytes;
|
||||
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 std::fmt;
|
||||
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)]
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// with the same name as the struct.
|
||||
|
||||
// class independent
|
||||
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
|
||||
#[RRClass(ANY)]
|
||||
pub enum LOC {
|
||||
Version0(LOC0),
|
||||
UnknownVersion{
|
||||
@ -56,8 +56,8 @@ pub struct LOC0 {
|
||||
altitude: u32,
|
||||
}
|
||||
|
||||
// class IN
|
||||
#[derive(Clone, PartialEq, Eq, Debug, RRData)]
|
||||
#[RRClass(IN)]
|
||||
pub struct A6 {
|
||||
prefix: u8, // [0...128]
|
||||
// might include non-zero padding
|
||||
|
@ -1,24 +1,54 @@
|
||||
use bytes::Bytes;
|
||||
use common_types::Type;
|
||||
use common_types::{Class, Type};
|
||||
use common_types::classes;
|
||||
use errors::*;
|
||||
use std::io::Cursor;
|
||||
use ser::DnsPacketData;
|
||||
use ser::text::{DnsTextData, DnsTextFormatter};
|
||||
use std::fmt;
|
||||
use std::io::Cursor;
|
||||
|
||||
pub trait RRDataPacket: Sized {
|
||||
fn deserialize_rr_data(ttl: u32, rr_class: u16, rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self>;
|
||||
pub trait RRDataPacket {
|
||||
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 {
|
||||
fn deserialize_rr_data(_ttl: u32, _rr_class: u16, _rr_type: Type, data: &mut Cursor<Bytes>) -> Result<Self> {
|
||||
impl<T: DnsPacketData + StaticRRData> RRDataPacket for T {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
pub trait StaticRRData: RRData {
|
||||
const TYPE: Type;
|
||||
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 {
|
||||
fn dns_parse(data: &mut &str) -> ::errors::Result<Self>;
|
||||
pub trait DnsTextData {
|
||||
fn dns_parse(data: &mut &str) -> ::errors::Result<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
;
|
||||
// format might fail if there is no (known) text representation.
|
||||
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()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(RRData, attributes(RRTypeName))]
|
||||
#[proc_macro_derive(RRData, attributes(RRTypeName, RRClass))]
|
||||
pub fn derive_rr_data(input: TokenStream) -> TokenStream {
|
||||
let s = input.to_string();
|
||||
|
||||
|
@ -6,6 +6,7 @@ use super::{attr_get_single_list_arg};
|
||||
#[derive(Clone,Debug)]
|
||||
enum StructAttribute {
|
||||
RRTypeName(quote::Tokens),
|
||||
RRClass(quote::Tokens),
|
||||
}
|
||||
|
||||
struct StructAttributeParser<'a>(pub &'a [syn::Attribute]);
|
||||
@ -21,6 +22,9 @@ impl<'a> Iterator for StructAttributeParser<'a> {
|
||||
"RRTypeName" => {
|
||||
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 mut name_str = {
|
||||
let name_str: &str = name.as_ref();
|
||||
quote!{#name_str}
|
||||
};
|
||||
|
||||
let mut name_str = None;
|
||||
let mut rr_class = None;
|
||||
|
||||
for attr in StructAttributeParser(&ast.attrs) {
|
||||
match attr {
|
||||
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));
|
||||
|
||||
quote!{
|
||||
@ -67,6 +81,7 @@ pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
||||
impl ::dnsbox_base::ser::StaticRRData for #name {
|
||||
const TYPE: ::dnsbox_base::common_types::Type = ::dnsbox_base::common_types::types::#name;
|
||||
const NAME: &'static str = #name_str;
|
||||
const CLASS: ::dnsbox_base::common_types::Class = ::dnsbox_base::common_types::classes::#rr_class;
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
@ -78,10 +93,7 @@ pub fn build(ast: &syn::DeriveInput) -> quote::Tokens {
|
||||
|
||||
#[test]
|
||||
fn test_registry() {
|
||||
assert_eq!(
|
||||
registry::known_name_to_type(#name::NAME),
|
||||
Some(types::#name)
|
||||
);
|
||||
registry::check_registration::<#name>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user