flex_dns/rdata/
soa.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/// # Marks the start of a zone of authority
8/// This record is used to mark the start of a zone of authority
9/// and contains the parameters of the zone
10#[derive(Copy, Clone, Debug, PartialEq)]
11pub struct Soa<'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 Soa<'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 Soa<'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        53,
90        [
91            0x03, b'w', b'w', b'w',
92            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
93            0x03, b'c', b'o', b'm',
94            0x00, // mname
95            0x03, b'w', b'w', b'w',
96            0x06, b'g', b'o', b'o', b'g', b'l', b'e',
97            0x03, b'c', b'o', b'm',
98            0x00, // rname
99            0x00, 0x00, 0x00, 0x0e, // serial
100            0x00, 0x00, 0x00, 0x0f, // refresh
101            0x00, 0x00, 0x00, 0x10, // retry
102            0x00, 0x00, 0x00, 0x11, // expire
103            0x00, 0x00, 0x00, 0x12, // minimum
104        ],
105        Soa {
106            mname: unsafe { DnsName::new_unchecked(b"\x03www\x07example\x03com\x00") },
107            rname: unsafe { DnsName::new_unchecked(b"\x03www\x06google\x03com\x00") },
108            serial: 14,
109            refresh: 15,
110            retry: 16,
111            expire: 17,
112            minimum: 18,
113        },
114    );
115}