simple_dns/dns/rdata/
nsap.rs1use crate::{bytes_buffer::BytesBuffer, dns::WireFormat};
2
3use super::RR;
4
5#[derive(Debug, PartialEq, Eq, Hash, Clone)]
6pub struct NSAP {
9 pub afi: u8,
11 pub idi: u16,
13 pub dfi: u8,
15 pub aa: u32,
17 pub rsvd: u16,
19 pub rd: u16,
21 pub area: u16,
23 pub id: u64,
25 pub sel: u8,
27}
28
29impl RR for NSAP {
30 const TYPE_CODE: u16 = 22;
31}
32
33impl NSAP {
34 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 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}