1use crate::core::MtopError;
2use crate::dns::bytes::{read_be_u8, read_be_u16, read_be_u32, write_be_u8, write_be_u16, write_be_u32};
3use crate::dns::core::RecordType;
4use crate::dns::name::Name;
5use std::fmt::{self, Display};
6use std::io::{Read, Seek, Write};
7use std::net::{Ipv4Addr, Ipv6Addr};
8
9#[derive(Debug, Clone, Eq, PartialEq)]
10pub enum RecordData {
11 A(RecordDataA),
12 NS(RecordDataNS),
13 CNAME(RecordDataCNAME),
14 SOA(RecordDataSOA),
15 TXT(RecordDataTXT),
16 AAAA(RecordDataAAAA),
17 SRV(RecordDataSRV),
18 OPT(RecordDataOpt),
19 Unknown(RecordDataUnknown),
20}
21
22impl RecordData {
23 pub fn size(&self) -> usize {
24 match self {
25 Self::A(rd) => rd.size(),
26 Self::NS(rd) => rd.size(),
27 Self::CNAME(rd) => rd.size(),
28 Self::SOA(rd) => rd.size(),
29 Self::TXT(rd) => rd.size(),
30 Self::AAAA(rd) => rd.size(),
31 Self::SRV(rd) => rd.size(),
32 Self::OPT(rd) => rd.size(),
33 Self::Unknown(rd) => rd.size(),
34 }
35 }
36
37 pub fn write_network_bytes<T>(&self, buf: T) -> Result<(), MtopError>
38 where
39 T: Write,
40 {
41 match self {
42 Self::A(rd) => rd.write_network_bytes(buf),
43 Self::NS(rd) => rd.write_network_bytes(buf),
44 Self::CNAME(rd) => rd.write_network_bytes(buf),
45 Self::SOA(rd) => rd.write_network_bytes(buf),
46 Self::TXT(rd) => rd.write_network_bytes(buf),
47 Self::AAAA(rd) => rd.write_network_bytes(buf),
48 Self::SRV(rd) => rd.write_network_bytes(buf),
49 Self::OPT(rd) => rd.write_network_bytes(buf),
50 Self::Unknown(rd) => rd.write_network_bytes(buf),
51 }
52 }
53
54 pub fn read_network_bytes<T>(rtype: RecordType, rdata_len: u16, buf: T) -> Result<Self, MtopError>
55 where
56 T: Read + Seek,
57 {
58 match rtype {
59 RecordType::A => Ok(RecordData::A(RecordDataA::read_network_bytes(buf)?)),
60 RecordType::NS => Ok(RecordData::NS(RecordDataNS::read_network_bytes(buf)?)),
61 RecordType::CNAME => Ok(RecordData::CNAME(RecordDataCNAME::read_network_bytes(buf)?)),
62 RecordType::SOA => Ok(RecordData::SOA(RecordDataSOA::read_network_bytes(buf)?)),
63 RecordType::TXT => Ok(RecordData::TXT(RecordDataTXT::read_network_bytes(rdata_len, buf)?)),
64 RecordType::AAAA => Ok(RecordData::AAAA(RecordDataAAAA::read_network_bytes(buf)?)),
65 RecordType::SRV => Ok(RecordData::SRV(RecordDataSRV::read_network_bytes(buf)?)),
66 RecordType::OPT => Ok(RecordData::OPT(RecordDataOpt::read_network_bytes(rdata_len, buf)?)),
67 RecordType::Unknown(_) => Ok(RecordData::Unknown(RecordDataUnknown::read_network_bytes(
68 rdata_len, buf,
69 )?)),
70 }
71 }
72}
73
74impl Display for RecordData {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 match self {
77 RecordData::A(rd) => Display::fmt(rd, f),
78 RecordData::NS(rd) => Display::fmt(rd, f),
79 RecordData::CNAME(rd) => Display::fmt(rd, f),
80 RecordData::SOA(rd) => Display::fmt(rd, f),
81 RecordData::TXT(rd) => Display::fmt(rd, f),
82 RecordData::AAAA(rd) => Display::fmt(rd, f),
83 RecordData::SRV(rd) => Display::fmt(rd, f),
84 RecordData::OPT(rd) => Display::fmt(rd, f),
85 RecordData::Unknown(rd) => Display::fmt(rd, f),
86 }
87 }
88}
89
90#[derive(Debug, Clone, Eq, PartialEq)]
91pub struct RecordDataA(Ipv4Addr);
92
93impl RecordDataA {
94 pub fn new(addr: Ipv4Addr) -> Self {
95 Self(addr)
96 }
97
98 pub fn addr(&self) -> Ipv4Addr {
99 self.0
100 }
101
102 pub fn size(&self) -> usize {
103 4
104 }
105
106 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
107 where
108 T: Write,
109 {
110 Ok(buf.write_all(&self.0.octets())?)
111 }
112
113 pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
114 where
115 T: Read + Seek,
116 {
117 let mut bytes = [0_u8; 4];
118 buf.read_exact(&mut bytes)?;
119 Ok(RecordDataA::new(Ipv4Addr::from(bytes)))
120 }
121}
122
123impl Display for RecordDataA {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 Display::fmt(&self.0, f)
126 }
127}
128
129#[derive(Debug, Clone, Eq, PartialEq)]
130pub struct RecordDataNS(Name);
131
132impl RecordDataNS {
133 pub fn new(name: Name) -> Self {
134 Self(name)
135 }
136
137 pub fn name(&self) -> &Name {
138 &self.0
139 }
140
141 pub fn size(&self) -> usize {
142 self.0.size()
143 }
144
145 pub fn write_network_bytes<T>(&self, buf: T) -> Result<(), MtopError>
146 where
147 T: Write,
148 {
149 self.0.write_network_bytes(buf)
150 }
151
152 pub fn read_network_bytes<T>(buf: T) -> Result<Self, MtopError>
153 where
154 T: Read + Seek,
155 {
156 Ok(Self::new(Name::read_network_bytes(buf)?))
157 }
158}
159
160impl Display for RecordDataNS {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 Display::fmt(&self.0, f)
163 }
164}
165
166#[derive(Debug, Clone, Eq, PartialEq)]
167pub struct RecordDataCNAME(Name);
168
169impl RecordDataCNAME {
170 pub fn new(name: Name) -> Self {
171 Self(name)
172 }
173
174 pub fn name(&self) -> &Name {
175 &self.0
176 }
177
178 pub fn size(&self) -> usize {
179 self.0.size()
180 }
181
182 pub fn write_network_bytes<T>(&self, buf: T) -> Result<(), MtopError>
183 where
184 T: Write,
185 {
186 self.0.write_network_bytes(buf)
187 }
188
189 pub fn read_network_bytes<T>(buf: T) -> Result<Self, MtopError>
190 where
191 T: Read + Seek,
192 {
193 Ok(Self::new(Name::read_network_bytes(buf)?))
194 }
195}
196impl Display for RecordDataCNAME {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 Display::fmt(&self.0, f)
199 }
200}
201
202#[derive(Debug, Clone, Eq, PartialEq)]
203pub struct RecordDataSOA {
204 mname: Name,
205 rname: Name,
206 serial: u32,
207 refresh: u32,
208 retry: u32,
209 expire: u32,
210 minimum: u32,
211}
212
213impl RecordDataSOA {
214 pub fn new(mname: Name, rname: Name, serial: u32, refresh: u32, retry: u32, expire: u32, minimum: u32) -> Self {
215 Self {
216 mname,
217 rname,
218 serial,
219 refresh,
220 retry,
221 expire,
222 minimum,
223 }
224 }
225
226 pub fn mname(&self) -> &Name {
227 &self.mname
228 }
229
230 pub fn rname(&self) -> &Name {
231 &self.rname
232 }
233
234 pub fn serial(&self) -> u32 {
235 self.serial
236 }
237
238 pub fn refresh(&self) -> u32 {
239 self.refresh
240 }
241
242 pub fn retry(&self) -> u32 {
243 self.retry
244 }
245
246 pub fn expire(&self) -> u32 {
247 self.expire
248 }
249
250 pub fn minimum(&self) -> u32 {
251 self.minimum
252 }
253
254 pub fn size(&self) -> usize {
255 self.mname.size() + self.rname.size() + (4 * 5)
256 }
257
258 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
259 where
260 T: Write,
261 {
262 self.mname.write_network_bytes(&mut buf)?;
263 self.rname.write_network_bytes(&mut buf)?;
264 write_be_u32(&mut buf, self.serial)?;
265 write_be_u32(&mut buf, self.refresh)?;
266 write_be_u32(&mut buf, self.retry)?;
267 write_be_u32(&mut buf, self.expire)?;
268 write_be_u32(&mut buf, self.minimum)?;
269 Ok(())
270 }
271
272 pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
273 where
274 T: Read + Seek,
275 {
276 let mname = Name::read_network_bytes(&mut buf)?;
277 let rname = Name::read_network_bytes(&mut buf)?;
278 let serial = read_be_u32(&mut buf)?;
279 let refresh = read_be_u32(&mut buf)?;
280 let retry = read_be_u32(&mut buf)?;
281 let expire = read_be_u32(&mut buf)?;
282 let minimum = read_be_u32(&mut buf)?;
283
284 Ok(Self::new(mname, rname, serial, refresh, retry, expire, minimum))
285 }
286}
287
288impl Display for RecordDataSOA {
289 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290 write!(
291 f,
292 "{} {} {} {} {} {} {}",
293 self.mname, self.rname, self.serial, self.refresh, self.retry, self.expire, self.minimum
294 )
295 }
296}
297
298#[derive(Debug, Clone, Eq, PartialEq)]
299pub struct RecordDataTXT(Vec<Vec<u8>>);
300
301impl RecordDataTXT {
302 const MAX_LENGTH: usize = 65535;
303 const MAX_SEGMENT_LENGTH: usize = 255;
304
305 pub fn new<I, B>(items: I) -> Result<Self, MtopError>
306 where
307 I: IntoIterator<Item = B>,
308 B: Into<Vec<u8>>,
309 {
310 let mut segments = Vec::new();
311 let mut total = 0;
312
313 for txt in items {
314 let bytes = txt.into();
315 if bytes.len() > Self::MAX_SEGMENT_LENGTH {
316 return Err(MtopError::runtime(format!(
317 "TXT record segment too long; {} bytes, max {} bytes",
318 bytes.len(),
319 Self::MAX_SEGMENT_LENGTH
320 )));
321 }
322
323 total += 1 + bytes.len();
327 if total > Self::MAX_LENGTH {
328 return Err(MtopError::runtime(format!(
329 "TXT record too long; {} bytes, max {} bytes",
330 total,
331 Self::MAX_LENGTH
332 )));
333 }
334
335 segments.push(bytes);
336 }
337
338 Ok(Self(segments))
339 }
340
341 pub fn bytes(&self) -> &Vec<Vec<u8>> {
342 &self.0
343 }
344
345 pub fn size(&self) -> usize {
346 self.0.iter().map(Vec::len).sum::<usize>() + self.0.len()
349 }
350
351 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
352 where
353 T: Write,
354 {
355 for txt in &self.0 {
356 assert!(
357 txt.len() <= Self::MAX_SEGMENT_LENGTH,
358 "segment size of {} exceeds maximum of {}",
359 txt.len(),
360 Self::MAX_SEGMENT_LENGTH,
361 );
362
363 write_be_u8(&mut buf, u8::try_from(txt.len()).unwrap())?;
364 buf.write_all(txt)?;
365 }
366
367 Ok(())
368 }
369
370 pub fn read_network_bytes<T>(rdata_len: u16, mut buf: T) -> Result<Self, MtopError>
371 where
372 T: Read + Seek,
373 {
374 let rdata_len = usize::from(rdata_len);
375 let mut all = Vec::new();
376 let mut consumed = 0;
377
378 while consumed < rdata_len {
379 let len = read_be_u8(&mut buf)?;
380 if usize::from(len) + consumed > rdata_len {
381 return Err(MtopError::runtime(format!(
382 "text for RecordDataTXT exceeds rdata size; len: {}, consumed: {}, rdata: {}",
383 len, consumed, rdata_len
384 )));
385 }
386
387 let mut txt = Vec::with_capacity(usize::from(len));
388 let mut handle = buf.take(u64::from(len));
389 let n = handle.read_to_end(&mut txt)?;
390 if n != usize::from(len) {
391 return Err(MtopError::runtime(format!(
392 "short read for RecordDataTXT text; expected {}, got {}",
393 len, n
394 )));
395 }
396
397 all.push(txt);
398 consumed += n + 1;
399 buf = handle.into_inner();
400 }
401
402 Self::new(all)
403 }
404}
405
406impl Display for RecordDataTXT {
407 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408 for txt in &self.0 {
409 write!(f, "\"{}\"", String::from_utf8_lossy(txt).replace('\"', "\\\""))?;
414 }
415
416 Ok(())
417 }
418}
419
420#[derive(Debug, Clone, Eq, PartialEq)]
421pub struct RecordDataAAAA(Ipv6Addr);
422
423impl RecordDataAAAA {
424 pub fn new(addr: Ipv6Addr) -> Self {
425 Self(addr)
426 }
427
428 pub fn addr(&self) -> Ipv6Addr {
429 self.0
430 }
431
432 pub fn size(&self) -> usize {
433 16
434 }
435
436 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
437 where
438 T: Write,
439 {
440 Ok(buf.write_all(&self.0.octets())?)
441 }
442
443 pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
444 where
445 T: Read + Seek,
446 {
447 let mut bytes = [0_u8; 16];
448 buf.read_exact(&mut bytes)?;
449 Ok(RecordDataAAAA::new(Ipv6Addr::from(bytes)))
450 }
451}
452
453impl Display for RecordDataAAAA {
454 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
455 Display::fmt(&self.0, f)
456 }
457}
458
459#[derive(Debug, Clone, Eq, PartialEq)]
460pub struct RecordDataSRV {
461 priority: u16,
462 weight: u16,
463 port: u16,
464 target: Name,
465}
466
467impl RecordDataSRV {
468 pub fn new(priority: u16, weight: u16, port: u16, target: Name) -> Self {
469 Self {
470 priority,
471 weight,
472 port,
473 target,
474 }
475 }
476
477 pub fn priority(&self) -> u16 {
478 self.priority
479 }
480
481 pub fn weight(&self) -> u16 {
482 self.weight
483 }
484
485 pub fn port(&self) -> u16 {
486 self.port
487 }
488
489 pub fn target(&self) -> &Name {
490 &self.target
491 }
492
493 pub fn size(&self) -> usize {
494 (2 * 3) + self.target.size()
495 }
496
497 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
498 where
499 T: Write,
500 {
501 write_be_u16(&mut buf, self.priority)?;
502 write_be_u16(&mut buf, self.weight)?;
503 write_be_u16(&mut buf, self.port)?;
504 self.target.write_network_bytes(buf)
505 }
506
507 pub fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
508 where
509 T: Read + Seek,
510 {
511 let priority = read_be_u16(&mut buf)?;
512 let weight = read_be_u16(&mut buf)?;
513 let port = read_be_u16(&mut buf)?;
514 let target = Name::read_network_bytes(buf)?;
515
516 Ok(Self::new(priority, weight, port, target))
517 }
518}
519
520impl Display for RecordDataSRV {
521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
522 write!(f, "{} {} {} {}", self.priority, self.weight, self.port, self.target)
523 }
524}
525
526#[derive(Debug, Clone, Eq, PartialEq)]
527pub struct RecordDataOptPair {
528 code: u16,
529 data: Vec<u8>,
530}
531
532impl RecordDataOptPair {
533 const MAX_DATA_LENGTH: usize = 65535;
534
535 pub fn new(code: u16, data: Vec<u8>) -> Result<Self, MtopError> {
536 if data.len() > Self::MAX_DATA_LENGTH {
537 Err(MtopError::runtime(format!(
538 "OPT attribute data too long; {} bytes, max {} bytes",
539 data.len(),
540 Self::MAX_DATA_LENGTH,
541 )))
542 } else {
543 Ok(Self { code, data })
544 }
545 }
546
547 pub fn code(&self) -> u16 {
548 self.code
549 }
550
551 pub fn data(&self) -> &[u8] {
552 &self.data
553 }
554
555 fn size(&self) -> usize {
556 2 + 2 + self.data.len() }
558
559 fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
560 where
561 T: Write,
562 {
563 assert!(
564 self.data.len() <= Self::MAX_DATA_LENGTH,
565 "data size of {} exceeds maximum of {}",
566 self.data.len(),
567 Self::MAX_DATA_LENGTH,
568 );
569
570 write_be_u16(&mut buf, self.code)?;
571 write_be_u16(&mut buf, u16::try_from(self.data.len()).unwrap())?;
572 Ok(buf.write_all(&self.data)?)
573 }
574
575 fn read_network_bytes<T>(mut buf: T) -> Result<Self, MtopError>
576 where
577 T: Read + Seek,
578 {
579 let code = read_be_u16(&mut buf)?;
580 let data_len = read_be_u16(&mut buf)?;
581 let mut data = Vec::with_capacity(usize::from(data_len));
582 buf.take(u64::from(data_len)).read_to_end(&mut data)?;
583 Ok(Self { code, data })
584 }
585}
586
587impl Display for RecordDataOptPair {
588 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
589 write!(f, "{}: {}", self.code, String::from_utf8_lossy(&self.data))
590 }
591}
592
593#[derive(Debug, Clone, Eq, PartialEq)]
594pub struct RecordDataOpt {
595 options: Vec<RecordDataOptPair>,
596}
597
598impl RecordDataOpt {
599 const MAX_LENGTH: usize = 65535;
600
601 pub fn new(options: Vec<RecordDataOptPair>) -> Result<Self, MtopError> {
602 let size = Self::options_size(&options);
603 if size > Self::MAX_LENGTH {
604 Err(MtopError::runtime(format!(
605 "OPT record data too long; {} bytes, max {} bytes",
606 size,
607 Self::MAX_LENGTH,
608 )))
609 } else {
610 Ok(Self { options })
611 }
612 }
613
614 fn options_size(opts: &[RecordDataOptPair]) -> usize {
615 opts.iter().map(RecordDataOptPair::size).sum()
616 }
617
618 pub fn options(&self) -> &[RecordDataOptPair] {
619 &self.options
620 }
621
622 pub fn size(&self) -> usize {
623 Self::options_size(&self.options)
624 }
625
626 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
627 where
628 T: Write,
629 {
630 for opt in &self.options {
631 opt.write_network_bytes(&mut buf)?;
632 }
633
634 Ok(())
635 }
636
637 pub fn read_network_bytes<T>(rdata_len: u16, mut buf: T) -> Result<Self, MtopError>
638 where
639 T: Read + Seek,
640 {
641 let rdata_len = usize::from(rdata_len);
642 let mut options = Vec::new();
643 let mut consumed = 0;
644
645 while consumed < rdata_len {
646 let opt = RecordDataOptPair::read_network_bytes(&mut buf)?;
647 consumed += opt.size();
648 options.push(opt);
649 }
650
651 Ok(Self { options })
652 }
653}
654
655impl Display for RecordDataOpt {
656 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
657 for opt in &self.options {
658 write!(f, "{}", opt)?;
659 }
660
661 Ok(())
662 }
663}
664
665#[derive(Debug, Clone, Eq, PartialEq)]
666pub struct RecordDataUnknown(Vec<u8>);
667
668impl RecordDataUnknown {
669 const MAX_LENGTH: usize = 65535;
670
671 pub fn new(bytes: Vec<u8>) -> Result<Self, MtopError> {
672 if bytes.len() > Self::MAX_LENGTH {
673 Err(MtopError::runtime(format!(
674 "record data too long; {} bytes, max {} bytes",
675 bytes.len(),
676 Self::MAX_LENGTH
677 )))
678 } else {
679 Ok(Self(bytes))
680 }
681 }
682
683 pub fn size(&self) -> usize {
684 self.0.len()
685 }
686
687 pub fn write_network_bytes<T>(&self, mut buf: T) -> Result<(), MtopError>
688 where
689 T: Write,
690 {
691 buf.write_all(&self.0)?;
692 Ok(())
693 }
694
695 pub fn read_network_bytes<T>(rdata_len: u16, buf: T) -> Result<Self, MtopError>
696 where
697 T: Read + Seek,
698 {
699 let mut bytes = Vec::with_capacity(usize::from(rdata_len));
700 let n = buf.take(u64::from(rdata_len)).read_to_end(&mut bytes)?;
701
702 if n == usize::from(rdata_len) {
703 Self::new(bytes)
704 } else {
705 Err(MtopError::runtime(format!(
706 "short read for RecordDataUnknown; expected {} got {}",
707 rdata_len, n
708 )))
709 }
710 }
711}
712
713impl Display for RecordDataUnknown {
714 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
715 write!(f, "[unknown]")
716 }
717}
718
719#[cfg(test)]
720mod test {
721 use super::{
722 RecordDataA, RecordDataAAAA, RecordDataCNAME, RecordDataNS, RecordDataOptPair, RecordDataSOA, RecordDataSRV,
723 RecordDataTXT,
724 };
725 use crate::dns::RecordDataOpt;
726 use crate::dns::name::Name;
727 use std::io::Cursor;
728 use std::net::{Ipv4Addr, Ipv6Addr};
729 use std::str::FromStr;
730
731 #[test]
732 fn test_record_data_a_write_network_bytes() {
733 let rdata = RecordDataA::new(Ipv4Addr::LOCALHOST);
734
735 let mut cur = Cursor::new(Vec::new());
736 rdata.write_network_bytes(&mut cur).unwrap();
737 let buf = cur.into_inner();
738
739 assert_eq!(vec![127, 0, 0, 1], buf);
740 }
741 #[test]
742 fn test_record_data_a_read_network_bytes() {
743 let cur = Cursor::new(vec![127, 0, 0, 1]);
744 let rdata = RecordDataA::read_network_bytes(cur).unwrap();
745
746 assert_eq!(Ipv4Addr::LOCALHOST, rdata.addr());
747 }
748
749 #[rustfmt::skip]
750 #[test]
751 fn test_record_data_ns_write_network_bytes() {
752 let name = Name::from_str("ns.example.com.").unwrap();
753 let ns = RecordDataNS::new(name);
754
755 let mut cur = Cursor::new(Vec::new());
756 ns.write_network_bytes(&mut cur).unwrap();
757 let buf = cur.into_inner();
758
759 assert_eq!(
760 vec![
761 2, 110, 115, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ],
769 buf,
770 );
771 }
772
773 #[rustfmt::skip]
774 #[test]
775 fn test_record_data_ns_read_network_bytes() {
776 let cur = Cursor::new(vec![
777 2, 110, 115, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ]);
785
786 let rdata = RecordDataNS::read_network_bytes(cur).unwrap();
787 assert_eq!("ns.example.com.", rdata.name().to_string());
788 }
789
790 #[rustfmt::skip]
791 #[test]
792 fn test_record_data_cname_write_network_bytes() {
793 let name = Name::from_str("www.example.com.").unwrap();
794 let ns = RecordDataCNAME::new(name);
795
796 let mut cur = Cursor::new(Vec::new());
797 ns.write_network_bytes(&mut cur).unwrap();
798 let buf = cur.into_inner();
799
800 assert_eq!(
801 vec![
802 3, 119, 119, 119, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ],
810 buf,
811 );
812 }
813
814 #[rustfmt::skip]
815 #[test]
816 fn test_record_data_cname_read_network_bytes() {
817 let cur = Cursor::new(vec![
818 3, 119, 119, 119, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ]);
826
827 let rdata = RecordDataCNAME::read_network_bytes(cur).unwrap();
828 assert_eq!("www.example.com.", rdata.name().to_string());
829 }
830
831 #[rustfmt::skip]
832 #[test]
833 fn test_record_data_soa_write_network_bytes() {
834 let mname = Name::from_str("m.example.com.").unwrap();
835 let rname = Name::from_str("r.example.com.").unwrap();
836 let serial = 123_456_790;
837 let refresh = 3000;
838 let retry = 300;
839 let expire = 3600;
840 let minimum = 600;
841
842 let soa = RecordDataSOA::new(mname, rname, serial, refresh, retry, expire, minimum);
843 let mut cur = Cursor::new(Vec::new());
844 soa.write_network_bytes(&mut cur).unwrap();
845 let buf = cur.into_inner();
846
847 assert_eq!(
848 vec![
849 1, 109, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 1, 114, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 7, 91, 205, 22, 0, 0, 11, 184, 0, 0, 1, 44, 0, 0, 14, 16, 0, 0, 2, 88 ],
869 buf,
870 );
871 }
872
873 #[rustfmt::skip]
874 #[test]
875 fn test_record_data_soa_read_network_bytes() {
876 let cur = Cursor::new(vec![
877 1, 109, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 1, 114, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, 7, 91, 205, 22, 0, 0, 11, 184, 0, 0, 1, 44, 0, 0, 14, 16, 0, 0, 2, 88 ]);
897
898 let rdata = RecordDataSOA::read_network_bytes(cur).unwrap();
899 assert_eq!("m.example.com.", rdata.mname().to_string());
900 assert_eq!("r.example.com.", rdata.rname().to_string());
901 assert_eq!(123_456_790, rdata.serial());
902 assert_eq!(3000, rdata.refresh());
903 assert_eq!(300, rdata.retry());
904 assert_eq!(3600, rdata.expire());
905 assert_eq!(600, rdata.minimum());
906 }
907
908 #[test]
909 fn test_record_data_txt_new_exceeds_max_size() {
910 let segment = "a".repeat(255);
915 let data: Vec<String> = (0..256).map(|_| segment.clone()).collect();
916 let res = RecordDataTXT::new(data);
917
918 assert!(res.is_err());
919 }
920
921 #[test]
922 fn test_record_data_txt_new_success() {
923 let segment = "a".repeat(255);
924 let data: Vec<String> = (0..255).map(|_| segment.clone()).collect();
925 let txt = RecordDataTXT::new(data).unwrap();
926
927 assert_eq!(65280, txt.size());
928 }
929
930 #[test]
931 fn test_record_data_txt_size() {
932 let txt = RecordDataTXT::new(vec!["id=hello", "user=world"]).unwrap();
933 assert_eq!(20, txt.size());
934 }
935
936 #[rustfmt::skip]
937 #[test]
938 fn test_record_data_txt_write_network_bytes() {
939 let txt = RecordDataTXT::new(vec!["id=hello", "user=world"]).unwrap();
940 let mut cur = Cursor::new(Vec::new());
941 txt.write_network_bytes(&mut cur).unwrap();
942 let buf = cur.into_inner();
943
944 assert_eq!(
945 vec![
946 8, 105, 100, 61, 104, 101, 108, 108, 111, 10, 117, 115, 101, 114, 61, 119, 111, 114, 108, 100, ],
951 buf,
952 );
953 }
954
955 #[rustfmt::skip]
956 #[test]
957 fn test_record_data_txt_read_network_bytes() {
958 let bytes = vec![
959 8, 105, 100, 61, 104, 101, 108, 108, 111, 10, 117, 115, 101, 114, 61, 119, 111, 114, 108, 100, ];
964 let bytes_len = u16::try_from(bytes.len()).unwrap();
965 let cur = Cursor::new(bytes);
966
967 let rdata = RecordDataTXT::read_network_bytes(bytes_len, cur).unwrap();
968 let contents = rdata.bytes();
969 assert_eq!("id=hello".as_bytes(), contents[0]);
970 assert_eq!("user=world".as_bytes(), contents[1]);
971 }
972
973 #[test]
974 fn test_record_data_aaaa_write_network_bytes() {
975 let addr = Ipv6Addr::LOCALHOST;
976 let rdata = RecordDataAAAA::new(addr);
977
978 let mut cur = Cursor::new(Vec::new());
979 rdata.write_network_bytes(&mut cur).unwrap();
980 let buf = cur.into_inner();
981
982 assert_eq!(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], buf);
983 }
984
985 #[test]
986 fn test_record_data_aaaa_read_network_bytes() {
987 let cur = Cursor::new(vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]);
988 let rdata = RecordDataAAAA::read_network_bytes(cur).unwrap();
989
990 assert_eq!(Ipv6Addr::LOCALHOST, rdata.addr());
991 }
992
993 #[rustfmt::skip]
994 #[test]
995 fn test_record_data_srv_write_network_bytes() {
996 let srv = RecordDataSRV::new(100, 20, 11211, Name::from_str("_cache.example.com.").unwrap());
997 let mut cur = Cursor::new(Vec::new());
998 srv.write_network_bytes(&mut cur).unwrap();
999 let buf = cur.into_inner();
1000
1001 assert_eq!(
1002 vec![
1003 0, 100, 0, 20, 43, 203, 6, 95, 99, 97, 99, 104, 101, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ],
1014 buf,
1015 );
1016 }
1017
1018 #[rustfmt::skip]
1019 #[test]
1020 fn test_record_data_srv_read_network_bytes() {
1021 let cur = Cursor::new(vec![
1022 0, 100, 0, 20, 43, 203, 6, 95, 99, 97, 99, 104, 101, 7, 101, 120, 97, 109, 112, 108, 101, 3, 99, 111, 109, 0, ]);
1033
1034 let rdata = RecordDataSRV::read_network_bytes(cur).unwrap();
1035 assert_eq!(100, rdata.priority());
1036 assert_eq!(20, rdata.weight());
1037 assert_eq!(11211, rdata.port());
1038 assert_eq!("_cache.example.com.", rdata.target().to_string());
1039 }
1040
1041 #[test]
1042 fn test_record_data_opt_pair_new_exceeds_max_size() {
1043 let res = RecordDataOptPair::new(0, "a".repeat(65536).into_bytes());
1044 assert!(res.is_err());
1045 }
1046
1047 #[test]
1048 fn test_record_data_opt_pair_new_success() {
1049 let opt = RecordDataOptPair::new(0, "a".repeat(100).into_bytes()).unwrap();
1050 assert_eq!(0, opt.code());
1051 assert_eq!(2 + 2 + 100, opt.size());
1052 }
1053
1054 #[test]
1055 fn test_record_data_opt_new_exceeds_max_size() {
1056 let opts = vec![
1057 RecordDataOptPair::new(0, "a".repeat(65535).into_bytes()).unwrap(),
1058 RecordDataOptPair::new(1, "a".repeat(65535).into_bytes()).unwrap(),
1059 ];
1060
1061 let res = RecordDataOpt::new(opts);
1062 assert!(res.is_err());
1063 }
1064
1065 #[test]
1066 fn test_record_data_opt_new_success() {
1067 let opts = vec![
1068 RecordDataOptPair::new(0, "a".repeat(100).into_bytes()).unwrap(),
1069 RecordDataOptPair::new(1, "a".repeat(100).into_bytes()).unwrap(),
1070 ];
1071
1072 let res = RecordDataOpt::new(opts).unwrap();
1073 assert_eq!(2 * (2 + 2 + 100), res.size());
1074 }
1075
1076 #[rustfmt::skip]
1077 #[test]
1078 fn test_record_data_opt_write_network_bytes() {
1079 let opt = RecordDataOpt::new(vec![RecordDataOptPair::new(1, "abc".as_bytes().to_vec()).unwrap()]).unwrap();
1080 let mut cur = Cursor::new(Vec::new());
1081 opt.write_network_bytes(&mut cur).unwrap();
1082 let buf = cur.into_inner();
1083
1084 assert_eq!(
1085 vec![
1086 0, 1, 0, 3, 97, 98, 99, ],
1090 buf,
1091 );
1092 }
1093
1094 #[rustfmt::skip]
1095 #[test]
1096 fn test_record_data_opt_read_network_bytes() {
1097 let cur = Cursor::new(vec![
1098 0, 1, 0, 3, 97, 98, 99, ]);
1102
1103 let rdata = RecordDataOpt::read_network_bytes(7, cur).unwrap();
1104 let options = rdata.options();
1105
1106 assert_eq!(
1107 RecordDataOptPair::new(1, "abc".as_bytes().to_vec()).unwrap(),
1108 options[0]
1109 );
1110 }
1111}