//! Types and constants for DNS TYPes use bytes::Bytes; use errors::*; use records::registry::{lookup_type_to_name, lookup_type_name}; use ser::packet::{DnsPacketData, DnsPacketWriteContext}; use ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field}; use std::borrow::Cow; use std::fmt; use std::io::Cursor; /// a host address pub const A : Type = Type(KnownType::A as u16); /// an authoritative name server pub const NS : Type = Type(KnownType::NS as u16); /// a mail destination (OBSOLETE - use MX) pub const MD : Type = Type(KnownType::MD as u16); /// a mail forwarder (OBSOLETE - use MX) pub const MF : Type = Type(KnownType::MF as u16); /// the canonical name for an alias pub const CNAME : Type = Type(KnownType::CNAME as u16); /// marks the start of a zone of authority pub const SOA : Type = Type(KnownType::SOA as u16); /// a mailbox domain name (EXPERIMENTAL) pub const MB : Type = Type(KnownType::MB as u16); /// a mail group member (EXPERIMENTAL) pub const MG : Type = Type(KnownType::MG as u16); /// a mail rename domain name (EXPERIMENTAL) pub const MR : Type = Type(KnownType::MR as u16); /// a null RR (EXPERIMENTAL) pub const NULL : Type = Type(KnownType::NULL as u16); /// a well known service description pub const WKS : Type = Type(KnownType::WKS as u16); /// a domain name pointer pub const PTR : Type = Type(KnownType::PTR as u16); /// host information pub const HINFO : Type = Type(KnownType::HINFO as u16); /// mailbox or mail list information pub const MINFO : Type = Type(KnownType::MINFO as u16); /// mail exchange pub const MX : Type = Type(KnownType::MX as u16); /// text strings pub const TXT : Type = Type(KnownType::TXT as u16); /// for Responsible Person pub const RP : Type = Type(KnownType::RP as u16); /// for AFS Data Base location pub const AFSDB : Type = Type(KnownType::AFSDB as u16); /// for X.25 PSDN address pub const X25 : Type = Type(KnownType::X25 as u16); /// for ISDN address pub const ISDN : Type = Type(KnownType::ISDN as u16); /// for Route Through pub const RT : Type = Type(KnownType::RT as u16); /// for NSAP address, NSAP style A record pub const NSAP : Type = Type(KnownType::NSAP as u16); /// for domain name pointer, NSAP style pub const NSAP_PTR : Type = Type(KnownType::NSAP_PTR as u16); /// for security signature pub const SIG : Type = Type(KnownType::SIG as u16); /// for security key pub const KEY : Type = Type(KnownType::KEY as u16); /// X.400 mail mapping information pub const PX : Type = Type(KnownType::PX as u16); /// Geographical Position pub const GPOS : Type = Type(KnownType::GPOS as u16); /// IP6 Address pub const AAAA : Type = Type(KnownType::AAAA as u16); /// Location Information pub const LOC : Type = Type(KnownType::LOC as u16); /// Next Domain (OBSOLETE) pub const NXT : Type = Type(KnownType::NXT as u16); /// Endpoint Identifier pub const EID : Type = Type(KnownType::EID as u16); /// Nimrod Locator pub const NIMLOC : Type = Type(KnownType::NIMLOC as u16); /// Server Selection pub const SRV : Type = Type(KnownType::SRV as u16); /// ATM Address pub const ATMA : Type = Type(KnownType::ATMA as u16); /// Naming Authority Pointer pub const NAPTR : Type = Type(KnownType::NAPTR as u16); /// Key Exchanger pub const KX : Type = Type(KnownType::KX as u16); /// CERT pub const CERT : Type = Type(KnownType::CERT as u16); /// A6 (OBSOLETE - use AAAA) pub const A6 : Type = Type(KnownType::A6 as u16); /// DNAME pub const DNAME : Type = Type(KnownType::DNAME as u16); /// SINK pub const SINK : Type = Type(KnownType::SINK as u16); /// OPT pub const OPT : Type = Type(KnownMetaType::OPT as u16); /// APL pub const APL : Type = Type(KnownType::APL as u16); /// Delegation Signer pub const DS : Type = Type(KnownType::DS as u16); /// SSH Key Fingerprint pub const SSHFP : Type = Type(KnownType::SSHFP as u16); /// IPSECKEY pub const IPSECKEY : Type = Type(KnownType::IPSECKEY as u16); /// RRSIG pub const RRSIG : Type = Type(KnownType::RRSIG as u16); /// NSEC pub const NSEC : Type = Type(KnownType::NSEC as u16); /// DNSKEY pub const DNSKEY : Type = Type(KnownType::DNSKEY as u16); /// DHCID pub const DHCID : Type = Type(KnownType::DHCID as u16); /// NSEC3 pub const NSEC3 : Type = Type(KnownType::NSEC3 as u16); /// NSEC3PARAM pub const NSEC3PARAM : Type = Type(KnownType::NSEC3PARAM as u16); /// TLSA pub const TLSA : Type = Type(KnownType::TLSA as u16); /// S/MIME cert association pub const SMIMEA : Type = Type(KnownType::SMIMEA as u16); /// Host Identity Protocol pub const HIP : Type = Type(KnownType::HIP as u16); /// NINFO pub const NINFO : Type = Type(KnownType::NINFO as u16); /// RKEY pub const RKEY : Type = Type(KnownType::RKEY as u16); /// Trust Anchor LINK pub const TALINK : Type = Type(KnownType::TALINK as u16); /// Child DS pub const CDS : Type = Type(KnownType::CDS as u16); /// DNSKEY(s) the Child wants reflected in DS pub const CDNSKEY : Type = Type(KnownType::CDNSKEY as u16); /// OpenPGP Key pub const OPENPGPKEY : Type = Type(KnownType::OPENPGPKEY as u16); /// Child-To-Parent Synchronization pub const CSYNC : Type = Type(KnownType::CSYNC as u16); /// SPF pub const SPF : Type = Type(KnownType::SPF as u16); /// UINFO pub const UINFO : Type = Type(KnownType::UINFO as u16); /// UID pub const UID : Type = Type(KnownType::UID as u16); /// GID pub const GID : Type = Type(KnownType::GID as u16); /// UNSPEC pub const UNSPEC : Type = Type(KnownType::UNSPEC as u16); /// NID pub const NID : Type = Type(KnownType::NID as u16); /// L32 pub const L32 : Type = Type(KnownType::L32 as u16); /// L64 pub const L64 : Type = Type(KnownType::L64 as u16); /// LP pub const LP : Type = Type(KnownType::LP as u16); /// an EUI-48 address pub const EUI48 : Type = Type(KnownType::EUI48 as u16); /// an EUI-64 address pub const EUI64 : Type = Type(KnownType::EUI64 as u16); /// Transaction Key pub const TKEY : Type = Type(KnownMetaType::TKEY as u16); /// Transaction Signature pub const TSIG : Type = Type(KnownMetaType::TSIG as u16); /// incremental transfer pub const IXFR : Type = Type(KnownQType::IXFR as u16); /// transfer of an entire zone pub const AXFR : Type = Type(KnownQType::AXFR as u16); /// mailbox-related RRs (MB, MG or MR) pub const MAILB : Type = Type(KnownQType::MAILB as u16); /// mail agent RRs (OBSOLETE - see MX) pub const MAILA : Type = Type(KnownQType::MAILA as u16); /// "*", a request for all records the server/cache has available pub const ANY : Type = Type(KnownQType::ANY as u16); /// URI pub const URI : Type = Type(KnownType::URI as u16); /// Certification Authority Restriction pub const CAA : Type = Type(KnownType::CAA as u16); /// Application Visibility and Control pub const AVC : Type = Type(KnownType::AVC as u16); /// Digital Object Architecture pub const DOA : Type = Type(KnownType::DOA as u16); /// DNSSEC Trust Authorities pub const TA : Type = Type(KnownType::TA as u16); /// DNSSEC Lookaside Validation pub const DLV : Type = Type(KnownType::DLV as u16); /// powerdns feature: authoritate should resolve to A and AAAA pub const ALIAS : Type = Type(KnownType::ALIAS as u16); /// known data TYPEs #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum KnownType { // try to list "original" rfc /// a host address A = 0x0001, // RFC 1035 /// an authoritative name server NS = 0x0002, // RFC 1035 /// a mail destination (OBSOLETE - use MX) MD = 0x0003, // RFC 1035 /// a mail forwarder (OBSOLETE - use MX) MF = 0x0004, // RFC 1035 /// the canonical name for an alias CNAME = 0x0005, // RFC 1035 /// marks the start of a zone of authority SOA = 0x0006, // RFC 1035 /// a mailbox domain name (EXPERIMENTAL) MB = 0x0007, // RFC 1035 /// a mail group member (EXPERIMENTAL) MG = 0x0008, // RFC 1035 /// a mail rename domain name (EXPERIMENTAL) MR = 0x0009, // RFC 1035 /// a null RR (EXPERIMENTAL) NULL = 0x000a, // RFC 1035 /// a well known service description WKS = 0x000b, // RFC 1035 /// a domain name pointer PTR = 0x000c, // RFC 1035 /// host information HINFO = 0x000d, // RFC 1035 /// mailbox or mail list information MINFO = 0x000e, // RFC 1035 /// mail exchange MX = 0x000f, // RFC 1035 /// text strings TXT = 0x0010, // RFC 1035 /// for Responsible Person RP = 0x0011, // RFC 1183 /// for AFS Data Base location AFSDB = 0x0012, // RFC 1183 /// for X.25 PSDN address X25 = 0x0013, // RFC 1183 /// for ISDN address ISDN = 0x0014, // RFC 1183 /// for Route Through RT = 0x0015, // RFC 1183 /// for NSAP address, NSAP style A record NSAP = 0x0016, // RFC 1706 /// for domain name pointer, NSAP style NSAP_PTR = 0x0017, // RFC 1348 /// for security signature SIG = 0x0018, // RFC 2535 /// for security key KEY = 0x0019, // RFC 2535 /// X.400 mail mapping information PX = 0x001a, // RFC 2163 /// Geographical Position GPOS = 0x001b, // RFC 1712 /// IP6 Address AAAA = 0x001c, // RFC 3596 /// Location Information LOC = 0x001d, // RFC 1876 /// Next Domain (OBSOLETE) NXT = 0x001e, // RFC 2535 /// Endpoint Identifier EID = 0x001f, // Michael Patton: http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt /// Nimrod Locator NIMLOC = 0x0020, // Michael Patton: http://ana-3.lcs.mit.edu/~jnc/nimrod/dns.txt /// Server Selection SRV = 0x0021, // RFC 2782 /// ATM Address ATMA = 0x0022, // http://www.broadband-forum.org/ftp/pub/approved-specs/af-dans-0152.000.pdf /// Naming Authority Pointer NAPTR = 0x0023, // RFC 2168 /// Key Exchanger KX = 0x0024, // RFC 2230 /// CERT CERT = 0x0025, // RFC 4398 /// A6 (OBSOLETE - use AAAA) A6 = 0x0026, // RFC 2874 /// DNAME DNAME = 0x0027, // RFC 6672 /// SINK SINK = 0x0028, // Donald E Eastlake: http://tools.ietf.org/html/draft-eastlake-kitchen-sink // OPT (0x0029) is a meta type /// APL APL = 0x002a, // RFC 3123 /// Delegation Signer DS = 0x002b, // RFC 3658 /// SSH Key Fingerprint SSHFP = 0x002c, // RFC 4255 /// IPSECKEY IPSECKEY = 0x002d, // RFC 4025 /// RRSIG RRSIG = 0x002e, // RFC 4034 /// NSEC NSEC = 0x002f, // RFC 4034 /// DNSKEY DNSKEY = 0x0030, // RFC 4034 /// DHCID DHCID = 0x0031, // RFC 4701 /// NSEC3 NSEC3 = 0x0032, // RFC 5155 /// NSEC3PARAM NSEC3PARAM = 0x0033, // RFC 5155 /// TLSA TLSA = 0x0034, // RFC 6698 /// S/MIME cert association SMIMEA = 0x0035, // RFC 8162 /// Host Identity Protocol HIP = 0x0037, // RFC 8005 /// NINFO NINFO = 0x0038, // Jim Reid: https://tools.ietf.org/html/draft-reid-dnsext-zs-01 /// RKEY RKEY = 0x0039, // Jim Reid: https://tools.ietf.org/html/draft-reid-dnsext-rkey-00 /// Trust Anchor LINK TALINK = 0x003a, // Wouter Wijngaards /// Child DS CDS = 0x003b, // RFC 7344 /// DNSKEY(s) the Child wants reflected in DS CDNSKEY = 0x003c, // RFC 7344 /// OpenPGP Key OPENPGPKEY = 0x003d, // RFC 7929 /// Child-To-Parent Synchronization CSYNC = 0x003e, // RFC 7477 /// SPF SPF = 0x0063, // RFC 7208 /// UINFO UINFO = 0x0064, // IANA-Reserved /// UID UID = 0x0065, // IANA-Reserved /// GID GID = 0x0066, // IANA-Reserved /// UNSPEC UNSPEC = 0x0067, // IANA-Reserved /// NID NID = 0x0068, // RFC 6742 /// L32 L32 = 0x0069, // RFC 6742 /// L64 L64 = 0x006a, // RFC 6742 /// LP LP = 0x006b, // RFC 6742 /// an EUI-48 address EUI48 = 0x006c, // RFC 7043 /// an EUI-64 address EUI64 = 0x006d, // RFC 7043 // 0x0080..0x00ff: meta and qtypes /// URI URI = 0x0100, // RFC 7553 /// Certification Authority Restriction CAA = 0x0101, // RFC 6844 /// Application Visibility and Control AVC = 0x0102, // Wolfgang Riedel /// Digital Object Architecture DOA = 0x0103, // http://www.iana.org/go/draft-durand-doa-over-dns /// DNSSEC Trust Authorities TA = 0x8000, // /// DNSSEC Lookaside Validation DLV = 0x8001, // RFC 4431 /// powerdns feature: authoritate should resolve to A and AAAA ALIAS = 0xff79, // powerdns } /// known QTYPEs #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum KnownQType { /// incremental transfer IXFR = 0x00fb, // RFC 1995 /// transfer of an entire zone AXFR = 0x00fc, // RFC 1035 /// mailbox-related RRs (MB, MG or MR) MAILB = 0x00fd, // RFC 1035 /// mail agent RRs (OBSOLETE - see MX) MAILA = 0x00fe, // RFC 1035 /// "*", a request for all records the server/cache has available ANY = 0x00ff, // RFC 1035 } /// known Meta-TYPEs #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[repr(u16)] #[allow(non_camel_case_types)] pub enum KnownMetaType { /// OPT OPT = 0x0029, // RFC 6891 /// Transaction Key TKEY = 0x00f9, // RFC 2930 /// Transaction Signature TSIG = 0x00fa, // RFC 2845 } /// DNS (RR)TYPE /// /// Originally QTYPE was a superset of TYPE; RFC 6895 now defines: /// /// > There are three subcategories of RRTYPE numbers: data TYPEs, /// > QTYPEs, and Meta-TYPEs. /// /// ## `ANY` /// /// QTYPE 255 ("*") doesn't seem to have an official mnemonic; `ANY` is /// used in most tools though. /// /// The `ANY` mnemonic conflicts with the QCLASS `ANY` though; the name /// functions for `Class` have `_without_any` variants though. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct Type(pub u16); impl Type { /// whether TYPE is known or reserved to be a QTYPE or a Meta-TYPE. /// /// 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) } /// map to `KnownQType` pub fn known_qtype(self) -> Option { Some(match self { IXFR => KnownQType::IXFR, AXFR => KnownQType::AXFR, MAILB => KnownQType::MAILB, MAILA => KnownQType::MAILA, ANY => KnownQType::ANY, _ => return None, }) } /// whether TYPE is known to be a QTYPE pub fn is_known_qtype(self) -> bool { self.known_qtype().is_some() } /// map to `KnownMetaType` pub fn known_meta_type(self) -> Option { Some(match self { OPT => KnownMetaType::OPT, TKEY => KnownMetaType::TKEY, TSIG => KnownMetaType::TSIG, _ => return None, }) } /// whether TYPE is known to be a Meta-TYPE pub fn is_known_meta_type(self) -> bool { self.known_meta_type().is_some() } /// name for TYPE if known /// /// Known TYPEs are represented using their known mnemonic, others /// return None. pub fn known_name(self) -> Option<&'static str> { lookup_type_to_name(self) } /// name for TYPE /// /// Known TYPEes are represented using their known mnemonic, others /// using the "TYPE..." syntax (RFC 3597). pub fn name(self) -> Cow<'static, str> { match self.known_name() { Some(name) => Cow::Borrowed(name), None => Cow::Owned(self.generic_name()) } } /// generic name "TYPE..." pub fn generic_name(self) -> String { let mut result = String::new(); self.write_generic_name(&mut result).unwrap(); result } /// directly write generic name "TYPE..." to some target pub fn write_generic_name(self, w: &mut W) -> fmt::Result { write!(w, "TYPE{}", self.0) } /// parses known names (mnemonics) pub fn from_known_name(name: &str) -> Option { lookup_type_name(name) } /// parses generic names of the form "TYPE..." pub fn from_generic_name(name: &str) -> Option { use std::ascii::AsciiExt; if name.len() > 4 && name.as_bytes()[0..4].eq_ignore_ascii_case(b"TYPE") { name[4..].parse::().ok().map(Type) } else { None } } /// parses any name (mnemonics and "TYPE...") pub fn from_name(name: &str) -> Option { Self::from_generic_name(name).or_else(|| { Self::from_known_name(name) }) } /// whether TYPE is defined in RFC 1035 pub fn is_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). /// /// For DNSSEC name compression is forbidden too; all compressable /// TYPEs are included in the list anyway. /// /// See [RFC 4034 section 6.2][1] (obsoletes RFC 3597). Also /// updated by [RFC 6840 section 5.1][2]. /// /// [1]: https://tools.ietf.org/html/rfc4034#section-6.2 /// [2]: https://tools.ietf.org/html/rfc6840#section-5.1 pub fn use_canonical_names(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 for Type { fn from(value: KnownType) -> Self { Type(value as u16) } } impl From for Type { fn from(value: KnownQType) -> Self { Type(value as u16) } } impl From for Type { fn from(value: KnownMetaType) -> Self { Type(value as u16) } } impl fmt::Display for Type { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.known_name() { Some(name) => write!(f, "{}", name), None => self.write_generic_name(f), } } } impl DnsPacketData for Type { fn deserialize(data: &mut Cursor) -> Result { Ok(Type(DnsPacketData::deserialize(data)?)) } fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec) -> Result<()> { self.0.serialize(context, packet) } } impl DnsTextData for Type { fn dns_parse(_context: &DnsTextContext, data: &mut &str) -> Result { 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) => { { use records::registry; // compare decimal value assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t)); // make sure it's registered assert_eq!(registry::lookup_type_name(stringify!($t)), Some($t), "{} not registered", stringify!($t)); } }; ($t:ident, $dec:expr, $name:expr) => { { use records::registry; // compare decimal value assert_eq!($t, Type($dec), "wrong decimal value for {}", stringify!($t)); // make sure it's registered assert_eq!(registry::lookup_type_name($name), Some($t), "{} not registered as {:?}", stringify!($t), $name); } }; } // the IANA registry uses decimal numbers; make sure there were no typos // when converting them to hex in the constants above. // // also checks the registry has the name-to-number mapping. #[cfg(test)] #[test] fn check_types() { check_type!(A , 1); check_type!(NS , 2); check_type!(MD , 3); check_type!(MF , 4); check_type!(CNAME , 5); check_type!(SOA , 6); check_type!(MB , 7); check_type!(MG , 8); check_type!(MR , 9); check_type!(NULL , 10); check_type!(WKS , 11); check_type!(PTR , 12); check_type!(HINFO , 13); check_type!(MINFO , 14); check_type!(MX , 15); check_type!(TXT , 16); check_type!(RP , 17); check_type!(AFSDB , 18); check_type!(X25 , 19); check_type!(ISDN , 20); check_type!(RT , 21); check_type!(NSAP , 22); check_type!(NSAP_PTR , 23, "NSAP-PTR"); check_type!(SIG , 24); check_type!(KEY , 25); check_type!(PX , 26); check_type!(GPOS , 27); check_type!(AAAA , 28); check_type!(LOC , 29); check_type!(NXT , 30); check_type!(EID , 31); check_type!(NIMLOC , 32); check_type!(SRV , 33); check_type!(ATMA , 34); check_type!(NAPTR , 35); check_type!(KX , 36); check_type!(CERT , 37); check_type!(A6 , 38); check_type!(DNAME , 39); check_type!(SINK , 40); check_type!(OPT , 41); check_type!(APL , 42); check_type!(DS , 43); check_type!(SSHFP , 44); check_type!(IPSECKEY , 45); check_type!(RRSIG , 46); check_type!(NSEC , 47); check_type!(DNSKEY , 48); check_type!(DHCID , 49); check_type!(NSEC3 , 50); check_type!(NSEC3PARAM, 51); check_type!(TLSA , 52); check_type!(SMIMEA , 53); check_type!(HIP , 55); check_type!(NINFO , 56); check_type!(RKEY , 57); check_type!(TALINK , 58); check_type!(CDS , 59); check_type!(CDNSKEY , 60); check_type!(OPENPGPKEY, 61); check_type!(CSYNC , 62); check_type!(SPF , 99); check_type!(UINFO , 100); check_type!(UID , 101); check_type!(GID , 102); check_type!(UNSPEC , 103); check_type!(NID , 104); check_type!(L32 , 105); check_type!(L64 , 106); check_type!(LP , 107); check_type!(EUI48 , 108); check_type!(EUI64 , 109); check_type!(TKEY , 249); check_type!(TSIG , 250); check_type!(IXFR , 251); check_type!(AXFR , 252); check_type!(MAILB , 253); check_type!(MAILA , 254); check_type!(ANY , 255); check_type!(URI , 256); check_type!(CAA , 257); check_type!(AVC , 258); check_type!(DOA , 259); check_type!(TA , 32768); check_type!(DLV , 32769); check_type!(ALIAS , 65401); }