flex_dns/rdata/
axfr.rs

1use crate::{Buffer, DnsMessage, DnsMessageError, MutBuffer};
2use crate::name::DnsName;
3use crate::parse::Parse;
4use crate::rdata::{RData, RDataParse};
5use crate::write::WriteBytes;
6
7/// # Authoritative zone transfer record (AXFR)
8/// This record is used to transfer an entire zone from a primary server to a
9/// secondary server.
10#[derive(Copy, Clone, Debug, PartialEq)]
11pub struct AXfr<'a> {
12    /// The domain name of the name server that was the
13    /// original or primary source of data for this zone
14    pub mname: DnsName<'a>,
15    /// A domain name which specifies the mailbox of the
16    /// person responsible for this zone
17    pub rname: DnsName<'a>,
18    /// The unsigned 32 bit version number of the original copy
19    /// of the zone. Zone transfers preserve this value. This
20    /// value wraps and should be compared using sequence space
21    /// arithmetic
22    pub serial: u32,
23    /// A 32 bit time interval before the zone should be
24    /// refreshed
25    pub refresh: u32,
26    /// A 32 bit time interval that should elapse before a
27    /// failed refresh should be retried
28    pub retry: u32,
29    /// A 32 bit time value that specifies the upper limit on
30    /// the time interval that can elapse before the zone is no
31    /// longer authoritative
32    pub expire: u32,
33    /// The unsigned 32 bit minimum TTL field that should be
34    /// exported with any RR from this zone
35    pub minimum: u32,
36}
37
38impl<'a> RDataParse<'a> for AXfr<'a> {
39    #[inline]
40    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
41        let mname = DnsName::parse(rdata.buffer, i)?;
42        let rname = DnsName::parse(rdata.buffer, i)?;
43        let serial = u32::parse(rdata.buffer, i)?;
44        let refresh = u32::parse(rdata.buffer, i)?;
45        let retry = u32::parse(rdata.buffer, i)?;
46        let expire = u32::parse(rdata.buffer, i)?;
47        let minimum = u32::parse(rdata.buffer, i)?;
48
49        Ok(Self {
50            mname,
51            rname,
52            serial,
53            refresh,
54            retry,
55            expire,
56            minimum,
57        })
58    }
59}
60
61impl<'a> WriteBytes for AXfr<'a> {
62    #[inline]
63    fn write<
64        const PTR_STORAGE: usize,
65        const DNS_SECTION: usize,
66        B: MutBuffer + Buffer,
67    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<usize, DnsMessageError> {
68        let mut bytes = 0;
69
70        bytes += self.mname.write(message)?;
71        bytes += self.rname.write(message)?;
72        bytes += self.serial.write(message)?;
73        bytes += self.refresh.write(message)?;
74        bytes += self.retry.write(message)?;
75        bytes += self.expire.write(message)?;
76        bytes += self.minimum.write(message)?;
77
78        Ok(bytes)
79    }
80}
81
82#[cfg(test)]
83mod test {
84    use crate::rdata::testutils::parse_write_test;
85
86    use super::*;
87
88    parse_write_test!(
89        45,
90        [
91            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 0x03, b'c', b'o', b'm', 0x00, // example.com
92            0x06, b'g', b'o', b'o', b'g', b'l', b'e', 0x03, b'c', b'o', b'm', 0x00, // google.com
93            0x00, 0x00, 0x00, 0x01, // Serial
94            0x00, 0x00, 0x00, 0x02, // Refresh
95            0x00, 0x00, 0x00, 0x03, // Retry
96            0x00, 0x00, 0x00, 0x04, // Expire
97            0x00, 0x00, 0x00, 0x05, // Minimum
98        ],
99        AXfr {
100            mname: unsafe { DnsName::new_unchecked(b"\x07example\x03com\x00") },
101            rname: unsafe { DnsName::new_unchecked(b"\x06google\x03com\x00") },
102            serial: 1,
103            refresh: 2,
104            retry: 3,
105            expire: 4,
106            minimum: 5,
107        }
108    );
109}