simple_dns/dns/rdata/
nsap.rs

1use crate::{bytes_buffer::BytesBuffer, dns::WireFormat};
2
3use super::RR;
4
5#[derive(Debug, PartialEq, Eq, Hash, Clone)]
6/// NSAP structure [RFC 1706](https://datatracker.ietf.org/doc/html/rfc1706)  
7///  ATTENTION: this code doesn't validade the content of the NSAP RR, it just split the bytes in the correct order
8pub struct NSAP {
9    /// Authority and Format Identifier
10    pub afi: u8,
11    /// Initial Domain Identifier
12    pub idi: u16,
13    /// DSP Format Identifier
14    pub dfi: u8,
15    /// Administrative Authority
16    pub aa: u32,
17    /// Reserved
18    pub rsvd: u16,
19    /// Routing Domain Identifier
20    pub rd: u16,
21    /// Area Identifier
22    pub area: u16,
23    /// System Identifier
24    pub id: u64,
25    /// NSAP Selector
26    pub sel: u8,
27}
28
29impl RR for NSAP {
30    const TYPE_CODE: u16 = 22;
31}
32
33impl NSAP {
34    /// Transforms the inner data into its owned type
35    pub fn into_owned(self) -> Self {
36        self
37    }
38}
39
40impl<'a> WireFormat<'a> for NSAP {
41    const MINIMUM_LEN: usize = 20;
42
43    fn parse(data: &mut BytesBuffer<'a>) -> crate::Result<Self>
44    where
45        Self: Sized,
46    {
47        let afi = data.get_u8()?;
48        let idi = data.get_u16()?;
49
50        let dfi = data.get_u8()?;
51        let aa: [u8; 3] = data.get_array()?;
52        let aa = u32::from_be_bytes([0, aa[0], aa[1], aa[2]]);
53
54        let rsvd = data.get_u16()?;
55        let rd = data.get_u16()?;
56
57        let area = data.get_u16()?;
58        let id: [u8; 6] = data.get_array()?;
59        let id = u64::from_be_bytes([0, 0, id[0], id[1], id[2], id[3], id[4], id[5]]);
60        let sel = data.get_u8()?;
61
62        Ok(Self {
63            afi,
64            idi,
65            dfi,
66            aa,
67            rsvd,
68            rd,
69            area,
70            id,
71            sel,
72        })
73    }
74
75    fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
76        out.write_all(&[self.afi.to_be()])?;
77        out.write_all(&self.idi.to_be_bytes())?;
78        out.write_all(&[self.dfi.to_be()])?;
79        out.write_all(&self.aa.to_be_bytes()[1..4])?;
80        out.write_all(&self.rsvd.to_be_bytes())?;
81        out.write_all(&self.rd.to_be_bytes())?;
82        out.write_all(&self.area.to_be_bytes())?;
83        out.write_all(&self.id.to_be_bytes()[2..8])?;
84        out.write_all(&[self.sel.to_be()])?;
85
86        Ok(())
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use crate::{rdata::RData, ResourceRecord};
93
94    use super::*;
95
96    #[test]
97    pub fn parse_and_write_nsap() {
98        let nsap = NSAP {
99            afi: 47,
100            idi: 5,
101            dfi: 0x80,
102            aa: 0x005a00,
103            rsvd: 0x10,
104            rd: 0x1000,
105            area: 0x0020,
106            id: 0x00800a123456,
107            sel: 0x10,
108        };
109
110        let mut data = Vec::new();
111        assert!(nsap.write_to(&mut data).is_ok());
112        assert_eq!(20, data.len());
113
114        let nsap = NSAP::parse(&mut data[..].into());
115        assert!(nsap.is_ok());
116        let nsap = nsap.unwrap();
117
118        assert_eq!(data.len(), nsap.len());
119        assert_eq!(47, nsap.afi);
120        assert_eq!(5, nsap.idi);
121        assert_eq!(0x80, nsap.dfi);
122        assert_eq!(0x005a00, nsap.aa);
123        assert_eq!(0x10, nsap.rsvd);
124        assert_eq!(0x1000, nsap.rd);
125        assert_eq!(0x0020, nsap.area);
126        assert_eq!(0x00800a123456, nsap.id);
127        assert_eq!(0x10, nsap.sel);
128    }
129
130    #[test]
131    fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
132        let sample_file = std::fs::read("samples/zonefile/NSAP.sample")?;
133
134        let sample_rdata = match ResourceRecord::parse(&mut sample_file[..].into())?.rdata {
135            RData::NSAP(rdata) => rdata,
136            _ => unreachable!(),
137        };
138
139        //  0x47.0005.80.005a00.0000.0001.e133.ffffff000164.00
140        assert_eq!(0x47, sample_rdata.afi);
141        assert_eq!(0x0005, sample_rdata.idi);
142        assert_eq!(0x80, sample_rdata.dfi);
143        assert_eq!(0x005a00, sample_rdata.aa);
144        assert_eq!(0x00, sample_rdata.rsvd);
145        assert_eq!(0x0001, sample_rdata.rd);
146        assert_eq!(0xe133, sample_rdata.area);
147        assert_eq!(0xffffff000164, sample_rdata.id);
148        assert_eq!(0x00, sample_rdata.sel);
149
150        Ok(())
151    }
152}