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 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}