flex_dns/
rdata.rs

1mod a;
2mod ns;
3mod cname;
4mod soa;
5mod ptr;
6mod hinfo;
7mod mx;
8mod txt;
9mod rp;
10mod afsdb;
11mod sig;
12mod key;
13mod aaaa;
14mod loc;
15mod srv;
16mod naptr;
17mod kx;
18mod cert;
19mod dname;
20mod opt;
21mod apl;
22mod ds;
23mod sshfp;
24mod ipseckey;
25mod rrsig;
26mod nsec;
27mod dnskey;
28mod dhcid;
29mod nsec3;
30mod nsec3param;
31mod tlsa;
32mod smimea;
33mod hip;
34mod cds;
35mod cdnskey;
36mod openpgpkey;
37mod csync;
38mod zonemd;
39mod svcb;
40mod https;
41mod eui48;
42mod eui64;
43mod tkey;
44mod tsig;
45mod ixfr;
46mod axfr;
47mod uri;
48mod caa;
49mod ta;
50mod dlv;
51
52pub use a::A;
53pub use ns::Ns;
54pub use cname::CName;
55pub use soa::Soa;
56pub use ptr::Ptr;
57pub use hinfo::HInfo;
58pub use mx::Mx;
59pub use txt::Txt;
60pub use rp::Rp;
61pub use afsdb::AfsDb;
62pub use sig::Sig;
63pub use key::Key;
64pub use aaaa::Aaaa;
65pub use loc::Loc;
66pub use srv::Srv;
67pub use naptr::Naptr;
68pub use kx::Kx;
69pub use cert::Cert;
70pub use dname::DName;
71pub use opt::Opt;
72pub use apl::Apl;
73pub use ds::Ds;
74pub use sshfp::SshFp;
75pub use ipseckey::IpSecKey;
76pub use rrsig::RRSig;
77pub use nsec::Nsec;
78pub use dnskey::DnsKey;
79pub use dhcid::DhcId;
80pub use nsec3::Nsec3;
81pub use nsec3param::Nsec3Param;
82pub use tlsa::Tlsa;
83pub use smimea::SmimeA;
84pub use hip::Hip;
85pub use cds::Cds;
86pub use cdnskey::CdnsKey;
87pub use openpgpkey::OpenPgpKey;
88pub use csync::CSync;
89pub use zonemd::ZoneMd;
90pub use svcb::Svcb;
91pub use https::Https;
92pub use eui48::EUI48;
93pub use eui64::EUI64;
94pub use tkey::TKey;
95pub use tsig::TSig;
96pub use ixfr::IXfr;
97pub use axfr::AXfr;
98pub use uri::Uri;
99pub use caa::Caa;
100pub use ta::Ta;
101pub use dlv::Dlv;
102
103use crate::{Buffer, DnsError, DnsMessage, DnsMessageError, MutBuffer};
104use crate::parse::{Parse, ParseData};
105use crate::question::DnsQType;
106use crate::write::WriteBytes;
107
108#[derive(Debug, Clone, Copy, PartialEq)]
109pub struct RData<'a> {
110    buffer: &'a [u8],
111    pos: usize,
112    len: usize,
113    type_: DnsQType,
114}
115
116impl<'a> ParseData<'a> for RData<'a> {
117    #[inline(always)]
118    fn parse_data(&self) -> &'a [u8] {
119        self.buffer
120    }
121}
122
123impl<'a> ParseData<'a> for &'_ RData<'a> {
124    #[inline(always)]
125    fn parse_data(&self) -> &'a [u8] {
126        self.buffer
127    }
128}
129
130pub(crate) trait RDataParse<'a>: Sized {
131    fn parse(bytes: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError>;
132}
133
134impl<'a> RData<'a> {
135    #[inline(always)]
136    pub fn id(&self) -> u16 {
137        self.type_.id()
138    }
139
140    pub fn parse(bytes: &'a [u8], i: &mut usize, type_: DnsQType) -> Result<Self, DnsMessageError> {
141        let len = u16::parse(bytes, i)? as usize;
142        let pos = *i;
143
144        if pos + len > bytes.len() {
145            return Err(DnsMessageError::DnsError(DnsError::RDataLongerThanMessage));
146        }
147
148        *i += len;
149
150        Ok(RData { buffer: bytes, pos, len, type_ })
151    }
152
153    pub fn into_parsed(self) -> Result<DnsAType<'a>, DnsMessageError> {
154        let mut pos = self.pos;
155
156        Ok(match self.type_ {
157            DnsQType::A => DnsAType::A(A::parse(&self, &mut pos)?),
158            DnsQType::NS => DnsAType::NS(Ns::parse(&self, &mut pos)?),
159            DnsQType::CNAME => DnsAType::CName(CName::parse(&self, &mut pos)?),
160            DnsQType::SOA => DnsAType::Soa(Soa::parse(&self, &mut pos)?),
161            DnsQType::PTR => DnsAType::Ptr(Ptr::parse(&self, &mut pos)?),
162            DnsQType::HINFO => DnsAType::HInfo(HInfo::parse(&self, &mut pos)?),
163            DnsQType::MX => DnsAType::MX(Mx::parse(&self, &mut pos)?),
164            DnsQType::TXT => DnsAType::Txt(Txt::parse(&self, &mut pos)?),
165            DnsQType::RP => DnsAType::RP(Rp::parse(&self, &mut pos)?),
166            DnsQType::AFSDB => DnsAType::AFSDB(AfsDb::parse(&self, &mut pos)?),
167            DnsQType::SIG => DnsAType::SIG(Sig::parse(&self, &mut pos)?),
168            DnsQType::KEY => DnsAType::KEY(Key::parse(&self, &mut pos)?),
169            DnsQType::AAAA => DnsAType::AAAA(Aaaa::parse(&self, &mut pos)?),
170            DnsQType::LOC => DnsAType::Loc(Loc::parse(&self, &mut pos)?),
171            DnsQType::SRV => DnsAType::Srv(Srv::parse(&self, &mut pos)?),
172            DnsQType::NAPTR => DnsAType::Naptr(Naptr::parse(&self, &mut pos)?),
173            DnsQType::KX => DnsAType::KX(Kx::parse(&self, &mut pos)?),
174            DnsQType::CERT => DnsAType::Cert(Cert::parse(&self, &mut pos)?),
175            DnsQType::DNAME => DnsAType::DName(DName::parse(&self, &mut pos)?),
176            DnsQType::OPT => DnsAType::OPT(Opt::parse(&self, &mut pos)?),
177            DnsQType::APL => DnsAType::APL(Apl::parse(&self, &mut pos)?),
178            DnsQType::DS => DnsAType::DS(Ds::parse(&self, &mut pos)?),
179            DnsQType::SSHFP => DnsAType::SSHFP(SshFp::parse(&self, &mut pos)?),
180            DnsQType::IPSECKEY => DnsAType::IPSECKEY(IpSecKey::parse(&self, &mut pos)?),
181            DnsQType::RRSIG => DnsAType::RRSIG(RRSig::parse(&self, &mut pos)?),
182            DnsQType::NSEC => DnsAType::NSEC(Nsec::parse(&self, &mut pos)?),
183            DnsQType::DNSKEY => DnsAType::DNSKEY(DnsKey::parse(&self, &mut pos)?),
184            DnsQType::DHCID => DnsAType::DHCID(DhcId::parse(&self, &mut pos)?),
185            DnsQType::NSEC3 => DnsAType::NSEC3(Nsec3::parse(&self, &mut pos)?),
186            DnsQType::NSEC3PARAM => DnsAType::NSEC3PARAM(Nsec3Param::parse(&self, &mut pos)?),
187            DnsQType::TLSA => DnsAType::TLSA(Tlsa::parse(&self, &mut pos)?),
188            DnsQType::SMIMEA => DnsAType::SMIMEA(SmimeA::parse(&self, &mut pos)?),
189            DnsQType::HIP => DnsAType::HIP(Hip::parse(&self, &mut pos)?),
190            DnsQType::CDS => DnsAType::CDS(Cds::parse(&self, &mut pos)?),
191            DnsQType::CDNSKEY => DnsAType::CDNSKEY(CdnsKey::parse(&self, &mut pos)?),
192            DnsQType::OPENPGPKEY => DnsAType::OPENPGPKEY(OpenPgpKey::parse(&self, &mut pos)?),
193            DnsQType::CSYNC => DnsAType::CSYNC(CSync::parse(&self, &mut pos)?),
194            DnsQType::ZONEMD => DnsAType::ZONEMD(ZoneMd::parse(&self, &mut pos)?),
195            DnsQType::SVCB => DnsAType::SVCB(Svcb::parse(&self, &mut pos)?),
196            DnsQType::HTTPS => DnsAType::HTTPS(Https::parse(&self, &mut pos)?),
197            DnsQType::EUI48 => DnsAType::EUI48(EUI48::parse(&self, &mut pos)?),
198            DnsQType::EUI64 => DnsAType::EUI64(EUI64::parse(&self, &mut pos)?),
199            DnsQType::TKEY => DnsAType::TKEY(TKey::parse(&self, &mut pos)?),
200            DnsQType::TSIG => DnsAType::TSIG(TSig::parse(&self, &mut pos)?),
201            DnsQType::IXFR => DnsAType::IXFR(IXfr::parse(&self, &mut pos)?),
202            DnsQType::AXFR => DnsAType::AXFR(AXfr::parse(&self, &mut pos)?),
203            DnsQType::ALL => return Err(DnsMessageError::DnsError(DnsError::InvalidAnswer)),
204            DnsQType::URI => DnsAType::URI(Uri::parse(&self, &mut pos)?),
205            DnsQType::CAA => DnsAType::CAA(Caa::parse(&self, &mut pos)?),
206            DnsQType::TA => DnsAType::TA(Ta::parse(&self, &mut pos)?),
207            DnsQType::DLV => DnsAType::DLV(Dlv::parse(&self, &mut pos)?),
208            DnsQType::Reserved => return Err(DnsMessageError::DnsError(DnsError::InvalidAnswer)),
209        })
210    }
211}
212
213impl<'a> WriteBytes for RData<'a> {
214    fn write<
215        const PTR_STORAGE: usize,
216        const DNS_SECTION: usize,
217        B: MutBuffer + Buffer,
218    >(
219        &self,
220        message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>
221    ) -> Result<usize, DnsMessageError> {
222        let mut bytes = 0;
223
224        bytes += (self.len as u16).write(message)?;
225        bytes += message.write_bytes(&self.buffer[self.pos..self.pos + self.len])?;
226
227        Ok(bytes)
228    }
229}
230
231#[derive(Debug, Clone, Copy, PartialEq)]
232pub enum DnsAType<'a> {
233    A(A),
234    NS(Ns<'a>),
235    CName(CName<'a>),
236    Soa(Soa<'a>),
237    Ptr(Ptr<'a>),
238    HInfo(HInfo<'a>),
239    MX(Mx<'a>),
240    Txt(Txt<'a>),
241    RP(Rp<'a>),
242    AFSDB(AfsDb<'a>),
243    SIG(Sig<'a>),
244    KEY(Key<'a>),
245    AAAA(Aaaa),
246    Loc(Loc),
247    Srv(Srv<'a>),
248    Naptr(Naptr<'a>),
249    KX(Kx<'a>),
250    Cert(Cert<'a>),
251    DName(DName<'a>),
252    OPT(Opt<'a>),
253    APL(Apl<'a>),
254    DS(Ds<'a>),
255    SSHFP(SshFp<'a>),
256    IPSECKEY(IpSecKey<'a>),
257    RRSIG(RRSig<'a>),
258    NSEC(Nsec<'a>),
259    DNSKEY(DnsKey<'a>),
260    DHCID(DhcId<'a>),
261    NSEC3(Nsec3<'a>),
262    NSEC3PARAM(Nsec3Param<'a>),
263    TLSA(Tlsa<'a>),
264    SMIMEA(SmimeA<'a>),
265    HIP(Hip<'a>),
266    CDS(Cds<'a>),
267    CDNSKEY(CdnsKey<'a>),
268    OPENPGPKEY(OpenPgpKey<'a>),
269    CSYNC(CSync<'a>),
270    ZONEMD(ZoneMd<'a>),
271    SVCB(Svcb<'a>),
272    HTTPS(Https<'a>),
273    EUI48(EUI48),
274    EUI64(EUI64),
275    TKEY(TKey<'a>),
276    TSIG(TSig<'a>),
277    IXFR(IXfr<'a>),
278    AXFR(AXfr<'a>),
279    URI(Uri<'a>),
280    CAA(Caa<'a>),
281    TA(Ta<'a>),
282    DLV(Dlv<'a>),
283    /// Unknown
284    Reserved,
285}
286
287impl<'a> Into<DnsQType> for DnsAType<'a> {
288    #[inline(always)]
289    fn into(self) -> DnsQType {
290        match self {
291            DnsAType::A(_) => DnsQType::A,
292            DnsAType::NS(_) => DnsQType::NS,
293            DnsAType::CName(_) => DnsQType::CNAME,
294            DnsAType::Soa(_) => DnsQType::SOA,
295            DnsAType::Ptr(_) => DnsQType::PTR,
296            DnsAType::HInfo(_) => DnsQType::HINFO,
297            DnsAType::MX(_) => DnsQType::MX,
298            DnsAType::Txt(_) => DnsQType::TXT,
299            DnsAType::RP(_) => DnsQType::RP,
300            DnsAType::AFSDB(_) => DnsQType::AFSDB,
301            DnsAType::SIG(_) => DnsQType::SIG,
302            DnsAType::KEY(_) => DnsQType::KEY,
303            DnsAType::AAAA(_) => DnsQType::AAAA,
304            DnsAType::Loc(_) => DnsQType::LOC,
305            DnsAType::Srv(_) => DnsQType::SRV,
306            DnsAType::Naptr(_) => DnsQType::NAPTR,
307            DnsAType::KX(_) => DnsQType::KX,
308            DnsAType::Cert(_) => DnsQType::CERT,
309            DnsAType::DName(_) => DnsQType::DNAME,
310            DnsAType::OPT(_) => DnsQType::OPT,
311            DnsAType::APL(_) => DnsQType::APL,
312            DnsAType::DS(_) => DnsQType::DS,
313            DnsAType::SSHFP(_) => DnsQType::SSHFP,
314            DnsAType::IPSECKEY(_) => DnsQType::IPSECKEY,
315            DnsAType::RRSIG(_) => DnsQType::RRSIG,
316            DnsAType::NSEC(_) => DnsQType::NSEC,
317            DnsAType::DNSKEY(_) => DnsQType::DNSKEY,
318            DnsAType::DHCID(_) => DnsQType::DHCID,
319            DnsAType::NSEC3(_) => DnsQType::NSEC3,
320            DnsAType::NSEC3PARAM(_) => DnsQType::NSEC3PARAM,
321            DnsAType::TLSA(_) => DnsQType::TLSA,
322            DnsAType::SMIMEA(_) => DnsQType::SMIMEA,
323            DnsAType::HIP(_) => DnsQType::HIP,
324            DnsAType::CDS(_) => DnsQType::CDS,
325            DnsAType::CDNSKEY(_) => DnsQType::CDNSKEY,
326            DnsAType::OPENPGPKEY(_) => DnsQType::OPENPGPKEY,
327            DnsAType::CSYNC(_) => DnsQType::CSYNC,
328            DnsAType::ZONEMD(_) => DnsQType::ZONEMD,
329            DnsAType::SVCB(_) => DnsQType::SVCB,
330            DnsAType::HTTPS(_) => DnsQType::HTTPS,
331            DnsAType::EUI48(_) => DnsQType::EUI48,
332            DnsAType::EUI64(_) => DnsQType::EUI64,
333            DnsAType::TKEY(_) => DnsQType::TKEY,
334            DnsAType::TSIG(_) => DnsQType::TSIG,
335            DnsAType::IXFR(_) => DnsQType::IXFR,
336            DnsAType::AXFR(_) => DnsQType::AXFR,
337            DnsAType::URI(_) => DnsQType::URI,
338            DnsAType::CAA(_) => DnsQType::CAA,
339            DnsAType::TA(_) => DnsQType::TA,
340            DnsAType::DLV(_) => DnsQType::DLV,
341            DnsAType::Reserved => DnsQType::Reserved,
342        }
343    }
344}
345
346impl<'a> WriteBytes for DnsAType<'a> {
347    #[inline]
348    fn write<
349        const PTR_STORAGE: usize,
350        const DNS_SECTION: usize,
351        B: MutBuffer + Buffer,
352    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<usize, DnsMessageError> {
353        match self {
354            DnsAType::A(r) => r.write(message),
355            DnsAType::NS(r) => r.write(message),
356            DnsAType::CName(r) => r.write(message),
357            DnsAType::Soa(r) => r.write(message),
358            DnsAType::Ptr(r) => r.write(message),
359            DnsAType::HInfo(r) => r.write(message),
360            DnsAType::MX(r) => r.write(message),
361            DnsAType::Txt(r) => r.write(message),
362            DnsAType::RP(r) => r.write(message),
363            DnsAType::AFSDB(r) => r.write(message),
364            DnsAType::SIG(r) => r.write(message),
365            DnsAType::KEY(r) => r.write(message),
366            DnsAType::AAAA(r) => r.write(message),
367            DnsAType::Loc(r) => r.write(message),
368            DnsAType::Srv(r) => r.write(message),
369            DnsAType::Naptr(r) => r.write(message),
370            DnsAType::KX(r) => r.write(message),
371            DnsAType::Cert(r) => r.write(message),
372            DnsAType::DName(r) => r.write(message),
373            DnsAType::OPT(r) => r.write(message),
374            DnsAType::APL(r) => r.write(message),
375            DnsAType::DS(r) => r.write(message),
376            DnsAType::SSHFP(r) => r.write(message),
377            DnsAType::IPSECKEY(r) => r.write(message),
378            DnsAType::RRSIG(r) => r.write(message),
379            DnsAType::NSEC(r) => r.write(message),
380            DnsAType::DNSKEY(r) => r.write(message),
381            DnsAType::DHCID(r) => r.write(message),
382            DnsAType::NSEC3(r) => r.write(message),
383            DnsAType::NSEC3PARAM(r) => r.write(message),
384            DnsAType::TLSA(r) => r.write(message),
385            DnsAType::SMIMEA(r) => r.write(message),
386            DnsAType::HIP(r) => r.write(message),
387            DnsAType::CDS(r) => r.write(message),
388            DnsAType::CDNSKEY(r) => r.write(message),
389            DnsAType::OPENPGPKEY(r) => r.write(message),
390            DnsAType::CSYNC(r) => r.write(message),
391            DnsAType::ZONEMD(r) => r.write(message),
392            DnsAType::SVCB(r) => r.write(message),
393            DnsAType::HTTPS(r) => r.write(message),
394            DnsAType::EUI48(r) => r.write(message),
395            DnsAType::EUI64(r) => r.write(message),
396            DnsAType::TKEY(r) => r.write(message),
397            DnsAType::TSIG(r) => r.write(message),
398            DnsAType::IXFR(r) => r.write(message),
399            DnsAType::AXFR(r) => r.write(message),
400            DnsAType::URI(r) => r.write(message),
401            DnsAType::CAA(r) => r.write(message),
402            DnsAType::TA(r) => r.write(message),
403            DnsAType::DLV(r) => r.write(message),
404            DnsAType::Reserved => Err(DnsMessageError::DnsError(DnsError::InvalidAnswer)),
405        }
406    }
407}
408
409impl<'a> DnsAType<'a> {
410    #[inline(always)]
411    pub fn id(&self) -> u16 {
412        let qtype: DnsQType = (*self).into();
413        qtype.id()
414    }
415}
416
417#[cfg(test)]
418mod testutils {
419    use core::fmt::Debug;
420    use super::*;
421
422    #[cfg(feature = "vec")]
423    extern crate alloc;
424
425    pub(crate) fn parse_and_compare<
426        'a,
427        A: RDataParse<'a> + PartialEq + Debug,
428    >(bytes: &'a [u8], expected: A) {
429        let mut i = 0;
430        let rdata = RData {
431            buffer: bytes,
432            pos: 0,
433            len: bytes.len(),
434            type_: DnsQType::ALL,
435        };
436        let parsed = A::parse(&rdata, &mut i).unwrap();
437        assert_eq!(parsed, expected);
438    }
439
440    #[cfg(feature = "arrayvec")]
441    pub(crate) fn write_and_compare_arrayvec<
442        const N: usize,
443        A: WriteBytes + PartialEq + Debug,
444    >(a: A, expected: &[u8; N])
445        where
446            [(); crate::DNS_HEADER_SIZE + N]: Sized,
447    {
448        let mut message: DnsMessage<
449            0, 0, arrayvec::ArrayVec<u8, { crate::DNS_HEADER_SIZE + N }>
450        > = DnsMessage::new_mut(arrayvec::ArrayVec::new()).unwrap();
451        a.write(&mut message).unwrap();
452        let buffer = message.abort().unwrap();
453        assert_eq!(&buffer[crate::DNS_HEADER_SIZE..], expected.as_slice());
454    }
455
456    #[cfg(feature = "heapless")]
457    pub(crate) fn write_and_compare_heapless<
458        const N: usize,
459        A: WriteBytes + PartialEq + Debug,
460    >(a: A, expected: &[u8; N])
461        where
462            [(); crate::DNS_HEADER_SIZE + N]: Sized,
463    {
464        let mut message: DnsMessage<
465            0, 0, heapless::Vec<u8, { crate::DNS_HEADER_SIZE + N }>
466        > = DnsMessage::new_mut(heapless::Vec::new()).unwrap();
467        a.write(&mut message).unwrap();
468        let buffer = message.abort().unwrap();
469        assert_eq!(&buffer[crate::DNS_HEADER_SIZE..], expected.as_slice());
470    }
471
472    #[cfg(feature = "vec")]
473    pub(crate) fn write_and_compare_alloc<
474        const N: usize,
475        A: WriteBytes + PartialEq + Debug,
476    >(a: A, expected: &[u8; N])
477        where
478            [(); crate::DNS_HEADER_SIZE + N]: Sized,
479    {
480        let mut message: DnsMessage<
481            0, 0, alloc::vec::Vec<u8>
482        > = DnsMessage::new_mut(alloc::vec::Vec::new()).unwrap();
483        a.write(&mut message).unwrap();
484        let buffer = message.abort().unwrap();
485        assert_eq!(&buffer[crate::DNS_HEADER_SIZE..], expected.as_slice());
486    }
487
488    macro_rules! parse_write_test_macro {
489        (
490            $byte_count:literal,
491            [ $( $bytes:literal ),* $(,)? ],
492            $struct_name:ident { $( $content:ident: $content_builder:expr ),* $(,)? } $(,)?
493        ) => {
494            parse_write_test!(
495                $byte_count,
496                [ $( $bytes ),* ],
497                $struct_name { $( $content: $content_builder ),* },
498                parse,
499                write,
500            );
501        };
502        (
503            $byte_count:literal,
504            [ $( $bytes:literal ),* $(,)? ],
505            $struct_name:ident { $( $content:ident: $content_builder:expr ),* $(,)? },
506            $parse_name:ident,
507            $write_name:ident $(,)?
508        ) => {
509            #[test]
510            fn $parse_name() {
511                const BYTES: [u8; $byte_count] = [ $( $bytes ),* ];
512                const STRUCT: $struct_name = $struct_name {
513                    $( $content: $content_builder ),*
514                };
515
516                crate::rdata::testutils::parse_and_compare(&BYTES, STRUCT);
517            }
518
519            #[cfg(any(feature = "heapless", feature = "arrayvec", feature = "vec"))]
520            #[test]
521            fn $write_name() {
522                const BYTES: [u8; $byte_count] = [ $( $bytes ),* ];
523                const STRUCT: $struct_name = $struct_name {
524                    $( $content: $content_builder ),*
525                };
526
527                #[cfg(feature = "heapless")]
528                {
529                    crate::rdata::testutils::write_and_compare_heapless(STRUCT, &BYTES);
530                }
531                #[cfg(feature = "arrayvec")]
532                {
533                    crate::rdata::testutils::write_and_compare_arrayvec(STRUCT, &BYTES);
534                }
535                #[cfg(feature = "vec")]
536                {
537                    crate::rdata::testutils::write_and_compare_alloc(STRUCT, &BYTES);
538                }
539            }
540        };
541    }
542
543    pub(crate) use parse_write_test_macro as parse_write_test;
544}