rust-dnsbox/lib/dnsbox-base/src/common_types/rr_type/mod.rs

100 lines
2.6 KiB
Rust

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)
}
}