simple_dns/dns/rdata/
ds.rs1use crate::{bytes_buffer::BytesBuffer, dns::WireFormat};
2use std::borrow::Cow;
3
4use super::RR;
5
6#[derive(Debug, PartialEq, Eq, Hash, Clone)]
8pub struct DS<'a> {
9 pub key_tag: u16,
11 pub algorithm: u8,
13 pub digest_type: u8,
15 pub digest: Cow<'a, [u8]>,
17}
18
19impl RR for DS<'_> {
20 const TYPE_CODE: u16 = 43;
21}
22
23impl<'a> WireFormat<'a> for DS<'a> {
24 const MINIMUM_LEN: usize = 4;
25
26 fn parse(data: &mut BytesBuffer<'a>) -> crate::Result<Self>
27 where
28 Self: Sized,
29 {
30 let key_tag = data.get_u16()?;
31 let algorithm = data.get_u8()?;
32 let digest_type = data.get_u8()?;
33 let digest = Cow::Borrowed(data.get_remaining());
34
35 Ok(Self {
36 key_tag,
37 algorithm,
38 digest_type,
39 digest,
40 })
41 }
42
43 fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
44 out.write_all(&self.key_tag.to_be_bytes())?;
45 out.write_all(&[self.algorithm, self.digest_type])?;
46 out.write_all(&self.digest)?;
47
48 Ok(())
49 }
50
51 fn len(&self) -> usize {
52 self.digest.len() + Self::MINIMUM_LEN
53 }
54}
55
56impl DS<'_> {
57 pub fn into_owned<'b>(self) -> DS<'b> {
59 DS {
60 key_tag: self.key_tag,
61 algorithm: self.algorithm,
62 digest_type: self.digest_type,
63 digest: Cow::Owned(self.digest.into_owned()),
64 }
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use crate::{rdata::RData, ResourceRecord};
71
72 use super::*;
73
74 #[test]
75 fn parse_and_write_ds() {
76 let key_tag = 12345u16;
77 let algorithm = 8u8;
78 let digest_type = 2u8;
79 let digest = vec![1, 2, 3, 4, 5];
80 let rdata = DS {
81 key_tag,
82 algorithm,
83 digest_type,
84 digest: Cow::Owned(digest),
85 };
86 let mut writer = Vec::new();
87 rdata.write_to(&mut writer).unwrap();
88 let rdata = DS::parse(&mut (&writer[..]).into()).unwrap();
89 assert_eq!(rdata.key_tag, key_tag);
90 assert_eq!(rdata.algorithm, algorithm);
91 assert_eq!(rdata.digest_type, digest_type);
92 assert_eq!(&*rdata.digest, &[1, 2, 3, 4, 5]);
93 }
94
95 #[test]
96 fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
97 let sample_file = std::fs::read("samples/zonefile/DS.sample")?;
98
99 let sample_rdata = match ResourceRecord::parse(&mut (&sample_file[..]).into())?.rdata {
100 RData::DS(rdata) => rdata,
101 _ => unreachable!(),
102 };
103
104 assert_eq!(sample_rdata.algorithm, 5);
105 assert_eq!(sample_rdata.digest_type, 1);
106 assert_eq!(sample_rdata.key_tag, 60485);
107 assert_eq!(
108 *sample_rdata.digest,
109 *b"\x2B\xB1\x83\xAF\x5F\x22\x58\x81\x79\xA5\x3B\x0A\x98\x63\x1F\xAD\x1A\x29\x21\x18"
110 );
111
112 Ok(())
113 }
114}