Skip to main content

dnssec_prover/
rr.rs

1//! Resource Records are the fundamental type in the DNS - individual records mapping a name to
2//! some data.
3//!
4//! This module holds structs and utilities for the Resource Records supported by this crate.
5
6use alloc::vec::Vec;
7use alloc::string::String;
8use alloc::borrow::ToOwned;
9use alloc::format;
10
11use core::cmp::Ordering;
12use core::fmt;
13use core::fmt::Write;
14use core::num::NonZeroU8;
15
16use crate::ser::*;
17
18pub(crate) fn name_ends_with_labels(name: &[u8], suffix: &str) -> bool {
19	if name.len() < suffix.len() { return false; }
20	if name.ends_with(b".") && suffix == "." { return true; }
21
22	let suffix_lowercase_bytes = suffix.bytes().map(|b| b.to_ascii_lowercase());
23	let name_suffix_lowercase =
24		name.iter().skip(name.len() - suffix.len()).map(|b| b.to_ascii_lowercase());
25	if !name_suffix_lowercase.eq(suffix_lowercase_bytes) {
26		return false;
27	}
28	if name.len() == suffix.len() {
29		return true;
30	}
31	name[name.len() - suffix.len() - 1] == b'.'
32}
33
34/// A valid host name.
35///
36/// It must end with a ".", be no longer than 255 bytes, consist of only the chars a-zA-Z0-9*.-_
37/// and each label may be no longer than 63 bytes.
38///
39/// Note that DNS allows for names to be any arbitrary byte string, but we restrict most instances
40/// to valid host names for practical purposes.
41#[derive(Debug, Clone, Hash, PartialEq, Eq)]
42pub struct Name(String);
43impl Name {
44	/// Gets the underlying human-readable domain name
45	pub fn as_str(&self) -> &str { &self.0 }
46	/// Gets the number of labels in this name
47	pub fn labels(&self) -> u8 {
48		if self.as_str() == "." {
49			0
50		} else {
51			self.as_str().chars().filter(|c| *c == '.').count() as u8
52		}
53	}
54	/// Gets a string containing the last `n` labels in this [`Name`] (which is also a valid name).
55	pub fn trailing_n_labels(&self, n: u8) -> Option<&str> {
56		let labels = self.labels();
57		if n > labels {
58			None
59		} else if n == labels {
60			Some(self.as_str())
61		} else if n == 0 {
62			Some(".")
63		} else {
64			self.as_str().splitn(labels as usize - n as usize + 1, '.').last()
65		}
66	}
67	/// Checks if the provided `suffix` is a suffix of `self`.
68	///
69	/// This is similar to `str::ends_with` but validates that the suffix is in terms of labels,
70	/// rather than raw characters.
71	pub fn ends_with_labels<N: core::ops::Deref<Target = str>>(&self, suffix: N) -> bool {
72		name_ends_with_labels(self.0.as_bytes(), &*suffix)
73	}
74}
75impl Ord for Name {
76	fn cmp(&self, o: &Name) -> Ordering {
77		// Name has several several orderings depending on the context. Here we default to sorting
78		// by the wire encoding so that RRs that contain a `Name` are sorted correctly. This is
79		// different from how freestanding `Name`s are sorted in the context of DNSSEC, which is
80		// handled in validation.rs.
81		let mut self_iter = self.0.split('.');
82		let mut o_iter = o.0.split('.');
83		loop {
84			match (self_iter.next(), o_iter.next()) {
85				(None, None) => return Ordering::Equal,
86				(Some(_), None) => return Ordering::Greater,
87				(None, Some(_)) => return Ordering::Less,
88				(Some(a_label), Some(b_label)) => {
89					let label_ord = a_label.len().cmp(&b_label.len())
90						.then_with(|| a_label.cmp(&b_label));
91					if label_ord != Ordering::Equal { return label_ord; }
92				},
93			}
94		}
95	}
96}
97impl PartialOrd for Name {
98	fn partial_cmp(&self, o: &Name) -> Option<Ordering> { Some(self.cmp(o)) }
99}
100impl core::ops::Deref for Name {
101	type Target = str;
102	fn deref(&self) -> &str { &self.0 }
103}
104impl fmt::Display for Name {
105	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
106		self.0.fmt(f)
107	}
108}
109impl TryFrom<String> for Name {
110	type Error = ();
111	fn try_from(s: String) -> Result<Name, ()> {
112		if s.is_empty() { return Err(()); }
113		if *s.as_bytes().last().unwrap_or(&0) != b"."[0] { return Err(()); }
114		if s.len() > 255 { return Err(()); }
115		if s.chars().any(|c| !['-', '.', '_', '*'].contains(&c) && (c < '0' || c > '9') && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')) {
116			return Err(());
117		}
118		for label in s.split('.') {
119			if label.len() > 63 { return Err(()); }
120		}
121
122		Ok(Name(s.to_ascii_lowercase()))
123	}
124}
125impl TryFrom<&str> for Name {
126	type Error = ();
127	fn try_from(s: &str) -> Result<Name, ()> {
128		Self::try_from(s.to_owned())
129	}
130}
131
132#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
133/// A supported Resource Record
134///
135/// Note that we only currently support a handful of RR types as needed to generate and validate
136/// TXT or TLSA record proofs.
137pub enum RR {
138	/// An IPv4 resource record
139	A(A),
140	/// An IPv6 resource record
141	AAAA(AAAA),
142	/// A name server resource record
143	NS(NS),
144	/// A text resource record
145	Txt(Txt),
146	/// A TLS Certificate Association resource record
147	TLSA(TLSA),
148	/// A Canonical Name record
149	CName(CName),
150	/// A Delegation Name record
151	DName(DName),
152	/// A DNS (Public) Key resource record
153	DnsKey(DnsKey),
154	/// A Delegated Signer resource record
155	DS(DS),
156	/// A Resource Record Signature record
157	RRSig(RRSig),
158	/// A Next Secure Record record
159	NSec(NSec),
160	/// A Next Secure Record version 3 record
161	NSec3(NSec3),
162}
163impl RR {
164	/// Gets the name this record refers to.
165	pub fn name(&self) -> &Name {
166		match self {
167			RR::A(rr) => &rr.name,
168			RR::AAAA(rr) => &rr.name,
169			RR::NS(rr) => &rr.name,
170			RR::Txt(rr) => &rr.name,
171			RR::CName(rr) => &rr.name,
172			RR::DName(rr) => &rr.name,
173			RR::TLSA(rr) => &rr.name,
174			RR::DnsKey(rr) => &rr.name,
175			RR::DS(rr) => &rr.name,
176			RR::RRSig(rr) => &rr.name,
177			RR::NSec(rr) => &rr.name,
178			RR::NSec3(rr) => &rr.name,
179		}
180	}
181	/// Gets a JSON encoding of this record
182	pub fn json(&self) -> String {
183		match self {
184			RR::A(rr) => StaticRecord::json(rr),
185			RR::AAAA(rr) => StaticRecord::json(rr),
186			RR::NS(rr) => StaticRecord::json(rr),
187			RR::Txt(rr) => StaticRecord::json(rr),
188			RR::CName(rr) => StaticRecord::json(rr),
189			RR::DName(rr) => StaticRecord::json(rr),
190			RR::TLSA(rr) => StaticRecord::json(rr),
191			RR::DnsKey(rr) => StaticRecord::json(rr),
192			RR::DS(rr) => StaticRecord::json(rr),
193			RR::RRSig(rr) => StaticRecord::json(rr),
194			RR::NSec(rr) => StaticRecord::json(rr),
195			RR::NSec3(rr) => StaticRecord::json(rr),
196		}
197	}
198	fn ty(&self) -> u16 {
199		match self {
200			RR::A(_) => A::TYPE,
201			RR::AAAA(_) => AAAA::TYPE,
202			RR::NS(_) => NS::TYPE,
203			RR::Txt(_) => Txt::TYPE,
204			RR::CName(_) => CName::TYPE,
205			RR::DName(_) => DName::TYPE,
206			RR::TLSA(_) => TLSA::TYPE,
207			RR::DnsKey(_) => DnsKey::TYPE,
208			RR::DS(_) => DS::TYPE,
209			RR::RRSig(_) => RRSig::TYPE,
210			RR::NSec(_) => NSec::TYPE,
211			RR::NSec3(_) => NSec3::TYPE,
212		}
213	}
214	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
215		match self {
216			RR::A(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
217			RR::AAAA(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
218			RR::NS(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
219			RR::Txt(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
220			RR::CName(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
221			RR::DName(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
222			RR::TLSA(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
223			RR::DnsKey(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
224			RR::DS(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
225			RR::RRSig(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
226			RR::NSec(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
227			RR::NSec3(rr) => StaticRecord::write_u16_len_prefixed_data(rr, out),
228		}
229	}
230	fn ty_to_rr_name(ty: u16) -> Option<&'static str> {
231		match ty {
232			A::TYPE => Some("A"),
233			AAAA::TYPE => Some("AAAA"),
234			NS::TYPE => Some("NS"),
235			Txt::TYPE => Some("TXT"),
236			CName::TYPE => Some("CNAME"),
237			DName::TYPE => Some("DNAME"),
238			TLSA::TYPE => Some("TLSA"),
239			DnsKey::TYPE => Some("DNSKEY"),
240			DS::TYPE => Some("DS"),
241			RRSig::TYPE => Some("RRSIG"),
242			NSec::TYPE => Some("NSEC"),
243			NSec3::TYPE => Some("NSEC3"),
244			_ => None,
245		}
246	}
247}
248impl From<A> for RR { fn from(a: A) -> RR { RR::A(a) } }
249impl From<AAAA> for RR { fn from(aaaa: AAAA) -> RR { RR::AAAA(aaaa) } }
250impl From<NS> for RR { fn from(ns: NS) -> RR { RR::NS(ns) } }
251impl From<Txt> for RR { fn from(txt: Txt) -> RR { RR::Txt(txt) } }
252impl From<CName> for RR { fn from(cname: CName) -> RR { RR::CName(cname) } }
253impl From<DName> for RR { fn from(cname: DName) -> RR { RR::DName(cname) } }
254impl From<TLSA> for RR { fn from(tlsa: TLSA) -> RR { RR::TLSA(tlsa) } }
255impl From<DnsKey> for RR { fn from(dnskey: DnsKey) -> RR { RR::DnsKey(dnskey) } }
256impl From<DS> for RR { fn from(ds: DS) -> RR { RR::DS(ds) } }
257impl From<RRSig> for RR { fn from(rrsig: RRSig) -> RR { RR::RRSig(rrsig) } }
258impl From<NSec> for RR { fn from(nsec: NSec) -> RR { RR::NSec(nsec) } }
259impl From<NSec3> for RR { fn from(nsec3: NSec3) -> RR { RR::NSec3(nsec3) } }
260
261pub(crate) trait StaticRecord : Ord + Sized {
262	// http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4
263	const TYPE: u16;
264	fn name(&self) -> &Name;
265	fn json(&self) -> String;
266	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W);
267	fn read_from_data(name: Name, data: &[u8], wire_packet: &[u8]) -> Result<Self, ()>;
268}
269
270/// A record that can be written to a generic [`Writer`]
271pub(crate) trait WriteableRecord : Record {
272	fn serialize_u16_len_prefixed<W: Writer>(&self, out: &mut W);
273}
274impl<RR: StaticRecord> WriteableRecord for RR {
275	fn serialize_u16_len_prefixed<W: Writer>(&self, out: &mut W) {
276		RR::write_u16_len_prefixed_data(self, out)
277	}
278}
279impl WriteableRecord for RR {
280	fn serialize_u16_len_prefixed<W: Writer>(&self, out: &mut W) {
281		RR::write_u16_len_prefixed_data(self, out)
282	}
283}
284
285/// A trait describing a resource record (including the [`RR`] enum).
286pub trait Record : Ord {
287	/// The resource record type, as maintained by IANA.
288	///
289	/// Current assignments can be found at
290	/// <http://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-4>
291	fn ty(&self) -> u16;
292	/// The name this record is at.
293	fn name(&self) -> &Name;
294	/// Gets a JSON encoding of this record.
295	fn json(&self) -> String;
296	/// Writes the data of this record, prefixed by a u16 length, to the given `Vec`.
297	fn write_u16_len_prefixed_data(&self, out: &mut Vec<u8>);
298}
299impl<RR: StaticRecord> Record for RR {
300	fn ty(&self) -> u16 { RR::TYPE }
301	fn name(&self) -> &Name { RR::name(self) }
302	fn json(&self) -> String { RR::json(self) }
303	fn write_u16_len_prefixed_data(&self, out: &mut Vec<u8>) {
304		RR::write_u16_len_prefixed_data(self, out)
305	}
306}
307impl Record for RR {
308	fn ty(&self) -> u16 { self.ty() }
309	fn name(&self) -> &Name { self.name() }
310	fn json(&self) -> String { self.json() }
311	fn write_u16_len_prefixed_data(&self, out: &mut Vec<u8>) {
312		self.write_u16_len_prefixed_data(out)
313	}
314}
315
316#[derive(Debug, Clone, Hash, PartialEq, Eq)]
317struct TxtBytePart {
318	/// The bytes themselves.
319	///
320	/// Bytes at or beyond [`Self::len`] may be filled with garbage and should be ignored.
321	bytes: [u8; 255],
322	/// The number of bytes which are to be used.
323	len: NonZeroU8,
324}
325
326/// The bytes of a [`Txt`] record.
327///
328/// They are stored as a series of byte buffers so that we can reconstruct the exact encoding which
329/// was used for signatures, however they're really just a simple list of bytes, and the underlying
330/// encoding should be ignored.
331#[derive(Debug, Clone, Hash, PartialEq, Eq)]
332pub struct TxtBytes {
333	/// The series of byte buffers storing the bytes themselves.
334	chunks: Vec<TxtBytePart>,
335}
336
337impl TxtBytes {
338	/// Constructs a new [`TxtBytes`] from the given bytes
339	///
340	/// Fails if there are too many bytes to fit in a [`Txt`] record.
341	pub fn new(bytes: &[u8]) -> Result<TxtBytes, ()> {
342		if bytes.len() > 255*255 + 254 { return Err(()); }
343		let mut chunks = Vec::with_capacity((bytes.len() + 254) / 255);
344		let mut data_write = &bytes[..];
345		while !data_write.is_empty() {
346			let split_pos = core::cmp::min(255, data_write.len());
347			let mut part = TxtBytePart {
348				bytes: [0; 255],
349				len: (split_pos as u8).try_into().expect("Cannot be 0 as data_write is not empty"),
350			};
351			part.bytes[..split_pos].copy_from_slice(&data_write[..split_pos]);
352			chunks.push(part);
353			data_write = &data_write[split_pos..];
354		}
355		debug_assert_eq!(chunks.len(), (bytes.len() + 254) / 255);
356		Ok(TxtBytes { chunks })
357	}
358
359	/// Gets the total number of bytes represented in this record.
360	pub fn len(&self) -> usize {
361		let mut res = 0;
362		for chunk in self.chunks.iter() {
363			res += chunk.len.get() as usize;
364		}
365		res
366	}
367
368	/// The length of the bytes when serialized on the wire.
369	pub fn serialized_len(&self) -> u16 {
370		let mut len = 0u16;
371		for chunk in self.chunks.iter() {
372			len = len.checked_add(1 + chunk.len.get() as u16)
373				.expect("TxtBytes objects must fit in 2^16 - 1 bytes when serialized");
374		}
375		len
376	}
377
378	/// Gets the bytes as a flat `Vec` of `u8`s. This should be considered
379	pub fn as_vec(&self) -> Vec<u8> {
380		let mut res = Vec::with_capacity(self.len());
381		for chunk in self.chunks.iter() {
382			res.extend_from_slice(&chunk.bytes[..chunk.len.get() as usize]);
383		}
384		res
385	}
386
387	/// Gets an iterator over all the bytes in this [`TxtBytes`].
388	pub fn iter<'a>(&'a self) -> TxtBytesIter<'a> {
389		TxtBytesIter {
390			bytes: self,
391			next_part: 0,
392			next_byte: 0,
393		}
394	}
395}
396
397impl TryFrom<&str> for TxtBytes {
398	type Error = ();
399	fn try_from(s: &str) -> Result<TxtBytes, ()> {
400		TxtBytes::new(s.as_bytes())
401	}
402}
403
404impl TryFrom<&[u8]> for TxtBytes {
405	type Error = ();
406	fn try_from(b: &[u8]) -> Result<TxtBytes, ()> {
407		TxtBytes::new(b)
408	}
409}
410
411/// An iterator over the bytes in a [`TxtBytes`]
412pub struct TxtBytesIter<'a> {
413	bytes: &'a TxtBytes,
414	next_part: usize,
415	next_byte: u8,
416}
417
418impl<'a> Iterator for TxtBytesIter<'a> {
419	type Item = u8;
420	fn next(&mut self) -> Option<u8> {
421		self.bytes.chunks.get(self.next_part)
422			.and_then(|part| if self.next_byte >= part.len.get() {
423				None
424			} else {
425				let res = Some(part.bytes[self.next_byte as usize]);
426				if self.next_byte == part.len.get() - 1 {
427					self.next_byte = 0;
428					self.next_part += 1;
429				} else {
430					self.next_byte += 1;
431				}
432				res
433			})
434	}
435}
436
437#[derive(Debug, Clone, Hash, PartialEq, Eq)]
438/// A text resource record, containing arbitrary text data
439pub struct Txt {
440	/// The name this record is at.
441	pub name: Name,
442	/// The text record itself.
443	///
444	/// While this is generally UTF-8-valid, there is no specific requirement that it be, and thus
445	/// is an arbitrary series of bytes here.
446	pub data: TxtBytes,
447}
448/// The wire type for TXT records
449pub const TXT_TYPE: u16 = 16;
450impl Ord for Txt {
451	fn cmp(&self, o: &Txt) -> Ordering {
452		self.name.cmp(&o.name)
453			.then_with(|| {
454				// Compare in wire encoding form, i.e. compare checks in order
455				let mut o_chunks = o.data.chunks.iter();
456				for chunk in self.data.chunks.iter() {
457					if let Some(o_chunk) = o_chunks.next() {
458						let chunk_cmp = chunk.len.cmp(&o_chunk.len)
459							.then_with(||chunk.bytes[..chunk.len.get() as usize]
460								.cmp(&o_chunk.bytes[..o_chunk.len.get() as usize]));
461						if !chunk_cmp.is_eq() { return chunk_cmp; }
462					} else {
463						// self has more chunks than o
464						return Ordering::Greater;
465					}
466				}
467				if o_chunks.next().is_some() {
468					Ordering::Less
469				} else {
470					Ordering::Equal
471				}
472			})
473	}
474}
475impl PartialOrd for Txt {
476	fn partial_cmp(&self, o: &Txt) -> Option<Ordering> { Some(self.cmp(o)) }
477}
478impl StaticRecord for Txt {
479	const TYPE: u16 = TXT_TYPE;
480	fn name(&self) -> &Name { &self.name }
481	fn json(&self) -> String {
482		let mut res = format!("{{\"type\":\"txt\",\"name\":\"{}\",\"contents\":", self.name.0);
483		if self.data.iter().all(|b| b >= 0x20 && b <= 0x7e) {
484			res += "\"";
485			for b in self.data.iter() {
486				if b == b'"' || b == b'\\' {
487					res.push('\\');
488				}
489				res.push(b as char);
490			}
491			res += "\"}";
492		} else {
493			res += "[";
494			let mut first_b = true;
495			for b in self.data.iter() {
496				if !first_b { res += ","; }
497				write!(&mut res, "{}", b).expect("Shouldn't fail to write to a String");
498				first_b = false;
499			}
500			res += "]}";
501		}
502		res
503	}
504	fn read_from_data(name: Name, mut data: &[u8], _wire_packet: &[u8]) -> Result<Self, ()> {
505		let mut parts = TxtBytes {
506			chunks: Vec::with_capacity((data.len() + 255) / 256),
507		};
508		let mut serialized_len = 0;
509		while !data.is_empty() {
510			let len = read_u8(&mut data)?;
511			if data.len() < len as usize { return Err(()); }
512			if len == 0 { return Err(()); }
513			serialized_len += 1 + len as u32;
514			if serialized_len > u16::MAX as u32 {
515				return Err(());
516			}
517			let mut part = TxtBytePart {
518				bytes: [0; 255],
519				len: len.try_into().expect("We already checked 0 above"),
520			};
521			part.bytes[..len as usize].copy_from_slice(&data[..len as usize]);
522			data = &data[len as usize..];
523			parts.chunks.push(part);
524		}
525		debug_assert!(data.is_empty());
526		Ok(Txt { name, data: parts })
527	}
528	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
529		out.write(&self.data.serialized_len().to_be_bytes());
530		for chunk in self.data.chunks.iter() {
531			out.write(&[chunk.len.get()]);
532			out.write(&chunk.bytes[..chunk.len.get() as usize]);
533		}
534	}
535}
536
537#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
538/// A TLS Certificate Association resource record containing information about the TLS certificate
539/// which should be expected when communicating with the host at the given name.
540///
541/// See <https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities#TLSA_RR> for more
542/// info.
543pub struct TLSA {
544	/// The name this record is at.
545	pub name: Name,
546	/// The type of constraint on the TLS certificate(s) used which should be enforced by this
547	/// record.
548	pub cert_usage: u8,
549	/// Whether to match on the full certificate, or only the public key.
550	pub selector: u8,
551	/// The type of data included which is used to match the TLS certificate(s).
552	pub data_ty: u8,
553	/// The certificate data or hash of the certificate data itself.
554	pub data: Vec<u8>,
555}
556/// The wire type for TLSA records
557pub const TLSA_TYPE: u16 = 52;
558impl StaticRecord for TLSA {
559	const TYPE: u16 = TLSA_TYPE;
560	fn name(&self) -> &Name { &self.name }
561	fn json(&self) -> String {
562		let mut out = String::with_capacity(128+self.data.len()*2);
563		write!(&mut out,
564			"{{\"type\":\"tlsa\",\"name\":\"{}\",\"usage\":{},\"selector\":{},\"data_ty\":{},\"data\":\"",
565			self.name.0, self.cert_usage, self.selector, self.data_ty
566		).expect("Write to a String shouldn't fail");
567		for c in self.data.iter() {
568			write!(&mut out, "{:02X}", c)
569				.expect("Write to a String shouldn't fail");
570		}
571		out += "\"}";
572		out
573	}
574	fn read_from_data(name: Name, mut data: &[u8], _wire_packet: &[u8]) -> Result<Self, ()> {
575		Ok(TLSA {
576			name, cert_usage: read_u8(&mut data)?, selector: read_u8(&mut data)?,
577			data_ty: read_u8(&mut data)?, data: data.to_vec(),
578		})
579	}
580	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
581		let len = 3 + self.data.len();
582		out.write(&(len as u16).to_be_bytes());
583		out.write(&[self.cert_usage, self.selector, self.data_ty]);
584		out.write(&self.data);
585	}
586}
587
588#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
589/// A Canonical Name resource record, referring all queries for this name to another name.
590pub struct CName {
591	/// The name this record is at.
592	pub name: Name,
593	/// The canonical name.
594	///
595	/// A resolver should use this name when looking up any further records for [`self.name`].
596	pub canonical_name: Name,
597}
598impl StaticRecord for CName {
599	const TYPE: u16 = 5;
600	fn name(&self) -> &Name { &self.name }
601	fn json(&self) -> String {
602		format!("{{\"type\":\"cname\",\"name\":\"{}\",\"canonical_name\":\"{}\"}}",
603			self.name.0, self.canonical_name.0)
604	}
605	fn read_from_data(name: Name, mut data: &[u8], wire_packet: &[u8]) -> Result<Self, ()> {
606		let res = CName { name, canonical_name: read_wire_packet_name(&mut data, wire_packet)? };
607		Ok(res)
608	}
609	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
610		let len: u16 = name_len(&self.canonical_name);
611		out.write(&len.to_be_bytes());
612		write_name(out, &self.canonical_name);
613	}
614}
615
616#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
617/// A Delegation Name resource record, referring all queries for subdomains of this name to another
618/// subtree of the DNS.
619pub struct DName {
620	/// The name this record is at.
621	pub name: Name,
622	/// The delegation name.
623	///
624	/// A resolver should use this domain name tree when looking up any further records for
625	/// subdomains of [`self.name`].
626	pub delegation_name: Name,
627}
628impl StaticRecord for DName {
629	const TYPE: u16 = 39;
630	fn name(&self) -> &Name { &self.name }
631	fn json(&self) -> String {
632		format!("{{\"type\":\"dname\",\"name\":\"{}\",\"delegation_name\":\"{}\"}}",
633			self.name.0, self.delegation_name.0)
634	}
635	fn read_from_data(name: Name, mut data: &[u8], wire_packet: &[u8]) -> Result<Self, ()> {
636		let res = DName { name, delegation_name: read_wire_packet_name(&mut data, wire_packet)? };
637		Ok(res)
638	}
639	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
640		let len: u16 = name_len(&self.delegation_name);
641		out.write(&len.to_be_bytes());
642		write_name(out, &self.delegation_name);
643	}
644}
645
646
647#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
648/// A public key resource record which can be used to validate [`RRSig`]s.
649pub struct DnsKey {
650	/// The name this record is at.
651	pub name: Name,
652	/// Flags which constrain the usage of this public key.
653	pub flags: u16,
654	/// The protocol this key is used for (protocol `3` is DNSSEC). 
655	pub protocol: u8,
656	/// The algorithm which this public key uses to sign data.
657	pub alg: u8,
658	/// The public key itself.
659	pub pubkey: Vec<u8>,
660}
661impl StaticRecord for DnsKey {
662	const TYPE: u16 = 48;
663	fn name(&self) -> &Name { &self.name }
664	fn json(&self) -> String {
665		let mut out = String::with_capacity(128+self.pubkey.len()*2);
666		write!(&mut out,
667			"{{\"type\":\"dnskey\",\"name\":\"{}\",\"flags\":{},\"protocol\":{},\"alg\":{},\"pubkey\":\"",
668			self.name.0, self.flags, self.protocol, self.alg
669		).expect("Write to a String shouldn't fail");
670		for c in self.pubkey.iter() {
671			write!(&mut out, "{:02X}", c)
672				.expect("Write to a String shouldn't fail");
673		}
674		out += "\"}";
675		out
676	}
677	fn read_from_data(name: Name, mut data: &[u8], _wire_packet: &[u8]) -> Result<Self, ()> {
678		Ok(DnsKey {
679			name, flags: read_u16(&mut data)?, protocol: read_u8(&mut data)?,
680			alg: read_u8(&mut data)?, pubkey: data.to_vec(),
681		})
682	}
683	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
684		let len = 2 + 1 + 1 + self.pubkey.len();
685		out.write(&(len as u16).to_be_bytes());
686		out.write(&self.flags.to_be_bytes());
687		out.write(&self.protocol.to_be_bytes());
688		out.write(&self.alg.to_be_bytes());
689		out.write(&self.pubkey);
690	}
691}
692impl DnsKey {
693	/// A short (non-cryptographic) digest which can be used to refer to this [`DnsKey`].
694	pub fn key_tag(&self) -> u16 {
695		let mut res = u32::from(self.flags);
696		res += u32::from(self.protocol) << 8;
697		res += u32::from(self.alg);
698		for (idx, b) in self.pubkey.iter().enumerate() {
699			if idx % 2 == 0 {
700				res += u32::from(*b) << 8;
701			} else {
702				res += u32::from(*b);
703			}
704		}
705		res += (res >> 16) & 0xffff;
706		(res & 0xffff) as u16
707	}
708}
709
710#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
711/// A Delegation Signer resource record which indicates that some alternative [`DnsKey`] can sign
712/// for records in the zone which matches [`self.name`].
713pub struct DS {
714	/// The name this record is at.
715	///
716	/// This is also the zone that a [`DnsKey`] which matches the [`Self::digest`] can sign for.
717	pub name: Name,
718	/// A short tag which describes the matching [`DnsKey`].
719	///
720	/// This matches the [`DnsKey::key_tag`] for the [`DnsKey`] which is referred to by this
721	/// [`DS`].
722	pub key_tag: u16,
723	/// The algorithm which the [`DnsKey`] referred to by this [`DS`] uses.
724	///
725	/// This matches the [`DnsKey::alg`] field in the referred-to [`DnsKey`].
726	pub alg: u8,
727	/// The type of digest used to hash the referred-to [`DnsKey`].
728	pub digest_type: u8,
729	/// The digest itself.
730	pub digest: Vec<u8>,
731}
732impl StaticRecord for DS {
733	const TYPE: u16 = 43;
734	fn name(&self) -> &Name { &self.name }
735	fn json(&self) -> String {
736		let mut out = String::with_capacity(128+self.digest.len()*2);
737		write!(&mut out,
738			"{{\"type\":\"ds\",\"name\":\"{}\",\"key_tag\":{},\"alg\":{},\"digest_type\":{},\"digest\":\"",
739			self.name.0, self.key_tag, self.alg, self.digest_type
740		).expect("Write to a String shouldn't fail");
741		for c in self.digest.iter() {
742			write!(&mut out, "{:02X}", c)
743				.expect("Write to a String shouldn't fail");
744		}
745		out += "\"}";
746		out
747	}
748	fn read_from_data(name: Name, mut data: &[u8], _wire_packet: &[u8]) -> Result<Self, ()> {
749		Ok(DS {
750			name, key_tag: read_u16(&mut data)?, alg: read_u8(&mut data)?,
751			digest_type: read_u8(&mut data)?, digest: data.to_vec(),
752		})
753	}
754	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
755		let len = 2 + 1 + 1 + self.digest.len();
756		out.write(&(len as u16).to_be_bytes());
757		out.write(&self.key_tag.to_be_bytes());
758		out.write(&self.alg.to_be_bytes());
759		out.write(&self.digest_type.to_be_bytes());
760		out.write(&self.digest);
761	}
762}
763
764#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
765/// A Resource Record (set) Signature resource record. This contains a signature over all the
766/// resources records of the given type at the given name.
767pub struct RRSig {
768	/// The name this record is at.
769	///
770	/// This is also the name of any records which this signature is covering (ignoring wildcards).
771	pub name: Name,
772	/// The resource record type which this [`RRSig`] is signing.
773	///
774	/// All resources records of this type at the same name as [`self.name`] must be signed by
775	/// this [`RRSig`].
776	pub ty: u16,
777	/// The algorithm which is being used to sign.
778	///
779	/// This must match the [`DnsKey::alg`] field in the [`DnsKey`] being used to sign.
780	pub alg: u8,
781	/// The number of labels in the name of the records that this signature is signing.
782	///
783	/// If this is less than the number of labels in [`self.name`], this signature is covering a
784	/// wildcard entry.
785	pub labels: u8,
786	/// The TTL of the records which this [`RRSig`] is signing.
787	pub orig_ttl: u32,
788	/// The expiration (as a UNIX timestamp) of this signature.
789	pub expiration: u32,
790	/// The time (as a UNIX timestamp) at which this signature becomes valid.
791	pub inception: u32,
792	/// A short tag which describes the matching [`DnsKey`].
793	///
794	/// This matches the [`DnsKey::key_tag`] for the [`DnsKey`] which created this signature.
795	pub key_tag: u16,
796	/// The [`DnsKey::name`] in the [`DnsKey`] which created this signature.
797	///
798	/// This must be a parent of [`self.name`].
799	///
800	/// [`DnsKey::name`]: Record::name
801	// We'd like to just link to the `DnsKey` member variable called `name`, but there doesn't
802	// appear to be a way to actually do that, so instead we have to link to the trait method.
803	pub key_name: Name,
804	/// The signature itself.
805	pub signature: Vec<u8>,
806}
807impl StaticRecord for RRSig {
808	const TYPE: u16 = 46;
809	fn name(&self) -> &Name { &self.name }
810	fn json(&self) -> String {
811		let mut out = String::with_capacity(256 + self.signature.len()*2);
812		write!(&mut out,
813			"{{\"type\":\"ds\",\"name\":\"{}\",\"signed_record_type\":{},\"alg\":{},\"signed_labels\":{},\"orig_ttl\":{},\"expiration\":{},\"inception\":{},\"key_tag\":{},\"key_name\":\"{}\",\"signature\":\"",
814			self.name.0, self.ty, self.alg, self.labels, self.orig_ttl, self.expiration, self.inception, self.key_tag, self.key_name.0
815		).expect("Write to a String shouldn't fail");
816		for c in self.signature.iter() {
817			write!(&mut out, "{:02X}", c)
818				.expect("Write to a String shouldn't fail");
819		}
820		out += "\"}";
821		out
822	}
823	fn read_from_data(name: Name, mut data: &[u8], wire_packet: &[u8]) -> Result<Self, ()> {
824		Ok(RRSig {
825			name, ty: read_u16(&mut data)?, alg: read_u8(&mut data)?,
826			labels: read_u8(&mut data)?, orig_ttl: read_u32(&mut data)?,
827			expiration: read_u32(&mut data)?, inception: read_u32(&mut data)?,
828			key_tag: read_u16(&mut data)?,
829			key_name: read_wire_packet_name(&mut data, wire_packet)?,
830			signature: data.to_vec(),
831		})
832	}
833	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
834		let len = 2 + 1 + 1 + 4*3 + 2 + name_len(&self.key_name) + self.signature.len() as u16;
835		out.write(&len.to_be_bytes());
836		out.write(&self.ty.to_be_bytes());
837		out.write(&self.alg.to_be_bytes());
838		out.write(&self.labels.to_be_bytes());
839		out.write(&self.orig_ttl.to_be_bytes());
840		out.write(&self.expiration.to_be_bytes());
841		out.write(&self.inception.to_be_bytes());
842		out.write(&self.key_tag.to_be_bytes());
843		write_name(out, &self.key_name);
844		out.write(&self.signature);
845	}
846}
847
848/// Note that anything less than 2*pointer_size - 1 will have no impact on NSecTypeMaskBytes size.
849const NSEC_MASK_INLINE_LEN: usize = 15;
850
851#[derive(Clone)]
852pub(super) enum NSecTypeMaskBytes {
853	Heap(Vec<u8>),
854	Inline {
855		bytes: [u8; NSEC_MASK_INLINE_LEN],
856		len: u8,
857	},
858}
859impl NSecTypeMaskBytes {
860	pub fn new() -> Self { Self::Inline { bytes: [0; NSEC_MASK_INLINE_LEN], len: 0 } }
861	pub fn len(&self) -> usize {
862		match self {
863			Self::Heap(bitmap) => bitmap.len(),
864			Self::Inline { len, .. } => *len as usize,
865		}
866	}
867	pub fn resize(&mut self, new_len: usize) {
868		match self {
869			Self::Heap(bitmap) => bitmap.resize(new_len, 0),
870			Self::Inline { bytes, len } if new_len <= NSEC_MASK_INLINE_LEN => {
871				bytes[core::cmp::min(*len as usize, new_len)..].fill(0);
872				*len = new_len as u8;
873			},
874			Self::Inline { bytes, len } => {
875				let mut bitmap = Vec::with_capacity(new_len);
876				bitmap.extend_from_slice(&bytes[..*len as usize]);
877				bitmap.resize(new_len, 0);
878				*self = Self::Heap(bitmap);
879			},
880		}
881	}
882	fn wire_blocks(&self) -> impl Iterator<Item = (u8, &[u8])> {
883		self.chunks(32).enumerate().filter_map(|(idx, flags)| {
884			let last_nonzero_idx = flags.iter().rposition(|flag| *flag != 0)?;
885			// Types are `u16`s, so there can be at most 8192 mask bytes, i.e. 256 blocks.
886			debug_assert!(idx <= u8::MAX as usize);
887			Some((idx as u8, &flags[..last_nonzero_idx + 1]))
888		})
889	}
890	fn wire_bytes(&self) -> impl Iterator<Item = u8> + '_ {
891		self.wire_blocks().flat_map(|(block, flags)| {
892			[block, flags.len() as u8].into_iter().chain(flags.iter().copied())
893		})
894	}
895	fn write<W: Writer>(&self, out: &mut W) {
896		for byte in self.wire_bytes() {
897			out.write(&byte.to_be_bytes());
898		}
899	}
900}
901impl core::ops::Deref for NSecTypeMaskBytes {
902	type Target = [u8];
903	fn deref(&self) -> &[u8] {
904		match self {
905			Self::Heap(bitmap) => &bitmap[..],
906			Self::Inline { bytes, len } => &bytes[..*len as usize],
907		}
908	}
909}
910impl core::ops::DerefMut for NSecTypeMaskBytes {
911	fn deref_mut(&mut self) -> &mut [u8] {
912		match self {
913			Self::Heap(bitmap) => &mut bitmap[..],
914			Self::Inline { bytes, len } => &mut bytes[..*len as usize],
915		}
916	}
917}
918impl PartialEq for NSecTypeMaskBytes {
919	fn eq(&self, o: &Self) -> bool { self.wire_bytes().eq(o.wire_bytes()) }
920}
921impl Eq for NSecTypeMaskBytes {}
922impl Ord for NSecTypeMaskBytes {
923	fn cmp(&self, o: &Self) -> Ordering { self.wire_bytes().cmp(o.wire_bytes()) }
924}
925impl PartialOrd for NSecTypeMaskBytes {
926	fn partial_cmp(&self, o: &Self) -> Option<Ordering> { Some(self.cmp(o)) }
927}
928impl core::hash::Hash for NSecTypeMaskBytes {
929	fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
930		for byte in self.wire_bytes() {
931			hasher.write_u8(byte);
932		}
933	}
934}
935
936#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
937/// A mask used in [`NSec`] and [`NSec3`] records which indicates the resource record types which
938/// exist at the (hash of the) name described in [`Record::name`].
939pub struct NSecTypeMask(NSecTypeMaskBytes);
940impl NSecTypeMask {
941	/// Constructs a new, empty, type mask.
942	pub fn new() -> Self { Self(NSecTypeMaskBytes::new()) }
943	/// Builds a new type mask with the given types set
944	pub fn from_types(types: &[u16]) -> Self {
945		let mut flags = NSecTypeMaskBytes::new();
946		if let Some(max_type) = types.iter().max() {
947			flags.resize((*max_type as usize >> 3) + 1);
948		}
949		for t in types {
950			flags[*t as usize >> 3] |= 1 << (7 - (*t as usize % 8));
951		}
952		let res = Self(flags);
953		for t in types {
954			debug_assert!(res.contains_type(*t));
955		}
956		res
957	}
958	/// Checks if the given type (from [`Record::ty`]) is set, indicating a record of this type
959	/// exists.
960	pub fn contains_type(&self, ty: u16) -> bool {
961		match self.0.get((ty >> 3) as usize) {
962			// DNSSEC's bit fields are in wire order, so the high bit is type 0, etc.
963			Some(f) => f & (1 << (7 - (ty % 8))) != 0,
964			None => false,
965		}
966	}
967	fn write_json(&self, s: &mut String) {
968		*s += "[";
969		write!(s, "{:?}", self).expect("Writes to a string shouldn't fail");
970		*s += "]";
971	}
972}
973impl fmt::Debug for NSecTypeMask {
974	fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
975		let mut have_written = false;
976		for (idx, mask) in self.0.iter().enumerate() {
977			if *mask == 0 { continue; }
978			for b in 0..8 {
979				if *mask & (1 << b) != 0 {
980					let ty = ((idx as u16) << 3) | (7 - b);
981					match RR::ty_to_rr_name(ty) {
982						Some(name) => write!(f, "{}\"{}\"", if have_written { "," } else { "" }, name)?,
983						_ => write!(f, "{}{}", if have_written { "," } else { "" }, ty)?,
984					}
985					have_written = true;
986				}
987			}
988		}
989		Ok(())
990	}
991}
992
993#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
994/// A Next Secure Record resource record. This indicates a range of possible names for which there
995/// is no such record.
996pub struct NSec {
997	/// The name this record is at.
998	pub name: Name,
999	/// The next name which contains a record. There are no names between `name` and
1000	/// [`Self::next_name`].
1001	///
1002	/// Note that unlike `name`, it isn't uncommon for this to contain null bytes (for online
1003	/// signing).
1004	pub next_name: Vec<u8>,
1005	/// The set of record types which exist at `name`. Any other record types do not exist at
1006	/// `name`.
1007	pub types: NSecTypeMask,
1008}
1009impl StaticRecord for NSec {
1010	const TYPE: u16 = 47;
1011	fn name(&self) -> &Name { &self.name }
1012	fn json(&self) -> String {
1013		let mut out = String::with_capacity(256 + self.next_name.len());
1014		write!(&mut out, "{{\"type\":\"nsec\",\"name\":\"{}\",\"next_name\":\"", self.name.0)
1015			.expect("Write to a String shouldn't fail");
1016		for c in self.next_name.iter() {
1017			if *c >= 0x20 && *c <= 0x7e {
1018				if *c == b'"' || *c == b'\\' {
1019					out.push('\\');
1020				}
1021				out.push(char::from_u32((*c).into()).unwrap());
1022			} else {
1023				out += "\\u";
1024				write!(&mut out, "00{:02x}", *c).expect("Write to a String shouldn't fail");
1025			}
1026		}
1027		out += "\",\"types\":";
1028		self.types.write_json(&mut out);
1029		out += "}";
1030		out
1031	}
1032	fn read_from_data(name: Name, mut data: &[u8], wire_packet: &[u8]) -> Result<Self, ()> {
1033		let res = NSec {
1034			name, next_name: read_wire_packet_name_bytes(&mut data, wire_packet)?,
1035			types: NSecTypeMask(read_nsec_types_bitmap(&mut data)?),
1036		};
1037		debug_assert!(data.is_empty());
1038		Ok(res)
1039	}
1040	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
1041		let len = name_bytes_len(&self.next_name) + self.types.0.wire_bytes().count() as u16;
1042		out.write(&len.to_be_bytes());
1043		// RFC 6840 ยง5.1 mandates this not be lowercased
1044		write_name_without_case_modification(out, &self.next_name);
1045		self.types.0.write(out);
1046	}
1047}
1048
1049#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1050/// A Next Secure Record resource record. This indicates a range of possible names for which there
1051/// is no such record.
1052pub struct NSec3 {
1053	/// The name this record is at.
1054	pub name: Name,
1055	/// The hash algorithm used to hash the `name` and [`Self::next_name_hash`]. Currently only 1
1056	/// (SHA-1) is defined.
1057	pub hash_algo: u8,
1058	/// Flags for this record. Currently only bit 0 (the "opt-out" bit) is defined.
1059	pub flags: u8,
1060	/// The number of hash iterations required.
1061	///
1062	/// As of RFC 9276 this MUST be set to 0, but sadly is often still set higher in the wild. A
1063	/// hard cap is applied in validation.
1064	pub hash_iterations: u16,
1065	/// The salt included in the hash.
1066	///
1067	/// As of RFC 9276 this SHOULD be empty, but often isn't in the wild.
1068	pub salt: Vec<u8>,
1069	/// The hash of the next name which contains a record. There are no records who's name's hash
1070	/// lies between `name` and [`Self::next_name_hash`].
1071	pub next_name_hash: Vec<u8>,
1072	/// The set of record types which exist at `name`. Any other record types do not exist at
1073	/// `name`.
1074	pub types: NSecTypeMask,
1075}
1076impl StaticRecord for NSec3 {
1077	const TYPE: u16 = 50;
1078	fn name(&self) -> &Name { &self.name }
1079	fn json(&self) -> String {
1080		let mut out = String::with_capacity(256);
1081		write!(&mut out,
1082			"{{\"type\":\"nsec3\",\"name\":\"{}\",\"hash_algo\":{},\"flags\":{},\"hash_iterations\":{},\"salt\":{:?},\"next_name_hash\":{:?},\"types\":",
1083			self.name.0, self.hash_algo, self.flags, self.hash_iterations, &self.salt[..], &self.next_name_hash[..]
1084		).expect("Write to a String shouldn't fail");
1085		self.types.write_json(&mut out);
1086		out += "}";
1087		out
1088	}
1089	fn read_from_data(name: Name, mut data: &[u8], _wire_packet: &[u8]) -> Result<Self, ()> {
1090		let res = NSec3 {
1091			name, hash_algo: read_u8(&mut data)?, flags: read_u8(&mut data)?,
1092			hash_iterations: read_u16(&mut data)?, salt: read_u8_len_prefixed_bytes(&mut data)?,
1093			next_name_hash: read_u8_len_prefixed_bytes(&mut data)?,
1094			types: NSecTypeMask(read_nsec_types_bitmap(&mut data)?),
1095		};
1096		debug_assert!(data.is_empty());
1097		Ok(res)
1098	}
1099	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
1100		let len = 4 + 2 + self.salt.len() as u16 + self.next_name_hash.len() as u16 +
1101			self.types.0.wire_bytes().count() as u16;
1102		out.write(&len.to_be_bytes());
1103		out.write(&self.hash_algo.to_be_bytes());
1104		out.write(&self.flags.to_be_bytes());
1105		out.write(&self.hash_iterations.to_be_bytes());
1106		out.write(&(self.salt.len() as u8).to_be_bytes());
1107		out.write(&self.salt);
1108		out.write(&(self.next_name_hash.len() as u8).to_be_bytes());
1109		out.write(&self.next_name_hash);
1110		self.types.0.write(out);
1111	}
1112}
1113
1114#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1115/// An IPv4 Address resource record
1116pub struct A {
1117	/// The name this record is at.
1118	pub name: Name,
1119	/// The bytes of the IPv4 address.
1120	pub address: [u8; 4],
1121}
1122/// The wire type for A records
1123pub const A_TYPE: u16 = 1;
1124impl StaticRecord for A {
1125	const TYPE: u16 = A_TYPE;
1126	fn name(&self) -> &Name { &self.name }
1127	fn json(&self) -> String {
1128		format!("{{\"type\":\"a\",\"name\":\"{}\",\"address\":{:?}}}", self.name.0, self.address)
1129	}
1130	fn read_from_data(name: Name, data: &[u8], _wire_packet: &[u8]) -> Result<Self, ()> {
1131		if data.len() != 4 { return Err(()); }
1132		let mut address = [0; 4];
1133		address.copy_from_slice(data);
1134		Ok(A { name, address })
1135	}
1136	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
1137		out.write(&4u16.to_be_bytes());
1138		out.write(&self.address);
1139	}
1140}
1141
1142#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1143/// An IPv6 Address resource record
1144pub struct AAAA {
1145	/// The name this record is at.
1146	pub name: Name,
1147	/// The bytes of the IPv6 address.
1148	pub address: [u8; 16],
1149}
1150/// The wire type for AAAA records
1151pub const AAAA_TYPE: u16 = 28;
1152impl StaticRecord for AAAA {
1153	const TYPE: u16 = AAAA_TYPE;
1154	fn name(&self) -> &Name { &self.name }
1155	fn json(&self) -> String {
1156		format!("{{\"type\":\"aaaa\",\"name\":\"{}\",\"address\":{:?}}}", self.name.0, self.address)
1157	}
1158	fn read_from_data(name: Name, data: &[u8], _wire_packet: &[u8]) -> Result<Self, ()> {
1159		if data.len() != 16 { return Err(()); }
1160		let mut address = [0; 16];
1161		address.copy_from_slice(data);
1162		Ok(AAAA { name, address })
1163	}
1164	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
1165		out.write(&16u16.to_be_bytes());
1166		out.write(&self.address);
1167	}
1168}
1169
1170#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
1171/// A Name Server resource record, which indicates the server responsible for handling queries for
1172/// a zone.
1173pub struct NS {
1174	/// The name this record is at.
1175	///
1176	/// This is also the zone which the server at [`Self::name_server`] is responsible for handling
1177	/// queries for.
1178	pub name: Name,
1179	/// The name of the server which is responsible for handling queries for the [`self.name`]
1180	/// zone.
1181	pub name_server: Name,
1182}
1183impl StaticRecord for NS {
1184	const TYPE: u16 = 2;
1185	fn name(&self) -> &Name { &self.name }
1186	fn json(&self) -> String {
1187		format!("{{\"type\":\"ns\",\"name\":\"{}\",\"ns\":\"{}\"}}", self.name.0, self.name_server.0)
1188	}
1189	fn read_from_data(name: Name, mut data: &[u8], wire_packet: &[u8]) -> Result<Self, ()> {
1190		let res = NS { name, name_server: read_wire_packet_name(&mut data, wire_packet)? };
1191		Ok(res)
1192	}
1193	fn write_u16_len_prefixed_data<W: Writer>(&self, out: &mut W) {
1194		out.write(&name_len(&self.name_server).to_be_bytes());
1195		write_name(out, &self.name_server);
1196	}
1197}
1198
1199#[cfg(test)]
1200mod tests {
1201	use super::*;
1202
1203	const NAMES: [&str; 14] = [
1204		".",
1205		"*.example.com.",
1206		"a.example.com.",
1207		"z.",
1208		"z.a.example.",
1209		"aa.",
1210		"com.",
1211		"ns2.exampl.com.",
1212		"ns2.example.com.",
1213		"sub.example.com.",
1214		"ns10.example.com.",
1215		"ns20.example.com.",
1216		"example.com.",
1217		"xn--e1afmkfd.com.",
1218	];
1219
1220	fn wire_encoding(name: &Name) -> Vec<u8> {
1221		let mut res = Vec::new();
1222		write_name(&mut res, name);
1223		res
1224	}
1225
1226	#[test]
1227	fn name_ord_matches_wire_encoding() {
1228		for a in NAMES.iter() {
1229			for b in NAMES.iter() {
1230				let a_name: Name = (*a).try_into().unwrap();
1231				let b_name: Name = (*b).try_into().unwrap();
1232				let wire_ord = wire_encoding(&a_name).cmp(&wire_encoding(&b_name));
1233				assert_eq!(a_name.cmp(&b_name), wire_ord);
1234				let a_ns = NS { name: ".".try_into().unwrap(), name_server: a_name};
1235				let b_ns = NS { name: ".".try_into().unwrap(), name_server: b_name};
1236				assert_eq!(a_ns.cmp(&b_ns), wire_ord);
1237			}
1238		}
1239	}
1240}