simple_dns/dns/rdata/
kx.rs

1use crate::{bytes_buffer::BytesBuffer, dns::WireFormat, Name};
2
3use super::RR;
4
5/// A Key eXchange record [rfc2230](https://www.rfc-editor.org/rfc/rfc2230)
6#[derive(Debug, PartialEq, Eq, Hash, Clone)]
7pub struct KX<'a> {
8    /// The preference (or priority) lowest values are prioritized.
9    pub preference: u16,
10    /// The DNS domain name of the key exchanger. This host must have an associated KEY RR.
11    pub exchanger: Name<'a>,
12}
13
14impl RR for KX<'_> {
15    const TYPE_CODE: u16 = 36;
16}
17
18impl<'a> WireFormat<'a> for KX<'a> {
19    const MINIMUM_LEN: usize = 2;
20
21    fn parse(data: &mut BytesBuffer<'a>) -> crate::Result<Self>
22    where
23        Self: Sized,
24    {
25        let preference = data.get_u16()?;
26        let exchanger = Name::parse(data)?;
27        Ok(Self {
28            preference,
29            exchanger,
30        })
31    }
32
33    fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
34        out.write_all(&self.preference.to_be_bytes())?;
35        self.exchanger.write_to(out)?;
36        Ok(())
37    }
38
39    fn len(&self) -> usize {
40        self.exchanger.len() + Self::MINIMUM_LEN
41    }
42}
43
44impl KX<'_> {
45    /// Transforms the inner data into its owned type
46    pub fn into_owned<'b>(self) -> KX<'b> {
47        KX {
48            preference: self.preference,
49            exchanger: self.exchanger.into_owned(),
50        }
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use crate::{rdata::RData, ResourceRecord};
57
58    use super::*;
59
60    #[test]
61    fn parse_and_write_kx() {
62        let kx = KX {
63            preference: 5,
64            exchanger: Name::new("example.com.").unwrap(),
65        };
66
67        let mut data = Vec::new();
68        kx.write_to(&mut data).unwrap();
69
70        let kx = KX::parse(&mut (&data[..]).into()).unwrap();
71        assert_eq!(kx.preference, 5);
72        assert_eq!(kx.exchanger, Name::new("example.com.").unwrap());
73    }
74
75    #[test]
76    fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
77        let sample_file = std::fs::read("samples/zonefile/KX.sample")?;
78
79        let sample_rdata = match ResourceRecord::parse(&mut (&sample_file[..]).into())?.rdata {
80            RData::KX(rdata) => rdata,
81            _ => unreachable!(),
82        };
83
84        assert_eq!(sample_rdata.preference, 5);
85        assert_eq!(sample_rdata.exchanger, Name::new("example.com.")?);
86
87        Ok(())
88    }
89}