simple_dns/dns/rdata/
rrsig.rs1use crate::{
2 bytes_buffer::BytesBuffer,
3 dns::{Name, WireFormat},
4};
5use std::borrow::Cow;
6
7use super::RR;
8
9#[derive(Debug, PartialEq, Eq, Hash, Clone)]
11pub struct RRSIG<'a> {
12 pub type_covered: u16,
14 pub algorithm: u8,
16 pub labels: u8,
18 pub original_ttl: u32,
20 pub signature_expiration: u32,
22 pub signature_inception: u32,
24 pub key_tag: u16,
26 pub signer_name: Name<'a>,
28 pub signature: Cow<'a, [u8]>,
30}
31
32impl RR for RRSIG<'_> {
33 const TYPE_CODE: u16 = 46;
34}
35
36impl<'a> WireFormat<'a> for RRSIG<'a> {
37 const MINIMUM_LEN: usize = 18;
38
39 fn parse(data: &mut BytesBuffer<'a>) -> crate::Result<Self>
40 where
41 Self: Sized,
42 {
43 let type_covered = data.get_u16()?;
44 let algorithm = data.get_u8()?;
45 let labels = data.get_u8()?;
46 let original_ttl = data.get_u32()?;
47 let signature_expiration = data.get_u32()?;
48 let signature_inception = data.get_u32()?;
49 let key_tag = data.get_u16()?;
50
51 let signer_name = Name::parse(data)?;
52 let signature = Cow::Borrowed(data.get_remaining());
53
54 Ok(Self {
55 type_covered,
56 algorithm,
57 labels,
58 original_ttl,
59 signature_expiration,
60 signature_inception,
61 key_tag,
62 signer_name,
63 signature,
64 })
65 }
66
67 fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
68 out.write_all(&self.type_covered.to_be_bytes())?;
69 out.write_all(&[self.algorithm])?;
70 out.write_all(&[self.labels])?;
71 out.write_all(&self.original_ttl.to_be_bytes())?;
72 out.write_all(&self.signature_expiration.to_be_bytes())?;
73 out.write_all(&self.signature_inception.to_be_bytes())?;
74 out.write_all(&self.key_tag.to_be_bytes())?;
75 self.signer_name.write_to(out)?;
76 out.write_all(&self.signature)?;
77
78 Ok(())
79 }
80
81 fn len(&self) -> usize {
82 self.signer_name.len() + self.signature.len() + Self::MINIMUM_LEN
83 }
84}
85
86impl RRSIG<'_> {
87 pub fn into_owned<'b>(self) -> RRSIG<'b> {
89 RRSIG {
90 type_covered: self.type_covered,
91 algorithm: self.algorithm,
92 labels: self.labels,
93 original_ttl: self.original_ttl,
94 signature_expiration: self.signature_expiration,
95 signature_inception: self.signature_inception,
96 key_tag: self.key_tag,
97 signer_name: self.signer_name.into_owned(),
98 signature: Cow::Owned(self.signature.into_owned()),
99 }
100 }
101}
102
103#[cfg(test)]
104mod tests {
105 use super::*;
106 use crate::{
107 rdata::{RData, A},
108 ResourceRecord,
109 };
110
111 #[test]
112 fn parse_and_write_rrsig() {
113 let rrsig = RRSIG {
114 type_covered: A::TYPE_CODE,
115 algorithm: 5,
116 labels: 3,
117 original_ttl: 86400,
118 signature_expiration: 1045762263,
119 signature_inception: 1048354263,
120 key_tag: 2642,
121 signer_name: Name::new("example.com.").unwrap(),
122 signature: b"TEST".to_vec().into(),
123 };
124
125 let mut data = Vec::new();
126 rrsig.write_to(&mut data).unwrap();
127 let rrsig2 = RRSIG::parse(&mut data[..].into()).unwrap();
128 assert_eq!(rrsig, rrsig2);
129 }
130
131 #[test]
132 fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
133 let sample_file = std::fs::read("samples/zonefile/RRSIG.sample")?;
134
135 let sample_rdata = match ResourceRecord::parse(&mut sample_file[..].into())?.rdata {
136 RData::RRSIG(rdata) => rdata,
137 _ => unreachable!(),
138 };
139
140 assert_eq!(sample_rdata.type_covered, A::TYPE_CODE);
141 assert_eq!(sample_rdata.algorithm, 5);
142 assert_eq!(sample_rdata.labels, 3);
143 assert_eq!(sample_rdata.original_ttl, 86400);
144 assert_eq!(sample_rdata.signature_expiration, 1048354263);
145 assert_eq!(sample_rdata.signature_inception, 1045762263);
146 assert_eq!(sample_rdata.key_tag, 2642);
147 assert_eq!(sample_rdata.signer_name, Name::new("example.com.")?);
148 assert_eq!(*sample_rdata.signature, *b"\xa0\x90\x75\x5b\xa5\x8d\x1a\xff\xa5\x76\xf4\x37\x58\x31\xb4\x31\x09\x20\xe4\x81\x21\x8d\x18\xa9\xf1\x64\xeb\x3d\x81\xaf\xd3\xb8\x75\xd3\xc7\x54\x28\x63\x1e\x0c\xf2\xa2\x8d\x50\x87\x5f\x70\xc3\x29\xd7\xdb\xfa\xfe\xa8\x07\xdc\x1f\xba\x1d\xc3\x4c\x95\xd4\x01\xf2\x3f\x33\x4c\xe6\x3b\xfc\xf3\xf1\xb5\xb4\x47\x39\xe5\xf0\xed\xed\x18\xd6\xb3\x3f\x04\x0a\x91\x13\x76\xd1\x73\xd7\x57\xa9\xf0\xc1\xfa\x17\x98\x94\x1b\xb0\xb3\x6b\x2d\xf9\x06\x27\x90\xfa\x7f\x01\x66\xf2\x73\x7e\xea\x90\x73\x78\x34\x1f\xb1\x2d\xc0\xa7\x7a");
149
150 Ok(())
151 }
152}