simple_dns/dns/rdata/
cert.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 CERT<'a> {
9 pub type_code: u16,
11 pub key_tag: u16,
13 pub algorithm: u8,
15 pub certificate: Cow<'a, [u8]>,
17}
18
19impl RR for CERT<'_> {
20 const TYPE_CODE: u16 = 37;
21}
22
23impl<'a> WireFormat<'a> for CERT<'a> {
24 const MINIMUM_LEN: usize = 5;
25
26 fn parse(data: &mut BytesBuffer<'a>) -> crate::Result<Self>
27 where
28 Self: Sized,
29 {
30 let type_code = data.get_u16()?;
31 let key_tag = data.get_u16()?;
32 let algorithm = data.get_u8()?;
33 let certificate = data.get_remaining();
34
35 Ok(Self {
36 type_code,
37 key_tag,
38 algorithm,
39 certificate: std::borrow::Cow::Borrowed(certificate),
40 })
41 }
42
43 fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
44 out.write_all(&self.type_code.to_be_bytes())?;
45 out.write_all(&self.key_tag.to_be_bytes())?;
46 out.write_all(&[self.algorithm])?;
47 out.write_all(&self.certificate)?;
48
49 Ok(())
50 }
51
52 fn len(&self) -> usize {
53 self.certificate.len() + Self::MINIMUM_LEN
54 }
55}
56
57impl CERT<'_> {
58 pub fn into_owned<'b>(self) -> CERT<'b> {
60 CERT {
61 type_code: self.type_code,
62 key_tag: self.key_tag,
63 algorithm: self.algorithm,
64 certificate: self.certificate.into_owned().into(),
65 }
66 }
67}
68
69#[cfg(test)]
70mod tests {
71 use crate::{rdata::RData, ResourceRecord};
72
73 use super::*;
74
75 #[test]
76 fn parse_and_write_cert() {
77 let type_code = 12345u16;
78 let key_tag = 8u16;
79 let algorithm = 2u8;
80 let certificate = vec![1, 2, 3, 4, 5];
81 let rdata = CERT {
82 type_code,
83 key_tag,
84 algorithm,
85 certificate: Cow::Owned(certificate),
86 };
87 let mut writer = Vec::new();
88 rdata.write_to(&mut writer).unwrap();
89 let rdata = CERT::parse(&mut (&writer[..]).into()).unwrap();
90 assert_eq!(rdata.type_code, type_code);
91 assert_eq!(rdata.key_tag, key_tag);
92 assert_eq!(rdata.algorithm, algorithm);
93 assert_eq!(&*rdata.certificate, &[1, 2, 3, 4, 5]);
94 }
95
96 #[test]
97 fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
98 let sample_file = std::fs::read("samples/zonefile/CERT.sample")?;
99
100 let sample_rdata = match ResourceRecord::parse(&mut (&sample_file[..]).into())?.rdata {
101 RData::CERT(rdata) => rdata,
102 _ => unreachable!(),
103 };
104
105 assert_eq!(sample_rdata.type_code, 3);
106 assert_eq!(sample_rdata.key_tag, 0);
107 assert_eq!(sample_rdata.algorithm, 0);
108 assert_eq!(*sample_rdata.certificate, *b"\x00\x00\x00\x00\x00");
109
110 Ok(())
111 }
112}